From baf455d7ecc67cac7c6c450535226f67d3af6c21 Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Sat, 5 Oct 2024 11:26:42 +1000 Subject: [PATCH] Updated vkd3d to 25232f2b2b35bcf1c265bc380c31cd1d32e4f4a6. --- libs/vkd3d/libs/vkd3d-shader/dxil.c | 7 +- libs/vkd3d/libs/vkd3d-shader/glsl.c | 474 +++++++++++++++++- libs/vkd3d/libs/vkd3d-shader/hlsl.c | 4 +- libs/vkd3d/libs/vkd3d-shader/hlsl.y | 42 +- libs/vkd3d/libs/vkd3d-shader/ir.c | 36 ++ .../libs/vkd3d-shader/vkd3d_shader_main.c | 7 +- .../libs/vkd3d-shader/vkd3d_shader_private.h | 2 + 7 files changed, 553 insertions(+), 19 deletions(-) diff --git a/libs/vkd3d/libs/vkd3d-shader/dxil.c b/libs/vkd3d/libs/vkd3d-shader/dxil.c index 165ab222fca..d4296ef4bc5 100644 --- a/libs/vkd3d/libs/vkd3d-shader/dxil.c +++ b/libs/vkd3d/libs/vkd3d-shader/dxil.c @@ -4864,8 +4864,10 @@ static void sm6_parser_emit_dx_cbuffer_load(struct sm6_parser *sm6, enum dx_intr if (!(src_param = instruction_src_params_alloc(ins, 1, sm6))) return; src_param_init_vector_from_reg(src_param, &buffer->u.handle.reg); + /* Differently from other descriptors, constant buffers require an + * additional index, used to index within the constant buffer itself. */ + src_param->reg.idx_count = 3; register_index_address_init(&src_param->reg.idx[2], operands[1], sm6); - VKD3D_ASSERT(src_param->reg.idx_count == 3); type = sm6_type_get_scalar_type(dst->type, 0); VKD3D_ASSERT(type); @@ -4964,8 +4966,7 @@ static void sm6_parser_emit_dx_create_handle(struct sm6_parser *sm6, enum dx_int dst->u.handle.d = d; reg = &dst->u.handle.reg; - /* Set idx_count to 3 for use with load/store instructions. */ - vsir_register_init(reg, d->reg_type, d->reg_data_type, 3); + vsir_register_init(reg, d->reg_type, d->reg_data_type, 2); reg->dimension = VSIR_DIMENSION_VEC4; reg->idx[0].offset = id; register_index_address_init(®->idx[1], operands[2], sm6); diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c index e2bcca56f05..c2fb58c55e6 100644 --- a/libs/vkd3d/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c @@ -18,6 +18,13 @@ #include "vkd3d_shader_private.h" +struct glsl_resource_type_info +{ + size_t coord_size; + bool shadow; + const char *sampler_type; +}; + struct glsl_src { struct vkd3d_string_buffer *str; @@ -52,6 +59,7 @@ struct vkd3d_glsl_generator const struct vkd3d_shader_interface_info *interface_info; const struct vkd3d_shader_descriptor_offset_info *offset_info; const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info; + const struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info; }; static void VKD3D_PRINTF_FUNC(3, 4) vkd3d_glsl_compiler_error( @@ -87,11 +95,81 @@ static const char *shader_glsl_get_prefix(enum vkd3d_shader_type type) } } +static const struct glsl_resource_type_info *shader_glsl_get_resource_type_info(enum vkd3d_shader_resource_type t) +{ + static const struct glsl_resource_type_info info[] = + { + {0, 0, "samplerNone"}, /* VKD3D_SHADER_RESOURCE_NONE */ + {1, 0, "samplerBuffer"}, /* VKD3D_SHADER_RESOURCE_BUFFER */ + {1, 1, "sampler1D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_1D */ + {2, 1, "sampler2D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2D */ + {2, 0, "sampler2DMS"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMS */ + {3, 0, "sampler3D"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_3D */ + {3, 1, "samplerCube"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBE */ + {2, 1, "sampler1DArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_1DARRAY */ + {3, 1, "sampler2DArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DARRAY */ + {3, 0, "sampler2DMSArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY */ + {4, 1, "samplerCubeArray"}, /* VKD3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY */ + }; + + if (!t || t >= ARRAY_SIZE(info)) + return NULL; + + return &info[t]; +} + +static const struct vkd3d_shader_descriptor_info1 *shader_glsl_get_descriptor(struct vkd3d_glsl_generator *gen, + enum vkd3d_shader_descriptor_type type, unsigned int idx, unsigned int space) +{ + const struct vkd3d_shader_scan_descriptor_info1 *info = gen->descriptor_info; + + for (unsigned int i = 0; i < info->descriptor_count; ++i) + { + const struct vkd3d_shader_descriptor_info1 *d = &info->descriptors[i]; + + if (d->type == type && d->register_space == space && d->register_index == idx) + return d; + } + + return NULL; +} + +static const struct vkd3d_shader_descriptor_info1 *shader_glsl_get_descriptor_by_id( + struct vkd3d_glsl_generator *gen, enum vkd3d_shader_descriptor_type type, unsigned int id) +{ + const struct vkd3d_shader_scan_descriptor_info1 *info = gen->descriptor_info; + + for (unsigned int i = 0; i < info->descriptor_count; ++i) + { + const struct vkd3d_shader_descriptor_info1 *d = &info->descriptors[i]; + + if (d->type == type && d->register_id == id) + return d; + } + + return NULL; +} + static void shader_glsl_print_indent(struct vkd3d_string_buffer *buffer, unsigned int indent) { vkd3d_string_buffer_printf(buffer, "%*s", 4 * indent, ""); } +static void shader_glsl_print_combined_sampler_name(struct vkd3d_string_buffer *buffer, + struct vkd3d_glsl_generator *gen, unsigned int resource_index, + unsigned int resource_space, unsigned int sampler_index, unsigned int sampler_space) +{ + vkd3d_string_buffer_printf(buffer, "%s_t_%u", gen->prefix, resource_index); + if (resource_space) + vkd3d_string_buffer_printf(buffer, "_%u", resource_space); + if (sampler_index != VKD3D_SHADER_DUMMY_SAMPLER_INDEX) + { + vkd3d_string_buffer_printf(buffer, "_s_%u", sampler_index); + if (sampler_space) + vkd3d_string_buffer_printf(buffer, "_%u", sampler_space); + } +} + static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_register *reg) { @@ -360,14 +438,12 @@ static uint32_t glsl_dst_init(struct glsl_dst *glsl_dst, struct vkd3d_glsl_gener return write_mask; } -static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( - struct vkd3d_glsl_generator *gen, struct glsl_dst *dst, const char *format, ...) +static void VKD3D_PRINTF_FUNC(4, 0) shader_glsl_vprint_assignment(struct vkd3d_glsl_generator *gen, + struct glsl_dst *dst, enum vkd3d_data_type data_type, const char *format, va_list args) { - const struct vkd3d_shader_register *dst_reg = &dst->vsir->reg; struct vkd3d_string_buffer *buffer = gen->buffer; uint32_t modifiers = dst->vsir->modifiers; bool close = true; - va_list args; if (dst->vsir->shift) vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, @@ -381,11 +457,11 @@ static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( if (modifiers & VKD3DSPDM_SATURATE) vkd3d_string_buffer_printf(buffer, "clamp("); - switch (dst_reg->data_type) + switch (data_type) { default: vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, - "Internal compiler error: Unhandled destination register data type %#x.", dst_reg->data_type); + "Internal compiler error: Unhandled destination register data type %#x.", data_type); /* fall through */ case VKD3D_DATA_FLOAT: close = false; @@ -398,9 +474,7 @@ static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( break; } - va_start(args, format); vkd3d_string_buffer_vprintf(buffer, format, args); - va_end(args); if (close) vkd3d_string_buffer_printf(buffer, ")"); @@ -409,6 +483,26 @@ static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( vkd3d_string_buffer_printf(buffer, ";\n"); } +static void VKD3D_PRINTF_FUNC(3, 4) shader_glsl_print_assignment( + struct vkd3d_glsl_generator *gen, struct glsl_dst *dst, const char *format, ...) +{ + va_list args; + + va_start(args, format); + shader_glsl_vprint_assignment(gen, dst, dst->vsir->reg.data_type, format, args); + va_end(args); +} + +static void VKD3D_PRINTF_FUNC(4, 5) shader_glsl_print_assignment_ext(struct vkd3d_glsl_generator *gen, + struct glsl_dst *dst, enum vkd3d_data_type data_type, const char *format, ...) +{ + va_list args; + + va_start(args, format); + shader_glsl_vprint_assignment(gen, dst, data_type, format, args); + va_end(args); +} + static void shader_glsl_unhandled(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) { shader_glsl_print_indent(gen->buffer, gen->indent); @@ -561,6 +655,159 @@ static void shader_glsl_endif(struct vkd3d_glsl_generator *gen) vkd3d_string_buffer_printf(gen->buffer, "}\n"); } +static void shader_glsl_ld(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) +{ + const struct glsl_resource_type_info *resource_type_info; + unsigned int resource_id, resource_idx, resource_space; + const struct vkd3d_shader_descriptor_info1 *d; + enum vkd3d_shader_component_type sampled_type; + enum vkd3d_shader_resource_type resource_type; + struct vkd3d_string_buffer *fetch; + enum vkd3d_data_type data_type; + struct glsl_src coord, lod; + struct glsl_dst dst; + uint32_t coord_mask; + + if (vkd3d_shader_instruction_has_texel_offset(ins)) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled texel fetch offset."); + + if (ins->src[1].reg.idx[0].rel_addr || ins->src[1].reg.idx[1].rel_addr) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED, + "Descriptor indexing is not supported."); + + resource_id = ins->src[1].reg.idx[0].offset; + resource_idx = ins->src[1].reg.idx[1].offset; + if ((d = shader_glsl_get_descriptor_by_id(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource_id))) + { + resource_type = d->resource_type; + resource_space = d->register_space; + sampled_type = vkd3d_component_type_from_resource_data_type(d->resource_data_type); + data_type = vkd3d_data_type_from_component_type(sampled_type); + } + else + { + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Undeclared resource descriptor %u.", resource_id); + resource_space = 0; + resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; + data_type = VKD3D_DATA_FLOAT; + } + + 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); + } + 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); + } + + glsl_dst_init(&dst, gen, ins, &ins->dst[0]); + glsl_src_init(&coord, gen, &ins->src[0], coord_mask); + glsl_src_init(&lod, gen, &ins->src[0], VKD3DSP_WRITEMASK_3); + fetch = vkd3d_string_buffer_get(&gen->string_buffers); + + vkd3d_string_buffer_printf(fetch, "texelFetch("); + shader_glsl_print_combined_sampler_name(fetch, gen, resource_idx, + resource_space, VKD3D_SHADER_DUMMY_SAMPLER_INDEX, 0); + vkd3d_string_buffer_printf(fetch, ", %s", coord.str->buffer); + if (resource_type != VKD3D_SHADER_RESOURCE_BUFFER) + vkd3d_string_buffer_printf(fetch, ", %s", lod.str->buffer); + vkd3d_string_buffer_printf(fetch, ")"); + shader_glsl_print_swizzle(fetch, ins->src[1].swizzle, ins->dst[0].write_mask); + + shader_glsl_print_assignment_ext(gen, &dst, data_type, "%s", fetch->buffer); + + vkd3d_string_buffer_release(&gen->string_buffers, fetch); + glsl_src_cleanup(&lod, &gen->string_buffers); + glsl_src_cleanup(&coord, &gen->string_buffers); + glsl_dst_cleanup(&dst, &gen->string_buffers); +} + +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; + unsigned int resource_id, resource_idx, resource_space; + unsigned int sampler_id, sampler_idx, sampler_space; + const struct vkd3d_shader_descriptor_info1 *d; + enum vkd3d_shader_component_type sampled_type; + enum vkd3d_shader_resource_type resource_type; + struct vkd3d_string_buffer *sample; + enum vkd3d_data_type data_type; + struct glsl_src coord; + struct glsl_dst dst; + uint32_t coord_mask; + + if (vkd3d_shader_instruction_has_texel_offset(ins)) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled texel sample offset."); + + if (ins->src[1].reg.idx[0].rel_addr || ins->src[1].reg.idx[1].rel_addr + || ins->src[2].reg.idx[0].rel_addr || ins->src[2].reg.idx[1].rel_addr) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED, + "Descriptor indexing is not supported."); + + resource_id = ins->src[1].reg.idx[0].offset; + resource_idx = ins->src[1].reg.idx[1].offset; + if ((d = shader_glsl_get_descriptor_by_id(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, resource_id))) + { + resource_type = d->resource_type; + resource_space = d->register_space; + sampled_type = vkd3d_component_type_from_resource_data_type(d->resource_data_type); + data_type = vkd3d_data_type_from_component_type(sampled_type); + } + else + { + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Undeclared resource descriptor %u.", resource_id); + resource_space = 0; + resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D; + data_type = VKD3D_DATA_FLOAT; + } + + 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); + } + 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); + } + + sampler_id = ins->src[2].reg.idx[0].offset; + sampler_idx = ins->src[2].reg.idx[1].offset; + if ((d = shader_glsl_get_descriptor_by_id(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, sampler_id))) + { + sampler_space = d->register_space; + } + else + { + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Undeclared sampler descriptor %u.", sampler_id); + sampler_space = 0; + } + + 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); + shader_glsl_print_swizzle(sample, ins->src[1].swizzle, ins->dst[0].write_mask); + + 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); +} + static void shader_glsl_unary_op(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins, const char *op) { @@ -617,6 +864,37 @@ static void shader_glsl_movc(struct vkd3d_glsl_generator *gen, const struct vkd3 glsl_dst_cleanup(&dst, &gen->string_buffers); } +static void shader_glsl_mul_extended(struct vkd3d_glsl_generator *gen, const struct vkd3d_shader_instruction *ins) +{ + struct glsl_src src[2]; + struct glsl_dst dst; + uint32_t mask; + + if (ins->dst[0].reg.type != VKD3DSPR_NULL) + { + /* FIXME: imulExtended()/umulExtended() from ARB_gpu_shader5/GLSL 4.00+. */ + mask = glsl_dst_init(&dst, gen, ins, &ins->dst[0]); + shader_glsl_print_assignment(gen, &dst, ""); + glsl_dst_cleanup(&dst, &gen->string_buffers); + + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled 64-bit integer multiplication."); + } + + if (ins->dst[1].reg.type != VKD3DSPR_NULL) + { + mask = glsl_dst_init(&dst, gen, ins, &ins->dst[1]); + glsl_src_init(&src[0], gen, &ins->src[0], mask); + glsl_src_init(&src[1], gen, &ins->src[1], mask); + + shader_glsl_print_assignment(gen, &dst, "%s * %s", src[0].str->buffer, src[1].str->buffer); + + glsl_src_cleanup(&src[1], &gen->string_buffers); + glsl_src_cleanup(&src[0], &gen->string_buffers); + glsl_dst_cleanup(&dst, &gen->string_buffers); + } +} + static void shader_glsl_print_sysval_name(struct vkd3d_string_buffer *buffer, struct vkd3d_glsl_generator *gen, enum vkd3d_shader_sysval_semantic sysval, unsigned int idx) { @@ -817,6 +1095,7 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, shader_glsl_cast(gen, ins, "uint", "uvec"); break; case VKD3DSIH_GEO: + case VKD3DSIH_IGE: shader_glsl_relop(gen, ins, ">=", "greaterThanEqual"); break; case VKD3DSIH_IF: @@ -825,6 +1104,13 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, case VKD3DSIH_MAD: shader_glsl_intrinsic(gen, ins, "fma"); break; + case VKD3DSIH_ILT: + case VKD3DSIH_LTO: + shader_glsl_relop(gen, ins, "<", "lessThan"); + break; + case VKD3DSIH_IMUL: + shader_glsl_mul_extended(gen, ins); + break; case VKD3DSIH_ISHL: shader_glsl_binop(gen, ins, "<<"); break; @@ -832,9 +1118,6 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, case VKD3DSIH_USHR: shader_glsl_binop(gen, ins, ">>"); break; - case VKD3DSIH_LTO: - shader_glsl_relop(gen, ins, "<", "lessThan"); - break; case VKD3DSIH_MAX: shader_glsl_intrinsic(gen, ins, "max"); break; @@ -849,6 +1132,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, case VKD3DSIH_UTOF: shader_glsl_cast(gen, ins, "float", "vec"); break; + case VKD3DSIH_LD: + shader_glsl_ld(gen, ins); + break; case VKD3DSIH_LOG: shader_glsl_intrinsic(gen, ins, "log2"); break; @@ -885,6 +1171,9 @@ static void vkd3d_glsl_handle_instruction(struct vkd3d_glsl_generator *gen, case VKD3DSIH_RSQ: shader_glsl_intrinsic(gen, ins, "inversesqrt"); break; + case VKD3DSIH_SAMPLE: + shader_glsl_sample(gen, ins); + break; case VKD3DSIH_SQRT: shader_glsl_intrinsic(gen, ins, "sqrt"); break; @@ -1012,8 +1301,156 @@ static void shader_glsl_generate_cbv_declaration(struct vkd3d_glsl_generator *ge binding->binding, prefix, cbv->register_id, prefix, cbv->register_id, size); } +static bool shader_glsl_get_combined_sampler_binding(const struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_combined_resource_sampler_info *crs, + enum vkd3d_shader_resource_type resource_type, unsigned int *binding_idx) +{ + const struct vkd3d_shader_interface_info *interface_info = gen->interface_info; + const struct vkd3d_shader_combined_resource_sampler *s; + enum vkd3d_shader_binding_flag resource_type_flag; + unsigned int i; + + if (!interface_info) + return false; + + resource_type_flag = resource_type == VKD3D_SHADER_RESOURCE_BUFFER + ? VKD3D_SHADER_BINDING_FLAG_BUFFER : VKD3D_SHADER_BINDING_FLAG_IMAGE; + + for (i = 0; i < interface_info->combined_sampler_count; ++i) + { + s = &interface_info->combined_samplers[i]; + + if (s->resource_space != crs->resource_space) + continue; + if (s->resource_index != crs->resource_index) + continue; + if (crs->sampler_index != VKD3D_SHADER_DUMMY_SAMPLER_INDEX) + { + if (s->sampler_space != crs->sampler_space) + continue; + if (s->sampler_index != crs->sampler_index) + continue; + } + if (!shader_glsl_check_shader_visibility(gen, s->shader_visibility)) + continue; + if (!(s->flags & resource_type_flag)) + continue; + *binding_idx = i; + return true; + } + + return false; +} + +static void shader_glsl_generate_sampler_declaration(struct vkd3d_glsl_generator *gen, + const struct vkd3d_shader_combined_resource_sampler_info *crs) +{ + const struct vkd3d_shader_descriptor_info1 *sampler, *srv; + const struct glsl_resource_type_info *resource_type_info; + const struct vkd3d_shader_descriptor_binding *binding; + struct vkd3d_string_buffer *buffer = gen->buffer; + enum vkd3d_shader_component_type component_type; + const char *sampler_type, *sampler_type_prefix; + unsigned int binding_idx; + bool shadow = false; + + if (crs->sampler_index != VKD3D_SHADER_DUMMY_SAMPLER_INDEX) + { + if (!(sampler = shader_glsl_get_descriptor(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER, + crs->sampler_index, crs->sampler_space))) + { + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: No descriptor found for sampler %u, space %u.", + crs->sampler_index, crs->sampler_space); + return; + } + shadow = sampler->flags & VKD3D_SHADER_DESCRIPTOR_INFO_FLAG_SAMPLER_COMPARISON_MODE; + } + + if (!(srv = shader_glsl_get_descriptor(gen, VKD3D_SHADER_DESCRIPTOR_TYPE_SRV, + crs->resource_index, crs->resource_space))) + { + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: No descriptor found for resource %u, space %u.", + crs->resource_index, crs->resource_space); + return; + } + + if ((resource_type_info = shader_glsl_get_resource_type_info(srv->resource_type))) + { + sampler_type = resource_type_info->sampler_type; + if (shadow && !resource_type_info->shadow) + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED, + "Comparison samplers are not supported with resource type %#x.", srv->resource_type); + } + else + { + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled resource type %#x for combined resource/sampler " + "for resource %u, space %u and sampler %u, space %u.", srv->resource_type, + crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); + sampler_type = ""; + } + + switch ((component_type = vkd3d_component_type_from_resource_data_type(srv->resource_data_type))) + { + case VKD3D_SHADER_COMPONENT_UINT: + sampler_type_prefix = "u"; + break; + case VKD3D_SHADER_COMPONENT_INT: + sampler_type_prefix = "i"; + break; + case VKD3D_SHADER_COMPONENT_FLOAT: + sampler_type_prefix = ""; + break; + default: + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, + "Internal compiler error: Unhandled component type %#x for combined resource/sampler " + "for resource %u, space %u and sampler %u, space %u.", component_type, + crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); + sampler_type_prefix = ""; + break; + } + + if (!shader_glsl_get_combined_sampler_binding(gen, crs, srv->resource_type, &binding_idx)) + { + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND, + "No descriptor binding specified for combined resource/sampler " + "for resource %u, space %u and sampler %u, space %u.", + crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); + return; + } + + binding = &gen->interface_info->combined_samplers[binding_idx].binding; + + if (binding->set != 0) + { + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND, + "Unsupported binding set %u specified for combined resource/sampler " + "for resource %u, space %u and sampler %u, space %u.", binding->set, + crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); + return; + } + + if (binding->count != 1) + { + vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND, + "Unsupported binding count %u specified for combined resource/sampler " + "for resource %u, space %u and sampler %u, space %u.", binding->count, + crs->resource_index, crs->resource_space, crs->sampler_index, crs->sampler_space); + return; + } + + vkd3d_string_buffer_printf(buffer, "layout(binding = %u) uniform %s%s%s ", + binding->binding, sampler_type_prefix, sampler_type, shadow ? "Shadow" : ""); + shader_glsl_print_combined_sampler_name(buffer, gen, crs->resource_index, + crs->resource_space, crs->sampler_index, crs->sampler_space); + vkd3d_string_buffer_printf(buffer, ";\n"); +} + static void shader_glsl_generate_descriptor_declarations(struct vkd3d_glsl_generator *gen) { + const struct vkd3d_shader_scan_combined_resource_sampler_info *sampler_info = gen->combined_sampler_info; const struct vkd3d_shader_scan_descriptor_info1 *info = gen->descriptor_info; const struct vkd3d_shader_descriptor_info1 *descriptor; unsigned int i; @@ -1024,6 +1461,11 @@ static void shader_glsl_generate_descriptor_declarations(struct vkd3d_glsl_gener switch (descriptor->type) { + case VKD3D_SHADER_DESCRIPTOR_TYPE_SRV: + case VKD3D_SHADER_DESCRIPTOR_TYPE_SAMPLER: + /* GLSL uses combined resource/sampler descriptors.*/ + break; + case VKD3D_SHADER_DESCRIPTOR_TYPE_CBV: shader_glsl_generate_cbv_declaration(gen, descriptor); break; @@ -1035,6 +1477,10 @@ static void shader_glsl_generate_descriptor_declarations(struct vkd3d_glsl_gener break; } } + for (i = 0; i < sampler_info->combined_sampler_count; ++i) + { + shader_glsl_generate_sampler_declaration(gen, &sampler_info->combined_samplers[i]); + } if (info->descriptor_count) vkd3d_string_buffer_printf(gen->buffer, "\n"); } @@ -1259,6 +1705,7 @@ static void shader_glsl_init_limits(struct vkd3d_glsl_generator *gen, const stru static void vkd3d_glsl_generator_init(struct vkd3d_glsl_generator *gen, struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info, const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info, + const struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info, struct vkd3d_shader_message_context *message_context) { enum vkd3d_shader_type type = program->shader_version.type; @@ -1282,10 +1729,12 @@ static void vkd3d_glsl_generator_init(struct vkd3d_glsl_generator *gen, gen->interface_info = vkd3d_find_struct(compile_info->next, INTERFACE_INFO); gen->offset_info = vkd3d_find_struct(compile_info->next, DESCRIPTOR_OFFSET_INFO); gen->descriptor_info = descriptor_info; + gen->combined_sampler_info = combined_sampler_info; } int glsl_compile(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info, + const struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) { @@ -1295,7 +1744,8 @@ int glsl_compile(struct vsir_program *program, uint64_t config_flags, if ((ret = vsir_program_transform(program, config_flags, compile_info, message_context)) < 0) return ret; - vkd3d_glsl_generator_init(&generator, program, compile_info, descriptor_info, message_context); + vkd3d_glsl_generator_init(&generator, program, compile_info, + descriptor_info, combined_sampler_info, message_context); ret = vkd3d_glsl_generator_generate(&generator, out); vkd3d_glsl_generator_cleanup(&generator); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c index ce3dd91f04f..9ace1930c1b 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c @@ -4408,8 +4408,6 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) struct hlsl_type *type, *next_type; unsigned int i; - hlsl_block_cleanup(&ctx->static_initializers); - for (i = 0; i < ctx->source_files_count; ++i) vkd3d_free((void *)ctx->source_files[i]); vkd3d_free(ctx->source_files); @@ -4417,6 +4415,8 @@ static void hlsl_ctx_cleanup(struct hlsl_ctx *ctx) rb_destroy(&ctx->functions, free_function_rb, NULL); + hlsl_block_cleanup(&ctx->static_initializers); + /* State blocks must be free before the variables, because they contain instructions that may * refer to them. */ LIST_FOR_EACH_ENTRY_SAFE(scope, next_scope, &ctx->scopes, struct hlsl_scope, entry) diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y index b4d9f0988b0..ef37eb75f03 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y @@ -1972,6 +1972,12 @@ static struct hlsl_block *add_binary_expr_merge(struct hlsl_ctx *ctx, struct hls hlsl_block_add_block(block1, block2); destroy_block(block2); + if (arg1->data_type->class == HLSL_CLASS_ERROR || arg2->data_type->class == HLSL_CLASS_ERROR) + { + block1->value = ctx->error_instr; + return block1; + } + if (add_binary_expr(ctx, block1, op, arg1, arg2, loc) == NULL) return NULL; @@ -2085,6 +2091,12 @@ static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struc unsigned int writemask = 0, width = 0; bool matrix_writemask = false; + if (lhs->data_type->class == HLSL_CLASS_ERROR || rhs->data_type->class == HLSL_CLASS_ERROR) + { + block->value = ctx->error_instr; + return true; + } + if (assign_op == ASSIGN_OP_SUB) { if (!(rhs = add_unary_arithmetic_expr(ctx, block, HLSL_OP1_NEG, rhs, &rhs->loc))) @@ -5141,6 +5153,15 @@ static struct hlsl_block *add_call(struct hlsl_ctx *ctx, const char *name, struct intrinsic_function *intrinsic; struct hlsl_ir_function_decl *decl; + for (unsigned int i = 0; i < args->args_count; ++i) + { + if (args->args[i]->data_type->class == HLSL_CLASS_ERROR) + { + args->instrs->value = ctx->error_instr; + return args->instrs; + } + } + if ((decl = find_function_call(ctx, name, args, false, loc))) { if (!add_user_call(ctx, decl, args, false, loc)) @@ -6071,6 +6092,21 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, stru const struct hlsl_type *object_type = object->data_type; const struct method_function *method; + if (object_type->class == HLSL_CLASS_ERROR) + { + block->value = ctx->error_instr; + return true; + } + + for (unsigned int i = 0; i < params->args_count; ++i) + { + if (params->args[i]->data_type->class == HLSL_CLASS_ERROR) + { + block->value = ctx->error_instr; + return true; + } + } + if (object_type->class != HLSL_CLASS_TEXTURE || object_type->sampler_dim == HLSL_SAMPLER_DIM_GENERIC) { struct vkd3d_string_buffer *string; @@ -8682,7 +8718,11 @@ primary_expr: else { hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, "Identifier \"%s\" is not declared.", $1); - YYABORT; + vkd3d_free($1); + + if (!($$ = make_empty_block(ctx))) + YYABORT; + $$->value = ctx->error_instr; } } diff --git a/libs/vkd3d/libs/vkd3d-shader/ir.c b/libs/vkd3d/libs/vkd3d-shader/ir.c index 2fe5472167f..6a74e2eb8de 100644 --- a/libs/vkd3d/libs/vkd3d-shader/ir.c +++ b/libs/vkd3d/libs/vkd3d-shader/ir.c @@ -6186,6 +6186,18 @@ static void vsir_validate_register(struct validation_context *ctx, if (reg->dimension == VSIR_DIMENSION_SCALAR) validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension SCALAR for a SAMPLER register."); + + if (reg->idx_count != 2) + { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, + "Invalid index count %u for a SAMPLER register.", + reg->idx_count); + break; + } + + if (reg->idx[0].rel_addr) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, + "Non-NULL relative address for the descriptor index of a SAMPLER register."); break; case VKD3DSPR_RESOURCE: @@ -6203,6 +6215,18 @@ static void vsir_validate_register(struct validation_context *ctx, validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension %#x for a RESOURCE register.", reg->dimension); + + if (reg->idx_count != 2) + { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, + "Invalid index count %u for a RESOURCE register.", + reg->idx_count); + break; + } + + if (reg->idx[0].rel_addr) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, + "Non-NULL relative address for the descriptor index of a RESOURCE register."); break; case VKD3DSPR_UAV: @@ -6221,6 +6245,18 @@ static void vsir_validate_register(struct validation_context *ctx, validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid dimension %#x for a UAV register.", reg->dimension); + + if (reg->idx_count != 2) + { + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, + "Invalid index count %u for a UAV register.", + reg->idx_count); + break; + } + + if (reg->idx[0].rel_addr) + validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX, + "Non-NULL relative address for the descriptor index of a UAV register."); break; case VKD3DSPR_DEPTHOUT: diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c index fc217860403..ee8a633431a 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_main.c @@ -1620,6 +1620,7 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context) { + struct vkd3d_shader_scan_combined_resource_sampler_info combined_sampler_info; struct vkd3d_shader_scan_descriptor_info1 scan_descriptor_info; struct vkd3d_shader_compile_info scan_info; int ret; @@ -1633,10 +1634,14 @@ int vsir_program_compile(struct vsir_program *program, uint64_t config_flags, break; case VKD3D_SHADER_TARGET_GLSL: + combined_sampler_info.type = VKD3D_SHADER_STRUCTURE_TYPE_SCAN_COMBINED_RESOURCE_SAMPLER_INFO; + combined_sampler_info.next = scan_info.next; + scan_info.next = &combined_sampler_info; if ((ret = vsir_program_scan(program, &scan_info, message_context, &scan_descriptor_info)) < 0) return ret; ret = glsl_compile(program, config_flags, &scan_descriptor_info, - compile_info, out, message_context); + &combined_sampler_info, compile_info, out, message_context); + vkd3d_shader_free_scan_combined_resource_sampler_info(&combined_sampler_info); vkd3d_shader_free_scan_descriptor_info1(&scan_descriptor_info); break; diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h index d9d5b4a405e..eab164cc848 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -173,6 +173,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_GLSL_INTERNAL = 6000, VKD3D_SHADER_ERROR_GLSL_BINDING_NOT_FOUND = 6001, + VKD3D_SHADER_ERROR_GLSL_UNSUPPORTED = 6002, VKD3D_SHADER_ERROR_D3DBC_UNEXPECTED_EOF = 7000, VKD3D_SHADER_ERROR_D3DBC_INVALID_VERSION_TOKEN = 7001, @@ -1599,6 +1600,7 @@ int shader_parse_input_signature(const struct vkd3d_shader_code *dxbc, int glsl_compile(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_scan_descriptor_info1 *descriptor_info, + const struct vkd3d_shader_scan_combined_resource_sampler_info *combined_sampler_info, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context); -- 2.45.2