1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-12 04:54:17 +01:00

[d3d11] Implement render pass spilling for UAV rendering

Spilling the render pass should make shader storage buffer/image writes
visible due to how external subpass dependencies are defined. For UAV
rendering, we need to do this when changing the UAVs, even if the render
targets themselves do not change.
This commit is contained in:
Philip Rebohle 2018-06-15 20:49:24 +02:00
parent 7a22fa22a7
commit 7fa26f1c87
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
8 changed files with 64 additions and 29 deletions

View File

@ -2069,20 +2069,8 @@ namespace dxvk {
UINT NumViews, UINT NumViews,
ID3D11RenderTargetView* const* ppRenderTargetViews, ID3D11RenderTargetView* const* ppRenderTargetViews,
ID3D11DepthStencilView* pDepthStencilView) { ID3D11DepthStencilView* pDepthStencilView) {
// Native D3D11 does not change the render targets if SetRenderTargets(NumViews, ppRenderTargetViews, pDepthStencilView);
// the parameters passed to this method are invalid. BindFramebuffer(std::exchange(m_state.om.isUavRendering, false));
if (!ValidateRenderTargets(NumViews, ppRenderTargetViews, pDepthStencilView))
return;
for (UINT i = 0; i < m_state.om.renderTargetViews.size(); i++) {
m_state.om.renderTargetViews.at(i) = i < NumViews
? static_cast<D3D11RenderTargetView*>(ppRenderTargetViews[i])
: nullptr;
}
m_state.om.depthStencilView = static_cast<D3D11DepthStencilView*>(pDepthStencilView);
BindFramebuffer();
} }
@ -2094,14 +2082,17 @@ namespace dxvk {
UINT NumUAVs, UINT NumUAVs,
ID3D11UnorderedAccessView* const* ppUnorderedAccessViews, ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
const UINT* pUAVInitialCounts) { const UINT* pUAVInitialCounts) {
bool spillOnBind = m_state.om.isUavRendering;
if (NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL) if (NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL)
OMSetRenderTargets(NumRTVs, ppRenderTargetViews, pDepthStencilView); SetRenderTargets(NumRTVs, ppRenderTargetViews, pDepthStencilView);
if (NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS) { if (NumUAVs != D3D11_KEEP_UNORDERED_ACCESS_VIEWS) {
static std::atomic<bool> s_warningShown = { false }; // Check whether there actually are any UAVs bound
m_state.om.isUavRendering = false;
if (NumUAVs != 0 && !s_warningShown.exchange(true)) for (uint32_t i = 0; i < NumUAVs && !m_state.om.isUavRendering; i++)
Logger::warn("D3D11: UAV rendering not properly implemented yet"); m_state.om.isUavRendering = ppUnorderedAccessViews[i] != nullptr;
// UAVs are made available to all shader stages in // UAVs are made available to all shader stages in
// the graphics pipeline even though this code may // the graphics pipeline even though this code may
@ -2118,6 +2109,8 @@ namespace dxvk {
ppUnorderedAccessViews, pUAVInitialCounts); ppUnorderedAccessViews, pUAVInitialCounts);
} }
} }
BindFramebuffer(spillOnBind);
} }
@ -2554,7 +2547,7 @@ namespace dxvk {
} }
void D3D11DeviceContext::BindFramebuffer() { void D3D11DeviceContext::BindFramebuffer(BOOL Spill) {
// NOTE According to the Microsoft docs, we are supposed to // NOTE According to the Microsoft docs, we are supposed to
// unbind overlapping shader resource views. Since this comes // unbind overlapping shader resource views. Since this comes
// with a large performance penalty we'll ignore this until an // with a large performance penalty we'll ignore this until an
@ -2579,8 +2572,11 @@ namespace dxvk {
} }
// Create and bind the framebuffer object to the context // Create and bind the framebuffer object to the context
EmitCs([cAttachments = std::move(attachments)] (DxvkContext* ctx) { EmitCs([
ctx->bindRenderTargets(cAttachments); cAttachments = std::move(attachments),
cSpill = Spill
] (DxvkContext* ctx) {
ctx->bindRenderTargets(cAttachments, cSpill);
}); });
} }
@ -2788,6 +2784,25 @@ namespace dxvk {
} }
void D3D11DeviceContext::SetRenderTargets(
UINT NumViews,
ID3D11RenderTargetView* const* ppRenderTargetViews,
ID3D11DepthStencilView* pDepthStencilView) {
// Native D3D11 does not change the render targets if
// the parameters passed to this method are invalid.
if (!ValidateRenderTargets(NumViews, ppRenderTargetViews, pDepthStencilView))
return;
for (UINT i = 0; i < m_state.om.renderTargetViews.size(); i++) {
m_state.om.renderTargetViews.at(i) = i < NumViews
? static_cast<D3D11RenderTargetView*>(ppRenderTargetViews[i])
: nullptr;
}
m_state.om.depthStencilView = static_cast<D3D11DepthStencilView*>(pDepthStencilView);
}
void D3D11DeviceContext::InitUnorderedAccessViewCounters( void D3D11DeviceContext::InitUnorderedAccessViewCounters(
UINT NumUAVs, UINT NumUAVs,
ID3D11UnorderedAccessView* const* ppUnorderedAccessViews, ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
@ -2835,7 +2850,7 @@ namespace dxvk {
void D3D11DeviceContext::RestoreState() { void D3D11DeviceContext::RestoreState() {
BindFramebuffer(); BindFramebuffer(m_state.om.isUavRendering);
BindShader(m_state.vs.shader.ptr(), VK_SHADER_STAGE_VERTEX_BIT); BindShader(m_state.vs.shader.ptr(), VK_SHADER_STAGE_VERTEX_BIT);
BindShader(m_state.hs.shader.ptr(), VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT); BindShader(m_state.hs.shader.ptr(), VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);

View File

@ -667,7 +667,8 @@ namespace dxvk {
void ApplyViewportState(); void ApplyViewportState();
void BindFramebuffer(); void BindFramebuffer(
BOOL Spill);
template<typename T> template<typename T>
void BindShader( void BindShader(
@ -739,6 +740,11 @@ namespace dxvk {
UINT NumUAVs, UINT NumUAVs,
ID3D11UnorderedAccessView* const* ppUnorderedAccessViews); ID3D11UnorderedAccessView* const* ppUnorderedAccessViews);
void SetRenderTargets(
UINT NumViews,
ID3D11RenderTargetView* const* ppRenderTargetViews,
ID3D11DepthStencilView* pDepthStencilView);
void InitUnorderedAccessViewCounters( void InitUnorderedAccessViewCounters(
UINT NumUAVs, UINT NumUAVs,
ID3D11UnorderedAccessView* const* ppUnorderedAccessViews, ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,

View File

@ -120,6 +120,8 @@ namespace dxvk {
FLOAT blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; FLOAT blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
UINT sampleMask = 0xFFFFFFFFu; UINT sampleMask = 0xFFFFFFFFu;
UINT stencilRef = 0u; UINT stencilRef = 0u;
BOOL isUavRendering = FALSE;
}; };

View File

@ -180,7 +180,7 @@ namespace dxvk {
DxvkRenderTargets renderTargets; DxvkRenderTargets renderTargets;
renderTargets.color[0].view = swapImage; renderTargets.color[0].view = swapImage;
renderTargets.color[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; renderTargets.color[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
m_context->bindRenderTargets(renderTargets); m_context->bindRenderTargets(renderTargets, false);
VkViewport viewport; VkViewport viewport;
viewport.x = 0.0f; viewport.x = 0.0f;

View File

@ -87,7 +87,9 @@ namespace dxvk {
} }
void DxvkContext::bindRenderTargets(const DxvkRenderTargets& targets) { void DxvkContext::bindRenderTargets(
const DxvkRenderTargets& targets,
bool spill) {
m_state.om.renderTargets = targets; m_state.om.renderTargets = targets;
// If necessary, perform clears on the active render targets // If necessary, perform clears on the active render targets
@ -108,6 +110,9 @@ namespace dxvk {
// the same render targets are bound again // the same render targets are bound again
m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer); m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer);
} }
if (spill)
this->spillRenderPass();
} }

View File

@ -77,12 +77,15 @@ namespace dxvk {
* \brief Sets render targets * \brief Sets render targets
* *
* Creates a framebuffer on the fly if necessary * Creates a framebuffer on the fly if necessary
* and binds it using \c bindFramebuffer. Prefer * and binds it using \c bindFramebuffer. Set the
* this method over doing the same thing manually. * \c spill flag in order to make shader writes
* from previous rendering operations visible.
* \param [in] targets Render targets to bind * \param [in] targets Render targets to bind
* \param [in] spill Spill render pass if true
*/ */
void bindRenderTargets( void bindRenderTargets(
const DxvkRenderTargets& targets); const DxvkRenderTargets& targets,
bool spill);
/** /**
* \brief Binds index buffer * \brief Binds index buffer

View File

@ -135,6 +135,8 @@ namespace dxvk {
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_READ_BIT |
VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT,
VK_ACCESS_SHADER_READ_BIT |
VK_ACCESS_SHADER_WRITE_BIT |
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
@ -144,6 +146,8 @@ namespace dxvk {
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_ACCESS_SHADER_READ_BIT |
VK_ACCESS_SHADER_WRITE_BIT |
VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |

View File

@ -108,7 +108,7 @@ namespace dxvk::hud {
clearRect.layerCount = 1; clearRect.layerCount = 1;
m_context->bindRenderTargets( m_context->bindRenderTargets(
m_renderTargetInfo); m_renderTargetInfo, false);
m_context->clearRenderTarget( m_context->clearRenderTarget(
m_renderTargetView, clearRect, m_renderTargetView, clearRect,