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:
parent
7a22fa22a7
commit
7fa26f1c87
@ -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);
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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 |
|
||||||
|
@ -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,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user