1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-18 13:54:16 +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) {
const DxbcGlobalFlags flags = ins.controls.globalFlags;
const DxbcGlobalFlags flags = ins.controls.globalFlags();
if (flags.test(DxbcGlobalFlag::EarlyFragmentTests))
m_module.setExecutionMode(m_entryPointId, spv::ExecutionModeEarlyFragmentTests);
@ -387,7 +387,7 @@ namespace dxvk {
DxbcInterpolationMode im = DxbcInterpolationMode::Undefined;
if (hasInterpolationMode)
im = ins.controls.interpolation;
im = ins.controls.interpolation();
// Declare the actual input/output variable
switch (ins.op) {
@ -766,7 +766,7 @@ namespace dxvk {
}
// 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
// to define four different types whereas SPIR-V only allows
@ -871,7 +871,7 @@ namespace dxvk {
m_module.decorateDescriptorSet(varId, 0);
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);
// Declare a specialization constant which will
@ -992,7 +992,7 @@ namespace dxvk {
m_module.decorateDescriptorSet(varId, 0);
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);
// Declare a specialization constant which will
@ -1083,7 +1083,7 @@ namespace dxvk {
// control bits of the opcode token. In SPIR-V, we
// have to define an execution mode.
const spv::ExecutionMode mode = [&] {
switch (ins.controls.primitive) {
switch (ins.controls.primitive()) {
case DxbcPrimitive::Point: return spv::ExecutionModeInputPoints;
case DxbcPrimitive::Line: return spv::ExecutionModeInputLines;
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);
const uint32_t vertexCount
@ -1109,7 +1109,7 @@ namespace dxvk {
// control bits of the opcode token. In SPIR-V, we have
// to define an execution mode.
const spv::ExecutionMode mode = [&] {
switch (ins.controls.primitiveTopology) {
switch (ins.controls.primitiveTopology()) {
case DxbcPrimitiveTopology::PointList: return spv::ExecutionModeOutputPoints;
case DxbcPrimitiveTopology::LineStrip: return spv::ExecutionModeOutputLineStrip;
case DxbcPrimitiveTopology::TriangleStrip: return spv::ExecutionModeOutputTriangleStrip;
@ -1134,11 +1134,11 @@ namespace dxvk {
// dcl_input_control_points has the control point
// count embedded within the opcode token.
if (m_version.type() == DxbcProgramType::HullShader) {
m_hs.vertexCountIn = ins.controls.controlPointCount;
m_hs.vertexCountIn = ins.controls.controlPointCount();
emitDclInputArray(m_hs.vertexCountIn);
} else {
m_ds.vertexCountIn = ins.controls.controlPointCount;
m_ds.vertexCountIn = ins.controls.controlPointCount();
m_ds.inputPerPatch = emitTessInterfacePerPatch (spv::StorageClassInput);
m_ds.inputPerVertex = emitTessInterfacePerVertex(spv::StorageClassInput, m_ds.vertexCountIn);
@ -1149,12 +1149,12 @@ namespace dxvk {
void DxbcCompiler::emitDclOutputControlPointCount(const DxbcShaderInstruction& ins) {
// dcl_output_control_points has the control point
// 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.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) {
const spv::ExecutionMode executionMode = [&] {
switch (ins.controls.tessDomain) {
switch (ins.controls.tessDomain()) {
case DxbcTessDomain::Isolines: return spv::ExecutionModeIsolines;
case DxbcTessDomain::Triangles: return spv::ExecutionModeTriangles;
case DxbcTessDomain::Quads: return spv::ExecutionModeQuads;
@ -1179,7 +1179,7 @@ namespace dxvk {
void DxbcCompiler::emitDclTessPartitioning(const DxbcShaderInstruction& ins) {
const spv::ExecutionMode executionMode = [&] {
switch (ins.controls.tessPartitioning) {
switch (ins.controls.tessPartitioning()) {
case DxbcTessPartitioning::Pow2:
case DxbcTessPartitioning::Integer: return spv::ExecutionModeSpacingEqual;
case DxbcTessPartitioning::FractOdd: return spv::ExecutionModeSpacingFractionalOdd;
@ -1193,7 +1193,7 @@ namespace dxvk {
void DxbcCompiler::emitDclTessOutputPrimitive(const DxbcShaderInstruction& ins) {
switch (ins.controls.tessOutputPrimitive) {
switch (ins.controls.tessOutputPrimitive()) {
case DxbcTessOutputPrimitive::Point:
m_module.setExecutionMode(m_entryPointId, spv::ExecutionModePointMode);
break;
@ -2184,7 +2184,7 @@ namespace dxvk {
void DxbcCompiler::emitBarrier(const DxbcShaderInstruction& ins) {
// sync takes no operands. Instead, the synchronization
// 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 memoryScope = spv::ScopeInvocation;
@ -2572,7 +2572,7 @@ namespace dxvk {
// (src1) Resource to query
// TODO Check if resource is bound
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
const DxbcRegisterValue mipLod = emitRegisterLoad(
@ -2709,7 +2709,7 @@ namespace dxvk {
// TODO Check if resource is bound
DxbcRegisterValue sampleCount = emitQueryTextureSamples(ins.src[0]);
if (ins.controls.returnType != DxbcInstructionReturnType::Uint) {
if (ins.controls.returnType() != DxbcInstructionReturnType::Uint) {
sampleCount.type = { DxbcScalarType::Float32, 1 };
sampleCount.id = m_module.opConvertUtoF(
getVectorTypeId(sampleCount.type),
@ -3250,7 +3250,7 @@ namespace dxvk {
ins.src[0], DxbcRegMask(true, false, false, false));
const DxbcRegisterValue zeroTest = emitRegisterZeroTest(
condition, ins.controls.zeroTest);
condition, ins.controls.zeroTest());
// Declare the 'if' block. We do not know if there
// 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));
const DxbcRegisterValue zeroTest = emitRegisterZeroTest(
condition, ins.controls.zeroTest);
condition, ins.controls.zeroTest());
// We basically have to wrap this into an 'if' block
const uint32_t breakBlock = m_module.allocateId();
@ -3551,7 +3551,7 @@ namespace dxvk {
ins.src[0], DxbcRegMask(true, false, false, false));
const DxbcRegisterValue zeroTest = emitRegisterZeroTest(
condition, ins.controls.zeroTest);
condition, ins.controls.zeroTest());
// We basically have to wrap this into an 'if' block
const uint32_t returnLabel = m_module.allocateId();
@ -3578,7 +3578,7 @@ namespace dxvk {
ins.src[0], DxbcRegMask(true, false, false, false));
const DxbcRegisterValue zeroTest = emitRegisterZeroTest(
condition, ins.controls.zeroTest);
condition, ins.controls.zeroTest());
// Insert a Pseudo-'If' block
const uint32_t discardBlock = m_module.allocateId();

View File

@ -107,37 +107,7 @@ namespace dxvk {
// Opcode controls. It will depend on the
// opcode itself which ones are valid.
// TODO refactor this nonsense
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));
m_instruction.controls = DxbcShaderOpcodeControls(token);
// Process extended opcode tokens
while (bit::extract(token, 31, 31)) {

View File

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