From 35a84053b576bd87b7e0d60764fc6e25688fc7b5 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 17 Sep 2022 22:38:28 +0200 Subject: [PATCH] [dxbc] Implement rasterizer ordered views --- src/dxbc/dxbc_compiler.cpp | 31 ++++++++++++++++++++++++++++++- src/dxbc/dxbc_compiler.h | 1 + src/dxbc/dxbc_options.cpp | 1 + src/dxbc/dxbc_options.h | 3 +++ src/spirv/spirv_module.cpp | 10 ++++++++++ src/spirv/spirv_module.h | 6 +++++- 6 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index cfb5708f5..ed5e7533c 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -6950,11 +6950,31 @@ namespace dxvk { this->emitInputSetup(); this->emitClipCullLoad(DxbcSystemValue::ClipDistance, m_clipDistances); this->emitClipCullLoad(DxbcSystemValue::CullDistance, m_cullDistances); - + + if (m_hasRasterizerOrderedUav) { + // For simplicity, just lock the entire fragment shader + // if there are any rasterizer ordered views. + m_module.enableExtension("SPV_EXT_fragment_shader_interlock"); + + if (m_module.hasCapability(spv::CapabilitySampleRateShading) + && m_moduleInfo.options.enableSampleShadingInterlock) { + m_module.enableCapability(spv::CapabilityFragmentShaderSampleInterlockEXT); + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeSampleInterlockOrderedEXT); + } else { + m_module.enableCapability(spv::CapabilityFragmentShaderPixelInterlockEXT); + m_module.setExecutionMode(m_entryPointId, spv::ExecutionModePixelInterlockOrderedEXT); + } + + m_module.opBeginInvocationInterlock(); + } + m_module.opFunctionCall( m_module.defVoidType(), m_ps.functionId, 0, nullptr); + if (m_hasRasterizerOrderedUav) + m_module.opEndInvocationInterlock(); + this->emitOutputSetup(); if (m_moduleInfo.options.useDepthClipWorkaround) @@ -7768,6 +7788,15 @@ namespace dxvk { uint32_t DxbcCompiler::getUavCoherence(uint32_t registerId, DxbcUavFlags flags) { + // For any ROV with write access, we must ensure that + // availability operations happen within the locked scope. + if (flags.test(DxbcUavFlag::RasterizerOrdered) + && (m_analysis->uavInfos[registerId].accessFlags & VK_ACCESS_SHADER_WRITE_BIT)) { + m_hasGloballyCoherentUav = true; + m_hasRasterizerOrderedUav = true; + return spv::ScopeQueueFamily; + } + // Ignore any resources that can't both be read and written in // the current shader, explicit availability/visibility operands // are not useful in that case. diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 03ddf7ad6..4720066cb 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -454,6 +454,7 @@ namespace dxvk { std::array m_uavs; bool m_hasGloballyCoherentUav = false; + bool m_hasRasterizerOrderedUav = false; /////////////////////////////////////////////// // Control flow information. Stores labels for diff --git a/src/dxbc/dxbc_options.cpp b/src/dxbc/dxbc_options.cpp index 51c565bd4..9b0a5cfff 100644 --- a/src/dxbc/dxbc_options.cpp +++ b/src/dxbc/dxbc_options.cpp @@ -39,6 +39,7 @@ namespace dxvk { zeroInitWorkgroupMemory = options.zeroInitWorkgroupMemory; forceVolatileTgsmAccess = options.forceVolatileTgsmAccess; disableMsaa = options.disableMsaa; + enableSampleShadingInterlock = device->features().extFragmentShaderInterlock.fragmentShaderSampleInterlock; // Figure out float control flags to match D3D11 rules if (options.floatControls) { diff --git a/src/dxbc/dxbc_options.h b/src/dxbc/dxbc_options.h index 0949a6e10..6551b3c07 100644 --- a/src/dxbc/dxbc_options.h +++ b/src/dxbc/dxbc_options.h @@ -46,6 +46,9 @@ namespace dxvk { /// Replace ld_ms with ld bool disableMsaa = false; + // Enable per-sample interlock if supported + bool enableSampleShadingInterlock = false; + /// Float control flags DxbcFloatControlFlags floatControl; diff --git a/src/spirv/spirv_module.cpp b/src/spirv/spirv_module.cpp index b90e1edce..09240f290 100644 --- a/src/spirv/spirv_module.cpp +++ b/src/spirv/spirv_module.cpp @@ -3693,6 +3693,16 @@ namespace dxvk { } + void SpirvModule::opBeginInvocationInterlock() { + m_code.putIns(spv::OpBeginInvocationInterlockEXT, 1); + } + + + void SpirvModule::opEndInvocationInterlock() { + m_code.putIns(spv::OpEndInvocationInterlockEXT, 1); + } + + uint32_t SpirvModule::defType( spv::Op op, uint32_t argCount, diff --git a/src/spirv/spirv_module.h b/src/spirv/spirv_module.h index 2113101bb..a878e2e11 100644 --- a/src/spirv/spirv_module.h +++ b/src/spirv/spirv_module.h @@ -1259,7 +1259,11 @@ namespace dxvk { void opEndPrimitive( uint32_t streamId); - + + void opBeginInvocationInterlock(); + + void opEndInvocationInterlock(); + private: uint32_t m_version;