2017-10-16 17:50:09 +02:00
|
|
|
#pragma once
|
|
|
|
|
2017-12-18 00:46:44 +01:00
|
|
|
#include <array>
|
|
|
|
#include <vector>
|
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
#include "../spirv/spirv_module.h"
|
|
|
|
|
|
|
|
#include "dxbc_chunk_isgn.h"
|
|
|
|
#include "dxbc_decoder.h"
|
|
|
|
#include "dxbc_defs.h"
|
2017-12-18 00:46:44 +01:00
|
|
|
#include "dxbc_names.h"
|
|
|
|
#include "dxbc_util.h"
|
2017-10-16 17:50:09 +02:00
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
/**
|
2017-12-18 00:46:44 +01:00
|
|
|
* \brief Vector type
|
2017-12-14 12:53:53 +01:00
|
|
|
*
|
2017-12-18 00:46:44 +01:00
|
|
|
* Convenience struct that stores a scalar
|
|
|
|
* type and a component count. The compiler
|
|
|
|
* can use this to generate SPIR-V types.
|
2017-12-14 12:53:53 +01:00
|
|
|
*/
|
2017-12-18 00:46:44 +01:00
|
|
|
struct DxbcVectorType {
|
|
|
|
DxbcScalarType ctype;
|
|
|
|
uint32_t ccount;
|
2017-12-13 15:32:54 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2017-12-18 00:46:44 +01:00
|
|
|
* \brief Register info
|
2017-12-13 15:32:54 +01:00
|
|
|
*
|
2017-12-18 00:46:44 +01:00
|
|
|
* Stores the vector type of a register and
|
|
|
|
* its storage class. The compiler can use
|
|
|
|
* this to generate SPIR-V pointer types.
|
2017-12-13 15:32:54 +01:00
|
|
|
*/
|
2017-12-18 00:46:44 +01:00
|
|
|
struct DxbcRegisterInfo {
|
|
|
|
DxbcVectorType type;
|
|
|
|
spv::StorageClass sclass;
|
2017-12-13 15:32:54 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2017-12-18 00:46:44 +01:00
|
|
|
* \brief Register value
|
2017-12-13 15:32:54 +01:00
|
|
|
*
|
2017-12-18 00:46:44 +01:00
|
|
|
* Stores a vector type and a SPIR-V ID that
|
|
|
|
* represents an intermediate value. This is
|
|
|
|
* used to track the type of such values.
|
2017-12-13 15:32:54 +01:00
|
|
|
*/
|
2017-12-18 00:46:44 +01:00
|
|
|
struct DxbcRegisterValue {
|
|
|
|
DxbcVectorType type;
|
|
|
|
uint32_t id;
|
2017-12-13 15:32:54 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2017-12-18 00:46:44 +01:00
|
|
|
* \brief Register pointer
|
2017-12-13 15:32:54 +01:00
|
|
|
*
|
2017-12-18 00:46:44 +01:00
|
|
|
* Stores a vector type and a SPIR-V ID that
|
|
|
|
* represents a pointer to such a vector. This
|
|
|
|
* can be used to load registers conveniently.
|
2017-12-13 15:32:54 +01:00
|
|
|
*/
|
2017-12-18 00:46:44 +01:00
|
|
|
struct DxbcRegisterPointer {
|
|
|
|
DxbcVectorType type;
|
|
|
|
uint32_t id;
|
2017-12-13 15:32:54 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2017-12-18 00:46:44 +01:00
|
|
|
* \brief Vertex shader-specific structure
|
2017-12-13 15:32:54 +01:00
|
|
|
*/
|
2017-12-18 00:46:44 +01:00
|
|
|
struct DxbcCompilerVsPart {
|
|
|
|
uint32_t functionId;
|
2017-12-13 15:32:54 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2017-12-18 00:46:44 +01:00
|
|
|
* \brief Pixel shader-specific structure
|
2017-12-13 15:32:54 +01:00
|
|
|
*/
|
2017-12-18 00:46:44 +01:00
|
|
|
struct DxbcCompilerPsPart {
|
|
|
|
uint32_t functionId;
|
|
|
|
std::array<DxbcVectorType, DxbcMaxInterfaceRegs> oTypes;
|
2017-12-13 15:32:54 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-12-18 11:53:28 +01:00
|
|
|
enum class DxbcCfgBlockType : uint32_t {
|
|
|
|
If, Loop,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct DxbcCfgBlockIf {
|
|
|
|
uint32_t labelIf;
|
|
|
|
uint32_t labelElse;
|
|
|
|
uint32_t labelEnd;
|
|
|
|
bool hadElse;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct DxbcCfgBlockLoop {
|
|
|
|
uint32_t labelHeader;
|
|
|
|
uint32_t labelBegin;
|
|
|
|
uint32_t labelContinue;
|
|
|
|
uint32_t labelBreak;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct DxbcCfgBlock {
|
|
|
|
DxbcCfgBlockType type;
|
|
|
|
|
|
|
|
union {
|
|
|
|
DxbcCfgBlockIf b_if;
|
|
|
|
DxbcCfgBlockLoop b_loop;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
/**
|
|
|
|
* \brief DXBC to SPIR-V shader compiler
|
|
|
|
*
|
|
|
|
* Processes instructions from a DXBC shader and creates
|
|
|
|
* a DXVK shader object, which contains the SPIR-V module
|
|
|
|
* and information about the shader resource bindings.
|
|
|
|
*/
|
2017-12-14 12:53:53 +01:00
|
|
|
class DxbcCompiler {
|
2017-10-16 17:50:09 +02:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcCompiler(
|
2017-12-07 16:29:34 +01:00
|
|
|
const DxbcProgramVersion& version,
|
|
|
|
const Rc<DxbcIsgn>& isgn,
|
|
|
|
const Rc<DxbcIsgn>& osgn);
|
2017-12-14 12:53:53 +01:00
|
|
|
~DxbcCompiler();
|
2017-10-16 17:50:09 +02:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
/**
|
|
|
|
* \brief Processes a single instruction
|
|
|
|
* \param [in] ins The instruction
|
|
|
|
*/
|
2017-12-18 00:46:44 +01:00
|
|
|
void processInstruction(
|
|
|
|
const DxbcShaderInstruction& ins);
|
2017-11-13 00:22:52 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
/**
|
|
|
|
* \brief Finalizes the shader
|
|
|
|
* \returns The final shader object
|
|
|
|
*/
|
2017-12-08 18:14:05 +01:00
|
|
|
Rc<DxvkShader> finalize();
|
2017-10-16 17:50:09 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
DxbcProgramVersion m_version;
|
|
|
|
SpirvModule m_module;
|
2017-11-13 00:22:52 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
Rc<DxbcIsgn> m_isgn;
|
|
|
|
Rc<DxbcIsgn> m_osgn;
|
2017-11-13 00:22:52 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// Resource slot description for the shader. This will
|
|
|
|
// be used to map D3D11 bindings to DXVK bindings.
|
|
|
|
std::vector<DxvkResourceSlot> m_resourceSlots;
|
2017-12-08 17:08:26 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
///////////////////////////////
|
|
|
|
// r# registers of type float4
|
|
|
|
std::vector<uint32_t> m_rRegs;
|
2017-12-10 10:34:18 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
// v# registers as defined by the shader. The type of each
|
|
|
|
// of these inputs is either float4 or an array of float4.
|
|
|
|
std::array<uint32_t, DxbcMaxInterfaceRegs> m_vRegs;
|
2017-12-18 00:46:44 +01:00
|
|
|
std::vector<DxbcSvMapping> m_vMappings;
|
2017-12-10 03:39:35 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
//////////////////////////////////////////////////////////
|
|
|
|
// o# registers as defined by the shader. In the fragment
|
|
|
|
// shader stage, these registers are typed by the signature,
|
|
|
|
// in all other stages, they are float4 registers or arrays.
|
|
|
|
std::array<uint32_t, DxbcMaxInterfaceRegs> m_oRegs;
|
2017-12-18 00:46:44 +01:00
|
|
|
std::vector<DxbcSvMapping> m_oMappings;
|
2017-11-13 00:22:52 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
//////////////////////////////////////////////////////
|
|
|
|
// Shader resource variables. These provide access to
|
|
|
|
// constant buffers, samplers, textures, and UAVs.
|
2017-12-14 12:53:53 +01:00
|
|
|
std::array<DxbcConstantBuffer, 16> m_constantBuffers;
|
|
|
|
std::array<DxbcSampler, 16> m_samplers;
|
|
|
|
std::array<DxbcShaderResource, 128> m_textures;
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-18 11:53:28 +01:00
|
|
|
///////////////////////////////////////////////
|
|
|
|
// Control flow information. Stores labels for
|
|
|
|
// currently active if-else blocks and loops.
|
|
|
|
std::vector<DxbcCfgBlock> m_controlFlowBlocks;
|
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
///////////////////////////////////////////////////////////
|
|
|
|
// Array of input values. Since v# registers are indexable
|
|
|
|
// in DXBC, we need to copy them into an array first.
|
|
|
|
uint32_t m_vArray = 0;
|
2017-12-11 14:36:35 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
////////////////////////////////////////////////////
|
|
|
|
// Per-vertex input and output blocks. Depending on
|
|
|
|
// the shader stage, these may be declared as arrays.
|
|
|
|
uint32_t m_perVertexIn = 0;
|
|
|
|
uint32_t m_perVertexOut = 0;
|
2017-12-09 01:49:30 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
///////////////////////////////////////////////////
|
|
|
|
// Entry point description - we'll need to declare
|
|
|
|
// the function ID and all input/output variables.
|
|
|
|
std::vector<uint32_t> m_entryPointInterfaces;
|
|
|
|
uint32_t m_entryPointId = 0;
|
2017-12-08 17:08:26 +01:00
|
|
|
|
2017-12-18 00:46:44 +01:00
|
|
|
///////////////////////////////////
|
|
|
|
// Shader-specific data structures
|
|
|
|
DxbcCompilerVsPart m_vs;
|
|
|
|
DxbcCompilerPsPart m_ps;
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////
|
|
|
|
// Shader interface and metadata declaration methods
|
2017-12-18 11:53:28 +01:00
|
|
|
void emitDcl(
|
|
|
|
const DxbcShaderInstruction& ins);
|
|
|
|
|
2017-12-18 00:46:44 +01:00
|
|
|
void emitDclGlobalFlags(
|
2017-12-18 11:53:28 +01:00
|
|
|
const DxbcShaderInstruction& ins);
|
2017-12-18 00:46:44 +01:00
|
|
|
|
|
|
|
void emitDclTemps(
|
2017-12-18 11:53:28 +01:00
|
|
|
const DxbcShaderInstruction& ins);
|
2017-12-18 00:46:44 +01:00
|
|
|
|
|
|
|
void emitDclInterfaceReg(
|
2017-12-18 11:53:28 +01:00
|
|
|
const DxbcShaderInstruction& ins);
|
2017-12-18 00:46:44 +01:00
|
|
|
|
|
|
|
void emitDclInput(
|
|
|
|
uint32_t regIdx,
|
|
|
|
uint32_t regDim,
|
|
|
|
DxbcRegMask regMask,
|
|
|
|
DxbcSystemValue sv,
|
|
|
|
DxbcInterpolationMode im);
|
|
|
|
|
|
|
|
void emitDclOutput(
|
|
|
|
uint32_t regIdx,
|
|
|
|
uint32_t regDim,
|
|
|
|
DxbcRegMask regMask,
|
|
|
|
DxbcSystemValue sv,
|
|
|
|
DxbcInterpolationMode im);
|
|
|
|
|
|
|
|
void emitDclConstantBuffer(
|
|
|
|
const DxbcShaderInstruction& ins);
|
|
|
|
|
|
|
|
void emitDclSampler(
|
|
|
|
const DxbcShaderInstruction& ins);
|
|
|
|
|
|
|
|
void emitDclResource(
|
|
|
|
const DxbcShaderInstruction& ins);
|
2017-12-10 20:01:38 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
//////////////////////////////
|
|
|
|
// Instruction class handlers
|
2017-12-18 00:46:44 +01:00
|
|
|
void emitVectorAlu(
|
|
|
|
const DxbcShaderInstruction& ins);
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-18 00:46:44 +01:00
|
|
|
void emitVectorCmov(
|
|
|
|
const DxbcShaderInstruction& ins);
|
2017-12-13 15:32:54 +01:00
|
|
|
|
2017-12-18 00:46:44 +01:00
|
|
|
void emitVectorCmp(
|
|
|
|
const DxbcShaderInstruction& ins);
|
2017-12-13 15:32:54 +01:00
|
|
|
|
2017-12-18 00:46:44 +01:00
|
|
|
void emitVectorDot(
|
|
|
|
const DxbcShaderInstruction& ins);
|
2017-12-10 12:08:20 +01:00
|
|
|
|
2017-12-18 00:46:44 +01:00
|
|
|
void emitVectorImul(
|
|
|
|
const DxbcShaderInstruction& ins);
|
2017-12-08 17:08:26 +01:00
|
|
|
|
2017-12-18 00:46:44 +01:00
|
|
|
void emitVectorSinCos(
|
|
|
|
const DxbcShaderInstruction& ins);
|
|
|
|
|
|
|
|
void emitSample(
|
|
|
|
const DxbcShaderInstruction& ins);
|
|
|
|
|
2017-12-18 11:53:28 +01:00
|
|
|
/////////////////////////////////////
|
|
|
|
// Control flow instruction handlers
|
|
|
|
void emitControlFlowIf(
|
2017-12-18 00:46:44 +01:00
|
|
|
const DxbcShaderInstruction& ins);
|
|
|
|
|
2017-12-18 11:53:28 +01:00
|
|
|
void emitControlFlowElse(
|
|
|
|
const DxbcShaderInstruction& ins);
|
|
|
|
|
|
|
|
void emitControlFlowEndIf(
|
|
|
|
const DxbcShaderInstruction& ins);
|
|
|
|
|
|
|
|
void emitControlFlowLoop(
|
|
|
|
const DxbcShaderInstruction& ins);
|
|
|
|
|
|
|
|
void emitControlFlowEndLoop(
|
|
|
|
const DxbcShaderInstruction& ins);
|
|
|
|
|
|
|
|
void emitControlFlowBreakc(
|
|
|
|
const DxbcShaderInstruction& ins);
|
|
|
|
|
|
|
|
void emitControlFlowRet(
|
|
|
|
const DxbcShaderInstruction& ins);
|
|
|
|
|
|
|
|
void emitControlFlow(
|
|
|
|
const DxbcShaderInstruction& ins);
|
2017-12-18 00:46:44 +01:00
|
|
|
|
|
|
|
/////////////////////////////////////////
|
|
|
|
// Generic register manipulation methods
|
|
|
|
DxbcRegisterValue emitRegisterBitcast(
|
|
|
|
DxbcRegisterValue srcValue,
|
|
|
|
DxbcScalarType dstType);
|
|
|
|
|
|
|
|
DxbcRegisterValue emitRegisterSwizzle(
|
|
|
|
DxbcRegisterValue value,
|
|
|
|
DxbcRegSwizzle swizzle,
|
|
|
|
DxbcRegMask writeMask);
|
|
|
|
|
|
|
|
DxbcRegisterValue emitRegisterExtract(
|
|
|
|
DxbcRegisterValue value,
|
|
|
|
DxbcRegMask mask);
|
|
|
|
|
|
|
|
DxbcRegisterValue emitRegisterInsert(
|
|
|
|
DxbcRegisterValue dstValue,
|
|
|
|
DxbcRegisterValue srcValue,
|
|
|
|
DxbcRegMask srcMask);
|
|
|
|
|
|
|
|
DxbcRegisterValue emitRegisterExtend(
|
|
|
|
DxbcRegisterValue value,
|
|
|
|
uint32_t size);
|
|
|
|
|
|
|
|
DxbcRegisterValue emitRegisterAbsolute(
|
|
|
|
DxbcRegisterValue value);
|
|
|
|
|
|
|
|
DxbcRegisterValue emitRegisterNegate(
|
|
|
|
DxbcRegisterValue value);
|
|
|
|
|
2017-12-18 11:53:28 +01:00
|
|
|
DxbcRegisterValue emitRegisterZeroTest(
|
|
|
|
DxbcRegisterValue value,
|
|
|
|
DxbcZeroTest test);
|
|
|
|
|
2017-12-18 00:46:44 +01:00
|
|
|
DxbcRegisterValue emitSrcOperandModifiers(
|
|
|
|
DxbcRegisterValue value,
|
|
|
|
DxbcRegModifiers modifiers);
|
|
|
|
|
|
|
|
DxbcRegisterValue emitDstOperandModifiers(
|
|
|
|
DxbcRegisterValue value,
|
|
|
|
DxbcOpModifiers modifiers);
|
|
|
|
|
|
|
|
////////////////////////
|
|
|
|
// Address load methods
|
|
|
|
DxbcRegisterPointer emitGetTempPtr(
|
|
|
|
const DxbcRegister& operand);
|
|
|
|
|
|
|
|
DxbcRegisterPointer emitGetInputPtr(
|
|
|
|
const DxbcRegister& operand);
|
|
|
|
|
|
|
|
DxbcRegisterPointer emitGetOutputPtr(
|
|
|
|
const DxbcRegister& operand);
|
|
|
|
|
|
|
|
DxbcRegisterPointer emitGetConstBufPtr(
|
|
|
|
const DxbcRegister& operand);
|
|
|
|
|
|
|
|
DxbcRegisterPointer emitGetOperandPtr(
|
|
|
|
const DxbcRegister& operand);
|
|
|
|
|
|
|
|
//////////////////////////////
|
|
|
|
// Operand load/store methods
|
|
|
|
DxbcRegisterValue emitIndexLoad(
|
|
|
|
DxbcRegIndex index);
|
|
|
|
|
|
|
|
DxbcRegisterValue emitValueLoad(
|
|
|
|
DxbcRegisterPointer ptr);
|
|
|
|
|
|
|
|
void emitValueStore(
|
|
|
|
DxbcRegisterPointer ptr,
|
|
|
|
DxbcRegisterValue value,
|
|
|
|
DxbcRegMask writeMask);
|
|
|
|
|
|
|
|
DxbcRegisterValue emitRegisterLoad(
|
|
|
|
const DxbcRegister& reg,
|
|
|
|
DxbcRegMask writeMask);
|
|
|
|
|
|
|
|
void emitRegisterStore(
|
|
|
|
const DxbcRegister& reg,
|
|
|
|
DxbcRegisterValue value);
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
/////////////////////////////
|
|
|
|
// Input preparation methods
|
2017-12-18 00:46:44 +01:00
|
|
|
void emitVsInputSetup();
|
|
|
|
void emitPsInputSetup();
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
//////////////////////////////
|
|
|
|
// Output preparation methods
|
2017-12-18 00:46:44 +01:00
|
|
|
void emitVsOutputSetup();
|
|
|
|
void emitPsOutputSetup();
|
|
|
|
|
|
|
|
/////////////////////////////////
|
|
|
|
// Shader initialization methods
|
|
|
|
void emitVsInit();
|
|
|
|
void emitPsInit();
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
///////////////////////////////
|
|
|
|
// Shader finalization methods
|
2017-12-18 00:46:44 +01:00
|
|
|
void emitVsFinalize();
|
|
|
|
void emitPsFinalize();
|
|
|
|
|
|
|
|
///////////////////////////////
|
|
|
|
// Variable definition methods
|
|
|
|
uint32_t emitNewVariable(
|
|
|
|
const DxbcRegisterInfo& info);
|
2017-12-08 17:08:26 +01:00
|
|
|
|
2017-12-18 11:53:28 +01:00
|
|
|
/////////////////////////////////////
|
|
|
|
// Control flow block search methods
|
|
|
|
DxbcCfgBlock* cfgFindLoopBlock();
|
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
///////////////////////////
|
|
|
|
// Type definition methods
|
2017-12-18 00:46:44 +01:00
|
|
|
uint32_t getScalarTypeId(
|
|
|
|
DxbcScalarType type);
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-18 00:46:44 +01:00
|
|
|
uint32_t getVectorTypeId(
|
|
|
|
const DxbcVectorType& type);
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-18 00:46:44 +01:00
|
|
|
uint32_t getPointerTypeId(
|
|
|
|
const DxbcRegisterInfo& type);
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-18 00:46:44 +01:00
|
|
|
uint32_t getPerVertexBlockId();
|
2017-10-16 19:53:17 +02:00
|
|
|
|
2017-10-16 17:50:09 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|