diff --git a/libs/vkd3d-shader/glsl.c b/libs/vkd3d-shader/glsl.c index ab1428a9..656e9ab2 100644 --- a/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d-shader/glsl.c @@ -829,6 +829,37 @@ static void shader_glsl_ld(struct vkd3d_glsl_generator *gen, const struct vkd3d_ glsl_dst_cleanup(&dst, &gen->string_buffers); } +static void shader_glsl_print_shadow_coord(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_src_param *coord, const struct vkd3d_shader_src_param *ref, unsigned int coord_size) +{ + uint32_t coord_mask = vkd3d_write_mask_from_component_count(coord_size); + + switch (coord_size) + { + case 1: + vkd3d_string_buffer_printf(buffer, "vec3("); + shader_glsl_print_src(buffer, gen, coord, coord_mask, coord->reg.data_type); + vkd3d_string_buffer_printf(buffer, ", 0.0, "); + shader_glsl_print_src(buffer, gen, ref, VKD3DSP_WRITEMASK_0, ref->reg.data_type); + vkd3d_string_buffer_printf(buffer, ")"); + break; + + case 4: + shader_glsl_print_src(buffer, gen, coord, coord_mask, coord->reg.data_type); + vkd3d_string_buffer_printf(buffer, ", "); + shader_glsl_print_src(buffer, gen, ref, VKD3DSP_WRITEMASK_0, ref->reg.data_type); + break; + + default: + vkd3d_string_buffer_printf(buffer, "vec%u(", coord_size + 1); + shader_glsl_print_src(buffer, gen, coord, coord_mask, coord->reg.data_type); + vkd3d_string_buffer_printf(buffer, ", "); + shader_glsl_print_src(buffer, gen, ref, VKD3DSP_WRITEMASK_0, ref->reg.data_type); + vkd3d_string_buffer_printf(buffer, ")"); + break; + } +} + static void shader_glsl_sample(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) { const struct glsl_resource_type_info *resource_type_info; @@ -839,9 +870,9 @@ static void shader_glsl_sample(struct vkd3d_glsl_generator *gen, const struct vk enum vkd3d_shader_resource_type resource_type; struct vkd3d_string_buffer *sample; enum vkd3d_data_type data_type; - struct glsl_src coord; + unsigned int coord_size; struct glsl_dst dst; - uint32_t coord_mask; + bool shadow; if (vkd3d_shader_instruction_has_texel_offset(ins)) vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, @@ -872,13 +903,13 @@ static void shader_glsl_sample(struct vkd3d_glsl_generator *gen, const struct vk if ((resource_type_info = shader_glsl_get_resource_type_info(resource_type))) { - coord_mask = vkd3d_write_mask_from_component_count(resource_type_info->coord_size); + coord_size = resource_type_info->coord_size; } else { vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, "Internal compiler error: Unhandled resource type %#x.", resource_type); - coord_mask = vkd3d_write_mask_from_component_count(2); + coord_size = 2; } sampler_id = ins->src[2].reg.idx[0].offset; @@ -886,6 +917,20 @@ static void shader_glsl_sample(struct vkd3d_glsl_generator *gen, const struct vk if ((d = shader_glsl_get_descriptor_by_id(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler_id))) { sampler_space = d->register_space; + shadow = d->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE; + + if (ins->opcode == VKD3DSIH_SAMPLE_C) + { + if (!shadow) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Sampler %u is not a comparison sampler.", sampler_id); + } + else + { + if (shadow) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Sampler %u is a comparison sampler.", sampler_id); + } } else { @@ -895,12 +940,16 @@ static void shader_glsl_sample(struct vkd3d_glsl_generator *gen, const struct vk } glsl_dst_init(&dst, gen, ins, &ins->dst[0]); - glsl_src_init(&coord, gen, &ins->src[0], coord_mask); sample = vkd3d_string_buffer_get(&gen->string_buffers); vkd3d_string_buffer_printf(sample, "texture("); shader_glsl_print_combined_sampler_name(sample, gen, resource_idx, resource_space, sampler_idx, sampler_space); - vkd3d_string_buffer_printf(sample, ", %s", coord.str->buffer); + vkd3d_string_buffer_printf(sample, ", "); + if (ins->opcode == VKD3DSIH_SAMPLE_C) + shader_glsl_print_shadow_coord(sample, gen, &ins->src[0], &ins->src[3], coord_size); + else + shader_glsl_print_src(sample, gen, &ins->src[0], + vkd3d_write_mask_from_component_count(coord_size), ins->src[0].reg.data_type); if (ins->opcode == VKD3DSIH_SAMPLE_B) { vkd3d_string_buffer_printf(sample, ", "); @@ -912,7 +961,6 @@ static void shader_glsl_sample(struct vkd3d_glsl_generator *gen, const struct vk shader_glsl_print_assignment_ext(gen, &dst, data_type, "%s", sample->buffer); vkd3d_string_buffer_release(&gen->string_buffers, sample); - glsl_src_cleanup(&coord, &gen->string_buffers); glsl_dst_cleanup(&dst, &gen->string_buffers); } @@ -1500,6 +1548,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, break; case VKD3DSIH_SAMPLE: case VKD3DSIH_SAMPLE_B: + case VKD3DSIH_SAMPLE_C: shader_glsl_sample(gen, ins); break; case VKD3DSIH_SQRT: diff --git a/tests/hlsl/sample-cmp.shader_test b/tests/hlsl/sample-cmp.shader_test index 1b76aceb..3f366c84 100644 --- a/tests/hlsl/sample-cmp.shader_test +++ b/tests/hlsl/sample-cmp.shader_test @@ -140,5 +140,5 @@ float4 main() : sv_target [test] uniform 0 float 0.5 -todo(glsl) draw quad +draw quad probe (0, 0) rgba (0.0, 0.0, 1.0, 1.0)