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:
parent
5cb65a6c19
commit
1fb22a6022
@ -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();
|
||||
|
@ -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)) {
|
||||
|
@ -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;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user