1
0
mirror of https://github.com/EduApps-CDG/OpenDX synced 2024-12-30 09:45:37 +01:00

Merge branch 'clearopt'

This commit is contained in:
Philip Rebohle 2018-05-02 00:45:17 +02:00
commit 5683422208
14 changed files with 242 additions and 97 deletions

View File

@ -42,19 +42,50 @@ namespace dxvk {
VkPipeline DxvkComputePipeline::getPipelineHandle( VkPipeline DxvkComputePipeline::getPipelineHandle(
const DxvkComputePipelineStateInfo& state, const DxvkComputePipelineStateInfo& state,
DxvkStatCounters& stats) { DxvkStatCounters& stats) {
for (const PipelineStruct& pair : m_pipelines) { VkPipeline pipeline = VK_NULL_HANDLE;
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->compilePipeline(state, m_basePipeline); // If no pipeline exists with the given state vector,
m_pipelines.push_back({ state, pipeline }); // create a new one and add it to the pipeline set.
VkPipeline newPipeline = this->compilePipeline(state, m_basePipeline);
if (m_basePipeline == VK_NULL_HANDLE) { std::lock_guard<sync::Spinlock> lock(m_mutex);
m_basePipeline = pipeline;
// 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 false;
return pipeline;
} }

View File

@ -1,5 +1,7 @@
#pragma once #pragma once
#include <vector>
#include "dxvk_binding.h" #include "dxvk_binding.h"
#include "dxvk_pipecache.h" #include "dxvk_pipecache.h"
#include "dxvk_pipelayout.h" #include "dxvk_pipelayout.h"
@ -76,10 +78,15 @@ namespace dxvk {
Rc<DxvkPipelineLayout> m_layout; Rc<DxvkPipelineLayout> m_layout;
Rc<DxvkShaderModule> m_cs; Rc<DxvkShaderModule> m_cs;
sync::Spinlock m_mutex;
std::vector<PipelineStruct> m_pipelines; std::vector<PipelineStruct> m_pipelines;
VkPipeline m_basePipeline = VK_NULL_HANDLE; VkPipeline m_basePipeline = VK_NULL_HANDLE;
bool findPipeline(
const DxvkComputePipelineStateInfo& state,
VkPipeline& pipeline) const;
VkPipeline compilePipeline( VkPipeline compilePipeline(
const DxvkComputePipelineStateInfo& state, const DxvkComputePipelineStateInfo& state,
VkPipeline baseHandle) const; VkPipeline baseHandle) const;

View File

@ -9,10 +9,11 @@ namespace dxvk {
DxvkContext::DxvkContext( DxvkContext::DxvkContext(
const Rc<DxvkDevice>& device, const Rc<DxvkDevice>& device,
const Rc<DxvkPipelineCache>& pipelineCache, const Rc<DxvkPipelineCache>& pipelineCache,
const Rc<DxvkPipelineManager>& pipelineManager,
const Rc<DxvkMetaClearObjects>& metaClearObjects) const Rc<DxvkMetaClearObjects>& metaClearObjects)
: m_device (device), : m_device (device),
m_pipeCache (pipelineCache), m_pipeCache (pipelineCache),
m_pipeMgr (new DxvkPipelineManager(device.ptr())), m_pipeMgr (pipelineManager),
m_metaClear (metaClearObjects) { } m_metaClear (metaClearObjects) { }
@ -29,7 +30,8 @@ namespace dxvk {
// undefined, so we have to bind and set up everything // undefined, so we have to bind and set up everything
// before any draw or dispatch command is recorded. // before any draw or dispatch command is recorded.
m_flags.clr( m_flags.clr(
DxvkContextFlag::GpRenderPassBound); DxvkContextFlag::GpRenderPassBound,
DxvkContextFlag::GpClearRenderTargets);
m_flags.set( m_flags.set(
DxvkContextFlag::GpDirtyPipeline, DxvkContextFlag::GpDirtyPipeline,
@ -88,7 +90,9 @@ namespace dxvk {
void DxvkContext::bindRenderTargets(const DxvkRenderTargets& targets) { void DxvkContext::bindRenderTargets(const DxvkRenderTargets& targets) {
m_state.om.renderTargets = 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 // Set up default render pass ops
this->resetRenderPassOps( this->resetRenderPassOps(
@ -386,6 +390,35 @@ namespace dxvk {
const VkClearValue& clearValue) { const VkClearValue& clearValue) {
this->updateFramebuffer(); 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 // Check whether the render target view is an attachment
// of the current framebuffer. If not, we need to create // of the current framebuffer. If not, we need to create
// a temporary framebuffer. // a temporary framebuffer.
@ -397,12 +430,6 @@ namespace dxvk {
if (attachmentIndex < 0) { if (attachmentIndex < 0) {
this->spillRenderPass(); 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 // Set up and bind a temporary framebuffer
DxvkRenderTargets attachments; DxvkRenderTargets attachments;
DxvkRenderPassOps ops; DxvkRenderPassOps ops;
@ -410,37 +437,39 @@ namespace dxvk {
if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT) { if (clearAspects & VK_IMAGE_ASPECT_COLOR_BIT) {
attachments.color[0].view = imageView; attachments.color[0].view = imageView;
attachments.color[0].layout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); attachments.color[0].layout = imageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
ops.colorOps[0] = op; ops.colorOps[0] = colorOp;
} else { } else {
attachments.depth.view = imageView; attachments.depth.view = imageView;
attachments.depth.layout = imageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); attachments.depth.layout = imageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
ops.depthOps = op; ops.depthOps = depthOp;
} }
this->renderPassBindFramebuffer( this->renderPassBindFramebuffer(
m_device->createFramebuffer(attachments), ops); m_device->createFramebuffer(attachments),
} else { ops, 1, &clearValue);
// 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)
this->renderPassUnbindFramebuffer(); 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) if (!m_flags.test(DxvkContextFlag::GpRenderPassBound)
&& (m_state.om.framebuffer != nullptr)) { && (m_state.om.framebuffer != nullptr)) {
m_flags.set(DxvkContextFlag::GpRenderPassBound); m_flags.set(DxvkContextFlag::GpRenderPassBound);
m_flags.clr(DxvkContextFlag::GpClearRenderTargets);
this->renderPassBindFramebuffer( this->renderPassBindFramebuffer(
m_state.om.framebuffer, 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 // Don't discard image contents if we have
// to spill the current render pass // to spill the current render pass
@ -1534,7 +1566,8 @@ namespace dxvk {
void DxvkContext::spillRenderPass() { void DxvkContext::spillRenderPass() {
// TODO execute pending clears if (m_flags.test(DxvkContextFlag::GpClearRenderTargets))
this->startRenderPass();
if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) { if (m_flags.test(DxvkContextFlag::GpRenderPassBound)) {
m_flags.clr(DxvkContextFlag::GpRenderPassBound); m_flags.clr(DxvkContextFlag::GpRenderPassBound);
@ -1545,7 +1578,9 @@ namespace dxvk {
void DxvkContext::renderPassBindFramebuffer( void DxvkContext::renderPassBindFramebuffer(
const Rc<DxvkFramebuffer>& framebuffer, const Rc<DxvkFramebuffer>& framebuffer,
const DxvkRenderPassOps& ops) { const DxvkRenderPassOps& ops,
uint32_t clearValueCount,
const VkClearValue* clearValues) {
const DxvkFramebufferSize fbSize = framebuffer->size(); const DxvkFramebufferSize fbSize = framebuffer->size();
VkRect2D renderArea; VkRect2D renderArea;
@ -1558,8 +1593,8 @@ namespace dxvk {
info.renderPass = framebuffer->getRenderPassHandle(ops); info.renderPass = framebuffer->getRenderPassHandle(ops);
info.framebuffer = framebuffer->handle(); info.framebuffer = framebuffer->handle();
info.renderArea = renderArea; info.renderArea = renderArea;
info.clearValueCount = 0; info.clearValueCount = clearValueCount;
info.pClearValues = nullptr; info.pClearValues = clearValues;
m_cmd->cmdBeginRenderPass(&info, m_cmd->cmdBeginRenderPass(&info,
VK_SUBPASS_CONTENTS_INLINE); VK_SUBPASS_CONTENTS_INLINE);
@ -1577,17 +1612,23 @@ namespace dxvk {
const DxvkRenderTargets& renderTargets, const DxvkRenderTargets& renderTargets,
DxvkRenderPassOps& renderPassOps) { DxvkRenderPassOps& renderPassOps) {
renderPassOps.depthOps = renderTargets.depth.view != nullptr renderPassOps.depthOps = renderTargets.depth.view != nullptr
? DxvkAttachmentOps { ? DxvkDepthAttachmentOps {
VK_ATTACHMENT_LOAD_OP_LOAD, renderTargets.depth.view->imageInfo().layout, VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE, renderTargets.depth.view->imageInfo().layout } VK_ATTACHMENT_LOAD_OP_LOAD,
: DxvkAttachmentOps { }; 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++) { for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
renderPassOps.colorOps[i] = renderTargets.color[i].view != nullptr renderPassOps.colorOps[i] = renderTargets.color[i].view != nullptr
? DxvkAttachmentOps { ? DxvkColorAttachmentOps {
VK_ATTACHMENT_LOAD_OP_LOAD, renderTargets.color[i].view->imageInfo().layout, VK_ATTACHMENT_LOAD_OP_LOAD,
VK_ATTACHMENT_STORE_OP_STORE, renderTargets.color[i].view->imageInfo().layout } renderTargets.color[i].view->imageInfo().layout,
: DxvkAttachmentOps { }; VK_ATTACHMENT_STORE_OP_STORE,
renderTargets.color[i].view->imageInfo().layout }
: DxvkColorAttachmentOps { };
} }
// TODO provide a sane alternative for this // TODO provide a sane alternative for this

View File

@ -30,6 +30,7 @@ namespace dxvk {
DxvkContext( DxvkContext(
const Rc<DxvkDevice>& device, const Rc<DxvkDevice>& device,
const Rc<DxvkPipelineCache>& pipelineCache, const Rc<DxvkPipelineCache>& pipelineCache,
const Rc<DxvkPipelineManager>& pipelineManager,
const Rc<DxvkMetaClearObjects>& metaClearObjects); const Rc<DxvkMetaClearObjects>& metaClearObjects);
~DxvkContext(); ~DxvkContext();
@ -644,7 +645,9 @@ namespace dxvk {
void renderPassBindFramebuffer( void renderPassBindFramebuffer(
const Rc<DxvkFramebuffer>& framebuffer, const Rc<DxvkFramebuffer>& framebuffer,
const DxvkRenderPassOps& ops); const DxvkRenderPassOps& ops,
uint32_t clearValueCount,
const VkClearValue* clearValues);
void renderPassUnbindFramebuffer(); void renderPassUnbindFramebuffer();

View File

@ -16,12 +16,13 @@ namespace dxvk {
/** /**
* \brief Graphics pipeline state flags * \brief Graphics pipeline state flags
* *
* Stores some information on which state of the * Stores some information on which state
* graphics pipeline has changed and/or needs to * of the graphics and compute pipelines
* be updated. * has changed and/or needs to be updated.
*/ */
enum class DxvkContextFlag : uint64_t { enum class DxvkContextFlag : uint64_t {
GpRenderPassBound, ///< Render pass is currently bound GpRenderPassBound, ///< Render pass is currently bound
GpClearRenderTargets, ///< Render targets need to be cleared
GpDirtyFramebuffer, ///< Framebuffer binding is out of date GpDirtyFramebuffer, ///< Framebuffer binding is out of date
GpDirtyPipeline, ///< Graphics pipeline binding is out of date GpDirtyPipeline, ///< Graphics pipeline binding is out of date
GpDirtyPipelineState, ///< Graphics pipeline needs to be recompiled GpDirtyPipelineState, ///< Graphics pipeline needs to be recompiled
@ -54,7 +55,7 @@ namespace dxvk {
struct DxvkOutputMergerState { struct DxvkOutputMergerState {
std::array<VkClearValue, MaxNumRenderTargets + 1> clearValue; std::array<VkClearValue, MaxNumRenderTargets + 1> clearValues = { };
DxvkRenderTargets renderTargets; DxvkRenderTargets renderTargets;
DxvkRenderPassOps renderPassOps; DxvkRenderPassOps renderPassOps;

View File

@ -16,6 +16,7 @@ namespace dxvk {
m_memory (new DxvkMemoryAllocator (adapter, vkd)), m_memory (new DxvkMemoryAllocator (adapter, vkd)),
m_renderPassPool (new DxvkRenderPassPool (vkd)), m_renderPassPool (new DxvkRenderPassPool (vkd)),
m_pipelineCache (new DxvkPipelineCache (vkd)), m_pipelineCache (new DxvkPipelineCache (vkd)),
m_pipelineManager (new DxvkPipelineManager (this)),
m_metaClearObjects(new DxvkMetaClearObjects (vkd)), m_metaClearObjects(new DxvkMetaClearObjects (vkd)),
m_unboundResources(this), m_unboundResources(this),
m_submissionQueue (this) { m_submissionQueue (this) {
@ -106,6 +107,7 @@ namespace dxvk {
Rc<DxvkContext> DxvkDevice::createContext() { Rc<DxvkContext> DxvkDevice::createContext() {
return new DxvkContext(this, return new DxvkContext(this,
m_pipelineCache, m_pipelineCache,
m_pipelineManager,
m_metaClearObjects); m_metaClearObjects);
} }

View File

@ -355,6 +355,7 @@ namespace dxvk {
Rc<DxvkMemoryAllocator> m_memory; Rc<DxvkMemoryAllocator> m_memory;
Rc<DxvkRenderPassPool> m_renderPassPool; Rc<DxvkRenderPassPool> m_renderPassPool;
Rc<DxvkPipelineCache> m_pipelineCache; Rc<DxvkPipelineCache> m_pipelineCache;
Rc<DxvkPipelineManager> m_pipelineManager;
Rc<DxvkMetaClearObjects> m_metaClearObjects; Rc<DxvkMetaClearObjects> m_metaClearObjects;
DxvkUnboundResources m_unboundResources; DxvkUnboundResources m_unboundResources;

View File

@ -13,20 +13,18 @@ namespace dxvk {
m_renderSize (computeRenderSize(defaultSize)) { m_renderSize (computeRenderSize(defaultSize)) {
std::array<VkImageView, MaxNumRenderTargets + 1> views; std::array<VkImageView, MaxNumRenderTargets + 1> views;
uint32_t viewId = 0;
for (uint32_t i = 0; i < MaxNumRenderTargets; i++) { for (uint32_t i = 0; i < MaxNumRenderTargets; i++) {
if (m_renderTargets.color[i].view != nullptr) { if (m_renderTargets.color[i].view != nullptr) {
views[viewId] = m_renderTargets.color[i].view->handle(); views[m_attachmentCount] = m_renderTargets.color[i].view->handle();
m_attachments[viewId] = &m_renderTargets.color[i]; m_attachments[m_attachmentCount] = &m_renderTargets.color[i];
viewId += 1; m_attachmentCount += 1;
} }
} }
if (m_renderTargets.depth.view != nullptr) { if (m_renderTargets.depth.view != nullptr) {
views[viewId] = m_renderTargets.depth.view->handle(); views[m_attachmentCount] = m_renderTargets.depth.view->handle();
m_attachments[viewId] = &m_renderTargets.depth; m_attachments[m_attachmentCount] = &m_renderTargets.depth;
viewId += 1; m_attachmentCount += 1;
} }
VkFramebufferCreateInfo info; VkFramebufferCreateInfo info;
@ -34,7 +32,7 @@ namespace dxvk {
info.pNext = nullptr; info.pNext = nullptr;
info.flags = 0; info.flags = 0;
info.renderPass = m_renderPass->getDefaultHandle(); info.renderPass = m_renderPass->getDefaultHandle();
info.attachmentCount = viewId; info.attachmentCount = m_attachmentCount;
info.pAttachments = views.data(); info.pAttachments = views.data();
info.width = m_renderSize.width; info.width = m_renderSize.width;
info.height = m_renderSize.height; info.height = m_renderSize.height;

View File

@ -78,23 +78,52 @@ namespace dxvk {
VkPipeline DxvkGraphicsPipeline::getPipelineHandle( VkPipeline DxvkGraphicsPipeline::getPipelineHandle(
const DxvkGraphicsPipelineStateInfo& state, const DxvkGraphicsPipelineStateInfo& state,
DxvkStatCounters& stats) { DxvkStatCounters& stats) {
VkPipeline pipeline = VK_NULL_HANDLE;
for (const PipelineStruct& pair : m_pipelines) { { std::lock_guard<sync::Spinlock> lock(m_mutex);
if (pair.stateVector == state)
return pair.pipeline; 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) ? this->compilePipeline(state, m_basePipeline)
: VK_NULL_HANDLE; : 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) return false;
m_basePipeline = pipeline;
stats.addCtr(DxvkStatCounter::PipeCountGraphics, 1);
return pipeline;
} }

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <vector> #include <mutex>
#include "dxvk_binding.h" #include "dxvk_binding.h"
#include "dxvk_constant_state.h" #include "dxvk_constant_state.h"
@ -160,10 +160,15 @@ namespace dxvk {
DxvkGraphicsCommonPipelineStateInfo m_common; DxvkGraphicsCommonPipelineStateInfo m_common;
sync::Spinlock m_mutex;
std::vector<PipelineStruct> m_pipelines; std::vector<PipelineStruct> m_pipelines;
VkPipeline m_basePipeline = VK_NULL_HANDLE; VkPipeline m_basePipeline = VK_NULL_HANDLE;
bool findPipeline(
const DxvkGraphicsPipelineStateInfo& state,
VkPipeline& pipeline) const;
VkPipeline compilePipeline( VkPipeline compilePipeline(
const DxvkGraphicsPipelineStateInfo& state, const DxvkGraphicsPipelineStateInfo& state,
VkPipeline baseHandle) const; VkPipeline baseHandle) const;

View File

@ -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; return a.cs == b.cs;
} }
bool DxvkPipelineKeyEq::operator () (const DxvkGraphicsPipelineKey& a, const DxvkGraphicsPipelineKey& b) const { bool DxvkPipelineKeyEq::operator () (
return a.vs == b.vs const DxvkGraphicsPipelineKey& a,
&& a.tcs == b.tcs const DxvkGraphicsPipelineKey& b) const {
&& a.tes == b.tes return a.vs == b.vs && a.tcs == b.tcs
&& a.gs == b.gs && a.tes == b.tes && a.gs == b.gs
&& a.fs == b.fs; && a.fs == b.fs;
} }
@ -52,6 +54,8 @@ namespace dxvk {
if (cs == nullptr) if (cs == nullptr)
return nullptr; return nullptr;
std::lock_guard<std::mutex> lock(m_mutex);
DxvkComputePipelineKey key; DxvkComputePipelineKey key;
key.cs = cs; key.cs = cs;
@ -77,6 +81,8 @@ namespace dxvk {
if (vs == nullptr) if (vs == nullptr)
return nullptr; return nullptr;
std::lock_guard<std::mutex> lock(m_mutex);
DxvkGraphicsPipelineKey key; DxvkGraphicsPipelineKey key;
key.vs = vs; key.vs = vs;
key.tcs = tcs; key.tcs = tcs;

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <mutex>
#include <unordered_map> #include <unordered_map>
#include "dxvk_compute.h" #include "dxvk_compute.h"
@ -99,6 +100,8 @@ namespace dxvk {
const DxvkDevice* m_device; const DxvkDevice* m_device;
std::mutex m_mutex;
std::unordered_map< std::unordered_map<
DxvkComputePipelineKey, DxvkComputePipelineKey,
Rc<DxvkComputePipeline>, Rc<DxvkComputePipeline>,

View File

@ -89,10 +89,10 @@ namespace dxvk {
desc.flags = 0; desc.flags = 0;
desc.format = m_format.depth.format; desc.format = m_format.depth.format;
desc.samples = m_format.sampleCount; desc.samples = m_format.sampleCount;
desc.loadOp = ops.depthOps.loadOp; desc.loadOp = ops.depthOps.loadOpD;
desc.storeOp = ops.depthOps.storeOp; desc.storeOp = ops.depthOps.storeOpD;
desc.stencilLoadOp = ops.depthOps.loadOp; desc.stencilLoadOp = ops.depthOps.loadOpS;
desc.stencilStoreOp = ops.depthOps.storeOp; desc.stencilStoreOp = ops.depthOps.storeOpS;
desc.initialLayout = ops.depthOps.loadLayout; desc.initialLayout = ops.depthOps.loadLayout;
desc.finalLayout = ops.depthOps.storeLayout; desc.finalLayout = ops.depthOps.storeLayout;
@ -179,9 +179,11 @@ namespace dxvk {
bool DxvkRenderPass::compareOps( bool DxvkRenderPass::compareOps(
const DxvkRenderPassOps& a, const DxvkRenderPassOps& a,
const DxvkRenderPassOps& b) { 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.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; && a.depthOps.storeLayout == b.depthOps.storeLayout;
for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) { for (uint32_t i = 0; i < MaxNumRenderTargets && eq; i++) {

View File

@ -35,12 +35,12 @@ namespace dxvk {
/** /**
* \brief Attachment transitions * \brief Color attachment transitions
* *
* Stores the load/store ops and the initial * Stores the load/store ops and the initial
* and final layout of a single attachment. * and final layout of a single attachment.
*/ */
struct DxvkAttachmentOps { struct DxvkColorAttachmentOps {
VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; VkAttachmentLoadOp loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
VkImageLayout loadLayout = VK_IMAGE_LAYOUT_UNDEFINED; VkImageLayout loadLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkAttachmentStoreOp storeOp = VK_ATTACHMENT_STORE_OP_STORE; 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 * \brief Render pass transitions
* *
@ -56,8 +72,8 @@ namespace dxvk {
* from a group of render passes with the same format. * from a group of render passes with the same format.
*/ */
struct DxvkRenderPassOps { struct DxvkRenderPassOps {
DxvkAttachmentOps depthOps; DxvkDepthAttachmentOps depthOps;
DxvkAttachmentOps colorOps[MaxNumRenderTargets]; DxvkColorAttachmentOps colorOps[MaxNumRenderTargets];
}; };