mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +01:00
[dxbc] Basic geometry shader (sm4) support
This commit is contained in:
parent
c44b50ae4d
commit
6cc3ff4ad8
@ -17,7 +17,6 @@ namespace dxvk {
|
|||||||
BytecodeLength);
|
BytecodeLength);
|
||||||
|
|
||||||
DxbcModule module(reader);
|
DxbcModule module(reader);
|
||||||
m_shader = module.compile();
|
|
||||||
|
|
||||||
// If requested by the user, dump both the raw DXBC
|
// If requested by the user, dump both the raw DXBC
|
||||||
// shader and the compiled SPIR-V module to a file.
|
// shader and the compiled SPIR-V module to a file.
|
||||||
@ -31,12 +30,20 @@ namespace dxvk {
|
|||||||
|
|
||||||
reader.store(std::ofstream(str::format(baseName, ".dxbc"),
|
reader.store(std::ofstream(str::format(baseName, ".dxbc"),
|
||||||
std::ios_base::binary | std::ios_base::trunc));
|
std::ios_base::binary | std::ios_base::trunc));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
m_shader = module.compile();
|
||||||
|
|
||||||
|
if (dumpPath.size() != 0) {
|
||||||
|
const std::string baseName = str::format(dumpPath, "/",
|
||||||
|
ConstructFileName(ComputeShaderHash(pShaderBytecode, BytecodeLength),
|
||||||
|
module.version().type()));
|
||||||
|
|
||||||
m_shader->dump(std::ofstream(str::format(baseName, ".spv"),
|
m_shader->dump(std::ofstream(str::format(baseName, ".spv"),
|
||||||
std::ios_base::binary | std::ios_base::trunc));
|
std::ios_base::binary | std::ios_base::trunc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// If requested by the user, replace
|
// If requested by the user, replace
|
||||||
// the shader with another file.
|
// the shader with another file.
|
||||||
const std::string readPath
|
const std::string readPath
|
||||||
|
@ -35,8 +35,9 @@ namespace dxvk {
|
|||||||
// Initialize the shader module with capabilities
|
// Initialize the shader module with capabilities
|
||||||
// etc. Each shader type has its own peculiarities.
|
// etc. Each shader type has its own peculiarities.
|
||||||
switch (m_version.type()) {
|
switch (m_version.type()) {
|
||||||
case DxbcProgramType::VertexShader: this->emitVsInit(); break;
|
case DxbcProgramType::VertexShader: this->emitVsInit(); break;
|
||||||
case DxbcProgramType::PixelShader: this->emitPsInit(); break;
|
case DxbcProgramType::GeometryShader: this->emitGsInit(); break;
|
||||||
|
case DxbcProgramType::PixelShader: this->emitPsInit(); break;
|
||||||
default: throw DxvkError("DxbcCompiler: Unsupported program type");
|
default: throw DxvkError("DxbcCompiler: Unsupported program type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,6 +56,9 @@ namespace dxvk {
|
|||||||
case DxbcInstClass::ControlFlow:
|
case DxbcInstClass::ControlFlow:
|
||||||
return this->emitControlFlow(ins);
|
return this->emitControlFlow(ins);
|
||||||
|
|
||||||
|
case DxbcInstClass::GeometryEmit:
|
||||||
|
return this->emitGeometryEmit(ins);
|
||||||
|
|
||||||
case DxbcInstClass::TextureSample:
|
case DxbcInstClass::TextureSample:
|
||||||
return this->emitSample(ins);
|
return this->emitSample(ins);
|
||||||
|
|
||||||
@ -70,6 +74,9 @@ namespace dxvk {
|
|||||||
case DxbcInstClass::VectorDot:
|
case DxbcInstClass::VectorDot:
|
||||||
return this->emitVectorDot(ins);
|
return this->emitVectorDot(ins);
|
||||||
|
|
||||||
|
case DxbcInstClass::VectorIdiv:
|
||||||
|
return this->emitVectorIdiv(ins);
|
||||||
|
|
||||||
case DxbcInstClass::VectorImul:
|
case DxbcInstClass::VectorImul:
|
||||||
return this->emitVectorImul(ins);
|
return this->emitVectorImul(ins);
|
||||||
|
|
||||||
@ -98,8 +105,9 @@ namespace dxvk {
|
|||||||
// input registers, call various shader functions
|
// input registers, call various shader functions
|
||||||
// and write back the output registers.
|
// and write back the output registers.
|
||||||
switch (m_version.type()) {
|
switch (m_version.type()) {
|
||||||
case DxbcProgramType::VertexShader: this->emitVsFinalize(); break;
|
case DxbcProgramType::VertexShader: this->emitVsFinalize(); break;
|
||||||
case DxbcProgramType::PixelShader: this->emitPsFinalize(); break;
|
case DxbcProgramType::GeometryShader: this->emitGsFinalize(); break;
|
||||||
|
case DxbcProgramType::PixelShader: this->emitPsFinalize(); break;
|
||||||
default: throw DxvkError("DxbcCompiler: Unsupported program type");
|
default: throw DxvkError("DxbcCompiler: Unsupported program type");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -152,6 +160,15 @@ namespace dxvk {
|
|||||||
case DxbcOpcode::DclResource:
|
case DxbcOpcode::DclResource:
|
||||||
return this->emitDclResource(ins);
|
return this->emitDclResource(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::DclGsInputPrimitive:
|
||||||
|
return this->emitDclGsInputPrimitive(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::DclGsOutputPrimitiveTopology:
|
||||||
|
return this->emitDclGsOutputTopology(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::DclMaxOutputVertexCount:
|
||||||
|
return this->emitDclMaxOutputVertexCount(ins);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Logger::warn(
|
Logger::warn(
|
||||||
str::format("DxbcCompiler: Unhandled opcode: ",
|
str::format("DxbcCompiler: Unhandled opcode: ",
|
||||||
@ -175,9 +192,10 @@ namespace dxvk {
|
|||||||
m_rRegs.resize(newCount);
|
m_rRegs.resize(newCount);
|
||||||
|
|
||||||
DxbcRegisterInfo info;
|
DxbcRegisterInfo info;
|
||||||
info.type.ctype = DxbcScalarType::Float32;
|
info.type.ctype = DxbcScalarType::Float32;
|
||||||
info.type.ccount = 4;
|
info.type.ccount = 4;
|
||||||
info.sclass = spv::StorageClassPrivate;
|
info.type.alength = 0;
|
||||||
|
info.sclass = spv::StorageClassPrivate;
|
||||||
|
|
||||||
for (uint32_t i = oldCount; i < newCount; i++) {
|
for (uint32_t i = oldCount; i < newCount; i++) {
|
||||||
const uint32_t varId = this->emitNewVariable(info);
|
const uint32_t varId = this->emitNewVariable(info);
|
||||||
@ -274,21 +292,17 @@ namespace dxvk {
|
|||||||
DxbcRegMask regMask,
|
DxbcRegMask regMask,
|
||||||
DxbcSystemValue sv,
|
DxbcSystemValue sv,
|
||||||
DxbcInterpolationMode im) {
|
DxbcInterpolationMode im) {
|
||||||
if (regDim != 0) {
|
|
||||||
Logger::err("DxbcCompiler: Input arrays not yet supported");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Avoid declaring the same variable multiple times.
|
// Avoid declaring the same variable multiple times.
|
||||||
// This may happen when multiple system values are
|
// This may happen when multiple system values are
|
||||||
// mapped to different parts of the same register.
|
// mapped to different parts of the same register.
|
||||||
if (m_vRegs.at(regIdx) == 0) {
|
if (m_vRegs.at(regIdx) == 0) {
|
||||||
DxbcRegisterInfo info;
|
DxbcRegisterInfo info;
|
||||||
info.type.ctype = DxbcScalarType::Float32;
|
info.type.ctype = DxbcScalarType::Float32;
|
||||||
info.type.ccount = 4;
|
info.type.ccount = 4;
|
||||||
|
info.type.alength = regDim;
|
||||||
info.sclass = spv::StorageClassInput;
|
info.sclass = spv::StorageClassInput;
|
||||||
|
|
||||||
const uint32_t varId = this->emitNewVariable(info);
|
uint32_t varId = this->emitNewVariable(info);
|
||||||
|
|
||||||
m_module.decorateLocation(varId, regIdx);
|
m_module.decorateLocation(varId, regIdx);
|
||||||
m_module.setDebugName(varId, str::format("v", regIdx).c_str());
|
m_module.setDebugName(varId, str::format("v", regIdx).c_str());
|
||||||
@ -327,18 +341,14 @@ namespace dxvk {
|
|||||||
DxbcRegMask regMask,
|
DxbcRegMask regMask,
|
||||||
DxbcSystemValue sv,
|
DxbcSystemValue sv,
|
||||||
DxbcInterpolationMode im) {
|
DxbcInterpolationMode im) {
|
||||||
if (regDim != 0) {
|
|
||||||
Logger::err("DxbcCompiler: Output arrays not yet supported");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Avoid declaring the same variable multiple times.
|
// Avoid declaring the same variable multiple times.
|
||||||
// This may happen when multiple system values are
|
// This may happen when multiple system values are
|
||||||
// mapped to different parts of the same register.
|
// mapped to different parts of the same register.
|
||||||
if (m_oRegs.at(regIdx) == 0) {
|
if (m_oRegs.at(regIdx) == 0) {
|
||||||
DxbcRegisterInfo info;
|
DxbcRegisterInfo info;
|
||||||
info.type.ctype = DxbcScalarType::Float32;
|
info.type.ctype = DxbcScalarType::Float32;
|
||||||
info.type.ccount = 4;
|
info.type.ccount = 4;
|
||||||
|
info.type.alength = regDim;
|
||||||
info.sclass = spv::StorageClassOutput;
|
info.sclass = spv::StorageClassOutput;
|
||||||
|
|
||||||
const uint32_t varId = this->emitNewVariable(info);
|
const uint32_t varId = this->emitNewVariable(info);
|
||||||
@ -555,6 +565,50 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitDclGsInputPrimitive(const DxbcShaderInstruction& ins) {
|
||||||
|
// The input primitive type is stored within in the
|
||||||
|
// control bits of the opcode token. In SPIR-V, we
|
||||||
|
// have to define an execution mode.
|
||||||
|
const spv::ExecutionMode mode = [&] {
|
||||||
|
switch (ins.controls.primitive) {
|
||||||
|
case DxbcPrimitive::Point: return spv::ExecutionModeInputPoints;
|
||||||
|
case DxbcPrimitive::Line: return spv::ExecutionModeInputLines;
|
||||||
|
case DxbcPrimitive::Triangle: return spv::ExecutionModeTriangles;
|
||||||
|
case DxbcPrimitive::LineAdj: return spv::ExecutionModeInputLinesAdjacency;
|
||||||
|
case DxbcPrimitive::TriangleAdj: return spv::ExecutionModeInputTrianglesAdjacency;
|
||||||
|
default: throw DxvkError("DxbcCompiler: Unsupported primitive type");
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
m_module.setExecutionMode(m_entryPointId, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitDclGsOutputTopology(const DxbcShaderInstruction& ins) {
|
||||||
|
// The input primitive topology is stored within in the
|
||||||
|
// control bits of the opcode token. In SPIR-V, we have
|
||||||
|
// to define an execution mode.
|
||||||
|
const spv::ExecutionMode mode = [&] {
|
||||||
|
switch (ins.controls.primitiveTopology) {
|
||||||
|
case DxbcPrimitiveTopology::PointList: return spv::ExecutionModeOutputPoints;
|
||||||
|
case DxbcPrimitiveTopology::LineStrip: return spv::ExecutionModeOutputLineStrip;
|
||||||
|
case DxbcPrimitiveTopology::TriangleStrip: return spv::ExecutionModeOutputTriangleStrip;
|
||||||
|
default: throw DxvkError("DxbcCompiler: Unsupported primitive topology");
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
m_module.setExecutionMode(m_entryPointId, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitDclMaxOutputVertexCount(const DxbcShaderInstruction& ins) {
|
||||||
|
// dcl_max_output_vertex_count has one operand:
|
||||||
|
// (imm0) The maximum number of vertices
|
||||||
|
m_gs.outputVertexCount = ins.imm[0].u32;
|
||||||
|
m_module.setOutputVertices(m_entryPointId, m_gs.outputVertexCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitVectorAlu(const DxbcShaderInstruction& ins) {
|
void DxbcCompiler::emitVectorAlu(const DxbcShaderInstruction& ins) {
|
||||||
std::array<DxbcRegisterValue, DxbcMaxOperandCount> src;
|
std::array<DxbcRegisterValue, DxbcMaxOperandCount> src;
|
||||||
|
|
||||||
@ -824,6 +878,66 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitVectorIdiv(const DxbcShaderInstruction& ins) {
|
||||||
|
// udiv has four operands:
|
||||||
|
// (dst0) Quotient destination register
|
||||||
|
// (dst1) Remainder destination register
|
||||||
|
// (src0) The first vector to compare
|
||||||
|
// (src1) The second vector to compare
|
||||||
|
if (ins.dst[0].type == DxbcOperandType::Null
|
||||||
|
&& ins.dst[1].type == DxbcOperandType::Null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// FIXME support this if applications require it
|
||||||
|
if (ins.dst[0].type != DxbcOperandType::Null
|
||||||
|
&& ins.dst[1].type != DxbcOperandType::Null
|
||||||
|
&& ins.dst[0].mask != ins.dst[1].mask) {
|
||||||
|
Logger::warn("DxbcCompiler: Umul with different destination masks not supported");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load source operands as integers with the
|
||||||
|
// mask of one non-NULL destination operand
|
||||||
|
const DxbcRegMask srcMask =
|
||||||
|
ins.dst[0].type != DxbcOperandType::Null
|
||||||
|
? ins.dst[0].mask
|
||||||
|
: ins.dst[1].mask;
|
||||||
|
|
||||||
|
const std::array<DxbcRegisterValue, 2> src = {
|
||||||
|
emitRegisterLoad(ins.src[0], srcMask),
|
||||||
|
emitRegisterLoad(ins.src[1], srcMask),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Compute results only if the destination
|
||||||
|
// operands are not NULL.
|
||||||
|
if (ins.dst[0].type != DxbcOperandType::Null) {
|
||||||
|
DxbcRegisterValue quotient;
|
||||||
|
quotient.type.ctype = ins.dst[0].dataType;
|
||||||
|
quotient.type.ccount = ins.dst[0].mask.setCount();
|
||||||
|
|
||||||
|
quotient.id = m_module.opUDiv(
|
||||||
|
getVectorTypeId(quotient.type),
|
||||||
|
src.at(0).id, src.at(1).id);
|
||||||
|
|
||||||
|
quotient = emitDstOperandModifiers(quotient, ins.modifiers);
|
||||||
|
emitRegisterStore(ins.dst[0], quotient);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ins.dst[1].type != DxbcOperandType::Null) {
|
||||||
|
DxbcRegisterValue remainder;
|
||||||
|
remainder.type.ctype = ins.dst[1].dataType;
|
||||||
|
remainder.type.ccount = ins.dst[1].mask.setCount();
|
||||||
|
|
||||||
|
remainder.id = m_module.opUMod(
|
||||||
|
getVectorTypeId(remainder.type),
|
||||||
|
src.at(0).id, src.at(1).id);
|
||||||
|
|
||||||
|
remainder = emitDstOperandModifiers(remainder, ins.modifiers);
|
||||||
|
emitRegisterStore(ins.dst[1], remainder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitVectorImul(const DxbcShaderInstruction& ins) {
|
void DxbcCompiler::emitVectorImul(const DxbcShaderInstruction& ins) {
|
||||||
// imul and umul have four operands:
|
// imul and umul have four operands:
|
||||||
// (dst0) High destination register
|
// (dst0) High destination register
|
||||||
@ -835,7 +949,7 @@ namespace dxvk {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// If dst0 is NULL, this instruction behaves just
|
// If dst0 is NULL, this instruction behaves just
|
||||||
// like any other three -operand ALU instruction
|
// like any other three-operand ALU instruction
|
||||||
const std::array<DxbcRegisterValue, 2> src = {
|
const std::array<DxbcRegisterValue, 2> src = {
|
||||||
emitRegisterLoad(ins.src[0], ins.dst[1].mask),
|
emitRegisterLoad(ins.src[0], ins.dst[1].mask),
|
||||||
emitRegisterLoad(ins.src[1], ins.dst[1].mask),
|
emitRegisterLoad(ins.src[1], ins.dst[1].mask),
|
||||||
@ -897,8 +1011,26 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitSample(
|
void DxbcCompiler::emitGeometryEmit(const DxbcShaderInstruction& ins) {
|
||||||
const DxbcShaderInstruction& ins) {
|
switch (ins.op) {
|
||||||
|
case DxbcOpcode::Emit: {
|
||||||
|
emitGsOutputSetup();
|
||||||
|
m_module.opEmitVertex();
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DxbcOpcode::Cut: {
|
||||||
|
m_module.opEndPrimitive();
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Logger::warn(str::format(
|
||||||
|
"DxbcCompiler: Unhandled instruction: ",
|
||||||
|
ins.op));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitSample(const DxbcShaderInstruction& ins) {
|
||||||
// TODO support address offset
|
// TODO support address offset
|
||||||
// TODO support more sample ops
|
// TODO support more sample ops
|
||||||
|
|
||||||
@ -1106,6 +1238,33 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitControlFlowDiscard(const DxbcShaderInstruction& ins) {
|
||||||
|
// Discard actually has an operand that determines
|
||||||
|
// whether or not the fragment should be discarded
|
||||||
|
const DxbcRegisterValue condition = emitRegisterLoad(
|
||||||
|
ins.src[0], DxbcRegMask(true, false, false, false));
|
||||||
|
|
||||||
|
const DxbcRegisterValue zeroTest = emitRegisterZeroTest(
|
||||||
|
condition, ins.controls.zeroTest);
|
||||||
|
|
||||||
|
// Insert a Pseudo-'If' block
|
||||||
|
const uint32_t discardBlock = m_module.allocateId();
|
||||||
|
const uint32_t mergeBlock = m_module.allocateId();
|
||||||
|
|
||||||
|
m_module.opSelectionMerge(mergeBlock,
|
||||||
|
spv::SelectionControlMaskNone);
|
||||||
|
|
||||||
|
m_module.opBranchConditional(
|
||||||
|
zeroTest.id, discardBlock, mergeBlock);
|
||||||
|
|
||||||
|
// OpKill terminates the block
|
||||||
|
m_module.opLabel(discardBlock);
|
||||||
|
m_module.opKill();
|
||||||
|
|
||||||
|
m_module.opLabel(mergeBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitControlFlow(const DxbcShaderInstruction& ins) {
|
void DxbcCompiler::emitControlFlow(const DxbcShaderInstruction& ins) {
|
||||||
switch (ins.op) {
|
switch (ins.op) {
|
||||||
case DxbcOpcode::If:
|
case DxbcOpcode::If:
|
||||||
@ -1128,6 +1287,9 @@ namespace dxvk {
|
|||||||
|
|
||||||
case DxbcOpcode::Ret:
|
case DxbcOpcode::Ret:
|
||||||
return this->emitControlFlowRet(ins);
|
return this->emitControlFlowRet(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::Discard:
|
||||||
|
return this->emitControlFlowDiscard(ins);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Logger::warn(str::format(
|
Logger::warn(str::format(
|
||||||
@ -1368,16 +1530,30 @@ namespace dxvk {
|
|||||||
// stages, the index has two dimensions:
|
// stages, the index has two dimensions:
|
||||||
// (0) vertex index (relative)
|
// (0) vertex index (relative)
|
||||||
// (1) register index (relative)
|
// (1) register index (relative)
|
||||||
if (operand.idxDim != 1)
|
|
||||||
throw DxvkError("DxbcCompiler: 2D index for v# not yet supported");
|
|
||||||
|
|
||||||
// We don't support two-dimensional indices yet
|
|
||||||
const uint32_t registerId = operand.idx[0].offset;
|
|
||||||
|
|
||||||
DxbcRegisterPointer result;
|
DxbcRegisterPointer result;
|
||||||
result.type.ctype = DxbcScalarType::Float32;
|
result.type.ctype = DxbcScalarType::Float32;
|
||||||
result.type.ccount = 4;
|
result.type.ccount = 4;
|
||||||
result.id = m_vRegs.at(registerId);
|
|
||||||
|
if (operand.idxDim == 1) {
|
||||||
|
// TODO add support for relative register index
|
||||||
|
result.id = m_vRegs.at(operand.idx[0].offset);
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
// TODO add support for relative register index
|
||||||
|
const DxbcRegisterValue vertexId = emitIndexLoad(operand.idx[0]);
|
||||||
|
|
||||||
|
DxbcRegisterInfo info;
|
||||||
|
info.type.ctype = result.type.ctype;
|
||||||
|
info.type.ccount = result.type.ccount;
|
||||||
|
info.type.alength = 0;
|
||||||
|
info.sclass = spv::StorageClassInput;
|
||||||
|
|
||||||
|
result.id = m_module.opAccessChain(
|
||||||
|
getPointerTypeId(info),
|
||||||
|
m_vRegs.at(operand.idx[1].offset),
|
||||||
|
1, &vertexId.id);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1415,8 +1591,9 @@ namespace dxvk {
|
|||||||
// (0) register index (immediate)
|
// (0) register index (immediate)
|
||||||
// (1) constant offset (relative)
|
// (1) constant offset (relative)
|
||||||
DxbcRegisterInfo info;
|
DxbcRegisterInfo info;
|
||||||
info.type.ctype = DxbcScalarType::Float32;
|
info.type.ctype = DxbcScalarType::Float32;
|
||||||
info.type.ccount = 4;
|
info.type.ccount = 4;
|
||||||
|
info.type.alength = 0;
|
||||||
info.sclass = spv::StorageClassUniform;
|
info.sclass = spv::StorageClassUniform;
|
||||||
|
|
||||||
const uint32_t regId = operand.idx[0].offset;
|
const uint32_t regId = operand.idx[0].offset;
|
||||||
@ -1429,7 +1606,8 @@ namespace dxvk {
|
|||||||
};
|
};
|
||||||
|
|
||||||
DxbcRegisterPointer result;
|
DxbcRegisterPointer result;
|
||||||
result.type = info.type;
|
result.type.ctype = info.type.ctype;
|
||||||
|
result.type.ccount = info.type.ccount;
|
||||||
result.id = m_module.opAccessChain(ptrTypeId,
|
result.id = m_module.opAccessChain(ptrTypeId,
|
||||||
m_constantBuffers.at(regId).varId,
|
m_constantBuffers.at(regId).varId,
|
||||||
indices.size(), indices.data());
|
indices.size(), indices.data());
|
||||||
@ -1585,6 +1763,11 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitGsInputSetup() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitPsInputSetup() {
|
void DxbcCompiler::emitPsInputSetup() {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1595,21 +1778,61 @@ namespace dxvk {
|
|||||||
switch (svMapping.sv) {
|
switch (svMapping.sv) {
|
||||||
case DxbcSystemValue::Position: {
|
case DxbcSystemValue::Position: {
|
||||||
DxbcRegisterInfo info;
|
DxbcRegisterInfo info;
|
||||||
info.type.ctype = DxbcScalarType::Float32;
|
info.type.ctype = DxbcScalarType::Float32;
|
||||||
info.type.ccount = 4;
|
info.type.ccount = 4;
|
||||||
|
info.type.alength = 0;
|
||||||
info.sclass = spv::StorageClassOutput;
|
info.sclass = spv::StorageClassOutput;
|
||||||
|
|
||||||
const uint32_t ptrTypeId = getPointerTypeId(info);
|
const uint32_t ptrTypeId = getPointerTypeId(info);
|
||||||
const uint32_t memberId = m_module.constu32(PerVertex_Position);
|
const uint32_t memberId = m_module.constu32(PerVertex_Position);
|
||||||
|
|
||||||
DxbcRegisterPointer dstPtr;
|
DxbcRegisterPointer dstPtr;
|
||||||
dstPtr.type = info.type;
|
dstPtr.type.ctype = info.type.ctype;
|
||||||
dstPtr.id = m_module.opAccessChain(
|
dstPtr.type.ccount = info.type.ccount;
|
||||||
|
dstPtr.id = m_module.opAccessChain(
|
||||||
ptrTypeId, m_perVertexOut, 1, &memberId);
|
ptrTypeId, m_perVertexOut, 1, &memberId);
|
||||||
|
|
||||||
DxbcRegisterPointer srcPtr;
|
DxbcRegisterPointer srcPtr;
|
||||||
srcPtr.type = info.type;
|
srcPtr.type.ctype = info.type.ctype;
|
||||||
srcPtr.id = m_oRegs.at(svMapping.regId);
|
srcPtr.type.ccount = info.type.ccount;
|
||||||
|
srcPtr.id = m_oRegs.at(svMapping.regId);
|
||||||
|
|
||||||
|
emitValueStore(dstPtr, emitValueLoad(srcPtr),
|
||||||
|
DxbcRegMask(true, true, true, true));
|
||||||
|
} break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Logger::warn(str::format(
|
||||||
|
"DxbcCompiler: Unhandled vertex sv output: ",
|
||||||
|
svMapping.sv));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitGsOutputSetup() {
|
||||||
|
for (const DxbcSvMapping& svMapping : m_oMappings) {
|
||||||
|
switch (svMapping.sv) {
|
||||||
|
case DxbcSystemValue::Position: {
|
||||||
|
DxbcRegisterInfo info;
|
||||||
|
info.type.ctype = DxbcScalarType::Float32;
|
||||||
|
info.type.ccount = 4;
|
||||||
|
info.type.alength = 0;
|
||||||
|
info.sclass = spv::StorageClassOutput;
|
||||||
|
|
||||||
|
const uint32_t ptrTypeId = getPointerTypeId(info);
|
||||||
|
const uint32_t memberId = m_module.constu32(PerVertex_Position);
|
||||||
|
|
||||||
|
DxbcRegisterPointer dstPtr;
|
||||||
|
dstPtr.type.ctype = info.type.ctype;
|
||||||
|
dstPtr.type.ccount = info.type.ccount;
|
||||||
|
dstPtr.id = m_module.opAccessChain(
|
||||||
|
ptrTypeId, m_perVertexOut, 1, &memberId);
|
||||||
|
|
||||||
|
DxbcRegisterPointer srcPtr;
|
||||||
|
srcPtr.type.ctype = info.type.ctype;
|
||||||
|
srcPtr.type.ccount = info.type.ccount;
|
||||||
|
srcPtr.id = m_oRegs.at(svMapping.regId);
|
||||||
|
|
||||||
emitValueStore(dstPtr, emitValueLoad(srcPtr),
|
emitValueStore(dstPtr, emitValueLoad(srcPtr),
|
||||||
DxbcRegMask(true, true, true, true));
|
DxbcRegMask(true, true, true, true));
|
||||||
@ -1659,9 +1882,41 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitGsInit() {
|
||||||
|
m_module.enableCapability(spv::CapabilityGeometry);
|
||||||
|
m_module.enableCapability(spv::CapabilityClipDistance);
|
||||||
|
m_module.enableCapability(spv::CapabilityCullDistance);
|
||||||
|
|
||||||
|
// Declare the per-vertex output block. Outputs are not
|
||||||
|
// declared as arrays, instead they will be flushed when
|
||||||
|
// calling EmitVertex.
|
||||||
|
const uint32_t perVertexStruct = this->getPerVertexBlockId();
|
||||||
|
const uint32_t perVertexPointer = m_module.defPointerType(
|
||||||
|
perVertexStruct, spv::StorageClassOutput);
|
||||||
|
|
||||||
|
m_perVertexOut = m_module.newVar(
|
||||||
|
perVertexPointer, spv::StorageClassOutput);
|
||||||
|
m_entryPointInterfaces.push_back(m_perVertexOut);
|
||||||
|
m_module.setDebugName(m_perVertexOut, "gs_vertex_out");
|
||||||
|
|
||||||
|
// Main function of the vertex shader
|
||||||
|
m_gs.functionId = m_module.allocateId();
|
||||||
|
m_module.setDebugName(m_gs.functionId, "gs_main");
|
||||||
|
|
||||||
|
m_module.functionBegin(
|
||||||
|
m_module.defVoidType(),
|
||||||
|
m_gs.functionId,
|
||||||
|
m_module.defFunctionType(
|
||||||
|
m_module.defVoidType(), 0, nullptr),
|
||||||
|
spv::FunctionControlMaskNone);
|
||||||
|
m_module.opLabel(m_module.allocateId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitPsInit() {
|
void DxbcCompiler::emitPsInit() {
|
||||||
m_module.enableCapability(spv::CapabilityShader);
|
m_module.enableCapability(spv::CapabilityShader);
|
||||||
m_module.setOriginUpperLeft(m_entryPointId);
|
m_module.setExecutionMode(m_entryPointId,
|
||||||
|
spv::ExecutionModeOriginUpperLeft);
|
||||||
|
|
||||||
// Declare pixel shader outputs. According to the Vulkan
|
// Declare pixel shader outputs. According to the Vulkan
|
||||||
// documentation, they are required to match the type of
|
// documentation, they are required to match the type of
|
||||||
@ -1669,8 +1924,9 @@ namespace dxvk {
|
|||||||
for (auto e = m_osgn->begin(); e != m_osgn->end(); e++) {
|
for (auto e = m_osgn->begin(); e != m_osgn->end(); e++) {
|
||||||
if (e->systemValue == DxbcSystemValue::None) {
|
if (e->systemValue == DxbcSystemValue::None) {
|
||||||
DxbcRegisterInfo info;
|
DxbcRegisterInfo info;
|
||||||
info.type.ctype = e->componentType;
|
info.type.ctype = e->componentType;
|
||||||
info.type.ccount = e->componentMask.setCount();
|
info.type.ccount = e->componentMask.setCount();
|
||||||
|
info.type.alength = 0;
|
||||||
info.sclass = spv::StorageClassOutput;
|
info.sclass = spv::StorageClassOutput;
|
||||||
|
|
||||||
const uint32_t varId = emitNewVariable(info);
|
const uint32_t varId = emitNewVariable(info);
|
||||||
@ -1680,7 +1936,8 @@ namespace dxvk {
|
|||||||
m_entryPointInterfaces.push_back(varId);
|
m_entryPointInterfaces.push_back(varId);
|
||||||
|
|
||||||
m_oRegs.at(e->registerId) = varId;
|
m_oRegs.at(e->registerId) = varId;
|
||||||
m_ps.oTypes.at(e->registerId) = info.type;
|
m_ps.oTypes.at(e->registerId).ctype = info.type.ctype;
|
||||||
|
m_ps.oTypes.at(e->registerId).ccount = info.type.ccount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1707,6 +1964,16 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::emitGsFinalize() {
|
||||||
|
this->emitGsInputSetup();
|
||||||
|
m_module.opFunctionCall(
|
||||||
|
m_module.defVoidType(),
|
||||||
|
m_gs.functionId, 0, nullptr);
|
||||||
|
// No output setup at this point as that was
|
||||||
|
// already done during the EmitVertex step
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitPsFinalize() {
|
void DxbcCompiler::emitPsFinalize() {
|
||||||
this->emitPsInputSetup();
|
this->emitPsInputSetup();
|
||||||
m_module.opFunctionCall(
|
m_module.opFunctionCall(
|
||||||
@ -1758,9 +2025,25 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t DxbcCompiler::getArrayTypeId(const DxbcArrayType& type) {
|
||||||
|
DxbcVectorType vtype;
|
||||||
|
vtype.ctype = type.ctype;
|
||||||
|
vtype.ccount = type.ccount;
|
||||||
|
|
||||||
|
uint32_t typeId = this->getVectorTypeId(vtype);
|
||||||
|
|
||||||
|
if (type.alength != 0) {
|
||||||
|
typeId = m_module.defArrayType(typeId,
|
||||||
|
m_module.constu32(type.alength));
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t DxbcCompiler::getPointerTypeId(const DxbcRegisterInfo& type) {
|
uint32_t DxbcCompiler::getPointerTypeId(const DxbcRegisterInfo& type) {
|
||||||
return m_module.defPointerType(
|
return m_module.defPointerType(
|
||||||
this->getVectorTypeId(type.type),
|
this->getArrayTypeId(type.type),
|
||||||
type.sclass);
|
type.sclass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,15 +26,30 @@ namespace dxvk {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Array type
|
||||||
|
*
|
||||||
|
* Convenience struct that stores a scalar type, a
|
||||||
|
* component count and an array size. An array of
|
||||||
|
* length 0 will be evaluated to a vector type. The
|
||||||
|
* compiler can use this to generate SPIR-V types.
|
||||||
|
*/
|
||||||
|
struct DxbcArrayType {
|
||||||
|
DxbcScalarType ctype;
|
||||||
|
uint32_t ccount;
|
||||||
|
uint32_t alength;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Register info
|
* \brief Register info
|
||||||
*
|
*
|
||||||
* Stores the vector type of a register and
|
* Stores the array type of a register and
|
||||||
* its storage class. The compiler can use
|
* its storage class. The compiler can use
|
||||||
* this to generate SPIR-V pointer types.
|
* this to generate SPIR-V pointer types.
|
||||||
*/
|
*/
|
||||||
struct DxbcRegisterInfo {
|
struct DxbcRegisterInfo {
|
||||||
DxbcVectorType type;
|
DxbcArrayType type;
|
||||||
spv::StorageClass sclass;
|
spv::StorageClass sclass;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -69,7 +84,18 @@ namespace dxvk {
|
|||||||
* \brief Vertex shader-specific structure
|
* \brief Vertex shader-specific structure
|
||||||
*/
|
*/
|
||||||
struct DxbcCompilerVsPart {
|
struct DxbcCompilerVsPart {
|
||||||
uint32_t functionId;
|
uint32_t functionId = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Geometry shader-specific structure
|
||||||
|
*/
|
||||||
|
struct DxbcCompilerGsPart {
|
||||||
|
DxbcPrimitive inputPrimitive = DxbcPrimitive::Undefined;
|
||||||
|
DxbcPrimitiveTopology outputTopology = DxbcPrimitiveTopology::Undefined;
|
||||||
|
uint32_t outputVertexCount = 0;
|
||||||
|
uint32_t functionId = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -77,7 +103,8 @@ namespace dxvk {
|
|||||||
* \brief Pixel shader-specific structure
|
* \brief Pixel shader-specific structure
|
||||||
*/
|
*/
|
||||||
struct DxbcCompilerPsPart {
|
struct DxbcCompilerPsPart {
|
||||||
uint32_t functionId;
|
uint32_t functionId = 0;
|
||||||
|
|
||||||
std::array<DxbcVectorType, DxbcMaxInterfaceRegs> oTypes;
|
std::array<DxbcVectorType, DxbcMaxInterfaceRegs> oTypes;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -205,6 +232,7 @@ namespace dxvk {
|
|||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
// Shader-specific data structures
|
// Shader-specific data structures
|
||||||
DxbcCompilerVsPart m_vs;
|
DxbcCompilerVsPart m_vs;
|
||||||
|
DxbcCompilerGsPart m_gs;
|
||||||
DxbcCompilerPsPart m_ps;
|
DxbcCompilerPsPart m_ps;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
@ -244,6 +272,15 @@ namespace dxvk {
|
|||||||
void emitDclResource(
|
void emitDclResource(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
void emitDclGsInputPrimitive(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
void emitDclGsOutputTopology(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
void emitDclMaxOutputVertexCount(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
// Instruction class handlers
|
// Instruction class handlers
|
||||||
void emitVectorAlu(
|
void emitVectorAlu(
|
||||||
@ -258,12 +295,18 @@ namespace dxvk {
|
|||||||
void emitVectorDot(
|
void emitVectorDot(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
void emitVectorIdiv(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
void emitVectorImul(
|
void emitVectorImul(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
void emitVectorSinCos(
|
void emitVectorSinCos(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
void emitGeometryEmit(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
void emitSample(
|
void emitSample(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
@ -290,6 +333,9 @@ namespace dxvk {
|
|||||||
void emitControlFlowRet(
|
void emitControlFlowRet(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
|
void emitControlFlowDiscard(
|
||||||
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
void emitControlFlow(
|
void emitControlFlow(
|
||||||
const DxbcShaderInstruction& ins);
|
const DxbcShaderInstruction& ins);
|
||||||
|
|
||||||
@ -376,21 +422,25 @@ namespace dxvk {
|
|||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
// Input preparation methods
|
// Input preparation methods
|
||||||
void emitVsInputSetup();
|
void emitVsInputSetup();
|
||||||
|
void emitGsInputSetup();
|
||||||
void emitPsInputSetup();
|
void emitPsInputSetup();
|
||||||
|
|
||||||
//////////////////////////////
|
//////////////////////////////
|
||||||
// Output preparation methods
|
// Output preparation methods
|
||||||
void emitVsOutputSetup();
|
void emitVsOutputSetup();
|
||||||
|
void emitGsOutputSetup();
|
||||||
void emitPsOutputSetup();
|
void emitPsOutputSetup();
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
// Shader initialization methods
|
// Shader initialization methods
|
||||||
void emitVsInit();
|
void emitVsInit();
|
||||||
|
void emitGsInit();
|
||||||
void emitPsInit();
|
void emitPsInit();
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
// Shader finalization methods
|
// Shader finalization methods
|
||||||
void emitVsFinalize();
|
void emitVsFinalize();
|
||||||
|
void emitGsFinalize();
|
||||||
void emitPsFinalize();
|
void emitPsFinalize();
|
||||||
|
|
||||||
///////////////////////////////
|
///////////////////////////////
|
||||||
@ -410,6 +460,9 @@ namespace dxvk {
|
|||||||
uint32_t getVectorTypeId(
|
uint32_t getVectorTypeId(
|
||||||
const DxbcVectorType& type);
|
const DxbcVectorType& type);
|
||||||
|
|
||||||
|
uint32_t getArrayTypeId(
|
||||||
|
const DxbcArrayType& type);
|
||||||
|
|
||||||
uint32_t getPointerTypeId(
|
uint32_t getPointerTypeId(
|
||||||
const DxbcRegisterInfo& type);
|
const DxbcRegisterInfo& type);
|
||||||
|
|
||||||
|
@ -80,11 +80,22 @@ namespace dxvk {
|
|||||||
m_instruction.modifiers.precise = !!bit::extract(token, 19, 22);
|
m_instruction.modifiers.precise = !!bit::extract(token, 19, 22);
|
||||||
|
|
||||||
// Opcode controls. It will depend on the opcode itself which ones are valid.
|
// Opcode controls. It will depend on the opcode itself which ones are valid.
|
||||||
m_instruction.controls.zeroTest = static_cast<DxbcZeroTest> (bit::extract(token, 18, 18));
|
m_instruction.controls.zeroTest =
|
||||||
m_instruction.controls.syncFlags = static_cast<DxbcSyncFlags> (bit::extract(token, 11, 14));
|
static_cast<DxbcZeroTest>(bit::extract(token, 18, 18));
|
||||||
m_instruction.controls.resourceDim = static_cast<DxbcResourceDim> (bit::extract(token, 11, 15));
|
m_instruction.controls.syncFlags =
|
||||||
m_instruction.controls.resinfoType = static_cast<DxbcResinfoType> (bit::extract(token, 11, 12));
|
static_cast<DxbcSyncFlags>(bit::extract(token, 11, 14));
|
||||||
m_instruction.controls.interpolation = static_cast<DxbcInterpolationMode>(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));
|
||||||
|
|
||||||
// Process extended opcode tokens
|
// Process extended opcode tokens
|
||||||
while (bit::extract(token, 31, 31)) {
|
while (bit::extract(token, 31, 31)) {
|
||||||
|
@ -75,15 +75,18 @@ namespace dxvk {
|
|||||||
|
|
||||||
DxbcRegSwizzle() { }
|
DxbcRegSwizzle() { }
|
||||||
DxbcRegSwizzle(uint32_t x, uint32_t y, uint32_t z, uint32_t w)
|
DxbcRegSwizzle(uint32_t x, uint32_t y, uint32_t z, uint32_t w)
|
||||||
: m_data((x << 0) | (y << 2) | (z << 4) | (w << 6)) { }
|
: m_mask((x << 0) | (y << 2) | (z << 4) | (w << 6)) { }
|
||||||
|
|
||||||
uint32_t operator [] (uint32_t id) const {
|
uint32_t operator [] (uint32_t id) const {
|
||||||
return (m_data >> (id + id)) & 0x3;
|
return (m_mask >> (id + id)) & 0x3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator == (const DxbcRegSwizzle& other) const { return m_mask == other.m_mask; }
|
||||||
|
bool operator != (const DxbcRegSwizzle& other) const { return m_mask != other.m_mask; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint8_t m_data = 0;
|
uint8_t m_mask = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -99,30 +102,33 @@ namespace dxvk {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
DxbcRegMask() { }
|
DxbcRegMask() { }
|
||||||
DxbcRegMask(uint32_t mask) : m_data(mask) { }
|
DxbcRegMask(uint32_t mask) : m_mask(mask) { }
|
||||||
DxbcRegMask(bool x, bool y, bool z, bool w)
|
DxbcRegMask(bool x, bool y, bool z, bool w)
|
||||||
: m_data((x ? 0x1 : 0) | (y ? 0x2 : 0)
|
: m_mask((x ? 0x1 : 0) | (y ? 0x2 : 0)
|
||||||
| (z ? 0x4 : 0) | (w ? 0x8 : 0)) { }
|
| (z ? 0x4 : 0) | (w ? 0x8 : 0)) { }
|
||||||
|
|
||||||
bool operator [] (uint32_t id) const {
|
bool operator [] (uint32_t id) const {
|
||||||
return (m_data >> id) & 1;
|
return (m_mask >> id) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t setCount() const {
|
uint32_t setCount() const {
|
||||||
const uint8_t n[16] = { 0, 1, 1, 2, 1, 2, 2, 3,
|
const uint8_t n[16] = { 0, 1, 1, 2, 1, 2, 2, 3,
|
||||||
1, 2, 2, 3, 2, 3, 3, 4 };
|
1, 2, 2, 3, 2, 3, 3, 4 };
|
||||||
return n[m_data & 0xF];
|
return n[m_mask & 0xF];
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t firstSet() const {
|
uint32_t firstSet() const {
|
||||||
const uint8_t n[16] = { 4, 0, 1, 0, 2, 0, 1, 0,
|
const uint8_t n[16] = { 4, 0, 1, 0, 2, 0, 1, 0,
|
||||||
3, 0, 1, 0, 2, 0, 1, 0 };
|
3, 0, 1, 0, 2, 0, 1, 0 };
|
||||||
return n[m_data & 0xF];
|
return n[m_mask & 0xF];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator == (const DxbcRegMask& other) const { return m_mask == other.m_mask; }
|
||||||
|
bool operator != (const DxbcRegMask& other) const { return m_mask != other.m_mask; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint8_t m_data = 0;
|
uint8_t m_mask = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -194,6 +200,9 @@ namespace dxvk {
|
|||||||
DxbcResourceDim resourceDim;
|
DxbcResourceDim resourceDim;
|
||||||
DxbcResinfoType resinfoType;
|
DxbcResinfoType resinfoType;
|
||||||
DxbcInterpolationMode interpolation;
|
DxbcInterpolationMode interpolation;
|
||||||
|
DxbcSamplerMode samplerMode;
|
||||||
|
DxbcPrimitiveTopology primitiveTopology;
|
||||||
|
DxbcPrimitive primitive;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ namespace dxvk {
|
|||||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||||
} },
|
} },
|
||||||
/* Cut */
|
/* Cut */
|
||||||
{ },
|
{ 0, DxbcInstClass::GeometryEmit },
|
||||||
/* Default */
|
/* Default */
|
||||||
{ },
|
{ },
|
||||||
/* DerivRtx */
|
/* DerivRtx */
|
||||||
@ -42,7 +42,9 @@ namespace dxvk {
|
|||||||
/* DerivRty */
|
/* DerivRty */
|
||||||
{ },
|
{ },
|
||||||
/* Discard */
|
/* Discard */
|
||||||
{ },
|
{ 1, DxbcInstClass::ControlFlow, {
|
||||||
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
||||||
|
} },
|
||||||
/* Div */
|
/* Div */
|
||||||
{ 3, DxbcInstClass::VectorAlu, {
|
{ 3, DxbcInstClass::VectorAlu, {
|
||||||
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
|
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
|
||||||
@ -70,7 +72,7 @@ namespace dxvk {
|
|||||||
/* Else */
|
/* Else */
|
||||||
{ 0, DxbcInstClass::ControlFlow },
|
{ 0, DxbcInstClass::ControlFlow },
|
||||||
/* Emit */
|
/* Emit */
|
||||||
{ },
|
{ 0, DxbcInstClass::GeometryEmit },
|
||||||
/* EmitThenCut */
|
/* EmitThenCut */
|
||||||
{ },
|
{ },
|
||||||
/* EndIf */
|
/* EndIf */
|
||||||
@ -295,13 +297,23 @@ namespace dxvk {
|
|||||||
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
||||||
} },
|
} },
|
||||||
/* UDiv */
|
/* UDiv */
|
||||||
{ },
|
{ 4, DxbcInstClass::VectorIdiv, {
|
||||||
|
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },
|
||||||
|
{ DxbcOperandKind::DstReg, DxbcScalarType::Uint32 },
|
||||||
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||||
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Uint32 },
|
||||||
|
} },
|
||||||
/* ULt */
|
/* ULt */
|
||||||
{ },
|
{ },
|
||||||
/* UGe */
|
/* UGe */
|
||||||
{ },
|
{ },
|
||||||
/* UMul */
|
/* UMul */
|
||||||
{ },
|
{ 4, DxbcInstClass::VectorImul, {
|
||||||
|
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
|
||||||
|
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
|
||||||
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
||||||
|
{ DxbcOperandKind::SrcReg, DxbcScalarType::Float32 },
|
||||||
|
} },
|
||||||
/* UMad */
|
/* UMad */
|
||||||
{ },
|
{ },
|
||||||
/* UMax */
|
/* UMax */
|
||||||
@ -330,11 +342,13 @@ namespace dxvk {
|
|||||||
/* DclIndexRange */
|
/* DclIndexRange */
|
||||||
{ },
|
{ },
|
||||||
/* DclGsOutputPrimitiveTopology */
|
/* DclGsOutputPrimitiveTopology */
|
||||||
{ },
|
{ 0, DxbcInstClass::Declaration },
|
||||||
/* DclGsInputPrimitive */
|
/* DclGsInputPrimitive */
|
||||||
{ },
|
{ 0, DxbcInstClass::Declaration },
|
||||||
/* DclMaxOutputVertexCount */
|
/* DclMaxOutputVertexCount */
|
||||||
{ },
|
{ 1, DxbcInstClass::Declaration, {
|
||||||
|
{ DxbcOperandKind::Imm32, DxbcScalarType::Uint32 },
|
||||||
|
} },
|
||||||
/* DclInput */
|
/* DclInput */
|
||||||
{ 1, DxbcInstClass::Declaration, {
|
{ 1, DxbcInstClass::Declaration, {
|
||||||
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
|
{ DxbcOperandKind::DstReg, DxbcScalarType::Float32 },
|
||||||
|
@ -30,11 +30,13 @@ namespace dxvk {
|
|||||||
enum class DxbcInstClass {
|
enum class DxbcInstClass {
|
||||||
Declaration, ///< Interface or resource declaration
|
Declaration, ///< Interface or resource declaration
|
||||||
ControlFlow, ///< Control flow instructions
|
ControlFlow, ///< Control flow instructions
|
||||||
|
GeometryEmit, ///< Special geometry shader instructions
|
||||||
TextureSample, ///< Texture sampling instruction
|
TextureSample, ///< Texture sampling instruction
|
||||||
VectorAlu, ///< Component-wise vector instructions
|
VectorAlu, ///< Component-wise vector instructions
|
||||||
VectorCmov, ///< Component-wise conditional move
|
VectorCmov, ///< Component-wise conditional move
|
||||||
VectorCmp, ///< Component-wise vector comparison
|
VectorCmp, ///< Component-wise vector comparison
|
||||||
VectorDot, ///< Dot product instruction
|
VectorDot, ///< Dot product instruction
|
||||||
|
VectorIdiv, ///< Component-wise integer division
|
||||||
VectorImul, ///< Component-wise integer multiplication
|
VectorImul, ///< Component-wise integer multiplication
|
||||||
VectorSinCos, ///< Sine and Cosine instruction
|
VectorSinCos, ///< Sine and Cosine instruction
|
||||||
Undefined, ///< Instruction code not defined
|
Undefined, ///< Instruction code not defined
|
||||||
|
@ -456,6 +456,79 @@ namespace dxvk {
|
|||||||
|
|
||||||
using DxbcSyncFlags = Flags<DxbcSyncFlag>;
|
using DxbcSyncFlags = Flags<DxbcSyncFlag>;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Geometry shader input primitive
|
||||||
|
*/
|
||||||
|
enum class DxbcPrimitive : uint32_t {
|
||||||
|
Undefined = 0,
|
||||||
|
Point = 1,
|
||||||
|
Line = 2,
|
||||||
|
Triangle = 3,
|
||||||
|
LineAdj = 6,
|
||||||
|
TriangleAdj = 7,
|
||||||
|
Patch1 = 8,
|
||||||
|
Patch2 = 9,
|
||||||
|
Patch3 = 10,
|
||||||
|
Patch4 = 11,
|
||||||
|
Patch5 = 12,
|
||||||
|
Patch6 = 13,
|
||||||
|
Patch7 = 14,
|
||||||
|
Patch8 = 15,
|
||||||
|
Patch9 = 16,
|
||||||
|
Patch10 = 17,
|
||||||
|
Patch11 = 18,
|
||||||
|
Patch12 = 19,
|
||||||
|
Patch13 = 20,
|
||||||
|
Patch14 = 21,
|
||||||
|
Patch15 = 22,
|
||||||
|
Patch16 = 23,
|
||||||
|
Patch17 = 24,
|
||||||
|
Patch18 = 25,
|
||||||
|
Patch19 = 26,
|
||||||
|
Patch20 = 27,
|
||||||
|
Patch21 = 28,
|
||||||
|
Patch22 = 29,
|
||||||
|
Patch23 = 30,
|
||||||
|
Patch24 = 31,
|
||||||
|
Patch25 = 32,
|
||||||
|
Patch26 = 33,
|
||||||
|
Patch27 = 34,
|
||||||
|
Patch28 = 35,
|
||||||
|
Patch29 = 36,
|
||||||
|
Patch30 = 37,
|
||||||
|
Patch31 = 38,
|
||||||
|
Patch32 = 39,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Geometry shader output topology
|
||||||
|
*/
|
||||||
|
enum class DxbcPrimitiveTopology : uint32_t {
|
||||||
|
Undefined = 0,
|
||||||
|
PointList = 1,
|
||||||
|
LineList = 2,
|
||||||
|
LineStrip = 3,
|
||||||
|
TriangleList = 4,
|
||||||
|
TriangleStrip = 5,
|
||||||
|
LineListAdj = 10,
|
||||||
|
LineStripAdj = 11,
|
||||||
|
TriangleListAdj = 12,
|
||||||
|
TriangleStripAdj = 13,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Sampler operation mode
|
||||||
|
*/
|
||||||
|
enum class DxbcSamplerMode : uint32_t {
|
||||||
|
Default = 0,
|
||||||
|
Comparison = 1,
|
||||||
|
Mono = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Scalar value type
|
* \brief Scalar value type
|
||||||
*
|
*
|
||||||
|
@ -41,4 +41,25 @@ namespace dxvk {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t primitiveVertexCount(DxbcPrimitive primitive) {
|
||||||
|
static const std::array<uint32_t, 8> s_vertexCounts = {
|
||||||
|
0, // Undefined
|
||||||
|
1, // Point
|
||||||
|
2, // Line
|
||||||
|
3, // Triangle
|
||||||
|
0, // Undefined
|
||||||
|
0, // Undefined
|
||||||
|
4, // Line with adjacency
|
||||||
|
6, // Triangle with adjacency
|
||||||
|
};
|
||||||
|
|
||||||
|
if (primitive >= DxbcPrimitive::Patch1) {
|
||||||
|
return static_cast<uint32_t>(primitive)
|
||||||
|
- static_cast<uint32_t>(DxbcPrimitive::Patch1);
|
||||||
|
} else {
|
||||||
|
return s_vertexCounts.at(
|
||||||
|
static_cast<uint32_t>(primitive));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "dxbc_common.h"
|
#include "dxbc_common.h"
|
||||||
|
#include "dxbc_enums.h"
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
@ -32,4 +33,13 @@ namespace dxvk {
|
|||||||
DxbcBindingType bindingType,
|
DxbcBindingType bindingType,
|
||||||
uint32_t bindingIndex);
|
uint32_t bindingIndex);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Primitive vertex count
|
||||||
|
*
|
||||||
|
* Calculates the number of vertices
|
||||||
|
* for a given primitive type.
|
||||||
|
*/
|
||||||
|
uint32_t primitiveVertexCount(
|
||||||
|
DxbcPrimitive primitive);
|
||||||
|
|
||||||
}
|
}
|
@ -72,12 +72,13 @@ namespace dxvk {
|
|||||||
m_memoryModel.putWord (memoryModel);
|
m_memoryModel.putWord (memoryModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SpirvModule::enableEarlyFragmentTests(
|
void SpirvModule::setExecutionMode(
|
||||||
uint32_t entryPointId) {
|
uint32_t entryPointId,
|
||||||
|
spv::ExecutionMode executionMode) {
|
||||||
m_execModeInfo.putIns (spv::OpExecutionMode, 3);
|
m_execModeInfo.putIns (spv::OpExecutionMode, 3);
|
||||||
m_execModeInfo.putWord(entryPointId);
|
m_execModeInfo.putWord(entryPointId);
|
||||||
m_execModeInfo.putWord(spv::ExecutionModeEarlyFragmentTests);
|
m_execModeInfo.putWord(executionMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -95,11 +96,13 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SpirvModule::setOriginUpperLeft(
|
void SpirvModule::setOutputVertices(
|
||||||
uint32_t entryPointId) {
|
uint32_t entryPointId,
|
||||||
m_execModeInfo.putIns (spv::OpExecutionMode, 3);
|
uint32_t vertexCount) {
|
||||||
|
m_execModeInfo.putIns (spv::OpExecutionMode, 4);
|
||||||
m_execModeInfo.putWord(entryPointId);
|
m_execModeInfo.putWord(entryPointId);
|
||||||
m_execModeInfo.putWord(spv::ExecutionModeOriginUpperLeft);
|
m_execModeInfo.putWord(spv::ExecutionModeOutputVertices);
|
||||||
|
m_execModeInfo.putWord(vertexCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -738,6 +741,66 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::opSDiv(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t a,
|
||||||
|
uint32_t b) {
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_code.putIns (spv::OpSDiv, 5);
|
||||||
|
m_code.putWord(resultType);
|
||||||
|
m_code.putWord(resultId);
|
||||||
|
m_code.putWord(a);
|
||||||
|
m_code.putWord(b);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::opUDiv(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t a,
|
||||||
|
uint32_t b) {
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_code.putIns (spv::OpUDiv, 5);
|
||||||
|
m_code.putWord(resultType);
|
||||||
|
m_code.putWord(resultId);
|
||||||
|
m_code.putWord(a);
|
||||||
|
m_code.putWord(b);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::opSRem(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t a,
|
||||||
|
uint32_t b) {
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_code.putIns (spv::OpSRem, 5);
|
||||||
|
m_code.putWord(resultType);
|
||||||
|
m_code.putWord(resultId);
|
||||||
|
m_code.putWord(a);
|
||||||
|
m_code.putWord(b);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t SpirvModule::opUMod(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t a,
|
||||||
|
uint32_t b) {
|
||||||
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
|
m_code.putIns (spv::OpUMod, 5);
|
||||||
|
m_code.putWord(resultType);
|
||||||
|
m_code.putWord(resultId);
|
||||||
|
m_code.putWord(a);
|
||||||
|
m_code.putWord(b);
|
||||||
|
return resultId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvModule::opFDiv(
|
uint32_t SpirvModule::opFDiv(
|
||||||
uint32_t resultType,
|
uint32_t resultType,
|
||||||
uint32_t a,
|
uint32_t a,
|
||||||
@ -1310,6 +1373,21 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::opKill() {
|
||||||
|
m_code.putIns (spv::OpKill, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::opEmitVertex() {
|
||||||
|
m_code.putIns (spv::OpEmitVertex, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::opEndPrimitive() {
|
||||||
|
m_code.putIns (spv::OpEndPrimitive, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvModule::defType(
|
uint32_t SpirvModule::defType(
|
||||||
spv::Op op,
|
spv::Op op,
|
||||||
uint32_t argCount,
|
uint32_t argCount,
|
||||||
|
@ -37,8 +37,9 @@ namespace dxvk {
|
|||||||
spv::AddressingModel addressModel,
|
spv::AddressingModel addressModel,
|
||||||
spv::MemoryModel memoryModel);
|
spv::MemoryModel memoryModel);
|
||||||
|
|
||||||
void enableEarlyFragmentTests(
|
void setExecutionMode(
|
||||||
uint32_t entryPointId);
|
uint32_t entryPointId,
|
||||||
|
spv::ExecutionMode executionMode);
|
||||||
|
|
||||||
void setLocalSize(
|
void setLocalSize(
|
||||||
uint32_t entryPointId,
|
uint32_t entryPointId,
|
||||||
@ -46,8 +47,9 @@ namespace dxvk {
|
|||||||
uint32_t y,
|
uint32_t y,
|
||||||
uint32_t z);
|
uint32_t z);
|
||||||
|
|
||||||
void setOriginUpperLeft(
|
void setOutputVertices(
|
||||||
uint32_t entryPointId);
|
uint32_t entryPointId,
|
||||||
|
uint32_t vertexCount);
|
||||||
|
|
||||||
void setDebugName(
|
void setDebugName(
|
||||||
uint32_t expressionId,
|
uint32_t expressionId,
|
||||||
@ -265,6 +267,26 @@ namespace dxvk {
|
|||||||
uint32_t a,
|
uint32_t a,
|
||||||
uint32_t b);
|
uint32_t b);
|
||||||
|
|
||||||
|
uint32_t opSDiv(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t a,
|
||||||
|
uint32_t b);
|
||||||
|
|
||||||
|
uint32_t opUDiv(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t a,
|
||||||
|
uint32_t b);
|
||||||
|
|
||||||
|
uint32_t opSRem(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t a,
|
||||||
|
uint32_t b);
|
||||||
|
|
||||||
|
uint32_t opUMod(
|
||||||
|
uint32_t resultType,
|
||||||
|
uint32_t a,
|
||||||
|
uint32_t b);
|
||||||
|
|
||||||
uint32_t opFDiv(
|
uint32_t opFDiv(
|
||||||
uint32_t resultType,
|
uint32_t resultType,
|
||||||
uint32_t a,
|
uint32_t a,
|
||||||
@ -453,6 +475,12 @@ namespace dxvk {
|
|||||||
|
|
||||||
void opReturn();
|
void opReturn();
|
||||||
|
|
||||||
|
void opKill();
|
||||||
|
|
||||||
|
void opEmitVertex();
|
||||||
|
|
||||||
|
void opEndPrimitive();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
uint32_t m_id = 1;
|
uint32_t m_id = 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user