From 83a3253798716f86bf8ace1e2cf0fbbd829e614a Mon Sep 17 00:00:00 2001 From: Alistair Leslie-Hughes Date: Fri, 14 Mar 2025 08:23:50 +1100 Subject: [PATCH] Updated vkd3d to a4f58be00c58e06b5bd60bec7eb9e37b6f112c24. --- libs/vkd3d/include/private/vkd3d_version.h | 2 +- libs/vkd3d/libs/vkd3d-shader/glsl.c | 9 +- libs/vkd3d/libs/vkd3d-shader/hlsl.c | 76 +- libs/vkd3d/libs/vkd3d-shader/hlsl.h | 31 +- libs/vkd3d/libs/vkd3d-shader/hlsl.l | 5 + libs/vkd3d/libs/vkd3d-shader/hlsl.y | 735 +++++--------- libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c | 893 ++++++++++++++---- .../libs/vkd3d-shader/hlsl_constant_ops.c | 10 +- libs/vkd3d/libs/vkd3d-shader/tpf.c | 10 +- .../libs/vkd3d-shader/vkd3d_shader_private.h | 3 + 10 files changed, 1057 insertions(+), 717 deletions(-) diff --git a/libs/vkd3d/include/private/vkd3d_version.h b/libs/vkd3d/include/private/vkd3d_version.h index a73ae3fb03c..795bc2dc490 100644 --- a/libs/vkd3d/include/private/vkd3d_version.h +++ b/libs/vkd3d/include/private/vkd3d_version.h @@ -1 +1 @@ -#define VKD3D_VCS_ID " (git 81dc67b1)" +#define VKD3D_VCS_ID " (git a4f58be0)" diff --git a/libs/vkd3d/libs/vkd3d-shader/glsl.c b/libs/vkd3d/libs/vkd3d-shader/glsl.c index ab6604bd703..a47c2feb094 100644 --- a/libs/vkd3d/libs/vkd3d-shader/glsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/glsl.c @@ -269,15 +269,15 @@ static void shader_glsl_print_register_name(struct vkd3d_string_buffer *buffer, vkd3d_string_buffer_printf(buffer, "", reg->type); break; } - if (reg->idx[0].rel_addr || reg->idx[2].rel_addr) + if (reg->idx[0].rel_addr) { vkd3d_glsl_compiler_error(gen, VKD3D_SHADER_ERROR_GLSL_INTERNAL, "Internal compiler error: Unhandled constant buffer register indirect addressing."); vkd3d_string_buffer_printf(buffer, "", reg->type); break; } - vkd3d_string_buffer_printf(buffer, "%s_cb_%u[%u]", - gen->prefix, reg->idx[0].offset, reg->idx[2].offset); + vkd3d_string_buffer_printf(buffer, "%s_cb_%u", gen->prefix, reg->idx[0].offset); + shader_glsl_print_subscript(buffer, gen, reg->idx[2].rel_addr, reg->idx[2].offset); break; case VKD3DSPR_THREADID: @@ -485,8 +485,7 @@ static void shader_glsl_print_subscript(struct vkd3d_string_buffer *buffer, stru vkd3d_string_buffer_printf(buffer, "[%s", r.str->buffer); if (offset) vkd3d_string_buffer_printf(buffer, " + %u", offset); - else - vkd3d_string_buffer_printf(buffer, "]"); + vkd3d_string_buffer_printf(buffer, "]"); glsl_src_cleanup(&r, &gen->string_buffers); } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.c b/libs/vkd3d/libs/vkd3d-shader/hlsl.c index a7641a203f3..01586592b25 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.c @@ -234,6 +234,33 @@ unsigned int hlsl_get_multiarray_size(const struct hlsl_type *type) return 1; } +const struct hlsl_type *hlsl_get_stream_output_type(const struct hlsl_type *type) +{ + unsigned int i; + + switch (type->class) + { + case HLSL_CLASS_ARRAY: + return hlsl_get_stream_output_type(type->e.array.type); + + case HLSL_CLASS_STRUCT: + for (i = 0; i < type->e.record.field_count; ++i) + { + const struct hlsl_type *field_type = hlsl_get_stream_output_type(type->e.record.fields[i].type); + + if (field_type) + return field_type; + } + return NULL; + + case HLSL_CLASS_STREAM_OUTPUT: + return type; + + default: + return NULL; + } +} + bool hlsl_type_is_resource(const struct hlsl_type *type) { switch (type->class) @@ -298,6 +325,12 @@ bool hlsl_type_is_patch_array(const struct hlsl_type *type) || type->e.array.array_type == HLSL_ARRAY_PATCH_OUTPUT); } +bool hlsl_type_is_primitive_array(const struct hlsl_type *type) +{ + return type->class == HLSL_CLASS_ARRAY && (type->e.array.array_type != HLSL_ARRAY_GENERIC + || (type->modifiers & HLSL_PRIMITIVE_MODIFIERS_MASK)); +} + bool hlsl_base_type_is_integer(enum hlsl_base_type type) { switch (type) @@ -739,8 +772,7 @@ unsigned int hlsl_type_get_component_offset(struct hlsl_ctx *ctx, struct hlsl_ty return offset[*regset]; } -static bool init_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_var *var, - unsigned int path_len) +bool hlsl_init_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_var *var, unsigned int path_len) { deref->var = var; deref->path_len = path_len; @@ -798,7 +830,7 @@ bool hlsl_init_deref_from_index_chain(struct hlsl_ctx *ctx, struct hlsl_deref *d } load = hlsl_ir_load(ptr); - if (!init_deref(ctx, deref, load->src.var, load->src.path_len + chain_len)) + if (!hlsl_init_deref(ctx, deref, load->src.var, load->src.path_len + chain_len)) return false; for (i = 0; i < load->src.path_len; ++i) @@ -867,7 +899,7 @@ static bool init_deref_from_component_index(struct hlsl_ctx *ctx, struct hlsl_bl ++path_len; } - if (!init_deref(ctx, deref, prefix->var, prefix->path_len + path_len)) + if (!hlsl_init_deref(ctx, deref, prefix->var, prefix->path_len + path_len)) return false; deref_path_len = 0; @@ -1133,6 +1165,7 @@ unsigned int hlsl_type_component_count(const struct hlsl_type *type) case HLSL_CLASS_HULL_SHADER: case HLSL_CLASS_GEOMETRY_SHADER: case HLSL_CLASS_BLEND_STATE: + case HLSL_CLASS_STREAM_OUTPUT: case HLSL_CLASS_NULL: return 1; @@ -1140,7 +1173,6 @@ unsigned int hlsl_type_component_count(const struct hlsl_type *type) case HLSL_CLASS_PASS: case HLSL_CLASS_TECHNIQUE: case HLSL_CLASS_VOID: - case HLSL_CLASS_STREAM_OUTPUT: break; } @@ -1459,7 +1491,7 @@ bool hlsl_copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, const struc VKD3D_ASSERT(!hlsl_deref_is_lowered(other)); - if (!init_deref(ctx, deref, other->var, other->path_len)) + if (!hlsl_init_deref(ctx, deref, other->var, other->path_len)) return false; for (i = 0; i < deref->path_len; ++i) @@ -1521,7 +1553,7 @@ struct hlsl_ir_node *hlsl_new_store_index(struct hlsl_ctx *ctx, const struct hls return NULL; init_node(&store->node, HLSL_IR_STORE, NULL, loc); - if (!init_deref(ctx, &store->lhs, lhs->var, lhs->path_len + !!idx)) + if (!hlsl_init_deref(ctx, &store->lhs, lhs->var, lhs->path_len + !!idx)) { vkd3d_free(store); return NULL; @@ -1857,7 +1889,7 @@ struct hlsl_ir_load *hlsl_new_load_index(struct hlsl_ctx *ctx, const struct hlsl return NULL; init_node(&load->node, HLSL_IR_LOAD, type, loc); - if (!init_deref(ctx, &load->src, deref->var, deref->path_len + !!idx)) + if (!hlsl_init_deref(ctx, &load->src, deref->var, deref->path_len + !!idx)) { vkd3d_free(load); return NULL; @@ -1939,7 +1971,7 @@ struct hlsl_ir_node *hlsl_block_add_load_component(struct hlsl_ctx *ctx, struct return &load->node; } -struct hlsl_ir_node *hlsl_new_resource_load(struct hlsl_ctx *ctx, +static struct hlsl_ir_node *hlsl_new_resource_load(struct hlsl_ctx *ctx, const struct hlsl_resource_load_params *params, const struct vkd3d_shader_location *loc) { struct hlsl_ir_resource_load *load; @@ -1978,6 +2010,12 @@ struct hlsl_ir_node *hlsl_new_resource_load(struct hlsl_ctx *ctx, return &load->node; } +struct hlsl_ir_node *hlsl_block_add_resource_load(struct hlsl_ctx *ctx, struct hlsl_block *block, + const struct hlsl_resource_load_params *params, const struct vkd3d_shader_location *loc) +{ + return append_new_instr(ctx, block, hlsl_new_resource_load(ctx, params, loc)); +} + static struct hlsl_ir_node *hlsl_new_resource_store(struct hlsl_ctx *ctx, const struct hlsl_deref *resource, struct hlsl_ir_node *coords, struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc) { @@ -2022,6 +2060,12 @@ struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned return &swizzle->node; } +struct hlsl_ir_node *hlsl_block_add_swizzle(struct hlsl_ctx *ctx, struct hlsl_block *block, uint32_t s, + unsigned int width, struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc) +{ + return append_new_instr(ctx, block, hlsl_new_swizzle(ctx, s, width, val, loc)); +} + struct hlsl_ir_node *hlsl_new_matrix_swizzle(struct hlsl_ctx *ctx, struct hlsl_matrix_swizzle s, unsigned int component_count, struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc) { @@ -2367,7 +2411,7 @@ static bool clone_deref(struct hlsl_ctx *ctx, struct clone_instr_map *map, VKD3D_ASSERT(!hlsl_deref_is_lowered(src)); - if (!init_deref(ctx, dst, src->var, src->path_len)) + if (!hlsl_init_deref(ctx, dst, src->var, src->path_len)) return false; for (i = 0; i < src->path_len; ++i) @@ -3203,6 +3247,16 @@ struct vkd3d_string_buffer *hlsl_modifiers_to_string(struct hlsl_ctx *ctx, uint3 vkd3d_string_buffer_printf(string, "row_major "); if (modifiers & HLSL_MODIFIER_COLUMN_MAJOR) vkd3d_string_buffer_printf(string, "column_major "); + if (modifiers & HLSL_PRIMITIVE_POINT) + vkd3d_string_buffer_printf(string, "point "); + if (modifiers & HLSL_PRIMITIVE_LINE) + vkd3d_string_buffer_printf(string, "line "); + if (modifiers & HLSL_PRIMITIVE_TRIANGLE) + vkd3d_string_buffer_printf(string, "triangle "); + if (modifiers & HLSL_PRIMITIVE_LINEADJ) + vkd3d_string_buffer_printf(string, "lineadj "); + if (modifiers & HLSL_PRIMITIVE_TRIANGLEADJ) + vkd3d_string_buffer_printf(string, "triangleadj "); if ((modifiers & (HLSL_STORAGE_IN | HLSL_STORAGE_OUT)) == (HLSL_STORAGE_IN | HLSL_STORAGE_OUT)) vkd3d_string_buffer_printf(string, "inout "); else if (modifiers & HLSL_STORAGE_IN) @@ -4736,6 +4790,8 @@ static bool hlsl_ctx_init(struct hlsl_ctx *ctx, const struct vkd3d_shader_compil ctx->output_primitive = 0; ctx->partitioning = 0; ctx->input_control_point_count = UINT_MAX; + ctx->max_vertex_count = 0; + ctx->input_primitive_type = VKD3D_PT_UNDEFINED; return true; } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.h b/libs/vkd3d/libs/vkd3d-shader/hlsl.h index 2ef84d35ff2..98d3d17e826 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.h +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.h @@ -417,6 +417,11 @@ struct hlsl_attribute #define HLSL_STORAGE_ANNOTATION 0x00080000 #define HLSL_MODIFIER_UNORM 0x00100000 #define HLSL_MODIFIER_SNORM 0x00200000 +#define HLSL_PRIMITIVE_POINT 0x00400000 +#define HLSL_PRIMITIVE_LINE 0x00800000 +#define HLSL_PRIMITIVE_TRIANGLE 0x01000000 +#define HLSL_PRIMITIVE_LINEADJ 0x02000000 +#define HLSL_PRIMITIVE_TRIANGLEADJ 0x04000000 #define HLSL_TYPE_MODIFIERS_MASK (HLSL_MODIFIER_PRECISE | HLSL_MODIFIER_VOLATILE | \ HLSL_MODIFIER_CONST | HLSL_MODIFIER_ROW_MAJOR | \ @@ -427,6 +432,9 @@ struct hlsl_attribute #define HLSL_MODIFIERS_MAJORITY_MASK (HLSL_MODIFIER_ROW_MAJOR | HLSL_MODIFIER_COLUMN_MAJOR) +#define HLSL_PRIMITIVE_MODIFIERS_MASK (HLSL_PRIMITIVE_POINT | HLSL_PRIMITIVE_LINE | HLSL_PRIMITIVE_TRIANGLE | \ + HLSL_PRIMITIVE_LINEADJ | HLSL_PRIMITIVE_TRIANGLEADJ) + #define HLSL_ARRAY_ELEMENTS_COUNT_IMPLICIT 0 /* Reservation of a register and/or an offset for objects inside constant buffers, to be used as a @@ -1184,10 +1192,18 @@ struct hlsl_ctx unsigned int input_control_point_count; struct hlsl_type *input_control_point_type; + /* The first declared input primitive parameter in tessellation and geometry shaders. */ + struct hlsl_ir_var *input_primitive_param; + /* Whether the current function being processed during HLSL codegen is * the patch constant function in a hull shader. */ bool is_patch_constant_func; + /* The maximum output vertex count of a geometry shader. */ + unsigned int max_vertex_count; + /* The input primitive type of a geometry shader. */ + enum vkd3d_primitive_type input_primitive_type; + /* In some cases we generate opcodes by parsing an HLSL function and then * invoking it. If not NULL, this field is the name of the function that we * are currently parsing, "mangled" with an internal prefix to avoid @@ -1458,6 +1474,11 @@ static inline bool hlsl_is_numeric_type(const struct hlsl_type *type) return type->class <= HLSL_CLASS_LAST_NUMERIC; } +static inline bool hlsl_is_vec1(const struct hlsl_type *type) +{ + return type->class == HLSL_CLASS_SCALAR || (type->class == HLSL_CLASS_VECTOR && type->e.numeric.dimx == 1); +} + static inline unsigned int hlsl_sampler_dim_count(enum hlsl_sampler_dim dim) { switch (dim) @@ -1530,6 +1551,8 @@ struct hlsl_ir_node *hlsl_block_add_load_index(struct hlsl_ctx *ctx, struct hlsl void hlsl_block_add_loop(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_block *iter, struct hlsl_block *body, enum hlsl_loop_unroll_type unroll_type, unsigned int unroll_limit, const struct vkd3d_shader_location *loc); +struct hlsl_ir_node *hlsl_block_add_resource_load(struct hlsl_ctx *ctx, struct hlsl_block *block, + const struct hlsl_resource_load_params *params, const struct vkd3d_shader_location *loc); void hlsl_block_add_resource_store(struct hlsl_ctx *ctx, struct hlsl_block *block, const struct hlsl_deref *resource, struct hlsl_ir_node *coords, struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc); struct hlsl_ir_node *hlsl_block_add_simple_load(struct hlsl_ctx *ctx, struct hlsl_block *block, @@ -1541,6 +1564,8 @@ void hlsl_block_add_store_component(struct hlsl_ctx *ctx, struct hlsl_block *blo void hlsl_block_add_store_index(struct hlsl_ctx *ctx, struct hlsl_block *block, const struct hlsl_deref *lhs, struct hlsl_ir_node *idx, struct hlsl_ir_node *rhs, unsigned int writemask, const struct vkd3d_shader_location *loc); +struct hlsl_ir_node *hlsl_block_add_swizzle(struct hlsl_ctx *ctx, struct hlsl_block *block, uint32_t s, + unsigned int width, struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc); struct hlsl_ir_node *hlsl_block_add_uint_constant(struct hlsl_ctx *ctx, struct hlsl_block *block, unsigned int n, const struct vkd3d_shader_location *loc); struct hlsl_ir_node *hlsl_block_add_unary_expr(struct hlsl_ctx *ctx, struct hlsl_block *block, @@ -1567,6 +1592,7 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out); int hlsl_emit_effect_binary(struct hlsl_ctx *ctx, struct vkd3d_shader_code *out); +bool hlsl_init_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_var *var, unsigned int path_len); bool hlsl_init_deref_from_index_chain(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *chain); bool hlsl_copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, const struct hlsl_deref *other); @@ -1653,8 +1679,6 @@ struct hlsl_ir_node *hlsl_new_interlocked(struct hlsl_ctx *ctx, enum hlsl_interl struct hlsl_ir_node *value, const struct vkd3d_shader_location *loc); struct hlsl_ir_node *hlsl_new_matrix_swizzle(struct hlsl_ctx *ctx, struct hlsl_matrix_swizzle s, unsigned int width, struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc); -struct hlsl_ir_node *hlsl_new_resource_load(struct hlsl_ctx *ctx, - const struct hlsl_resource_load_params *params, const struct vkd3d_shader_location *loc); struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name, struct hlsl_struct_field *fields, size_t field_count); struct hlsl_ir_node *hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int components, @@ -1719,6 +1743,7 @@ bool hlsl_type_is_integer(const struct hlsl_type *type); bool hlsl_type_is_resource(const struct hlsl_type *type); bool hlsl_type_is_shader(const struct hlsl_type *type); bool hlsl_type_is_patch_array(const struct hlsl_type *type); +bool hlsl_type_is_primitive_array(const struct hlsl_type *type); unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int offset); bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2); @@ -1727,6 +1752,8 @@ void hlsl_calculate_buffer_offsets(struct hlsl_ctx *ctx); const struct hlsl_type *hlsl_get_multiarray_element_type(const struct hlsl_type *type); unsigned int hlsl_get_multiarray_size(const struct hlsl_type *type); +const struct hlsl_type *hlsl_get_stream_output_type(const struct hlsl_type *type); + uint32_t hlsl_combine_swizzles(uint32_t first, uint32_t second, unsigned int dim); unsigned int hlsl_combine_writemasks(unsigned int first, unsigned int second); uint32_t hlsl_map_swizzle(uint32_t swizzle, unsigned int writemask); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.l b/libs/vkd3d/libs/vkd3d-shader/hlsl.l index 605a9abaa93..d9fd43b5e78 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.l +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.l @@ -106,6 +106,8 @@ inline {return KW_INLINE; } inout {return KW_INOUT; } InputPatch {return KW_INPUTPATCH; } LineStream {return KW_LINESTREAM; } +line {return KW_LINE; } +lineadj {return KW_LINEADJ; } linear {return KW_LINEAR; } matrix {return KW_MATRIX; } namespace {return KW_NAMESPACE; } @@ -119,6 +121,7 @@ pass {return KW_PASS; } PixelShader {return KW_PIXELSHADER; } PointStream {return KW_POINTSTREAM; } pixelshader {return KW_PIXELSHADER; } +point {return KW_POINT; } RasterizerOrderedBuffer {return KW_RASTERIZERORDEREDBUFFER; } RasterizerOrderedStructuredBuffer {return KW_RASTERIZERORDEREDSTRUCTUREDBUFFER; } RasterizerOrderedTexture1D {return KW_RASTERIZERORDEREDTEXTURE1D; } @@ -175,6 +178,8 @@ TextureCube {return KW_TEXTURECUBE; } textureCUBE {return KW_TEXTURECUBE; } TextureCubeArray {return KW_TEXTURECUBEARRAY; } TriangleStream {return KW_TRIANGLESTREAM; } +triangle {return KW_TRIANGLE; } +triangleadj {return KW_TRIANGLEADJ; } true {return KW_TRUE; } typedef {return KW_TYPEDEF; } unsigned {return KW_UNSIGNED; } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl.y b/libs/vkd3d/libs/vkd3d-shader/hlsl.y index 71802fce388..ff3d58da8f4 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl.y @@ -372,7 +372,15 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct if (node->type == HLSL_IR_SAMPLER_STATE && dst_type->class == HLSL_CLASS_SAMPLER) return node; - if (!implicit_compatible_data_types(ctx, src_type, dst_type)) + if (implicit_compatible_data_types(ctx, src_type, dst_type)) + { + if (hlsl_is_numeric_type(dst_type) && hlsl_is_numeric_type(src_type) + && dst_type->e.numeric.dimx * dst_type->e.numeric.dimy < src_type->e.numeric.dimx * src_type->e.numeric.dimy + && ctx->warn_implicit_truncation) + hlsl_warning(ctx, loc, VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION, "Implicit truncation of %s type.", + src_type->class == HLSL_CLASS_VECTOR ? "vector" : "matrix"); + } + else { struct vkd3d_string_buffer *src_string, *dst_string; @@ -383,19 +391,12 @@ static struct hlsl_ir_node *add_implicit_conversion(struct hlsl_ctx *ctx, struct "Can't implicitly convert from %s to %s.", src_string->buffer, dst_string->buffer); hlsl_release_string_buffer(ctx, src_string); hlsl_release_string_buffer(ctx, dst_string); - return NULL; } - if (hlsl_is_numeric_type(dst_type) && hlsl_is_numeric_type(src_type) - && dst_type->e.numeric.dimx * dst_type->e.numeric.dimy < src_type->e.numeric.dimx * src_type->e.numeric.dimy - && ctx->warn_implicit_truncation) - hlsl_warning(ctx, loc, VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION, "Implicit truncation of %s type.", - src_type->class == HLSL_CLASS_VECTOR ? "vector" : "matrix"); - return add_cast(ctx, block, node, dst_type, loc); } -static bool add_explicit_conversion(struct hlsl_ctx *ctx, struct hlsl_block *block, +static void add_explicit_conversion(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_type *dst_type, const struct parse_array_sizes *arrays, const struct vkd3d_shader_location *loc) { struct hlsl_ir_node *instr = node_from_block(block); @@ -414,7 +415,7 @@ static bool add_explicit_conversion(struct hlsl_ctx *ctx, struct hlsl_block *blo } if (instr->data_type->class == HLSL_CLASS_ERROR) - return true; + return; if (!explicit_compatible_data_types(ctx, src_type, dst_type)) { @@ -427,10 +428,9 @@ static bool add_explicit_conversion(struct hlsl_ctx *ctx, struct hlsl_block *blo src_string->buffer, dst_string->buffer); hlsl_release_string_buffer(ctx, src_string); hlsl_release_string_buffer(ctx, dst_string); - return false; } - return add_cast(ctx, block, instr, dst_type, loc); + add_cast(ctx, block, instr, dst_type, loc); } static uint32_t add_modifiers(struct hlsl_ctx *ctx, uint32_t modifiers, uint32_t mod, @@ -449,7 +449,7 @@ static uint32_t add_modifiers(struct hlsl_ctx *ctx, uint32_t modifiers, uint32_t return modifiers | mod; } -static bool append_conditional_break(struct hlsl_ctx *ctx, struct hlsl_block *cond_block) +static void append_conditional_break(struct hlsl_ctx *ctx, struct hlsl_block *cond_block) { struct hlsl_ir_node *condition, *cast, *not; struct hlsl_block then_block; @@ -457,7 +457,7 @@ static bool append_conditional_break(struct hlsl_ctx *ctx, struct hlsl_block *co /* E.g. "for (i = 0; ; ++i)". */ if (list_empty(&cond_block->instrs)) - return true; + return; condition = node_from_block(cond_block); @@ -466,15 +466,12 @@ static bool append_conditional_break(struct hlsl_ctx *ctx, struct hlsl_block *co bool_type = hlsl_get_scalar_type(ctx, HLSL_TYPE_BOOL); /* We already checked for a 1-component numeric type, so * add_implicit_conversion() is equivalent to add_cast() here. */ - if (!(cast = add_cast(ctx, cond_block, condition, bool_type, &condition->loc))) - return false; - + cast = add_cast(ctx, cond_block, condition, bool_type, &condition->loc); not = hlsl_block_add_unary_expr(ctx, cond_block, HLSL_OP1_LOGIC_NOT, cast, &condition->loc); hlsl_block_init(&then_block); hlsl_block_add_jump(ctx, &then_block, HLSL_IR_JUMP_BREAK, NULL, &condition->loc); hlsl_block_add_if(ctx, cond_block, not, &then_block, NULL, &condition->loc); - return true; } static void check_attribute_list_for_duplicates(struct hlsl_ctx *ctx, const struct parse_attribute_list *attrs) @@ -518,11 +515,7 @@ static void resolve_loop_continue(struct hlsl_ctx *ctx, struct hlsl_block *block { if (!hlsl_clone_block(ctx, &cond_block, cond)) return; - if (!append_conditional_break(ctx, &cond_block)) - { - hlsl_block_cleanup(&cond_block); - return; - } + append_conditional_break(ctx, &cond_block); list_move_before(&instr->entry, &cond_block.instrs); } } @@ -598,11 +591,7 @@ static struct hlsl_default_value evaluate_static_expression(struct hlsl_ctx *ctx return ret; hlsl_block_add_block(&expr, block); - if (!(node = add_implicit_conversion(ctx, &expr, node_from_block(&expr), dst_type, loc))) - { - hlsl_block_cleanup(&expr); - return ret; - } + node = add_implicit_conversion(ctx, &expr, node_from_block(&expr), dst_type, loc); /* Wrap the node into a src to allow the reference to survive the multiple const passes. */ hlsl_src_from_node(&src, node); @@ -705,8 +694,7 @@ static struct hlsl_block *create_loop(struct hlsl_ctx *ctx, enum hlsl_loop_type if (!init && !(init = make_empty_block(ctx))) goto oom; - if (!append_conditional_break(ctx, cond)) - goto oom; + append_conditional_break(ctx, cond); if (type == HLSL_LOOP_DO_WHILE) list_move_tail(&body->instrs, &cond->instrs); @@ -850,9 +838,7 @@ static bool add_return(struct hlsl_ctx *ctx, struct hlsl_block *block, if (return_value->data_type->class == HLSL_CLASS_ERROR) return true; - if (!(return_value = add_implicit_conversion(ctx, block, return_value, return_type, loc))) - return false; - + return_value = add_implicit_conversion(ctx, block, return_value, return_type, loc); hlsl_block_add_simple_store(ctx, block, ctx->cur_function->return_var, return_value); } else @@ -931,10 +917,8 @@ static bool add_array_access(struct hlsl_ctx *ctx, struct hlsl_block *block, str return false; } - if (!(index = add_implicit_conversion(ctx, block, index, - hlsl_get_vector_type(ctx, HLSL_TYPE_UINT, dim_count), &index->loc))) - return false; - + index = add_implicit_conversion(ctx, block, index, + hlsl_get_vector_type(ctx, HLSL_TYPE_UINT, dim_count), &index->loc); hlsl_block_add_index(ctx, block, array, index, loc); return true; } @@ -1196,6 +1180,14 @@ static bool add_typedef(struct hlsl_ctx *ctx, struct hlsl_type *const orig_type, return true; } +static void check_invalid_stream_output_object(struct hlsl_ctx *ctx, const struct hlsl_type *type, + const char *name, const struct vkd3d_shader_location* loc) +{ + if (hlsl_type_component_count(type) != 1) + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Stream output object '%s' is not single-element.", name); +} + static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *instrs, struct hlsl_ir_var *dst, unsigned int *store_index, struct hlsl_ir_node *src, bool is_default_values_initializer); @@ -1230,6 +1222,9 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, "Output parameter '%s' has a default value.", param->name); + if (hlsl_get_stream_output_type(param->type)) + check_invalid_stream_output_object(ctx, param->type, param->name, loc); + if (!(var = hlsl_new_var(ctx, param->name, param->type, loc, ¶m->semantic, param->modifiers, ¶m->reg_reservation))) return false; @@ -1246,9 +1241,7 @@ static bool add_func_parameter(struct hlsl_ctx *ctx, struct hlsl_func_parameters if (!param->initializer.braces) { - if (!(add_implicit_conversion(ctx, param->initializer.instrs, param->initializer.args[0], param->type, loc))) - return false; - + add_implicit_conversion(ctx, param->initializer.instrs, param->initializer.args[0], param->type, loc); param->initializer.args[0] = node_from_block(param->initializer.instrs); } @@ -1645,10 +1638,7 @@ static struct hlsl_ir_node *add_unary_logical_expr(struct hlsl_ctx *ctx, struct bool_type = hlsl_get_numeric_type(ctx, arg->data_type->class, HLSL_TYPE_BOOL, arg->data_type->e.numeric.dimx, arg->data_type->e.numeric.dimy); - - if (!(args[0] = add_implicit_conversion(ctx, block, arg, bool_type, loc))) - return NULL; - + args[0] = add_implicit_conversion(ctx, block, arg, bool_type, loc); return add_expr(ctx, block, op, args, bool_type, loc); } @@ -1678,12 +1668,8 @@ static struct hlsl_ir_node *add_binary_arithmetic_expr(struct hlsl_ctx *ctx, str return block->value; } - if (!(args[0] = add_implicit_conversion(ctx, block, arg1, common_type, loc))) - return NULL; - - if (!(args[1] = add_implicit_conversion(ctx, block, arg2, common_type, loc))) - return NULL; - + args[0] = add_implicit_conversion(ctx, block, arg1, common_type, loc); + args[1] = add_implicit_conversion(ctx, block, arg2, common_type, loc); return add_expr(ctx, block, op, args, common_type, loc); } @@ -1714,12 +1700,8 @@ static struct hlsl_ir_node *add_binary_comparison_expr(struct hlsl_ctx *ctx, str common_type = hlsl_get_numeric_type(ctx, type, base, dimx, dimy); return_type = hlsl_get_numeric_type(ctx, type, HLSL_TYPE_BOOL, dimx, dimy); - if (!(args[0] = add_implicit_conversion(ctx, block, arg1, common_type, loc))) - return NULL; - - if (!(args[1] = add_implicit_conversion(ctx, block, arg2, common_type, loc))) - return NULL; - + args[0] = add_implicit_conversion(ctx, block, arg1, common_type, loc); + args[1] = add_implicit_conversion(ctx, block, arg2, common_type, loc); return add_expr(ctx, block, op, args, return_type, loc); } @@ -1737,12 +1719,8 @@ static struct hlsl_ir_node *add_binary_logical_expr(struct hlsl_ctx *ctx, struct common_type = hlsl_get_numeric_type(ctx, type, HLSL_TYPE_BOOL, dimx, dimy); - if (!(args[0] = add_implicit_conversion(ctx, block, arg1, common_type, loc))) - return NULL; - - if (!(args[1] = add_implicit_conversion(ctx, block, arg2, common_type, loc))) - return NULL; - + args[0] = add_implicit_conversion(ctx, block, arg1, common_type, loc); + args[1] = add_implicit_conversion(ctx, block, arg2, common_type, loc); return add_expr(ctx, block, op, args, common_type, loc); } @@ -1768,12 +1746,8 @@ static struct hlsl_ir_node *add_binary_shift_expr(struct hlsl_ctx *ctx, struct h return_type = hlsl_get_numeric_type(ctx, type, base, dimx, dimy); integer_type = hlsl_get_numeric_type(ctx, type, HLSL_TYPE_INT, dimx, dimy); - if (!(args[0] = add_implicit_conversion(ctx, block, arg1, return_type, loc))) - return NULL; - - if (!(args[1] = add_implicit_conversion(ctx, block, arg2, integer_type, loc))) - return NULL; - + args[0] = add_implicit_conversion(ctx, block, arg1, return_type, loc); + args[1] = add_implicit_conversion(ctx, block, arg2, integer_type, loc); return add_expr(ctx, block, op, args, return_type, loc); } @@ -1821,12 +1795,8 @@ static struct hlsl_ir_node *add_binary_dot_expr(struct hlsl_ctx *ctx, struct hls common_type = hlsl_get_vector_type(ctx, base, dim); ret_type = hlsl_get_scalar_type(ctx, base); - if (!(args[0] = add_implicit_conversion(ctx, instrs, arg1, common_type, loc))) - return NULL; - - if (!(args[1] = add_implicit_conversion(ctx, instrs, arg2, common_type, loc))) - return NULL; - + args[0] = add_implicit_conversion(ctx, instrs, arg1, common_type, loc); + args[1] = add_implicit_conversion(ctx, instrs, arg2, common_type, loc); return add_expr(ctx, instrs, op, args, ret_type, loc); } @@ -2022,8 +1992,7 @@ static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struc width = size; } - if (!(rhs = add_implicit_conversion(ctx, block, rhs, lhs_type, &rhs->loc))) - return false; + rhs = add_implicit_conversion(ctx, block, rhs, lhs_type, &rhs->loc); while (lhs->type != HLSL_IR_LOAD && lhs->type != HLSL_IR_INDEX) { @@ -2053,7 +2022,6 @@ static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struc else if (lhs->type == HLSL_IR_SWIZZLE) { struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(lhs); - struct hlsl_ir_node *new_swizzle; uint32_t s; VKD3D_ASSERT(!matrix_writemask); @@ -2084,13 +2052,9 @@ static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struc } } - if (!(new_swizzle = hlsl_new_swizzle(ctx, s, width, rhs, &swizzle->node.loc))) - return false; - hlsl_block_add_instr(block, new_swizzle); - + rhs = hlsl_block_add_swizzle(ctx, block, s, width, rhs, &swizzle->node.loc); lhs = swizzle->val.node; lhs_type = hlsl_get_vector_type(ctx, lhs_type->e.numeric.type, width); - rhs = new_swizzle; } else { @@ -2102,8 +2066,7 @@ static bool add_assignment(struct hlsl_ctx *ctx, struct hlsl_block *block, struc /* lhs casts could have resulted in a discrepancy between the * rhs->data_type and the type of the variable that will be ulimately * stored to. This is corrected. */ - if (!(rhs = add_cast(ctx, block, rhs, lhs_type, &rhs->loc))) - return false; + rhs = add_cast(ctx, block, rhs, lhs_type, &rhs->loc); if (lhs->type == HLSL_IR_INDEX && hlsl_index_chain_has_resource_access(hlsl_ir_index(lhs))) { @@ -2325,9 +2288,7 @@ static void initialize_var_components(struct hlsl_ctx *ctx, struct hlsl_block *i } else { - if (!(conv = add_implicit_conversion(ctx, instrs, load, dst_comp_type, &src->loc))) - return; - + conv = add_implicit_conversion(ctx, instrs, load, dst_comp_type, &src->loc); hlsl_block_add_store_component(ctx, instrs, &dst_deref, *store_index, conv); } } @@ -2401,10 +2362,10 @@ static bool type_has_numeric_components(struct hlsl_type *type) return false; } -static void check_invalid_in_out_modifiers(struct hlsl_ctx *ctx, unsigned int modifiers, +static void check_invalid_non_parameter_modifiers(struct hlsl_ctx *ctx, unsigned int modifiers, const struct vkd3d_shader_location *loc) { - modifiers &= (HLSL_STORAGE_IN | HLSL_STORAGE_OUT); + modifiers &= (HLSL_STORAGE_IN | HLSL_STORAGE_OUT | HLSL_PRIMITIVE_MODIFIERS_MASK); if (modifiers) { struct vkd3d_string_buffer *string; @@ -2438,6 +2399,7 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) bool constant_buffer = false; struct hlsl_ir_var *var; struct hlsl_type *type; + bool stream_output; char *var_name; unsigned int i; @@ -2529,6 +2491,10 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) hlsl_fixme(ctx, &v->loc, "Shader model 5.1+ resource array."); } + stream_output = !!hlsl_get_stream_output_type(type); + if (stream_output) + check_invalid_stream_output_object(ctx, type, v->name, &v->loc); + if (!(var_name = vkd3d_strdup(v->name))) return; @@ -2583,6 +2549,10 @@ static void declare_var(struct hlsl_ctx *ctx, struct parse_variable_def *v) if (!(modifiers & HLSL_STORAGE_STATIC)) var->storage_modifiers |= HLSL_STORAGE_UNIFORM; + if (stream_output) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_MISPLACED_STREAM_OUTPUT, + "Stream output object '%s' is not allowed in the global scope.", var->name); + if ((ctx->profile->major_version < 5 || ctx->profile->type == VKD3D_SHADER_TYPE_EFFECT) && (var->storage_modifiers & HLSL_STORAGE_UNIFORM)) { @@ -2713,15 +2683,8 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var } if (!v->initializer.braces) - { - if (!(add_implicit_conversion(ctx, v->initializer.instrs, v->initializer.args[0], type, &v->loc))) - { - free_parse_variable_def(v); - continue; - } - - v->initializer.args[0] = node_from_block(v->initializer.instrs); - } + v->initializer.args[0] = add_implicit_conversion(ctx, + v->initializer.instrs, v->initializer.args[0], type, &v->loc); if (var->data_type->class != HLSL_CLASS_ERROR) initialize_var(ctx, var, &v->initializer, is_default_values_initializer); @@ -2755,13 +2718,7 @@ static struct hlsl_block *initialize_vars(struct hlsl_ctx *ctx, struct list *var } zero = hlsl_block_add_uint_constant(ctx, &ctx->static_initializers, 0, &var->loc); - - if (!(cast = add_cast(ctx, &ctx->static_initializers, zero, var->data_type, &var->loc))) - { - free_parse_variable_def(v); - continue; - } - + cast = add_cast(ctx, &ctx->static_initializers, zero, var->data_type, &var->loc); hlsl_block_add_simple_store(ctx, &ctx->static_initializers, var, cast); } free_parse_variable_def(v); @@ -3033,13 +2990,7 @@ static struct hlsl_ir_node *add_user_call(struct hlsl_ctx *ctx, if (param->storage_modifiers & HLSL_STORAGE_IN) { if (!hlsl_types_are_equal(arg->data_type, param->data_type)) - { - struct hlsl_ir_node *cast; - - if (!(cast = add_cast(ctx, args->instrs, arg, param->data_type, &arg->loc))) - return NULL; - arg = cast; - } + arg = add_cast(ctx, args->instrs, arg, param->data_type, &arg->loc); hlsl_block_add_simple_store(ctx, args->instrs, param, arg); } @@ -3125,21 +3076,13 @@ static struct hlsl_ir_node *intrinsic_float_convert_arg(struct hlsl_ctx *ctx, return add_implicit_conversion(ctx, params->instrs, arg, type, loc); } -static bool convert_args(struct hlsl_ctx *ctx, const struct parse_initializer *params, +static void convert_args(struct hlsl_ctx *ctx, const struct parse_initializer *params, struct hlsl_type *type, const struct vkd3d_shader_location *loc) { unsigned int i; for (i = 0; i < params->args_count; ++i) - { - struct hlsl_ir_node *new_arg; - - if (!(new_arg = add_implicit_conversion(ctx, params->instrs, params->args[i], type, loc))) - return false; - params->args[i] = new_arg; - } - - return true; + params->args[i] = add_implicit_conversion(ctx, params->instrs, params->args[i], type, loc); } static struct hlsl_type *elementwise_intrinsic_get_common_type(struct hlsl_ctx *ctx, @@ -3200,7 +3143,8 @@ static bool elementwise_intrinsic_convert_args(struct hlsl_ctx *ctx, if (!(common_type = elementwise_intrinsic_get_common_type(ctx, params, loc))) return false; - return convert_args(ctx, params, common_type, loc); + convert_args(ctx, params, common_type, loc); + return true; } static bool elementwise_intrinsic_float_convert_args(struct hlsl_ctx *ctx, @@ -3213,7 +3157,8 @@ static bool elementwise_intrinsic_float_convert_args(struct hlsl_ctx *ctx, if (hlsl_type_is_integer(type)) type = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_FLOAT, type->e.numeric.dimx, type->e.numeric.dimy); - return convert_args(ctx, params, type, loc); + convert_args(ctx, params, type, loc); + return true; } static bool elementwise_intrinsic_uint_convert_args(struct hlsl_ctx *ctx, @@ -3226,7 +3171,8 @@ static bool elementwise_intrinsic_uint_convert_args(struct hlsl_ctx *ctx, type = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_UINT, type->e.numeric.dimx, type->e.numeric.dimy); - return convert_args(ctx, params, type, loc); + convert_args(ctx, params, type, loc); + return true; } static bool intrinsic_abs(struct hlsl_ctx *ctx, @@ -3263,8 +3209,7 @@ static bool write_acos_or_asin(struct hlsl_ctx *ctx, const char *fn_name = asin_mode ? fn_name_asin : fn_name_acos; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); type = arg->data_type; if (!(body = hlsl_sprintf_alloc(ctx, template, @@ -3318,9 +3263,7 @@ static bool intrinsic_all(struct hlsl_ctx *ctx, struct hlsl_type *bool_type; bool_type = convert_numeric_type(ctx, arg->data_type, HLSL_TYPE_BOOL); - if (!(cast = add_cast(ctx, params->instrs, arg, bool_type, loc))) - return false; - + cast = add_cast(ctx, params->instrs, arg, bool_type, loc); add_combine_components(ctx, params, cast, HLSL_OP2_LOGIC_AND, loc); return true; } @@ -3332,9 +3275,7 @@ static bool intrinsic_any(struct hlsl_ctx *ctx, const struct parse_initializer * struct hlsl_type *bool_type; bool_type = convert_numeric_type(ctx, arg->data_type, HLSL_TYPE_BOOL); - if (!(cast = add_cast(ctx, params->instrs, arg, bool_type, loc))) - return false; - + cast = add_cast(ctx, params->instrs, arg, bool_type, loc); add_combine_components(ctx, params, cast, HLSL_OP2_LOGIC_OR, loc); return true; } @@ -3522,10 +3463,7 @@ static bool intrinsic_asuint(struct hlsl_ctx *ctx, static bool intrinsic_ceil(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { - struct hlsl_ir_node *arg; - - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + struct hlsl_ir_node *arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_CEIL, arg, loc); } @@ -3572,10 +3510,7 @@ static bool intrinsic_clip(struct hlsl_ctx *ctx, static bool intrinsic_cos(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { - struct hlsl_ir_node *arg; - - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + struct hlsl_ir_node *arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_COS, arg, loc); } @@ -3596,8 +3531,7 @@ static bool write_cosh_or_sinh(struct hlsl_ctx *ctx, static const char fn_name_sinh[] = "sinh"; static const char fn_name_cosh[] = "cosh"; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); type_name = arg->data_type->name; fn_name = sinh_mode ? fn_name_sinh : fn_name_cosh; @@ -3635,32 +3569,18 @@ static bool intrinsic_cross(struct hlsl_ctx *ctx, cast_type = hlsl_get_vector_type(ctx, base, 3); - if (!(arg1_cast = add_implicit_conversion(ctx, params->instrs, arg1, cast_type, loc))) - return false; - - if (!(arg2_cast = add_implicit_conversion(ctx, params->instrs, arg2, cast_type, loc))) - return false; - - if (!(arg1_swzl1 = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(Z, X, Y, Z), 3, arg1_cast, loc))) - return false; - hlsl_block_add_instr(params->instrs, arg1_swzl1); - - if (!(arg2_swzl1 = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(Y, Z, X, Y), 3, arg2_cast, loc))) - return false; - hlsl_block_add_instr(params->instrs, arg2_swzl1); + arg1_cast = add_implicit_conversion(ctx, params->instrs, arg1, cast_type, loc); + arg2_cast = add_implicit_conversion(ctx, params->instrs, arg2, cast_type, loc); + arg1_swzl1 = hlsl_block_add_swizzle(ctx, params->instrs, HLSL_SWIZZLE(Z, X, Y, Z), 3, arg1_cast, loc); + arg2_swzl1 = hlsl_block_add_swizzle(ctx, params->instrs, HLSL_SWIZZLE(Y, Z, X, Y), 3, arg2_cast, loc); if (!(mul1 = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, arg1_swzl1, arg2_swzl1, loc))) return false; mul1_neg = hlsl_block_add_unary_expr(ctx, params->instrs, HLSL_OP1_NEG, mul1, loc); - if (!(arg1_swzl2 = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(Y, Z, X, Y), 3, arg1_cast, loc))) - return false; - hlsl_block_add_instr(params->instrs, arg1_swzl2); - - if (!(arg2_swzl2 = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(Z, X, Y, Z), 3, arg2_cast, loc))) - return false; - hlsl_block_add_instr(params->instrs, arg2_swzl2); + arg1_swzl2 = hlsl_block_add_swizzle(ctx, params->instrs, HLSL_SWIZZLE(Y, Z, X, Y), 3, arg1_cast, loc); + arg2_swzl2 = hlsl_block_add_swizzle(ctx, params->instrs, HLSL_SWIZZLE(Z, X, Y, Z), 3, arg2_cast, loc); if (!(mul2 = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, arg1_swzl2, arg2_swzl2, loc))) return false; @@ -3673,8 +3593,7 @@ static bool intrinsic_ddx(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_DSX, arg, loc); } @@ -3684,8 +3603,7 @@ static bool intrinsic_ddx_coarse(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_DSX_COARSE, arg, loc); } @@ -3695,8 +3613,7 @@ static bool intrinsic_ddx_fine(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_DSX_FINE, arg, loc); } @@ -3706,8 +3623,7 @@ static bool intrinsic_ddy(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_DSY, arg, loc); } @@ -3717,8 +3633,7 @@ static bool intrinsic_ddy_coarse(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_DSY_COARSE, arg, loc); } @@ -3728,8 +3643,7 @@ static bool intrinsic_degrees(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg, *deg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); /* 1 rad = 180/pi degree = 57.2957795 degree */ deg = hlsl_block_add_float_constant(ctx, params->instrs, 57.2957795f, loc); @@ -3741,8 +3655,7 @@ static bool intrinsic_ddy_fine(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_DSY_FINE, arg, loc); } @@ -3796,8 +3709,7 @@ static bool intrinsic_determinant(struct hlsl_ctx *ctx, return false; } - if (!(arg = intrinsic_float_convert_arg(ctx, params, arg, loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, arg, loc); dim = min(type->e.numeric.dimx, type->e.numeric.dimy); if (dim == 1) @@ -3839,11 +3751,8 @@ static bool intrinsic_distance(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg1, *arg2, *neg, *add, *dot; - if (!(arg1 = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; - - if (!(arg2 = intrinsic_float_convert_arg(ctx, params, params->args[1], loc))) - return false; + arg1 = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); + arg2 = intrinsic_float_convert_arg(ctx, params, params->args[1], loc); if (!(neg = add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_NEG, arg2, loc))) return false; @@ -3912,8 +3821,7 @@ static bool intrinsic_exp(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg, *mul, *coeff; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); /* 1/ln(2) */ coeff = hlsl_block_add_float_constant(ctx, params->instrs, 1.442695f, loc); @@ -3929,8 +3837,7 @@ static bool intrinsic_exp2(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_EXP2, arg, loc); } @@ -3998,8 +3905,7 @@ static bool intrinsic_floor(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_FLOOR, arg, loc); } @@ -4011,11 +3917,8 @@ static bool intrinsic_fmod(struct hlsl_ctx *ctx, const struct parse_initializer struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = { 0 }; static const struct hlsl_constant_value zero_value; - if (!(x = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; - - if (!(y = intrinsic_float_convert_arg(ctx, params, params->args[1], loc))) - return false; + x = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); + y = intrinsic_float_convert_arg(ctx, params, params->args[1], loc); if (!(div = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_DIV, x, y, loc))) return false; @@ -4050,8 +3953,7 @@ static bool intrinsic_frac(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_FRACT, arg, loc); } @@ -4126,8 +4028,7 @@ static bool intrinsic_length(struct hlsl_ctx *ctx, hlsl_release_string_buffer(ctx, string); } - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); if (!(dot = add_binary_dot_expr(ctx, params->instrs, arg, arg, loc))) return false; @@ -4189,8 +4090,7 @@ static bool intrinsic_log(struct hlsl_ctx *ctx, { struct hlsl_ir_node *log, *arg, *coeff; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); if (!(log = add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_LOG2, arg, loc))) return false; @@ -4205,8 +4105,7 @@ static bool intrinsic_log10(struct hlsl_ctx *ctx, { struct hlsl_ir_node *log, *arg, *coeff; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); if (!(log = add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_LOG2, arg, loc))) return false; @@ -4221,8 +4120,7 @@ static bool intrinsic_log2(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_LOG2, arg, loc); } @@ -4330,11 +4228,8 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, ret_type = hlsl_get_scalar_type(ctx, base); } - if (!(cast1 = add_implicit_conversion(ctx, params->instrs, arg1, cast_type1, loc))) - return false; - - if (!(cast2 = add_implicit_conversion(ctx, params->instrs, arg2, cast_type2, loc))) - return false; + cast1 = add_implicit_conversion(ctx, params->instrs, arg1, cast_type1, loc); + cast2 = add_implicit_conversion(ctx, params->instrs, arg2, cast_type2, loc); if (!(var = hlsl_new_synthetic_var(ctx, "mul", matrix_type, loc))) return false; @@ -4375,7 +4270,8 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, } load = hlsl_block_add_simple_load(ctx, params->instrs, var, loc); - return !!add_implicit_conversion(ctx, params->instrs, load, ret_type, loc); + add_implicit_conversion(ctx, params->instrs, load, ret_type, loc); + return true; } static bool intrinsic_normalize(struct hlsl_ctx *ctx, @@ -4394,8 +4290,7 @@ static bool intrinsic_normalize(struct hlsl_ctx *ctx, hlsl_release_string_buffer(ctx, string); } - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); if (!(dot = add_binary_dot_expr(ctx, params->instrs, arg, arg, loc))) return false; @@ -4428,8 +4323,7 @@ static bool intrinsic_radians(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg, *rad; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); /* 1 degree = pi/180 rad = 0.0174532925f rad */ rad = hlsl_block_add_float_constant(ctx, params->instrs, 0.0174532925f, loc); @@ -4441,8 +4335,7 @@ static bool intrinsic_rcp(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_RCP, arg, loc); } @@ -4473,7 +4366,6 @@ static bool intrinsic_refract(struct hlsl_ctx *ctx, { struct hlsl_type *type, *scalar_type; struct hlsl_ir_function_decl *func; - struct hlsl_ir_node *index; char *body; static const char template[] = @@ -4503,9 +4395,7 @@ static bool intrinsic_refract(struct hlsl_ctx *ctx, * which we will only use the first component of. */ scalar_type = hlsl_get_scalar_type(ctx, params->args[2]->data_type->e.numeric.type); - if (!(index = add_implicit_conversion(ctx, params->instrs, params->args[2], scalar_type, loc))) - return false; - params->args[2] = index; + params->args[2] = add_implicit_conversion(ctx, params->instrs, params->args[2], scalar_type, loc); if (!elementwise_intrinsic_float_convert_args(ctx, params, loc)) return false; @@ -4528,8 +4418,7 @@ static bool intrinsic_round(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_ROUND, arg, loc); } @@ -4539,8 +4428,7 @@ static bool intrinsic_rsqrt(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_RSQ, arg, loc); } @@ -4550,8 +4438,7 @@ static bool intrinsic_saturate(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_SAT, arg, loc); } @@ -4574,16 +4461,14 @@ static bool intrinsic_sign(struct hlsl_ctx *ctx, if (!(lt = add_binary_comparison_expr(ctx, params->instrs, HLSL_OP2_LESS, zero, arg, loc))) return false; - if (!(op1 = add_implicit_conversion(ctx, params->instrs, lt, int_type, loc))) - return false; + op1 = add_implicit_conversion(ctx, params->instrs, lt, int_type, loc); /* Check if arg < 0, cast bool to int and invert (meaning true is -1) */ if (!(lt = add_binary_comparison_expr(ctx, params->instrs, HLSL_OP2_LESS, arg, zero, loc))) return false; - if (!(op2 = add_implicit_conversion(ctx, params->instrs, lt, int_type, loc))) - return false; + op2 = add_implicit_conversion(ctx, params->instrs, lt, int_type, loc); if (!(neg = add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_NEG, op2, loc))) return false; @@ -4597,8 +4482,7 @@ static bool intrinsic_sin(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_SIN, arg, loc); } @@ -4672,8 +4556,7 @@ static bool intrinsic_sqrt(struct hlsl_ctx *ctx, { struct hlsl_ir_node *arg; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_SQRT, arg, loc); } @@ -4692,7 +4575,8 @@ static bool intrinsic_step(struct hlsl_ctx *ctx, params->args[1], params->args[0], loc))) return false; - return !!add_implicit_conversion(ctx, params->instrs, ge, type, loc); + add_implicit_conversion(ctx, params->instrs, ge, type, loc); + return true; } static bool intrinsic_tan(struct hlsl_ctx *ctx, @@ -4726,8 +4610,7 @@ static bool intrinsic_tanh(struct hlsl_ctx *ctx, " return (exp_pos - exp_neg) / (exp_pos + exp_neg);\n" "}\n"; - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); type = arg->data_type; if (!(body = hlsl_sprintf_alloc(ctx, template, @@ -4748,7 +4631,7 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * unsigned int sampler_dim = hlsl_sampler_dim_count(dim); struct hlsl_resource_load_params load_params = { 0 }; const struct hlsl_type *sampler_type; - struct hlsl_ir_node *coords, *sample; + struct hlsl_ir_node *coords; if (params->args_count != 2 && params->args_count != 4) { @@ -4780,47 +4663,27 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * else load_params.type = HLSL_RESOURCE_SAMPLE_LOD_BIAS; - if (!(c = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, Y, Z, W), sampler_dim, params->args[1], loc))) - return false; - hlsl_block_add_instr(params->instrs, c); - - if (!(coords = add_implicit_conversion(ctx, params->instrs, c, - hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) - { - return false; - } - - if (!(lod = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(W, W, W, W), 1, params->args[1], loc))) - return false; - hlsl_block_add_instr(params->instrs, lod); + c = hlsl_block_add_swizzle(ctx, params->instrs, HLSL_SWIZZLE(X, Y, Z, W), sampler_dim, params->args[1], loc); + coords = add_implicit_conversion(ctx, params->instrs, c, + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc); - if (!(load_params.lod = add_implicit_conversion(ctx, params->instrs, lod, - hlsl_get_scalar_type(ctx, HLSL_TYPE_FLOAT), loc))) - { - return false; - } + lod = hlsl_block_add_swizzle(ctx, params->instrs, HLSL_SWIZZLE(W, W, W, W), 1, params->args[1], loc); + load_params.lod = add_implicit_conversion(ctx, params->instrs, lod, + hlsl_get_scalar_type(ctx, HLSL_TYPE_FLOAT), loc); } else if (!strcmp(name, "tex2Dproj") || !strcmp(name, "tex3Dproj") || !strcmp(name, "texCUBEproj")) { - if (!(coords = add_implicit_conversion(ctx, params->instrs, params->args[1], - hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4), loc))) - { - return false; - } + coords = add_implicit_conversion(ctx, params->instrs, params->args[1], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4), loc); if (hlsl_version_ge(ctx, 4, 0)) { struct hlsl_ir_node *divisor; - if (!(divisor = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(W, W, W, W), sampler_dim, coords, loc))) - return false; - hlsl_block_add_instr(params->instrs, divisor); - - if (!(coords = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, Y, Z, W), sampler_dim, coords, loc))) - return false; - hlsl_block_add_instr(params->instrs, coords); + divisor = hlsl_block_add_swizzle(ctx, params->instrs, HLSL_SWIZZLE(W, W, W, W), sampler_dim, coords, loc); + coords = hlsl_block_add_swizzle(ctx, params->instrs, HLSL_SWIZZLE(X, Y, Z, W), sampler_dim, coords, loc); if (!(coords = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_DIV, coords, divisor, loc))) return false; @@ -4834,35 +4697,19 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * } else if (params->args_count == 4) /* Gradient sampling. */ { - if (!(coords = add_implicit_conversion(ctx, params->instrs, params->args[1], - hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) - { - return false; - } - - if (!(load_params.ddx = add_implicit_conversion(ctx, params->instrs, params->args[2], - hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) - { - return false; - } - - if (!(load_params.ddy = add_implicit_conversion(ctx, params->instrs, params->args[3], - hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) - { - return false; - } - + coords = add_implicit_conversion(ctx, params->instrs, params->args[1], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc); + load_params.ddx = add_implicit_conversion(ctx, params->instrs, params->args[2], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc); + load_params.ddy = add_implicit_conversion(ctx, params->instrs, params->args[3], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc); load_params.type = HLSL_RESOURCE_SAMPLE_GRAD; } else { load_params.type = HLSL_RESOURCE_SAMPLE; - - if (!(coords = add_implicit_conversion(ctx, params->instrs, params->args[1], - hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) - { - return false; - } + coords = add_implicit_conversion(ctx, params->instrs, params->args[1], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc); } /* tex1D() functions never produce 1D resource declarations. For newer profiles half offset @@ -4889,9 +4736,7 @@ static bool intrinsic_tex(struct hlsl_ctx *ctx, const struct parse_initializer * load_params.format = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, 4); load_params.sampling_dim = dim; - if (!(sample = hlsl_new_resource_load(ctx, &load_params, loc))) - return false; - hlsl_block_add_instr(params->instrs, sample); + hlsl_block_add_resource_load(ctx, params->instrs, &load_params, loc); return true; } @@ -5026,10 +4871,7 @@ static bool intrinsic_transpose(struct hlsl_ctx *ctx, static bool intrinsic_trunc(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { - struct hlsl_ir_node *arg; - - if (!(arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc))) - return false; + struct hlsl_ir_node *arg = intrinsic_float_convert_arg(ctx, params, params->args[0], loc); return !!add_unary_arithmetic_expr(ctx, params->instrs, HLSL_OP1_TRUNC, arg, loc); } @@ -5037,7 +4879,7 @@ static bool intrinsic_trunc(struct hlsl_ctx *ctx, static bool intrinsic_d3dcolor_to_ubyte4(struct hlsl_ctx *ctx, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { - struct hlsl_ir_node *arg = params->args[0], *ret, *c, *swizzle; + struct hlsl_ir_node *arg = params->args[0], *ret, *c; struct hlsl_type *arg_type = arg->data_type; if (arg_type->class != HLSL_CLASS_SCALAR && !(arg_type->class == HLSL_CLASS_VECTOR @@ -5054,19 +4896,11 @@ static bool intrinsic_d3dcolor_to_ubyte4(struct hlsl_ctx *ctx, return false; } - if (!(arg = intrinsic_float_convert_arg(ctx, params, arg, loc))) - return false; - + arg = intrinsic_float_convert_arg(ctx, params, arg, loc); c = hlsl_block_add_float_constant(ctx, params->instrs, 255.0f + (0.5f / 256.0f), loc); if (arg_type->class == HLSL_CLASS_VECTOR) - { - if (!(swizzle = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(Z, Y, X, W), 4, arg, loc))) - return false; - hlsl_block_add_instr(params->instrs, swizzle); - - arg = swizzle; - } + arg = hlsl_block_add_swizzle(ctx, params->instrs, HLSL_SWIZZLE(Z, Y, X, W), 4, arg, loc); if (!(ret = add_binary_arithmetic_expr(ctx, params->instrs, HLSL_OP2_MUL, arg, c, loc))) return false; @@ -5603,8 +5437,7 @@ static bool add_ternary(struct hlsl_ctx *ctx, struct hlsl_block *block, { cond_type = hlsl_get_numeric_type(ctx, common_type->class, HLSL_TYPE_BOOL, common_type->e.numeric.dimx, common_type->e.numeric.dimy); - if (!(cond = add_implicit_conversion(ctx, block, cond, cond_type, &cond->loc))) - return false; + cond = add_implicit_conversion(ctx, block, cond, cond_type, &cond->loc); } else { @@ -5633,15 +5466,11 @@ static bool add_ternary(struct hlsl_ctx *ctx, struct hlsl_block *block, cond_type = hlsl_get_numeric_type(ctx, common_type->class, HLSL_TYPE_BOOL, common_type->e.numeric.dimx, common_type->e.numeric.dimy); - if (!(cond = add_implicit_conversion(ctx, block, cond, cond_type, &cond->loc))) - return false; + cond = add_implicit_conversion(ctx, block, cond, cond_type, &cond->loc); } - if (!(first = add_implicit_conversion(ctx, block, first, common_type, &first->loc))) - return false; - - if (!(second = add_implicit_conversion(ctx, block, second, common_type, &second->loc))) - return false; + first = add_implicit_conversion(ctx, block, first, common_type, &first->loc); + second = add_implicit_conversion(ctx, block, second, common_type, &second->loc); } else { @@ -5661,9 +5490,7 @@ static bool add_ternary(struct hlsl_ctx *ctx, struct hlsl_block *block, cond_type = hlsl_get_numeric_type(ctx, cond_type->class, HLSL_TYPE_BOOL, cond_type->e.numeric.dimx, cond_type->e.numeric.dimy); - if (!(cond = add_implicit_conversion(ctx, block, cond, cond_type, &cond->loc))) - return false; - + cond = add_implicit_conversion(ctx, block, cond, cond_type, &cond->loc); common_type = first->data_type; } @@ -5716,7 +5543,6 @@ static bool add_raw_load_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bl const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { struct hlsl_resource_load_params load_params = {.type = HLSL_RESOURCE_LOAD}; - struct hlsl_ir_node *load; unsigned int value_dim; if (params->args_count != 1 && params->args_count != 2) @@ -5748,16 +5574,11 @@ static bool add_raw_load_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bl else value_dim = 4; - if (!(load_params.coords = add_implicit_conversion(ctx, block, params->args[0], - hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc))) - return false; - + load_params.coords = add_implicit_conversion(ctx, block, params->args[0], + hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc); load_params.format = hlsl_get_vector_type(ctx, HLSL_TYPE_UINT, value_dim); load_params.resource = object; - - if (!(load = hlsl_new_resource_load(ctx, &load_params, loc))) - return false; - hlsl_block_add_instr(block, load); + hlsl_block_add_resource_load(ctx, block, &load_params, loc); return true; } @@ -5767,7 +5588,6 @@ static bool add_load_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, const struct hlsl_type *object_type = object->data_type; struct hlsl_resource_load_params load_params = {.type = HLSL_RESOURCE_LOAD}; unsigned int sampler_dim, offset_dim; - struct hlsl_ir_node *load; bool multisampled; if (object_type->sampler_dim == HLSL_SAMPLER_DIM_RAW_BUFFER) @@ -5794,18 +5614,12 @@ static bool add_load_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, } if (multisampled) - { - if (!(load_params.sample_index = add_implicit_conversion(ctx, block, params->args[1], - hlsl_get_scalar_type(ctx, HLSL_TYPE_INT), loc))) - return false; - } + load_params.sample_index = add_implicit_conversion(ctx, block, params->args[1], + hlsl_get_scalar_type(ctx, HLSL_TYPE_INT), loc); if (!!offset_dim && params->args_count > 1 + multisampled) - { - if (!(load_params.texel_offset = add_implicit_conversion(ctx, block, params->args[1 + multisampled], - hlsl_get_vector_type(ctx, HLSL_TYPE_INT, offset_dim), loc))) - return false; - } + load_params.texel_offset = add_implicit_conversion(ctx, block, params->args[1 + multisampled], + hlsl_get_vector_type(ctx, HLSL_TYPE_INT, offset_dim), loc); if (params->args_count > 1 + multisampled + !!offset_dim) { @@ -5813,16 +5627,11 @@ static bool add_load_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, } /* +1 for the mipmap level for non-multisampled textures */ - if (!(load_params.coords = add_implicit_conversion(ctx, block, params->args[0], - hlsl_get_vector_type(ctx, HLSL_TYPE_INT, sampler_dim + !multisampled), loc))) - return false; - + load_params.coords = add_implicit_conversion(ctx, block, params->args[0], + hlsl_get_vector_type(ctx, HLSL_TYPE_INT, sampler_dim + !multisampled), loc); load_params.format = object_type->e.resource.format; load_params.resource = object; - - if (!(load = hlsl_new_resource_load(ctx, &load_params, loc))) - return false; - hlsl_block_add_instr(block, load); + hlsl_block_add_resource_load(ctx, block, &load_params, loc); return true; } @@ -5833,7 +5642,6 @@ static bool add_sample_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc struct hlsl_resource_load_params load_params = {.type = HLSL_RESOURCE_SAMPLE}; 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); @@ -5858,16 +5666,12 @@ static bool add_sample_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc 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; + load_params.coords = add_implicit_conversion(ctx, block, params->args[1], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc); if (offset_dim && params->args_count > 2) - { - if (!(load_params.texel_offset = add_implicit_conversion(ctx, block, params->args[2], - hlsl_get_vector_type(ctx, HLSL_TYPE_INT, offset_dim), loc))) - return false; - } + load_params.texel_offset = add_implicit_conversion(ctx, block, params->args[2], + hlsl_get_vector_type(ctx, HLSL_TYPE_INT, offset_dim), loc); if (params->args_count > 2 + !!offset_dim) hlsl_fixme(ctx, loc, "Sample() clamp parameter."); @@ -5877,11 +5681,7 @@ static bool add_sample_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc load_params.format = object_type->e.resource.format; 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); - + hlsl_block_add_resource_load(ctx, block, &load_params, loc); return true; } @@ -5892,7 +5692,6 @@ static bool add_sample_cmp_method_call(struct hlsl_ctx *ctx, struct hlsl_block * 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); @@ -5923,20 +5722,14 @@ static bool add_sample_cmp_method_call(struct hlsl_ctx *ctx, struct hlsl_block * 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))) - load_params.cmp = params->args[2]; + load_params.coords = add_implicit_conversion(ctx, block, params->args[1], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc); + load_params.cmp = add_implicit_conversion(ctx, block, params->args[2], + hlsl_get_scalar_type(ctx, HLSL_TYPE_FLOAT), loc); if (offset_dim && params->args_count > 3) - { - if (!(load_params.texel_offset = add_implicit_conversion(ctx, block, params->args[2], - hlsl_get_vector_type(ctx, HLSL_TYPE_INT, offset_dim), loc))) - return false; - } + load_params.texel_offset = add_implicit_conversion(ctx, block, params->args[2], + hlsl_get_vector_type(ctx, HLSL_TYPE_INT, offset_dim), loc); if (params->args_count > 3 + !!offset_dim) hlsl_fixme(ctx, loc, "%s() clamp parameter.", name); @@ -5946,11 +5739,7 @@ static bool add_sample_cmp_method_call(struct hlsl_ctx *ctx, struct hlsl_block * load_params.format = object_type->e.resource.format; 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); - + hlsl_block_add_resource_load(ctx, block, &load_params, loc); return true; } @@ -5961,7 +5750,6 @@ static bool add_gather_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc 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; unsigned int read_channel; sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); @@ -6015,9 +5803,8 @@ static bool add_gather_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc } else if (offset_dim && params->args_count > 2) { - if (!(load_params.texel_offset = add_implicit_conversion(ctx, block, params->args[2], - hlsl_get_vector_type(ctx, HLSL_TYPE_INT, offset_dim), loc))) - return false; + load_params.texel_offset = add_implicit_conversion(ctx, block, params->args[2], + hlsl_get_vector_type(ctx, HLSL_TYPE_INT, offset_dim), loc); } sampler_type = params->args[0]->data_type; @@ -6039,17 +5826,12 @@ static bool add_gather_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc 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; - + load_params.coords = add_implicit_conversion(ctx, block, params->args[1], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc); 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); + hlsl_block_add_resource_load(ctx, block, &load_params, loc); return true; } @@ -6060,7 +5842,6 @@ static bool add_gather_cmp_method_call(struct hlsl_ctx *ctx, struct hlsl_block * 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); @@ -6127,10 +5908,7 @@ static bool add_gather_cmp_method_call(struct hlsl_ctx *ctx, struct hlsl_block * 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); + hlsl_block_add_resource_load(ctx, block, &load_params, loc); return true; } @@ -6219,12 +5997,8 @@ static bool add_getdimensions_method_call(struct hlsl_ctx *ctx, struct hlsl_bloc /* Input parameter. */ if (iter->args[j] == ARG_MIP_LEVEL) { - if (!(args[ARG_MIP_LEVEL] = add_implicit_conversion(ctx, block, args[ARG_MIP_LEVEL], - hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc))) - { - return false; - } - + args[ARG_MIP_LEVEL] = add_implicit_conversion(ctx, block, args[ARG_MIP_LEVEL], + hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc); continue; } @@ -6263,10 +6037,7 @@ static bool add_getdimensions_method_call(struct hlsl_ctx *ctx, struct hlsl_bloc load_params.resource = object; load_params.lod = args[ARG_MIP_LEVEL]; load_params.format = hlsl_get_vector_type(ctx, uint_resinfo ? HLSL_TYPE_UINT : HLSL_TYPE_FLOAT, 4); - - if (!(res_info = hlsl_new_resource_load(ctx, &load_params, loc))) - return false; - hlsl_block_add_instr(block, res_info); + res_info = hlsl_block_add_resource_load(ctx, block, &load_params, loc); if (!add_assignment_from_component(ctx, block, args[ARG_WIDTH], res_info, 0, loc)) return false; @@ -6289,9 +6060,7 @@ static bool add_getdimensions_method_call(struct hlsl_ctx *ctx, struct hlsl_bloc load_params.type = HLSL_RESOURCE_SAMPLE_INFO; load_params.resource = object; load_params.format = args[ARG_SAMPLE_COUNT]->data_type; - if (!(sample_info = hlsl_new_resource_load(ctx, &load_params, loc))) - return false; - hlsl_block_add_instr(block, sample_info); + sample_info = hlsl_block_add_resource_load(ctx, block, &load_params, loc); if (!add_assignment(ctx, block, args[ARG_SAMPLE_COUNT], ASSIGN_OP_ASSIGN, sample_info, false)) return false; @@ -6308,7 +6077,6 @@ static bool add_sample_lod_method_call(struct hlsl_ctx *ctx, struct hlsl_block * 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); @@ -6338,20 +6106,14 @@ static bool add_sample_lod_method_call(struct hlsl_ctx *ctx, struct hlsl_block * 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))) - load_params.coords = params->args[1]; - - if (!(load_params.lod = add_implicit_conversion(ctx, block, params->args[2], - hlsl_get_scalar_type(ctx, HLSL_TYPE_FLOAT), loc))) - load_params.lod = params->args[2]; + load_params.coords = add_implicit_conversion(ctx, block, params->args[1], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc); + load_params.lod = add_implicit_conversion(ctx, block, params->args[2], + hlsl_get_scalar_type(ctx, HLSL_TYPE_FLOAT), loc); 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; - } + load_params.texel_offset = add_implicit_conversion(ctx, block, params->args[3], + hlsl_get_vector_type(ctx, HLSL_TYPE_INT, offset_dim), loc); if (params->args_count > 3 + !!offset_dim) hlsl_fixme(ctx, loc, "Tiled resource status argument."); @@ -6359,10 +6121,7 @@ static bool add_sample_lod_method_call(struct hlsl_ctx *ctx, struct hlsl_block * load_params.format = object_type->e.resource.format; 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); + hlsl_block_add_resource_load(ctx, block, &load_params, loc); return true; } @@ -6373,7 +6132,6 @@ static bool add_sample_grad_method_call(struct hlsl_ctx *ctx, struct hlsl_block 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); @@ -6400,24 +6158,16 @@ static bool add_sample_grad_method_call(struct hlsl_ctx *ctx, struct hlsl_block 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))) - load_params.coords = params->args[1]; - - if (!(load_params.ddx = add_implicit_conversion(ctx, block, params->args[2], - hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) - load_params.ddx = params->args[2]; - - if (!(load_params.ddy = add_implicit_conversion(ctx, block, params->args[3], - hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) - load_params.ddy = params->args[3]; + load_params.coords = add_implicit_conversion(ctx, block, params->args[1], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc); + load_params.ddx = add_implicit_conversion(ctx, block, params->args[2], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc); + load_params.ddy = add_implicit_conversion(ctx, block, params->args[3], + hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc); if (offset_dim && params->args_count > 4) - { - if (!(load_params.texel_offset = add_implicit_conversion(ctx, block, params->args[4], - hlsl_get_vector_type(ctx, HLSL_TYPE_INT, offset_dim), loc))) - return false; - } + load_params.texel_offset = add_implicit_conversion(ctx, block, params->args[4], + hlsl_get_vector_type(ctx, HLSL_TYPE_INT, offset_dim), loc); if (params->args_count > 4 + !!offset_dim) hlsl_fixme(ctx, loc, "Tiled resource status argument."); @@ -6425,10 +6175,7 @@ static bool add_sample_grad_method_call(struct hlsl_ctx *ctx, struct hlsl_block load_params.format = object_type->e.resource.format; 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); + hlsl_block_add_resource_load(ctx, block, &load_params, loc); return true; } @@ -6455,13 +6202,10 @@ static bool add_store_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block else value_dim = 4; - if (!(offset = add_implicit_conversion(ctx, block, params->args[0], - hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc))) - return false; - - if (!(rhs = add_implicit_conversion(ctx, block, params->args[1], - hlsl_get_vector_type(ctx, HLSL_TYPE_UINT, value_dim), loc))) - return false; + offset = add_implicit_conversion(ctx, block, params->args[0], + hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc); + rhs = add_implicit_conversion(ctx, block, params->args[1], + hlsl_get_vector_type(ctx, HLSL_TYPE_UINT, value_dim), loc); if (!hlsl_init_deref_from_index_chain(ctx, &resource_deref, object)) return false; @@ -6667,15 +6411,8 @@ static bool add_switch(struct hlsl_ctx *ctx, struct hlsl_block *block, return true; } - if (!(selector = add_implicit_conversion(ctx, block, selector, - hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), &selector->loc))) - { - destroy_switch_cases(cases); - destroy_block(block); - cleanup_parse_attribute_list(attributes); - return false; - } - + selector = add_implicit_conversion(ctx, block, selector, + hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), &selector->loc); s = hlsl_new_switch(ctx, selector, cases, loc); destroy_switch_cases(cases); @@ -6816,6 +6553,8 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, %token KW_INLINE %token KW_INOUT %token KW_INPUTPATCH +%token KW_LINE +%token KW_LINEADJ %token KW_LINEAR %token KW_LINESTREAM %token KW_MATRIX @@ -6828,6 +6567,7 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, %token KW_PACKOFFSET %token KW_PASS %token KW_PIXELSHADER +%token KW_POINT %token KW_POINTSTREAM %token KW_RASTERIZERORDEREDBUFFER %token KW_RASTERIZERORDEREDSTRUCTUREDBUFFER @@ -6878,6 +6618,8 @@ static void validate_uav_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, %token KW_TEXTURE3D %token KW_TEXTURECUBE %token KW_TEXTURECUBEARRAY +%token KW_TRIANGLE +%token KW_TRIANGLEADJ %token KW_TRIANGLESTREAM %token KW_TRUE %token KW_TYPEDEF @@ -7885,7 +7627,8 @@ parameter: parameter_decl: var_modifiers type_no_void any_identifier arrays colon_attributes { - uint32_t modifiers = $1; + uint32_t prim_modifiers = $1 & HLSL_PRIMITIVE_MODIFIERS_MASK; + uint32_t modifiers = $1 & ~HLSL_PRIMITIVE_MODIFIERS_MASK; struct hlsl_type *type; unsigned int i; @@ -7910,6 +7653,22 @@ parameter_decl: } vkd3d_free($4.sizes); + if (prim_modifiers && (prim_modifiers & (prim_modifiers - 1))) + { + hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Primitive type modifiers are mutually exclusive."); + prim_modifiers = 0; + } + + if (prim_modifiers) + { + if (type->class != HLSL_CLASS_ARRAY) + hlsl_error(ctx, &@1, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Primitive type modifiers can only be applied to arrays."); + else + type->modifiers |= prim_modifiers; + } + $$.type = type; if (hlsl_version_ge(ctx, 5, 1) && type->class == HLSL_CLASS_ARRAY && hlsl_type_is_resource(type)) @@ -8629,7 +8388,7 @@ variable_def_typed: if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) YYABORT; - check_invalid_in_out_modifiers(ctx, modifiers, &@1); + check_invalid_non_parameter_modifiers(ctx, modifiers, &@1); $$ = $3; $$->basic_type = type; @@ -8644,7 +8403,7 @@ variable_def_typed: if (!(type = apply_type_modifiers(ctx, $2, &modifiers, true, &@1))) YYABORT; - check_invalid_in_out_modifiers(ctx, modifiers, &@1); + check_invalid_non_parameter_modifiers(ctx, modifiers, &@1); $$ = $3; $$->basic_type = type; @@ -8785,6 +8544,26 @@ var_modifiers: { $$ = add_modifiers(ctx, $2, HLSL_MODIFIER_SNORM, &@1); } + | KW_LINE var_modifiers + { + $$ = add_modifiers(ctx, $2, HLSL_PRIMITIVE_LINE, &@1); + } + | KW_LINEADJ var_modifiers + { + $$ = add_modifiers(ctx, $2, HLSL_PRIMITIVE_LINEADJ, &@1); + } + | KW_POINT var_modifiers + { + $$ = add_modifiers(ctx, $2, HLSL_PRIMITIVE_POINT, &@1); + } + | KW_TRIANGLE var_modifiers + { + $$ = add_modifiers(ctx, $2, HLSL_PRIMITIVE_TRIANGLE, &@1); + } + | KW_TRIANGLEADJ var_modifiers + { + $$ = add_modifiers(ctx, $2, HLSL_PRIMITIVE_TRIANGLEADJ, &@1); + } | var_identifier var_modifiers { $$ = $2; @@ -8981,14 +8760,7 @@ selection_statement: check_condition_type(ctx, condition); - if (!(condition = add_cast(ctx, $4, condition, hlsl_get_scalar_type(ctx, HLSL_TYPE_BOOL), &@4))) - { - destroy_block($6.then_block); - destroy_block($6.else_block); - cleanup_parse_attribute_list(&$1); - YYABORT; - } - + condition = add_cast(ctx, $4, condition, hlsl_get_scalar_type(ctx, HLSL_TYPE_BOOL), &@4); hlsl_block_add_if(ctx, $4, condition, $6.then_block, $6.else_block, &@2); destroy_block($6.then_block); @@ -9449,12 +9221,7 @@ unary_expr: hlsl_error(ctx, &@2, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, "Modifiers are not allowed on casts."); - if (!add_explicit_conversion(ctx, $6, $3, &$4, &@3)) - { - destroy_block($6); - vkd3d_free($4.sizes); - YYABORT; - } + add_explicit_conversion(ctx, $6, $3, &$4, &@3); vkd3d_free($4.sizes); $$ = $6; } diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c index edcd9ce62a7..b5652475b43 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_codegen.c @@ -1214,7 +1214,6 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, unsigned int dim_count = hlsl_sampler_dim_count(val->data_type->sampler_dim); struct hlsl_ir_node *coords = index->idx.node; struct hlsl_resource_load_params params = {0}; - struct hlsl_ir_node *resource_load; VKD3D_ASSERT(coords->data_type->class == HLSL_CLASS_VECTOR); VKD3D_ASSERT(coords->data_type->e.numeric.type == HLSL_TYPE_UINT); @@ -1227,10 +1226,7 @@ static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, params.resource = val; params.coords = coords; params.format = val->data_type->e.resource.format; - - if (!(resource_load = hlsl_new_resource_load(ctx, ¶ms, &instr->loc))) - return false; - hlsl_block_add_instr(block, resource_load); + hlsl_block_add_resource_load(ctx, block, ¶ms, &instr->loc); return true; } @@ -1295,7 +1291,7 @@ static bool lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, s if (src_type->class <= HLSL_CLASS_VECTOR && dst_type->class <= HLSL_CLASS_VECTOR && src_type->e.numeric.dimx == 1) { - struct hlsl_ir_node *new_cast, *swizzle; + struct hlsl_ir_node *new_cast; dst_scalar_type = hlsl_get_scalar_type(ctx, dst_type->e.numeric.type); /* We need to preserve the cast since it might be doing more than just @@ -1303,12 +1299,8 @@ static bool lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, s new_cast = hlsl_block_add_cast(ctx, block, cast->operands[0].node, dst_scalar_type, &cast->node.loc); if (dst_type->e.numeric.dimx != 1) - { - if (!(swizzle = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, X, X, X), - dst_type->e.numeric.dimx, new_cast, &cast->node.loc))) - return false; - hlsl_block_add_instr(block, swizzle); - } + hlsl_block_add_swizzle(ctx, block, HLSL_SWIZZLE(X, X, X, X), + dst_type->e.numeric.dimx, new_cast, &cast->node.loc); return true; } @@ -1400,6 +1392,17 @@ static unsigned int index_instructions(struct hlsl_block *block, unsigned int in * * we can copy-prop the load (@7) into a constant vector {123, 456}, but we * cannot easily vectorize the stores @3 and @6. + * + * Moreover, we implement a transformation that propagates loads with a single + * non-constant index in its deref path. Consider a load of the form + * var[[a0][a1]...[i]...[an]], where ak are integral constants, and i is an + * arbitrary non-constant node. If, for all j, the following holds: + * + * var[[a0][a1]...[j]...[an]] = x[[c0*j + d0][c1*j + d1]...[cm*j + dm]], + * + * where ck, dk are constants, then we can replace the load with + * x[[c0*i + d0]...[cm*i + dm]]. This pass is implemented by + * copy_propagation_replace_with_deref(). */ struct copy_propagation_value @@ -1624,16 +1627,25 @@ static void copy_propagation_invalidate_variable_from_deref_recurse(struct hlsl_ if (path_node->type == HLSL_IR_CONSTANT) { + uint32_t index = hlsl_ir_constant(path_node)->value.u[0].u; + + /* Don't bother invalidating anything if the index is constant but + * out-of-range. + * Such indices are illegal in HLSL, but only if the code is not + * dead, and we can't always know if code is dead without copy-prop + * itself. */ + if (index >= hlsl_type_element_count(type)) + return; + copy_propagation_invalidate_variable_from_deref_recurse(ctx, var_def, deref, subtype, - depth + 1, hlsl_ir_constant(path_node)->value.u[0].u * subtype_comp_count, - writemask, time); + depth + 1, comp_start + index * subtype_comp_count, writemask, time); } else { for (i = 0; i < hlsl_type_element_count(type); ++i) { copy_propagation_invalidate_variable_from_deref_recurse(ctx, var_def, deref, subtype, - depth + 1, i * subtype_comp_count, writemask, time); + depth + 1, comp_start + i * subtype_comp_count, writemask, time); } } } @@ -1757,6 +1769,325 @@ static bool copy_propagation_replace_with_constant_vector(struct hlsl_ctx *ctx, return true; } +static bool component_index_from_deref_path_node(struct hlsl_ir_node *path_node, + struct hlsl_type *type, unsigned int *index) +{ + unsigned int idx, i; + + if (path_node->type != HLSL_IR_CONSTANT) + return false; + + idx = hlsl_ir_constant(path_node)->value.u[0].u; + *index = 0; + + switch (type->class) + { + case HLSL_CLASS_VECTOR: + if (idx >= type->e.numeric.dimx) + return false; + *index = idx; + break; + + case HLSL_CLASS_MATRIX: + if (idx >= hlsl_type_major_size(type)) + return false; + if (hlsl_type_is_row_major(type)) + *index = idx * type->e.numeric.dimx; + else + *index = idx * type->e.numeric.dimy; + break; + + case HLSL_CLASS_ARRAY: + if (idx >= type->e.array.elements_count) + return false; + *index = idx * hlsl_type_component_count(type->e.array.type); + break; + + case HLSL_CLASS_STRUCT: + for (i = 0; i < idx; ++i) + *index += hlsl_type_component_count(type->e.record.fields[i].type); + break; + + default: + vkd3d_unreachable(); + } + + return true; +} + +static bool nonconst_index_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, + unsigned int *idx, unsigned int *base, unsigned int *scale, unsigned int *count) +{ + struct hlsl_type *type = deref->var->data_type; + bool found = false; + unsigned int i; + + *base = 0; + + for (i = 0; i < deref->path_len; ++i) + { + struct hlsl_ir_node *path_node = deref->path[i].node; + struct hlsl_type *next_type; + + VKD3D_ASSERT(path_node); + + /* We should always have generated a cast to UINT. */ + VKD3D_ASSERT(hlsl_is_vec1(path_node->data_type) && path_node->data_type->e.numeric.type == HLSL_TYPE_UINT); + + next_type = hlsl_get_element_type_from_path_index(ctx, type, path_node); + + if (path_node->type != HLSL_IR_CONSTANT) + { + if (found) + return false; + found = true; + *idx = i; + *scale = hlsl_type_component_count(next_type); + *count = hlsl_type_element_count(type); + } + else + { + unsigned int index; + + if (!component_index_from_deref_path_node(path_node, type, &index)) + return false; + *base += index; + } + + type = next_type; + } + + return found; +} + +static struct hlsl_ir_node *new_affine_path_index(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc, + struct hlsl_block *block, struct hlsl_ir_node *index, int c, int d) +{ + struct hlsl_ir_node *c_node, *d_node, *ic, *idx; + bool use_uint = c >= 0 && d >= 0; + + if (!c) + { + VKD3D_ASSERT(d >= 0); + + return hlsl_block_add_uint_constant(ctx, block, d, loc); + } + + if (use_uint) + { + c_node = hlsl_block_add_uint_constant(ctx, block, c, loc); + d_node = hlsl_block_add_uint_constant(ctx, block, d, loc); + } + else + { + c_node = hlsl_block_add_int_constant(ctx, block, c, loc); + d_node = hlsl_block_add_int_constant(ctx, block, d, loc); + index = hlsl_block_add_cast(ctx, block, index, hlsl_get_scalar_type(ctx, HLSL_TYPE_INT), loc); + } + + ic = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_MUL, index, c_node); + idx = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, ic, d_node); + if (!use_uint) + idx = hlsl_block_add_cast(ctx, block, idx, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), loc); + + return idx; +} + +static bool copy_propagation_replace_with_deref(struct hlsl_ctx *ctx, + const struct copy_propagation_state *state, const struct hlsl_ir_load *load, + uint32_t swizzle, struct hlsl_ir_node *instr) +{ + const unsigned int instr_component_count = hlsl_type_component_count(instr->data_type); + unsigned int nonconst_i = 0, base, scale, count; + struct hlsl_ir_node *index, *new_instr = NULL; + const struct hlsl_deref *deref = &load->src; + const struct hlsl_ir_var *var = deref->var; + unsigned int time = load->node.index; + struct hlsl_deref tmp_deref = {0}; + struct hlsl_ir_load *new_load; + struct hlsl_ir_var *x = NULL; + int *c = NULL, *d = NULL; + uint32_t ret_swizzle = 0; + struct hlsl_block block; + unsigned int path_len; + bool success = false; + int i, j, k; + + if (!nonconst_index_from_deref(ctx, deref, &nonconst_i, &base, &scale, &count)) + return false; + + if (hlsl_version_lt(ctx, 4, 0)) + { + TRACE("Non-constant index propagation is not yet supported for SM1.\n"); + return false; + } + + VKD3D_ASSERT(count); + + hlsl_block_init(&block); + + index = deref->path[nonconst_i].node; + + /* Iterate over the nonconst index, and check if their values all have the form + * x[[c0*i + d0][c1*i + d1]...[cm*i + dm]], and determine the constants c, d. */ + for (i = 0; i < count; ++i) + { + unsigned int start = base + scale * i; + struct copy_propagation_value *value; + struct hlsl_ir_load *idx; + uint32_t cur_swizzle = 0; + + if (!(value = copy_propagation_get_value(state, var, + start + hlsl_swizzle_get_component(swizzle, 0), time))) + goto done; + + if (value->node->type != HLSL_IR_LOAD) + goto done; + idx = hlsl_ir_load(value->node); + + if (!x) + x = idx->src.var; + else if (x != idx->src.var) + goto done; + + if (i == 0) + { + path_len = idx->src.path_len; + + if (path_len) + { + if (!(c = hlsl_calloc(ctx, path_len, sizeof(c[0]))) + || !(d = hlsl_alloc(ctx, path_len * sizeof(d[0])))) + goto done; + } + + for (k = 0; k < path_len; ++k) + { + if (idx->src.path[k].node->type != HLSL_IR_CONSTANT) + goto done; + d[k] = hlsl_ir_constant(idx->src.path[k].node)->value.u[0].u; + } + + } + else if (i == 1) + { + struct hlsl_type *type = idx->src.var->data_type; + + if (idx->src.path_len != path_len) + goto done; + + /* Calculate constants c and d based on the first two path indices. */ + for (k = 0; k < path_len; ++k) + { + int ix; + + if (idx->src.path[k].node->type != HLSL_IR_CONSTANT) + goto done; + ix = hlsl_ir_constant(idx->src.path[k].node)->value.u[0].u; + c[k] = ix - d[k]; + d[k] = ix - c[k] * i; + + if (c[k] && type->class == HLSL_CLASS_STRUCT) + goto done; + + type = hlsl_get_element_type_from_path_index(ctx, type, idx->src.path[k].node); + } + } + else + { + if (idx->src.path_len != path_len) + goto done; + + /* Check that this load has the form x[[c0*i +d0][c1*i + d1]...[cm*i + dm]]. */ + for (k = 0; k < path_len; ++k) + { + if (idx->src.path[k].node->type != HLSL_IR_CONSTANT) + goto done; + if (hlsl_ir_constant(idx->src.path[k].node)->value.u[0].u != c[k] * i + d[k]) + goto done; + } + } + + hlsl_swizzle_set_component(&cur_swizzle, 0, value->component); + + for (j = 1; j < instr_component_count; ++j) + { + struct copy_propagation_value *val; + + if (!(val = copy_propagation_get_value(state, var, + start + hlsl_swizzle_get_component(swizzle, j), time))) + goto done; + if (val->node != &idx->node) + goto done; + + hlsl_swizzle_set_component(&cur_swizzle, j, val->component); + } + + if (i == 0) + ret_swizzle = cur_swizzle; + else if (ret_swizzle != cur_swizzle) + goto done; + } + + if (!hlsl_init_deref(ctx, &tmp_deref, x, path_len)) + goto done; + + for (k = 0; k < path_len; ++k) + { + hlsl_src_from_node(&tmp_deref.path[k], + new_affine_path_index(ctx, &load->node.loc, &block, index, c[k], d[k])); + } + + if (!(new_load = hlsl_new_load_index(ctx, &tmp_deref, NULL, &load->node.loc))) + goto done; + new_instr = &new_load->node; + hlsl_block_add_instr(&block, new_instr); + + if (new_instr->data_type->class == HLSL_CLASS_SCALAR || new_instr->data_type->class == HLSL_CLASS_VECTOR) + new_instr = hlsl_block_add_swizzle(ctx, &block, ret_swizzle, instr_component_count, new_instr, &instr->loc); + + if (TRACE_ON()) + { + struct vkd3d_string_buffer buffer; + + vkd3d_string_buffer_init(&buffer); + + vkd3d_string_buffer_printf(&buffer, "Load from %s[", var->name); + for (j = 0; j < deref->path_len; ++j) + { + if (j == nonconst_i) + vkd3d_string_buffer_printf(&buffer, "[i]"); + else + vkd3d_string_buffer_printf(&buffer, "[%u]", hlsl_ir_constant(deref->path[j].node)->value.u[0].u); + } + vkd3d_string_buffer_printf(&buffer, "]%s propagated as %s[", + debug_hlsl_swizzle(swizzle, instr_component_count), tmp_deref.var->name); + for (k = 0; k < path_len; ++k) + { + if (c[k]) + vkd3d_string_buffer_printf(&buffer, "[i*%d + %d]", c[k], d[k]); + else + vkd3d_string_buffer_printf(&buffer, "[%d]", d[k]); + } + vkd3d_string_buffer_printf(&buffer, "]%s (i = %p).\n", + debug_hlsl_swizzle(ret_swizzle, instr_component_count), index); + + vkd3d_string_buffer_trace(&buffer); + vkd3d_string_buffer_cleanup(&buffer); + } + + list_move_before(&instr->entry, &block.instrs); + hlsl_replace_node(instr, new_instr); + success = true; + +done: + hlsl_cleanup_deref(&tmp_deref); + hlsl_block_cleanup(&block); + vkd3d_free(c); + vkd3d_free(d); + return success; +} + static bool copy_propagation_transform_load(struct hlsl_ctx *ctx, struct hlsl_ir_load *load, struct copy_propagation_state *state) { @@ -1811,6 +2142,9 @@ static bool copy_propagation_transform_load(struct hlsl_ctx *ctx, if (copy_propagation_replace_with_single_instr(ctx, state, load, HLSL_SWIZZLE(X, Y, Z, W), &load->node)) return true; + if (copy_propagation_replace_with_deref(ctx, state, load, HLSL_SWIZZLE(X, Y, Z, W), &load->node)) + return true; + return false; } @@ -1829,6 +2163,9 @@ static bool copy_propagation_transform_swizzle(struct hlsl_ctx *ctx, if (copy_propagation_replace_with_single_instr(ctx, state, load, swizzle->u.vector, &swizzle->node)) return true; + if (copy_propagation_replace_with_deref(ctx, state, load, swizzle->u.vector, &swizzle->node)) + return true; + return false; } @@ -2167,8 +2504,7 @@ static enum validation_result validate_component_index_range_from_deref(struct h return DEREF_VALIDATION_NOT_CONSTANT; /* We should always have generated a cast to UINT. */ - VKD3D_ASSERT(path_node->data_type->class == HLSL_CLASS_SCALAR - && path_node->data_type->e.numeric.type == HLSL_TYPE_UINT); + VKD3D_ASSERT(hlsl_is_vec1(path_node->data_type) && path_node->data_type->e.numeric.type == HLSL_TYPE_UINT); idx = hlsl_ir_constant(path_node)->value.u[0].u; @@ -2325,11 +2661,6 @@ static bool validate_dereferences(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins return false; } -static bool is_vec1(const struct hlsl_type *type) -{ - return (type->class == HLSL_CLASS_SCALAR) || (type->class == HLSL_CLASS_VECTOR && type->e.numeric.dimx == 1); -} - static bool fold_redundant_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) { if (instr->type == HLSL_IR_EXPR) @@ -2344,7 +2675,8 @@ static bool fold_redundant_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst src_type = expr->operands[0].node->data_type; if (hlsl_types_are_equal(src_type, dst_type) - || (src_type->e.numeric.type == dst_type->e.numeric.type && is_vec1(src_type) && is_vec1(dst_type))) + || (src_type->e.numeric.type == dst_type->e.numeric.type + && hlsl_is_vec1(src_type) && hlsl_is_vec1(dst_type))) { hlsl_replace_node(&expr->node, expr->operands[0].node); return true; @@ -2507,18 +2839,14 @@ static bool lower_narrowing_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *ins if (src_type->class <= HLSL_CLASS_VECTOR && dst_type->class <= HLSL_CLASS_VECTOR && dst_type->e.numeric.dimx < src_type->e.numeric.dimx) { - struct hlsl_ir_node *new_cast, *swizzle; + struct hlsl_ir_node *new_cast; dst_vector_type = hlsl_get_vector_type(ctx, dst_type->e.numeric.type, src_type->e.numeric.dimx); /* We need to preserve the cast since it might be doing more than just * narrowing the vector. */ new_cast = hlsl_block_add_cast(ctx, block, cast->operands[0].node, dst_vector_type, &cast->node.loc); - - if (!(swizzle = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, Y, Z, W), - dst_type->e.numeric.dimx, new_cast, &cast->node.loc))) - return false; - hlsl_block_add_instr(block, swizzle); - + hlsl_block_add_swizzle(ctx, block, HLSL_SWIZZLE(X, Y, Z, W), + dst_type->e.numeric.dimx, new_cast, &cast->node.loc); return true; } @@ -2732,9 +3060,7 @@ static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir return false; hlsl_block_add_instr(block, &vector_load->node); - if (!(swizzle = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, X, X, X), width, idx, &instr->loc))) - return false; - hlsl_block_add_instr(block, swizzle); + swizzle = hlsl_block_add_swizzle(ctx, block, HLSL_SWIZZLE(X, X, X, X), width, idx, &instr->loc); value.u[0].u = 0; value.u[1].u = 1; @@ -2867,11 +3193,8 @@ static bool lower_nonconstant_array_loads(struct hlsl_ctx *ctx, struct hlsl_ir_n operands[0] = cut_index; operands[1] = const_i; equals = hlsl_block_add_expr(ctx, block, HLSL_OP2_EQUAL, operands, btype, &cut_index->loc); - - if (!(equals = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, X, X, X), - var->data_type->e.numeric.dimx, equals, &cut_index->loc))) - return false; - hlsl_block_add_instr(block, equals); + equals = hlsl_block_add_swizzle(ctx, block, HLSL_SWIZZLE(X, X, X, X), + var->data_type->e.numeric.dimx, equals, &cut_index->loc); var_load = hlsl_block_add_simple_load(ctx, block, var, &cut_index->loc); @@ -3161,9 +3484,37 @@ static bool sort_synthetic_separated_samplers_first(struct hlsl_ctx *ctx) return false; } -/* Turn CAST to int or uint as follows: +/* Turn CAST to int or uint into TRUNC + REINTERPRET */ +static bool lower_casts_to_int(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) +{ + struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = { 0 }; + struct hlsl_ir_node *arg, *trunc; + struct hlsl_ir_expr *expr; + + if (instr->type != HLSL_IR_EXPR) + return false; + expr = hlsl_ir_expr(instr); + if (expr->op != HLSL_OP1_CAST) + return false; + + arg = expr->operands[0].node; + if (!hlsl_type_is_integer(instr->data_type) || instr->data_type->e.numeric.type == HLSL_TYPE_BOOL) + return false; + if (!hlsl_type_is_floating_point(arg->data_type)) + return false; + + trunc = hlsl_block_add_unary_expr(ctx, block, HLSL_OP1_TRUNC, arg, &instr->loc); + + memset(operands, 0, sizeof(operands)); + operands[0] = trunc; + hlsl_block_add_expr(ctx, block, HLSL_OP1_REINTERPRET, operands, instr->data_type, &instr->loc); + + return true; +} + +/* Turn TRUNC into: * - * CAST(x) = x - FRACT(x) + extra + * TRUNC(x) = x - FRACT(x) + extra * * where * @@ -3171,27 +3522,19 @@ static bool sort_synthetic_separated_samplers_first(struct hlsl_ctx *ctx) * * where the comparisons in the extra term are performed using CMP or SLT * depending on whether this is a pixel or vertex shader, respectively. - * - * A REINTERPET (which is written as a mere MOV) is also applied to the final - * result for type consistency. */ -static bool lower_casts_to_int(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) +static bool lower_trunc(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block) { - struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = { 0 }; struct hlsl_ir_node *arg, *res; struct hlsl_ir_expr *expr; if (instr->type != HLSL_IR_EXPR) return false; expr = hlsl_ir_expr(instr); - if (expr->op != HLSL_OP1_CAST) + if (expr->op != HLSL_OP1_TRUNC) return false; arg = expr->operands[0].node; - if (!hlsl_type_is_integer(instr->data_type) || instr->data_type->e.numeric.type == HLSL_TYPE_BOOL) - return false; - if (arg->data_type->e.numeric.type != HLSL_TYPE_FLOAT && arg->data_type->e.numeric.type != HLSL_TYPE_HALF) - return false; if (ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL) { @@ -3241,9 +3584,6 @@ static bool lower_casts_to_int(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, hlsl_block_add_instr(block, res); } - memset(operands, 0, sizeof(operands)); - operands[0] = res; - hlsl_block_add_expr(ctx, block, HLSL_OP1_REINTERPRET, operands, instr->data_type, &instr->loc); return true; } @@ -3327,16 +3667,10 @@ static bool lower_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct h { mul = hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_MUL, expr->operands[0].node, expr->operands[1].node); - if (!(add_x = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, X, X, X), - instr->data_type->e.numeric.dimx, mul, &expr->node.loc))) - return false; - hlsl_block_add_instr(block, add_x); - - if (!(add_y = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(Y, Y, Y, Y), - instr->data_type->e.numeric.dimx, mul, &expr->node.loc))) - return false; - hlsl_block_add_instr(block, add_y); - + add_x = hlsl_block_add_swizzle(ctx, block, HLSL_SWIZZLE(X, X, X, X), + instr->data_type->e.numeric.dimx, mul, &expr->node.loc); + add_y = hlsl_block_add_swizzle(ctx, block, HLSL_SWIZZLE(Y, Y, Y, Y), + instr->data_type->e.numeric.dimx, mul, &expr->node.loc); hlsl_block_add_binary_expr(ctx, block, HLSL_OP2_ADD, add_x, add_y); } @@ -3499,9 +3833,7 @@ static bool lower_trig(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct { uint32_t s = hlsl_swizzle_from_writemask(1 << i); - if (!(comps[i] = hlsl_new_swizzle(ctx, s, 1, reduced, &instr->loc))) - return false; - hlsl_block_add_instr(block, comps[i]); + comps[i] = hlsl_block_add_swizzle(ctx, block, s, 1, reduced, &instr->loc); } if (!(var = hlsl_new_synthetic_var(ctx, "sincos", type, &instr->loc))) @@ -4021,9 +4353,7 @@ static bool lower_int_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, stru { uint32_t s = hlsl_swizzle_from_writemask(1 << i); - if (!(comps[i] = hlsl_new_swizzle(ctx, s, 1, mult, &instr->loc))) - return false; - hlsl_block_add_instr(block, comps[i]); + comps[i] = hlsl_block_add_swizzle(ctx, block, s, 1, mult, &instr->loc); } res = comps[0]; @@ -4812,8 +5142,7 @@ static void register_deref_usage(struct hlsl_ctx *ctx, struct hlsl_deref *deref) struct hlsl_type *type; unsigned int index; - if (!hlsl_regset_index_from_deref(ctx, deref, regset, &index)) - return; + hlsl_regset_index_from_deref(ctx, deref, regset, &index); if (regset <= HLSL_REGSET_LAST_OBJECT) { @@ -4824,7 +5153,6 @@ static void register_deref_usage(struct hlsl_ctx *ctx, struct hlsl_deref *deref) { type = hlsl_deref_get_type(ctx, deref); - hlsl_regset_index_from_deref(ctx, deref, regset, &index); required_bind_count = align(index + type->reg_size[regset], 4) / 4; var->bind_count[regset] = max(var->bind_count[regset], required_bind_count); } @@ -5913,7 +6241,7 @@ bool hlsl_component_index_range_from_deref(struct hlsl_ctx *ctx, const struct hl unsigned int *start, unsigned int *count) { struct hlsl_type *type = deref->var->data_type; - unsigned int i, k; + unsigned int i; *start = 0; *count = 0; @@ -5921,49 +6249,18 @@ bool hlsl_component_index_range_from_deref(struct hlsl_ctx *ctx, const struct hl for (i = 0; i < deref->path_len; ++i) { struct hlsl_ir_node *path_node = deref->path[i].node; - unsigned int idx = 0; + unsigned int index; VKD3D_ASSERT(path_node); if (path_node->type != HLSL_IR_CONSTANT) return false; /* We should always have generated a cast to UINT. */ - VKD3D_ASSERT(path_node->data_type->class == HLSL_CLASS_SCALAR - && path_node->data_type->e.numeric.type == HLSL_TYPE_UINT); - - idx = hlsl_ir_constant(path_node)->value.u[0].u; - - switch (type->class) - { - case HLSL_CLASS_VECTOR: - if (idx >= type->e.numeric.dimx) - return false; - *start += idx; - break; - - case HLSL_CLASS_MATRIX: - if (idx >= hlsl_type_major_size(type)) - return false; - if (hlsl_type_is_row_major(type)) - *start += idx * type->e.numeric.dimx; - else - *start += idx * type->e.numeric.dimy; - break; - - case HLSL_CLASS_ARRAY: - if (idx >= type->e.array.elements_count) - return false; - *start += idx * hlsl_type_component_count(type->e.array.type); - break; + VKD3D_ASSERT(hlsl_is_vec1(path_node->data_type) && path_node->data_type->e.numeric.type == HLSL_TYPE_UINT); - case HLSL_CLASS_STRUCT: - for (k = 0; k < idx; ++k) - *start += hlsl_type_component_count(type->e.record.fields[k].type); - break; - - default: - vkd3d_unreachable(); - } + if (!component_index_from_deref_path_node(path_node, type, &index)) + return false; + *start += index; type = hlsl_get_element_type_from_path_index(ctx, type, path_node); } @@ -5992,8 +6289,7 @@ bool hlsl_regset_index_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref if (path_node->type == HLSL_IR_CONSTANT) { /* We should always have generated a cast to UINT. */ - VKD3D_ASSERT(path_node->data_type->class == HLSL_CLASS_SCALAR - && path_node->data_type->e.numeric.type == HLSL_TYPE_UINT); + VKD3D_ASSERT(hlsl_is_vec1(path_node->data_type) && path_node->data_type->e.numeric.type == HLSL_TYPE_UINT); idx = hlsl_ir_constant(path_node)->value.u[0].u; @@ -6061,8 +6357,7 @@ bool hlsl_offset_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref if (offset_node) { /* We should always have generated a cast to UINT. */ - VKD3D_ASSERT(offset_node->data_type->class == HLSL_CLASS_SCALAR - && offset_node->data_type->e.numeric.type == HLSL_TYPE_UINT); + VKD3D_ASSERT(hlsl_is_vec1(offset_node->data_type) && offset_node->data_type->e.numeric.type == HLSL_TYPE_UINT); VKD3D_ASSERT(offset_node->type != HLSL_IR_CONSTANT); return false; } @@ -6097,11 +6392,14 @@ struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_dere { const struct hlsl_ir_var *var = deref->var; struct hlsl_reg ret = var->regs[HLSL_REGSET_NUMERIC]; - unsigned int offset = hlsl_offset_from_deref_safe(ctx, deref); + unsigned int offset = 0; VKD3D_ASSERT(deref->data_type); VKD3D_ASSERT(hlsl_is_numeric_type(deref->data_type)); + if (!hlsl_type_is_patch_array(deref->var->data_type)) + offset = hlsl_offset_from_deref_safe(ctx, deref); + ret.index += offset / 4; ret.id += offset / 4; @@ -6112,6 +6410,36 @@ struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_dere return ret; } +static bool get_integral_argument_value(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr, + unsigned int i, enum hlsl_base_type *base_type, int *value) +{ + const struct hlsl_ir_node *instr = attr->args[i].node; + const struct hlsl_type *type = instr->data_type; + + if (type->class != HLSL_CLASS_SCALAR + || (type->e.numeric.type != HLSL_TYPE_INT && type->e.numeric.type != HLSL_TYPE_UINT)) + { + struct vkd3d_string_buffer *string; + + if ((string = hlsl_type_to_string(ctx, type))) + hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Unexpected type for argument %u of [%s]: expected int or uint, but got %s.", + i, attr->name, string->buffer); + hlsl_release_string_buffer(ctx, string); + return false; + } + + if (instr->type != HLSL_IR_CONSTANT) + { + hlsl_fixme(ctx, &instr->loc, "Non-constant expression in [%s] initializer.", attr->name); + return false; + } + + *base_type = type->e.numeric.type; + *value = hlsl_ir_constant(instr)->value.u[0].i; + return true; +} + static const char *get_string_argument_value(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr, unsigned int i) { const struct hlsl_ir_node *instr = attr->args[i].node; @@ -6147,36 +6475,17 @@ static void parse_numthreads_attribute(struct hlsl_ctx *ctx, const struct hlsl_a for (i = 0; i < attr->args_count; ++i) { - const struct hlsl_ir_node *instr = attr->args[i].node; - const struct hlsl_type *type = instr->data_type; - const struct hlsl_ir_constant *constant; + enum hlsl_base_type base_type; + int value; - if (type->class != HLSL_CLASS_SCALAR - || (type->e.numeric.type != HLSL_TYPE_INT && type->e.numeric.type != HLSL_TYPE_UINT)) - { - struct vkd3d_string_buffer *string; - - if ((string = hlsl_type_to_string(ctx, type))) - hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Wrong type for argument %u of [numthreads]: expected int or uint, but got %s.", - i, string->buffer); - hlsl_release_string_buffer(ctx, string); - break; - } - - if (instr->type != HLSL_IR_CONSTANT) - { - hlsl_fixme(ctx, &instr->loc, "Non-constant expression in [numthreads] initializer."); - break; - } - constant = hlsl_ir_constant(instr); + if (!get_integral_argument_value(ctx, attr, i, &base_type, &value)) + return; - if ((type->e.numeric.type == HLSL_TYPE_INT && constant->value.u[0].i <= 0) - || (type->e.numeric.type == HLSL_TYPE_UINT && !constant->value.u[0].u)) - hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_THREAD_COUNT, + if ((base_type == HLSL_TYPE_INT && value <= 0) || (base_type == HLSL_TYPE_UINT && !value)) + hlsl_error(ctx, &attr->args[i].node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_THREAD_COUNT, "Thread count must be a positive integer."); - ctx->thread_count[i] = constant->value.u[0].u; + ctx->thread_count[i] = value; } } @@ -6208,9 +6517,8 @@ static void parse_domain_attribute(struct hlsl_ctx *ctx, const struct hlsl_attri static void parse_outputcontrolpoints_attribute(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr) { - const struct hlsl_ir_node *instr; - const struct hlsl_type *type; - const struct hlsl_ir_constant *constant; + enum hlsl_base_type base_type; + int value; if (attr->args_count != 1) { @@ -6219,35 +6527,14 @@ static void parse_outputcontrolpoints_attribute(struct hlsl_ctx *ctx, const stru return; } - instr = attr->args[0].node; - type = instr->data_type; - - if (type->class != HLSL_CLASS_SCALAR - || (type->e.numeric.type != HLSL_TYPE_INT && type->e.numeric.type != HLSL_TYPE_UINT)) - { - struct vkd3d_string_buffer *string; - - if ((string = hlsl_type_to_string(ctx, type))) - hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Wrong type for argument 0 of [outputcontrolpoints]: expected int or uint, but got %s.", - string->buffer); - hlsl_release_string_buffer(ctx, string); - return; - } - - if (instr->type != HLSL_IR_CONSTANT) - { - hlsl_fixme(ctx, &instr->loc, "Non-constant expression in [outputcontrolpoints] initializer."); + if (!get_integral_argument_value(ctx, attr, 0, &base_type, &value)) return; - } - constant = hlsl_ir_constant(instr); - if ((type->e.numeric.type == HLSL_TYPE_INT && constant->value.u[0].i < 0) - || constant->value.u[0].u > 32) - hlsl_error(ctx, &instr->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT, + if (value < 0 || value > 32) + hlsl_error(ctx, &attr->args[0].node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT, "Output control point count must be between 0 and 32."); - ctx->output_control_point_count = constant->value.u[0].u; + ctx->output_control_point_count = value; } static void parse_outputtopology_attribute(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr) @@ -6341,6 +6628,28 @@ static void parse_patchconstantfunc_attribute(struct hlsl_ctx *ctx, const struct "Patch constant function \"%s\" is not defined.", name); } +static void parse_maxvertexcount_attribute(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr) +{ + enum hlsl_base_type base_type; + int value; + + if (attr->args_count != 1) + { + hlsl_error(ctx, &attr->loc, VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT, + "Expected 1 parameter for [maxvertexcount] attribute, but got %u.", attr->args_count); + return; + } + + if (!get_integral_argument_value(ctx, attr, 0, &base_type, &value)) + return; + + if (value < 1 || value > 1024) + hlsl_error(ctx, &attr->args[0].node->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MAX_VERTEX_COUNT, + "Max vertex count must be between 1 and 1024."); + + ctx->max_vertex_count = value; +} + static void parse_entry_function_attributes(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func) { const struct hlsl_profile_info *profile = ctx->profile; @@ -6365,6 +6674,8 @@ static void parse_entry_function_attributes(struct hlsl_ctx *ctx, struct hlsl_ir parse_patchconstantfunc_attribute(ctx, attr); else if (!strcmp(attr->name, "earlydepthstencil") && profile->type == VKD3D_SHADER_TYPE_PIXEL) entry_func->early_depth_test = true; + else if (!strcmp(attr->name, "maxvertexcount") && profile->type == VKD3D_SHADER_TYPE_GEOMETRY) + parse_maxvertexcount_attribute(ctx, attr); else hlsl_warning(ctx, &entry_func->attrs[i]->loc, VKD3D_SHADER_WARNING_HLSL_UNKNOWN_ATTRIBUTE, "Ignoring unknown attribute \"%s\".", entry_func->attrs[i]->name); @@ -6437,7 +6748,71 @@ static void validate_hull_shader_attributes(struct hlsl_ctx *ctx, const struct h } } -static void validate_and_record_patch_type(struct hlsl_ctx *ctx, struct hlsl_ir_var *var) +static enum vkd3d_primitive_type get_primitive_type(struct hlsl_ctx *ctx, struct hlsl_ir_var *var) +{ + uint32_t prim_modifier = var->data_type->modifiers & HLSL_PRIMITIVE_MODIFIERS_MASK; + enum vkd3d_primitive_type prim_type = VKD3D_PT_UNDEFINED; + + if (prim_modifier) + { + unsigned int count = var->data_type->e.array.elements_count; + unsigned int expected_count; + + VKD3D_ASSERT(!(prim_modifier & (prim_modifier - 1))); + + switch (prim_modifier) + { + case HLSL_PRIMITIVE_POINT: + prim_type = VKD3D_PT_POINTLIST; + expected_count = 1; + break; + + case HLSL_PRIMITIVE_LINE: + prim_type = VKD3D_PT_LINELIST; + expected_count = 2; + break; + + case HLSL_PRIMITIVE_TRIANGLE: + prim_type = VKD3D_PT_TRIANGLELIST; + expected_count = 3; + break; + + case HLSL_PRIMITIVE_LINEADJ: + prim_type = VKD3D_PT_LINELIST_ADJ; + expected_count = 4; + break; + + case HLSL_PRIMITIVE_TRIANGLEADJ: + prim_type = VKD3D_PT_TRIANGLELIST_ADJ; + expected_count = 6; + break; + + default: + vkd3d_unreachable(); + } + + if (count != expected_count) + { + struct vkd3d_string_buffer *string; + + if ((string = hlsl_modifiers_to_string(ctx, prim_modifier))) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT, + "Control point count %u does not match the expect count %u for the %s input primitive type.", + count, expected_count, string->buffer); + hlsl_release_string_buffer(ctx, string); + } + } + + /* Patch types take precedence over primitive modifiers. */ + if (hlsl_type_is_patch_array(var->data_type)) + prim_type = VKD3D_PT_PATCH; + + VKD3D_ASSERT(prim_type != VKD3D_PT_UNDEFINED); + return prim_type; +} + + +static void validate_and_record_prim_type(struct hlsl_ctx *ctx, struct hlsl_ir_var *var) { unsigned int control_point_count = var->data_type->e.array.elements_count; enum hlsl_array_type array_type = var->data_type->e.array.array_type; @@ -6455,7 +6830,7 @@ static void validate_and_record_patch_type(struct hlsl_ctx *ctx, struct hlsl_ir_ return; } } - else + else if (array_type == HLSL_ARRAY_PATCH_OUTPUT) { if (!ctx->is_patch_constant_func && profile->type != VKD3D_SHADER_TYPE_DOMAIN) { @@ -6466,6 +6841,30 @@ static void validate_and_record_patch_type(struct hlsl_ctx *ctx, struct hlsl_ir_ } } + if ((var->data_type->modifiers & HLSL_PRIMITIVE_MODIFIERS_MASK) && profile->type != VKD3D_SHADER_TYPE_GEOMETRY) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, + "Input primitive parameters can only be used in geometry shaders."); + return; + } + + if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY) + { + enum vkd3d_primitive_type prim_type = get_primitive_type(ctx, var); + + if (ctx->input_primitive_type == VKD3D_PT_UNDEFINED) + { + ctx->input_primitive_type = prim_type; + } + else if (ctx->input_primitive_type != prim_type) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, + "Input primitive type does not match the previously declared type."); + hlsl_note(ctx, &ctx->input_primitive_param->loc, VKD3D_SHADER_LOG_ERROR, + "The input primitive was previously declared here."); + } + } + if (control_point_count > 32) { hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT, @@ -6478,7 +6877,7 @@ static void validate_and_record_patch_type(struct hlsl_ctx *ctx, struct hlsl_ir_ { if (control_point_count != ctx->output_control_point_count) hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT, - "Output control point count %u does not match the count %u specified in the control point function.", + "Output control point count %u does not match the count %u declared in the control point function.", control_point_count, ctx->output_control_point_count); if (!hlsl_types_are_equal(control_point_type, ctx->output_control_point_type)) @@ -6490,22 +6889,32 @@ static void validate_and_record_patch_type(struct hlsl_ctx *ctx, struct hlsl_ir_ if (ctx->input_control_point_count != UINT_MAX) { - VKD3D_ASSERT(ctx->is_patch_constant_func); + VKD3D_ASSERT(profile->type == VKD3D_SHADER_TYPE_GEOMETRY || ctx->is_patch_constant_func); if (control_point_count != ctx->input_control_point_count) + { hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT, - "Input control point count %u does not match the count %u specified in the control point function.", + "Input control point count %u does not match the count %u declared previously.", control_point_count, ctx->input_control_point_count); + hlsl_note(ctx, &ctx->input_primitive_param->loc, VKD3D_SHADER_LOG_ERROR, + "The input primitive was previously declared here."); + } - if (!hlsl_types_are_equal(control_point_type, ctx->input_control_point_type)) + if (profile->type != VKD3D_SHADER_TYPE_GEOMETRY + && !hlsl_types_are_equal(control_point_type, ctx->input_control_point_type)) + { hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, - "Input control point type does not match the input type specified in the control point function."); + "Input control point type does not match the input type declared previously."); + hlsl_note(ctx, &ctx->input_primitive_param->loc, VKD3D_SHADER_LOG_ERROR, + "The input primitive was previously declared here."); + } return; } ctx->input_control_point_count = control_point_count; ctx->input_control_point_type = control_point_type; + ctx->input_primitive_param = var; } static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *body) @@ -6569,6 +6978,24 @@ void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *body) lower_ir(ctx, lower_index_loads, body); } + +static bool simplify_exprs(struct hlsl_ctx *ctx, struct hlsl_block *block) +{ + bool progress, any_progress = false; + + do + { + progress = hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, block, NULL); + progress |= hlsl_transform_ir(ctx, hlsl_normalize_binary_exprs, block, NULL); + progress |= hlsl_transform_ir(ctx, hlsl_fold_constant_identities, block, NULL); + progress |= hlsl_transform_ir(ctx, hlsl_fold_constant_swizzles, block, NULL); + + any_progress |= progress; + } while (progress); + + return any_progress; +} + static void hlsl_run_folding_passes(struct hlsl_ctx *ctx, struct hlsl_block *body) { bool progress; @@ -6576,15 +7003,13 @@ static void hlsl_run_folding_passes(struct hlsl_ctx *ctx, struct hlsl_block *bod hlsl_transform_ir(ctx, fold_redundant_casts, body, NULL); do { - progress = hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, body, NULL); - progress |= hlsl_transform_ir(ctx, hlsl_fold_constant_identities, body, NULL); - progress |= hlsl_transform_ir(ctx, hlsl_normalize_binary_exprs, body, NULL); - progress |= hlsl_transform_ir(ctx, hlsl_fold_constant_swizzles, body, NULL); + progress = simplify_exprs(ctx, body); progress |= hlsl_copy_propagation_execute(ctx, body); progress |= hlsl_transform_ir(ctx, fold_swizzle_chains, body, NULL); progress |= hlsl_transform_ir(ctx, remove_trivial_swizzles, body, NULL); progress |= hlsl_transform_ir(ctx, remove_trivial_conditional_branches, body, NULL); } while (progress); + hlsl_transform_ir(ctx, fold_redundant_casts, body, NULL); } void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body) @@ -7214,7 +7639,7 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p } else { - unsigned int offset = hlsl_offset_from_deref_safe(ctx, deref) + var->buffer_offset; + unsigned int offset = deref->const_offset + var->buffer_offset; VKD3D_ASSERT(data_type->class <= HLSL_CLASS_VECTOR); reg->type = VKD3DSPR_CONSTBUFFER; @@ -7232,6 +7657,14 @@ static bool sm4_generate_vsir_reg_from_deref(struct hlsl_ctx *ctx, struct vsir_p reg->idx[1].offset = offset / 4; reg->idx_count = 2; } + + if (deref->rel_offset.node) + { + if (!(reg->idx[reg->idx_count - 1].rel_addr = sm4_generate_vsir_new_idx_src(ctx, + program, deref->rel_offset.node))) + return false; + } + *writemask = ((1u << data_type->e.numeric.dimx) - 1) << (offset & 3); } } @@ -11515,9 +11948,7 @@ static void loop_unrolling_simplify(struct hlsl_ctx *ctx, struct hlsl_block *blo copy_propagation_pop_scope(state); copy_propagation_push_scope(state, ctx); - progress = hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, block, NULL); - progress |= hlsl_transform_ir(ctx, hlsl_fold_constant_identities, block, NULL); - progress |= hlsl_transform_ir(ctx, hlsl_fold_constant_swizzles, block, NULL); + progress = simplify_exprs(ctx, block); current_index = index_instructions(block, *index); progress |= copy_propagation_transform_block(ctx, block, state); @@ -12060,42 +12491,68 @@ static void process_entry_function(struct hlsl_ctx *ctx, else prepend_uniform_copy(ctx, body, var); } - else if (hlsl_type_is_patch_array(var->data_type)) + else if (hlsl_type_is_primitive_array(var->data_type)) { - if (var->data_type->e.array.array_type == HLSL_ARRAY_PATCH_INPUT) + if (var->storage_modifiers & HLSL_STORAGE_OUT) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Input primitive parameter \"%s\" is declared as \"out\".", var->name); + + if (profile->type != VKD3D_SHADER_TYPE_GEOMETRY) { - if (input_patch) + enum hlsl_array_type array_type = var->data_type->e.array.array_type; + + if (array_type == HLSL_ARRAY_PATCH_INPUT) { - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_DUPLICATE_PATCH, - "Found multiple InputPatch parameters."); - hlsl_note(ctx, &input_patch->loc, VKD3D_SHADER_LOG_ERROR, - "The InputPatch parameter was previously declared here."); - continue; + if (input_patch) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_DUPLICATE_PATCH, + "Found multiple InputPatch parameters."); + hlsl_note(ctx, &input_patch->loc, VKD3D_SHADER_LOG_ERROR, + "The InputPatch parameter was previously declared here."); + continue; + } + input_patch = var; } - input_patch = var; - } - else - { - if (output_patch) + else if (array_type == HLSL_ARRAY_PATCH_OUTPUT) { - hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_DUPLICATE_PATCH, - "Found multiple OutputPatch parameters."); - hlsl_note(ctx, &output_patch->loc, VKD3D_SHADER_LOG_ERROR, - "The OutputPatch parameter was previously declared here."); - continue; + if (output_patch) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_DUPLICATE_PATCH, + "Found multiple OutputPatch parameters."); + hlsl_note(ctx, &output_patch->loc, VKD3D_SHADER_LOG_ERROR, + "The OutputPatch parameter was previously declared here."); + continue; + } + output_patch = var; } - output_patch = var; } - validate_and_record_patch_type(ctx, var); + validate_and_record_prim_type(ctx, var); if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY) { - hlsl_fixme(ctx, &var->loc, "InputPatch/OutputPatch parameters in geometry shaders."); + hlsl_fixme(ctx, &var->loc, "Input primitive parameters in geometry shaders."); continue; } prepend_input_var_copy(ctx, entry_func, var); } + else if (hlsl_get_stream_output_type(var->data_type)) + { + if (profile->type != VKD3D_SHADER_TYPE_GEOMETRY) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, + "Stream output parameters can only be used in geometry shaders."); + continue; + } + + if (!(var->storage_modifiers & HLSL_STORAGE_IN) || !(var->storage_modifiers & HLSL_STORAGE_OUT)) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Stream output parameter \"%s\" must be declared as \"inout\".", var->name); + + /* TODO: check that maxvertexcount * component_count(element_type) <= 1024. */ + + continue; + } else { if (hlsl_get_multiarray_element_type(var->data_type)->class != HLSL_CLASS_STRUCT @@ -12107,12 +12564,24 @@ static void process_entry_function(struct hlsl_ctx *ctx, } if (var->storage_modifiers & HLSL_STORAGE_IN) + { + if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY) + { + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_PRIMITIVE_TYPE, + "Input parameter \"%s\" is missing a primitive type.", var->name); + continue; + } + prepend_input_var_copy(ctx, entry_func, var); + } if (var->storage_modifiers & HLSL_STORAGE_OUT) { if (profile->type == VKD3D_SHADER_TYPE_HULL && !ctx->is_patch_constant_func) hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, "Output parameters are not supported in hull shader control point functions."); + else if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY) + hlsl_error(ctx, &var->loc, VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER, + "Output parameters are not allowed in geometry shaders."); else append_output_var_copy(ctx, entry_func, var); } @@ -12120,7 +12589,11 @@ static void process_entry_function(struct hlsl_ctx *ctx, } if (entry_func->return_var) { - if (entry_func->return_var->data_type->class != HLSL_CLASS_STRUCT && !entry_func->return_var->semantic.name) + if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY) + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_INCOMPATIBLE_PROFILE, + "Geometry shaders cannot return values."); + else if (entry_func->return_var->data_type->class != HLSL_CLASS_STRUCT + && !entry_func->return_var->semantic.name) hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC, "Entry point \"%s\" is missing a return value semantic.", entry_func->func->name); @@ -12135,6 +12608,10 @@ static void process_entry_function(struct hlsl_ctx *ctx, hlsl_fixme(ctx, &entry_func->loc, "Passthrough hull shader control point function."); } + if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY && ctx->input_primitive_type == VKD3D_PT_UNDEFINED) + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_PRIMITIVE_TYPE, + "Entry point \"%s\" is missing an input primitive parameter.", entry_func->func->name); + if (hlsl_version_ge(ctx, 4, 0)) { hlsl_transform_ir(ctx, lower_discard_neg, body, NULL); @@ -12188,6 +12665,7 @@ static void process_entry_function(struct hlsl_ctx *ctx, lower_ir(ctx, lower_casts_to_bool, body); lower_ir(ctx, lower_casts_to_int, body); + lower_ir(ctx, lower_trunc, body); lower_ir(ctx, lower_sqrt, body); lower_ir(ctx, lower_dot, body); lower_ir(ctx, lower_round, body); @@ -12217,7 +12695,7 @@ static void process_entry_function(struct hlsl_ctx *ctx, /* TODO: move forward, remove when no longer needed */ transform_derefs(ctx, replace_deref_path_with_offset, body); - while (hlsl_transform_ir(ctx, hlsl_fold_constant_exprs, body, NULL)); + simplify_exprs(ctx, body); transform_derefs(ctx, clean_constant_deref_offset_srcs, body); do @@ -12253,6 +12731,9 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry else if (profile->type == VKD3D_SHADER_TYPE_DOMAIN && ctx->domain == VKD3D_TESSELLATOR_DOMAIN_INVALID) hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_ATTRIBUTE, "Entry point \"%s\" is missing a [domain] attribute.", entry_func->func->name); + else if (profile->type == VKD3D_SHADER_TYPE_GEOMETRY && !ctx->max_vertex_count) + hlsl_error(ctx, &entry_func->loc, VKD3D_SHADER_ERROR_HLSL_MISSING_ATTRIBUTE, + "Entry point \"%s\" is missing a [maxvertexcount] attribute.", entry_func->func->name); hlsl_block_init(&global_uniform_block); diff --git a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c index f4715a9224c..f74ecffcd4b 100644 --- a/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c +++ b/libs/vkd3d/libs/vkd3d-shader/hlsl_constant_ops.c @@ -1712,7 +1712,8 @@ bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst progress = true; } - if (!progress && e1 && (tmp = collect_exprs(ctx, &block, instr, op, e1->operands[1].node, arg2))) + if (!progress && e1 && e1->op == op + && (tmp = collect_exprs(ctx, &block, instr, op, e1->operands[1].node, arg2))) { /* (y OPR (x OPL a)) OPR (x OPL b) -> y OPR (x OPL (a OPR b)) */ arg1 = e1->operands[0].node; @@ -1720,7 +1721,7 @@ bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst progress = true; } - if (!progress && is_op_commutative(op) && e1 + if (!progress && is_op_commutative(op) && e1 && e1->op == op && (tmp = collect_exprs(ctx, &block, instr, op, e1->operands[0].node, arg2))) { /* ((x OPL a) OPR y) OPR (x OPL b) -> (x OPL (a OPR b)) OPR y */ @@ -1729,7 +1730,8 @@ bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst progress = true; } - if (!progress && e2 && (tmp = collect_exprs(ctx, &block, instr, op, arg1, e2->operands[0].node))) + if (!progress && e2 && e2->op == op + && (tmp = collect_exprs(ctx, &block, instr, op, arg1, e2->operands[0].node))) { /* (x OPL a) OPR ((x OPL b) OPR y) -> (x OPL (a OPR b)) OPR y */ arg1 = tmp; @@ -1737,7 +1739,7 @@ bool hlsl_normalize_binary_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *inst progress = true; } - if (!progress && is_op_commutative(op) && e2 + if (!progress && is_op_commutative(op) && e2 && e2->op == op && (tmp = collect_exprs(ctx, &block, instr, op, arg1, e2->operands[1].node))) { /* (x OPL a) OPR (y OPR (x OPL b)) -> (x OPL (a OPR b)) OPR y */ diff --git a/libs/vkd3d/libs/vkd3d-shader/tpf.c b/libs/vkd3d/libs/vkd3d-shader/tpf.c index 267f0884d83..f4525009f77 100644 --- a/libs/vkd3d/libs/vkd3d-shader/tpf.c +++ b/libs/vkd3d/libs/vkd3d-shader/tpf.c @@ -3462,12 +3462,16 @@ static void sm4_write_register_index(const struct tpf_compiler *tpf, const struc unsigned int j) { unsigned int addressing = sm4_get_index_addressing_from_reg(reg, j); + const struct vkd3d_shader_register_index *idx = ®->idx[j]; struct vkd3d_bytecode_buffer *buffer = tpf->buffer; unsigned int k; + if (!addressing || (addressing & VKD3D_SM4_ADDRESSING_OFFSET)) + put_u32(buffer, idx->offset); + if (addressing & VKD3D_SM4_ADDRESSING_RELATIVE) { - const struct vkd3d_shader_src_param *idx_src = reg->idx[j].rel_addr; + const struct vkd3d_shader_src_param *idx_src = idx->rel_addr; uint32_t idx_src_token; VKD3D_ASSERT(idx_src); @@ -3482,10 +3486,6 @@ static void sm4_write_register_index(const struct tpf_compiler *tpf, const struc VKD3D_ASSERT(!idx_src->reg.idx[k].rel_addr); } } - else - { - put_u32(tpf->buffer, reg->idx[j].offset); - } } static void sm4_write_dst_register(const struct tpf_compiler *tpf, const struct vkd3d_shader_dst_param *dst) diff --git a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h index eb50da28d24..8329bf169b0 100644 --- a/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d/libs/vkd3d-shader/vkd3d_shader_private.h @@ -169,6 +169,9 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_HLSL_MISPLACED_SAMPLER_STATE = 5039, VKD3D_SHADER_ERROR_HLSL_AMBIGUOUS_CALL = 5040, VKD3D_SHADER_ERROR_HLSL_DUPLICATE_PATCH = 5041, + VKD3D_SHADER_ERROR_HLSL_INVALID_MAX_VERTEX_COUNT = 5042, + VKD3D_SHADER_ERROR_HLSL_MISSING_PRIMITIVE_TYPE = 5043, + VKD3D_SHADER_ERROR_HLSL_MISPLACED_STREAM_OUTPUT = 5044, VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300, VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301, -- 2.47.2