2017-10-16 17:50:09 +02:00
|
|
|
#pragma once
|
|
|
|
|
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-10-16 17:50:09 +02:00
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
/**
|
|
|
|
* \brief Expression value
|
|
|
|
*
|
|
|
|
* Tracks the type and the SPIR-V variable
|
|
|
|
* ID when evaluating DXBC instructions.
|
|
|
|
*/
|
|
|
|
struct DxbcValue {
|
2017-12-13 15:32:54 +01:00
|
|
|
DxbcScalarType componentType = DxbcScalarType::Float32;
|
|
|
|
uint32_t componentCount = 0;
|
|
|
|
uint32_t valueId = 0;
|
|
|
|
};
|
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
/**
|
|
|
|
* \brief Variable pointer
|
|
|
|
*
|
|
|
|
* Stores the SPIR-V pointer ID and the
|
|
|
|
* type of the referenced variable. Used
|
|
|
|
* to access variables and resources.
|
|
|
|
*/
|
|
|
|
struct DxbcPointer {
|
2017-12-13 15:32:54 +01:00
|
|
|
DxbcScalarType componentType = DxbcScalarType::Float32;
|
|
|
|
uint32_t componentCount = 0;
|
|
|
|
uint32_t pointerId = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Constant buffer binding
|
|
|
|
*
|
|
|
|
* Stores information required to
|
|
|
|
* access a constant buffer.
|
|
|
|
*/
|
2017-12-14 12:53:53 +01:00
|
|
|
struct DxbcConstantBuffer {
|
2017-12-13 15:32:54 +01:00
|
|
|
uint32_t varId = 0;
|
|
|
|
uint32_t size = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Sampler binding
|
|
|
|
*
|
|
|
|
* Stores a sampler variable that can be
|
|
|
|
* used together with a texture resource.
|
|
|
|
*/
|
2017-12-14 12:53:53 +01:00
|
|
|
struct DxbcSampler {
|
2017-12-13 15:32:54 +01:00
|
|
|
uint32_t varId = 0;
|
|
|
|
uint32_t typeId = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Shader resource binding
|
|
|
|
*
|
|
|
|
* Stores a resource variable
|
|
|
|
* and associated type IDs.
|
|
|
|
*/
|
2017-12-14 12:53:53 +01:00
|
|
|
struct DxbcShaderResource {
|
2017-12-13 15:32:54 +01:00
|
|
|
uint32_t varId = 0;
|
|
|
|
uint32_t sampledTypeId = 0;
|
|
|
|
uint32_t textureTypeId = 0;
|
|
|
|
};
|
|
|
|
|
2017-10-16 17:50:09 +02:00
|
|
|
/**
|
2017-12-13 15:32:54 +01:00
|
|
|
* \brief System value mapping
|
2017-11-13 00:22:52 +01:00
|
|
|
*
|
2017-12-13 15:32:54 +01:00
|
|
|
* Maps a system value to a given set of
|
|
|
|
* components of an input or output register.
|
2017-10-16 17:50:09 +02:00
|
|
|
*/
|
2017-12-14 12:53:53 +01:00
|
|
|
struct DxbcSvMapping {
|
2017-12-13 15:32:54 +01:00
|
|
|
uint32_t regId;
|
|
|
|
DxbcRegMask regMask;
|
|
|
|
DxbcSystemValue sv;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Compiler error code
|
|
|
|
*
|
|
|
|
* Helps identify the type of error
|
|
|
|
* that may occur during compilation.
|
|
|
|
*/
|
|
|
|
enum class DxbcError {
|
|
|
|
sOk,
|
|
|
|
eInternal,
|
|
|
|
eInstructionFormat,
|
|
|
|
eInvalidOperand,
|
|
|
|
eInvalidOperandIndex,
|
|
|
|
eTypeMismatch,
|
|
|
|
eUnhandledOpcode,
|
|
|
|
eUnsupported,
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Operand index type
|
|
|
|
*
|
|
|
|
* Defines whether a register index
|
|
|
|
* is relative or constant.
|
|
|
|
*/
|
|
|
|
enum class DxbcIndexType {
|
|
|
|
Immediate, ///< Index is a constant value
|
|
|
|
Relative, ///< Index depends on a r# register
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Instruction operand index
|
|
|
|
*
|
|
|
|
* Stores the type of the index as well as the
|
|
|
|
* register (if relative) and the constant offset.
|
|
|
|
*/
|
|
|
|
struct DxbcInstOpIndex {
|
|
|
|
DxbcIndexType type = DxbcIndexType::Immediate;
|
|
|
|
uint32_t immediate = 0;
|
|
|
|
uint32_t tempRegId = 0;
|
|
|
|
uint32_t tempRegComponent = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Instruction operand
|
|
|
|
*
|
|
|
|
* Stores all information about a single
|
|
|
|
* operand, including the register index.
|
|
|
|
*/
|
|
|
|
struct DxbcInstOp {
|
|
|
|
DxbcOperandType type = DxbcOperandType::Temp;
|
|
|
|
DxbcOperandModifiers modifiers = 0;
|
|
|
|
uint32_t immediates[4] = { 0u, 0u, 0u, 0u };
|
|
|
|
|
|
|
|
uint32_t indexDim = 0;
|
|
|
|
DxbcInstOpIndex index[3];
|
|
|
|
|
|
|
|
uint32_t componentCount = 0;
|
|
|
|
DxbcRegMode componentMode = DxbcRegMode::Mask;
|
|
|
|
|
|
|
|
DxbcRegMask mask = { false, false, false, false };
|
|
|
|
DxbcRegSwizzle swizzle = { 0, 0, 0, 0 };
|
|
|
|
uint32_t select1 = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Decoded instruction
|
|
|
|
*
|
|
|
|
* Stores all information about a single
|
|
|
|
* instruction, including its operands.
|
|
|
|
*/
|
|
|
|
struct DxbcInst {
|
|
|
|
DxbcOpcode opcode = DxbcOpcode::Nop;
|
|
|
|
DxbcOpcodeControl control = 0;
|
|
|
|
DxbcInstFormat format;
|
|
|
|
DxbcInstOp operands[DxbcMaxOperandCount];
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Vertex shader-specific data
|
|
|
|
*/
|
|
|
|
struct DxbcVsSpecifics {
|
|
|
|
uint32_t functionId = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* \brief Pixel shader-specific data
|
|
|
|
*/
|
|
|
|
struct DxbcPsSpecifics {
|
|
|
|
uint32_t functionId = 0;
|
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
std::array<DxbcPointer, DxbcMaxInterfaceRegs> oregs;
|
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
|
|
|
|
* \returns An error code, or \c sOK
|
|
|
|
*/
|
|
|
|
DxbcError processInstruction(
|
2017-12-07 16:29:34 +01:00
|
|
|
const DxbcInstruction& 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-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-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-13 15:32:54 +01:00
|
|
|
////////////////////////////////////////////////////////
|
|
|
|
// Input/Output system value mappings. These will need
|
|
|
|
// to be set up before or after the main function runs.
|
2017-12-14 12:53:53 +01:00
|
|
|
std::vector<DxbcSvMapping> m_vSvs;
|
|
|
|
std::vector<DxbcSvMapping> m_oSvs;
|
2017-11-17 11:41:56 +01:00
|
|
|
|
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-13 15:32:54 +01:00
|
|
|
////////////////////////////////////////
|
|
|
|
// Data structures for each shader type
|
|
|
|
DxbcVsSpecifics m_vs;
|
|
|
|
DxbcPsSpecifics m_ps;
|
2017-12-10 20:01:38 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
//////////////////////////////
|
|
|
|
// Instruction class handlers
|
|
|
|
DxbcError handleDeclaration(
|
|
|
|
const DxbcInst& ins);
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
DxbcError handleControlFlow(
|
|
|
|
const DxbcInst& ins);
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
DxbcError handleTextureSample(
|
|
|
|
const DxbcInst& ins);
|
|
|
|
|
|
|
|
DxbcError handleVectorAlu(
|
|
|
|
const DxbcInst& ins);
|
|
|
|
|
|
|
|
DxbcError handleVectorDot(
|
|
|
|
const DxbcInst& ins);
|
|
|
|
|
2017-12-13 16:35:01 +01:00
|
|
|
DxbcError handleVectorSinCos(
|
|
|
|
const DxbcInst& ins);
|
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
///////////////////////
|
|
|
|
// Declaration methods
|
|
|
|
DxbcError declareGlobalFlags(
|
|
|
|
const DxbcInst& ins);
|
|
|
|
|
|
|
|
DxbcError declareTemps(
|
|
|
|
const DxbcInst& ins);
|
|
|
|
|
|
|
|
DxbcError declareInterfaceVar(
|
|
|
|
const DxbcInst& ins);
|
|
|
|
|
|
|
|
DxbcError declareConstantBuffer(
|
|
|
|
const DxbcInst& ins);
|
|
|
|
|
|
|
|
DxbcError declareSampler(
|
|
|
|
const DxbcInst& ins);
|
|
|
|
|
|
|
|
DxbcError declareResource(
|
|
|
|
const DxbcInst& ins);
|
|
|
|
|
|
|
|
DxbcError declareInputVar(
|
|
|
|
uint32_t regId,
|
|
|
|
uint32_t regDim,
|
|
|
|
DxbcRegMask regMask,
|
|
|
|
DxbcSystemValue sv,
|
|
|
|
DxbcInterpolationMode im);
|
|
|
|
|
|
|
|
DxbcError declareOutputVar(
|
|
|
|
uint32_t regId,
|
|
|
|
uint32_t regDim,
|
|
|
|
DxbcRegMask regMask,
|
|
|
|
DxbcSystemValue sv,
|
|
|
|
DxbcInterpolationMode im);
|
|
|
|
|
|
|
|
////////////////////////////////////
|
|
|
|
// Register manipulation operations
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcValue bitcastReg(
|
|
|
|
const DxbcValue& src,
|
2017-12-13 15:32:54 +01:00
|
|
|
DxbcScalarType type);
|
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcValue insertReg(
|
|
|
|
const DxbcValue& dst,
|
|
|
|
const DxbcValue& src,
|
2017-12-13 15:32:54 +01:00
|
|
|
DxbcRegMask mask);
|
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcValue extractReg(
|
|
|
|
const DxbcValue& src,
|
2017-12-13 15:32:54 +01:00
|
|
|
DxbcRegMask mask);
|
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcValue swizzleReg(
|
|
|
|
const DxbcValue& src,
|
2017-12-13 15:32:54 +01:00
|
|
|
const DxbcRegSwizzle& swizzle,
|
|
|
|
DxbcRegMask mask);
|
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcValue regVector(
|
|
|
|
const DxbcValue& src,
|
2017-12-13 15:32:54 +01:00
|
|
|
uint32_t size);
|
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcValue extendReg(
|
|
|
|
const DxbcValue& src,
|
2017-12-13 15:32:54 +01:00
|
|
|
uint32_t size);
|
|
|
|
|
|
|
|
////////////////////////////
|
|
|
|
// Operand modifier methods
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcValue applyOperandModifiers(
|
|
|
|
DxbcValue value,
|
2017-12-13 15:32:54 +01:00
|
|
|
DxbcOperandModifiers modifiers);
|
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcValue applyResultModifiers(
|
|
|
|
DxbcValue value,
|
2017-12-13 15:32:54 +01:00
|
|
|
DxbcOpcodeControl control);
|
|
|
|
|
|
|
|
/////////////////////////
|
|
|
|
// Load/Store operations
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcValue loadOp(
|
2017-12-13 15:32:54 +01:00
|
|
|
const DxbcInstOp& srcOp,
|
|
|
|
DxbcRegMask srcMask,
|
|
|
|
DxbcScalarType dstType);
|
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcValue loadImm32(
|
2017-12-13 15:32:54 +01:00
|
|
|
const DxbcInstOp& srcOp,
|
|
|
|
DxbcRegMask srcMask,
|
|
|
|
DxbcScalarType dstType);
|
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcValue loadRegister(
|
2017-12-13 15:32:54 +01:00
|
|
|
const DxbcInstOp& srcOp,
|
|
|
|
DxbcRegMask srcMask,
|
|
|
|
DxbcScalarType dstType);
|
|
|
|
|
|
|
|
void storeOp(
|
|
|
|
const DxbcInstOp& dstOp,
|
2017-12-14 12:53:53 +01:00
|
|
|
const DxbcValue& srcValue);
|
2017-12-13 15:32:54 +01:00
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcValue loadPtr(
|
|
|
|
const DxbcPointer& ptr);
|
2017-12-13 15:32:54 +01:00
|
|
|
|
|
|
|
void storePtr(
|
2017-12-14 12:53:53 +01:00
|
|
|
const DxbcPointer& ptr,
|
|
|
|
const DxbcValue& value,
|
2017-12-13 15:32:54 +01:00
|
|
|
DxbcRegMask mask);
|
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcValue loadIndex(
|
2017-12-13 15:32:54 +01:00
|
|
|
const DxbcInstOpIndex& idx);
|
|
|
|
|
|
|
|
///////////////////////////
|
|
|
|
// Operand pointer methods
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcPointer getOperandPtr(
|
2017-12-13 15:32:54 +01:00
|
|
|
const DxbcInstOp& op);
|
2017-12-10 12:08:20 +01:00
|
|
|
|
2017-12-14 12:53:53 +01:00
|
|
|
DxbcPointer getConstantBufferPtr(
|
2017-12-13 15:32:54 +01:00
|
|
|
const DxbcInstOp& op);
|
2017-12-08 17:08:26 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
/////////////////////////////////
|
|
|
|
// Shader initialization methods
|
|
|
|
void beginVertexShader(const Rc<DxbcIsgn>& isgn);
|
|
|
|
void beginPixelShader (const Rc<DxbcIsgn>& osgn);
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
/////////////////////////////
|
|
|
|
// Input preparation methods
|
|
|
|
void prepareVertexInputs();
|
|
|
|
void preparePixelInputs();
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
//////////////////////////////
|
|
|
|
// Output preparation methods
|
|
|
|
void prepareVertexOutputs();
|
|
|
|
void preparePixelOutputs();
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
///////////////////////////////
|
|
|
|
// Shader finalization methods
|
|
|
|
void endVertexShader();
|
|
|
|
void endPixelShader();
|
2017-12-08 17:08:26 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
///////////////////////////
|
|
|
|
// Type definition methods
|
|
|
|
uint32_t definePerVertexBlock();
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
uint32_t defineScalarType(
|
|
|
|
DxbcScalarType componentType);
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
uint32_t defineVectorType(
|
|
|
|
DxbcScalarType componentType,
|
|
|
|
uint32_t componentCount);
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
uint32_t definePointerType(
|
|
|
|
DxbcScalarType componentType,
|
|
|
|
uint32_t componentCount,
|
|
|
|
spv::StorageClass storageClass);
|
2017-11-16 01:30:17 +01:00
|
|
|
|
2017-12-13 15:32:54 +01:00
|
|
|
/////////////////////////
|
|
|
|
// DXBC decoding methods
|
|
|
|
DxbcError parseInstruction(
|
|
|
|
const DxbcInstruction& ins,
|
|
|
|
DxbcInst& out);
|
2017-10-16 19:53:17 +02:00
|
|
|
|
2017-10-16 17:50:09 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
}
|