1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-11-29 10:24:10 +01:00

[dxbc] Removed most of the DXBC compiler again

This commit is contained in:
Philip Rebohle 2017-11-07 15:10:38 +01:00
parent 9cdc341946
commit 4052951542
15 changed files with 236 additions and 381 deletions

View File

@ -29,14 +29,4 @@ namespace dxvk {
}
uint32_t DxbcIsgn::entryCount() const {
return m_entries.size();
}
const DxbcSgnEntry& DxbcIsgn::entry(uint32_t id) const {
return m_entries.at(id);
}
}

View File

@ -36,9 +36,8 @@ namespace dxvk {
DxbcIsgn(DxbcReader reader);
~DxbcIsgn();
uint32_t entryCount() const;
const DxbcSgnEntry& entry(uint32_t id) const;
auto begin() const { return m_entries.cbegin(); }
auto end () const { return m_entries.cend(); }
private:

View File

@ -1,28 +1,12 @@
#include "dxbc_compiler.h"
#include "dxbc_names.h"
namespace dxvk {
DxbcCompiler::DxbcCompiler(
DxbcProgramVersion version,
const Rc<DxbcIsgn>& inputSig,
const Rc<DxbcIsgn>& outputSig)
: m_version (version),
m_inputSig (inputSig),
m_outputSig (outputSig) {
m_entryPointId = m_module.allocateId();
DxbcProgramVersion version)
: m_version(version) {
this->declareCapabilities();
this->declareMemoryModel();
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);
// TODO implement proper control flow
m_module.opLabel(m_module.allocateId());
}
@ -32,240 +16,13 @@ namespace dxvk {
void DxbcCompiler::processInstruction(const DxbcInstruction& ins) {
const DxbcOpcodeToken token = ins.token();
switch (token.opcode()) {
case DxbcOpcode::DclGlobalFlags:
return this->dclGlobalFlags(ins);
case DxbcOpcode::DclInput:
return this->dclInput(ins);
case DxbcOpcode::DclOutputSiv:
return this->dclOutputSiv(ins);
case DxbcOpcode::DclTemps:
return this->dclTemps(ins);
case DxbcOpcode::DclThreadGroup:
return this->dclThreadGroup(ins);
case DxbcOpcode::Mov:
return this->opMov(ins);
case DxbcOpcode::Ret:
return this->opRet(ins);
default:
throw DxvkError(str::format("DXBC: Unhandled instruction: ", ins.token().opcode()));
}
}
Rc<DxvkShader> DxbcCompiler::finalize() {
m_module.functionEnd();
m_module.addEntryPoint(m_entryPointId,
m_version.executionModel(), "main",
m_interfaces.size(),
m_interfaces.data());
return new DxvkShader(m_version.shaderStage(),
m_module.compile(), 0, nullptr);
}
void DxbcCompiler::declareCapabilities() {
m_module.enableCapability(spv::CapabilityShader);
switch (m_version.type()) {
case DxbcProgramType::GeometryShader:
m_module.enableCapability(spv::CapabilityGeometry);
break;
case DxbcProgramType::HullShader:
case DxbcProgramType::DomainShader:
m_module.enableCapability(spv::CapabilityTessellation);
break;
default:
break;
}
}
void DxbcCompiler::declareMemoryModel() {
m_module.setMemoryModel(
spv::AddressingModelLogical,
spv::MemoryModelGLSL450);
}
void DxbcCompiler::dclGlobalFlags(const DxbcInstruction& ins) {
const DxbcGlobalFlags flags(ins.token().control());
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.
}
void DxbcCompiler::dclInput(const DxbcInstruction& ins) {
const DxbcOperand operand = ins.operand(0);
const DxbcOperandToken token = operand.token();
}
void DxbcCompiler::dclOutputSiv(const DxbcInstruction& ins) {
Logger::err("DXBC: dclOutputSiv: Not implemented yet");
}
void DxbcCompiler::dclTemps(const DxbcInstruction& ins) {
// Temporaries are treated as untyped 4x32-bit vectors.
const DxbcValueType regType(DxbcScalarType::Uint32, 4);
const DxbcPointerType ptrType(regType, spv::StorageClassPrivate);
const uint32_t ptrTypeId = this->getPointerTypeId(ptrType);
for (uint32_t i = 0; i < ins.arg(0); i++) {
DxbcPointer reg;
reg.type = ptrType;
reg.typeId = ptrTypeId;
reg.valueId = m_module.newVar(ptrTypeId, spv::StorageClassPrivate);
m_rRegs.push_back(reg);
m_module.setDebugName(reg.valueId,
str::format("r", i).c_str());
}
}
void DxbcCompiler::dclThreadGroup(const DxbcInstruction& ins) {
m_module.setLocalSize(m_entryPointId,
ins.arg(0), ins.arg(1), ins.arg(2));
}
void DxbcCompiler::opMov(const DxbcInstruction& ins) {
const DxbcOperand dstOp = ins.operand(0);
const DxbcOperand srcOp = ins.operand(dstOp.length());
DxbcValueType dstType(DxbcScalarType::Uint32, 1);
this->loadOperand(srcOp, dstType);
Logger::err("DXBC: mov: Not implemented yet");
}
void DxbcCompiler::opRet(const DxbcInstruction& ins) {
// TODO implement proper control flow
m_module.opReturn();
}
uint32_t DxbcCompiler::getScalarTypeId(const DxbcScalarType& type) {
switch (type) {
case DxbcScalarType::Uint32 : return m_module.defIntType(32, 0);
case DxbcScalarType::Uint64 : return m_module.defIntType(64, 0);
case DxbcScalarType::Sint32 : return m_module.defIntType(32, 1);
case DxbcScalarType::Sint64 : return m_module.defIntType(64, 1);
case DxbcScalarType::Float32: return m_module.defFloatType(32);
case DxbcScalarType::Float64: return m_module.defFloatType(64);
}
throw DxvkError("DXBC: Invalid scalar type");
}
uint32_t DxbcCompiler::getValueTypeId(const DxbcValueType& type) {
const uint32_t scalarTypeId = this->getScalarTypeId(type.componentType);
return type.componentCount > 1
? m_module.defVectorType(scalarTypeId, type.componentCount)
: scalarTypeId;
}
uint32_t DxbcCompiler::getPointerTypeId(const DxbcPointerType& type) {
return m_module.defPointerType(
this->getValueTypeId(type.valueType),
type.storageClass);
}
DxbcValue DxbcCompiler::loadPointer(const DxbcPointer& pointer) {
DxbcValue result;
result.type = pointer.type.valueType;
result.typeId = this->getValueTypeId(result.type);
result.valueId = m_module.opLoad(result.typeId, pointer.valueId);
return result;
}
DxbcValue DxbcCompiler::loadOperand(
const DxbcOperand& operand,
const DxbcValueType& type) {
const DxbcOperandToken token = operand.token();
DxbcValue result;
switch (token.type()) {
case DxbcOperandType::Imm32: {
const uint32_t componentCount = token.numComponents();
result.type = DxbcValueType(DxbcScalarType::Uint32, componentCount);
result.typeId = this->getValueTypeId(result.type);
if (componentCount == 1) {
result.valueId = m_module.constu32(operand.imm32(0));
} else {
std::array<uint32_t, 4> constIds;
for (uint32_t i = 0; i < componentCount; i++)
constIds.at(i) = m_module.constu32(operand.imm32(i));
result.valueId = m_module.constComposite(
result.typeId, componentCount, constIds.data());
}
} break;
case DxbcOperandType::Temp: {
const DxbcOperandIndex index = operand.index(0);
result = this->loadPointer(m_rRegs.at(index.immPart()));
} break;
default:
throw DxvkError(str::format(
"DxbcCompiler::loadOperandRegister: Unhandled operand type: ",
token.type()));
}
return result;
}
void DxbcCompiler::storePointer(
const DxbcPointer& pointer,
const DxbcValue& value) {
m_module.opStore(pointer.valueId, value.valueId);
}
void DxbcCompiler::storeOperand(
const DxbcOperand& operand,
const DxbcValueType& srcType,
uint32_t srcValue) {
}
}

View File

@ -17,9 +17,7 @@ namespace dxvk {
public:
DxbcCompiler(
DxbcProgramVersion version,
const Rc<DxbcIsgn>& inputSig,
const Rc<DxbcIsgn>& outputSig);
DxbcProgramVersion version);
~DxbcCompiler();
DxbcCompiler (DxbcCompiler&&) = delete;
@ -32,7 +30,7 @@ namespace dxvk {
* \returns \c true on success
*/
void processInstruction(
const DxbcInstruction& ins);
const DxbcInstruction& ins);
/**
* \brief Creates actual shader object
@ -47,77 +45,6 @@ namespace dxvk {
DxbcProgramVersion m_version;
SpirvModule m_module;
Rc<DxbcIsgn> m_inputSig;
Rc<DxbcIsgn> m_outputSig;
std::vector<uint32_t> m_interfaces;
std::vector<DxbcPointer> m_rRegs; // Temps
DxbcPointer m_svPosition;
std::vector<DxbcPointer> m_svClipDistance;
std::vector<DxbcPointer> m_svCullDistance;
uint32_t m_entryPointId = 0;
uint32_t m_typeVoid = 0;
uint32_t m_typeFunction = 0;
bool m_useRestrictedMath = false;
void declareCapabilities();
void declareMemoryModel();
void dclGlobalFlags(
const DxbcInstruction& ins);
void dclInput(
const DxbcInstruction& ins);
void dclOutputSiv(
const DxbcInstruction& ins);
void dclTemps(
const DxbcInstruction& ins);
void dclThreadGroup(
const DxbcInstruction& ins);
void opMov(
const DxbcInstruction& ins);
void opRet(
const DxbcInstruction& ins);
uint32_t getScalarTypeId(
const DxbcScalarType& type);
uint32_t getValueTypeId(
const DxbcValueType& type);
uint32_t getPointerTypeId(
const DxbcPointerType& type);
DxbcValue loadPointer(
const DxbcPointer& pointer);
DxbcValue loadOperand(
const DxbcOperand& operand,
const DxbcValueType& type);
void storePointer(
const DxbcPointer& pointer,
const DxbcValue& value);
void storeOperand(
const DxbcOperand& operand,
const DxbcValueType& srcType,
uint32_t srcValue);
};
}

View File

@ -5,26 +5,12 @@
#include "dxbc_enums.h"
#include "dxbc_names.h"
#include "dxbc_type.h"
namespace dxvk {
class DxbcOperand;
/**
* \brief Component swizzle
*/
struct DxbcComponentSwizzle {
DxbcComponentName x;
DxbcComponentName y;
DxbcComponentName z;
DxbcComponentName w;
};
/**
* \brief Component mask
*/
using DxbcComponentMask = Flags<DxbcComponentName>;
/**
* \brief DXBC instruction token
*
@ -213,11 +199,11 @@ namespace dxvk {
* \returns The component swizzle
*/
DxbcComponentSwizzle componentSwizzle() const {
return DxbcComponentSwizzle {
static_cast<DxbcComponentName>(bit::extract(m_token, 4, 5)),
static_cast<DxbcComponentName>(bit::extract(m_token, 6, 7)),
static_cast<DxbcComponentName>(bit::extract(m_token, 8, 9)),
static_cast<DxbcComponentName>(bit::extract(m_token, 10, 11)) };
return DxbcComponentSwizzle(
bit::extract(m_token, 4, 5),
bit::extract(m_token, 6, 7),
bit::extract(m_token, 8, 9),
bit::extract(m_token, 10, 11));
}
/**
@ -226,9 +212,8 @@ namespace dxvk {
* Used when the component selection mode is
* \c DxbcComponentSelectionMode::Select1.
*/
DxbcComponentName componentSelection() const {
return static_cast<DxbcComponentName>(
bit::extract(m_token, 4, 5));
DxbcComponentMask componentSelection() const {
return DxbcComponentMask(bit::extract(m_token, 4, 5));
}
/**

View File

@ -307,15 +307,6 @@ namespace dxvk {
};
/**
* \brief Component name
* Used for component selection.
*/
enum class DxbcComponentName : uint32_t {
X = 0, Y = 1, Z = 2, W = 3,
};
/**
* \brief Index representation
*

View File

@ -44,7 +44,13 @@ namespace dxvk {
if (m_shexChunk == nullptr)
throw DxvkError("DxbcModule::compile: No SHDR/SHEX chunk");
DxbcCompiler compiler(m_shexChunk->version(), m_isgnChunk, m_osgnChunk);
DxbcCompiler compiler(m_shexChunk->version());
// if (m_isgnChunk != nullptr)
// compiler.declareInputSignature(*m_isgnChunk);
// if (m_osgnChunk != nullptr)
// compiler.declareOutputSignature(*m_osgnChunk);
for (auto ins : *m_shexChunk)
compiler.processInstruction(ins);

View File

@ -295,17 +295,6 @@ std::ostream& operator << (std::ostream& os, DxbcComponentSelectionMode e) {
}
std::ostream& operator << (std::ostream& os, DxbcComponentName e) {
switch (e) {
ENUM_NAME(DxbcComponentName::X);
ENUM_NAME(DxbcComponentName::Y);
ENUM_NAME(DxbcComponentName::Z);
ENUM_NAME(DxbcComponentName::W);
ENUM_DEFAULT(e);
}
}
std::ostream& operator << (std::ostream& os, DxbcOperandIndexRepresentation e) {
switch (e) {
ENUM_NAME(DxbcOperandIndexRepresentation::Imm32);

View File

@ -9,7 +9,6 @@ std::ostream& operator << (std::ostream& os, dxvk::DxbcExtOpcode e);
std::ostream& operator << (std::ostream& os, dxvk::DxbcOperandType e);
std::ostream& operator << (std::ostream& os, dxvk::DxbcComponentCount e);
std::ostream& operator << (std::ostream& os, dxvk::DxbcComponentSelectionMode e);
std::ostream& operator << (std::ostream& os, dxvk::DxbcComponentName e);
std::ostream& operator << (std::ostream& os, dxvk::DxbcOperandIndexRepresentation e);
std::ostream& operator << (std::ostream& os, dxvk::DxbcResourceDim e);
std::ostream& operator << (std::ostream& os, dxvk::DxbcResourceReturnType e);

View File

@ -101,4 +101,83 @@ namespace dxvk {
uint32_t valueId = 0;
};
/**
* \brief Component mask
*/
class DxbcComponentMask {
public:
DxbcComponentMask() { }
DxbcComponentMask(uint32_t mask)
: m_mask(mask) { }
DxbcComponentMask(bool x, bool y, bool z, bool w)
: m_mask((x ? 1 : 0) | (y ? 2 : 0) | (z ? 4 : 0) | (w ? 8 : 0)) { }
void set(uint32_t id) { m_mask |= bit(id); }
void clr(uint32_t id) { m_mask &= ~bit(id); }
bool test(uint32_t id) const {
return !!(m_mask & bit(id));
}
uint32_t componentCount() const {
return bit::popcnt(m_mask);
}
uint32_t firstComponent() const {
return bit::tzcnt(m_mask);
}
DxbcComponentMask operator ~ () const { return (~m_mask) & 0xF; }
DxbcComponentMask operator & (const DxbcComponentMask& other) const { return m_mask & other.m_mask; }
DxbcComponentMask operator | (const DxbcComponentMask& other) const { return m_mask | other.m_mask; }
bool operator == (const DxbcComponentMask& other) const { return m_mask == other.m_mask; }
bool operator != (const DxbcComponentMask& other) const { return m_mask != other.m_mask; }
operator bool () const {
return m_mask != 0;
}
private:
uint32_t m_mask = 0;
uint32_t bit(uint32_t id) const {
return 1u << id;
}
};
/**
* \brief Component swizzle
*/
class DxbcComponentSwizzle {
public:
DxbcComponentSwizzle()
: DxbcComponentSwizzle(0, 1, 2, 3) { }
DxbcComponentSwizzle(uint32_t x, uint32_t y, uint32_t z, uint32_t w)
: m_components {{ x, y, z, w }} { }
uint32_t operator [] (uint32_t id) const { return m_components.at(id); }
uint32_t& operator [] (uint32_t id) { return m_components.at(id); }
const uint32_t* operator & () const {
return m_components.data();
}
DxbcComponentSwizzle extract(DxbcComponentMask mask) const;
DxbcComponentMask mask(uint32_t n) const;
private:
std::array<uint32_t, 4> m_components;
};
}

View File

@ -8,6 +8,7 @@ dxbc_src = files([
'dxbc_module.cpp',
'dxbc_names.cpp',
'dxbc_reader.cpp',
'dxbc_type.cpp',
])
dxbc_lib = static_library('dxbc', dxbc_src,

View File

@ -204,6 +204,36 @@ namespace dxvk {
}
void SpirvModule::decorateBuiltIn(
uint32_t object,
spv::BuiltIn builtIn) {
m_annotations.putIns (spv::OpDecorate, 4);
m_annotations.putWord (object);
m_annotations.putWord (spv::DecorationBuiltIn);
m_annotations.putWord (builtIn);
}
void SpirvModule::decorateComponent(
uint32_t object,
uint32_t location) {
m_annotations.putIns (spv::OpDecorate, 4);
m_annotations.putWord (object);
m_annotations.putWord (spv::DecorationComponent);
m_annotations.putInt32(location);
}
void SpirvModule::decorateLocation(
uint32_t object,
uint32_t location) {
m_annotations.putIns (spv::OpDecorate, 4);
m_annotations.putWord (object);
m_annotations.putWord (spv::DecorationLocation);
m_annotations.putInt32(location);
}
uint32_t SpirvModule::defVoidType() {
return this->defType(spv::OpTypeVoid, 0, nullptr);
}
@ -354,6 +384,57 @@ namespace dxvk {
}
uint32_t SpirvModule::opBitcast(
uint32_t resultType,
uint32_t operand) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpBitcast, 4);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(operand);
return resultId;
}
uint32_t SpirvModule::opCompositeExtract(
uint32_t resultType,
uint32_t composite,
uint32_t indexCount,
const uint32_t* indexArray) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpCompositeExtract, 4 + indexCount);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(composite);
for (uint32_t i = 0; i < indexCount; i++)
m_code.putInt32(indexArray[i]);
return resultId;
}
uint32_t SpirvModule::opVectorShuffle(
uint32_t resultType,
uint32_t vectorLeft,
uint32_t vectorRight,
uint32_t indexCount,
const uint32_t* indexArray) {
uint32_t resultId = this->allocateId();
m_code.putIns (spv::OpVectorShuffle, 5 + indexCount);
m_code.putWord(resultType);
m_code.putWord(resultId);
m_code.putWord(vectorLeft);
m_code.putWord(vectorRight);
for (uint32_t i = 0; i < indexCount; i++)
m_code.putInt32(indexArray[i]);
return resultId;
}
uint32_t SpirvModule::opFunctionCall(
uint32_t resultType,
uint32_t functionId,
@ -373,7 +454,7 @@ namespace dxvk {
void SpirvModule::opLabel(uint32_t labelId) {
m_code.putIns (spv::OpReturn, 2);
m_code.putIns (spv::OpLabel, 2);
m_code.putWord(labelId);
}

View File

@ -76,6 +76,18 @@ namespace dxvk {
uint32_t constCount,
const uint32_t* constIds);
void decorateBuiltIn(
uint32_t object,
spv::BuiltIn builtIn);
void decorateComponent(
uint32_t object,
uint32_t location);
void decorateLocation(
uint32_t object,
uint32_t location);
uint32_t defVoidType();
uint32_t defBoolType();
@ -130,6 +142,23 @@ namespace dxvk {
void functionEnd();
uint32_t opBitcast(
uint32_t resultType,
uint32_t operand);
uint32_t opCompositeExtract(
uint32_t resultType,
uint32_t composite,
uint32_t indexCount,
const uint32_t* indexArray);
uint32_t opVectorShuffle(
uint32_t resultType,
uint32_t vectorLeft,
uint32_t vectorRight,
uint32_t indexCount,
const uint32_t* indexArray);
uint32_t opFunctionCall(
uint32_t resultType,
uint32_t functionId,

View File

@ -3,8 +3,24 @@
namespace dxvk::bit {
template<typename T>
inline T extract(T value, uint32_t fst, uint32_t lst) {
T extract(T value, uint32_t fst, uint32_t lst) {
return (value >> fst) & ~(~T(0) << (lst - fst + 1));
}
template<typename T>
T popcnt(T value) {
return value != 0
? (value & 1) + popcnt(value >> 1)
: 0;
}
template<typename T>
T tzcnt(T value) {
uint32_t result = 0;
while ((result < sizeof(T) * 8)
&& (((value >> result) & 1) == 0))
result += 1;
return result;
}
}

View File

@ -2,6 +2,8 @@
#include <type_traits>
#include "util_bit.h"
namespace dxvk {
template<typename T>
@ -54,6 +56,10 @@ namespace dxvk {
m_bits = 0;
}
uint32_t raw() const {
return m_bits;
}
private:
IntType m_bits = 0;