mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-31 05:52:11 +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,
|
||||
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);
|
||||
|
||||
BindFramebuffer();
|
||||
SetRenderTargets(NumViews, ppRenderTargetViews, pDepthStencilView);
|
||||
BindFramebuffer(std::exchange(m_state.om.isUavRendering, false));
|
||||
}
|
||||
|
||||
|
||||
@ -2094,14 +2082,17 @@ namespace dxvk {
|
||||
UINT NumUAVs,
|
||||
ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
|
||||
const UINT* pUAVInitialCounts) {
|
||||
bool spillOnBind = m_state.om.isUavRendering;
|
||||
|
||||
if (NumRTVs != D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL)
|
||||
OMSetRenderTargets(NumRTVs, ppRenderTargetViews, pDepthStencilView);
|
||||
SetRenderTargets(NumRTVs, ppRenderTargetViews, pDepthStencilView);
|
||||
|
||||
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))
|
||||
Logger::warn("D3D11: UAV rendering not properly implemented yet");
|
||||
for (uint32_t i = 0; i < NumUAVs && !m_state.om.isUavRendering; i++)
|
||||
m_state.om.isUavRendering = ppUnorderedAccessViews[i] != nullptr;
|
||||
|
||||
// UAVs are made available to all shader stages in
|
||||
// the graphics pipeline even though this code may
|
||||
@ -2118,6 +2109,8 @@ namespace dxvk {
|
||||
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
|
||||
// unbind overlapping shader resource views. Since this comes
|
||||
// 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
|
||||
EmitCs([cAttachments = std::move(attachments)] (DxvkContext* ctx) {
|
||||
ctx->bindRenderTargets(cAttachments);
|
||||
EmitCs([
|
||||
cAttachments = std::move(attachments),
|
||||
cSpill = Spill
|
||||
] (DxvkContext* ctx) {
|
||||
ctx->bindRenderTargets(cAttachments, cSpill);
|
||||
});
|
||||
}
|
||||
|
||||
@ -2786,6 +2782,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(
|
||||
@ -2835,7 +2850,7 @@ namespace dxvk {
|
||||
|
||||
|
||||
void D3D11DeviceContext::RestoreState() {
|
||||
BindFramebuffer();
|
||||
BindFramebuffer(m_state.om.isUavRendering);
|
||||
|
||||
BindShader(m_state.vs.shader.ptr(), VK_SHADER_STAGE_VERTEX_BIT);
|
||||
BindShader(m_state.hs.shader.ptr(), VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT);
|
||||
|
@ -667,7 +667,8 @@ namespace dxvk {
|
||||
|
||||
void ApplyViewportState();
|
||||
|
||||
void BindFramebuffer();
|
||||
void BindFramebuffer(
|
||||
BOOL Spill);
|
||||
|
||||
template<typename T>
|
||||
void BindShader(
|
||||
@ -739,6 +740,11 @@ namespace dxvk {
|
||||
UINT NumUAVs,
|
||||
ID3D11UnorderedAccessView* const* ppUnorderedAccessViews);
|
||||
|
||||
void SetRenderTargets(
|
||||
UINT NumViews,
|
||||
ID3D11RenderTargetView* const* ppRenderTargetViews,
|
||||
ID3D11DepthStencilView* pDepthStencilView);
|
||||
|
||||
void InitUnorderedAccessViewCounters(
|
||||
UINT NumUAVs,
|
||||
ID3D11UnorderedAccessView* const* ppUnorderedAccessViews,
|
||||
|
@ -120,6 +120,8 @@ namespace dxvk {
|
||||
FLOAT blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
UINT sampleMask = 0xFFFFFFFFu;
|
||||
UINT stencilRef = 0u;
|
||||
|
||||
BOOL isUavRendering = FALSE;
|
||||
};
|
||||
|
||||
|
||||
|
@ -180,7 +180,7 @@ namespace dxvk {
|
||||
DxvkRenderTargets renderTargets;
|
||||
renderTargets.color[0].view = swapImage;
|
||||
renderTargets.color[0].layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
m_context->bindRenderTargets(renderTargets);
|
||||
m_context->bindRenderTargets(renderTargets, false);
|
||||
|
||||
VkViewport viewport;
|
||||
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;
|
||||
|
||||
// If necessary, perform clears on the active render targets
|
||||
@ -108,6 +110,9 @@ namespace dxvk {
|
||||
// the same render targets are bound again
|
||||
m_flags.clr(DxvkContextFlag::GpDirtyFramebuffer);
|
||||
}
|
||||
|
||||
if (spill)
|
||||
this->spillRenderPass();
|
||||
}
|
||||
|
||||
|
||||
|
@ -77,12 +77,15 @@ namespace dxvk {
|
||||
* \brief Sets render targets
|
||||
*
|
||||
* Creates a framebuffer on the fly if necessary
|
||||
* and binds it using \c bindFramebuffer. Prefer
|
||||
* this method over doing the same thing manually.
|
||||
* and binds it using \c bindFramebuffer. Set the
|
||||
* \c spill flag in order to make shader writes
|
||||
* from previous rendering operations visible.
|
||||
* \param [in] targets Render targets to bind
|
||||
* \param [in] spill Spill render pass if true
|
||||
*/
|
||||
void bindRenderTargets(
|
||||
const DxvkRenderTargets& targets);
|
||||
const DxvkRenderTargets& targets,
|
||||
bool spill);
|
||||
|
||||
/**
|
||||
* \brief Binds index buffer
|
||||
|
@ -135,6 +135,8 @@ namespace dxvk {
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT |
|
||||
VK_ACCESS_TRANSFER_READ_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_WRITE_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
@ -144,6 +146,8 @@ namespace dxvk {
|
||||
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_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_WRITE_BIT |
|
||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||
|
@ -108,7 +108,7 @@ namespace dxvk::hud {
|
||||
clearRect.layerCount = 1;
|
||||
|
||||
m_context->bindRenderTargets(
|
||||
m_renderTargetInfo);
|
||||
m_renderTargetInfo, false);
|
||||
|
||||
m_context->clearRenderTarget(
|
||||
m_renderTargetView, clearRect,
|
||||
|
Loading…
x
Reference in New Issue
Block a user