From: Francisco Casas fcasas@codeweavers.com
Also, call hlsl_sampler_dim_count() and hlsl_offset_dim_count() after type checking, to avoid reaching unreacheable cases. --- libs/vkd3d-shader/hlsl.y | 148 +++++++++++++++++++++++++-------------- 1 file changed, 96 insertions(+), 52 deletions(-)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 5f6334a4d..31c8c950d 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -4237,32 +4237,85 @@ static unsigned int hlsl_offset_dim_count(enum hlsl_sampler_dim dim) }
static bool raise_invalid_method_object_type(struct hlsl_ctx *ctx, const struct hlsl_type *object_type, - const char *method, const struct vkd3d_shader_location *loc) + const char *method, const struct vkd3d_shader_location *loc, bool is_fixme) { struct vkd3d_string_buffer *string;
if ((string = hlsl_type_to_string(ctx, object_type))) - hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, - "Method '%s' is not defined on type '%s'.", method, string->buffer); + { + if (is_fixme) + hlsl_fixme(ctx, loc, "Method '%s' for type '%s'.", method, string->buffer); + else + hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED, + "Method '%s' is not defined on type '%s'.", method, string->buffer); + } hlsl_release_string_buffer(ctx, string); return false; }
+enum resource_load_method +{ + RESOURCE_LOAD_METHOD_LOAD = 0, + RESOURCE_LOAD_METHOD_SAMPLE = 1, + RESOURCE_LOAD_METHOD_SAMPLE_CMP = 2, + RESOURCE_LOAD_METHOD_GATHER = 3, + RESOURCE_LOAD_METHOD_GETDIMENSIONS = 4, + RESOURCE_LOAD_METHOD_SAMPLE_LOD = 5, + RESOURCE_LOAD_METHOD_SAMPLE_GRAD = 6, + RESOURCE_LOAD_METHOD_SAMPLE_LAST = RESOURCE_LOAD_METHOD_SAMPLE_GRAD, +}; + +static bool validate_method_call(struct hlsl_ctx *ctx, struct hlsl_ir_node *object, const char *name, + enum resource_load_method method, const struct vkd3d_shader_location *loc) +{ + const struct hlsl_type *object_type = object->data_type; + enum hlsl_sampler_dim sampler_dim = object_type->sampler_dim; + + static char valid_methods[HLSL_SAMPLER_DIM_MAX + 1][RESOURCE_LOAD_METHOD_SAMPLE_LAST + 1] = + { + /* load, sample, samplecmp, gather, getdims, samplelod, samplegrad */ + [HLSL_SAMPLER_DIM_GENERIC] = { 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, + [HLSL_SAMPLER_DIM_COMPARISON] = { 'x', 'x', 'x', 'x', 'x', 'x', 'x'}, + [HLSL_SAMPLER_DIM_1D] = { '1', '1', '1', ' ', '1', '1', '1'}, + [HLSL_SAMPLER_DIM_2D] = { '1', '1', '1', '1', '1', '1', '1'}, + [HLSL_SAMPLER_DIM_3D] = { '1', '1', '1', ' ', '1', '1', '1'}, + [HLSL_SAMPLER_DIM_CUBE] = { ' ', '1', '1', '1', '1', '1', '1'}, + [HLSL_SAMPLER_DIM_1DARRAY] = { '1', '1', '1', ' ', '1', '1', '1'}, + [HLSL_SAMPLER_DIM_2DARRAY] = { '1', '1', '1', '1', '1', '1', '1'}, + [HLSL_SAMPLER_DIM_2DMS] = { '1', ' ', ' ', ' ', '1', ' ', ' '}, + [HLSL_SAMPLER_DIM_2DMSARRAY] = { '1', ' ', ' ', ' ', '1', ' ', ' '}, + [HLSL_SAMPLER_DIM_CUBEARRAY] = { ' ', '1', '1', '1', '1', '1', '1'}, + [HLSL_SAMPLER_DIM_BUFFER] = { 'f', ' ', ' ', ' ', 'f', ' ', ' '}, + [HLSL_SAMPLER_DIM_STRUCTURED_BUFFER] = { 'f', ' ', ' ', ' ', 'f', ' ', ' '}, + }; + + if (valid_methods[sampler_dim][method] == '1') + return true; + + if (valid_methods[sampler_dim][method] == 'f') + return raise_invalid_method_object_type(ctx, object_type, name, loc, true); + + if (valid_methods[sampler_dim][method] == ' ') + return raise_invalid_method_object_type(ctx, object_type, name, loc, false); + + vkd3d_unreachable(); +} + + static bool add_load_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *object, const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { const struct hlsl_type *object_type = object->data_type; - const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); - const unsigned int offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); 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_CUBE - || object_type->sampler_dim == HLSL_SAMPLER_DIM_CUBEARRAY) - { - return raise_invalid_method_object_type(ctx, object_type, name, loc); - } + if (!validate_method_call(ctx, object, name, RESOURCE_LOAD_METHOD_LOAD, loc)) + return false; + + sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); + offset_dim = hlsl_offset_dim_count(object_type->sampler_dim);
multisampled = object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS || object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY; @@ -4311,17 +4364,16 @@ static bool add_sample_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { const struct hlsl_type *object_type = object->data_type; - const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); - const unsigned int offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); 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;
- if (object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS - || object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY) - { - return raise_invalid_method_object_type(ctx, object_type, name, loc); - } + if (!validate_method_call(ctx, object, name, RESOURCE_LOAD_METHOD_SAMPLE, loc)) + return false; + + sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); + offset_dim = hlsl_offset_dim_count(object_type->sampler_dim);
if (params->args_count < 2 || params->args_count > 4 + !!offset_dim) { @@ -4375,17 +4427,16 @@ static bool add_sample_cmp_method_call(struct hlsl_ctx *ctx, struct hlsl_block * const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { const struct hlsl_type *object_type = object->data_type; - const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); - const unsigned int offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); 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;
- if (object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS - || object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY) - { - return raise_invalid_method_object_type(ctx, object_type, name, loc); - } + if (!validate_method_call(ctx, object, name, RESOURCE_LOAD_METHOD_SAMPLE_CMP, loc)) + return false; + + sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); + offset_dim = hlsl_offset_dim_count(object_type->sampler_dim);
if (!strcmp(name, "SampleCmpLevelZero")) load_params.type = HLSL_RESOURCE_SAMPLE_CMP_LZ; @@ -4449,20 +4500,17 @@ static bool add_gather_method_call(struct hlsl_ctx *ctx, struct hlsl_block *bloc const char *name, const struct parse_initializer *params, const struct vkd3d_shader_location *loc) { const struct hlsl_type *object_type = object->data_type; - const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); - const unsigned int offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); 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;
- if (object_type->sampler_dim != HLSL_SAMPLER_DIM_2D - && object_type->sampler_dim != HLSL_SAMPLER_DIM_2DARRAY - && object_type->sampler_dim != HLSL_SAMPLER_DIM_CUBE - && object_type->sampler_dim != HLSL_SAMPLER_DIM_CUBEARRAY) - { - return raise_invalid_method_object_type(ctx, object_type, name, loc); - } + if (!validate_method_call(ctx, object, name, RESOURCE_LOAD_METHOD_GATHER, loc)) + return false; + + sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); + offset_dim = hlsl_offset_dim_count(object_type->sampler_dim);
if (!strcmp(name, "GatherGreen")) { @@ -4616,10 +4664,8 @@ static bool add_getdimensions_method_call(struct hlsl_ctx *ctx, struct hlsl_bloc }; const struct overload *o = NULL;
- if (object_type->sampler_dim > HLSL_SAMPLER_DIM_LAST_TEXTURE) - { - hlsl_error(ctx, loc, VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE, "GetDimensions() is not defined for this type."); - } + if (!validate_method_call(ctx, object, name, RESOURCE_LOAD_METHOD_GETDIMENSIONS, loc)) + return false;
uint_type = hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT); float_type = hlsl_get_scalar_type(ctx, HLSL_TYPE_FLOAT); @@ -4732,16 +4778,15 @@ static bool add_sample_lod_method_call(struct hlsl_ctx *ctx, struct hlsl_block * { const struct hlsl_type *object_type = object->data_type; struct hlsl_resource_load_params load_params = { 0 }; - const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); - const unsigned int offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); + unsigned int sampler_dim, offset_dim; const struct hlsl_type *sampler_type; struct hlsl_ir_node *load;
- if (object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS - || object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY) - { - return raise_invalid_method_object_type(ctx, object_type, name, loc); - } + if (!validate_method_call(ctx, object, name, RESOURCE_LOAD_METHOD_SAMPLE_LOD, loc)) + return false; + + sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); + offset_dim = hlsl_offset_dim_count(object_type->sampler_dim);
if (!strcmp(name, "SampleLevel")) load_params.type = HLSL_RESOURCE_SAMPLE_LOD; @@ -4802,16 +4847,15 @@ static bool add_sample_grad_method_call(struct hlsl_ctx *ctx, struct hlsl_block { const struct hlsl_type *object_type = object->data_type; struct hlsl_resource_load_params load_params = { 0 }; - const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); - const unsigned int offset_dim = hlsl_offset_dim_count(object_type->sampler_dim); + unsigned int sampler_dim, offset_dim; const struct hlsl_type *sampler_type; struct hlsl_ir_node *load;
- if (object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS - || object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY) - { - return raise_invalid_method_object_type(ctx, object_type, name, loc); - } + if (!validate_method_call(ctx, object, name, RESOURCE_LOAD_METHOD_SAMPLE_GRAD, loc)) + return false; + + sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); + offset_dim = hlsl_offset_dim_count(object_type->sampler_dim);
load_params.type = HLSL_RESOURCE_SAMPLE_GRAD;
@@ -4926,7 +4970,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct hlsl_block *block, stru } else { - return raise_invalid_method_object_type(ctx, object_type, name, loc); + return raise_invalid_method_object_type(ctx, object_type, name, loc, false); } }