1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-31 14:52:11 +01:00

[dxbc] Add support for multiple streams in geometry shaders

This commit is contained in:
Philip Rebohle 2018-06-23 23:46:24 +02:00
parent a42f03e32d
commit 6a5fe2247a
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 41 additions and 9 deletions

View File

@ -796,7 +796,7 @@ namespace dxvk {
void DxbcCompiler::emitDclStream(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitDclStream(const DxbcShaderInstruction& ins) {
if (ins.dst[0].idx[0].offset != 0) if (ins.dst[0].idx[0].offset != 0 && m_moduleInfo.xfb == nullptr)
Logger::err("Dxbc: Multiple streams not supported"); Logger::err("Dxbc: Multiple streams not supported");
} }
@ -2053,6 +2053,16 @@ namespace dxvk {
void DxbcCompiler::emitGeometryEmit(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitGeometryEmit(const DxbcShaderInstruction& ins) {
// In xfb mode we might have multiple streams, so
// we have to figure out which stream to write to
uint32_t streamId = 0;
uint32_t streamVar = 0;
if (m_moduleInfo.xfb != nullptr) {
streamId = ins.dstCount > 0 ? ins.dst[0].idx[0].offset : 0;
streamVar = m_module.constu32(streamId);
}
// Checking the negation is easier for EmitThenCut/EmitThenCutStream // Checking the negation is easier for EmitThenCut/EmitThenCutStream
bool doEmit = ins.op != DxbcOpcode::Cut && ins.op != DxbcOpcode::CutStream; bool doEmit = ins.op != DxbcOpcode::Cut && ins.op != DxbcOpcode::CutStream;
bool doCut = ins.op != DxbcOpcode::Emit && ins.op != DxbcOpcode::EmitStream; bool doCut = ins.op != DxbcOpcode::Emit && ins.op != DxbcOpcode::EmitStream;
@ -2061,11 +2071,11 @@ namespace dxvk {
emitOutputSetup(); emitOutputSetup();
emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances); emitClipCullStore(DxbcSystemValue::ClipDistance, m_clipDistances);
emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances); emitClipCullStore(DxbcSystemValue::CullDistance, m_cullDistances);
m_module.opEmitVertex(); m_module.opEmitVertex(streamVar);
} }
if (doCut) if (doCut)
m_module.opEndPrimitive(); m_module.opEndPrimitive(streamVar);
} }
@ -6008,6 +6018,14 @@ namespace dxvk {
m_module.enableCapability(spv::CapabilityGeometry); m_module.enableCapability(spv::CapabilityGeometry);
m_module.enableCapability(spv::CapabilityClipDistance); m_module.enableCapability(spv::CapabilityClipDistance);
m_module.enableCapability(spv::CapabilityCullDistance); m_module.enableCapability(spv::CapabilityCullDistance);
// Enable capabilities for xfb mode if necessary
if (m_moduleInfo.xfb != nullptr) {
m_module.enableCapability(spv::CapabilityGeometryStreams);
m_module.enableCapability(spv::CapabilityTransformFeedback);
m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeXfb);
}
// Declare the per-vertex output block. Outputs are not // Declare the per-vertex output block. Outputs are not
// declared as arrays, instead they will be flushed when // declared as arrays, instead they will be flushed when

View File

@ -2937,13 +2937,25 @@ namespace dxvk {
} }
void SpirvModule::opEmitVertex() { void SpirvModule::opEmitVertex(
m_code.putIns (spv::OpEmitVertex, 1); uint32_t streamId) {
if (streamId == 0) {
m_code.putIns (spv::OpEmitVertex, 1);
} else {
m_code.putIns (spv::OpEmitStreamVertex, 2);
m_code.putWord(streamId);
}
} }
void SpirvModule::opEndPrimitive() { void SpirvModule::opEndPrimitive(
m_code.putIns (spv::OpEndPrimitive, 1); uint32_t streamId) {
if (streamId == 0) {
m_code.putIns (spv::OpEndPrimitive, 1);
} else {
m_code.putIns (spv::OpEndStreamPrimitive, 2);
m_code.putWord(streamId);
}
} }

View File

@ -1022,9 +1022,11 @@ namespace dxvk {
void opKill(); void opKill();
void opEmitVertex(); void opEmitVertex(
uint32_t streamId);
void opEndPrimitive(); void opEndPrimitive(
uint32_t streamId);
private: private: