summaryrefslogtreecommitdiffstats
path: root/Graphics/ShaderTools
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2021-02-09 21:32:56 +0000
committerassiduous <assiduous@diligentgraphics.com>2021-03-19 00:31:35 +0000
commit757a17f471db4bf1cefab76106549beef1a89d63 (patch)
treef2d051826b3b009742951bbf8267091b594a22ca /Graphics/ShaderTools
parentmerged with resource_signature (diff)
downloadDiligentCore-757a17f471db4bf1cefab76106549beef1a89d63.tar.gz
DiligentCore-757a17f471db4bf1cefab76106549beef1a89d63.zip
remap resources in DXBC shader bytecode
Diffstat (limited to 'Graphics/ShaderTools')
-rw-r--r--Graphics/ShaderTools/src/DXBCUtils.cpp1426
1 files changed, 1387 insertions, 39 deletions
diff --git a/Graphics/ShaderTools/src/DXBCUtils.cpp b/Graphics/ShaderTools/src/DXBCUtils.cpp
index e65e0350..8398acfb 100644
--- a/Graphics/ShaderTools/src/DXBCUtils.cpp
+++ b/Graphics/ShaderTools/src/DXBCUtils.cpp
@@ -26,6 +26,8 @@
*/
#include <d3d11shader.h>
+#include <array>
+#include <vector>
#include "DXBCUtils.hpp"
#include "../../../ThirdParty/GPUOpenShaderUtils/DXBCChecksum.h"
@@ -94,25 +96,759 @@ struct ResourceBindingInfo51
};
static_assert(sizeof(ResourceBindingInfo51) == 40, "The size of SM51 resource binding info struct must be 40 bytes");
+enum PROGRAM_TYPE : Uint32
+{
+ PROGRAM_TYPE_PIXEL = 0,
+ PROGRAM_TYPE_VERTEX = 1,
+ PROGRAM_TYPE_COUNT_SM4,
+
+ PROGRAM_TYPE_GEOMETRY = 2,
+ PROGRAM_TYPE_HULL = 3,
+ PROGRAM_TYPE_DOMAIN = 4,
+ PROGRAM_TYPE_COMPUTE = 5,
+ PROGRAM_TYPE_COUNT_SM5,
+};
+
+struct ShaderChunkHeader : ChunkHeader
+{
+ Uint32 VersionMinor : 4;
+ Uint32 VersionMajor : 4;
+ Uint32 _Padding : 8;
+ PROGRAM_TYPE ProgramType : 16; // 2..3
+ Uint32 NumDWords; // 4..7, number of DWORDs in the chunk
+};
+static_assert(sizeof(ShaderChunkHeader) == 16, "The size of shader code header must be 16 bytes");
+
+// from d3d11TokenizedProgramFormat.hpp
+enum D3D10_SB_OPCODE_TYPE : Uint32
+{
+ D3D10_SB_OPCODE_ADD,
+ D3D10_SB_OPCODE_AND,
+ D3D10_SB_OPCODE_BREAK,
+ D3D10_SB_OPCODE_BREAKC,
+ D3D10_SB_OPCODE_CALL,
+ D3D10_SB_OPCODE_CALLC,
+ D3D10_SB_OPCODE_CASE,
+ D3D10_SB_OPCODE_CONTINUE,
+ D3D10_SB_OPCODE_CONTINUEC,
+ D3D10_SB_OPCODE_CUT,
+ D3D10_SB_OPCODE_DEFAULT,
+ D3D10_SB_OPCODE_DERIV_RTX,
+ D3D10_SB_OPCODE_DERIV_RTY,
+ D3D10_SB_OPCODE_DISCARD,
+ D3D10_SB_OPCODE_DIV,
+ D3D10_SB_OPCODE_DP2,
+ D3D10_SB_OPCODE_DP3,
+ D3D10_SB_OPCODE_DP4,
+ D3D10_SB_OPCODE_ELSE,
+ D3D10_SB_OPCODE_EMIT,
+ D3D10_SB_OPCODE_EMITTHENCUT,
+ D3D10_SB_OPCODE_ENDIF,
+ D3D10_SB_OPCODE_ENDLOOP,
+ D3D10_SB_OPCODE_ENDSWITCH,
+ D3D10_SB_OPCODE_EQ,
+ D3D10_SB_OPCODE_EXP,
+ D3D10_SB_OPCODE_FRC,
+ D3D10_SB_OPCODE_FTOI,
+ D3D10_SB_OPCODE_FTOU,
+ D3D10_SB_OPCODE_GE,
+ D3D10_SB_OPCODE_IADD,
+ D3D10_SB_OPCODE_IF,
+ D3D10_SB_OPCODE_IEQ,
+ D3D10_SB_OPCODE_IGE,
+ D3D10_SB_OPCODE_ILT,
+ D3D10_SB_OPCODE_IMAD,
+ D3D10_SB_OPCODE_IMAX,
+ D3D10_SB_OPCODE_IMIN,
+ D3D10_SB_OPCODE_IMUL,
+ D3D10_SB_OPCODE_INE,
+ D3D10_SB_OPCODE_INEG,
+ D3D10_SB_OPCODE_ISHL,
+ D3D10_SB_OPCODE_ISHR,
+ D3D10_SB_OPCODE_ITOF,
+ D3D10_SB_OPCODE_LABEL,
+ D3D10_SB_OPCODE_LD,
+ D3D10_SB_OPCODE_LD_MS,
+ D3D10_SB_OPCODE_LOG,
+ D3D10_SB_OPCODE_LOOP,
+ D3D10_SB_OPCODE_LT,
+ D3D10_SB_OPCODE_MAD,
+ D3D10_SB_OPCODE_MIN,
+ D3D10_SB_OPCODE_MAX,
+ D3D10_SB_OPCODE_CUSTOMDATA,
+ D3D10_SB_OPCODE_MOV,
+ D3D10_SB_OPCODE_MOVC,
+ D3D10_SB_OPCODE_MUL,
+ D3D10_SB_OPCODE_NE,
+ D3D10_SB_OPCODE_NOP,
+ D3D10_SB_OPCODE_NOT,
+ D3D10_SB_OPCODE_OR,
+ D3D10_SB_OPCODE_RESINFO,
+ D3D10_SB_OPCODE_RET,
+ D3D10_SB_OPCODE_RETC,
+ D3D10_SB_OPCODE_ROUND_NE,
+ D3D10_SB_OPCODE_ROUND_NI,
+ D3D10_SB_OPCODE_ROUND_PI,
+ D3D10_SB_OPCODE_ROUND_Z,
+ D3D10_SB_OPCODE_RSQ,
+ D3D10_SB_OPCODE_SAMPLE,
+ D3D10_SB_OPCODE_SAMPLE_C,
+ D3D10_SB_OPCODE_SAMPLE_C_LZ,
+ D3D10_SB_OPCODE_SAMPLE_L,
+ D3D10_SB_OPCODE_SAMPLE_D,
+ D3D10_SB_OPCODE_SAMPLE_B,
+ D3D10_SB_OPCODE_SQRT,
+ D3D10_SB_OPCODE_SWITCH,
+ D3D10_SB_OPCODE_SINCOS,
+ D3D10_SB_OPCODE_UDIV,
+ D3D10_SB_OPCODE_ULT,
+ D3D10_SB_OPCODE_UGE,
+ D3D10_SB_OPCODE_UMUL,
+ D3D10_SB_OPCODE_UMAD,
+ D3D10_SB_OPCODE_UMAX,
+ D3D10_SB_OPCODE_UMIN,
+ D3D10_SB_OPCODE_USHR,
+ D3D10_SB_OPCODE_UTOF,
+ D3D10_SB_OPCODE_XOR,
+ D3D10_SB_OPCODE_DCL_RESOURCE, // DCL* opcodes have
+ D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER, // custom operand formats.
+ D3D10_SB_OPCODE_DCL_SAMPLER,
+ D3D10_SB_OPCODE_DCL_INDEX_RANGE,
+ D3D10_SB_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY,
+ D3D10_SB_OPCODE_DCL_GS_INPUT_PRIMITIVE,
+ D3D10_SB_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT,
+ D3D10_SB_OPCODE_DCL_INPUT,
+ D3D10_SB_OPCODE_DCL_INPUT_SGV,
+ D3D10_SB_OPCODE_DCL_INPUT_SIV,
+ D3D10_SB_OPCODE_DCL_INPUT_PS,
+ D3D10_SB_OPCODE_DCL_INPUT_PS_SGV,
+ D3D10_SB_OPCODE_DCL_INPUT_PS_SIV,
+ D3D10_SB_OPCODE_DCL_OUTPUT,
+ D3D10_SB_OPCODE_DCL_OUTPUT_SGV,
+ D3D10_SB_OPCODE_DCL_OUTPUT_SIV,
+ D3D10_SB_OPCODE_DCL_TEMPS,
+ D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP,
+ D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS,
+
+ // -----------------------------------------------
+
+ // This marks the end of D3D10.0 opcodes
+ D3D10_SB_OPCODE_RESERVED0,
+
+ // ---------- DX 10.1 op codes---------------------
+
+ D3D10_1_SB_OPCODE_LOD,
+ D3D10_1_SB_OPCODE_GATHER4,
+ D3D10_1_SB_OPCODE_SAMPLE_POS,
+ D3D10_1_SB_OPCODE_SAMPLE_INFO,
+
+ // -----------------------------------------------
+
+ // This marks the end of D3D10.1 opcodes
+ D3D10_1_SB_OPCODE_RESERVED1,
+
+ // ---------- DX 11 op codes---------------------
+ D3D11_SB_OPCODE_HS_DECLS, // token marks beginning of HS sub-shader
+ D3D11_SB_OPCODE_HS_CONTROL_POINT_PHASE, // token marks beginning of HS sub-shader
+ D3D11_SB_OPCODE_HS_FORK_PHASE, // token marks beginning of HS sub-shader
+ D3D11_SB_OPCODE_HS_JOIN_PHASE, // token marks beginning of HS sub-shader
+
+ D3D11_SB_OPCODE_EMIT_STREAM,
+ D3D11_SB_OPCODE_CUT_STREAM,
+ D3D11_SB_OPCODE_EMITTHENCUT_STREAM,
+ D3D11_SB_OPCODE_INTERFACE_CALL,
+
+ D3D11_SB_OPCODE_BUFINFO,
+ D3D11_SB_OPCODE_DERIV_RTX_COARSE,
+ D3D11_SB_OPCODE_DERIV_RTX_FINE,
+ D3D11_SB_OPCODE_DERIV_RTY_COARSE,
+ D3D11_SB_OPCODE_DERIV_RTY_FINE,
+ D3D11_SB_OPCODE_GATHER4_C,
+ D3D11_SB_OPCODE_GATHER4_PO,
+ D3D11_SB_OPCODE_GATHER4_PO_C,
+ D3D11_SB_OPCODE_RCP,
+ D3D11_SB_OPCODE_F32TOF16,
+ D3D11_SB_OPCODE_F16TOF32,
+ D3D11_SB_OPCODE_UADDC,
+ D3D11_SB_OPCODE_USUBB,
+ D3D11_SB_OPCODE_COUNTBITS,
+ D3D11_SB_OPCODE_FIRSTBIT_HI,
+ D3D11_SB_OPCODE_FIRSTBIT_LO,
+ D3D11_SB_OPCODE_FIRSTBIT_SHI,
+ D3D11_SB_OPCODE_UBFE,
+ D3D11_SB_OPCODE_IBFE,
+ D3D11_SB_OPCODE_BFI,
+ D3D11_SB_OPCODE_BFREV,
+ D3D11_SB_OPCODE_SWAPC,
+
+ D3D11_SB_OPCODE_DCL_STREAM,
+ D3D11_SB_OPCODE_DCL_FUNCTION_BODY,
+ D3D11_SB_OPCODE_DCL_FUNCTION_TABLE,
+ D3D11_SB_OPCODE_DCL_INTERFACE,
+
+ D3D11_SB_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT,
+ D3D11_SB_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT,
+ D3D11_SB_OPCODE_DCL_TESS_DOMAIN,
+ D3D11_SB_OPCODE_DCL_TESS_PARTITIONING,
+ D3D11_SB_OPCODE_DCL_TESS_OUTPUT_PRIMITIVE,
+ D3D11_SB_OPCODE_DCL_HS_MAX_TESSFACTOR,
+ D3D11_SB_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT,
+ D3D11_SB_OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT,
+
+ D3D11_SB_OPCODE_DCL_THREAD_GROUP,
+ D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED,
+ D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW,
+ D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED,
+ D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW,
+ D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED,
+ D3D11_SB_OPCODE_DCL_RESOURCE_RAW,
+ D3D11_SB_OPCODE_DCL_RESOURCE_STRUCTURED,
+ D3D11_SB_OPCODE_LD_UAV_TYPED,
+ D3D11_SB_OPCODE_STORE_UAV_TYPED,
+ D3D11_SB_OPCODE_LD_RAW,
+ D3D11_SB_OPCODE_STORE_RAW,
+ D3D11_SB_OPCODE_LD_STRUCTURED,
+ D3D11_SB_OPCODE_STORE_STRUCTURED,
+ D3D11_SB_OPCODE_ATOMIC_AND,
+ D3D11_SB_OPCODE_ATOMIC_OR,
+ D3D11_SB_OPCODE_ATOMIC_XOR,
+ D3D11_SB_OPCODE_ATOMIC_CMP_STORE,
+ D3D11_SB_OPCODE_ATOMIC_IADD,
+ D3D11_SB_OPCODE_ATOMIC_IMAX,
+ D3D11_SB_OPCODE_ATOMIC_IMIN,
+ D3D11_SB_OPCODE_ATOMIC_UMAX,
+ D3D11_SB_OPCODE_ATOMIC_UMIN,
+ D3D11_SB_OPCODE_IMM_ATOMIC_ALLOC,
+ D3D11_SB_OPCODE_IMM_ATOMIC_CONSUME,
+ D3D11_SB_OPCODE_IMM_ATOMIC_IADD,
+ D3D11_SB_OPCODE_IMM_ATOMIC_AND,
+ D3D11_SB_OPCODE_IMM_ATOMIC_OR,
+ D3D11_SB_OPCODE_IMM_ATOMIC_XOR,
+ D3D11_SB_OPCODE_IMM_ATOMIC_EXCH,
+ D3D11_SB_OPCODE_IMM_ATOMIC_CMP_EXCH,
+ D3D11_SB_OPCODE_IMM_ATOMIC_IMAX,
+ D3D11_SB_OPCODE_IMM_ATOMIC_IMIN,
+ D3D11_SB_OPCODE_IMM_ATOMIC_UMAX,
+ D3D11_SB_OPCODE_IMM_ATOMIC_UMIN,
+ D3D11_SB_OPCODE_SYNC,
+
+ D3D11_SB_OPCODE_DADD,
+ D3D11_SB_OPCODE_DMAX,
+ D3D11_SB_OPCODE_DMIN,
+ D3D11_SB_OPCODE_DMUL,
+ D3D11_SB_OPCODE_DEQ,
+ D3D11_SB_OPCODE_DGE,
+ D3D11_SB_OPCODE_DLT,
+ D3D11_SB_OPCODE_DNE,
+ D3D11_SB_OPCODE_DMOV,
+ D3D11_SB_OPCODE_DMOVC,
+ D3D11_SB_OPCODE_DTOF,
+ D3D11_SB_OPCODE_FTOD,
+
+ D3D11_SB_OPCODE_EVAL_SNAPPED,
+ D3D11_SB_OPCODE_EVAL_SAMPLE_INDEX,
+ D3D11_SB_OPCODE_EVAL_CENTROID,
+
+ D3D11_SB_OPCODE_DCL_GS_INSTANCE_COUNT,
+
+ D3D11_SB_OPCODE_ABORT,
+ D3D11_SB_OPCODE_DEBUG_BREAK,
+
+ // -----------------------------------------------
+
+ // This marks the end of D3D11.0 opcodes
+ D3D11_SB_OPCODE_RESERVED0,
+
+ D3D11_1_SB_OPCODE_DDIV,
+ D3D11_1_SB_OPCODE_DFMA,
+ D3D11_1_SB_OPCODE_DRCP,
+
+ D3D11_1_SB_OPCODE_MSAD,
+
+ D3D11_1_SB_OPCODE_DTOI,
+ D3D11_1_SB_OPCODE_DTOU,
+ D3D11_1_SB_OPCODE_ITOD,
+ D3D11_1_SB_OPCODE_UTOD,
+
+ // -----------------------------------------------
+
+ // This marks the end of D3D11.1 opcodes
+ D3D11_1_SB_OPCODE_RESERVED0,
+
+ D3DWDDM1_3_SB_OPCODE_GATHER4_FEEDBACK,
+ D3DWDDM1_3_SB_OPCODE_GATHER4_C_FEEDBACK,
+ D3DWDDM1_3_SB_OPCODE_GATHER4_PO_FEEDBACK,
+ D3DWDDM1_3_SB_OPCODE_GATHER4_PO_C_FEEDBACK,
+ D3DWDDM1_3_SB_OPCODE_LD_FEEDBACK,
+ D3DWDDM1_3_SB_OPCODE_LD_MS_FEEDBACK,
+ D3DWDDM1_3_SB_OPCODE_LD_UAV_TYPED_FEEDBACK,
+ D3DWDDM1_3_SB_OPCODE_LD_RAW_FEEDBACK,
+ D3DWDDM1_3_SB_OPCODE_LD_STRUCTURED_FEEDBACK,
+ D3DWDDM1_3_SB_OPCODE_SAMPLE_L_FEEDBACK,
+ D3DWDDM1_3_SB_OPCODE_SAMPLE_C_LZ_FEEDBACK,
+
+ D3DWDDM1_3_SB_OPCODE_SAMPLE_CLAMP_FEEDBACK,
+ D3DWDDM1_3_SB_OPCODE_SAMPLE_B_CLAMP_FEEDBACK,
+ D3DWDDM1_3_SB_OPCODE_SAMPLE_D_CLAMP_FEEDBACK,
+ D3DWDDM1_3_SB_OPCODE_SAMPLE_C_CLAMP_FEEDBACK,
+
+ D3DWDDM1_3_SB_OPCODE_CHECK_ACCESS_FULLY_MAPPED,
+
+ // -----------------------------------------------
+
+ // This marks the end of WDDM 1.3 opcodes
+ D3DWDDM1_3_SB_OPCODE_RESERVED0,
+
+ D3D10_SB_NUM_OPCODES // Should be the last entry
+
+};
+
+// from d3d11TokenizedProgramFormat.hpp
+enum D3D10_SB_OPERAND_NUM_COMPONENTS : Uint32
+{
+ D3D10_SB_OPERAND_0_COMPONENT = 0,
+ D3D10_SB_OPERAND_1_COMPONENT = 1,
+ D3D10_SB_OPERAND_4_COMPONENT = 2,
+ D3D10_SB_OPERAND_N_COMPONENT = 3 // unused for now
+};
+
+// from d3d11TokenizedProgramFormat.hpp
+enum D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE : Uint32
+{
+ D3D10_SB_OPERAND_4_COMPONENT_MASK_MODE = 0, // mask 4 components
+ D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_MODE = 1, // swizzle 4 components
+ D3D10_SB_OPERAND_4_COMPONENT_SELECT_1_MODE = 2, // select 1 of 4 components
+};
+
+// from d3d11TokenizedProgramFormat.hpp
+enum D3D10_SB_OPERAND_TYPE : Uint32
+{
+ D3D10_SB_OPERAND_TYPE_TEMP = 0, // Temporary Register File
+ D3D10_SB_OPERAND_TYPE_INPUT = 1, // General Input Register File
+ D3D10_SB_OPERAND_TYPE_OUTPUT = 2, // General Output Register File
+ D3D10_SB_OPERAND_TYPE_INDEXABLE_TEMP = 3, // Temporary Register File (indexable)
+ D3D10_SB_OPERAND_TYPE_IMMEDIATE32 = 4, // 32bit/component immediate value(s)
+ // If for example, operand token bits
+ // [01:00]==D3D10_SB_OPERAND_4_COMPONENT,
+ // this means that the operand type:
+ // D3D10_SB_OPERAND_TYPE_IMMEDIATE32
+ // results in 4 additional 32bit
+ // DWORDS present for the operand.
+ D3D10_SB_OPERAND_TYPE_IMMEDIATE64 = 5, // 64bit/comp.imm.val(s)HI:LO
+ D3D10_SB_OPERAND_TYPE_SAMPLER = 6, // Reference to sampler state
+ D3D10_SB_OPERAND_TYPE_RESOURCE = 7, // Reference to memory resource (e.g. texture)
+ D3D10_SB_OPERAND_TYPE_CONSTANT_BUFFER = 8, // Reference to constant buffer
+ D3D10_SB_OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER = 9, // Reference to immediate constant buffer
+ D3D10_SB_OPERAND_TYPE_LABEL = 10, // Label
+ D3D10_SB_OPERAND_TYPE_INPUT_PRIMITIVEID = 11, // Input primitive ID
+ D3D10_SB_OPERAND_TYPE_OUTPUT_DEPTH = 12, // Output Depth
+ D3D10_SB_OPERAND_TYPE_NULL = 13, // Null register, used to discard results of operations
+ // Below Are operands new in DX 10.1
+ D3D10_SB_OPERAND_TYPE_RASTERIZER = 14, // DX10.1 Rasterizer register, used to denote the depth/stencil and render target resources
+ D3D10_SB_OPERAND_TYPE_OUTPUT_COVERAGE_MASK = 15, // DX10.1 PS output MSAA coverage mask (scalar)
+ // Below Are operands new in DX 11
+ D3D11_SB_OPERAND_TYPE_STREAM = 16, // Reference to GS stream output resource
+ D3D11_SB_OPERAND_TYPE_FUNCTION_BODY = 17, // Reference to a function definition
+ D3D11_SB_OPERAND_TYPE_FUNCTION_TABLE = 18, // Reference to a set of functions used by a class
+ D3D11_SB_OPERAND_TYPE_INTERFACE = 19, // Reference to an interface
+ D3D11_SB_OPERAND_TYPE_FUNCTION_INPUT = 20, // Reference to an input parameter to a function
+ D3D11_SB_OPERAND_TYPE_FUNCTION_OUTPUT = 21, // Reference to an output parameter to a function
+ D3D11_SB_OPERAND_TYPE_OUTPUT_CONTROL_POINT_ID = 22, // HS Control Point phase input saying which output control point ID this is
+ D3D11_SB_OPERAND_TYPE_INPUT_FORK_INSTANCE_ID = 23, // HS Fork Phase input instance ID
+ D3D11_SB_OPERAND_TYPE_INPUT_JOIN_INSTANCE_ID = 24, // HS Join Phase input instance ID
+ D3D11_SB_OPERAND_TYPE_INPUT_CONTROL_POINT = 25, // HS Fork+Join, DS phase input control points (array of them)
+ D3D11_SB_OPERAND_TYPE_OUTPUT_CONTROL_POINT = 26, // HS Fork+Join phase output control points (array of them)
+ D3D11_SB_OPERAND_TYPE_INPUT_PATCH_CONSTANT = 27, // DS+HSJoin Input Patch Constants (array of them)
+ D3D11_SB_OPERAND_TYPE_INPUT_DOMAIN_POINT = 28, // DS Input Domain point
+ D3D11_SB_OPERAND_TYPE_THIS_POINTER = 29, // Reference to an interface this pointer
+ D3D11_SB_OPERAND_TYPE_UNORDERED_ACCESS_VIEW = 30, // Reference to UAV u#
+ D3D11_SB_OPERAND_TYPE_THREAD_GROUP_SHARED_MEMORY = 31, // Reference to Thread Group Shared Memory g#
+ D3D11_SB_OPERAND_TYPE_INPUT_THREAD_ID = 32, // Compute Shader Thread ID
+ D3D11_SB_OPERAND_TYPE_INPUT_THREAD_GROUP_ID = 33, // Compute Shader Thread Group ID
+ D3D11_SB_OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP = 34, // Compute Shader Thread ID In Thread Group
+ D3D11_SB_OPERAND_TYPE_INPUT_COVERAGE_MASK = 35, // Pixel shader coverage mask input
+ D3D11_SB_OPERAND_TYPE_INPUT_THREAD_ID_IN_GROUP_FLATTENED = 36, // Compute Shader Thread ID In Group Flattened to a 1D value.
+ D3D11_SB_OPERAND_TYPE_INPUT_GS_INSTANCE_ID = 37, // Input GS instance ID
+ D3D11_SB_OPERAND_TYPE_OUTPUT_DEPTH_GREATER_EQUAL = 38, // Output Depth, forced to be greater than or equal than current depth
+ D3D11_SB_OPERAND_TYPE_OUTPUT_DEPTH_LESS_EQUAL = 39, // Output Depth, forced to be less than or equal to current depth
+ D3D11_SB_OPERAND_TYPE_CYCLE_COUNTER = 40, // Cycle counter
+
+ D3D11_SB_NUM_OPERANDS,
+};
+
+// from d3d11TokenizedProgramFormat.hpp
+enum D3D10_SB_OPERAND_INDEX_DIMENSION : Uint32
+{
+ D3D10_SB_OPERAND_INDEX_0D = 0, // e.g. Position
+ D3D10_SB_OPERAND_INDEX_1D = 1, // Most common. e.g. Temp registers.
+ D3D10_SB_OPERAND_INDEX_2D = 2, // e.g. Geometry Program Input registers.
+ D3D10_SB_OPERAND_INDEX_3D = 3, // 3D rarely if ever used.
+};
+
+// from d3d11TokenizedProgramFormat.hpp
+enum D3D10_SB_OPERAND_INDEX_REPRESENTATION : Uint32
+{
+ D3D10_SB_OPERAND_INDEX_IMMEDIATE32 = 0, // Extra DWORD
+ D3D10_SB_OPERAND_INDEX_IMMEDIATE64 = 1, // 2 Extra DWORDs
+ // (HI32:LO32)
+ D3D10_SB_OPERAND_INDEX_RELATIVE = 2, // Extra operand
+ D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE = 3, // Extra DWORD followed by
+ // extra operand
+ D3D10_SB_OPERAND_INDEX_IMMEDIATE64_PLUS_RELATIVE = 4, // 2 Extra DWORDS
+ // (HI32:LO32) followed
+ // by extra operand
+};
+
+// standard opcode token
+struct OpcodeToken
+{
+ D3D10_SB_OPCODE_TYPE OpcodeType : 11; // bits 0..10
+ Uint32 Controls : 13; // bits 11..23, Opcode-Specific Controls
+ Uint32 OpcodeLength : 7; // bita 24..30
+ Uint32 Extended : 1; // bit 31, 1 if opcode is “extended”, otherwise 0
+};
+static_assert(sizeof(OpcodeToken) == 4, "");
+
+struct OperandToken
+{
+ D3D10_SB_OPERAND_NUM_COMPONENTS NumComponents : 2; // 0..1
+ D3D10_SB_OPERAND_4_COMPONENT_SELECTION_MODE CompSelection : 2; // 2..3
+ Uint32 CompMask : 8; // 4..11
+ D3D10_SB_OPERAND_TYPE OperandType : 8; // 12..19
+ D3D10_SB_OPERAND_INDEX_DIMENSION IndexDim : 2; // 20..21
+ D3D10_SB_OPERAND_INDEX_REPRESENTATION OperandIndex1D : 3; // 22..24
+ D3D10_SB_OPERAND_INDEX_REPRESENTATION OperandIndex2D : 3; // 25..27
+ D3D10_SB_OPERAND_INDEX_REPRESENTATION OperandIndex3D : 3; // 28..30
+ Uint32 Extended : 1; // 31
+};
+static_assert(sizeof(OperandToken) == 4, "");
+
+// from d3d11TokenizedProgramFormat.hpp
+enum D3D10_SB_CUSTOMDATA_CLASS
+{
+ D3D10_SB_CUSTOMDATA_COMMENT = 0,
+ D3D10_SB_CUSTOMDATA_DEBUGINFO,
+ D3D10_SB_CUSTOMDATA_OPAQUE,
+ D3D10_SB_CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER,
+ D3D11_SB_CUSTOMDATA_SHADER_MESSAGE,
+ D3D11_SB_CUSTOMDATA_SHADER_CLIP_PLANE_CONSTANT_MAPPINGS_FOR_DX9,
+};
+
+enum SHADER_RES_TYPE : Uint32
+{
+ SHADER_RES_TYPE_CBUFFER = 0, // D3D10_SB_OPERAND_TYPE_CONSTANT_BUFFER, D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER
+ SHADER_RES_TYPE_TEXTURE = 1, // D3D10_SB_OPERAND_TYPE_RESOURCE, D3D10_SB_OPCODE_DCL_RESOURCE, D3D11_SB_OPCODE_DCL_RESOURCE_RAW, D3D11_SB_OPCODE_DCL_RESOURCE_STRUCTURED
+ SHADER_RES_TYPE_SAMPLER = 2, // D3D10_SB_OPERAND_TYPE_SAMPLER, D3D10_SB_OPCODE_DCL_SAMPLER
+ SHADER_RES_TYPE_UAV = 3, // D3D11_SB_OPERAND_TYPE_UNORDERED_ACCESS_VIEW, D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED, D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW, D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED
+ SHADER_RES_TYPE_COUNT,
+};
+
+struct ResInfo
+{
+ DXBCUtils::BindInfo const* Bind;
+ Uint32 BindCount;
+
+ ResInfo(DXBCUtils::BindInfo const* _Bind, Uint32 _BindCount) :
+ Bind{_Bind}, BindCount{_BindCount}
+ {}
+};
+
+using ResourceBindingPerType = std::array<std::vector<ResInfo>, SHADER_RES_TYPE_COUNT + 1>;
+
+
#define FOURCC(a, b, c, d) (Uint32{(d) << 24} | Uint32{(c) << 16} | Uint32{(b) << 8} | Uint32{a})
constexpr Uint32 DXBCFourCC = FOURCC('D', 'X', 'B', 'C');
-constexpr Uint32 RDEFFourCC = FOURCC('R', 'D', 'E', 'F');
+constexpr Uint32 RDEFFourCC = FOURCC('R', 'D', 'E', 'F'); // Resource definition. Describes constant buffers and resource bindings.
+constexpr Uint32 SHDRFourCC = FOURCC('S', 'H', 'D', 'R'); // Shader (SM4)
+constexpr Uint32 SHEXFourCC = FOURCC('S', 'H', 'E', 'X'); // Shader (SM5)
+
+
+SHADER_RES_TYPE ToResType(D3D_SHADER_INPUT_TYPE InputType)
+{
+ switch (InputType)
+ {
+ case D3D_SIT_CBUFFER:
+ return SHADER_RES_TYPE_CBUFFER;
+ case D3D_SIT_SAMPLER:
+ return SHADER_RES_TYPE_SAMPLER;
+
+ case D3D_SIT_TBUFFER:
+ case D3D_SIT_TEXTURE:
+ case D3D_SIT_STRUCTURED:
+ case D3D_SIT_BYTEADDRESS:
+ return SHADER_RES_TYPE_TEXTURE;
+
+ case D3D_SIT_UAV_RWSTRUCTURED:
+ case D3D_SIT_UAV_RWTYPED:
+ case D3D_SIT_UAV_RWBYTEADDRESS:
+ case D3D_SIT_UAV_APPEND_STRUCTURED:
+ case D3D_SIT_UAV_CONSUME_STRUCTURED:
+ case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER:
+ return SHADER_RES_TYPE_UAV;
+
+ default:
+ UNEXPECTED("Unsupported shader input type");
+ return SHADER_RES_TYPE_COUNT;
+ }
+}
-inline bool PatchSpace(ResourceBindingInfo51& Res, Uint32 Space)
+Uint32 GetNumOperands(D3D10_SB_OPCODE_TYPE Opcode)
{
- Res.Space = Space;
+ switch (Opcode)
+ {
+ case D3D10_SB_OPCODE_ADD: return 3;
+ case D3D10_SB_OPCODE_AND: return 3;
+ case D3D10_SB_OPCODE_BREAK: return 0;
+ case D3D10_SB_OPCODE_BREAKC: return 1;
+ case D3D10_SB_OPCODE_CALL: return 1;
+ case D3D10_SB_OPCODE_CALLC: return 2;
+ case D3D10_SB_OPCODE_CONTINUE: return 0;
+ case D3D10_SB_OPCODE_CONTINUEC: return 1;
+ case D3D10_SB_OPCODE_CASE: return 1;
+ case D3D10_SB_OPCODE_CUT: return 0;
+ case D3D10_SB_OPCODE_DEFAULT: return 0;
+ case D3D10_SB_OPCODE_DISCARD: return 1;
+ case D3D10_SB_OPCODE_DIV: return 3;
+ case D3D10_SB_OPCODE_DP2: return 3;
+ case D3D10_SB_OPCODE_DP3: return 3;
+ case D3D10_SB_OPCODE_DP4: return 3;
+ case D3D10_SB_OPCODE_ELSE: return 0;
+ case D3D10_SB_OPCODE_EMIT: return 0;
+ case D3D10_SB_OPCODE_EMITTHENCUT: return 0;
+ case D3D10_SB_OPCODE_ENDIF: return 0;
+ case D3D10_SB_OPCODE_ENDLOOP: return 0;
+ case D3D10_SB_OPCODE_ENDSWITCH: return 0;
+ case D3D10_SB_OPCODE_EQ: return 3;
+ case D3D10_SB_OPCODE_EXP: return 2;
+ case D3D10_SB_OPCODE_FRC: return 2;
+ case D3D10_SB_OPCODE_FTOI: return 2;
+ case D3D10_SB_OPCODE_FTOU: return 2;
+ case D3D10_SB_OPCODE_GE: return 3;
+ case D3D10_SB_OPCODE_DERIV_RTX: return 2;
+ case D3D10_SB_OPCODE_DERIV_RTY: return 2;
+ case D3D10_SB_OPCODE_IADD: return 3;
+ case D3D10_SB_OPCODE_IF: return 1;
+ case D3D10_SB_OPCODE_IEQ: return 3;
+ case D3D10_SB_OPCODE_IGE: return 3;
+ case D3D10_SB_OPCODE_ILT: return 3;
+ case D3D10_SB_OPCODE_IMAD: return 4;
+ case D3D10_SB_OPCODE_IMAX: return 3;
+ case D3D10_SB_OPCODE_IMIN: return 3;
+ case D3D10_SB_OPCODE_IMUL: return 4;
+ case D3D10_SB_OPCODE_INE: return 3;
+ case D3D10_SB_OPCODE_INEG: return 2;
+ case D3D10_SB_OPCODE_ISHL: return 3;
+ case D3D10_SB_OPCODE_ISHR: return 3;
+ case D3D10_SB_OPCODE_ITOF: return 2;
+ case D3D10_SB_OPCODE_LABEL: return 1;
+ case D3D10_SB_OPCODE_LD: return 3;
+ case D3D10_SB_OPCODE_LD_MS: return 4;
+ case D3D10_SB_OPCODE_LOG: return 2;
+ case D3D10_SB_OPCODE_LOOP: return 0;
+ case D3D10_SB_OPCODE_LT: return 3;
+ case D3D10_SB_OPCODE_MAD: return 4;
+ case D3D10_SB_OPCODE_MAX: return 3;
+ case D3D10_SB_OPCODE_MIN: return 3;
+ case D3D10_SB_OPCODE_MOV: return 2;
+ case D3D10_SB_OPCODE_MOVC: return 4;
+ case D3D10_SB_OPCODE_MUL: return 3;
+ case D3D10_SB_OPCODE_NE: return 3;
+ case D3D10_SB_OPCODE_NOP: return 0;
+ case D3D10_SB_OPCODE_NOT: return 2;
+ case D3D10_SB_OPCODE_OR: return 3;
+ case D3D10_SB_OPCODE_RESINFO: return 3;
+ case D3D10_SB_OPCODE_RET: return 0;
+ case D3D10_SB_OPCODE_RETC: return 1;
+ case D3D10_SB_OPCODE_ROUND_NE: return 2;
+ case D3D10_SB_OPCODE_ROUND_NI: return 2;
+ case D3D10_SB_OPCODE_ROUND_PI: return 2;
+ case D3D10_SB_OPCODE_ROUND_Z: return 2;
+ case D3D10_SB_OPCODE_RSQ: return 2;
+ case D3D10_SB_OPCODE_SAMPLE: return 4;
+ case D3D10_SB_OPCODE_SAMPLE_B: return 5;
+ case D3D10_SB_OPCODE_SAMPLE_L: return 5;
+ case D3D10_SB_OPCODE_SAMPLE_D: return 6;
+ case D3D10_SB_OPCODE_SAMPLE_C: return 5;
+ case D3D10_SB_OPCODE_SAMPLE_C_LZ: return 5;
+ case D3D10_SB_OPCODE_SQRT: return 2;
+ case D3D10_SB_OPCODE_SWITCH: return 1;
+ case D3D10_SB_OPCODE_SINCOS: return 3;
+ case D3D10_SB_OPCODE_UDIV: return 4;
+ case D3D10_SB_OPCODE_ULT: return 3;
+ case D3D10_SB_OPCODE_UGE: return 3;
+ case D3D10_SB_OPCODE_UMAX: return 3;
+ case D3D10_SB_OPCODE_UMIN: return 3;
+ case D3D10_SB_OPCODE_UMUL: return 4;
+ case D3D10_SB_OPCODE_UMAD: return 4;
+ case D3D10_SB_OPCODE_USHR: return 3;
+ case D3D10_SB_OPCODE_UTOF: return 2;
+ case D3D10_SB_OPCODE_XOR: return 3;
+ case D3D10_SB_OPCODE_RESERVED0: return 0;
+ case D3D10_SB_OPCODE_DCL_INPUT: return 1;
+ case D3D10_SB_OPCODE_DCL_OUTPUT: return 1;
+ case D3D10_SB_OPCODE_DCL_INPUT_SGV: return 1;
+ case D3D10_SB_OPCODE_DCL_INPUT_PS_SGV: return 1;
+ case D3D10_SB_OPCODE_DCL_GS_INPUT_PRIMITIVE: return 0;
+ case D3D10_SB_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY: return 0;
+ case D3D10_SB_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: return 0;
+ case D3D10_SB_OPCODE_DCL_INPUT_PS: return 1;
+ case D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER: return 1;
+ case D3D10_SB_OPCODE_DCL_SAMPLER: return 1;
+ case D3D10_SB_OPCODE_DCL_RESOURCE: return 1;
+ case D3D10_SB_OPCODE_DCL_INPUT_SIV: return 1;
+ case D3D10_SB_OPCODE_DCL_INPUT_PS_SIV: return 1;
+ case D3D10_SB_OPCODE_DCL_OUTPUT_SIV: return 1;
+ case D3D10_SB_OPCODE_DCL_OUTPUT_SGV: return 1;
+ case D3D10_SB_OPCODE_DCL_TEMPS: return 0;
+ case D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP: return 0;
+ case D3D10_SB_OPCODE_DCL_INDEX_RANGE: return 1;
+ case D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS: return 0;
+ case D3D10_1_SB_OPCODE_SAMPLE_INFO: return 2;
+ case D3D10_1_SB_OPCODE_SAMPLE_POS: return 3;
+ case D3D10_1_SB_OPCODE_GATHER4: return 4;
+ case D3D10_1_SB_OPCODE_LOD: return 4;
+ case D3D11_SB_OPCODE_EMIT_STREAM: return 1;
+ case D3D11_SB_OPCODE_CUT_STREAM: return 1;
+ case D3D11_SB_OPCODE_EMITTHENCUT_STREAM: return 1;
+ case D3D11_SB_OPCODE_INTERFACE_CALL: return 1;
+ case D3D11_SB_OPCODE_DCL_STREAM: return 1;
+ case D3D11_SB_OPCODE_DCL_FUNCTION_BODY: return 0;
+ case D3D11_SB_OPCODE_DCL_FUNCTION_TABLE: return 0;
+ case D3D11_SB_OPCODE_DCL_INTERFACE: return 0;
+ case D3D11_SB_OPCODE_BUFINFO: return 2;
+ case D3D11_SB_OPCODE_DERIV_RTX_COARSE: return 2;
+ case D3D11_SB_OPCODE_DERIV_RTX_FINE: return 2;
+ case D3D11_SB_OPCODE_DERIV_RTY_COARSE: return 2;
+ case D3D11_SB_OPCODE_DERIV_RTY_FINE: return 2;
+ case D3D11_SB_OPCODE_GATHER4_C: return 5;
+ case D3D11_SB_OPCODE_GATHER4_PO: return 5;
+ case D3D11_SB_OPCODE_GATHER4_PO_C: return 6;
+ case D3D11_SB_OPCODE_RCP: return 2;
+ case D3D11_SB_OPCODE_F32TOF16: return 2;
+ case D3D11_SB_OPCODE_F16TOF32: return 2;
+ case D3D11_SB_OPCODE_UADDC: return 4;
+ case D3D11_SB_OPCODE_USUBB: return 4;
+ case D3D11_SB_OPCODE_COUNTBITS: return 2;
+ case D3D11_SB_OPCODE_FIRSTBIT_HI: return 2;
+ case D3D11_SB_OPCODE_FIRSTBIT_LO: return 2;
+ case D3D11_SB_OPCODE_FIRSTBIT_SHI: return 2;
+ case D3D11_SB_OPCODE_UBFE: return 4;
+ case D3D11_SB_OPCODE_IBFE: return 4;
+ case D3D11_SB_OPCODE_BFI: return 5;
+ case D3D11_SB_OPCODE_BFREV: return 2;
+ case D3D11_SB_OPCODE_SWAPC: return 5;
+ case D3D11_SB_OPCODE_HS_DECLS: return 0;
+ case D3D11_SB_OPCODE_HS_CONTROL_POINT_PHASE: return 0;
+ case D3D11_SB_OPCODE_HS_FORK_PHASE: return 0;
+ case D3D11_SB_OPCODE_HS_JOIN_PHASE: return 0;
+ case D3D11_SB_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT: return 0;
+ case D3D11_SB_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT: return 0;
+ case D3D11_SB_OPCODE_DCL_TESS_DOMAIN: return 0;
+ case D3D11_SB_OPCODE_DCL_TESS_PARTITIONING: return 0;
+ case D3D11_SB_OPCODE_DCL_TESS_OUTPUT_PRIMITIVE: return 0;
+ case D3D11_SB_OPCODE_DCL_HS_MAX_TESSFACTOR: return 0;
+ case D3D11_SB_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: return 0;
+ case D3D11_SB_OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT: return 0;
+ case D3D11_SB_OPCODE_DCL_THREAD_GROUP: return 0;
+ case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED: return 1;
+ case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW: return 1;
+ case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED: return 1;
+ case D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW: return 1;
+ case D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED: return 1;
+ case D3D11_SB_OPCODE_DCL_RESOURCE_RAW: return 1;
+ case D3D11_SB_OPCODE_DCL_RESOURCE_STRUCTURED: return 1;
+ case D3D11_SB_OPCODE_LD_UAV_TYPED: return 3;
+ case D3D11_SB_OPCODE_STORE_UAV_TYPED: return 3;
+ case D3D11_SB_OPCODE_LD_RAW: return 3;
+ case D3D11_SB_OPCODE_STORE_RAW: return 3;
+ case D3D11_SB_OPCODE_LD_STRUCTURED: return 4;
+ case D3D11_SB_OPCODE_STORE_STRUCTURED: return 4;
+ case D3D11_SB_OPCODE_ATOMIC_AND: return 3;
+ case D3D11_SB_OPCODE_ATOMIC_OR: return 3;
+ case D3D11_SB_OPCODE_ATOMIC_XOR: return 3;
+ case D3D11_SB_OPCODE_ATOMIC_CMP_STORE: return 4;
+ case D3D11_SB_OPCODE_ATOMIC_IADD: return 3;
+ case D3D11_SB_OPCODE_ATOMIC_IMAX: return 3;
+ case D3D11_SB_OPCODE_ATOMIC_IMIN: return 3;
+ case D3D11_SB_OPCODE_ATOMIC_UMAX: return 3;
+ case D3D11_SB_OPCODE_ATOMIC_UMIN: return 3;
+ case D3D11_SB_OPCODE_IMM_ATOMIC_ALLOC: return 2;
+ case D3D11_SB_OPCODE_IMM_ATOMIC_CONSUME: return 2;
+ case D3D11_SB_OPCODE_IMM_ATOMIC_IADD: return 4;
+ case D3D11_SB_OPCODE_IMM_ATOMIC_AND: return 4;
+ case D3D11_SB_OPCODE_IMM_ATOMIC_OR: return 4;
+ case D3D11_SB_OPCODE_IMM_ATOMIC_XOR: return 4;
+ case D3D11_SB_OPCODE_IMM_ATOMIC_EXCH: return 4;
+ case D3D11_SB_OPCODE_IMM_ATOMIC_CMP_EXCH: return 5;
+ case D3D11_SB_OPCODE_IMM_ATOMIC_IMAX: return 4;
+ case D3D11_SB_OPCODE_IMM_ATOMIC_IMIN: return 4;
+ case D3D11_SB_OPCODE_IMM_ATOMIC_UMAX: return 4;
+ case D3D11_SB_OPCODE_IMM_ATOMIC_UMIN: return 4;
+ case D3D11_SB_OPCODE_SYNC: return 0;
+ case D3D11_SB_OPCODE_EVAL_SNAPPED: return 3;
+ case D3D11_SB_OPCODE_EVAL_SAMPLE_INDEX: return 3;
+ case D3D11_SB_OPCODE_EVAL_CENTROID: return 2;
+ case D3D11_SB_OPCODE_DCL_GS_INSTANCE_COUNT: return 0;
+ case D3D11_SB_OPCODE_DADD: return 3;
+ case D3D11_SB_OPCODE_DMAX: return 3;
+ case D3D11_SB_OPCODE_DMIN: return 3;
+ case D3D11_SB_OPCODE_DMUL: return 3;
+ case D3D11_SB_OPCODE_DEQ: return 3;
+ case D3D11_SB_OPCODE_DGE: return 3;
+ case D3D11_SB_OPCODE_DLT: return 3;
+ case D3D11_SB_OPCODE_DNE: return 3;
+ case D3D11_SB_OPCODE_DMOV: return 2;
+ case D3D11_SB_OPCODE_DMOVC: return 4;
+ case D3D11_SB_OPCODE_DTOF: return 2;
+ case D3D11_SB_OPCODE_FTOD: return 2;
+ case D3D11_SB_OPCODE_ABORT: return 0;
+ case D3D11_SB_OPCODE_DEBUG_BREAK: return 0;
+ case D3D11_1_SB_OPCODE_DDIV: return 3;
+ case D3D11_1_SB_OPCODE_DFMA: return 4;
+ case D3D11_1_SB_OPCODE_DRCP: return 2;
+ case D3D11_1_SB_OPCODE_MSAD: return 4;
+ case D3D11_1_SB_OPCODE_DTOI: return 2;
+ case D3D11_1_SB_OPCODE_DTOU: return 2;
+ case D3D11_1_SB_OPCODE_ITOD: return 2;
+ case D3D11_1_SB_OPCODE_UTOD: return 2;
+ case D3DWDDM1_3_SB_OPCODE_GATHER4_FEEDBACK: return 5;
+ case D3DWDDM1_3_SB_OPCODE_GATHER4_C_FEEDBACK: return 6;
+ case D3DWDDM1_3_SB_OPCODE_GATHER4_PO_FEEDBACK: return 6;
+ case D3DWDDM1_3_SB_OPCODE_GATHER4_PO_C_FEEDBACK: return 7;
+ case D3DWDDM1_3_SB_OPCODE_LD_FEEDBACK: return 4;
+ case D3DWDDM1_3_SB_OPCODE_LD_MS_FEEDBACK: return 5;
+ case D3DWDDM1_3_SB_OPCODE_LD_UAV_TYPED_FEEDBACK: return 4;
+ case D3DWDDM1_3_SB_OPCODE_LD_RAW_FEEDBACK: return 4;
+ case D3DWDDM1_3_SB_OPCODE_LD_STRUCTURED_FEEDBACK: return 5;
+ case D3DWDDM1_3_SB_OPCODE_SAMPLE_L_FEEDBACK: return 6;
+ case D3DWDDM1_3_SB_OPCODE_SAMPLE_C_LZ_FEEDBACK: return 6;
+ case D3DWDDM1_3_SB_OPCODE_SAMPLE_CLAMP_FEEDBACK: return 6;
+ case D3DWDDM1_3_SB_OPCODE_SAMPLE_B_CLAMP_FEEDBACK: return 7;
+ case D3DWDDM1_3_SB_OPCODE_SAMPLE_D_CLAMP_FEEDBACK: return 8;
+ case D3DWDDM1_3_SB_OPCODE_SAMPLE_C_CLAMP_FEEDBACK: return 7;
+ case D3DWDDM1_3_SB_OPCODE_CHECK_ACCESS_FULLY_MAPPED: return 2;
+ default:
+ UNEXPECTED("Unknown opcode");
+ return ~0u;
+ }
+}
+
+inline bool PatchSpace(ResourceBindingInfo51& Res, const DXBCUtils::BindInfo& Info)
+{
+ Info.SrcSpace = Res.Space;
+ Res.Space = Info.Space;
return true;
}
-inline bool PatchSpace(ResourceBindingInfo50&, Uint32 Space)
+inline bool PatchSpace(ResourceBindingInfo50&, const DXBCUtils::BindInfo& Info)
{
- return Space == 0 || Space == ~0U;
+ return Info.Space == 0 || Info.Space == ~0U;
}
template <typename ResourceBindingInfoType>
-bool RemapShaderResources(const DXBCUtils::TResourceBindingMap& ResourceMap, const void* EndPtr, ResourceDefChunkHeader* RDEFHeader)
+void RemapShaderResources(const DXBCUtils::TResourceBindingMap& ResourceMap, const void* EndPtr, ResourceDefChunkHeader* RDEFHeader, ResourceBindingPerType& BindingsPerType)
{
VERIFY_EXPR(RDEFHeader->Magic == RDEFFourCC);
@@ -120,8 +856,7 @@ bool RemapShaderResources(const DXBCUtils::TResourceBindingMap& ResourceMap, con
auto* ResBinding = reinterpret_cast<ResourceBindingInfoType*>(Ptr + RDEFHeader->ResBindingOffset);
if (ResBinding + RDEFHeader->ResBindingCount > EndPtr)
{
- LOG_ERROR_MESSAGE("Resource binding data is outside of the specified byte code range. The byte code may be corrupted.");
- return false;
+ LOG_ERROR_AND_THROW("Resource binding data is outside of the specified byte code range. The byte code may be corrupted.");
}
for (Uint32 r = 0; r < RDEFHeader->ResBindingCount; ++r)
@@ -130,27 +865,606 @@ bool RemapShaderResources(const DXBCUtils::TResourceBindingMap& ResourceMap, con
const char* Name = Ptr + Res.NameOffset;
if (Name + 1 > EndPtr)
{
- LOG_ERROR_MESSAGE("Resource name pointer is outside of the specified byte code range. The byte code may be corrupted.");
- return false;
+ LOG_ERROR_AND_THROW("Resource name pointer is outside of the specified byte code range. The byte code may be corrupted.");
+ }
+
+ const auto ResType = ToResType(Res.ShaderInputType);
+ if (ResType > BindingsPerType.size())
+ {
+ LOG_ERROR_AND_THROW("Invalid shader input type.");
}
auto Iter = ResourceMap.find(HashMapStringKey{Name});
if (Iter == ResourceMap.end())
{
- LOG_ERROR_MESSAGE("Failed to find '", Name, "' in the resource mapping.");
- return false;
+ LOG_ERROR_AND_THROW("Failed to find '", Name, "' in the resource mapping.");
+ }
+
+ auto& Binding = BindingsPerType[ResType];
+ Binding.emplace_back(&Iter->second, Res.BindCount);
+
+ Iter->second.SrcBindPoint = Res.BindPoint;
+ Res.BindPoint = Iter->second.BindPoint;
+
+ if (!PatchSpace(Res, Iter->second))
+ {
+ LOG_ERROR_AND_THROW("Can not change space for resource '", Name, "' because the shader was not compiled for SM 5.1.");
+ }
+ }
+}
+
+void RemapResourceOperand2(const OperandToken& Operand, Uint32* Token, const ResInfo& Info)
+{
+ switch (Operand.OperandIndex2D)
+ {
+ case D3D10_SB_OPERAND_INDEX_IMMEDIATE32:
+ case D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE:
+ {
+ if (Token[1] < Info.Bind->SrcBindPoint || Token[1] >= Info.Bind->SrcBindPoint + Info.BindCount)
+ LOG_ERROR_AND_THROW("Invalid bind point (", Token[1], "), expected be in range (", Info.Bind->SrcBindPoint, "..", Info.Bind->SrcBindPoint + Info.BindCount - 1, ").");
+
+ Token[1] = Info.Bind->BindPoint + (Token[1] - Info.Bind->SrcBindPoint);
+ break;
+ }
+ case D3D10_SB_OPERAND_INDEX_RELATIVE:
+ {
+ const auto Operand2 = reinterpret_cast<OperandToken&>(Token[1]);
+ VERIFY_EXPR(Operand2.OperandType == D3D10_SB_OPERAND_TYPE_TEMP);
+ VERIFY_EXPR(Operand2.IndexDim == D3D10_SB_OPERAND_INDEX_1D);
+ VERIFY_EXPR(Operand2.OperandIndex1D == D3D10_SB_OPERAND_INDEX_IMMEDIATE32);
+
+ if (Token[2] < Info.Bind->SrcBindPoint || Token[2] >= Info.Bind->SrcBindPoint + Info.BindCount)
+ LOG_ERROR_AND_THROW("Invalid bind point (", Token[2], "), expected be in range (", Info.Bind->SrcBindPoint, "..", Info.Bind->SrcBindPoint + Info.BindCount - 1, ").");
+
+ Token[2] = Info.Bind->BindPoint + (Token[2] - Info.Bind->SrcBindPoint);
+ break;
+ }
+ }
+}
+
+void RemapResourceOperand(const OperandToken& Operand, Uint32* Token, const void* Finish, const ResourceBindingPerType& BindingsPerType)
+{
+ switch (Operand.OperandType)
+ {
+ case D3D10_SB_OPERAND_TYPE_CONSTANT_BUFFER:
+ {
+ // 0 - cbuffer index in resource definition
+ // 1 - cbuffer bind point
+ // 2 - row offset (16 bytes per row)
+
+ VERIFY_EXPR(Token + 3 <= Finish);
+ VERIFY_EXPR(Operand.IndexDim == D3D10_SB_OPERAND_INDEX_3D);
+ VERIFY_EXPR(Operand.OperandIndex1D == D3D10_SB_OPERAND_INDEX_IMMEDIATE32);
+
+ const auto& Bindings = BindingsPerType[SHADER_RES_TYPE_CBUFFER];
+ if (Token[0] >= Bindings.size())
+ LOG_ERROR_AND_THROW("Invalid cbuffer index (", Token[0], "), the number of constant buffers is (", Bindings.size(), ").");
+
+ RemapResourceOperand2(Operand, Token, Bindings[Token[0]]);
+ break;
+ }
+
+ case D3D10_SB_OPERAND_TYPE_SAMPLER:
+ {
+ // 0 - sampler index in resource definition
+ // 1 - sampler bind point
+
+ VERIFY_EXPR(Token + 2 <= Finish);
+ VERIFY_EXPR(Operand.IndexDim >= D3D10_SB_OPERAND_INDEX_2D);
+ VERIFY_EXPR(Operand.OperandIndex1D == D3D10_SB_OPERAND_INDEX_IMMEDIATE32);
+
+ const auto& Bindings = BindingsPerType[SHADER_RES_TYPE_SAMPLER];
+ if (Token[0] >= Bindings.size())
+ LOG_ERROR_AND_THROW("Invalid sampler index (", Token[0], "), the number of samplers is (", Bindings.size(), ").");
+
+ RemapResourceOperand2(Operand, Token, Bindings[Token[0]]);
+ break;
+ }
+
+ case D3D10_SB_OPERAND_TYPE_RESOURCE:
+ {
+ // 0 - texture index in resource definition
+ // 1 - texture bind point
+
+ VERIFY_EXPR(Token + 2 <= Finish);
+ VERIFY_EXPR(Operand.IndexDim >= D3D10_SB_OPERAND_INDEX_2D);
+ VERIFY_EXPR(Operand.OperandIndex1D == D3D10_SB_OPERAND_INDEX_IMMEDIATE32);
+
+ const auto& Bindings = BindingsPerType[SHADER_RES_TYPE_TEXTURE];
+ if (Token[0] >= Bindings.size())
+ LOG_ERROR_AND_THROW("Invalid texture index (", Token[0], "), the number of textures is (", Bindings.size(), ").");
+
+ RemapResourceOperand2(Operand, Token, Bindings[Token[0]]);
+ break;
+ }
+
+ case D3D10_SB_OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER:
+ case D3D11_SB_OPERAND_TYPE_UNORDERED_ACCESS_VIEW:
+ {
+ // 0 - UAV index in resource definition
+ // 1 - UAV bind point
+
+ VERIFY_EXPR(Token + 2 <= Finish);
+ VERIFY_EXPR(Operand.IndexDim >= D3D10_SB_OPERAND_INDEX_2D);
+ VERIFY_EXPR(Operand.OperandIndex1D == D3D10_SB_OPERAND_INDEX_IMMEDIATE32);
+
+ const auto& Bindings = BindingsPerType[SHADER_RES_TYPE_UAV];
+ if (Token[0] >= Bindings.size())
+ LOG_ERROR_AND_THROW("Invalid UAV index (", Token[0], "), the number of UAVs is (", Bindings.size(), ").");
+
+ RemapResourceOperand2(Operand, Token, Bindings[Token[0]]);
+ break;
+ }
+ }
+}
+
+void RemapResourceBinding(const OpcodeToken& Opcode, Uint32* Token, const void* Finish, const ResourceBindingPerType& BindingsPerType)
+{
+ switch (Opcode.OpcodeType)
+ {
+ case D3D10_SB_OPCODE_DCL_CONSTANT_BUFFER:
+ {
+ // 0 - operand info
+ // 1 - cbuffer index
+ // 2 - first bind point -- remapped in RemapResourceOperand()
+ // 3 - last bind point
+ // 4 - cbuffer size
+ // 5 - register space
+
+ VERIFY_EXPR(Token + 6 <= Finish);
+ VERIFY_EXPR(Opcode.OpcodeLength > 5);
+
+ const auto& Bindings = BindingsPerType[SHADER_RES_TYPE_CBUFFER];
+ if (Token[1] >= Bindings.size())
+ LOG_ERROR_AND_THROW("Invalid cbuffer index (", Token[1], "), the number of constant buffers is (", Bindings.size(), ").");
+
+ const auto& Info = Bindings[Token[1]];
+ VERIFY_EXPR(Info.Bind->SrcBindPoint == Token[2]);
+
+ if (Token[3] != Info.Bind->SrcBindPoint + Info.BindCount - 1)
+ LOG_ERROR_AND_THROW("Invalid cbuffer bind point (", Token[3], "), expected (", Info.Bind->SrcBindPoint + Info.BindCount - 1, ").");
+ if (Info.Bind->SrcSpace != Token[5])
+ LOG_ERROR_AND_THROW("Invalid cbuffer register space (", Token[5], "), expected (", Info.Bind->SrcSpace, ").");
+
+ Token[3] = Info.Bind->BindPoint + Info.BindCount - 1;
+ Token[5] = Info.Bind->Space;
+ break;
+ }
+
+ case D3D10_SB_OPCODE_DCL_SAMPLER:
+ {
+ // 0 - operand info
+ // 1 - sampler index
+ // 2 - first bind point -- remapped in RemapResourceOperand()
+ // 3 - last bind point
+ // 4 - register space
+
+ VERIFY_EXPR(Token + 5 <= Finish);
+ VERIFY_EXPR(Opcode.OpcodeLength > 4);
+
+ const auto& Bindings = BindingsPerType[SHADER_RES_TYPE_SAMPLER];
+ if (Token[1] >= Bindings.size())
+ LOG_ERROR_AND_THROW("Invalid sampler index (", Token[1], "), the number of samplers is (", Bindings.size(), ").");
+
+ const auto& Info = Bindings[Token[1]];
+ VERIFY_EXPR(Info.Bind->BindPoint == Token[2]);
+
+ if (Token[3] != Info.Bind->SrcBindPoint + Info.BindCount - 1)
+ LOG_ERROR_AND_THROW("Invalid sampler bind point (", Token[3], "), expected (", Info.Bind->SrcBindPoint + Info.BindCount - 1, ").");
+ if (Info.Bind->SrcSpace != Token[4])
+ LOG_ERROR_AND_THROW("Invalid sampler register space (", Token[4], "), expected (", Info.Bind->SrcSpace, ").");
+
+ Token[3] = Info.Bind->BindPoint + Info.BindCount - 1;
+ Token[4] = Info.Bind->Space;
+ break;
+ }
+
+ // Texture
+ case D3D10_SB_OPCODE_DCL_RESOURCE:
+ case D3D11_SB_OPCODE_DCL_RESOURCE_STRUCTURED:
+ {
+ // 0 - operand info
+ // 1 - texture index
+ // 2 - first bind point -- remapped in RemapResourceOperand()
+ // 3 - last bind point
+ // 4 - format? / struct size
+ // 5 - register space
+
+ VERIFY_EXPR(Token + 6 <= Finish);
+ VERIFY_EXPR(Opcode.OpcodeLength > 5);
+
+ const auto& Bindings = BindingsPerType[SHADER_RES_TYPE_TEXTURE];
+ if (Token[1] >= Bindings.size())
+ LOG_ERROR_AND_THROW("Invalid texture index (", Token[1], "), the number of textures is (", Bindings.size(), ").");
+
+ const auto& Info = Bindings[Token[1]];
+ VERIFY_EXPR(Info.Bind->BindPoint == Token[2]);
+
+ if (Token[3] != Info.Bind->SrcBindPoint + Info.BindCount - 1)
+ LOG_ERROR_AND_THROW("Invalid texture bind point (", Token[3], "), expected (", Info.Bind->SrcBindPoint + Info.BindCount - 1, ").");
+ if (Info.Bind->SrcSpace != Token[5])
+ LOG_ERROR_AND_THROW("Invalid texture register space (", Token[5], "), expected (", Info.Bind->SrcSpace, ").");
+
+ Token[3] = Info.Bind->BindPoint + Info.BindCount - 1;
+ Token[5] = Info.Bind->Space;
+ break;
+ }
+ case D3D11_SB_OPCODE_DCL_RESOURCE_RAW:
+ {
+ const auto& Bindings = BindingsPerType[SHADER_RES_TYPE_TEXTURE];
+ (void)(Bindings);
+ UNEXPECTED("Not implemented");
+ break;
+ }
+
+ // UAV
+ case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_TYPED:
+ case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED:
+ {
+ // 0 - operand info
+ // 1 - UAV index
+ // 2 - first bind point -- remapped in RemapResourceOperand()
+ // 3 - last bind point
+ // 4 - format? / struct size
+ // 5 - register space
+
+ VERIFY_EXPR(Token + 6 <= Finish);
+ VERIFY_EXPR(Opcode.OpcodeLength > 5);
+
+ const auto& Bindings = BindingsPerType[SHADER_RES_TYPE_UAV];
+ if (Token[1] >= Bindings.size())
+ LOG_ERROR_AND_THROW("Invalid UAV index (", Token[1], "), the number of UAVs is (", Bindings.size(), ").");
+
+ const auto& Info = Bindings[Token[1]];
+ VERIFY_EXPR(Info.Bind->BindPoint == Token[2]);
+
+ if (Token[3] != Info.Bind->SrcBindPoint + Info.BindCount - 1)
+ LOG_ERROR_AND_THROW("Invalid UAV bind point (", Token[3], "), expected (", Info.Bind->SrcBindPoint + Info.BindCount - 1, ").");
+ if (Info.Bind->SrcSpace != Token[5])
+ LOG_ERROR_AND_THROW("Invalid UAV register space (", Token[5], "), expected (", Info.Bind->SrcSpace, ").");
+
+ Token[3] = Info.Bind->BindPoint + Info.BindCount - 1;
+ Token[5] = Info.Bind->Space;
+ break;
+ }
+ case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_RAW:
+ {
+ const auto& Bindings = BindingsPerType[SHADER_RES_TYPE_UAV];
+ (void)(Bindings);
+ UNEXPECTED("Not implemented");
+ break;
}
+ }
+}
+
+void ParseOperand(Uint32*& Token, const void* Finish, const ResourceBindingPerType& BindingsPerType);
- Res.BindPoint = Iter->second.BindPoint;
- if (!PatchSpace(Res, Iter->second.Space))
+void ParseIndex(D3D10_SB_OPERAND_INDEX_REPRESENTATION IndexType, Uint32*& Token, const void* Finish, const ResourceBindingPerType& BindingsPerType)
+{
+ switch (IndexType)
+ {
+ case D3D10_SB_OPERAND_INDEX_IMMEDIATE32:
{
- LOG_ERROR_MESSAGE("Can not change space for resource '", Name, "' because the shader was not compiled for SM 5.1.");
+ Token += 1;
+ break;
+ }
+ case D3D10_SB_OPERAND_INDEX_IMMEDIATE64:
+ {
+ Token += 2;
+ break;
+ }
+ case D3D10_SB_OPERAND_INDEX_RELATIVE:
+ {
+ ParseOperand(Token, Finish, BindingsPerType);
+ break;
+ }
+ case D3D10_SB_OPERAND_INDEX_IMMEDIATE32_PLUS_RELATIVE:
+ {
+ Token += 1;
+ ParseOperand(Token, Finish, BindingsPerType);
+ break;
+ }
+ case D3D10_SB_OPERAND_INDEX_IMMEDIATE64_PLUS_RELATIVE:
+ {
+ Token += 2;
+ ParseOperand(Token, Finish, BindingsPerType);
+ break;
+ }
+ default:
+ LOG_ERROR_AND_THROW("Unknown index type");
+ }
+}
+
+void ParseOperand(Uint32*& Token, const void* Finish, const ResourceBindingPerType& BindingsPerType)
+{
+ const auto& Operand = *reinterpret_cast<OperandToken*>(Token++);
+
+ Uint32 NumComponents = 0;
+ switch (Operand.NumComponents)
+ {
+ case D3D10_SB_OPERAND_0_COMPONENT: NumComponents = 0; break;
+ case D3D10_SB_OPERAND_1_COMPONENT: NumComponents = 1; break;
+ case D3D10_SB_OPERAND_4_COMPONENT: NumComponents = 4; break;
+ case D3D10_SB_OPERAND_N_COMPONENT:
+ default: LOG_ERROR_AND_THROW("Unsupported component count");
+ }
+
+ switch (Operand.OperandType)
+ {
+ case D3D10_SB_OPERAND_TYPE_IMMEDIATE32:
+ case D3D10_SB_OPERAND_TYPE_IMMEDIATE64:
+ break;
+ default:
+ if (NumComponents == 4)
+ {
+ switch (Operand.CompSelection)
+ {
+ case D3D10_SB_OPERAND_4_COMPONENT_MASK_MODE:
+ {
+ Uint32 WriteMask = Operand.CompMask;
+ (void)(WriteMask);
+ break;
+ }
+ case D3D10_SB_OPERAND_4_COMPONENT_SWIZZLE_MODE:
+ {
+ Uint32 Swizzle[4];
+ Swizzle[0] = (Operand.CompMask >> 0) & 3;
+ Swizzle[1] = (Operand.CompMask >> 2) & 3;
+ Swizzle[2] = (Operand.CompMask >> 4) & 3;
+ Swizzle[3] = (Operand.CompMask >> 6) & 3;
+ break;
+ }
+ case D3D10_SB_OPERAND_4_COMPONENT_SELECT_1_MODE:
+ {
+ Uint32 Component = Operand.CompMask & 3;
+ (void)(Component);
+ break;
+ }
+ default:
+ LOG_ERROR_AND_THROW("Unknown component selection");
+ }
+ }
+ break;
+ }
+
+ if (Operand.Extended)
+ {
+ Token++; // extended operand type
+ }
+
+ switch (Operand.OperandType)
+ {
+ case D3D10_SB_OPERAND_TYPE_IMMEDIATE32:
+ case D3D10_SB_OPERAND_TYPE_IMMEDIATE64:
+ {
+ Token += NumComponents;
+ break;
+ }
+
+ case D3D10_SB_OPERAND_TYPE_SAMPLER:
+ case D3D10_SB_OPERAND_TYPE_RESOURCE:
+ case D3D10_SB_OPERAND_TYPE_CONSTANT_BUFFER:
+ case D3D10_SB_OPERAND_TYPE_IMMEDIATE_CONSTANT_BUFFER:
+ case D3D11_SB_OPERAND_TYPE_UNORDERED_ACCESS_VIEW:
+ RemapResourceOperand(Operand, Token, Finish, BindingsPerType);
+ break;
+ }
+
+ if (Operand.IndexDim != D3D10_SB_OPERAND_INDEX_0D)
+ {
+ if (Operand.IndexDim >= D3D10_SB_OPERAND_INDEX_1D)
+ ParseIndex(Operand.OperandIndex1D, Token, Finish, BindingsPerType);
+
+ if (Operand.IndexDim >= D3D10_SB_OPERAND_INDEX_2D)
+ ParseIndex(Operand.OperandIndex2D, Token, Finish, BindingsPerType);
+
+ if (Operand.IndexDim >= D3D10_SB_OPERAND_INDEX_3D)
+ ParseIndex(Operand.OperandIndex3D, Token, Finish, BindingsPerType);
+ }
+
+ VERIFY_EXPR(Token <= Finish);
+}
+
+void ParseCustomData(Uint32*& Token, const void* Finish, D3D10_SB_CUSTOMDATA_CLASS Type)
+{
+ switch (Type)
+ {
+ case D3D10_SB_CUSTOMDATA_COMMENT:
+ case D3D10_SB_CUSTOMDATA_DEBUGINFO:
+ case D3D10_SB_CUSTOMDATA_OPAQUE:
+ case D3D10_SB_CUSTOMDATA_DCL_IMMEDIATE_CONSTANT_BUFFER:
+ case D3D11_SB_CUSTOMDATA_SHADER_MESSAGE:
+ case D3D11_SB_CUSTOMDATA_SHADER_CLIP_PLANE_CONSTANT_MAPPINGS_FOR_DX9:
+ UNEXPECTED("not implemented");
+ break;
+ default:
+ LOG_ERROR_AND_THROW("Unknown custom data type");
+ }
+}
+
+void ParseOpcode(Uint32*& Token, const void* Finish, const ResourceBindingPerType& BindingsPerType)
+{
+ // based on code from
+ // https://github.com/microsoft/D3D12TranslationLayer/blob/master/src/ShaderBinary.cpp
+ // Copyright (c) Microsoft Corporation.
+ // MIT License
+
+ Uint32* StartToken = Token;
+ const auto Opcode = reinterpret_cast<OpcodeToken&>(*Token++);
+ const Uint32 NumOperands = GetNumOperands(Opcode.OpcodeType);
+ Uint32 InstructionLength = Opcode.OpcodeLength;
+
+ VERIFY_EXPR(Opcode.OpcodeType < D3D10_SB_NUM_OPCODES);
+ VERIFY_EXPR(Opcode.Extended == 0); // not supported yet
+
+ switch (Opcode.OpcodeType)
+ {
+ case D3D10_SB_OPCODE_CUSTOMDATA:
+ {
+ const auto Type = static_cast<D3D10_SB_CUSTOMDATA_CLASS>((*(Token - 1) & 0xfffff800) >> 11);
+ InstructionLength = *Token;
+ VERIFY_EXPR(InstructionLength >= 2);
+
+ ParseCustomData(Token, Finish, Type);
+ break;
+ }
+
+ // clang-format off
+ case D3D11_SB_OPCODE_DCL_FUNCTION_BODY: Token += 1; break;
+ case D3D11_SB_OPCODE_DCL_FUNCTION_TABLE: Token += 2; break;
+ case D3D11_SB_OPCODE_DCL_INTERFACE: Token += 3; break;
+ case D3D11_SB_OPCODE_INTERFACE_CALL: Token += 1; break;
+ case D3D10_SB_OPCODE_DCL_TEMPS: Token += 1; break;
+ case D3D10_SB_OPCODE_DCL_INDEXABLE_TEMP: Token += 3; break;
+ case D3D10_SB_OPCODE_DCL_MAX_OUTPUT_VERTEX_COUNT: Token += 1; break;
+ case D3D11_SB_OPCODE_DCL_GS_INSTANCE_COUNT: Token += 1; break;
+ case D3D11_SB_OPCODE_DCL_HS_MAX_TESSFACTOR: Token += 1; break;
+ case D3D11_SB_OPCODE_DCL_HS_FORK_PHASE_INSTANCE_COUNT: Token += 1; break;
+ case D3D11_SB_OPCODE_DCL_HS_JOIN_PHASE_INSTANCE_COUNT: Token += 1; break;
+ case D3D11_SB_OPCODE_DCL_THREAD_GROUP: Token += 3; break;
+ // clang-format on
+
+ case D3D10_SB_OPCODE_DCL_GS_OUTPUT_PRIMITIVE_TOPOLOGY:
+ case D3D10_SB_OPCODE_DCL_GS_INPUT_PRIMITIVE:
+ case D3D10_SB_OPCODE_DCL_GLOBAL_FLAGS:
+ case D3D11_SB_OPCODE_DCL_INPUT_CONTROL_POINT_COUNT:
+ case D3D11_SB_OPCODE_DCL_OUTPUT_CONTROL_POINT_COUNT:
+ case D3D11_SB_OPCODE_DCL_TESS_DOMAIN:
+ case D3D11_SB_OPCODE_DCL_TESS_PARTITIONING:
+ case D3D11_SB_OPCODE_DCL_TESS_OUTPUT_PRIMITIVE:
+ case D3D11_SB_OPCODE_SYNC:
+ break;
+ /*
+ case D3D10_SB_OPCODE_DCL_RESOURCE:
+ ParseOperand(Token, Finish, BindingsPerType);
+ Token += 1;
+ break;
+ case D3D10_SB_OPCODE_DCL_INPUT_SIV:
+ ParseOperand(Token, Finish, BindingsPerType);
+ Token += 1;
+ break;
+ case D3D10_SB_OPCODE_DCL_INPUT_SGV:
+ ParseOperand(Token, Finish, BindingsPerType);
+ Token += 1;
+ break;
+ case D3D10_SB_OPCODE_DCL_INPUT_PS_SIV:
+ ParseOperand(Token, Finish, BindingsPerType);
+ Token += 1;
+ break;
+ case D3D10_SB_OPCODE_DCL_INPUT_PS_SGV:
+ ParseOperand(Token, Finish, BindingsPerType);
+ Token += 1;
+ break;
+ case D3D10_SB_OPCODE_DCL_OUTPUT_SIV:
+ ParseOperand(Token, Finish, BindingsPerType);
+ Token += 1;
+ break;
+ case D3D10_SB_OPCODE_DCL_OUTPUT_SGV:
+ ParseOperand(Token, Finish, BindingsPerType);
+ Token += 1;
+ break;
+ case D3D10_SB_OPCODE_DCL_INDEX_RANGE:
+ ParseOperand(Token, Finish, BindingsPerType);
+ Token += 1;
+ break;
+ case D3D11_SB_OPCODE_DCL_UNORDERED_ACCESS_VIEW_STRUCTURED:
+ ParseOperand(Token, Finish, BindingsPerType);
+ Token += 1;
+ break;
+ case D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_RAW:
+ ParseOperand(Token, Finish, BindingsPerType);
+ Token += 1;
+ break;
+ case D3D11_SB_OPCODE_DCL_THREAD_GROUP_SHARED_MEMORY_STRUCTURED:
+ ParseOperand(Token, Finish, BindingsPerType);
+ Token += 2;
+ break;
+ case D3D11_SB_OPCODE_DCL_RESOURCE_STRUCTURED:
+ ParseOperand(Token, Finish, BindingsPerType);
+ Token += 1;
+ break;
+ */
+ default:
+ for (Uint32 i = 0; i < NumOperands; ++i)
+ ParseOperand(Token, Finish, BindingsPerType);
+ break;
+ }
+
+ Uint32* EndToken = StartToken + InstructionLength;
+ VERIFY_EXPR(Token <= EndToken);
+
+ RemapResourceBinding(Opcode, StartToken + 1, EndToken, BindingsPerType);
+
+ Token = EndToken;
+
+ if (Token < Finish)
+ {
+ const auto NextOpcode = reinterpret_cast<OpcodeToken&>(*Token);
+ VERIFY_EXPR(NextOpcode.OpcodeType < D3D10_SB_NUM_OPCODES);
+ }
+}
+/*
+bool RemapShaderBytecodeSM4(const DXBCUtils::TResourceBindingMap& ResourceMap, const void* EndPtr, ShaderChunkHeaderSM4* Chunk)
+{
+ Uint32* Token = reinterpret_cast<Uint32*>(Chunk + 1);
+ const Uint32* Finish = Token + Chunk->NumDWords;
+
+ VERIFY_EXPR(Chunk->VersionMajor < 5);
+ VERIFY_EXPR(Chunk->ProgramType < PROGRAM_TYPE_COUNT_SM4);
+
+ if (Finish > EndPtr)
+ {
+ LOG_ERROR_MESSAGE("Shader code chunk is outside of the specified byte code range. The byte code may be corrupted.");
+ return false;
+ }
+
+ for (; Token < Finish;)
+ {
+ const auto Opcode = reinterpret_cast<OpcodeToken&>(*Token);
+ Uint32* Ptr = Token;
+
+ VERIFY_EXPR(Opcode.OpcodeType < D3D10_SB_NUM_OPCODES);
+ VERIFY_EXPR(Opcode.Extended == 0); // not supported yet
+
+ if (!ParseOpcode(Ptr, ResourceMap))
return false;
+
+ if (Opcode.OpcodeType == D3D10_SB_OPCODE_CUSTOMDATA)
+ {
+ int CustomSize = *(Token + 1) - 2;
+ auto CustomDataOp = GetCustomDataClass(*Token);
+ (void)(CustomDataOp);
+
+ Token += CustomSize + 1;
+ }
+ else
+ {
+ Token += Opcode.OpcodeLength;
}
+ VERIFY_EXPR(Ptr <= Token);
}
return true;
}
+*/
+void RemapShaderBytecodeSM5(const DXBCUtils::TResourceBindingMap& ResourceMap, const ResourceBindingPerType& BindingsPerType, const void* EndPtr, ShaderChunkHeader* Chunk)
+{
+ Uint32* Token = reinterpret_cast<Uint32*>(Chunk + 1);
+ const void* Finish = reinterpret_cast<char*>(Chunk) + sizeof(ChunkHeader) + Chunk->Length;
+
+ VERIFY_EXPR(Chunk->VersionMajor >= 5);
+ VERIFY_EXPR(Chunk->ProgramType < PROGRAM_TYPE_COUNT_SM5);
+ VERIFY_EXPR(Chunk->NumDWords * 4 == Chunk->Length);
+ if (Finish > EndPtr)
+ {
+ LOG_ERROR_AND_THROW("Shader code chunk is outside of the specified byte code range. The byte code may be corrupted.");
+ }
+
+ for (; Token < Finish;)
+ {
+ ParseOpcode(Token, Finish, BindingsPerType);
+ }
+}
} // namespace
@@ -164,6 +1478,12 @@ bool DXBCUtils::RemapResourceBindings(const TResourceBindingMap& ResourceMap,
return false;
}
+ CComPtr<ID3DBlob> DisasmBlob;
+ D3DDisassemble(pBytecode, Size, D3D_DISASM_ENABLE_INSTRUCTION_OFFSET, nullptr, &DisasmBlob);
+
+ const auto* DisasmStr = (char*)DisasmBlob->GetBufferPointer();
+ (void)(DisasmStr);
+
auto* const Ptr = static_cast<char*>(pBytecode);
const void* const EndPtr = Ptr + Size;
@@ -200,49 +1520,77 @@ bool DXBCUtils::RemapResourceBindings(const TResourceBindingMap& ResourceMap,
return false;
}
- const Uint32* Chunks = reinterpret_cast<Uint32*>(Ptr + sizeof(Header));
+ const Uint32* Chunks = reinterpret_cast<Uint32*>(Ptr + sizeof(Header));
+ ResourceBindingPerType BindingsPerType;
- bool RemappingOK = false;
- for (Uint32 i = 0; i < Header.ChunkCount; ++i)
+ bool RemapResDef = false;
+ bool RemapBytecode = false;
+ try
{
- auto* pChunk = reinterpret_cast<ChunkHeader*>(Ptr + Chunks[i]);
- if (pChunk + 1 > EndPtr)
+ for (Uint32 i = 0; i < Header.ChunkCount; ++i)
{
- LOG_ERROR_MESSAGE("Not enough space for the chunk header. The byte code may be corrupted.");
- return false;
- }
-
- if (pChunk->Magic == RDEFFourCC)
- {
- auto* RDEFHeader = reinterpret_cast<ResourceDefChunkHeader*>(pChunk);
-
- if (RDEFHeader->MajorVersion == 5 && RDEFHeader->MinorVersion == 1)
+ auto* pChunk = reinterpret_cast<ChunkHeader*>(Ptr + Chunks[i]);
+ if (pChunk + 1 > EndPtr)
{
- RemappingOK = RemapShaderResources<ResourceBindingInfo51>(ResourceMap, EndPtr, RDEFHeader);
+ LOG_ERROR_MESSAGE("Not enough space for the chunk header. The byte code may be corrupted.");
+ return false;
}
- else if (RDEFHeader->MajorVersion == 5 && RDEFHeader->MinorVersion == 0 || RDEFHeader->MajorVersion < 5)
+ if ((Ptr + Chunks[i] + pChunk->Length) > EndPtr)
{
- RemappingOK = RemapShaderResources<ResourceBindingInfo50>(ResourceMap, EndPtr, RDEFHeader);
+ LOG_ERROR_MESSAGE("Not enough space for the chunk data. The byte code may be corrupted.");
+ return false;
}
- else
+
+ if (pChunk->Magic == RDEFFourCC)
{
- LOG_ERROR_MESSAGE("Unexpected shader model: ", RDEFHeader->MajorVersion, '.', RDEFHeader->MinorVersion);
- RemappingOK = false;
+ auto* RDEFHeader = reinterpret_cast<ResourceDefChunkHeader*>(pChunk);
+
+ if (RDEFHeader->MajorVersion == 5 && RDEFHeader->MinorVersion == 1)
+ {
+ RemapShaderResources<ResourceBindingInfo51>(ResourceMap, EndPtr, RDEFHeader, BindingsPerType);
+ RemapResDef = true;
+ }
+ else if (RDEFHeader->MajorVersion == 5 && RDEFHeader->MinorVersion == 0 || RDEFHeader->MajorVersion < 5)
+ {
+ RemapShaderResources<ResourceBindingInfo50>(ResourceMap, EndPtr, RDEFHeader, BindingsPerType);
+ RemapResDef = true;
+ }
+ else
+ {
+ LOG_ERROR_MESSAGE("Unexpected shader model: ", RDEFHeader->MajorVersion, '.', RDEFHeader->MinorVersion);
+ }
}
- if (!RemappingOK)
- return false;
+ if (pChunk->Magic == SHDRFourCC)
+ {
+ RemapShaderBytecodeSM5(ResourceMap, BindingsPerType, EndPtr, reinterpret_cast<ShaderChunkHeader*>(pChunk)); // TODO: SM4
+ RemapBytecode = true;
+ }
- break;
+ if (pChunk->Magic == SHEXFourCC)
+ {
+ RemapShaderBytecodeSM5(ResourceMap, BindingsPerType, EndPtr, reinterpret_cast<ShaderChunkHeader*>(pChunk));
+ RemapBytecode = true;
+ }
}
}
+ catch (...)
+ {
+ return false;
+ }
- if (!RemappingOK)
+ if (!RemapResDef)
{
LOG_ERROR_MESSAGE("Failed to find 'RDEF' chunk with the resource definition.");
return false;
}
+ if (!RemapBytecode)
+ {
+ LOG_ERROR_MESSAGE("Failed to find 'SHDR' or 'SHEX' chunk with the shader bytecode.");
+ return false;
+ }
+
// update checksum
DWORD Checksum[4] = {};
CalculateDXBCChecksum(reinterpret_cast<BYTE*>(Ptr), static_cast<DWORD>(Size), Checksum);