From 338dc2926ae97ad64ff352299b915f05c3fb3da6 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Thu, 19 Dec 2024 06:57:42 +1100 Subject: [PATCH] Updated vkd3d to d164752efc2dffc06d1e3ad9dd04cafff31e742a. --- libs/vkd3d/libs/vkd3d-shader/d3d_asm.c | 301 ++++-------------- libs/vkd3d/libs/vkd3d-shader/d3dbc.c | 234 +++++++++----- libs/vkd3d/libs/vkd3d-shader/dxil.c | 51 +++ libs/vkd3d/libs/vkd3d-shader/hlsl.h | 4 + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 86 +++++ libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 158 ++++++--- libs/vkd3d/libs/vkd3d-shader/ir.c | 105 +++++- libs/vkd3d/libs/vkd3d-shader/spirv.c | 46 ++- libs/vkd3d/libs/vkd3d-shader/tpf.c | 2 + .../libs/vkd3d-shader/vkd3d_shader_private.h | 41 ++- 10 files changed, 629 insertions(+), 399 deletions(-) diff --git a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c index 8c96befadea..69e14e0c7bf 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3d_asm.c @@ -354,6 +354,64 @@ static const char * const shader_opcode_names[] = [VKD3DSIH_XOR ] = "xor", }; +static const char * const shader_register_names[] = +{ + [VKD3DSPR_ADDR ] = "a", + [VKD3DSPR_ATTROUT ] = "oD", + [VKD3DSPR_COLOROUT ] = "oC", + [VKD3DSPR_COMBINED_SAMPLER ] = "s", + [VKD3DSPR_CONST ] = "c", + [VKD3DSPR_CONSTBOOL ] = "b", + [VKD3DSPR_CONSTBUFFER ] = "cb", + [VKD3DSPR_CONSTINT ] = "i", + [VKD3DSPR_COVERAGE ] = "vCoverage", + [VKD3DSPR_DEPTHOUT ] = "oDepth", + [VKD3DSPR_DEPTHOUTGE ] = "oDepthGE", + [VKD3DSPR_DEPTHOUTLE ] = "oDepthLE", + [VKD3DSPR_FORKINSTID ] = "vForkInstanceId", + [VKD3DSPR_FUNCTIONBODY ] = "fb", + [VKD3DSPR_FUNCTIONPOINTER ] = "fp", + [VKD3DSPR_GROUPSHAREDMEM ] = "g", + [VKD3DSPR_GSINSTID ] = "vGSInstanceID", + [VKD3DSPR_IDXTEMP ] = "x", + [VKD3DSPR_IMMCONST ] = "l", + [VKD3DSPR_IMMCONST64 ] = "d", + [VKD3DSPR_IMMCONSTBUFFER ] = "icb", + [VKD3DSPR_INCONTROLPOINT ] = "vicp", + [VKD3DSPR_INPUT ] = "v", + [VKD3DSPR_JOININSTID ] = "vJoinInstanceId", + [VKD3DSPR_LABEL ] = "l", + [VKD3DSPR_LOCALTHREADID ] = "vThreadIDInGroup", + [VKD3DSPR_LOCALTHREADINDEX ] = "vThreadIDInGroupFlattened", + [VKD3DSPR_LOOP ] = "aL", + [VKD3DSPR_NULL ] = "null", + [VKD3DSPR_OUTCONTROLPOINT ] = "vocp", + [VKD3DSPR_OUTPOINTID ] = "vOutputControlPointID", + [VKD3DSPR_OUTPUT ] = "o", + [VKD3DSPR_OUTSTENCILREF ] = "oStencilRef", + [VKD3DSPR_PARAMETER ] = "parameter", + [VKD3DSPR_PATCHCONST ] = "vpc", + [VKD3DSPR_POINT_COORD ] = "vPointCoord", + [VKD3DSPR_PREDICATE ] = "p", + [VKD3DSPR_PRIMID ] = "primID", + [VKD3DSPR_RASTERIZER ] = "rasterizer", + [VKD3DSPR_RESOURCE ] = "t", + [VKD3DSPR_SAMPLEMASK ] = "oMask", + [VKD3DSPR_SAMPLER ] = "s", + [VKD3DSPR_SSA ] = "sr", + [VKD3DSPR_STREAM ] = "m", + [VKD3DSPR_TEMP ] = "r", + [VKD3DSPR_TESSCOORD ] = "vDomainLocation", + [VKD3DSPR_TEXCRDOUT ] = "oT", + [VKD3DSPR_TEXTURE ] = "t", + [VKD3DSPR_THREADGROUPID ] = "vThreadGroupID", + [VKD3DSPR_THREADID ] = "vThreadID", + [VKD3DSPR_UAV ] = "u", + [VKD3DSPR_UNDEF ] = "undef", + [VKD3DSPR_WAVELANECOUNT ] = "vWaveLaneCount", + [VKD3DSPR_WAVELANEINDEX ] = "vWaveLaneIndex", +}; + struct vkd3d_d3d_asm_colours { const char *reset; @@ -377,22 +435,6 @@ struct vkd3d_d3d_asm_compiler const struct vkd3d_shader_instruction *current; }; -/* Convert floating point offset relative to a register file to an absolute - * offset for float constants. */ -static unsigned int shader_get_float_offset(enum vkd3d_shader_register_type register_type, UINT register_idx) -{ - switch (register_type) - { - case VKD3DSPR_CONST: return register_idx; - case VKD3DSPR_CONST2: return 2048 + register_idx; - case VKD3DSPR_CONST3: return 4096 + register_idx; - case VKD3DSPR_CONST4: return 6144 + register_idx; - default: - FIXME("Unsupported register type: %u.\n", register_type); - return register_idx; - } -} - static void shader_dump_global_flags(struct vkd3d_d3d_asm_compiler *compiler, enum vsir_global_flags global_flags) { unsigned int i; @@ -966,82 +1008,10 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const reg->type == VKD3DSPR_LABEL ? compiler->colours.label : compiler->colours.reg); switch (reg->type) { - case VKD3DSPR_TEMP: - vkd3d_string_buffer_printf(buffer, "r"); - break; - - case VKD3DSPR_INPUT: - vkd3d_string_buffer_printf(buffer, "v"); - break; - - case VKD3DSPR_CONST: - case VKD3DSPR_CONST2: - case VKD3DSPR_CONST3: - case VKD3DSPR_CONST4: - vkd3d_string_buffer_printf(buffer, "c"); - offset = shader_get_float_offset(reg->type, offset); - break; - - case VKD3DSPR_TEXTURE: /* vs: case VKD3DSPR_ADDR */ - vkd3d_string_buffer_printf(buffer, "%c", - compiler->shader_version.type == VKD3D_SHADER_TYPE_PIXEL ? 't' : 'a'); - break; - case VKD3DSPR_RASTOUT: vkd3d_string_buffer_printf(buffer, "%s", rastout_reg_names[offset]); break; - case VKD3DSPR_COLOROUT: - vkd3d_string_buffer_printf(buffer, "oC"); - break; - - case VKD3DSPR_DEPTHOUT: - vkd3d_string_buffer_printf(buffer, "oDepth"); - break; - - case VKD3DSPR_DEPTHOUTGE: - vkd3d_string_buffer_printf(buffer, "oDepthGE"); - break; - - case VKD3DSPR_DEPTHOUTLE: - vkd3d_string_buffer_printf(buffer, "oDepthLE"); - break; - - case VKD3DSPR_ATTROUT: - vkd3d_string_buffer_printf(buffer, "oD"); - break; - - case VKD3DSPR_TEXCRDOUT: - /* Vertex shaders >= 3.0 use general purpose output registers - * (VKD3DSPR_OUTPUT), which can include an address token. */ - if (vkd3d_shader_ver_ge(&compiler->shader_version, 3, 0)) - vkd3d_string_buffer_printf(buffer, "o"); - else - vkd3d_string_buffer_printf(buffer, "oT"); - break; - - case VKD3DSPR_CONSTINT: - vkd3d_string_buffer_printf(buffer, "i"); - break; - - case VKD3DSPR_CONSTBOOL: - vkd3d_string_buffer_printf(buffer, "b"); - break; - - case VKD3DSPR_LABEL: - vkd3d_string_buffer_printf(buffer, "l"); - break; - - case VKD3DSPR_LOOP: - vkd3d_string_buffer_printf(buffer, "aL"); - break; - - case VKD3DSPR_COMBINED_SAMPLER: - case VKD3DSPR_SAMPLER: - vkd3d_string_buffer_printf(buffer, "s"); - is_descriptor = true; - break; - case VKD3DSPR_MISCTYPE: if (offset > 1) vkd3d_string_buffer_printf(buffer, "%s%s", @@ -1050,156 +1020,20 @@ static void shader_print_register(struct vkd3d_d3d_asm_compiler *compiler, const vkd3d_string_buffer_printf(buffer, "%s", misctype_reg_names[offset]); break; - case VKD3DSPR_PREDICATE: - vkd3d_string_buffer_printf(buffer, "p"); - break; - - case VKD3DSPR_IMMCONST: - vkd3d_string_buffer_printf(buffer, "l"); - break; - - case VKD3DSPR_IMMCONST64: - vkd3d_string_buffer_printf(buffer, "d"); - break; - + case VKD3DSPR_COMBINED_SAMPLER: + case VKD3DSPR_SAMPLER: case VKD3DSPR_CONSTBUFFER: - vkd3d_string_buffer_printf(buffer, "cb"); - is_descriptor = true; - break; - - case VKD3DSPR_IMMCONSTBUFFER: - vkd3d_string_buffer_printf(buffer, "icb"); - break; - - case VKD3DSPR_PRIMID: - vkd3d_string_buffer_printf(buffer, "primID"); - break; - - case VKD3DSPR_NULL: - vkd3d_string_buffer_printf(buffer, "null"); - break; - - case VKD3DSPR_RASTERIZER: - vkd3d_string_buffer_printf(buffer, "rasterizer"); - break; - case VKD3DSPR_RESOURCE: - vkd3d_string_buffer_printf(buffer, "t"); - is_descriptor = true; - break; - case VKD3DSPR_UAV: - vkd3d_string_buffer_printf(buffer, "u"); is_descriptor = true; - break; - - case VKD3DSPR_OUTPOINTID: - vkd3d_string_buffer_printf(buffer, "vOutputControlPointID"); - break; - - case VKD3DSPR_FORKINSTID: - vkd3d_string_buffer_printf(buffer, "vForkInstanceId"); - break; - - case VKD3DSPR_JOININSTID: - vkd3d_string_buffer_printf(buffer, "vJoinInstanceId"); - break; - - case VKD3DSPR_INCONTROLPOINT: - vkd3d_string_buffer_printf(buffer, "vicp"); - break; - - case VKD3DSPR_OUTCONTROLPOINT: - vkd3d_string_buffer_printf(buffer, "vocp"); - break; - - case VKD3DSPR_PATCHCONST: - vkd3d_string_buffer_printf(buffer, "vpc"); - break; - - case VKD3DSPR_TESSCOORD: - vkd3d_string_buffer_printf(buffer, "vDomainLocation"); - break; - - case VKD3DSPR_GROUPSHAREDMEM: - vkd3d_string_buffer_printf(buffer, "g"); - break; - - case VKD3DSPR_THREADID: - vkd3d_string_buffer_printf(buffer, "vThreadID"); - break; - - case VKD3DSPR_THREADGROUPID: - vkd3d_string_buffer_printf(buffer, "vThreadGroupID"); - break; - - case VKD3DSPR_LOCALTHREADID: - vkd3d_string_buffer_printf(buffer, "vThreadIDInGroup"); - break; - - case VKD3DSPR_LOCALTHREADINDEX: - vkd3d_string_buffer_printf(buffer, "vThreadIDInGroupFlattened"); - break; - - case VKD3DSPR_IDXTEMP: - vkd3d_string_buffer_printf(buffer, "x"); - break; - - case VKD3DSPR_STREAM: - vkd3d_string_buffer_printf(buffer, "m"); - break; - - case VKD3DSPR_FUNCTIONBODY: - vkd3d_string_buffer_printf(buffer, "fb"); - break; - - case VKD3DSPR_FUNCTIONPOINTER: - vkd3d_string_buffer_printf(buffer, "fp"); - break; - - case VKD3DSPR_COVERAGE: - vkd3d_string_buffer_printf(buffer, "vCoverage"); - break; - - case VKD3DSPR_SAMPLEMASK: - vkd3d_string_buffer_printf(buffer, "oMask"); - break; - - case VKD3DSPR_GSINSTID: - vkd3d_string_buffer_printf(buffer, "vGSInstanceID"); - break; - - case VKD3DSPR_OUTSTENCILREF: - vkd3d_string_buffer_printf(buffer, "oStencilRef"); - break; - - case VKD3DSPR_UNDEF: - vkd3d_string_buffer_printf(buffer, "undef"); - break; - - case VKD3DSPR_SSA: - vkd3d_string_buffer_printf(buffer, "sr"); - break; - - case VKD3DSPR_WAVELANECOUNT: - vkd3d_string_buffer_printf(buffer, "vWaveLaneCount"); - break; - - case VKD3DSPR_WAVELANEINDEX: - vkd3d_string_buffer_printf(buffer, "vWaveLaneIndex"); - break; - - case VKD3DSPR_PARAMETER: - vkd3d_string_buffer_printf(buffer, "parameter"); - break; - - case VKD3DSPR_POINT_COORD: - vkd3d_string_buffer_printf(buffer, "vPointCoord"); - break; + /* fall through */ default: - vkd3d_string_buffer_printf(buffer, "%s%s", - compiler->colours.error, reg->type, compiler->colours.reset); + if (reg->type < ARRAY_SIZE(shader_register_names) && shader_register_names[reg->type]) + vkd3d_string_buffer_printf(buffer, "%s", shader_register_names[reg->type]); + else + vkd3d_string_buffer_printf(buffer, "%s%s", + compiler->colours.error, reg->type, compiler->colours.reset); break; } @@ -2132,8 +1966,7 @@ static void shader_dump_instruction(struct vkd3d_d3d_asm_compiler *compiler, case VKD3DSIH_DEF: vkd3d_string_buffer_printf(buffer, " %sc%u%s", compiler->colours.reg, - shader_get_float_offset(ins->dst[0].reg.type, ins->dst[0].reg.idx[0].offset), - compiler->colours.reset); + ins->dst[0].reg.idx[0].offset, compiler->colours.reset); shader_print_float_literal(compiler, " = ", ins->src[0].reg.u.immconst_f32[0], ""); shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[1], ""); shader_print_float_literal(compiler, ", ", ins->src[0].reg.u.immconst_f32[2], ""); diff --git a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c index a931883e8d1..58e35cf22e8 100644 --- a/libs/vkd3d/libs/vkd3d-shader/d3dbc.c +++ b/libs/vkd3d/libs/vkd3d-shader/d3dbc.c @@ -89,6 +89,32 @@ #define VKD3D_SM1_VERSION_MAJOR(version) (((version) >> 8u) & 0xffu) #define VKD3D_SM1_VERSION_MINOR(version) (((version) >> 0u) & 0xffu) +enum vkd3d_sm1_register_type +{ + VKD3D_SM1_REG_TEMP = 0x00, + VKD3D_SM1_REG_INPUT = 0x01, + VKD3D_SM1_REG_CONST = 0x02, + VKD3D_SM1_REG_ADDR = 0x03, + VKD3D_SM1_REG_TEXTURE = 0x03, + VKD3D_SM1_REG_RASTOUT = 0x04, + VKD3D_SM1_REG_ATTROUT = 0x05, + VKD3D_SM1_REG_TEXCRDOUT = 0x06, + VKD3D_SM1_REG_OUTPUT = 0x06, + VKD3D_SM1_REG_CONSTINT = 0x07, + VKD3D_SM1_REG_COLOROUT = 0x08, + VKD3D_SM1_REG_DEPTHOUT = 0x09, + VKD3D_SM1_REG_SAMPLER = 0x0a, + VKD3D_SM1_REG_CONST2 = 0x0b, + VKD3D_SM1_REG_CONST3 = 0x0c, + VKD3D_SM1_REG_CONST4 = 0x0d, + VKD3D_SM1_REG_CONSTBOOL = 0x0e, + VKD3D_SM1_REG_LOOP = 0x0f, + VKD3D_SM1_REG_TEMPFLOAT16 = 0x10, + VKD3D_SM1_REG_MISCTYPE = 0x11, + VKD3D_SM1_REG_LABEL = 0x12, + VKD3D_SM1_REG_PREDICATE = 0x13, +}; + enum vkd3d_sm1_address_mode_type { VKD3D_SM1_ADDRESS_MODE_ABSOLUTE = 0x0, @@ -388,6 +414,34 @@ static const struct vkd3d_sm1_opcode_info ps_opcode_table[] = {0, 0, 0, VKD3DSIH_INVALID}, }; +static const struct +{ + enum vkd3d_sm1_register_type d3dbc_type; + enum vkd3d_shader_register_type vsir_type; +} +register_types[] = +{ + {VKD3D_SM1_REG_TEMP, VKD3DSPR_TEMP}, + {VKD3D_SM1_REG_INPUT, VKD3DSPR_INPUT}, + {VKD3D_SM1_REG_CONST, VKD3DSPR_CONST}, + {VKD3D_SM1_REG_ADDR, VKD3DSPR_ADDR}, + {VKD3D_SM1_REG_TEXTURE, VKD3DSPR_TEXTURE}, + {VKD3D_SM1_REG_RASTOUT, VKD3DSPR_RASTOUT}, + {VKD3D_SM1_REG_ATTROUT, VKD3DSPR_ATTROUT}, + {VKD3D_SM1_REG_OUTPUT, VKD3DSPR_OUTPUT}, + {VKD3D_SM1_REG_TEXCRDOUT, VKD3DSPR_TEXCRDOUT}, + {VKD3D_SM1_REG_CONSTINT, VKD3DSPR_CONSTINT}, + {VKD3D_SM1_REG_COLOROUT, VKD3DSPR_COLOROUT}, + {VKD3D_SM1_REG_DEPTHOUT, VKD3DSPR_DEPTHOUT}, + {VKD3D_SM1_REG_SAMPLER, VKD3DSPR_COMBINED_SAMPLER}, + {VKD3D_SM1_REG_CONSTBOOL, VKD3DSPR_CONSTBOOL}, + {VKD3D_SM1_REG_LOOP, VKD3DSPR_LOOP}, + {VKD3D_SM1_REG_TEMPFLOAT16, VKD3DSPR_TEMPFLOAT16}, + {VKD3D_SM1_REG_MISCTYPE, VKD3DSPR_MISCTYPE}, + {VKD3D_SM1_REG_LABEL, VKD3DSPR_LABEL}, + {VKD3D_SM1_REG_PREDICATE, VKD3DSPR_PREDICATE}, +}; + static const enum vkd3d_shader_resource_type resource_type_table[] = { /* VKD3D_SM1_RESOURCE_UNKNOWN */ VKD3D_SHADER_RESOURCE_NONE, @@ -453,6 +507,7 @@ static unsigned int idx_count_from_reg_type(enum vkd3d_shader_register_type reg_ switch (reg_type) { case VKD3DSPR_DEPTHOUT: + case VKD3DSPR_ADDR: return 0; default: @@ -460,52 +515,82 @@ static unsigned int idx_count_from_reg_type(enum vkd3d_shader_register_type reg_ } } -static void shader_sm1_parse_src_param(uint32_t param, struct vkd3d_shader_src_param *rel_addr, - struct vkd3d_shader_src_param *src) +static enum vkd3d_shader_register_type parse_register_type( + struct vkd3d_shader_sm1_parser *sm1, uint32_t param, unsigned int *index_offset) { - enum vkd3d_shader_register_type reg_type = ((param & VKD3D_SM1_REGISTER_TYPE_MASK) >> VKD3D_SM1_REGISTER_TYPE_SHIFT) + enum vkd3d_sm1_register_type d3dbc_type = ((param & VKD3D_SM1_REGISTER_TYPE_MASK) >> VKD3D_SM1_REGISTER_TYPE_SHIFT) | ((param & VKD3D_SM1_REGISTER_TYPE_MASK2) >> VKD3D_SM1_REGISTER_TYPE_SHIFT2); - unsigned int idx_count = idx_count_from_reg_type(reg_type); - vsir_register_init(&src->reg, reg_type, VKD3D_DATA_FLOAT, idx_count); - src->reg.precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT; - src->reg.non_uniform = false; - if (idx_count == 1) + *index_offset = 0; + + if (d3dbc_type == VKD3D_SM1_REG_CONST2) { - src->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK; - src->reg.idx[0].rel_addr = rel_addr; + *index_offset = 2048; + return VKD3DSPR_CONST; } - if (src->reg.type == VKD3DSPR_SAMPLER) - src->reg.dimension = VSIR_DIMENSION_NONE; - else if (src->reg.type == VKD3DSPR_DEPTHOUT) - src->reg.dimension = VSIR_DIMENSION_SCALAR; - else - src->reg.dimension = VSIR_DIMENSION_VEC4; - src->swizzle = swizzle_from_sm1((param & VKD3D_SM1_SWIZZLE_MASK) >> VKD3D_SM1_SWIZZLE_SHIFT); - src->modifiers = (param & VKD3D_SM1_SRC_MODIFIER_MASK) >> VKD3D_SM1_SRC_MODIFIER_SHIFT; + + if (d3dbc_type == VKD3D_SM1_REG_CONST3) + { + *index_offset = 4096; + return VKD3DSPR_CONST; + } + + if (d3dbc_type == VKD3D_SM1_REG_CONST4) + { + *index_offset = 6144; + return VKD3DSPR_CONST; + } + + if (d3dbc_type == VKD3D_SM1_REG_ADDR) + return sm1->p.program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL ? VKD3DSPR_TEXTURE : VKD3DSPR_ADDR; + if (d3dbc_type == VKD3D_SM1_REG_TEXCRDOUT) + return vkd3d_shader_ver_ge(&sm1->p.program->shader_version, 3, 0) ? VKD3DSPR_OUTPUT : VKD3DSPR_TEXCRDOUT; + + for (unsigned int i = 0; i < ARRAY_SIZE(register_types); ++i) + { + if (register_types[i].d3dbc_type == d3dbc_type) + return register_types[i].vsir_type; + } + + return VKD3DSPR_INVALID; } -static void shader_sm1_parse_dst_param(uint32_t param, struct vkd3d_shader_src_param *rel_addr, - struct vkd3d_shader_dst_param *dst) +static void d3dbc_parse_register(struct vkd3d_shader_sm1_parser *d3dbc, + struct vkd3d_shader_register *reg, uint32_t param, struct vkd3d_shader_src_param *rel_addr) { - enum vkd3d_shader_register_type reg_type = ((param & VKD3D_SM1_REGISTER_TYPE_MASK) >> VKD3D_SM1_REGISTER_TYPE_SHIFT) - | ((param & VKD3D_SM1_REGISTER_TYPE_MASK2) >> VKD3D_SM1_REGISTER_TYPE_SHIFT2); - unsigned int idx_count = idx_count_from_reg_type(reg_type); - - vsir_register_init(&dst->reg, reg_type, VKD3D_DATA_FLOAT, idx_count); - dst->reg.precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT; - dst->reg.non_uniform = false; + enum vkd3d_shader_register_type reg_type; + unsigned int index_offset, idx_count; + + reg_type = parse_register_type(d3dbc, param, &index_offset); + idx_count = idx_count_from_reg_type(reg_type); + vsir_register_init(reg, reg_type, VKD3D_DATA_FLOAT, idx_count); + reg->precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT; + reg->non_uniform = false; if (idx_count == 1) { - dst->reg.idx[0].offset = param & VKD3D_SM1_REGISTER_NUMBER_MASK; - dst->reg.idx[0].rel_addr = rel_addr; + reg->idx[0].offset = index_offset + (param & VKD3D_SM1_REGISTER_NUMBER_MASK); + reg->idx[0].rel_addr = rel_addr; } - if (dst->reg.type == VKD3DSPR_SAMPLER) - dst->reg.dimension = VSIR_DIMENSION_NONE; - else if (dst->reg.type == VKD3DSPR_DEPTHOUT) - dst->reg.dimension = VSIR_DIMENSION_SCALAR; + if (reg->type == VKD3DSPR_SAMPLER) + reg->dimension = VSIR_DIMENSION_NONE; + else if (reg->type == VKD3DSPR_DEPTHOUT) + reg->dimension = VSIR_DIMENSION_SCALAR; else - dst->reg.dimension = VSIR_DIMENSION_VEC4; + reg->dimension = VSIR_DIMENSION_VEC4; +} + +static void shader_sm1_parse_src_param(struct vkd3d_shader_sm1_parser *sm1, uint32_t param, + struct vkd3d_shader_src_param *rel_addr, struct vkd3d_shader_src_param *src) +{ + d3dbc_parse_register(sm1, &src->reg, param, rel_addr); + src->swizzle = swizzle_from_sm1((param & VKD3D_SM1_SWIZZLE_MASK) >> VKD3D_SM1_SWIZZLE_SHIFT); + src->modifiers = (param & VKD3D_SM1_SRC_MODIFIER_MASK) >> VKD3D_SM1_SRC_MODIFIER_SHIFT; +} + +static void shader_sm1_parse_dst_param(struct vkd3d_shader_sm1_parser *sm1, uint32_t param, + struct vkd3d_shader_src_param *rel_addr, struct vkd3d_shader_dst_param *dst) +{ + d3dbc_parse_register(sm1, &dst->reg, param, rel_addr); dst->modifiers = (param & VKD3D_SM1_DST_MODIFIER_MASK) >> VKD3D_SM1_DST_MODIFIER_SHIFT; dst->shift = (param & VKD3D_SM1_DSTSHIFT_MASK) >> VKD3D_SM1_DSTSHIFT_SHIFT; @@ -686,26 +771,18 @@ static bool add_signature_element_from_register(struct vkd3d_shader_sm1_parser * VKD3D_SHADER_SV_NONE, SM1_COLOR_REGISTER_OFFSET + register_index, is_dcl, mask); case VKD3DSPR_TEXTURE: - /* For vertex shaders, this is ADDR. */ - if (version->type == VKD3D_SHADER_TYPE_VERTEX) - return true; return add_signature_element(sm1, false, "TEXCOORD", register_index, VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask); + case VKD3DSPR_TEXCRDOUT: + return add_signature_element(sm1, true, "TEXCOORD", register_index, + VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask); + case VKD3DSPR_OUTPUT: if (version->type == VKD3D_SHADER_TYPE_VERTEX) { - /* For sm < 2 vertex shaders, this is TEXCRDOUT. - * - * For sm3 vertex shaders, this is OUTPUT, but we already - * should have had a DCL instruction. */ - if (version->major == 3) - { - add_signature_mask(sm1, true, register_index, mask); - return true; - } - return add_signature_element(sm1, true, "TEXCOORD", register_index, - VKD3D_SHADER_SV_NONE, register_index, is_dcl, mask); + add_signature_mask(sm1, true, register_index, mask); + return true; } /* fall through */ @@ -842,18 +919,6 @@ static void shader_sm1_scan_register(struct vkd3d_shader_sm1_parser *sm1, record_constant_register(sm1, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER, register_index, from_def); break; - case VKD3DSPR_CONST2: - record_constant_register(sm1, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER, 2048 + register_index, from_def); - break; - - case VKD3DSPR_CONST3: - record_constant_register(sm1, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER, 4096 + register_index, from_def); - break; - - case VKD3DSPR_CONST4: - record_constant_register(sm1, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER, 6144 + register_index, from_def); - break; - case VKD3DSPR_CONSTINT: record_constant_register(sm1, VKD3D_SHADER_D3DBC_INT_CONSTANT_REGISTER, register_index, from_def); break; @@ -961,9 +1026,9 @@ static void shader_sm1_read_src_param(struct vkd3d_shader_sm1_parser *sm1, const sm1->abort = true; return; } - shader_sm1_parse_src_param(addr_token, NULL, src_rel_addr); + shader_sm1_parse_src_param(sm1, addr_token, NULL, src_rel_addr); } - shader_sm1_parse_src_param(token, src_rel_addr, src_param); + shader_sm1_parse_src_param(sm1, token, src_rel_addr, src_param); } static void shader_sm1_read_dst_param(struct vkd3d_shader_sm1_parser *sm1, const uint32_t **ptr, @@ -982,9 +1047,9 @@ static void shader_sm1_read_dst_param(struct vkd3d_shader_sm1_parser *sm1, const sm1->abort = true; return; } - shader_sm1_parse_src_param(addr_token, NULL, dst_rel_addr); + shader_sm1_parse_src_param(sm1, addr_token, NULL, dst_rel_addr); } - shader_sm1_parse_dst_param(token, dst_rel_addr, dst_param); + shader_sm1_parse_dst_param(sm1, token, dst_rel_addr, dst_param); if (dst_param->reg.type == VKD3DSPR_RASTOUT && dst_param->reg.idx[0].offset == VSIR_RASTOUT_POINT_SIZE) sm1->p.program->has_point_size = true; @@ -1027,7 +1092,7 @@ static void shader_sm1_read_semantic(struct vkd3d_shader_sm1_parser *sm1, semantic->resource_data_type[1] = VKD3D_DATA_FLOAT; semantic->resource_data_type[2] = VKD3D_DATA_FLOAT; semantic->resource_data_type[3] = VKD3D_DATA_FLOAT; - shader_sm1_parse_dst_param(dst_token, NULL, &semantic->resource.reg); + shader_sm1_parse_dst_param(sm1, dst_token, NULL, &semantic->resource.reg); range = &semantic->resource.range; range->space = 0; range->first = range->last = semantic->resource.reg.reg.idx[0].offset; @@ -1621,10 +1686,33 @@ static void d3dbc_write_comment(struct d3dbc_compiler *d3dbc, set_u32(buffer, offset, vkd3d_make_u32(VKD3D_SM1_OP_COMMENT, (end - start) / sizeof(uint32_t))); } -static uint32_t sm1_encode_register_type(enum vkd3d_shader_register_type type) +static enum vkd3d_sm1_register_type d3dbc_register_type_from_vsir(const struct vkd3d_shader_register *reg) +{ + if (reg->type == VKD3DSPR_CONST) + { + if (reg->idx[0].offset >= 6144) + return VKD3D_SM1_REG_CONST4; + if (reg->idx[0].offset >= 4096) + return VKD3D_SM1_REG_CONST3; + if (reg->idx[0].offset >= 2048) + return VKD3D_SM1_REG_CONST2; + } + + for (unsigned int i = 0; i < ARRAY_SIZE(register_types); ++i) + { + if (register_types[i].vsir_type == reg->type) + return register_types[i].d3dbc_type; + } + + vkd3d_unreachable(); +} + +static uint32_t sm1_encode_register_type(const struct vkd3d_shader_register *reg) { - return ((type << VKD3D_SM1_REGISTER_TYPE_SHIFT) & VKD3D_SM1_REGISTER_TYPE_MASK) - | ((type << VKD3D_SM1_REGISTER_TYPE_SHIFT2) & VKD3D_SM1_REGISTER_TYPE_MASK2); + enum vkd3d_sm1_register_type sm1_type = d3dbc_register_type_from_vsir(reg); + + return ((sm1_type << VKD3D_SM1_REGISTER_TYPE_SHIFT) & VKD3D_SM1_REGISTER_TYPE_MASK) + | ((sm1_type << VKD3D_SM1_REGISTER_TYPE_SHIFT2) & VKD3D_SM1_REGISTER_TYPE_MASK2); } static uint32_t swizzle_from_vsir(uint32_t swizzle) @@ -1673,17 +1761,19 @@ static void write_sm1_dst_register(struct vkd3d_bytecode_buffer *buffer, const s { VKD3D_ASSERT(reg->write_mask); put_u32(buffer, VKD3D_SM1_INSTRUCTION_PARAMETER - | sm1_encode_register_type(reg->reg.type) + | sm1_encode_register_type(®->reg) | (reg->modifiers << VKD3D_SM1_DST_MODIFIER_SHIFT) - | (reg->write_mask << VKD3D_SM1_WRITEMASK_SHIFT) | reg->reg.idx[0].offset); + | (reg->write_mask << VKD3D_SM1_WRITEMASK_SHIFT) + | (reg->reg.idx[0].offset & VKD3D_SM1_REGISTER_NUMBER_MASK)); } static void write_sm1_src_register(struct vkd3d_bytecode_buffer *buffer, const struct vkd3d_shader_src_param *reg) { put_u32(buffer, VKD3D_SM1_INSTRUCTION_PARAMETER - | sm1_encode_register_type(reg->reg.type) + | sm1_encode_register_type(®->reg) | (reg->modifiers << VKD3D_SM1_SRC_MODIFIER_SHIFT) - | (swizzle_from_vsir(reg->swizzle) << VKD3D_SM1_SWIZZLE_SHIFT) | reg->reg.idx[0].offset); + | (swizzle_from_vsir(reg->swizzle) << VKD3D_SM1_SWIZZLE_SHIFT) + | (reg->reg.idx[0].offset & VKD3D_SM1_REGISTER_NUMBER_MASK)); } static void d3dbc_write_instruction(struct d3dbc_compiler *d3dbc, const struct vkd3d_shader_instruction *ins) diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c index 4493602dfb7..399c2b67eae 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c @@ -430,6 +430,8 @@ enum dx_intrinsic_opcode DX_DERIV_COARSEY = 84, DX_DERIV_FINEX = 85, DX_DERIV_FINEY = 86, + DX_EVAL_SAMPLE_INDEX = 88, + DX_EVAL_CENTROID = 89, DX_SAMPLE_INDEX = 90, DX_COVERAGE = 91, DX_THREAD_ID = 93, @@ -5098,6 +5100,53 @@ static void sm6_parser_emit_dx_dot(struct sm6_parser *sm6, enum dx_intrinsic_opc instruction_dst_param_init_ssa_scalar(ins, sm6); } +static void sm6_parser_emit_dx_eval_attrib(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, + const struct sm6_value **operands, struct function_emission_state *state) +{ + struct vkd3d_shader_instruction *ins = state->ins; + struct vkd3d_shader_src_param *src_params; + const struct shader_signature *signature; + unsigned int row_index, column_index; + const struct signature_element *e; + + row_index = sm6_value_get_constant_uint(operands[0]); + column_index = sm6_value_get_constant_uint(operands[2]); + + signature = &sm6->p.program->input_signature; + if (row_index >= signature->element_count) + { + WARN("Invalid row index %u.\n", row_index); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid input row index %u for an attribute evaluation.", row_index); + return; + } + + e = &signature->elements[row_index]; + if (column_index >= VKD3D_VEC4_SIZE || !(e->mask & (1 << column_index))) + { + WARN("Invalid column index %u.\n", column_index); + vkd3d_shader_parser_error(&sm6->p, VKD3D_SHADER_ERROR_DXIL_INVALID_OPERAND, + "Invalid input column index %u for an attribute evaluation.", column_index); + return; + } + + vsir_instruction_init(ins, &sm6->p.location, (op == DX_EVAL_CENTROID) + ? VKD3DSIH_EVAL_CENTROID : VKD3DSIH_EVAL_SAMPLE_INDEX); + + if (!(src_params = instruction_src_params_alloc(ins, 1 + (op == DX_EVAL_SAMPLE_INDEX), sm6))) + return; + + src_params[0].reg = sm6->input_params[row_index].reg; + src_param_init_scalar(&src_params[0], column_index); + if (e->register_count > 1) + register_index_address_init(&src_params[0].reg.idx[0], operands[1], sm6); + + if (op == DX_EVAL_SAMPLE_INDEX) + src_param_init_from_value(&src_params[1], operands[3]); + + instruction_dst_param_init_ssa_scalar(ins, sm6); +} + static void sm6_parser_emit_dx_fabs(struct sm6_parser *sm6, enum dx_intrinsic_opcode op, const struct sm6_value **operands, struct function_emission_state *state) { @@ -6288,6 +6337,8 @@ static const struct sm6_dx_opcode_info sm6_dx_op_table[] = [DX_DOT4 ] = {"g", "RRRRRRRR", sm6_parser_emit_dx_dot}, [DX_EMIT_STREAM ] = {"v", "c", sm6_parser_emit_dx_stream}, [DX_EMIT_THEN_CUT_STREAM ] = {"v", "c", sm6_parser_emit_dx_stream}, + [DX_EVAL_CENTROID ] = {"o", "cic", sm6_parser_emit_dx_eval_attrib}, + [DX_EVAL_SAMPLE_INDEX ] = {"o", "cici", sm6_parser_emit_dx_eval_attrib}, [DX_EXP ] = {"g", "R", sm6_parser_emit_dx_unary}, [DX_FABS ] = {"g", "R", sm6_parser_emit_dx_fabs}, [DX_FIRST_BIT_HI ] = {"i", "m", sm6_parser_emit_dx_unary}, diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h index 7c9547a1c01..2acc003c9a1 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h @@ -861,6 +861,10 @@ enum hlsl_resource_load_type HLSL_RESOURCE_GATHER_GREEN, HLSL_RESOURCE_GATHER_BLUE, HLSL_RESOURCE_GATHER_ALPHA, + HLSL_RESOURCE_GATHER_CMP_RED, + HLSL_RESOURCE_GATHER_CMP_GREEN, + HLSL_RESOURCE_GATHER_CMP_BLUE, + HLSL_RESOURCE_GATHER_CMP_ALPHA, HLSL_RESOURCE_SAMPLE_INFO, HLSL_RESOURCE_RESINFO, }; diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y index a3814a810b5..dbed11cd8b3 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y @@ -6124,6 +6124,87 @@ static bool add_gather_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc return true; } +static bool add_gather_cmp_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *object, + const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) +{ + const struct hlsl_type *object_type = object->data_type; + struct hlsl_resource_load_params load_params = {0}; + unsigned int sampler_dim, offset_dim; + const struct hlsl_type *sampler_type; + struct hlsl_ir_node *load; + + sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); + offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); + + if (!strcmp(name, "GatherCmpGreen")) + load_params.type = HLSL_RESOURCE_GATHER_CMP_GREEN; + else if (!strcmp(name, "GatherCmpBlue")) + load_params.type = HLSL_RESOURCE_GATHER_CMP_BLUE; + else if (!strcmp(name, "GatherCmpAlpha")) + load_params.type = HLSL_RESOURCE_GATHER_CMP_ALPHA; + else + load_params.type = HLSL_RESOURCE_GATHER_CMP_RED; + + if (!strcmp(name, "GatherCmp") || !offset_dim) + { + if (params->args_count < 3 || params->args_count > 4 + !!offset_dim) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, + "Wrong number of arguments to method '%s': expected from 3 to %u, but got %u.", + name, 4 + !!offset_dim, params->args_count); + return false; + } + } + else if (params->args_count < 3 || params->args_count == 6 || params->args_count > 8) + { + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, + "Wrong number of arguments to method '%s': expected 3, 4, 5, 7, or 8, but got %u.", + name, params->args_count); + return false; + } + + if (params->args_count == 5 || params->args_count == 8) + { + hlsl_fixme(ctx, loc, "Tiled resource status argument."); + } + else if (offset_dim && params->args_count > 3) + { + if (!(load_params.texel_offset = add_implicit_conversion(ctx, block, params->args[3], + hlsl_get_vector_type(ctx, HLSL_TYPE_INT, offset_dim), loc))) + return false; + } + + sampler_type = params->args[0]->data_type; + if (sampler_type->class != HLSL_CLASS_SAMPLER || sampler_type->sampler_dim != HLSL_SAMPLER_DIM_COMPARISON) + { + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(ctx, sampler_type))) + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Wrong type for argument 0 of %s(): expected 'SamplerComparisonState', but got '%s'.", + name, string->buffer); + hlsl_release_string_buffer(ctx, string); + return false; + } + + if (!(load_params.coords = add_implicit_conversion(ctx, block, params->args[1], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) + return false; + + if (!(load_params.cmp = add_implicit_conversion(ctx, block, params->args[2], + hlsl_get_scalar_type(ctx, HLSL_TYPE_FLOAT), loc))) + return false; + + load_params.format = hlsl_get_vector_type(ctx, object_type->e.resource.format->e.numeric.type, 4); + load_params.resource = object; + load_params.sampler = params->args[0]; + + if (!(load = hlsl_new_resource_load(ctx, &load_params, loc))) + return false; + hlsl_block_add_instr(block, load); + return true; +} + static bool add_assignment_from_component(struct hlsl_ctx *ctx, struct hlsl_block *instrs, struct hlsl_ir_node *dest, struct hlsl_ir_node *src, unsigned int component, const struct vkd3d_shader_location *loc) { @@ -6491,6 +6572,11 @@ texture_methods[] = { "Gather", add_gather_method_call, "00010101001000" }, { "GatherAlpha", add_gather_method_call, "00010101001000" }, { "GatherBlue", add_gather_method_call, "00010101001000" }, + { "GatherCmp", add_gather_cmp_method_call, "00010101001000" }, + { "GatherCmpAlpha", add_gather_cmp_method_call, "00010101001000" }, + { "GatherCmpBlue", add_gather_cmp_method_call, "00010101001000" }, + { "GatherCmpGreen", add_gather_cmp_method_call, "00010101001000" }, + { "GatherCmpRed", add_gather_cmp_method_call, "00010101001000" }, { "GatherGreen", add_gather_method_call, "00010101001000" }, { "GatherRed", add_gather_method_call, "00010101001000" }, diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c index a43ea53089e..08f139f5e8f 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c @@ -2949,6 +2949,10 @@ static bool lower_combined_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *in case HLSL_RESOURCE_GATHER_GREEN: case HLSL_RESOURCE_GATHER_BLUE: case HLSL_RESOURCE_GATHER_ALPHA: + case HLSL_RESOURCE_GATHER_CMP_RED: + case HLSL_RESOURCE_GATHER_CMP_GREEN: + case HLSL_RESOURCE_GATHER_CMP_BLUE: + case HLSL_RESOURCE_GATHER_CMP_ALPHA: case HLSL_RESOURCE_RESINFO: case HLSL_RESOURCE_SAMPLE_CMP: case HLSL_RESOURCE_SAMPLE_CMP_LZ: @@ -3537,6 +3541,51 @@ static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru return true; } +static bool lower_resource_load_bias(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) +{ + struct hlsl_ir_node *swizzle, *store; + struct hlsl_ir_resource_load *load; + struct hlsl_ir_load *tmp_load; + struct hlsl_ir_var *tmp_var; + struct hlsl_deref deref; + + if (instr->type != HLSL_IR_RESOURCE_LOAD) + return false; + load = hlsl_ir_resource_load(instr); + if (load->load_type != HLSL_RESOURCE_SAMPLE_LOD + && load->load_type != HLSL_RESOURCE_SAMPLE_LOD_BIAS) + return false; + + if (!load->lod.node) + return false; + + if (!(tmp_var = hlsl_new_synthetic_var(ctx, "coords-with-lod", + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4), &instr->loc))) + return false; + + if (!(swizzle = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, X, X, X), 4, load->lod.node, &load->lod.node->loc))) + return false; + list_add_before(&instr->entry, &swizzle->entry); + + if (!(store = hlsl_new_simple_store(ctx, tmp_var, swizzle))) + return false; + list_add_before(&instr->entry, &store->entry); + + hlsl_init_simple_deref_from_var(&deref, tmp_var); + if (!(store = hlsl_new_store_index(ctx, &deref, NULL, load->coords.node, 0, &instr->loc))) + return false; + list_add_before(&instr->entry, &store->entry); + + if (!(tmp_load = hlsl_new_var_load(ctx, tmp_var, &instr->loc))) + return false; + list_add_before(&instr->entry, &tmp_load->node.entry); + + hlsl_src_remove(&load->coords); + hlsl_src_from_node(&load->coords, &tmp_load->node); + hlsl_src_remove(&load->lod); + return true; +} + static bool lower_comparison_operators(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) { @@ -9596,18 +9645,18 @@ static bool sm4_generate_vsir_instr_sample(struct hlsl_ctx *ctx, } static bool sm4_generate_vsir_instr_gather(struct hlsl_ctx *ctx, struct vsir_program *program, - const struct hlsl_ir_resource_load *load, uint32_t swizzle) + const struct hlsl_ir_resource_load *load, uint32_t swizzle, bool compare) { const struct vkd3d_shader_version *version = &program->shader_version; const struct hlsl_ir_node *texel_offset = load->texel_offset.node; const struct hlsl_ir_node *coords = load->coords.node; const struct hlsl_deref *resource = &load->resource; + enum vkd3d_shader_opcode opcode = VKD3DSIH_GATHER4; const struct hlsl_deref *sampler = &load->sampler; const struct hlsl_ir_node *instr = &load->node; + unsigned int src_count = 3, current_arg = 0; struct vkd3d_shader_instruction *ins; - enum vkd3d_shader_opcode opcode; - opcode = VKD3DSIH_GATHER4; if (texel_offset && !sm4_generate_vsir_validate_texel_offset_aoffimmi(texel_offset)) { if (!vkd3d_shader_ver_ge(version, 5, 0)) @@ -9617,50 +9666,40 @@ static bool sm4_generate_vsir_instr_gather(struct hlsl_ctx *ctx, struct vsir_pro return false; } opcode = VKD3DSIH_GATHER4_PO; + ++src_count; } - if (opcode == VKD3DSIH_GATHER4) + if (compare) { - if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, 3))) - return false; + opcode = opcode == VKD3DSIH_GATHER4 ? VKD3DSIH_GATHER4_C : VKD3DSIH_GATHER4_PO_C; + ++src_count; + } - vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); - vsir_src_from_hlsl_node(&ins->src[0], ctx, coords, VKD3DSP_WRITEMASK_ALL); - sm4_generate_vsir_encode_texel_offset_as_aoffimmi(ins, texel_offset); + if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, src_count))) + return false; - if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program, - &ins->src[1], resource, ins->dst[0].write_mask, &instr->loc)) - return false; + vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); + vsir_src_from_hlsl_node(&ins->src[current_arg++], ctx, coords, VKD3DSP_WRITEMASK_ALL); - if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program, - &ins->src[2], sampler, VKD3DSP_WRITEMASK_ALL, &instr->loc)) - return false; - ins->src[2].reg.dimension = VSIR_DIMENSION_VEC4; - ins->src[2].swizzle = swizzle; - } - else if (opcode == VKD3DSIH_GATHER4_PO) - { - if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, 4))) - return false; + if (opcode == VKD3DSIH_GATHER4_PO || opcode == VKD3DSIH_GATHER4_PO_C) + vsir_src_from_hlsl_node(&ins->src[current_arg++], ctx, texel_offset, VKD3DSP_WRITEMASK_ALL); + else + sm4_generate_vsir_encode_texel_offset_as_aoffimmi(ins, texel_offset); - vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr); - vsir_src_from_hlsl_node(&ins->src[0], ctx, coords, VKD3DSP_WRITEMASK_ALL); - vsir_src_from_hlsl_node(&ins->src[1], ctx, texel_offset, VKD3DSP_WRITEMASK_ALL); + if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program, + &ins->src[current_arg++], resource, ins->dst[0].write_mask, &instr->loc)) + return false; - if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program, - &ins->src[2], resource, ins->dst[0].write_mask, &instr->loc)) - return false; + if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program, + &ins->src[current_arg], sampler, VKD3DSP_WRITEMASK_ALL, &instr->loc)) + return false; + ins->src[current_arg].reg.dimension = VSIR_DIMENSION_VEC4; + ins->src[current_arg].swizzle = swizzle; + current_arg++; + + if (compare) + vsir_src_from_hlsl_node(&ins->src[current_arg++], ctx, load->cmp.node, VKD3DSP_WRITEMASK_0); - if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program, - &ins->src[3], sampler, VKD3DSP_WRITEMASK_ALL, &instr->loc)) - return false; - ins->src[3].reg.dimension = VSIR_DIMENSION_VEC4; - ins->src[3].swizzle = swizzle; - } - else - { - vkd3d_unreachable(); - } return true; } @@ -9723,6 +9762,32 @@ static bool sm4_generate_vsir_instr_resinfo(struct hlsl_ctx *ctx, return true; } +static uint32_t get_gather_swizzle(enum hlsl_resource_load_type type) +{ + switch (type) + { + case HLSL_RESOURCE_GATHER_RED: + case HLSL_RESOURCE_GATHER_CMP_RED: + return VKD3D_SHADER_SWIZZLE(X, X, X, X); + + case HLSL_RESOURCE_GATHER_GREEN: + case HLSL_RESOURCE_GATHER_CMP_GREEN: + return VKD3D_SHADER_SWIZZLE(Y, Y, Y, Y); + + case HLSL_RESOURCE_GATHER_BLUE: + case HLSL_RESOURCE_GATHER_CMP_BLUE: + return VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z); + + case HLSL_RESOURCE_GATHER_ALPHA: + case HLSL_RESOURCE_GATHER_CMP_ALPHA: + return VKD3D_SHADER_SWIZZLE(W, W, W, W); + default: + return 0; + } + + return 0; +} + static bool sm4_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx, struct vsir_program *program, const struct hlsl_ir_resource_load *load) { @@ -9754,16 +9819,16 @@ static bool sm4_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx, return sm4_generate_vsir_instr_sample(ctx, program, load); case HLSL_RESOURCE_GATHER_RED: - return sm4_generate_vsir_instr_gather(ctx, program, load, VKD3D_SHADER_SWIZZLE(X, X, X, X)); - case HLSL_RESOURCE_GATHER_GREEN: - return sm4_generate_vsir_instr_gather(ctx, program, load, VKD3D_SHADER_SWIZZLE(Y, Y, Y, Y)); - case HLSL_RESOURCE_GATHER_BLUE: - return sm4_generate_vsir_instr_gather(ctx, program, load, VKD3D_SHADER_SWIZZLE(Z, Z, Z, Z)); - case HLSL_RESOURCE_GATHER_ALPHA: - return sm4_generate_vsir_instr_gather(ctx, program, load, VKD3D_SHADER_SWIZZLE(W, W, W, W)); + return sm4_generate_vsir_instr_gather(ctx, program, load, get_gather_swizzle(load->load_type), false); + + case HLSL_RESOURCE_GATHER_CMP_RED: + case HLSL_RESOURCE_GATHER_CMP_GREEN: + case HLSL_RESOURCE_GATHER_CMP_BLUE: + case HLSL_RESOURCE_GATHER_CMP_ALPHA: + return sm4_generate_vsir_instr_gather(ctx, program, load, get_gather_swizzle(load->load_type), true); case HLSL_RESOURCE_SAMPLE_INFO: return sm4_generate_vsir_instr_sample_info(ctx, program, load); @@ -11039,13 +11104,14 @@ static void process_entry_function(struct hlsl_ctx *ctx, append_output_var_copy(ctx, entry_func, entry_func->return_var); } - if (profile->major_version >= 4) + if (hlsl_version_ge(ctx, 4, 0)) { hlsl_transform_ir(ctx, lower_discard_neg, body, NULL); } else { hlsl_transform_ir(ctx, lower_discard_nz, body, NULL); + hlsl_transform_ir(ctx, lower_resource_load_bias, body, NULL); } loop_unrolling_execute(ctx, body); diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index cdc0c18466f..ec7e2d036c8 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -703,7 +703,56 @@ static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *prog return VKD3D_OK; } -static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, struct vkd3d_shader_instruction *tex) +static enum vkd3d_result vsir_program_lower_texldp(struct vsir_program *program, + struct vkd3d_shader_instruction *tex, unsigned int *tmp_idx) +{ + struct vkd3d_shader_instruction_array *instructions = &program->instructions; + struct vkd3d_shader_location *location = &tex->location; + struct vkd3d_shader_instruction *div_ins, *tex_ins; + size_t pos = tex - instructions->elements; + unsigned int w_comp; + + w_comp = vsir_swizzle_get_component(tex->src[0].swizzle, 3); + + if (!shader_instruction_array_insert_at(instructions, pos + 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + if (*tmp_idx == ~0u) + *tmp_idx = program->temp_count++; + + div_ins = &instructions->elements[pos + 1]; + tex_ins = &instructions->elements[pos + 2]; + + if (!vsir_instruction_init_with_params(program, div_ins, location, VKD3DSIH_DIV, 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + vsir_dst_param_init(&div_ins->dst[0], VKD3DSPR_TEMP, VKD3D_DATA_FLOAT, 1); + div_ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4; + div_ins->dst[0].reg.idx[0].offset = *tmp_idx; + div_ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL; + + div_ins->src[0] = tex->src[0]; + + div_ins->src[1] = tex->src[0]; + div_ins->src[1].swizzle = vkd3d_shader_create_swizzle(w_comp, w_comp, w_comp, w_comp); + + if (!vsir_instruction_init_with_params(program, tex_ins, location, VKD3DSIH_TEX, 1, 2)) + return VKD3D_ERROR_OUT_OF_MEMORY; + + tex_ins->dst[0] = tex->dst[0]; + + tex_ins->src[0].reg = div_ins->dst[0].reg; + tex_ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE; + + tex_ins->src[1] = tex->src[1]; + + vkd3d_shader_instruction_make_nop(tex); + + return VKD3D_OK; +} + +static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, + struct vkd3d_shader_instruction *tex, struct vkd3d_shader_message_context *message_context) { unsigned int idx = tex->src[1].reg.idx[0].offset; struct vkd3d_shader_src_param *srcs; @@ -711,16 +760,34 @@ static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, st VKD3D_ASSERT(tex->src[1].reg.idx_count == 1); VKD3D_ASSERT(!tex->src[1].reg.idx[0].rel_addr); - if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 3))) + if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 4))) return VKD3D_ERROR_OUT_OF_MEMORY; srcs[0] = tex->src[0]; vsir_src_param_init_resource(&srcs[1], idx, idx); vsir_src_param_init_sampler(&srcs[2], idx, idx); - tex->opcode = VKD3DSIH_SAMPLE; - tex->src = srcs; - tex->src_count = 3; + if (!tex->flags) + { + tex->opcode = VKD3DSIH_SAMPLE; + tex->src = srcs; + tex->src_count = 3; + } + else if (tex->flags == VKD3DSI_TEXLD_BIAS) + { + tex->opcode = VKD3DSIH_SAMPLE_B; + tex->src = srcs; + tex->src_count = 4; + + srcs[3] = tex->src[0]; + srcs[3].swizzle = VKD3D_SHADER_SWIZZLE(W, W, W, W); + } + else + { + vkd3d_shader_error(message_context, &tex->location, + VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED, "Unhandled tex flags %#x.", tex->flags); + return VKD3D_ERROR_NOT_IMPLEMENTED; + } return VKD3D_OK; } @@ -885,8 +952,16 @@ static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *pr break; case VKD3DSIH_TEX: - if ((ret = vsir_program_lower_tex(program, ins)) < 0) - return ret; + if (ins->flags == VKD3DSI_TEXLD_PROJECT) + { + if ((ret = vsir_program_lower_texldp(program, ins, &tmp_idx)) < 0) + return ret; + } + else + { + if ((ret = vsir_program_lower_tex(program, ins, message_context)) < 0) + return ret; + } break; case VKD3DSIH_TEXLDD: @@ -1117,6 +1192,7 @@ static void remove_unread_output_components(const struct shader_signature *signa switch (dst->reg.type) { case VKD3DSPR_OUTPUT: + case VKD3DSPR_TEXCRDOUT: e = vsir_signature_find_element_for_reg(signature, dst->reg.idx[0].offset, 0); break; @@ -2102,6 +2178,7 @@ static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_par signature = normaliser->patch_constant_signature; break; + case VKD3DSPR_TEXCRDOUT: case VKD3DSPR_COLOROUT: reg_idx = reg->idx[0].offset; signature = normaliser->output_signature; @@ -2205,8 +2282,6 @@ static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_par break; case VKD3DSPR_TEXTURE: - if (normaliser->shader_type != VKD3D_SHADER_TYPE_PIXEL) - return; reg->type = VKD3DSPR_INPUT; reg_idx = reg->idx[0].offset; signature = normaliser->input_signature; @@ -2338,16 +2413,12 @@ static bool get_flat_constant_register_type(const struct vkd3d_shader_register * { enum vkd3d_shader_register_type type; enum vkd3d_shader_d3dbc_constant_register set; - uint32_t offset; } regs[] = { - {VKD3DSPR_CONST, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER, 0}, - {VKD3DSPR_CONST2, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER, 2048}, - {VKD3DSPR_CONST3, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER, 4096}, - {VKD3DSPR_CONST4, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER, 6144}, - {VKD3DSPR_CONSTINT, VKD3D_SHADER_D3DBC_INT_CONSTANT_REGISTER, 0}, - {VKD3DSPR_CONSTBOOL, VKD3D_SHADER_D3DBC_BOOL_CONSTANT_REGISTER, 0}, + {VKD3DSPR_CONST, VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER}, + {VKD3DSPR_CONSTINT, VKD3D_SHADER_D3DBC_INT_CONSTANT_REGISTER}, + {VKD3DSPR_CONSTBOOL, VKD3D_SHADER_D3DBC_BOOL_CONSTANT_REGISTER}, }; unsigned int i; @@ -2363,7 +2434,7 @@ static bool get_flat_constant_register_type(const struct vkd3d_shader_register * } *set = regs[i].set; - *index = regs[i].offset + reg->idx[0].offset; + *index = reg->idx[0].offset; return true; } } diff --git a/libs/vkd3d/libs/vkd3d-shader/spirv.c b/libs/vkd3d/libs/vkd3d-shader/spirv.c index a7b935543a0..cfbadab8933 100644 --- a/libs/vkd3d/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d/libs/vkd3d-shader/spirv.c @@ -7301,7 +7301,6 @@ static SpvOp spirv_compiler_map_alu_instruction(const struct vkd3d_shader_instru {VKD3DSIH_DDIV, SpvOpFDiv}, {VKD3DSIH_DIV, SpvOpFDiv}, {VKD3DSIH_DMUL, SpvOpFMul}, - {VKD3DSIH_DTOF, SpvOpFConvert}, {VKD3DSIH_DTOI, SpvOpConvertFToS}, {VKD3DSIH_DTOU, SpvOpConvertFToU}, {VKD3DSIH_FREM, SpvOpFRem}, @@ -7939,6 +7938,7 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, uint32_t src_type_id, dst_type_id, condition_type_id; enum vkd3d_shader_component_type component_type; unsigned int component_count; + uint32_t write_mask; VKD3D_ASSERT(instruction->dst_count == 1); VKD3D_ASSERT(instruction->src_count == 1); @@ -7948,21 +7948,23 @@ static void spirv_compiler_emit_ftoi(struct spirv_compiler *compiler, * and for NaN to yield zero. */ component_count = vsir_write_mask_component_count(dst->write_mask); - src_type_id = spirv_compiler_get_type_id_for_reg(compiler, &src->reg, dst->write_mask); - dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); - src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); if (src->reg.data_type == VKD3D_DATA_DOUBLE) { + write_mask = vkd3d_write_mask_from_component_count(component_count); int_min_id = spirv_compiler_get_constant_double_vector(compiler, -2147483648.0, component_count); float_max_id = spirv_compiler_get_constant_double_vector(compiler, 2147483648.0, component_count); } else { + write_mask = dst->write_mask; int_min_id = spirv_compiler_get_constant_float_vector(compiler, -2147483648.0f, component_count); float_max_id = spirv_compiler_get_constant_float_vector(compiler, 2147483648.0f, component_count); } + src_type_id = spirv_compiler_get_type_id_for_reg(compiler, &src->reg, write_mask); + dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); + src_id = spirv_compiler_emit_load_src(compiler, src, write_mask); val_id = vkd3d_spirv_build_op_glsl_std450_max(builder, src_type_id, src_id, int_min_id); /* VSIR allows the destination of a signed conversion to be unsigned. */ @@ -7992,6 +7994,7 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, const struct vkd3d_shader_src_param *src = instruction->src; uint32_t src_type_id, dst_type_id, condition_type_id; unsigned int component_count; + uint32_t write_mask; VKD3D_ASSERT(instruction->dst_count == 1); VKD3D_ASSERT(instruction->src_count == 1); @@ -8001,21 +8004,23 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, * and for NaN to yield zero. */ component_count = vsir_write_mask_component_count(dst->write_mask); - src_type_id = spirv_compiler_get_type_id_for_reg(compiler, &src->reg, dst->write_mask); - dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); - src_id = spirv_compiler_emit_load_src(compiler, src, dst->write_mask); if (src->reg.data_type == VKD3D_DATA_DOUBLE) { + write_mask = vkd3d_write_mask_from_component_count(component_count); zero_id = spirv_compiler_get_constant_double_vector(compiler, 0.0, component_count); float_max_id = spirv_compiler_get_constant_double_vector(compiler, 4294967296.0, component_count); } else { + write_mask = dst->write_mask; zero_id = spirv_compiler_get_constant_float_vector(compiler, 0.0f, component_count); float_max_id = spirv_compiler_get_constant_float_vector(compiler, 4294967296.0f, component_count); } + src_type_id = spirv_compiler_get_type_id_for_reg(compiler, &src->reg, write_mask); + dst_type_id = spirv_compiler_get_type_id_for_dst(compiler, dst); + src_id = spirv_compiler_emit_load_src(compiler, src, write_mask); val_id = vkd3d_spirv_build_op_glsl_std450_max(builder, src_type_id, src_id, zero_id); uint_max_id = spirv_compiler_get_constant_uint_vector(compiler, UINT_MAX, component_count); @@ -8029,6 +8034,29 @@ static void spirv_compiler_emit_ftou(struct spirv_compiler *compiler, spirv_compiler_emit_store_dst(compiler, dst, val_id); } +static void spirv_compiler_emit_dtof(struct spirv_compiler *compiler, + const struct vkd3d_shader_instruction *instruction) +{ + struct vkd3d_spirv_builder *builder = &compiler->spirv_builder; + const struct vkd3d_shader_dst_param *dst = instruction->dst; + const struct vkd3d_shader_src_param *src = instruction->src; + uint32_t type_id, val_id, src_id; + unsigned int component_count; + uint32_t write_mask; + + component_count = vsir_write_mask_component_count(dst->write_mask); + write_mask = vkd3d_write_mask_from_component_count(component_count); + + src_id = spirv_compiler_emit_load_src(compiler, src, write_mask); + + type_id = vkd3d_spirv_get_type_id(builder, VKD3D_SHADER_COMPONENT_FLOAT, component_count); + val_id = vkd3d_spirv_build_op_tr1(builder, &builder->function_stream, SpvOpFConvert, type_id, src_id); + if (instruction->flags & VKD3DSI_PRECISE_XYZW) + vkd3d_spirv_build_op_decorate(builder, val_id, SpvDecorationNoContraction, NULL, 0); + + spirv_compiler_emit_store_dst(compiler, dst, val_id); +} + static void spirv_compiler_emit_bitfield_instruction(struct spirv_compiler *compiler, const struct vkd3d_shader_instruction *instruction) { @@ -10419,7 +10447,6 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_DDIV: case VKD3DSIH_DIV: case VKD3DSIH_DMUL: - case VKD3DSIH_DTOF: case VKD3DSIH_FREM: case VKD3DSIH_FTOD: case VKD3DSIH_IADD: @@ -10507,6 +10534,9 @@ static int spirv_compiler_handle_instruction(struct spirv_compiler *compiler, case VKD3DSIH_FTOU: spirv_compiler_emit_ftou(compiler, instruction); break; + case VKD3DSIH_DTOF: + spirv_compiler_emit_dtof(compiler, instruction); + break; case VKD3DSIH_DEQO: case VKD3DSIH_DGEO: case VKD3DSIH_DLT: diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c index 872603052ac..7f115057622 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c @@ -4758,6 +4758,8 @@ static void tpf_handle_instruction(struct tpf_compiler *tpf, const struct vkd3d_ case VKD3DSIH_FTOU: case VKD3DSIH_GATHER4: case VKD3DSIH_GATHER4_PO: + case VKD3DSIH_GATHER4_C: + case VKD3DSIH_GATHER4_PO_C: case VKD3DSIH_GEO: case VKD3DSIH_HS_CONTROL_POINT_PHASE: case VKD3DSIH_HS_FORK_PHASE: diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h index 3bfb0a7c3cd..7e8ec156aad 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -595,28 +595,25 @@ enum vkd3d_shader_opcode enum vkd3d_shader_register_type { - VKD3DSPR_TEMP = 0, - VKD3DSPR_INPUT = 1, - VKD3DSPR_CONST = 2, - VKD3DSPR_ADDR = 3, - VKD3DSPR_TEXTURE = 3, - VKD3DSPR_RASTOUT = 4, - VKD3DSPR_ATTROUT = 5, - VKD3DSPR_TEXCRDOUT = 6, - VKD3DSPR_OUTPUT = 6, - VKD3DSPR_CONSTINT = 7, - VKD3DSPR_COLOROUT = 8, - VKD3DSPR_DEPTHOUT = 9, - VKD3DSPR_COMBINED_SAMPLER = 10, - VKD3DSPR_CONST2 = 11, - VKD3DSPR_CONST3 = 12, - VKD3DSPR_CONST4 = 13, - VKD3DSPR_CONSTBOOL = 14, - VKD3DSPR_LOOP = 15, - VKD3DSPR_TEMPFLOAT16 = 16, - VKD3DSPR_MISCTYPE = 17, - VKD3DSPR_LABEL = 18, - VKD3DSPR_PREDICATE = 19, + VKD3DSPR_TEMP, + VKD3DSPR_INPUT, + VKD3DSPR_CONST, + VKD3DSPR_ADDR, + VKD3DSPR_TEXTURE, + VKD3DSPR_RASTOUT, + VKD3DSPR_ATTROUT, + VKD3DSPR_TEXCRDOUT, + VKD3DSPR_OUTPUT, + VKD3DSPR_CONSTINT, + VKD3DSPR_COLOROUT, + VKD3DSPR_DEPTHOUT, + VKD3DSPR_COMBINED_SAMPLER, + VKD3DSPR_CONSTBOOL, + VKD3DSPR_LOOP, + VKD3DSPR_TEMPFLOAT16, + VKD3DSPR_MISCTYPE, + VKD3DSPR_LABEL, + VKD3DSPR_PREDICATE, VKD3DSPR_IMMCONST, VKD3DSPR_IMMCONST64, VKD3DSPR_CONSTBUFFER, -- 2.45.2