2017-10-16 17:50:09 +02:00
|
|
|
#include "dxbc_compiler.h"
|
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
2017-10-16 19:53:17 +02:00
|
|
|
DxbcCompiler::DxbcCompiler(DxbcProgramVersion version)
|
|
|
|
: m_version(version) {
|
2017-10-26 15:40:39 +02:00
|
|
|
m_entryPointId = m_module.allocateId();
|
2017-10-21 17:58:58 +02:00
|
|
|
|
2017-10-18 09:50:30 +02:00
|
|
|
this->declareCapabilities();
|
|
|
|
this->declareMemoryModel();
|
2017-10-26 16:32:10 +02:00
|
|
|
|
|
|
|
m_typeVoid = m_module.defVoidType();
|
|
|
|
m_typeFunction = m_module.defFunctionType(m_typeVoid, 0, nullptr);
|
|
|
|
|
|
|
|
m_module.functionBegin(m_typeVoid,
|
|
|
|
m_entryPointId, m_typeFunction,
|
|
|
|
spv::FunctionControlMaskNone);
|
2017-10-16 17:50:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DxbcCompiler::~DxbcCompiler() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-10-25 13:49:13 +02:00
|
|
|
bool DxbcCompiler::processInstruction(const DxbcInstruction& ins) {
|
|
|
|
const DxbcOpcodeToken token = ins.token();
|
2017-10-22 23:13:29 +02:00
|
|
|
|
2017-10-25 13:49:13 +02:00
|
|
|
switch (token.opcode()) {
|
2017-10-29 02:35:16 +02:00
|
|
|
case DxbcOpcode::DclGlobalFlags:
|
|
|
|
return this->dclGlobalFlags(token.control());
|
|
|
|
|
|
|
|
case DxbcOpcode::DclInput:
|
|
|
|
return this->dclInput(ins);
|
|
|
|
|
|
|
|
case DxbcOpcode::DclTemps:
|
|
|
|
return this->dclTemps(ins.arg(0));
|
2017-10-26 16:32:10 +02:00
|
|
|
|
2017-10-25 13:49:13 +02:00
|
|
|
case DxbcOpcode::DclThreadGroup: {
|
2017-10-26 15:40:39 +02:00
|
|
|
m_module.setLocalSize(
|
2017-10-25 13:49:13 +02:00
|
|
|
m_entryPointId,
|
2017-10-26 16:32:10 +02:00
|
|
|
ins.arg(0),
|
|
|
|
ins.arg(1),
|
|
|
|
ins.arg(2));
|
2017-10-25 13:49:13 +02:00
|
|
|
} return true;
|
|
|
|
|
|
|
|
default:
|
|
|
|
Logger::err(str::format("DXBC: unhandled instruction: ",
|
|
|
|
static_cast<uint32_t>(token.opcode())));
|
|
|
|
return false;
|
|
|
|
}
|
2017-10-16 17:50:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Rc<DxvkShader> DxbcCompiler::finalize() {
|
2017-10-26 16:32:10 +02:00
|
|
|
m_module.functionEnd();
|
|
|
|
|
2017-10-29 02:35:16 +02:00
|
|
|
m_module.addEntryPoint(m_entryPointId,
|
|
|
|
m_version.executionModel(), "main",
|
|
|
|
m_interfaces.size(),
|
|
|
|
m_interfaces.data());
|
|
|
|
|
2017-10-17 13:02:57 +02:00
|
|
|
return new DxvkShader(m_version.shaderStage(),
|
2017-10-26 15:40:39 +02:00
|
|
|
m_module.compile(), 0, nullptr);
|
2017-10-16 19:53:17 +02:00
|
|
|
}
|
|
|
|
|
2017-10-18 09:50:30 +02:00
|
|
|
|
|
|
|
void DxbcCompiler::declareCapabilities() {
|
2017-10-26 15:40:39 +02:00
|
|
|
m_module.enableCapability(spv::CapabilityShader);
|
2017-10-18 09:50:30 +02:00
|
|
|
|
|
|
|
switch (m_version.type()) {
|
|
|
|
case DxbcProgramType::GeometryShader:
|
2017-10-26 15:40:39 +02:00
|
|
|
m_module.enableCapability(spv::CapabilityGeometry);
|
2017-10-18 09:50:30 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
case DxbcProgramType::HullShader:
|
|
|
|
case DxbcProgramType::DomainShader:
|
2017-10-26 15:40:39 +02:00
|
|
|
m_module.enableCapability(spv::CapabilityTessellation);
|
2017-10-18 09:50:30 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void DxbcCompiler::declareMemoryModel() {
|
2017-10-26 15:40:39 +02:00
|
|
|
m_module.setMemoryModel(
|
2017-10-18 09:50:30 +02:00
|
|
|
spv::AddressingModelLogical,
|
|
|
|
spv::MemoryModelGLSL450);
|
|
|
|
}
|
|
|
|
|
2017-10-29 02:35:16 +02:00
|
|
|
|
|
|
|
bool DxbcCompiler::dclGlobalFlags(DxbcGlobalFlags flags) {
|
|
|
|
if (!flags.test(DxbcGlobalFlag::RefactoringAllowed))
|
|
|
|
m_useRestrictedMath = true;
|
|
|
|
|
|
|
|
if (flags.test(DxbcGlobalFlag::DoublePrecision))
|
|
|
|
m_module.enableCapability(spv::CapabilityFloat64);
|
|
|
|
|
|
|
|
if (flags.test(DxbcGlobalFlag::EarlyFragmentTests))
|
|
|
|
m_module.enableEarlyFragmentTests(m_entryPointId);
|
|
|
|
|
|
|
|
// Raw and structured buffers are supported regardless
|
|
|
|
// of whether the corresponding flag is set or not.
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool DxbcCompiler::dclInput(const DxbcInstruction& ins) {
|
|
|
|
// const DxbcOperand operand = ins.operand(0);
|
|
|
|
// const DxbcOperandToken token = operand.token();
|
|
|
|
|
|
|
|
Logger::err("DXBC: dcl_input: Not implemented yet");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool DxbcCompiler::dclTemps(uint32_t n) {
|
2017-10-26 16:32:10 +02:00
|
|
|
// Temporaries are treated as untyped 4x32-bit vectors.
|
|
|
|
uint32_t u32Type = m_module.defIntType(32, 0);
|
|
|
|
uint32_t regType = m_module.defVectorType(u32Type, 4);
|
|
|
|
uint32_t ptrType = m_module.defPointerType(regType, spv::StorageClassPrivate);
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < n; i++) {
|
|
|
|
DxbcRegTypeR reg;
|
|
|
|
reg.varType = regType;
|
|
|
|
reg.ptrType = ptrType;
|
|
|
|
reg.varId = m_module.newVar(ptrType, spv::StorageClassPrivate);
|
|
|
|
m_rRegs.push_back(reg);
|
|
|
|
|
|
|
|
m_module.setDebugName(reg.varId,
|
|
|
|
str::format("r", i).c_str());
|
|
|
|
}
|
2017-10-29 02:35:16 +02:00
|
|
|
|
|
|
|
return true;
|
2017-10-26 16:32:10 +02:00
|
|
|
}
|
|
|
|
|
2017-10-16 17:50:09 +02:00
|
|
|
}
|