[dxbc] Support RenderTargetId and ViewportId in Vertex/Domain shaders

Fixes shader compilation errors in Pillars of Eternity II (#408)
and Lost Sphear (#406). Currently unsupported by RADV.
This commit is contained in:
Philip Rebohle 2018-06-01 13:57:26 +02:00
parent 3a520dfe4a
commit 9ff17b03f2
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 78 additions and 38 deletions

View File

@ -5322,6 +5322,50 @@ namespace dxvk {
emitValueStore(ptr, value, mask); emitValueStore(ptr, value, mask);
} break; } break;
case DxbcSystemValue::RenderTargetId: {
if (m_version.type() != DxbcProgramType::GeometryShader)
enableShaderViewportIndexLayer();
if (m_gs.builtinLayer == 0) {
m_gs.builtinLayer = emitNewBuiltinVariable({
{ DxbcScalarType::Uint32, 1, 0 },
spv::StorageClassOutput },
spv::BuiltInLayer,
"o_layer");
}
DxbcRegisterPointer ptr;
ptr.type = { DxbcScalarType::Uint32, 1 };
ptr.id = m_gs.builtinLayer;
emitValueStore(
ptr, emitRegisterExtract(value, mask),
DxbcRegMask(true, false, false, false));
} break;
case DxbcSystemValue::ViewportId: {
if (m_version.type() != DxbcProgramType::GeometryShader)
enableShaderViewportIndexLayer();
if (m_gs.builtinViewportId == 0) {
m_module.enableCapability(spv::CapabilityMultiViewport);
m_gs.builtinViewportId = emitNewBuiltinVariable({
{ DxbcScalarType::Uint32, 1, 0 },
spv::StorageClassOutput },
spv::BuiltInViewportIndex,
"o_viewport");
}
DxbcRegisterPointer ptr;
ptr.type = { DxbcScalarType::Uint32, 1};
ptr.id = m_gs.builtinViewportId;
emitValueStore(
ptr, emitRegisterExtract(value, mask),
DxbcRegMask(true, false, false, false));
} break;
default: default:
Logger::warn(str::format( Logger::warn(str::format(
"DxbcCompiler: Unhandled VS SV output: ", sv)); "DxbcCompiler: Unhandled VS SV output: ", sv));
@ -5394,47 +5438,11 @@ namespace dxvk {
case DxbcSystemValue::Position: case DxbcSystemValue::Position:
case DxbcSystemValue::CullDistance: case DxbcSystemValue::CullDistance:
case DxbcSystemValue::ClipDistance: case DxbcSystemValue::ClipDistance:
case DxbcSystemValue::RenderTargetId:
case DxbcSystemValue::ViewportId:
emitVsSystemValueStore(sv, mask, value); emitVsSystemValueStore(sv, mask, value);
break; break;
case DxbcSystemValue::RenderTargetId: {
if (m_gs.builtinLayer == 0) {
m_gs.builtinLayer = emitNewBuiltinVariable({
{ DxbcScalarType::Uint32, 1, 0 },
spv::StorageClassOutput },
spv::BuiltInLayer,
"gs_layer");
}
DxbcRegisterPointer ptr;
ptr.type = { DxbcScalarType::Uint32, 1 };
ptr.id = m_gs.builtinLayer;
emitValueStore(
ptr, emitRegisterExtract(value, mask),
DxbcRegMask(true, false, false, false));
} break;
case DxbcSystemValue::ViewportId: {
if (m_gs.builtinViewportId == 0) {
m_module.enableCapability(spv::CapabilityMultiViewport);
m_gs.builtinViewportId = emitNewBuiltinVariable({
{ DxbcScalarType::Uint32, 1, 0 },
spv::StorageClassOutput },
spv::BuiltInViewportIndex,
"gs_viewport_id");
}
DxbcRegisterPointer ptr;
ptr.type = { DxbcScalarType::Uint32, 1};
ptr.id = m_gs.builtinViewportId;
emitValueStore(
ptr, emitRegisterExtract(value, mask),
DxbcRegMask(true, false, false, false));
} break;
case DxbcSystemValue::PrimitiveId: { case DxbcSystemValue::PrimitiveId: {
if (m_primitiveIdOut == 0) { if (m_primitiveIdOut == 0) {
m_primitiveIdOut = emitNewBuiltinVariable({ m_primitiveIdOut = emitNewBuiltinVariable({
@ -5477,6 +5485,8 @@ namespace dxvk {
case DxbcSystemValue::Position: case DxbcSystemValue::Position:
case DxbcSystemValue::CullDistance: case DxbcSystemValue::CullDistance:
case DxbcSystemValue::ClipDistance: case DxbcSystemValue::ClipDistance:
case DxbcSystemValue::RenderTargetId:
case DxbcSystemValue::ViewportId:
emitVsSystemValueStore(sv, mask, value); emitVsSystemValueStore(sv, mask, value);
break; break;
@ -6318,6 +6328,16 @@ namespace dxvk {
} }
void DxbcCompiler::enableShaderViewportIndexLayer() {
if (!m_extensions.shaderViewportIndexLayer) {
m_extensions.shaderViewportIndexLayer = true;
m_module.enableExtension("SPV_EXT_shader_viewport_index_layer");
m_module.enableCapability(spv::CapabilityShaderViewportIndexLayerEXT);
}
}
DxbcCfgBlock* DxbcCompiler::cfgFindBlock( DxbcCfgBlock* DxbcCompiler::cfgFindBlock(
const std::initializer_list<DxbcCfgBlockType>& types) { const std::initializer_list<DxbcCfgBlockType>& types) {
for (auto cur = m_controlFlowBlocks.rbegin(); for (auto cur = m_controlFlowBlocks.rbegin();

View File

@ -329,6 +329,18 @@ namespace dxvk {
}; };
/**
* \brief SPIR-V extension set
*
* Keeps track of which optional SPIR-V extensions
* are enabled so that any required setup code is
* only run once.
*/
struct DxbcSpirvExtensions {
bool shaderViewportIndexLayer = false;
};
/** /**
* \brief DXBC to SPIR-V shader compiler * \brief DXBC to SPIR-V shader compiler
* *
@ -473,6 +485,10 @@ namespace dxvk {
DxbcCompilerPsPart m_ps; DxbcCompilerPsPart m_ps;
DxbcCompilerCsPart m_cs; DxbcCompilerCsPart m_cs;
/////////////////////////////
// Enabled SPIR-V extensions
DxbcSpirvExtensions m_extensions;
///////////////////////////////////////////////////// /////////////////////////////////////////////////////
// Shader interface and metadata declaration methods // Shader interface and metadata declaration methods
void emitDcl( void emitDcl(
@ -1051,6 +1067,10 @@ namespace dxvk {
uint32_t emitBuiltinTessLevelInner( uint32_t emitBuiltinTessLevelInner(
spv::StorageClass storageClass); spv::StorageClass storageClass);
////////////////////////////////
// Extension enablement methods
void enableShaderViewportIndexLayer();
//////////////// ////////////////
// Misc methods // Misc methods
DxbcCfgBlock* cfgFindBlock( DxbcCfgBlock* cfgFindBlock(