diff --git a/libs/vkd3d-shader/hlsl.h b/libs/vkd3d-shader/hlsl.h index 307932cb..1d0b3f87 100644 --- a/libs/vkd3d-shader/hlsl.h +++ b/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-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index a3814a81..dbed11cd 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/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-shader/hlsl_codegen.c b/libs/vkd3d-shader/hlsl_codegen.c index a43ea530..55a94975 100644 --- a/libs/vkd3d-shader/hlsl_codegen.c +++ b/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: @@ -9596,18 +9600,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 +9621,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); + if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, src_count))) + 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 (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); - if (!sm4_generate_vsir_init_src_param_from_deref(ctx, program, - &ins->src[1], 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++], resource, ins->dst[0].write_mask, &instr->loc)) + return false; - 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 (!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++; - 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 (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[2], resource, ins->dst[0].write_mask, &instr->loc)) - return false; - - 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 +9717,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 +9774,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); diff --git a/libs/vkd3d-shader/tpf.c b/libs/vkd3d-shader/tpf.c index 3cb03649..342167b7 100644 --- a/libs/vkd3d-shader/tpf.c +++ b/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/tests/hlsl/gather-cmp.shader_test b/tests/hlsl/gather-cmp.shader_test index 842e6ee5..59b73fed 100644 --- a/tests/hlsl/gather-cmp.shader_test +++ b/tests/hlsl/gather-cmp.shader_test @@ -13,7 +13,7 @@ size (2d, 3, 3) 0.4 0.1 0.0 0.5 0.0 0.2 -[pixel shader todo] +[pixel shader] SamplerComparisonState s; Texture2D t; @@ -23,10 +23,10 @@ float4 main() : sv_target } [test] -todo(sm<6) draw quad +todo(msl | glsl) draw quad probe (0, 0) rgba(0.0, 1.0, 0.0, 0.0) -[pixel shader todo] +[pixel shader] SamplerComparisonState s; Texture2D t; @@ -36,10 +36,10 @@ float4 main() : sv_target } [test] -todo(sm<6) draw quad +todo(msl | glsl) draw quad probe (0, 0) rgba(0.0, 0.0, 0.0, 1.0) -[pixel shader todo] +[pixel shader] SamplerComparisonState s; Texture2D t; @@ -49,10 +49,10 @@ float4 main() : sv_target } [test] -todo(sm<6) draw quad +todo(msl | glsl) draw quad probe (0, 0) rgba(0.0, 1.0, 0.0, 0.0) -[pixel shader todo] +[pixel shader] SamplerComparisonState s; Texture2D t; @@ -62,10 +62,10 @@ float4 main() : sv_target } [test] -todo(sm<6) draw quad +todo(msl | glsl) draw quad probe (0, 0) rgba(0.0, 1.0, 0.0, 0.0) -[pixel shader todo] +[pixel shader] SamplerComparisonState s; Texture2D t; @@ -75,10 +75,10 @@ float4 main() : sv_target } [test] -todo(sm<6) draw quad +todo(msl | glsl) draw quad probe (0, 0) rgba(0.0, 1.0, 0.0, 0.0) -[pixel shader todo] +[pixel shader] SamplerComparisonState s; Texture2D t; @@ -88,10 +88,10 @@ float4 main() : sv_target } [test] -todo(sm<6) draw quad +todo(msl | glsl) draw quad probe (0, 0) rgba(1.0, 0.0, 0.0, 0.0) -[pixel shader todo] +[pixel shader] SamplerComparisonState s; Texture2D t; @@ -101,5 +101,5 @@ float4 main() : sv_target } [test] -todo(sm<6) draw quad +todo(msl | glsl) draw quad probe (0, 0) rgba(0.0, 0.0, 0.0, 1.0)