From 017699df1504a02a2210a92cf3d207a7f6f43122 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sun, 24 Jun 2018 01:07:48 +0200 Subject: [PATCH] [dxbc] Implement Xfb output declarations and setup --- src/dxbc/dxbc_compiler.cpp | 89 ++++++++++++++++++++++++++++++++++++-- src/dxbc/dxbc_compiler.h | 22 ++++++++++ 2 files changed, 108 insertions(+), 3 deletions(-) diff --git a/src/dxbc/dxbc_compiler.cpp b/src/dxbc/dxbc_compiler.cpp index 7e5c80dc..33bdb753 100644 --- a/src/dxbc/dxbc_compiler.cpp +++ b/src/dxbc/dxbc_compiler.cpp @@ -673,12 +673,19 @@ namespace dxvk { info.type.ccount = regType.ccount; info.type.alength = regDim; info.sclass = spv::StorageClassOutput; + + // In xfb mode, we set up the actual + // output vars when emitting a vertex + if (m_moduleInfo.xfb != nullptr) + info.sclass = spv::StorageClassPrivate; const uint32_t varId = this->emitNewVariable(info); - - m_module.decorateLocation(varId, regIdx); m_module.setDebugName(varId, str::format("o", regIdx).c_str()); - m_entryPointInterfaces.push_back(varId); + + if (info.sclass == spv::StorageClassOutput) { + m_module.decorateLocation(varId, regIdx); + m_entryPointInterfaces.push_back(varId); + } m_oRegs.at(regIdx) = { regType, varId }; @@ -2071,6 +2078,7 @@ namespace dxvk { emitOutputSetup(); emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances); emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances); + emitXfbOutputSetup(streamId); m_module.opEmitVertex(streamVar); } @@ -6050,6 +6058,10 @@ namespace dxvk { spv::BuiltInCullDistance, spv::StorageClassOutput); + // Emit Xfb variables if necessary + if (m_moduleInfo.xfb != nullptr) + emitXfbOutputDeclarations(); + // Main function of the vertex shader m_gs.functionId = m_module.allocateId(); m_module.setDebugName(m_gs.functionId, "gs_main"); @@ -6226,6 +6238,77 @@ namespace dxvk { } + void DxbcCompiler::emitXfbOutputDeclarations() { + for (uint32_t i = 0; i < m_moduleInfo.xfb->entryCount; i++) { + const DxbcXfbEntry* xfbEntry = m_moduleInfo.xfb->entries + i; + const DxbcSgnEntry* sigEntry = m_osgn->find( + xfbEntry->semanticName, + xfbEntry->semanticIndex, + xfbEntry->streamId); + + if (sigEntry == nullptr) + continue; + + DxbcRegisterInfo varInfo; + varInfo.type.ctype = DxbcScalarType::Float32; + varInfo.type.ccount = xfbEntry->componentCount; + varInfo.type.alength = 0; + varInfo.sclass = spv::StorageClassOutput; + + uint32_t dstComponentMask = (1 << xfbEntry->componentCount) - 1; + uint32_t srcComponentMask = dstComponentMask + << sigEntry->componentMask.firstSet() + << xfbEntry->componentIndex; + + DxbcXfbVar xfbVar; + xfbVar.varId = emitNewVariable(varInfo); + xfbVar.streamId = xfbEntry->streamId; + xfbVar.outputId = sigEntry->registerId; + xfbVar.srcMask = DxbcRegMask(srcComponentMask); + xfbVar.dstMask = DxbcRegMask(dstComponentMask); + m_xfbVars.push_back(xfbVar); + + m_entryPointInterfaces.push_back(xfbVar.varId); + m_module.setDebugName(xfbVar.varId, + str::format("xfb", i).c_str()); + + m_module.decorateXfb(xfbVar.varId, + xfbEntry->streamId, xfbEntry->bufferId, xfbEntry->offset, + m_moduleInfo.xfb->strides[xfbEntry->bufferId]); + } + + // TODO Compact location/component assignment + for (uint32_t i = 0; i < m_xfbVars.size(); i++) { + m_xfbVars[i].location = i; + m_xfbVars[i].component = 0; + } + + for (uint32_t i = 0; i < m_xfbVars.size(); i++) { + const DxbcXfbVar* var = &m_xfbVars[i]; + + m_module.decorateLocation (var->varId, var->location); + m_module.decorateComponent(var->varId, var->component); + } + } + + + void DxbcCompiler::emitXfbOutputSetup(uint32_t streamId) { + for (size_t i = 0; i < m_xfbVars.size(); i++) { + if (m_xfbVars[i].streamId == streamId) { + DxbcRegisterPointer srcPtr = m_oRegs[m_xfbVars[i].outputId]; + DxbcRegisterPointer dstPtr; + dstPtr.type.ctype = DxbcScalarType::Float32; + dstPtr.type.ccount = m_xfbVars[i].dstMask.popCount(); + dstPtr.id = m_xfbVars[i].varId; + + DxbcRegisterValue value = emitRegisterExtract( + emitValueLoad(srcPtr), m_xfbVars[i].srcMask); + emitValueStore(dstPtr, value, m_xfbVars[i].dstMask); + } + } + } + + void DxbcCompiler::emitHsControlPointPhase( const DxbcCompilerHsControlPointPhase& phase) { m_module.opFunctionCall( diff --git a/src/dxbc/dxbc_compiler.h b/src/dxbc/dxbc_compiler.h index 93ec819b..2e5e20fd 100644 --- a/src/dxbc/dxbc_compiler.h +++ b/src/dxbc/dxbc_compiler.h @@ -122,6 +122,17 @@ namespace dxvk { uint32_t labelElse = 0; uint32_t labelEnd = 0; }; + + + struct DxbcXfbVar { + uint32_t varId = 0; + uint32_t streamId = 0; + uint32_t outputId = 0; + DxbcRegMask srcMask = 0; + DxbcRegMask dstMask = 0; + uint32_t location = 0; + uint32_t component = 0; + }; /** @@ -419,6 +430,10 @@ namespace dxvk { DxbcRegisterPointer, DxbcMaxInterfaceRegs> m_oRegs; std::vector m_oMappings; + + ///////////////////////////////////////////// + // xfb output registers for geometry shaders + std::vector m_xfbVars; ////////////////////////////////////////////////////// // Shader resource variables. These provide access to @@ -1044,6 +1059,13 @@ namespace dxvk { void emitGsFinalize(); void emitPsFinalize(); void emitCsFinalize(); + + /////////////////////// + // Xfb related methods + void emitXfbOutputDeclarations(); + + void emitXfbOutputSetup( + uint32_t streamId); /////////////////////////////// // Hull shader phase methods