1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-20 19:54:19 +01:00

[dxbc] Refactored opcode controls

This commit is contained in:
Philip Rebohle 2018-04-10 08:01:54 +02:00
parent 5cb65a6c19
commit 1fb22a6022
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
3 changed files with 97 additions and 69 deletions

View File

@ -276,7 +276,7 @@ namespace dxvk {
void DxbcCompiler::emitDclGlobalFlags(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitDclGlobalFlags(const DxbcShaderInstruction& ins) {
const DxbcGlobalFlags flags = ins.controls.globalFlags; const DxbcGlobalFlags flags = ins.controls.globalFlags();
if (flags.test(DxbcGlobalFlag::EarlyFragmentTests)) if (flags.test(DxbcGlobalFlag::EarlyFragmentTests))
m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeEarlyFragmentTests); m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeEarlyFragmentTests);
@ -387,7 +387,7 @@ namespace dxvk {
DxbcInterpolationMode im = DxbcInterpolationMode::Undefined; DxbcInterpolationMode im = DxbcInterpolationMode::Undefined;
if (hasInterpolationMode) if (hasInterpolationMode)
im = ins.controls.interpolation; im = ins.controls.interpolation();
// Declare the actual input/output variable // Declare the actual input/output variable
switch (ins.op) { switch (ins.op) {
@ -766,7 +766,7 @@ namespace dxvk {
} }
// Defines the type of the resource (texture2D, ...) // Defines the type of the resource (texture2D, ...)
const DxbcResourceDim resourceType = ins.controls.resourceDim; const DxbcResourceDim resourceType = ins.controls.resourceDim();
// Defines the type of a read operation. DXBC has the ability // Defines the type of a read operation. DXBC has the ability
// to define four different types whereas SPIR-V only allows // to define four different types whereas SPIR-V only allows
@ -871,7 +871,7 @@ namespace dxvk {
m_module.decorateDescriptorSet(varId, 0); m_module.decorateDescriptorSet(varId, 0);
m_module.decorateBinding(varId, bindingId); m_module.decorateBinding(varId, bindingId);
if (ins.controls.uavFlags.test(DxbcUavFlag::GloballyCoherent)) if (ins.controls.uavFlags().test(DxbcUavFlag::GloballyCoherent))
m_module.decorate(varId, spv::DecorationCoherent); m_module.decorate(varId, spv::DecorationCoherent);
// Declare a specialization constant which will // Declare a specialization constant which will
@ -992,7 +992,7 @@ namespace dxvk {
m_module.decorateDescriptorSet(varId, 0); m_module.decorateDescriptorSet(varId, 0);
m_module.decorateBinding(varId, bindingId); m_module.decorateBinding(varId, bindingId);
if (ins.controls.uavFlags.test(DxbcUavFlag::GloballyCoherent)) if (ins.controls.uavFlags().test(DxbcUavFlag::GloballyCoherent))
m_module.decorate(varId, spv::DecorationCoherent); m_module.decorate(varId, spv::DecorationCoherent);
// Declare a specialization constant which will // Declare a specialization constant which will
@ -1083,7 +1083,7 @@ namespace dxvk {
// control bits of the opcode token. In SPIR-V, we // control bits of the opcode token. In SPIR-V, we
// have to define an execution mode. // have to define an execution mode.
const spv::ExecutionMode mode = [&] { const spv::ExecutionMode mode = [&] {
switch (ins.controls.primitive) { switch (ins.controls.primitive()) {
case DxbcPrimitive::Point: return spv::ExecutionModeInputPoints; case DxbcPrimitive::Point: return spv::ExecutionModeInputPoints;
case DxbcPrimitive::Line: return spv::ExecutionModeInputLines; case DxbcPrimitive::Line: return spv::ExecutionModeInputLines;
case DxbcPrimitive::Triangle: return spv::ExecutionModeTriangles; case DxbcPrimitive::Triangle: return spv::ExecutionModeTriangles;
@ -1093,7 +1093,7 @@ namespace dxvk {
} }
}(); }();
m_gs.inputPrimitive = ins.controls.primitive; m_gs.inputPrimitive = ins.controls.primitive();
m_module.setExecutionMode(m_entryPointId, mode); m_module.setExecutionMode(m_entryPointId, mode);
const uint32_t vertexCount const uint32_t vertexCount
@ -1109,7 +1109,7 @@ namespace dxvk {
// control bits of the opcode token. In SPIR-V, we have // control bits of the opcode token. In SPIR-V, we have
// to define an execution mode. // to define an execution mode.
const spv::ExecutionMode mode = [&] { const spv::ExecutionMode mode = [&] {
switch (ins.controls.primitiveTopology) { switch (ins.controls.primitiveTopology()) {
case DxbcPrimitiveTopology::PointList: return spv::ExecutionModeOutputPoints; case DxbcPrimitiveTopology::PointList: return spv::ExecutionModeOutputPoints;
case DxbcPrimitiveTopology::LineStrip: return spv::ExecutionModeOutputLineStrip; case DxbcPrimitiveTopology::LineStrip: return spv::ExecutionModeOutputLineStrip;
case DxbcPrimitiveTopology::TriangleStrip: return spv::ExecutionModeOutputTriangleStrip; case DxbcPrimitiveTopology::TriangleStrip: return spv::ExecutionModeOutputTriangleStrip;
@ -1134,11 +1134,11 @@ namespace dxvk {
// dcl_input_control_points has the control point // dcl_input_control_points has the control point
// count embedded within the opcode token. // count embedded within the opcode token.
if (m_version.type() == DxbcProgramType::HullShader) { if (m_version.type() == DxbcProgramType::HullShader) {
m_hs.vertexCountIn = ins.controls.controlPointCount; m_hs.vertexCountIn = ins.controls.controlPointCount();
emitDclInputArray(m_hs.vertexCountIn); emitDclInputArray(m_hs.vertexCountIn);
} else { } else {
m_ds.vertexCountIn = ins.controls.controlPointCount; m_ds.vertexCountIn = ins.controls.controlPointCount();
m_ds.inputPerPatch = emitTessInterfacePerPatch (spv::StorageClassInput); m_ds.inputPerPatch = emitTessInterfacePerPatch (spv::StorageClassInput);
m_ds.inputPerVertex = emitTessInterfacePerVertex(spv::StorageClassInput, m_ds.vertexCountIn); m_ds.inputPerVertex = emitTessInterfacePerVertex(spv::StorageClassInput, m_ds.vertexCountIn);
@ -1149,12 +1149,12 @@ namespace dxvk {
void DxbcCompiler::emitDclOutputControlPointCount(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitDclOutputControlPointCount(const DxbcShaderInstruction& ins) {
// dcl_output_control_points has the control point // dcl_output_control_points has the control point
// count embedded within the opcode token. // count embedded within the opcode token.
m_hs.vertexCountOut = ins.controls.controlPointCount; m_hs.vertexCountOut = ins.controls.controlPointCount();
m_hs.outputPerPatch = emitTessInterfacePerPatch (spv::StorageClassOutput); m_hs.outputPerPatch = emitTessInterfacePerPatch (spv::StorageClassOutput);
m_hs.outputPerVertex = emitTessInterfacePerVertex(spv::StorageClassOutput, m_hs.vertexCountOut); m_hs.outputPerVertex = emitTessInterfacePerVertex(spv::StorageClassOutput, m_hs.vertexCountOut);
m_module.setOutputVertices(m_entryPointId, ins.controls.controlPointCount); m_module.setOutputVertices(m_entryPointId, m_hs.vertexCountOut);
} }
@ -1165,7 +1165,7 @@ namespace dxvk {
void DxbcCompiler::emitDclTessDomain(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitDclTessDomain(const DxbcShaderInstruction& ins) {
const spv::ExecutionMode executionMode = [&] { const spv::ExecutionMode executionMode = [&] {
switch (ins.controls.tessDomain) { switch (ins.controls.tessDomain()) {
case DxbcTessDomain::Isolines: return spv::ExecutionModeIsolines; case DxbcTessDomain::Isolines: return spv::ExecutionModeIsolines;
case DxbcTessDomain::Triangles: return spv::ExecutionModeTriangles; case DxbcTessDomain::Triangles: return spv::ExecutionModeTriangles;
case DxbcTessDomain::Quads: return spv::ExecutionModeQuads; case DxbcTessDomain::Quads: return spv::ExecutionModeQuads;
@ -1179,7 +1179,7 @@ namespace dxvk {
void DxbcCompiler::emitDclTessPartitioning(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitDclTessPartitioning(const DxbcShaderInstruction& ins) {
const spv::ExecutionMode executionMode = [&] { const spv::ExecutionMode executionMode = [&] {
switch (ins.controls.tessPartitioning) { switch (ins.controls.tessPartitioning()) {
case DxbcTessPartitioning::Pow2: case DxbcTessPartitioning::Pow2:
case DxbcTessPartitioning::Integer: return spv::ExecutionModeSpacingEqual; case DxbcTessPartitioning::Integer: return spv::ExecutionModeSpacingEqual;
case DxbcTessPartitioning::FractOdd: return spv::ExecutionModeSpacingFractionalOdd; case DxbcTessPartitioning::FractOdd: return spv::ExecutionModeSpacingFractionalOdd;
@ -1193,7 +1193,7 @@ namespace dxvk {
void DxbcCompiler::emitDclTessOutputPrimitive(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitDclTessOutputPrimitive(const DxbcShaderInstruction& ins) {
switch (ins.controls.tessOutputPrimitive) { switch (ins.controls.tessOutputPrimitive()) {
case DxbcTessOutputPrimitive::Point: case DxbcTessOutputPrimitive::Point:
m_module.setExecutionMode(m_entryPointId, spv::ExecutionModePointMode); m_module.setExecutionMode(m_entryPointId, spv::ExecutionModePointMode);
break; break;
@ -2184,7 +2184,7 @@ namespace dxvk {
void DxbcCompiler::emitBarrier(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitBarrier(const DxbcShaderInstruction& ins) {
// sync takes no operands. Instead, the synchronization // sync takes no operands. Instead, the synchronization
// scope is defined by the operand control bits. // scope is defined by the operand control bits.
const DxbcSyncFlags flags = ins.controls.syncFlags; const DxbcSyncFlags flags = ins.controls.syncFlags();
uint32_t executionScope = spv::ScopeInvocation; uint32_t executionScope = spv::ScopeInvocation;
uint32_t memoryScope = spv::ScopeInvocation; uint32_t memoryScope = spv::ScopeInvocation;
@ -2572,7 +2572,7 @@ namespace dxvk {
// (src1) Resource to query // (src1) Resource to query
// TODO Check if resource is bound // TODO Check if resource is bound
const DxbcBufferInfo resourceInfo = getBufferInfo(ins.src[1]); const DxbcBufferInfo resourceInfo = getBufferInfo(ins.src[1]);
const DxbcResinfoType resinfoType = ins.controls.resinfoType; const DxbcResinfoType resinfoType = ins.controls.resinfoType();
// Read the exact LOD for the image query // Read the exact LOD for the image query
const DxbcRegisterValue mipLod = emitRegisterLoad( const DxbcRegisterValue mipLod = emitRegisterLoad(
@ -2709,7 +2709,7 @@ namespace dxvk {
// TODO Check if resource is bound // TODO Check if resource is bound
DxbcRegisterValue sampleCount = emitQueryTextureSamples(ins.src[0]); DxbcRegisterValue sampleCount = emitQueryTextureSamples(ins.src[0]);
if (ins.controls.returnType != DxbcInstructionReturnType::Uint) { if (ins.controls.returnType() != DxbcInstructionReturnType::Uint) {
sampleCount.type = { DxbcScalarType::Float32, 1 }; sampleCount.type = { DxbcScalarType::Float32, 1 };
sampleCount.id = m_module.opConvertUtoF( sampleCount.id = m_module.opConvertUtoF(
getVectorTypeId(sampleCount.type), getVectorTypeId(sampleCount.type),
@ -3250,7 +3250,7 @@ namespace dxvk {
ins.src[0], DxbcRegMask(true, false, false, false)); ins.src[0], DxbcRegMask(true, false, false, false));
const DxbcRegisterValue zeroTest = emitRegisterZeroTest( const DxbcRegisterValue zeroTest = emitRegisterZeroTest(
condition, ins.controls.zeroTest); condition, ins.controls.zeroTest());
// Declare the 'if' block. We do not know if there // Declare the 'if' block. We do not know if there
// will be an 'else' block or not, so we'll assume // will be an 'else' block or not, so we'll assume
@ -3508,7 +3508,7 @@ namespace dxvk {
ins.src[0], DxbcRegMask(true, false, false, false)); ins.src[0], DxbcRegMask(true, false, false, false));
const DxbcRegisterValue zeroTest = emitRegisterZeroTest( const DxbcRegisterValue zeroTest = emitRegisterZeroTest(
condition, ins.controls.zeroTest); condition, ins.controls.zeroTest());
// We basically have to wrap this into an 'if' block // We basically have to wrap this into an 'if' block
const uint32_t breakBlock = m_module.allocateId(); const uint32_t breakBlock = m_module.allocateId();
@ -3551,7 +3551,7 @@ namespace dxvk {
ins.src[0], DxbcRegMask(true, false, false, false)); ins.src[0], DxbcRegMask(true, false, false, false));
const DxbcRegisterValue zeroTest = emitRegisterZeroTest( const DxbcRegisterValue zeroTest = emitRegisterZeroTest(
condition, ins.controls.zeroTest); condition, ins.controls.zeroTest());
// We basically have to wrap this into an 'if' block // We basically have to wrap this into an 'if' block
const uint32_t returnLabel = m_module.allocateId(); const uint32_t returnLabel = m_module.allocateId();
@ -3578,7 +3578,7 @@ namespace dxvk {
ins.src[0], DxbcRegMask(true, false, false, false)); ins.src[0], DxbcRegMask(true, false, false, false));
const DxbcRegisterValue zeroTest = emitRegisterZeroTest( const DxbcRegisterValue zeroTest = emitRegisterZeroTest(
condition, ins.controls.zeroTest); condition, ins.controls.zeroTest());
// Insert a Pseudo-'If' block // Insert a Pseudo-'If' block
const uint32_t discardBlock = m_module.allocateId(); const uint32_t discardBlock = m_module.allocateId();

View File

@ -107,37 +107,7 @@ namespace dxvk {
// Opcode controls. It will depend on the // Opcode controls. It will depend on the
// opcode itself which ones are valid. // opcode itself which ones are valid.
// TODO refactor this nonsense m_instruction.controls = DxbcShaderOpcodeControls(token);
m_instruction.controls.returnType =
static_cast<DxbcInstructionReturnType>(bit::extract(token, 11, 11));
m_instruction.controls.globalFlags =
static_cast<DxbcGlobalFlag>(bit::extract(token, 11, 14));
m_instruction.controls.zeroTest =
static_cast<DxbcZeroTest>(bit::extract(token, 18, 18));
m_instruction.controls.syncFlags =
static_cast<DxbcSyncFlags>(bit::extract(token, 11, 14));
m_instruction.controls.resourceDim =
static_cast<DxbcResourceDim>(bit::extract(token, 11, 15));
m_instruction.controls.resinfoType =
static_cast<DxbcResinfoType>(bit::extract(token, 11, 12));
m_instruction.controls.interpolation =
static_cast<DxbcInterpolationMode>(bit::extract(token, 11, 14));
m_instruction.controls.samplerMode =
static_cast<DxbcSamplerMode>(bit::extract(token, 11, 14));
m_instruction.controls.primitiveTopology =
static_cast<DxbcPrimitiveTopology>(bit::extract(token, 11, 17));
m_instruction.controls.primitive =
static_cast<DxbcPrimitive>(bit::extract(token, 11, 16));
m_instruction.controls.tessDomain =
static_cast<DxbcTessDomain>(bit::extract(token, 11, 12));
m_instruction.controls.tessOutputPrimitive =
static_cast<DxbcTessOutputPrimitive>(bit::extract(token, 11, 13));
m_instruction.controls.tessPartitioning =
static_cast<DxbcTessPartitioning>(bit::extract(token, 11, 13));
m_instruction.controls.uavFlags =
static_cast<uint32_t>(bit::extract(token, 16, 16));
m_instruction.controls.controlPointCount =
static_cast<uint32_t>(bit::extract(token, 11, 16));
// Process extended opcode tokens // Process extended opcode tokens
while (bit::extract(token, 31, 31)) { while (bit::extract(token, 31, 31)) {

View File

@ -239,22 +239,80 @@ namespace dxvk {
* Instruction-specific controls. Usually, * Instruction-specific controls. Usually,
* only one of the members will be valid. * only one of the members will be valid.
*/ */
struct DxbcShaderOpcodeControls { class DxbcShaderOpcodeControls {
DxbcInstructionReturnType returnType;
DxbcGlobalFlags globalFlags; public:
DxbcZeroTest zeroTest;
DxbcSyncFlags syncFlags; DxbcShaderOpcodeControls()
DxbcResourceDim resourceDim; : m_bits(0) { }
DxbcResinfoType resinfoType;
DxbcInterpolationMode interpolation; DxbcShaderOpcodeControls(uint32_t bits)
DxbcSamplerMode samplerMode; : m_bits(bits) { }
DxbcPrimitiveTopology primitiveTopology;
DxbcPrimitive primitive; DxbcInstructionReturnType returnType() const {
DxbcTessDomain tessDomain; return DxbcInstructionReturnType(bit::extract(m_bits, 11, 11));
DxbcTessOutputPrimitive tessOutputPrimitive; }
DxbcTessPartitioning tessPartitioning;
DxbcUavFlags uavFlags; DxbcGlobalFlags globalFlags() const {
uint32_t controlPointCount; return DxbcGlobalFlags(bit::extract(m_bits, 11, 14));
}
DxbcZeroTest zeroTest() const {
return DxbcZeroTest(bit::extract(m_bits, 18, 18));
}
DxbcSyncFlags syncFlags() const {
return DxbcSyncFlags(bit::extract(m_bits, 11, 14));
}
DxbcResourceDim resourceDim() const {
return DxbcResourceDim(bit::extract(m_bits, 11, 15));
}
DxbcResinfoType resinfoType() const {
return DxbcResinfoType(bit::extract(m_bits, 11, 12));
}
DxbcInterpolationMode interpolation() const {
return DxbcInterpolationMode(bit::extract(m_bits, 11, 14));
}
DxbcSamplerMode samplerMode() const {
return DxbcSamplerMode(bit::extract(m_bits, 11, 14));
}
DxbcPrimitiveTopology primitiveTopology() const {
return DxbcPrimitiveTopology(bit::extract(m_bits, 11, 17));
}
DxbcPrimitive primitive() const {
return DxbcPrimitive(bit::extract(m_bits, 11, 16));
}
DxbcTessDomain tessDomain() const {
return DxbcTessDomain(bit::extract(m_bits, 11, 12));
}
DxbcTessOutputPrimitive tessOutputPrimitive() const {
return DxbcTessOutputPrimitive(bit::extract(m_bits, 11, 13));
}
DxbcTessPartitioning tessPartitioning() const {
return DxbcTessPartitioning(bit::extract(m_bits, 11, 13));
}
DxbcUavFlags uavFlags() const {
return DxbcUavFlags(bit::extract(m_bits, 16, 16));
}
uint32_t controlPointCount() const {
return bit::extract(m_bits, 11, 16);
}
private:
uint32_t m_bits;
}; };