mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-02 01:24:11 +01:00
Merge branch 'clearopt'
This commit is contained in:
commit
5683422208
@ -42,19 +42,50 @@ namespace dxvk {
|
||||
VkPipeline DxvkComputePipeline::getPipelineHandle(
|
||||
const DxvkComputePipelineStateInfo& state,
|
||||
DxvkStatCounters& stats) {
|
||||
for (const PipelineStruct& pair : m_pipelines) {
|
||||
if (pair.stateVector == state)
|
||||
return pair.pipeline;
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
|
||||
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
|
||||
|
||||
if (this->findPipeline(state, pipeline))
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
VkPipeline pipeline = this->compilePipeline(state, m_basePipeline);
|
||||
m_pipelines.push_back({ state, pipeline });
|
||||
// If no pipeline exists with the given state vector,
|
||||
// create a new one and add it to the pipeline set.
|
||||
VkPipeline newPipeline = this->compilePipeline(state, m_basePipeline);
|
||||
|
||||
if (m_basePipeline == VK_NULL_HANDLE)
|
||||
m_basePipeline = pipeline;
|
||||
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
|
||||
|
||||
// Discard the pipeline if another thread
|
||||
// was faster compiling the same pipeline
|
||||
if (this->findPipeline(state, pipeline)) {
|
||||
m_vkd->vkDestroyPipeline(m_vkd->device(), newPipeline, nullptr);
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
// Add new pipeline to the set
|
||||
m_pipelines.push_back({ state, newPipeline });
|
||||
|
||||
if (m_basePipeline == VK_NULL_HANDLE)
|
||||
m_basePipeline = newPipeline;
|
||||
|
||||
stats.addCtr(DxvkStatCounter::PipeCountCompute, 1);
|
||||
return newPipeline;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DxvkComputePipeline::findPipeline(
|
||||
const DxvkComputePipelineStateInfo& state,
|
||||
VkPipeline& pipeline) const {
|
||||
for (const PipelineStruct& pair : m_pipelines) {
|
||||
if (pair.stateVector == state) {
|
||||
pipeline = pair.pipeline;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
stats.addCtr(DxvkStatCounter::PipeCountCompute, 1);
|
||||
return pipeline;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "dxvk_binding.h"
|
||||
#include "dxvk_pipecache.h"
|
||||
#include "dxvk_pipelayout.h"
|
||||
@ -76,10 +78,15 @@ namespace dxvk {
|
||||
Rc<DxvkPipelineLayout> m_layout;
|
||||
Rc<DxvkShaderModule> m_cs;
|
||||
|
||||
sync::Spinlock m_mutex;
|
||||
std::vector<PipelineStruct> m_pipelines;
|
||||
|
||||
VkPipeline m_basePipeline = VK_NULL_HANDLE;
|
||||
|
||||
bool findPipeline(
|
||||
const DxvkComputePipelineStateInfo& state,
|
||||
VkPipeline& pipeline) const;
|
||||
|
||||
VkPipeline compilePipeline(
|
||||
const DxvkComputePipelineStateInfo& state,
|
||||
VkPipeline baseHandle) const;
|
||||
|
@ -9,10 +9,11 @@ namespace dxvk {
|
||||
DxvkContext::DxvkContext(
|
||||
const Rc<DxvkDevice>& device,
|
||||
const Rc<DxvkPipelineCache>& pipelineCache,
|
||||
const Rc<DxvkPipelineManager>& pipelineManager,
|
||||
const Rc<DxvkMetaClearObjects>& metaClearObjects)
|
||||
: m_device (device),
|
||||
m_pipeCache (pipelineCache),
|
||||
m_pipeMgr (new DxvkPipelineManager(device.ptr())),
|
||||
m_pipeMgr (pipelineManager),
|
||||
m_metaClear (metaClearObjects) { }
|
||||
|
||||
|
||||
@ -29,7 +30,8 @@ namespace dxvk {
|
||||
// undefined, so we have to bind and set up everything
|
||||
// before any draw or dispatch command is recorded.
|
||||
m_flags.clr(
|
||||
DxvkContextFlag::GpRenderPassBound);
|
||||
DxvkContextFlag::GpRenderPassBound,
|
||||
DxvkContextFlag::GpClearRenderTargets);
|
||||
|
||||
m_flags.set(
|
||||
DxvkContextFlag::GpDirtyPipeline,
|
||||
@ -88,7 +90,9 @@ namespace dxvk {
|
||||
void DxvkContext::bindRenderTargets(const DxvkRenderTargets& targets) {
|
||||
m_state.om.renderTargets = targets;
|
||||
|
||||
// TODO execute pending clears
|
||||
// If necessary, perform clears on the active render targets
|
||||
if (m_flags.test(DxvkContextFlag::GpClearRenderTargets))
|
||||
this->startRenderPass();
|
||||
|
||||
// Set up default render pass ops
|
||||
this->resetRenderPassOps(
|
||||
@ -386,6 +390,35 @@ namespace dxvk {
|
||||
const VkClearValue& clearValue) {
|
||||
this->updateFramebuffer();
|
||||
|
||||
// Prepare attachment ops
|
||||
DxvkColorAttachmentOps colorOp;
|
||||
colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
colorOp.loadLayout = imageView->imageInfo().layout;
|
||||
colorOp.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
colorOp.storeLayout = imageView->imageInfo().layout;
|
||||
|
||||
DxvkDepthAttachmentOps depthOp;
|
||||
depthOp.loadOpD = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
depthOp.loadLayout = imageView->imageInfo().layout;
|
||||
depthOp.storeOpD = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
depthOp.storeOpS = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
depthOp.storeLayout = imageView->imageInfo().layout;
|
||||
|
||||
if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
colorOp.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
|
||||
if (clearAspects & VK_IMAGE_ASPECT_DEPTH_BIT)
|
||||
depthOp.loadOpD = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
|
||||
if (clearAspects & VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||
depthOp.loadOpS = VK_ATTACHMENT_LOAD_OP_CLEAR;
|
||||
|
||||
if (clearAspects == imageView->info().aspect) {
|
||||
colorOp.loadLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
depthOp.loadLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
}
|
||||
|
||||
// Check whether the render target view is an attachment
|
||||
// of the current framebuffer. If not, we need to create
|
||||
// a temporary framebuffer.
|
||||
@ -397,12 +430,6 @@ namespace dxvk {
|
||||
if (attachmentIndex < 0) {
|
||||
this->spillRenderPass();
|
||||
|
||||
DxvkAttachmentOps op;
|
||||
op.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
|
||||
op.loadLayout = imageView->imageInfo().layout;
|
||||
op.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
op.storeLayout = imageView->imageInfo().layout;
|
||||
|
||||
// Set up and bind a temporary framebuffer
|
||||
DxvkRenderTargets attachments;
|
||||
DxvkRenderPassOps ops;
|
||||
@ -410,37 +437,39 @@ namespace dxvk {
|
||||
if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT) {
|
||||
attachments.color[0].view = imageView;
|
||||
attachments.color[0].layout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||
ops.colorOps[0] = op;
|
||||
ops.colorOps[0] = colorOp;
|
||||
} else {
|
||||
attachments.depth.view = imageView;
|
||||
attachments.depth.layout = imageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||
ops.depthOps = op;
|
||||
ops.depthOps = depthOp;
|
||||
}
|
||||
|
||||
this->renderPassBindFramebuffer(
|
||||
m_device->createFramebuffer(attachments), ops);
|
||||
} else {
|
||||
// Make sure that the currently bound
|
||||
// framebuffer can be rendered to
|
||||
this->startRenderPass();
|
||||
}
|
||||
|
||||
// Clear the attachment in quesion
|
||||
VkClearAttachment clearInfo;
|
||||
clearInfo.aspectMask = clearAspects;
|
||||
clearInfo.colorAttachment = attachmentIndex;
|
||||
clearInfo.clearValue = clearValue;
|
||||
|
||||
if (attachmentIndex < 0)
|
||||
clearInfo.colorAttachment = 0;
|
||||
|
||||
m_cmd->cmdClearAttachments(
|
||||
1, &clearInfo, 1, &clearRect);
|
||||
|
||||
// If we used a temporary framebuffer, we'll have to unbind it
|
||||
// again in order to not disturb subsequent rendering commands.
|
||||
if (attachmentIndex < 0)
|
||||
m_device->createFramebuffer(attachments),
|
||||
ops, 1, &clearValue);
|
||||
this->renderPassUnbindFramebuffer();
|
||||
} else if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) {
|
||||
// Clear the attachment in quesion. For color images,
|
||||
// the attachment index for the current subpass is
|
||||
// equal to the render pass attachment index.
|
||||
VkClearAttachment clearInfo;
|
||||
clearInfo.aspectMask = clearAspects;
|
||||
clearInfo.colorAttachment = attachmentIndex;
|
||||
clearInfo.clearValue = clearValue;
|
||||
|
||||
m_cmd->cmdClearAttachments(
|
||||
1, &clearInfo, 1, &clearRect);
|
||||
} else {
|
||||
// Perform the clear when starting the render pass
|
||||
if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT)
|
||||
m_state.om.renderPassOps.colorOps[attachmentIndex] = colorOp;
|
||||
|
||||
if (clearAspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))
|
||||
m_state.om.renderPassOps.depthOps = depthOp;
|
||||
|
||||
m_state.om.clearValues[attachmentIndex] = clearValue;
|
||||
m_flags.set(DxvkContextFlag::GpClearRenderTargets);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1519,10 +1548,13 @@ namespace dxvk {
|
||||
if (!m_flags.test(DxvkContextFlag::GpRenderPassBound)
|
||||
&& (m_state.om.framebuffer != nullptr)) {
|
||||
m_flags.set(DxvkContextFlag::GpRenderPassBound);
|
||||
m_flags.clr(DxvkContextFlag::GpClearRenderTargets);
|
||||
|
||||
this->renderPassBindFramebuffer(
|
||||
m_state.om.framebuffer,
|
||||
m_state.om.renderPassOps);
|
||||
m_state.om.renderPassOps,
|
||||
m_state.om.clearValues.size(),
|
||||
m_state.om.clearValues.data());
|
||||
|
||||
// Don't discard image contents if we have
|
||||
// to spill the current render pass
|
||||
@ -1534,7 +1566,8 @@ namespace dxvk {
|
||||
|
||||
|
||||
void DxvkContext::spillRenderPass() {
|
||||
// TODO execute pending clears
|
||||
if (m_flags.test(DxvkContextFlag::GpClearRenderTargets))
|
||||
this->startRenderPass();
|
||||
|
||||
if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) {
|
||||
m_flags.clr(DxvkContextFlag::GpRenderPassBound);
|
||||
@ -1545,7 +1578,9 @@ namespace dxvk {
|
||||
|
||||
void DxvkContext::renderPassBindFramebuffer(
|
||||
const Rc<DxvkFramebuffer>& framebuffer,
|
||||
const DxvkRenderPassOps& ops) {
|
||||
const DxvkRenderPassOps& ops,
|
||||
uint32_t clearValueCount,
|
||||
const VkClearValue* clearValues) {
|
||||
const DxvkFramebufferSize fbSize = framebuffer->size();
|
||||
|
||||
VkRect2D renderArea;
|
||||
@ -1558,8 +1593,8 @@ namespace dxvk {
|
||||
info.renderPass = framebuffer->getRenderPassHandle(ops);
|
||||
info.framebuffer = framebuffer->handle();
|
||||
info.renderArea = renderArea;
|
||||
info.clearValueCount = 0;
|
||||
info.pClearValues = nullptr;
|
||||
info.clearValueCount = clearValueCount;
|
||||
info.pClearValues = clearValues;
|
||||
|
||||
m_cmd->cmdBeginRenderPass(&info,
|
||||
VK_SUBPASS_CONTENTS_INLINE);
|
||||
@ -1577,17 +1612,23 @@ namespace dxvk {
|
||||
const DxvkRenderTargets& renderTargets,
|
||||
DxvkRenderPassOps& renderPassOps) {
|
||||
renderPassOps.depthOps = renderTargets.depth.view != nullptr
|
||||
? DxvkAttachmentOps {
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD, renderTargets.depth.view->imageInfo().layout,
|
||||
VK_ATTACHMENT_STORE_OP_STORE, renderTargets.depth.view->imageInfo().layout }
|
||||
: DxvkAttachmentOps { };
|
||||
? DxvkDepthAttachmentOps {
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
renderTargets.depth.view->imageInfo().layout,
|
||||
VK_ATTACHMENT_STORE_OP_STORE,
|
||||
VK_ATTACHMENT_STORE_OP_STORE,
|
||||
renderTargets.depth.view->imageInfo().layout }
|
||||
: DxvkDepthAttachmentOps { };
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||
renderPassOps.colorOps[i] = renderTargets.color[i].view != nullptr
|
||||
? DxvkAttachmentOps {
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD, renderTargets.color[i].view->imageInfo().layout,
|
||||
VK_ATTACHMENT_STORE_OP_STORE, renderTargets.color[i].view->imageInfo().layout }
|
||||
: DxvkAttachmentOps { };
|
||||
? DxvkColorAttachmentOps {
|
||||
VK_ATTACHMENT_LOAD_OP_LOAD,
|
||||
renderTargets.color[i].view->imageInfo().layout,
|
||||
VK_ATTACHMENT_STORE_OP_STORE,
|
||||
renderTargets.color[i].view->imageInfo().layout }
|
||||
: DxvkColorAttachmentOps { };
|
||||
}
|
||||
|
||||
// TODO provide a sane alternative for this
|
||||
|
@ -30,6 +30,7 @@ namespace dxvk {
|
||||
DxvkContext(
|
||||
const Rc<DxvkDevice>& device,
|
||||
const Rc<DxvkPipelineCache>& pipelineCache,
|
||||
const Rc<DxvkPipelineManager>& pipelineManager,
|
||||
const Rc<DxvkMetaClearObjects>& metaClearObjects);
|
||||
~DxvkContext();
|
||||
|
||||
@ -644,7 +645,9 @@ namespace dxvk {
|
||||
|
||||
void renderPassBindFramebuffer(
|
||||
const Rc<DxvkFramebuffer>& framebuffer,
|
||||
const DxvkRenderPassOps& ops);
|
||||
const DxvkRenderPassOps& ops,
|
||||
uint32_t clearValueCount,
|
||||
const VkClearValue* clearValues);
|
||||
|
||||
void renderPassUnbindFramebuffer();
|
||||
|
||||
|
@ -16,12 +16,13 @@ namespace dxvk {
|
||||
/**
|
||||
* \brief Graphics pipeline state flags
|
||||
*
|
||||
* Stores some information on which state of the
|
||||
* graphics pipeline has changed and/or needs to
|
||||
* be updated.
|
||||
* Stores some information on which state
|
||||
* of the graphics and compute pipelines
|
||||
* has changed and/or needs to be updated.
|
||||
*/
|
||||
enum class DxvkContextFlag : uint64_t {
|
||||
GpRenderPassBound, ///< Render pass is currently bound
|
||||
GpClearRenderTargets, ///< Render targets need to be cleared
|
||||
GpDirtyFramebuffer, ///< Framebuffer binding is out of date
|
||||
GpDirtyPipeline, ///< Graphics pipeline binding is out of date
|
||||
GpDirtyPipelineState, ///< Graphics pipeline needs to be recompiled
|
||||
@ -54,7 +55,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
struct DxvkOutputMergerState {
|
||||
std::array<VkClearValue, MaxNumRenderTargets + 1> clearValue;
|
||||
std::array<VkClearValue, MaxNumRenderTargets + 1> clearValues = { };
|
||||
|
||||
DxvkRenderTargets renderTargets;
|
||||
DxvkRenderPassOps renderPassOps;
|
||||
|
@ -16,6 +16,7 @@ namespace dxvk {
|
||||
m_memory (new DxvkMemoryAllocator (adapter, vkd)),
|
||||
m_renderPassPool (new DxvkRenderPassPool (vkd)),
|
||||
m_pipelineCache (new DxvkPipelineCache (vkd)),
|
||||
m_pipelineManager (new DxvkPipelineManager (this)),
|
||||
m_metaClearObjects(new DxvkMetaClearObjects (vkd)),
|
||||
m_unboundResources(this),
|
||||
m_submissionQueue (this) {
|
||||
@ -106,6 +107,7 @@ namespace dxvk {
|
||||
Rc<DxvkContext> DxvkDevice::createContext() {
|
||||
return new DxvkContext(this,
|
||||
m_pipelineCache,
|
||||
m_pipelineManager,
|
||||
m_metaClearObjects);
|
||||
}
|
||||
|
||||
|
@ -355,6 +355,7 @@ namespace dxvk {
|
||||
Rc<DxvkMemoryAllocator> m_memory;
|
||||
Rc<DxvkRenderPassPool> m_renderPassPool;
|
||||
Rc<DxvkPipelineCache> m_pipelineCache;
|
||||
Rc<DxvkPipelineManager> m_pipelineManager;
|
||||
Rc<DxvkMetaClearObjects> m_metaClearObjects;
|
||||
|
||||
DxvkUnboundResources m_unboundResources;
|
||||
|
@ -13,20 +13,18 @@ namespace dxvk {
|
||||
m_renderSize (computeRenderSize(defaultSize)) {
|
||||
std::array<VkImageView, MaxNumRenderTargets + 1> views;
|
||||
|
||||
uint32_t viewId = 0;
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
|
||||
if (m_renderTargets.color[i].view != nullptr) {
|
||||
views[viewId] = m_renderTargets.color[i].view->handle();
|
||||
m_attachments[viewId] = &m_renderTargets.color[i];
|
||||
viewId += 1;
|
||||
views[m_attachmentCount] = m_renderTargets.color[i].view->handle();
|
||||
m_attachments[m_attachmentCount] = &m_renderTargets.color[i];
|
||||
m_attachmentCount += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_renderTargets.depth.view != nullptr) {
|
||||
views[viewId] = m_renderTargets.depth.view->handle();
|
||||
m_attachments[viewId] = &m_renderTargets.depth;
|
||||
viewId += 1;
|
||||
views[m_attachmentCount] = m_renderTargets.depth.view->handle();
|
||||
m_attachments[m_attachmentCount] = &m_renderTargets.depth;
|
||||
m_attachmentCount += 1;
|
||||
}
|
||||
|
||||
VkFramebufferCreateInfo info;
|
||||
@ -34,7 +32,7 @@ namespace dxvk {
|
||||
info.pNext = nullptr;
|
||||
info.flags = 0;
|
||||
info.renderPass = m_renderPass->getDefaultHandle();
|
||||
info.attachmentCount = viewId;
|
||||
info.attachmentCount = m_attachmentCount;
|
||||
info.pAttachments = views.data();
|
||||
info.width = m_renderSize.width;
|
||||
info.height = m_renderSize.height;
|
||||
|
@ -78,23 +78,52 @@ namespace dxvk {
|
||||
VkPipeline DxvkGraphicsPipeline::getPipelineHandle(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
DxvkStatCounters& stats) {
|
||||
VkPipeline pipeline = VK_NULL_HANDLE;
|
||||
|
||||
for (const PipelineStruct& pair : m_pipelines) {
|
||||
if (pair.stateVector == state)
|
||||
return pair.pipeline;
|
||||
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
|
||||
|
||||
if (this->findPipeline(state, pipeline))
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
VkPipeline pipeline = this->validatePipelineState(state)
|
||||
// If no pipeline exists with the given state vector,
|
||||
// create a new one and add it to the pipeline set.
|
||||
VkPipeline newPipeline = this->validatePipelineState(state)
|
||||
? this->compilePipeline(state, m_basePipeline)
|
||||
: VK_NULL_HANDLE;
|
||||
|
||||
m_pipelines.push_back({ state, pipeline });
|
||||
{ std::lock_guard<sync::Spinlock> lock(m_mutex);
|
||||
|
||||
// Discard the pipeline if another thread
|
||||
// was faster compiling the same pipeline
|
||||
if (this->findPipeline(state, pipeline)) {
|
||||
m_vkd->vkDestroyPipeline(m_vkd->device(), newPipeline, nullptr);
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
// Add new pipeline to the set
|
||||
m_pipelines.push_back({ state, newPipeline });
|
||||
|
||||
if (m_basePipeline == VK_NULL_HANDLE)
|
||||
m_basePipeline = newPipeline;
|
||||
|
||||
stats.addCtr(DxvkStatCounter::PipeCountGraphics, 1);
|
||||
return newPipeline;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool DxvkGraphicsPipeline::findPipeline(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
VkPipeline& pipeline) const {
|
||||
for (const PipelineStruct& pair : m_pipelines) {
|
||||
if (pair.stateVector == state) {
|
||||
pipeline = pair.pipeline;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_basePipeline == VK_NULL_HANDLE)
|
||||
m_basePipeline = pipeline;
|
||||
|
||||
stats.addCtr(DxvkStatCounter::PipeCountGraphics, 1);
|
||||
return pipeline;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
|
||||
#include "dxvk_binding.h"
|
||||
#include "dxvk_constant_state.h"
|
||||
@ -160,10 +160,15 @@ namespace dxvk {
|
||||
|
||||
DxvkGraphicsCommonPipelineStateInfo m_common;
|
||||
|
||||
sync::Spinlock m_mutex;
|
||||
std::vector<PipelineStruct> m_pipelines;
|
||||
|
||||
VkPipeline m_basePipeline = VK_NULL_HANDLE;
|
||||
|
||||
bool findPipeline(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
VkPipeline& pipeline) const;
|
||||
|
||||
VkPipeline compilePipeline(
|
||||
const DxvkGraphicsPipelineStateInfo& state,
|
||||
VkPipeline baseHandle) const;
|
||||
|
@ -21,17 +21,19 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
bool DxvkPipelineKeyEq::operator () (const DxvkComputePipelineKey& a, const DxvkComputePipelineKey& b) const {
|
||||
bool DxvkPipelineKeyEq::operator () (
|
||||
const DxvkComputePipelineKey& a,
|
||||
const DxvkComputePipelineKey& b) const {
|
||||
return a.cs == b.cs;
|
||||
}
|
||||
|
||||
|
||||
bool DxvkPipelineKeyEq::operator () (const DxvkGraphicsPipelineKey& a, const DxvkGraphicsPipelineKey& b) const {
|
||||
return a.vs == b.vs
|
||||
&& a.tcs == b.tcs
|
||||
&& a.tes == b.tes
|
||||
&& a.gs == b.gs
|
||||
&& a.fs == b.fs;
|
||||
bool DxvkPipelineKeyEq::operator () (
|
||||
const DxvkGraphicsPipelineKey& a,
|
||||
const DxvkGraphicsPipelineKey& b) const {
|
||||
return a.vs == b.vs && a.tcs == b.tcs
|
||||
&& a.tes == b.tes && a.gs == b.gs
|
||||
&& a.fs == b.fs;
|
||||
}
|
||||
|
||||
|
||||
@ -52,6 +54,8 @@ namespace dxvk {
|
||||
if (cs == nullptr)
|
||||
return nullptr;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
DxvkComputePipelineKey key;
|
||||
key.cs = cs;
|
||||
|
||||
@ -77,6 +81,8 @@ namespace dxvk {
|
||||
if (vs == nullptr)
|
||||
return nullptr;
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
||||
DxvkGraphicsPipelineKey key;
|
||||
key.vs = vs;
|
||||
key.tcs = tcs;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "dxvk_compute.h"
|
||||
@ -99,6 +100,8 @@ namespace dxvk {
|
||||
|
||||
const DxvkDevice* m_device;
|
||||
|
||||
std::mutex m_mutex;
|
||||
|
||||
std::unordered_map<
|
||||
DxvkComputePipelineKey,
|
||||
Rc<DxvkComputePipeline>,
|
||||
|
@ -89,10 +89,10 @@ namespace dxvk {
|
||||
desc.flags = 0;
|
||||
desc.format = m_format.depth.format;
|
||||
desc.samples = m_format.sampleCount;
|
||||
desc.loadOp = ops.depthOps.loadOp;
|
||||
desc.storeOp = ops.depthOps.storeOp;
|
||||
desc.stencilLoadOp = ops.depthOps.loadOp;
|
||||
desc.stencilStoreOp = ops.depthOps.storeOp;
|
||||
desc.loadOp = ops.depthOps.loadOpD;
|
||||
desc.storeOp = ops.depthOps.storeOpD;
|
||||
desc.stencilLoadOp = ops.depthOps.loadOpS;
|
||||
desc.stencilStoreOp = ops.depthOps.storeOpS;
|
||||
desc.initialLayout = ops.depthOps.loadLayout;
|
||||
desc.finalLayout = ops.depthOps.storeLayout;
|
||||
|
||||
@ -179,9 +179,11 @@ namespace dxvk {
|
||||
bool DxvkRenderPass::compareOps(
|
||||
const DxvkRenderPassOps& a,
|
||||
const DxvkRenderPassOps& b) {
|
||||
bool eq = a.depthOps.loadOp == b.depthOps.loadOp
|
||||
bool eq = a.depthOps.loadOpD == b.depthOps.loadOpD
|
||||
&& a.depthOps.loadOpS == b.depthOps.loadOpS
|
||||
&& a.depthOps.loadLayout == b.depthOps.loadLayout
|
||||
&& a.depthOps.storeOp == b.depthOps.storeOp
|
||||
&& a.depthOps.storeOpD == b.depthOps.storeOpD
|
||||
&& a.depthOps.storeOpS == b.depthOps.storeOpS
|
||||
&& a.depthOps.storeLayout == b.depthOps.storeLayout;
|
||||
|
||||
for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) {
|
||||
|
@ -35,12 +35,12 @@ namespace dxvk {
|
||||
|
||||
|
||||
/**
|
||||
* \brief Attachment transitions
|
||||
* \brief Color attachment transitions
|
||||
*
|
||||
* Stores the load/store ops and the initial
|
||||
* and final layout of a single attachment.
|
||||
*/
|
||||
struct DxvkAttachmentOps {
|
||||
struct DxvkColorAttachmentOps {
|
||||
VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
VkImageLayout loadLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkAttachmentStoreOp storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
@ -48,6 +48,22 @@ namespace dxvk {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Depth attachment transitions
|
||||
*
|
||||
* Stores the load/store ops and the initial and
|
||||
* final layout of the depth-stencil attachment.
|
||||
*/
|
||||
struct DxvkDepthAttachmentOps {
|
||||
VkAttachmentLoadOp loadOpD = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
VkAttachmentLoadOp loadOpS = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
|
||||
VkImageLayout loadLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkAttachmentStoreOp storeOpD = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
VkAttachmentStoreOp storeOpS = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
VkImageLayout storeLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief Render pass transitions
|
||||
*
|
||||
@ -56,8 +72,8 @@ namespace dxvk {
|
||||
* from a group of render passes with the same format.
|
||||
*/
|
||||
struct DxvkRenderPassOps {
|
||||
DxvkAttachmentOps depthOps;
|
||||
DxvkAttachmentOps colorOps[MaxNumRenderTargets];
|
||||
DxvkDepthAttachmentOps depthOps;
|
||||
DxvkColorAttachmentOps colorOps[MaxNumRenderTargets];
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user