mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-27 04:54:15 +01:00
[dxbc] Separate code generator classed for each shader type
This commit is contained in:
parent
403ab75aeb
commit
43dfba2287
@ -1,13 +1,10 @@
|
|||||||
#include "dxbc_compiler.h"
|
#include "dxbc_compiler.h"
|
||||||
#include "dxbc_names.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
DxbcCompiler::DxbcCompiler(
|
DxbcCompiler::DxbcCompiler(
|
||||||
DxbcProgramVersion version)
|
const DxbcProgramVersion& version)
|
||||||
: m_version(version) {
|
: m_gen(DxbcCodeGen::create(version)) { }
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
DxbcCompiler::~DxbcCompiler() {
|
DxbcCompiler::~DxbcCompiler() {
|
||||||
@ -16,13 +13,58 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::processInstruction(const DxbcInstruction& ins) {
|
void DxbcCompiler::processInstruction(const DxbcInstruction& ins) {
|
||||||
|
const DxbcOpcodeToken token = ins.token();
|
||||||
|
|
||||||
|
switch (token.opcode()) {
|
||||||
|
case DxbcOpcode::DclGlobalFlags:
|
||||||
|
return this->dclGlobalFlags(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::DclInput:
|
||||||
|
case DxbcOpcode::DclInputSiv:
|
||||||
|
case DxbcOpcode::DclInputSgv:
|
||||||
|
case DxbcOpcode::DclInputPs:
|
||||||
|
case DxbcOpcode::DclInputPsSiv:
|
||||||
|
case DxbcOpcode::DclInputPsSgv:
|
||||||
|
return this->dclInput(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::DclOutput:
|
||||||
|
case DxbcOpcode::DclOutputSiv:
|
||||||
|
case DxbcOpcode::DclOutputSgv:
|
||||||
|
return this->dclOutput(ins);
|
||||||
|
|
||||||
|
case DxbcOpcode::DclTemps:
|
||||||
|
return this->dclTemps(ins);
|
||||||
|
|
||||||
|
default:
|
||||||
|
Logger::err(str::format(
|
||||||
|
"DxbcCompiler::processInstruction: Unhandled opcode: ",
|
||||||
|
token.opcode()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Rc<DxvkShader> DxbcCompiler::finalize() {
|
Rc<DxvkShader> DxbcCompiler::finalize() {
|
||||||
return new DxvkShader(m_version.shaderStage(),
|
return m_gen->finalize();
|
||||||
m_module.compile(), 0, nullptr);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::dclGlobalFlags(const DxbcInstruction& ins) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::dclInput(const DxbcInstruction& ins) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::dclOutput(const DxbcInstruction& ins) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCompiler::dclTemps(const DxbcInstruction& ins) {
|
||||||
|
m_gen->dclTemps(ins.arg(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -1,49 +1,43 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "dxbc_chunk_isgn.h"
|
#include "./gen/dxbc_gen_common.h"
|
||||||
#include "dxbc_chunk_shex.h"
|
|
||||||
#include "dxbc_names.h"
|
|
||||||
#include "dxbc_type.h"
|
|
||||||
|
|
||||||
#include "../spirv/spirv_module.h"
|
|
||||||
|
|
||||||
namespace dxvk {
|
namespace dxvk {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief DXBC to SPIR-V compiler
|
* \brief DXBC compiler
|
||||||
|
*
|
||||||
|
* Interprets DXBC instructions and generates
|
||||||
|
* SPIR-V code for the appropriate shader type.
|
||||||
*/
|
*/
|
||||||
class DxbcCompiler {
|
class DxbcCompiler {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DxbcCompiler(
|
DxbcCompiler(
|
||||||
DxbcProgramVersion version);
|
const DxbcProgramVersion& version);
|
||||||
~DxbcCompiler();
|
~DxbcCompiler();
|
||||||
|
|
||||||
DxbcCompiler (DxbcCompiler&&) = delete;
|
|
||||||
DxbcCompiler& operator = (DxbcCompiler&&) = delete;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Processes a single instruction
|
|
||||||
*
|
|
||||||
* \param [in] ins The instruction
|
|
||||||
* \returns \c true on success
|
|
||||||
*/
|
|
||||||
void processInstruction(
|
void processInstruction(
|
||||||
const DxbcInstruction& ins);
|
const DxbcInstruction& ins);
|
||||||
|
|
||||||
/**
|
|
||||||
* \brief Creates actual shader object
|
|
||||||
*
|
|
||||||
* Combines all information gatherd during the
|
|
||||||
* shader compilation into one shader object.
|
|
||||||
*/
|
|
||||||
Rc<DxvkShader> finalize();
|
Rc<DxvkShader> finalize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
DxbcProgramVersion m_version;
|
Rc<DxbcCodeGen> m_gen;
|
||||||
SpirvModule m_module;
|
|
||||||
|
void dclGlobalFlags(
|
||||||
|
const DxbcInstruction& ins);
|
||||||
|
|
||||||
|
void dclInput(
|
||||||
|
const DxbcInstruction& ins);
|
||||||
|
|
||||||
|
void dclOutput(
|
||||||
|
const DxbcInstruction& ins);
|
||||||
|
|
||||||
|
void dclTemps(
|
||||||
|
const DxbcInstruction& ins);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -527,6 +527,19 @@ namespace dxvk {
|
|||||||
return m_args.getWord(idx);
|
return m_args.getWord(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Reads an argument enum
|
||||||
|
*
|
||||||
|
* Casts the word at the given location to an enum.
|
||||||
|
* Some instructions take name tokens as operands.
|
||||||
|
* \param [in] idx Argument word index
|
||||||
|
* \returns The enum value of the given word
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
T readEnum(uint32_t idx) const {
|
||||||
|
return static_cast<T>(arg(idx));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Retrieves an operand
|
* \brief Retrieves an operand
|
||||||
*
|
*
|
||||||
|
@ -45,13 +45,6 @@ namespace dxvk {
|
|||||||
throw DxvkError("DxbcModule::compile: No SHDR/SHEX chunk");
|
throw DxvkError("DxbcModule::compile: No SHDR/SHEX chunk");
|
||||||
|
|
||||||
DxbcCompiler compiler(m_shexChunk->version());
|
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)
|
for (auto ins : *m_shexChunk)
|
||||||
compiler.processInstruction(ins);
|
compiler.processInstruction(ins);
|
||||||
return compiler.finalize();
|
return compiler.finalize();
|
||||||
|
@ -390,3 +390,16 @@ std::ostream& operator << (std::ostream& os, DxbcSystemValue e) {
|
|||||||
ENUM_DEFAULT(e);
|
ENUM_DEFAULT(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator << (std::ostream& os, dxvk::DxbcProgramType e) {
|
||||||
|
switch (e) {
|
||||||
|
ENUM_NAME(DxbcProgramType::PixelShader);
|
||||||
|
ENUM_NAME(DxbcProgramType::VertexShader);
|
||||||
|
ENUM_NAME(DxbcProgramType::GeometryShader);
|
||||||
|
ENUM_NAME(DxbcProgramType::HullShader);
|
||||||
|
ENUM_NAME(DxbcProgramType::DomainShader);
|
||||||
|
ENUM_NAME(DxbcProgramType::ComputeShader);
|
||||||
|
ENUM_DEFAULT(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
|
||||||
|
#include "dxbc_common.h"
|
||||||
#include "dxbc_enums.h"
|
#include "dxbc_enums.h"
|
||||||
|
|
||||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcOpcode e);
|
std::ostream& operator << (std::ostream& os, dxvk::DxbcOpcode e);
|
||||||
@ -15,3 +16,4 @@ std::ostream& operator << (std::ostream& os, dxvk::DxbcResourceReturnType e);
|
|||||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcRegisterComponentType e);
|
std::ostream& operator << (std::ostream& os, dxvk::DxbcRegisterComponentType e);
|
||||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcInstructionReturnType e);
|
std::ostream& operator << (std::ostream& os, dxvk::DxbcInstructionReturnType e);
|
||||||
std::ostream& operator << (std::ostream& os, dxvk::DxbcSystemValue e);
|
std::ostream& operator << (std::ostream& os, dxvk::DxbcSystemValue e);
|
||||||
|
std::ostream& operator << (std::ostream& os, dxvk::DxbcProgramType e);
|
||||||
|
@ -14,12 +14,4 @@ namespace dxvk {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DxbcComponentMask DxbcComponentSwizzle::mask(uint32_t n) const {
|
|
||||||
DxbcComponentMask mask;
|
|
||||||
for (uint32_t i = 0; i < n; i++)
|
|
||||||
mask.set(m_components.at(i));
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -30,10 +30,13 @@ namespace dxvk {
|
|||||||
struct DxbcValueType {
|
struct DxbcValueType {
|
||||||
DxbcValueType() { }
|
DxbcValueType() { }
|
||||||
DxbcValueType(DxbcScalarType s, uint32_t c)
|
DxbcValueType(DxbcScalarType s, uint32_t c)
|
||||||
: componentType(s), componentCount(c) { }
|
: DxbcValueType(s, c, 0) { }
|
||||||
|
DxbcValueType(DxbcScalarType s, uint32_t c, uint32_t e)
|
||||||
|
: componentType(s), componentCount(c), elementCount(e) { }
|
||||||
|
|
||||||
DxbcScalarType componentType = DxbcScalarType::Uint32;
|
DxbcScalarType componentType = DxbcScalarType::Uint32;
|
||||||
uint32_t componentCount = 0;
|
uint32_t componentCount = 0;
|
||||||
|
uint32_t elementCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -44,17 +47,7 @@ namespace dxvk {
|
|||||||
* result that can be used as an operand value.
|
* result that can be used as an operand value.
|
||||||
*/
|
*/
|
||||||
struct DxbcValue {
|
struct DxbcValue {
|
||||||
DxbcValue() { }
|
|
||||||
DxbcValue(
|
|
||||||
DxbcValueType p_type,
|
|
||||||
uint32_t p_typeId,
|
|
||||||
uint32_t p_valueId)
|
|
||||||
: type (p_type),
|
|
||||||
typeId (p_typeId),
|
|
||||||
valueId (p_valueId) { }
|
|
||||||
|
|
||||||
DxbcValueType type;
|
DxbcValueType type;
|
||||||
uint32_t typeId = 0;
|
|
||||||
uint32_t valueId = 0;
|
uint32_t valueId = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -87,20 +80,11 @@ namespace dxvk {
|
|||||||
* class. Can be used as a memory operand.
|
* class. Can be used as a memory operand.
|
||||||
*/
|
*/
|
||||||
struct DxbcPointer {
|
struct DxbcPointer {
|
||||||
DxbcPointer() { }
|
|
||||||
DxbcPointer(
|
|
||||||
DxbcPointerType p_type,
|
|
||||||
uint32_t p_typeId,
|
|
||||||
uint32_t p_valueId)
|
|
||||||
: type (p_type),
|
|
||||||
typeId (p_typeId),
|
|
||||||
valueId (p_valueId) { }
|
|
||||||
|
|
||||||
DxbcPointerType type;
|
DxbcPointerType type;
|
||||||
uint32_t typeId = 0;
|
|
||||||
uint32_t valueId = 0;
|
uint32_t valueId = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Component mask
|
* \brief Component mask
|
||||||
*/
|
*/
|
||||||
@ -172,8 +156,6 @@ namespace dxvk {
|
|||||||
|
|
||||||
DxbcComponentSwizzle extract(DxbcComponentMask mask) const;
|
DxbcComponentSwizzle extract(DxbcComponentMask mask) const;
|
||||||
|
|
||||||
DxbcComponentMask mask(uint32_t n) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::array<uint32_t, 4> m_components;
|
std::array<uint32_t, 4> m_components;
|
||||||
|
120
src/dxbc/gen/dxbc_gen_common.cpp
Normal file
120
src/dxbc/gen/dxbc_gen_common.cpp
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
#include "dxbc_gen_common.h"
|
||||||
|
#include "dxbc_gen_vertex.h"
|
||||||
|
|
||||||
|
#include "../dxbc_names.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
DxbcCodeGen::DxbcCodeGen() {
|
||||||
|
m_module.enableCapability(spv::CapabilityShader);
|
||||||
|
m_module.setMemoryModel(
|
||||||
|
spv::AddressingModelLogical,
|
||||||
|
spv::MemoryModelGLSL450);
|
||||||
|
m_entryPointId = m_module.allocateId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxbcCodeGen::~DxbcCodeGen() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcCodeGen::dclTemps(uint32_t n) {
|
||||||
|
const uint32_t oldSize = m_rRegs.size();
|
||||||
|
|
||||||
|
if (n > oldSize) {
|
||||||
|
m_rRegs.resize(n);
|
||||||
|
|
||||||
|
DxbcPointer reg;
|
||||||
|
reg.type = DxbcPointerType(
|
||||||
|
DxbcValueType(DxbcScalarType::Float32, 4),
|
||||||
|
spv::StorageClassPrivate);
|
||||||
|
|
||||||
|
const uint32_t typeId = this->defPointerType(reg.type);
|
||||||
|
|
||||||
|
for (uint32_t i = oldSize; i < n; i++) {
|
||||||
|
reg.valueId = m_module.newVar(typeId, spv::StorageClassPrivate);
|
||||||
|
m_module.setDebugName(reg.valueId, str::format("r", i).c_str());
|
||||||
|
m_rRegs.at(i) = reg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rc<DxbcCodeGen> DxbcCodeGen::create(
|
||||||
|
const DxbcProgramVersion& version) {
|
||||||
|
switch (version.type()) {
|
||||||
|
case DxbcProgramType::VertexShader:
|
||||||
|
return new DxbcVsCodeGen();
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw DxvkError(str::format(
|
||||||
|
"DxbcCodeGen::create: Unsupported program type: ",
|
||||||
|
version.type()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t DxbcCodeGen::defScalarType(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);
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw DxvkError("DxbcCodeGen::defScalarType: Invalid scalar type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t DxbcCodeGen::defValueType(const DxbcValueType& type) {
|
||||||
|
uint32_t typeId = this->defScalarType(type.componentType);
|
||||||
|
|
||||||
|
if (type.componentCount > 1)
|
||||||
|
typeId = m_module.defVectorType(typeId, type.componentCount);
|
||||||
|
|
||||||
|
if (type.elementCount > 0)
|
||||||
|
typeId = m_module.defArrayType(typeId, m_module.constu32(type.elementCount));
|
||||||
|
|
||||||
|
return typeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t DxbcCodeGen::defPointerType(const DxbcPointerType& type) {
|
||||||
|
uint32_t valueTypeId = this->defValueType(type.valueType);
|
||||||
|
return m_module.defPointerType(valueTypeId, type.storageClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t DxbcCodeGen::defPerVertexBlock() {
|
||||||
|
uint32_t s1f32 = this->defScalarType(DxbcScalarType::Float32);
|
||||||
|
uint32_t v4f32 = this->defValueType(DxbcValueType(DxbcScalarType::Float32, 4, 0));
|
||||||
|
uint32_t a2f32 = this->defValueType(DxbcValueType(DxbcScalarType::Float32, 1, 2));
|
||||||
|
|
||||||
|
std::array<uint32_t, 4> members;
|
||||||
|
members[PerVertex_Position] = v4f32;
|
||||||
|
members[PerVertex_PointSize] = s1f32;
|
||||||
|
members[PerVertex_CullDist] = a2f32;
|
||||||
|
members[PerVertex_ClipDist] = a2f32;
|
||||||
|
|
||||||
|
uint32_t typeId = m_module.defStructType(
|
||||||
|
members.size(), members.data());
|
||||||
|
|
||||||
|
m_module.memberDecorateBuiltIn(typeId, PerVertex_Position, spv::BuiltInPosition);
|
||||||
|
m_module.memberDecorateBuiltIn(typeId, PerVertex_PointSize, spv::BuiltInPointSize);
|
||||||
|
m_module.memberDecorateBuiltIn(typeId, PerVertex_CullDist, spv::BuiltInCullDistance);
|
||||||
|
m_module.memberDecorateBuiltIn(typeId, PerVertex_ClipDist, spv::BuiltInClipDistance);
|
||||||
|
m_module.decorateBlock(typeId);
|
||||||
|
|
||||||
|
m_module.setDebugName(typeId, "per_vertex");
|
||||||
|
m_module.setDebugMemberName(typeId, PerVertex_Position, "position");
|
||||||
|
m_module.setDebugMemberName(typeId, PerVertex_PointSize, "point_size");
|
||||||
|
m_module.setDebugMemberName(typeId, PerVertex_CullDist, "cull_dist");
|
||||||
|
m_module.setDebugMemberName(typeId, PerVertex_ClipDist, "clip_dist");
|
||||||
|
return typeId;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
108
src/dxbc/gen/dxbc_gen_common.h
Normal file
108
src/dxbc/gen/dxbc_gen_common.h
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../dxbc_common.h"
|
||||||
|
#include "../dxbc_decoder.h"
|
||||||
|
#include "../dxbc_type.h"
|
||||||
|
|
||||||
|
#include "../../spirv/spirv_module.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief System value mapping
|
||||||
|
*
|
||||||
|
* Maps a system value to a given set of
|
||||||
|
* components of an input or output register.
|
||||||
|
*/
|
||||||
|
struct DxbcSvMapping {
|
||||||
|
uint32_t regId;
|
||||||
|
DxbcComponentMask regMask;
|
||||||
|
DxbcSystemValue sv;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief DXBC code generator
|
||||||
|
*
|
||||||
|
* SPIR-V code generator. Implements simple micro ops that are
|
||||||
|
* generated when parsing the DXBC shader code. Some of these
|
||||||
|
* may require different implementations for each shader stage
|
||||||
|
* and are therefore implemented in a sub class.
|
||||||
|
*/
|
||||||
|
class DxbcCodeGen : public RcObject {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DxbcCodeGen();
|
||||||
|
|
||||||
|
virtual ~DxbcCodeGen();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Declares temporary registers
|
||||||
|
* \param [in] n Number of temp registers
|
||||||
|
*/
|
||||||
|
void dclTemps(uint32_t n);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Declares an interface variable
|
||||||
|
*
|
||||||
|
* \param [in] regType Register type
|
||||||
|
* \param [in] regId Interface register index
|
||||||
|
* \param [in] regDim Array dimension of interface variable
|
||||||
|
* \param [in] regMask Component mask for this declaration
|
||||||
|
* \param [in] sv System value to map to the given components
|
||||||
|
*/
|
||||||
|
virtual void dclInterfaceVar(
|
||||||
|
DxbcOperandType regType,
|
||||||
|
uint32_t regId,
|
||||||
|
uint32_t regDim,
|
||||||
|
DxbcComponentMask regMask,
|
||||||
|
DxbcSystemValue sv) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Finalizes shader
|
||||||
|
*
|
||||||
|
* Depending on the shader stage, this may generate
|
||||||
|
* additional code to set up input variables, output
|
||||||
|
* variables, and execute shader phases.
|
||||||
|
* \returns DXVK shader module
|
||||||
|
*/
|
||||||
|
virtual Rc<DxvkShader> finalize() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Creates code generator for a given program type
|
||||||
|
*
|
||||||
|
* \param [in] version Program version
|
||||||
|
* \returns The code generator
|
||||||
|
*/
|
||||||
|
static Rc<DxbcCodeGen> create(
|
||||||
|
const DxbcProgramVersion& version);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
constexpr static uint32_t PerVertex_Position = 0;
|
||||||
|
constexpr static uint32_t PerVertex_PointSize = 1;
|
||||||
|
constexpr static uint32_t PerVertex_CullDist = 2;
|
||||||
|
constexpr static uint32_t PerVertex_ClipDist = 3;
|
||||||
|
|
||||||
|
SpirvModule m_module;
|
||||||
|
|
||||||
|
std::vector<uint32_t> m_entryPointInterfaces;
|
||||||
|
uint32_t m_entryPointId = 0;
|
||||||
|
|
||||||
|
std::vector<DxbcPointer> m_rRegs;
|
||||||
|
|
||||||
|
uint32_t defScalarType(
|
||||||
|
DxbcScalarType type);
|
||||||
|
|
||||||
|
uint32_t defValueType(
|
||||||
|
const DxbcValueType& type);
|
||||||
|
|
||||||
|
uint32_t defPointerType(
|
||||||
|
const DxbcPointerType& type);
|
||||||
|
|
||||||
|
uint32_t defPerVertexBlock();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
38
src/dxbc/gen/dxbc_gen_vertex.cpp
Normal file
38
src/dxbc/gen/dxbc_gen_vertex.cpp
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#include "dxbc_gen_vertex.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
DxbcVsCodeGen::DxbcVsCodeGen() {
|
||||||
|
m_outPerVertex = m_module.newVar(
|
||||||
|
m_module.defPointerType(this->defPerVertexBlock(), spv::StorageClassOutput),
|
||||||
|
spv::StorageClassOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DxbcVsCodeGen::~DxbcVsCodeGen() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxbcVsCodeGen::dclInterfaceVar(
|
||||||
|
DxbcOperandType regType,
|
||||||
|
uint32_t regId,
|
||||||
|
uint32_t regDim,
|
||||||
|
DxbcComponentMask regMask,
|
||||||
|
DxbcSystemValue sv) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rc<DxvkShader> DxbcVsCodeGen::finalize() {
|
||||||
|
m_module.addEntryPoint(m_entryPointId,
|
||||||
|
spv::ExecutionModelVertex, "main",
|
||||||
|
m_entryPointInterfaces.size(),
|
||||||
|
m_entryPointInterfaces.data());
|
||||||
|
m_module.setDebugName(m_entryPointId, "main");
|
||||||
|
|
||||||
|
return new DxvkShader(VK_SHADER_STAGE_VERTEX_BIT,
|
||||||
|
m_module.compile(), 0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
38
src/dxbc/gen/dxbc_gen_vertex.h
Normal file
38
src/dxbc/gen/dxbc_gen_vertex.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "dxbc_gen_common.h"
|
||||||
|
|
||||||
|
namespace dxvk {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Vertex shader code generator
|
||||||
|
*/
|
||||||
|
class DxbcVsCodeGen : public DxbcCodeGen {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
DxbcVsCodeGen();
|
||||||
|
~DxbcVsCodeGen();
|
||||||
|
|
||||||
|
void dclInterfaceVar(
|
||||||
|
DxbcOperandType regType,
|
||||||
|
uint32_t regId,
|
||||||
|
uint32_t regDim,
|
||||||
|
DxbcComponentMask regMask,
|
||||||
|
DxbcSystemValue sv);
|
||||||
|
|
||||||
|
Rc<DxvkShader> finalize() final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
uint32_t m_outPerVertex = 0;
|
||||||
|
|
||||||
|
std::array<DxbcPointer, 32> m_vRegs;
|
||||||
|
std::array<DxbcPointer, 32> m_oRegs;
|
||||||
|
|
||||||
|
std::vector<DxbcSvMapping> m_svInputs;
|
||||||
|
std::vector<DxbcSvMapping> m_svOutputs;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -9,6 +9,9 @@ dxbc_src = files([
|
|||||||
'dxbc_names.cpp',
|
'dxbc_names.cpp',
|
||||||
'dxbc_reader.cpp',
|
'dxbc_reader.cpp',
|
||||||
'dxbc_type.cpp',
|
'dxbc_type.cpp',
|
||||||
|
|
||||||
|
'gen/dxbc_gen_common.cpp',
|
||||||
|
'gen/dxbc_gen_vertex.cpp',
|
||||||
])
|
])
|
||||||
|
|
||||||
dxbc_lib = static_library('dxbc', dxbc_src,
|
dxbc_lib = static_library('dxbc', dxbc_src,
|
||||||
|
@ -15,8 +15,7 @@ namespace dxvk {
|
|||||||
result.append(m_execModeInfo);
|
result.append(m_execModeInfo);
|
||||||
result.append(m_debugNames);
|
result.append(m_debugNames);
|
||||||
result.append(m_annotations);
|
result.append(m_annotations);
|
||||||
result.append(m_typeDefs);
|
result.append(m_typeConstDefs);
|
||||||
result.append(m_constDefs);
|
|
||||||
result.append(m_variables);
|
result.append(m_variables);
|
||||||
result.append(m_code);
|
result.append(m_code);
|
||||||
return result;
|
return result;
|
||||||
@ -98,14 +97,25 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::setDebugMemberName(
|
||||||
|
uint32_t structId,
|
||||||
|
uint32_t memberId,
|
||||||
|
const char* debugName) {
|
||||||
|
m_debugNames.putIns (spv::OpMemberName, 3 + m_debugNames.strLen(debugName));
|
||||||
|
m_debugNames.putWord(structId);
|
||||||
|
m_debugNames.putWord(memberId);
|
||||||
|
m_debugNames.putStr (debugName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvModule::constBool(
|
uint32_t SpirvModule::constBool(
|
||||||
bool v) {
|
bool v) {
|
||||||
uint32_t typeId = this->defBoolType();
|
uint32_t typeId = this->defBoolType();
|
||||||
uint32_t resultId = this->allocateId();
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
m_constDefs.putIns (v ? spv::OpConstantTrue : spv::OpConstantFalse, 3);
|
m_typeConstDefs.putIns (v ? spv::OpConstantTrue : spv::OpConstantFalse, 3);
|
||||||
m_constDefs.putWord (typeId);
|
m_typeConstDefs.putWord (typeId);
|
||||||
m_constDefs.putWord (resultId);
|
m_typeConstDefs.putWord (resultId);
|
||||||
return resultId;
|
return resultId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,10 +125,10 @@ namespace dxvk {
|
|||||||
uint32_t typeId = this->defIntType(32, 1);
|
uint32_t typeId = this->defIntType(32, 1);
|
||||||
uint32_t resultId = this->allocateId();
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
m_constDefs.putIns (spv::OpConstant, 4);
|
m_typeConstDefs.putIns (spv::OpConstant, 4);
|
||||||
m_constDefs.putWord (typeId);
|
m_typeConstDefs.putWord (typeId);
|
||||||
m_constDefs.putWord (resultId);
|
m_typeConstDefs.putWord (resultId);
|
||||||
m_constDefs.putInt32(v);
|
m_typeConstDefs.putInt32(v);
|
||||||
return resultId;
|
return resultId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,10 +138,10 @@ namespace dxvk {
|
|||||||
uint32_t typeId = this->defIntType(64, 1);
|
uint32_t typeId = this->defIntType(64, 1);
|
||||||
uint32_t resultId = this->allocateId();
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
m_constDefs.putIns (spv::OpConstant, 5);
|
m_typeConstDefs.putIns (spv::OpConstant, 5);
|
||||||
m_constDefs.putWord (typeId);
|
m_typeConstDefs.putWord (typeId);
|
||||||
m_constDefs.putWord (resultId);
|
m_typeConstDefs.putWord (resultId);
|
||||||
m_constDefs.putInt64(v);
|
m_typeConstDefs.putInt64(v);
|
||||||
return resultId;
|
return resultId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,10 +151,10 @@ namespace dxvk {
|
|||||||
uint32_t typeId = this->defIntType(32, 0);
|
uint32_t typeId = this->defIntType(32, 0);
|
||||||
uint32_t resultId = this->allocateId();
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
m_constDefs.putIns (spv::OpConstant, 4);
|
m_typeConstDefs.putIns (spv::OpConstant, 4);
|
||||||
m_constDefs.putWord (typeId);
|
m_typeConstDefs.putWord (typeId);
|
||||||
m_constDefs.putWord (resultId);
|
m_typeConstDefs.putWord (resultId);
|
||||||
m_constDefs.putInt32(v);
|
m_typeConstDefs.putInt32(v);
|
||||||
return resultId;
|
return resultId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,10 +164,10 @@ namespace dxvk {
|
|||||||
uint32_t typeId = this->defIntType(64, 0);
|
uint32_t typeId = this->defIntType(64, 0);
|
||||||
uint32_t resultId = this->allocateId();
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
m_constDefs.putIns (spv::OpConstant, 5);
|
m_typeConstDefs.putIns (spv::OpConstant, 5);
|
||||||
m_constDefs.putWord (typeId);
|
m_typeConstDefs.putWord (typeId);
|
||||||
m_constDefs.putWord (resultId);
|
m_typeConstDefs.putWord (resultId);
|
||||||
m_constDefs.putInt64(v);
|
m_typeConstDefs.putInt64(v);
|
||||||
return resultId;
|
return resultId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,10 +177,10 @@ namespace dxvk {
|
|||||||
uint32_t typeId = this->defFloatType(32);
|
uint32_t typeId = this->defFloatType(32);
|
||||||
uint32_t resultId = this->allocateId();
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
m_constDefs.putIns (spv::OpConstant, 4);
|
m_typeConstDefs.putIns (spv::OpConstant, 4);
|
||||||
m_constDefs.putWord (typeId);
|
m_typeConstDefs.putWord (typeId);
|
||||||
m_constDefs.putWord (resultId);
|
m_typeConstDefs.putWord (resultId);
|
||||||
m_constDefs.putFloat32(v);
|
m_typeConstDefs.putFloat32(v);
|
||||||
return resultId;
|
return resultId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,10 +190,10 @@ namespace dxvk {
|
|||||||
uint32_t typeId = this->defFloatType(64);
|
uint32_t typeId = this->defFloatType(64);
|
||||||
uint32_t resultId = this->allocateId();
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
m_constDefs.putIns (spv::OpConstant, 5);
|
m_typeConstDefs.putIns (spv::OpConstant, 5);
|
||||||
m_constDefs.putWord (typeId);
|
m_typeConstDefs.putWord (typeId);
|
||||||
m_constDefs.putWord (resultId);
|
m_typeConstDefs.putWord (resultId);
|
||||||
m_constDefs.putFloat64(v);
|
m_typeConstDefs.putFloat64(v);
|
||||||
return resultId;
|
return resultId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,16 +204,23 @@ namespace dxvk {
|
|||||||
const uint32_t* constIds) {
|
const uint32_t* constIds) {
|
||||||
uint32_t resultId = this->allocateId();
|
uint32_t resultId = this->allocateId();
|
||||||
|
|
||||||
m_constDefs.putIns (spv::OpConstantComposite, 3 + constCount);
|
m_typeConstDefs.putIns (spv::OpConstantComposite, 3 + constCount);
|
||||||
m_constDefs.putWord (typeId);
|
m_typeConstDefs.putWord (typeId);
|
||||||
m_constDefs.putWord (resultId);
|
m_typeConstDefs.putWord (resultId);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < constCount; i++)
|
for (uint32_t i = 0; i < constCount; i++)
|
||||||
m_constDefs.putWord(constIds[i]);
|
m_typeConstDefs.putWord(constIds[i]);
|
||||||
return resultId;
|
return resultId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::decorateBlock(uint32_t object) {
|
||||||
|
m_annotations.putIns (spv::OpDecorate, 3);
|
||||||
|
m_annotations.putWord (object);
|
||||||
|
m_annotations.putWord (spv::DecorationBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SpirvModule::decorateBuiltIn(
|
void SpirvModule::decorateBuiltIn(
|
||||||
uint32_t object,
|
uint32_t object,
|
||||||
spv::BuiltIn builtIn) {
|
spv::BuiltIn builtIn) {
|
||||||
@ -234,6 +251,18 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SpirvModule::memberDecorateBuiltIn(
|
||||||
|
uint32_t structId,
|
||||||
|
uint32_t memberId,
|
||||||
|
spv::BuiltIn builtIn) {
|
||||||
|
m_annotations.putIns (spv::OpMemberDecorate, 5);
|
||||||
|
m_annotations.putWord (structId);
|
||||||
|
m_annotations.putWord (memberId);
|
||||||
|
m_annotations.putWord (spv::DecorationBuiltIn);
|
||||||
|
m_annotations.putWord (builtIn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t SpirvModule::defVoidType() {
|
uint32_t SpirvModule::defVoidType() {
|
||||||
return this->defType(spv::OpTypeVoid, 0, nullptr);
|
return this->defType(spv::OpTypeVoid, 0, nullptr);
|
||||||
}
|
}
|
||||||
@ -493,7 +522,7 @@ namespace dxvk {
|
|||||||
// Since the type info is stored in the code buffer,
|
// Since the type info is stored in the code buffer,
|
||||||
// we can use the code buffer to look up type IDs as
|
// we can use the code buffer to look up type IDs as
|
||||||
// well. Result IDs are always stored as argument 1.
|
// well. Result IDs are always stored as argument 1.
|
||||||
for (auto ins : m_typeDefs) {
|
for (auto ins : m_typeConstDefs) {
|
||||||
bool match = ins.opCode() == op;
|
bool match = ins.opCode() == op;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < argCount && match; i++)
|
for (uint32_t i = 0; i < argCount && match; i++)
|
||||||
@ -505,11 +534,11 @@ namespace dxvk {
|
|||||||
|
|
||||||
// Type not yet declared, create a new one.
|
// Type not yet declared, create a new one.
|
||||||
uint32_t resultId = this->allocateId();
|
uint32_t resultId = this->allocateId();
|
||||||
m_typeDefs.putIns (op, 2 + argCount);
|
m_typeConstDefs.putIns (op, 2 + argCount);
|
||||||
m_typeDefs.putWord(resultId);
|
m_typeConstDefs.putWord(resultId);
|
||||||
|
|
||||||
for (uint32_t i = 0; i < argCount; i++)
|
for (uint32_t i = 0; i < argCount; i++)
|
||||||
m_typeDefs.putWord(argIds[i]);
|
m_typeConstDefs.putWord(argIds[i]);
|
||||||
return resultId;
|
return resultId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,6 +50,11 @@ namespace dxvk {
|
|||||||
uint32_t expressionId,
|
uint32_t expressionId,
|
||||||
const char* debugName);
|
const char* debugName);
|
||||||
|
|
||||||
|
void setDebugMemberName(
|
||||||
|
uint32_t structId,
|
||||||
|
uint32_t memberId,
|
||||||
|
const char* debugName);
|
||||||
|
|
||||||
uint32_t constBool(
|
uint32_t constBool(
|
||||||
bool v);
|
bool v);
|
||||||
|
|
||||||
@ -76,6 +81,9 @@ namespace dxvk {
|
|||||||
uint32_t constCount,
|
uint32_t constCount,
|
||||||
const uint32_t* constIds);
|
const uint32_t* constIds);
|
||||||
|
|
||||||
|
void decorateBlock(
|
||||||
|
uint32_t object);
|
||||||
|
|
||||||
void decorateBuiltIn(
|
void decorateBuiltIn(
|
||||||
uint32_t object,
|
uint32_t object,
|
||||||
spv::BuiltIn builtIn);
|
spv::BuiltIn builtIn);
|
||||||
@ -88,6 +96,11 @@ namespace dxvk {
|
|||||||
uint32_t object,
|
uint32_t object,
|
||||||
uint32_t location);
|
uint32_t location);
|
||||||
|
|
||||||
|
void memberDecorateBuiltIn(
|
||||||
|
uint32_t structId,
|
||||||
|
uint32_t memberId,
|
||||||
|
spv::BuiltIn builtIn);
|
||||||
|
|
||||||
uint32_t defVoidType();
|
uint32_t defVoidType();
|
||||||
|
|
||||||
uint32_t defBoolType();
|
uint32_t defBoolType();
|
||||||
@ -188,8 +201,7 @@ namespace dxvk {
|
|||||||
SpirvCodeBuffer m_execModeInfo;
|
SpirvCodeBuffer m_execModeInfo;
|
||||||
SpirvCodeBuffer m_debugNames;
|
SpirvCodeBuffer m_debugNames;
|
||||||
SpirvCodeBuffer m_annotations;
|
SpirvCodeBuffer m_annotations;
|
||||||
SpirvCodeBuffer m_typeDefs;
|
SpirvCodeBuffer m_typeConstDefs;
|
||||||
SpirvCodeBuffer m_constDefs;
|
|
||||||
SpirvCodeBuffer m_variables;
|
SpirvCodeBuffer m_variables;
|
||||||
SpirvCodeBuffer m_code;
|
SpirvCodeBuffer m_code;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user