mirror of
				https://gitlab.winehq.org/wine/vkd3d.git
				synced 2025-09-12 18:50:22 -07:00 
			
		
		
		
	vkd3d-shader/hlsl: Replace register offsets with index paths in load initializations.
The transform_deref_paths_into_offsets pass turns these index paths back into register offsets. Signed-off-by: Francisco Casas <fcasas@codeweavers.com> Signed-off-by: Giovanni Mascellani <gmascellani@codeweavers.com>
This commit is contained in:
		
				
					committed by
					
						 Alexandre Julliard
						Alexandre Julliard
					
				
			
			
				
	
			
			
			
						parent
						
							a2996c2d59
						
					
				
				
					commit
					4fede46c9a
				
			
				
				Notes:
				
					Alexandre Julliard
				
				2022-10-18 00:13:00 +02:00 
			
			Approved-by: Giovanni Mascellani (@giomasce) Approved-by: Zebediah Figura (@zfigura) Approved-by: Henri Verbeet (@hverbeet) Approved-by: Alexandre Julliard (@julliard) Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/5
| @@ -330,6 +330,180 @@ unsigned int hlsl_compute_component_offset(struct hlsl_ctx *ctx, struct hlsl_typ | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| static bool type_is_single_component(const struct hlsl_type *type) | ||||
| { | ||||
|     return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_OBJECT; | ||||
| } | ||||
|  | ||||
| /* Given a type and a component index, this function moves one step through the path required to | ||||
|  * reach that component within the type. | ||||
|  * It returns the first index of this path. | ||||
|  * It sets *type_ptr to the (outermost) type within the original type that contains the component. | ||||
|  * It sets *index_ptr to the index of the component within *type_ptr. | ||||
|  * So, this function can be called several times in sequence to obtain all the path's indexes until | ||||
|  * the component is finally reached. */ | ||||
| static unsigned int traverse_path_from_component_index(struct hlsl_ctx *ctx, | ||||
|         struct hlsl_type **type_ptr, unsigned int *index_ptr) | ||||
| { | ||||
|     struct hlsl_type *type = *type_ptr; | ||||
|     unsigned int index = *index_ptr; | ||||
|  | ||||
|     assert(!type_is_single_component(type)); | ||||
|     assert(index < hlsl_type_component_count(type)); | ||||
|  | ||||
|     switch (type->type) | ||||
|     { | ||||
|         case HLSL_CLASS_VECTOR: | ||||
|             assert(index < type->dimx); | ||||
|             *type_ptr = hlsl_get_scalar_type(ctx, type->base_type); | ||||
|             *index_ptr = 0; | ||||
|             return index; | ||||
|  | ||||
|         case HLSL_CLASS_MATRIX: | ||||
|         { | ||||
|             unsigned int y = index / type->dimx, x = index % type->dimx; | ||||
|             bool row_major = hlsl_type_is_row_major(type); | ||||
|  | ||||
|             assert(index < type->dimx * type->dimy); | ||||
|             *type_ptr = hlsl_get_vector_type(ctx, type->base_type, row_major ? type->dimx : type->dimy); | ||||
|             *index_ptr = row_major ? x : y; | ||||
|             return row_major ? y : x; | ||||
|         } | ||||
|  | ||||
|         case HLSL_CLASS_ARRAY: | ||||
|         { | ||||
|             unsigned int elem_comp_count = hlsl_type_component_count(type->e.array.type); | ||||
|             unsigned int array_index; | ||||
|  | ||||
|             *type_ptr = type->e.array.type; | ||||
|             *index_ptr = index % elem_comp_count; | ||||
|             array_index = index / elem_comp_count; | ||||
|             assert(array_index < type->e.array.elements_count); | ||||
|             return array_index; | ||||
|         } | ||||
|  | ||||
|         case HLSL_CLASS_STRUCT: | ||||
|         { | ||||
|             struct hlsl_struct_field *field; | ||||
|             unsigned int field_comp_count, i; | ||||
|  | ||||
|             for (i = 0; i < type->e.record.field_count; ++i) | ||||
|             { | ||||
|                 field = &type->e.record.fields[i]; | ||||
|                 field_comp_count = hlsl_type_component_count(field->type); | ||||
|                 if (index < field_comp_count) | ||||
|                 { | ||||
|                     *type_ptr = field->type; | ||||
|                     *index_ptr = index; | ||||
|                     return i; | ||||
|                 } | ||||
|                 index -= field_comp_count; | ||||
|             } | ||||
|             assert(0); | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         default: | ||||
|             assert(0); | ||||
|             return 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl_type *type, | ||||
|         unsigned int index) | ||||
| { | ||||
|     while (!type_is_single_component(type)) | ||||
|         traverse_path_from_component_index(ctx, &type, &index); | ||||
|  | ||||
|     return type; | ||||
| } | ||||
|  | ||||
| static bool 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; | ||||
|     deref->offset.node = NULL; | ||||
|  | ||||
|     if (path_len == 0) | ||||
|     { | ||||
|         deref->path = NULL; | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     if (!(deref->path = hlsl_alloc(ctx, sizeof(*deref->path) * deref->path_len))) | ||||
|     { | ||||
|         deref->var = NULL; | ||||
|         deref->path_len = 0; | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| static struct hlsl_type *get_type_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref) | ||||
| { | ||||
|     struct hlsl_type *type; | ||||
|     unsigned int i; | ||||
|  | ||||
|     assert(deref); | ||||
|     assert(!deref->offset.node); | ||||
|  | ||||
|     type = deref->var->data_type; | ||||
|     for (i = 0; i < deref->path_len; ++i) | ||||
|         type = hlsl_get_inner_type_from_path_index(ctx, type, deref->path[i].node); | ||||
|     return type; | ||||
| } | ||||
|  | ||||
| /* Initializes a deref from another deref (prefix) and a component index. | ||||
|  * *block is initialized to contain the new constant node instructions used by the deref's path. */ | ||||
| static bool init_deref_from_component_index(struct hlsl_ctx *ctx, struct hlsl_block *block, | ||||
|         struct hlsl_deref *deref, const struct hlsl_deref *prefix, unsigned int index, | ||||
|         const struct vkd3d_shader_location *loc) | ||||
| { | ||||
|     unsigned int path_len, path_index, deref_path_len, i; | ||||
|     struct hlsl_type *path_type; | ||||
|     struct hlsl_ir_constant *c; | ||||
|  | ||||
|     list_init(&block->instrs); | ||||
|  | ||||
|     path_len = 0; | ||||
|     path_type = get_type_from_deref(ctx, prefix); | ||||
|     path_index = index; | ||||
|     while (!type_is_single_component(path_type)) | ||||
|     { | ||||
|         traverse_path_from_component_index(ctx, &path_type, &path_index); | ||||
|         ++path_len; | ||||
|     } | ||||
|  | ||||
|     if (!init_deref(ctx, deref, prefix->var, prefix->path_len + path_len)) | ||||
|         return false; | ||||
|  | ||||
|     deref_path_len = 0; | ||||
|     for (i = 0; i < prefix->path_len; ++i) | ||||
|         hlsl_src_from_node(&deref->path[deref_path_len++], prefix->path[i].node); | ||||
|  | ||||
|     path_type = get_type_from_deref(ctx, prefix); | ||||
|     path_index = index; | ||||
|     while (!type_is_single_component(path_type)) | ||||
|     { | ||||
|         unsigned int next_index = traverse_path_from_component_index(ctx, &path_type, &path_index); | ||||
|  | ||||
|         if (!(c = hlsl_new_uint_constant(ctx, next_index, loc))) | ||||
|         { | ||||
|             hlsl_free_instr_list(&block->instrs); | ||||
|             return false; | ||||
|         } | ||||
|         list_add_tail(&block->instrs, &c->node.entry); | ||||
|  | ||||
|         hlsl_src_from_node(&deref->path[deref_path_len++], &c->node); | ||||
|     } | ||||
|  | ||||
|     assert(deref_path_len == deref->path_len); | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| struct hlsl_type *hlsl_get_inner_type_from_path_index(struct hlsl_ctx *ctx, const struct hlsl_type *type, | ||||
|         struct hlsl_ir_node *idx) | ||||
| { | ||||
| @@ -435,6 +609,37 @@ struct hlsl_ir_node *hlsl_new_offset_from_path_index(struct hlsl_ctx *ctx, struc | ||||
|     return idx_offset; | ||||
| } | ||||
|  | ||||
| struct hlsl_ir_node *hlsl_new_offset_instr_from_deref(struct hlsl_ctx *ctx, struct hlsl_block *block, | ||||
|         const struct hlsl_deref *deref, const struct vkd3d_shader_location *loc) | ||||
| { | ||||
|     struct hlsl_ir_node *offset = NULL; | ||||
|     struct hlsl_type *type; | ||||
|     unsigned int i; | ||||
|  | ||||
|     list_init(&block->instrs); | ||||
|  | ||||
|     if (deref->offset.node) | ||||
|         return deref->offset.node; | ||||
|  | ||||
|     assert(deref->var); | ||||
|  | ||||
|     type = deref->var->data_type; | ||||
|  | ||||
|     for (i = 0; i < deref->path_len; ++i) | ||||
|     { | ||||
|         struct hlsl_block idx_block; | ||||
|  | ||||
|         if (!(offset = hlsl_new_offset_from_path_index(ctx, &idx_block, type, offset, deref->path[i].node, loc))) | ||||
|             return NULL; | ||||
|  | ||||
|         list_move_tail(&block->instrs, &idx_block.instrs); | ||||
|  | ||||
|         type = hlsl_get_inner_type_from_path_index(ctx, type, deref->path[i].node); | ||||
|     } | ||||
|  | ||||
|     return offset; | ||||
| } | ||||
|  | ||||
| struct hlsl_type *hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, unsigned int array_size) | ||||
| { | ||||
|     struct hlsl_type *type; | ||||
| @@ -525,7 +730,7 @@ struct hlsl_ir_function_decl *hlsl_get_func_decl(struct hlsl_ctx *ctx, const cha | ||||
|     return NULL; | ||||
| } | ||||
|  | ||||
| unsigned int hlsl_type_component_count(struct hlsl_type *type) | ||||
| unsigned int hlsl_type_component_count(const struct hlsl_type *type) | ||||
| { | ||||
|     unsigned int count = 0, i; | ||||
|  | ||||
| @@ -742,8 +947,17 @@ static bool type_is_single_reg(const struct hlsl_type *type) | ||||
|     return type->type == HLSL_CLASS_SCALAR || type->type == HLSL_CLASS_VECTOR; | ||||
| } | ||||
|  | ||||
| static void cleanup_deref(struct hlsl_deref *deref) | ||||
| void hlsl_cleanup_deref(struct hlsl_deref *deref) | ||||
| { | ||||
|     unsigned int i; | ||||
|  | ||||
|     for (i = 0; i < deref->path_len; ++i) | ||||
|         hlsl_src_remove(&deref->path[i]); | ||||
|     vkd3d_free(deref->path); | ||||
|  | ||||
|     deref->path = NULL; | ||||
|     deref->path_len = 0; | ||||
|  | ||||
|     hlsl_src_remove(&deref->offset); | ||||
| } | ||||
|  | ||||
| @@ -759,13 +973,20 @@ struct hlsl_ir_store *hlsl_new_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *v | ||||
|         return NULL; | ||||
|  | ||||
|     init_node(&store->node, HLSL_IR_STORE, NULL, loc); | ||||
|     store->lhs.var = var; | ||||
|     init_deref(ctx, &store->lhs, var, 0); | ||||
|     hlsl_src_from_node(&store->lhs.offset, offset); | ||||
|     hlsl_src_from_node(&store->rhs, rhs); | ||||
|     store->writemask = writemask; | ||||
|     return store; | ||||
| } | ||||
|  | ||||
| /* Initializes a simple variable derefence, so that it can be passed to load/store functions. */ | ||||
| void hlsl_init_simple_deref_from_var(struct hlsl_deref *deref, struct hlsl_ir_var *var) | ||||
| { | ||||
|     memset(deref, 0, sizeof(*deref)); | ||||
|     deref->var = var; | ||||
| } | ||||
|  | ||||
| struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs) | ||||
| { | ||||
|     return hlsl_new_store(ctx, lhs, NULL, rhs, 0, rhs->loc); | ||||
| @@ -862,15 +1083,76 @@ struct hlsl_ir_load *hlsl_new_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var | ||||
|     if (!(load = hlsl_alloc(ctx, sizeof(*load)))) | ||||
|         return NULL; | ||||
|     init_node(&load->node, HLSL_IR_LOAD, type, loc); | ||||
|     load->src.var = var; | ||||
|     init_deref(ctx, &load->src, var, 0); | ||||
|     hlsl_src_from_node(&load->src.offset, offset); | ||||
|     return load; | ||||
| } | ||||
|  | ||||
| struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, | ||||
|         const struct vkd3d_shader_location loc) | ||||
| struct hlsl_ir_load *hlsl_new_load_index(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, | ||||
|         struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc) | ||||
| { | ||||
|     return hlsl_new_load(ctx, var, NULL, var->data_type, loc); | ||||
|     struct hlsl_ir_load *load; | ||||
|     struct hlsl_type *type; | ||||
|     unsigned int i; | ||||
|  | ||||
|     assert(!deref->offset.node); | ||||
|  | ||||
|     type = get_type_from_deref(ctx, deref); | ||||
|     if (idx) | ||||
|         type = hlsl_get_inner_type_from_path_index(ctx, type, idx); | ||||
|  | ||||
|     if (!(load = hlsl_alloc(ctx, sizeof(*load)))) | ||||
|         return NULL; | ||||
|     init_node(&load->node, HLSL_IR_LOAD, type, *loc); | ||||
|  | ||||
|     if (!init_deref(ctx, &load->src, deref->var, deref->path_len + !!idx)) | ||||
|     { | ||||
|         vkd3d_free(load); | ||||
|         return NULL; | ||||
|     } | ||||
|     for (i = 0; i < deref->path_len; ++i) | ||||
|         hlsl_src_from_node(&load->src.path[i], deref->path[i].node); | ||||
|     if (idx) | ||||
|         hlsl_src_from_node(&load->src.path[deref->path_len], idx); | ||||
|  | ||||
|     return load; | ||||
| } | ||||
|  | ||||
| struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, | ||||
|         struct vkd3d_shader_location loc) | ||||
| { | ||||
|     struct hlsl_deref var_deref; | ||||
|  | ||||
|     hlsl_init_simple_deref_from_var(&var_deref, var); | ||||
|     return hlsl_new_load_index(ctx, &var_deref, NULL, &loc); | ||||
| } | ||||
|  | ||||
| struct hlsl_ir_load *hlsl_new_load_component(struct hlsl_ctx *ctx, struct hlsl_block *block, | ||||
|         const struct hlsl_deref *deref, unsigned int comp, const struct vkd3d_shader_location *loc) | ||||
| { | ||||
|     struct hlsl_type *type, *comp_type; | ||||
|     struct hlsl_block comp_path_block; | ||||
|     struct hlsl_ir_load *load; | ||||
|  | ||||
|     list_init(&block->instrs); | ||||
|  | ||||
|     if (!(load = hlsl_alloc(ctx, sizeof(*load)))) | ||||
|         return NULL; | ||||
|  | ||||
|     type = get_type_from_deref(ctx, deref); | ||||
|     comp_type = hlsl_type_get_component_type(ctx, type, comp); | ||||
|     init_node(&load->node, HLSL_IR_LOAD, comp_type, *loc); | ||||
|  | ||||
|     if (!init_deref_from_component_index(ctx, &comp_path_block, &load->src, deref, comp, loc)) | ||||
|     { | ||||
|         vkd3d_free(load); | ||||
|         return NULL; | ||||
|     } | ||||
|     list_move_tail(&block->instrs, &comp_path_block.instrs); | ||||
|  | ||||
|     list_add_tail(&block->instrs, &load->node.entry); | ||||
|  | ||||
|     return load; | ||||
| } | ||||
|  | ||||
| struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, struct hlsl_type *data_type, | ||||
| @@ -1705,7 +1987,7 @@ static void free_ir_jump(struct hlsl_ir_jump *jump) | ||||
|  | ||||
| static void free_ir_load(struct hlsl_ir_load *load) | ||||
| { | ||||
|     cleanup_deref(&load->src); | ||||
|     hlsl_cleanup_deref(&load->src); | ||||
|     vkd3d_free(load); | ||||
| } | ||||
|  | ||||
| @@ -1718,8 +2000,8 @@ static void free_ir_loop(struct hlsl_ir_loop *loop) | ||||
| static void free_ir_resource_load(struct hlsl_ir_resource_load *load) | ||||
| { | ||||
|     hlsl_src_remove(&load->coords); | ||||
|     cleanup_deref(&load->sampler); | ||||
|     cleanup_deref(&load->resource); | ||||
|     hlsl_cleanup_deref(&load->sampler); | ||||
|     hlsl_cleanup_deref(&load->resource); | ||||
|     hlsl_src_remove(&load->texel_offset); | ||||
|     vkd3d_free(load); | ||||
| } | ||||
| @@ -1727,7 +2009,7 @@ static void free_ir_resource_load(struct hlsl_ir_resource_load *load) | ||||
| static void free_ir_store(struct hlsl_ir_store *store) | ||||
| { | ||||
|     hlsl_src_remove(&store->rhs); | ||||
|     cleanup_deref(&store->lhs); | ||||
|     hlsl_cleanup_deref(&store->lhs); | ||||
|     vkd3d_free(store); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -374,6 +374,10 @@ struct hlsl_ir_swizzle | ||||
| struct hlsl_deref | ||||
| { | ||||
|     struct hlsl_ir_var *var; | ||||
|  | ||||
|     unsigned int path_len; | ||||
|     struct hlsl_src *path; | ||||
|  | ||||
|     struct hlsl_src offset; | ||||
| }; | ||||
|  | ||||
| @@ -717,6 +721,8 @@ void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl | ||||
| int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, | ||||
|         enum vkd3d_shader_target_type target_type, struct vkd3d_shader_code *out); | ||||
|  | ||||
| void hlsl_cleanup_deref(struct hlsl_deref *deref); | ||||
|  | ||||
| void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new); | ||||
|  | ||||
| void hlsl_free_instr(struct hlsl_ir_node *node); | ||||
| @@ -751,14 +757,29 @@ struct hlsl_ir_if *hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *condit | ||||
| struct hlsl_ir_constant *hlsl_new_int_constant(struct hlsl_ctx *ctx, int n, | ||||
|         const struct vkd3d_shader_location *loc); | ||||
| struct hlsl_ir_jump *hlsl_new_jump(struct hlsl_ctx *ctx, enum hlsl_ir_jump_type type, struct vkd3d_shader_location loc); | ||||
| struct hlsl_ir_load *hlsl_new_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset, | ||||
|         struct hlsl_type *type, struct vkd3d_shader_location loc); | ||||
| struct hlsl_ir_loop *hlsl_new_loop(struct hlsl_ctx *ctx, struct vkd3d_shader_location loc); | ||||
|  | ||||
| void hlsl_init_simple_deref_from_var(struct hlsl_deref *deref, struct hlsl_ir_var *var); | ||||
|  | ||||
| struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, | ||||
|         struct vkd3d_shader_location loc); | ||||
| struct hlsl_ir_load *hlsl_new_load_index(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, | ||||
|         struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc); | ||||
| struct hlsl_ir_load *hlsl_new_load_component(struct hlsl_ctx *ctx, struct hlsl_block *block, | ||||
|         const struct hlsl_deref *deref, unsigned int comp, const struct vkd3d_shader_location *loc); | ||||
|  | ||||
| struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs); | ||||
|  | ||||
| struct hlsl_ir_node *hlsl_new_offset_instr_from_deref(struct hlsl_ctx *ctx, struct hlsl_block *block, | ||||
|         const struct hlsl_deref *deref, const struct vkd3d_shader_location *loc); | ||||
|  | ||||
| struct hlsl_ir_resource_load *hlsl_new_resource_load(struct hlsl_ctx *ctx, struct hlsl_type *data_type, | ||||
|         enum hlsl_resource_load_type type, struct hlsl_ir_var *resource, struct hlsl_ir_node *resource_offset, | ||||
|         struct hlsl_ir_var *sampler, struct hlsl_ir_node *sampler_offset, struct hlsl_ir_node *coords, | ||||
|         struct hlsl_ir_node *texel_offset, const struct vkd3d_shader_location *loc); | ||||
| struct hlsl_ir_store *hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs); | ||||
|  | ||||
| struct hlsl_ir_load *hlsl_new_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset, | ||||
|         struct hlsl_type *type, struct vkd3d_shader_location loc); | ||||
| struct hlsl_ir_loop *hlsl_new_loop(struct hlsl_ctx *ctx, struct vkd3d_shader_location loc); | ||||
| struct hlsl_ir_store *hlsl_new_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct hlsl_ir_node *offset, | ||||
|         struct hlsl_ir_node *rhs, unsigned int writemask, struct vkd3d_shader_location loc); | ||||
| struct hlsl_type *hlsl_new_struct_type(struct hlsl_ctx *ctx, const char *name, | ||||
| @@ -775,8 +796,6 @@ struct hlsl_ir_node *hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr | ||||
| struct hlsl_ir_var *hlsl_new_var(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type, | ||||
|         const struct vkd3d_shader_location loc, const struct hlsl_semantic *semantic, unsigned int modifiers, | ||||
|         const struct hlsl_reg_reservation *reg_reservation); | ||||
| struct hlsl_ir_load *hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, | ||||
|         const struct vkd3d_shader_location loc); | ||||
|  | ||||
| void hlsl_error(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc, | ||||
|         enum vkd3d_shader_error error, const char *fmt, ...) VKD3D_PRINTF_FUNC(4, 5); | ||||
| @@ -794,10 +813,12 @@ bool hlsl_scope_add_type(struct hlsl_scope *scope, struct hlsl_type *type); | ||||
|  | ||||
| struct hlsl_type *hlsl_type_clone(struct hlsl_ctx *ctx, struct hlsl_type *old, | ||||
|         unsigned int default_majority, unsigned int modifiers); | ||||
| unsigned int hlsl_type_component_count(struct hlsl_type *type); | ||||
| unsigned int hlsl_type_component_count(const struct hlsl_type *type); | ||||
| unsigned int hlsl_type_get_array_element_reg_size(const struct hlsl_type *type); | ||||
| unsigned int hlsl_compute_component_offset(struct hlsl_ctx *ctx, struct hlsl_type *type, | ||||
|         unsigned int idx, struct hlsl_type **comp_type); | ||||
| struct hlsl_type *hlsl_type_get_component_type(struct hlsl_ctx *ctx, struct hlsl_type *type, | ||||
|         unsigned int index); | ||||
| bool hlsl_type_is_row_major(const struct hlsl_type *type); | ||||
| unsigned int hlsl_type_minor_size(const struct hlsl_type *type); | ||||
| unsigned int hlsl_type_major_size(const struct hlsl_type *type); | ||||
|   | ||||
| @@ -352,7 +352,7 @@ static struct hlsl_ir_node *add_cast(struct hlsl_ctx *ctx, struct list *instrs, | ||||
|             list_add_tail(instrs, &store->node.entry); | ||||
|         } | ||||
|  | ||||
|         if (!(load = hlsl_new_load(ctx, var, NULL, dst_type, *loc))) | ||||
|         if (!(load = hlsl_new_var_load(ctx, var, *loc))) | ||||
|             return NULL; | ||||
|         list_add_tail(instrs, &load->node.entry); | ||||
|  | ||||
| @@ -625,31 +625,18 @@ static struct hlsl_ir_jump *add_return(struct hlsl_ctx *ctx, struct list *instrs | ||||
| static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_instr, | ||||
|         struct hlsl_ir_node *idx, const struct vkd3d_shader_location *loc) | ||||
| { | ||||
|     struct hlsl_type *elem_type; | ||||
|     struct hlsl_ir_node *offset; | ||||
|     const struct hlsl_deref *src; | ||||
|     struct hlsl_ir_load *load; | ||||
|     struct hlsl_block block; | ||||
|     struct hlsl_ir_var *var; | ||||
|  | ||||
|     elem_type = hlsl_get_inner_type_from_path_index(ctx, var_instr->data_type, idx); | ||||
|  | ||||
|     if (var_instr->type == HLSL_IR_LOAD) | ||||
|     { | ||||
|         const struct hlsl_deref *src = &hlsl_ir_load(var_instr)->src; | ||||
|  | ||||
|         var = src->var; | ||||
|         if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, var_instr->data_type, src->offset.node, idx, loc))) | ||||
|             return NULL; | ||||
|         list_move_tail(instrs, &block.instrs); | ||||
|         src = &hlsl_ir_load(var_instr)->src; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         struct vkd3d_string_buffer *name; | ||||
|         struct hlsl_ir_store *store; | ||||
|  | ||||
|         if (!(offset = hlsl_new_offset_from_path_index(ctx, &block, var_instr->data_type, NULL, idx, loc))) | ||||
|             return NULL; | ||||
|         list_move_tail(instrs, &block.instrs); | ||||
|         struct hlsl_ir_var *var; | ||||
|  | ||||
|         if (!(name = hlsl_get_string_buffer(ctx))) | ||||
|             return NULL; | ||||
| @@ -662,9 +649,11 @@ static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *in | ||||
|         if (!(store = hlsl_new_simple_store(ctx, var, var_instr))) | ||||
|             return NULL; | ||||
|         list_add_tail(instrs, &store->node.entry); | ||||
|  | ||||
|         src = &store->lhs; | ||||
|     } | ||||
|  | ||||
|     if (!(load = hlsl_new_load(ctx, var, offset, elem_type, *loc))) | ||||
|     if (!(load = hlsl_new_load_index(ctx, src, idx, loc))) | ||||
|         return NULL; | ||||
|     list_add_tail(instrs, &load->node.entry); | ||||
|  | ||||
| @@ -674,39 +663,19 @@ static struct hlsl_ir_load *add_load_index(struct hlsl_ctx *ctx, struct list *in | ||||
| static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list *instrs, struct hlsl_ir_node *var_instr, | ||||
|         unsigned int comp, const struct vkd3d_shader_location *loc) | ||||
| { | ||||
|     struct hlsl_type *comp_type; | ||||
|     struct hlsl_ir_node *offset; | ||||
|     struct hlsl_ir_constant *c; | ||||
|     const struct hlsl_deref *src; | ||||
|     struct hlsl_ir_load *load; | ||||
|     unsigned int comp_offset; | ||||
|     struct hlsl_ir_var *var; | ||||
|  | ||||
|     comp_offset = hlsl_compute_component_offset(ctx, var_instr->data_type, comp, &comp_type); | ||||
|  | ||||
|     if (!(c = hlsl_new_uint_constant(ctx, comp_offset, loc))) | ||||
|         return NULL; | ||||
|     list_add_tail(instrs, &c->node.entry); | ||||
|  | ||||
|     offset = &c->node; | ||||
|     struct hlsl_block block; | ||||
|  | ||||
|     if (var_instr->type == HLSL_IR_LOAD) | ||||
|     { | ||||
|         const struct hlsl_deref *src = &hlsl_ir_load(var_instr)->src; | ||||
|         struct hlsl_ir_node *add; | ||||
|  | ||||
|         var = src->var; | ||||
|         if (src->offset.node) | ||||
|         { | ||||
|             if (!(add = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, src->offset.node, &c->node))) | ||||
|                 return NULL; | ||||
|             list_add_tail(instrs, &add->entry); | ||||
|             offset = add; | ||||
|         } | ||||
|         src = &hlsl_ir_load(var_instr)->src; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         struct vkd3d_string_buffer *name; | ||||
|         struct hlsl_ir_store *store; | ||||
|         struct hlsl_ir_var *var; | ||||
|  | ||||
|         if (!(name = hlsl_get_string_buffer(ctx))) | ||||
|             return NULL; | ||||
| @@ -719,11 +688,13 @@ static struct hlsl_ir_load *add_load_component(struct hlsl_ctx *ctx, struct list | ||||
|         if (!(store = hlsl_new_simple_store(ctx, var, var_instr))) | ||||
|             return NULL; | ||||
|         list_add_tail(instrs, &store->node.entry); | ||||
|  | ||||
|         src = &store->lhs; | ||||
|     } | ||||
|  | ||||
|     if (!(load = hlsl_new_load(ctx, var, offset, comp_type, *loc))) | ||||
|     if (!(load = hlsl_new_load_component(ctx, &block, src, comp, loc))) | ||||
|         return NULL; | ||||
|     list_add_tail(instrs, &load->node.entry); | ||||
|     list_move_tail(instrs, &block.instrs); | ||||
|  | ||||
|     return load; | ||||
| } | ||||
| @@ -1277,7 +1248,7 @@ static struct hlsl_ir_node *add_expr(struct hlsl_ctx *ctx, struct list *instrs, | ||||
|             list_add_tail(instrs, &store->node.entry); | ||||
|         } | ||||
|  | ||||
|         if (!(load = hlsl_new_load(ctx, var, NULL, type, *loc))) | ||||
|         if (!(load = hlsl_new_var_load(ctx, var, *loc))) | ||||
|             return NULL; | ||||
|         list_add_tail(instrs, &load->node.entry); | ||||
|  | ||||
| @@ -1634,8 +1605,10 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in | ||||
| { | ||||
|     struct hlsl_type *lhs_type = lhs->data_type; | ||||
|     struct hlsl_ir_store *store; | ||||
|     struct hlsl_ir_node *offset; | ||||
|     struct hlsl_ir_expr *copy; | ||||
|     unsigned int writemask = 0; | ||||
|     struct hlsl_block block; | ||||
|  | ||||
|     if (assign_op == ASSIGN_OP_SUB) | ||||
|     { | ||||
| @@ -1704,10 +1677,13 @@ static struct hlsl_ir_node *add_assignment(struct hlsl_ctx *ctx, struct list *in | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     offset = hlsl_new_offset_instr_from_deref(ctx, &block, &hlsl_ir_load(lhs)->src, &lhs->loc); | ||||
|     list_move_tail(instrs, &block.instrs); | ||||
|  | ||||
|     init_node(&store->node, HLSL_IR_STORE, NULL, lhs->loc); | ||||
|     store->writemask = writemask; | ||||
|     store->lhs.var = hlsl_ir_load(lhs)->src.var; | ||||
|     hlsl_src_from_node(&store->lhs.offset, hlsl_ir_load(lhs)->src.offset.node); | ||||
|     hlsl_src_from_node(&store->lhs.offset, offset); | ||||
|     hlsl_src_from_node(&store->rhs, rhs); | ||||
|     list_add_tail(instrs, &store->node.entry); | ||||
|  | ||||
| @@ -2238,7 +2214,7 @@ static bool intrinsic_mul(struct hlsl_ctx *ctx, | ||||
|             list_add_tail(params->instrs, &store->node.entry); | ||||
|         } | ||||
|  | ||||
|     if (!(load = hlsl_new_load(ctx, var, NULL, matrix_type, *loc))) | ||||
|     if (!(load = hlsl_new_var_load(ctx, var, *loc))) | ||||
|         return false; | ||||
|     list_add_tail(params->instrs, &load->node.entry); | ||||
|  | ||||
| @@ -2447,8 +2423,10 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl | ||||
|             && object_type->sampler_dim != HLSL_SAMPLER_DIM_CUBEARRAY) | ||||
|     { | ||||
|         const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); | ||||
|         struct hlsl_ir_node *object_load_offset; | ||||
|         struct hlsl_ir_resource_load *load; | ||||
|         struct hlsl_ir_node *coords; | ||||
|         struct hlsl_block block; | ||||
|  | ||||
|         if (object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMS | ||||
|                 || object_type->sampler_dim == HLSL_SAMPLER_DIM_2DMSARRAY) | ||||
| @@ -2473,8 +2451,11 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl | ||||
|                 hlsl_get_vector_type(ctx, HLSL_TYPE_INT, sampler_dim + 1), loc))) | ||||
|             return false; | ||||
|  | ||||
|         object_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &object_load->src, loc); | ||||
|         list_move_tail(instrs, &block.instrs); | ||||
|  | ||||
|         if (!(load = hlsl_new_resource_load(ctx, object_type->e.resource_format, HLSL_RESOURCE_LOAD, | ||||
|                 object_load->src.var, object_load->src.offset.node, NULL, NULL, coords, NULL, loc))) | ||||
|                 object_load->src.var, object_load_offset, NULL, NULL, coords, NULL, loc))) | ||||
|             return false; | ||||
|         list_add_tail(instrs, &load->node.entry); | ||||
|         return true; | ||||
| @@ -2484,11 +2465,13 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl | ||||
|             && object_type->sampler_dim != HLSL_SAMPLER_DIM_2DMSARRAY) | ||||
|     { | ||||
|         const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); | ||||
|         struct hlsl_ir_node *object_load_offset, *sampler_load_offset; | ||||
|         const struct hlsl_type *sampler_type; | ||||
|         struct hlsl_ir_resource_load *load; | ||||
|         struct hlsl_ir_node *offset = NULL; | ||||
|         struct hlsl_ir_load *sampler_load; | ||||
|         struct hlsl_ir_node *coords; | ||||
|         struct hlsl_block block; | ||||
|  | ||||
|         if (params->args_count != 2 && params->args_count != 3) | ||||
|         { | ||||
| @@ -2524,11 +2507,18 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl | ||||
|                 return false; | ||||
|         } | ||||
|  | ||||
|         object_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &object_load->src, loc); | ||||
|         list_move_tail(instrs, &block.instrs); | ||||
|  | ||||
|         sampler_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &sampler_load->src, loc); | ||||
|         list_move_tail(instrs, &block.instrs); | ||||
|  | ||||
|         if (!(load = hlsl_new_resource_load(ctx, object_type->e.resource_format, | ||||
|                 HLSL_RESOURCE_SAMPLE, object_load->src.var, object_load->src.offset.node, | ||||
|                 sampler_load->src.var, sampler_load->src.offset.node, coords, offset, loc))) | ||||
|                 HLSL_RESOURCE_SAMPLE, object_load->src.var, object_load_offset, | ||||
|                 sampler_load->src.var, sampler_load_offset, coords, offset, loc))) | ||||
|             return false; | ||||
|         list_add_tail(instrs, &load->node.entry); | ||||
|  | ||||
|         return true; | ||||
|     } | ||||
|     else if ((!strcmp(name, "Gather") || !strcmp(name, "GatherRed") || !strcmp(name, "GatherBlue") | ||||
| @@ -2539,6 +2529,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl | ||||
|             || object_type->sampler_dim == HLSL_SAMPLER_DIM_CUBEARRAY)) | ||||
|     { | ||||
|         const unsigned int sampler_dim = hlsl_sampler_dim_count(object_type->sampler_dim); | ||||
|         struct hlsl_ir_node *object_load_offset, *sampler_load_offset; | ||||
|         enum hlsl_resource_load_type load_type; | ||||
|         const struct hlsl_type *sampler_type; | ||||
|         struct hlsl_ir_resource_load *load; | ||||
| @@ -2547,6 +2538,7 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl | ||||
|         struct hlsl_type *result_type; | ||||
|         struct hlsl_ir_node *coords; | ||||
|         unsigned int read_channel; | ||||
|         struct hlsl_block block; | ||||
|  | ||||
|         if (!strcmp(name, "GatherGreen")) | ||||
|         { | ||||
| @@ -2628,9 +2620,15 @@ static bool add_method_call(struct hlsl_ctx *ctx, struct list *instrs, struct hl | ||||
|                 hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, sampler_dim), loc))) | ||||
|             return false; | ||||
|  | ||||
|         object_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &object_load->src, loc); | ||||
|         list_move_tail(instrs, &block.instrs); | ||||
|  | ||||
|         sampler_load_offset = hlsl_new_offset_instr_from_deref(ctx, &block, &sampler_load->src, loc); | ||||
|         list_move_tail(instrs, &block.instrs); | ||||
|  | ||||
|         if (!(load = hlsl_new_resource_load(ctx, result_type, | ||||
|                 load_type, object_load->src.var, object_load->src.offset.node, | ||||
|                 sampler_load->src.var, sampler_load->src.offset.node, coords, offset, loc))) | ||||
|                 load_type, object_load->src.var, object_load_offset, | ||||
|                 sampler_load->src.var, sampler_load_offset, coords, offset, loc))) | ||||
|             return false; | ||||
|         list_add_tail(instrs, &load->node.entry); | ||||
|         return true; | ||||
|   | ||||
| @@ -21,6 +21,48 @@ | ||||
| #include "hlsl.h" | ||||
| #include <stdio.h> | ||||
|  | ||||
| /* TODO: remove when no longer needed, only used for transform_deref_paths_into_offsets() */ | ||||
| static void replace_deref_path_with_offset(struct hlsl_ctx *ctx, struct hlsl_deref *deref, | ||||
|         struct hlsl_ir_node *instr) | ||||
| { | ||||
|     struct hlsl_ir_node *offset; | ||||
|     struct hlsl_block block; | ||||
|  | ||||
|     if (!deref->var) | ||||
|         return; | ||||
|  | ||||
|     if (!(offset = hlsl_new_offset_instr_from_deref(ctx, &block, deref, &instr->loc))) | ||||
|         return; | ||||
|     list_move_before(&instr->entry, &block.instrs); | ||||
|  | ||||
|     hlsl_cleanup_deref(deref); | ||||
|     hlsl_src_from_node(&deref->offset, offset); | ||||
| } | ||||
|  | ||||
| /* TODO: remove when no longer needed. */ | ||||
| static bool transform_deref_paths_into_offsets(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context) | ||||
| { | ||||
|     switch(instr->type) | ||||
|     { | ||||
|         case HLSL_IR_LOAD: | ||||
|             replace_deref_path_with_offset(ctx, &hlsl_ir_load(instr)->src, instr); | ||||
|             return true; | ||||
|  | ||||
|         case HLSL_IR_STORE: | ||||
|             replace_deref_path_with_offset(ctx, &hlsl_ir_store(instr)->lhs, instr); | ||||
|             return true; | ||||
|  | ||||
|         case HLSL_IR_RESOURCE_LOAD: | ||||
|             replace_deref_path_with_offset(ctx, &hlsl_ir_resource_load(instr)->resource, instr); | ||||
|             replace_deref_path_with_offset(ctx, &hlsl_ir_resource_load(instr)->sampler, instr); | ||||
|             return true; | ||||
|  | ||||
|         default: | ||||
|             return false; | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /* Split uniforms into two variables representing the constant and temp | ||||
|  * registers, and copy the former to the latter, so that writes to uniforms | ||||
|  * work. */ | ||||
| @@ -1890,6 +1932,8 @@ int hlsl_emit_bytecode(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry | ||||
|  | ||||
|     list_move_head(&body->instrs, &ctx->static_initializers); | ||||
|  | ||||
|     transform_ir(ctx, transform_deref_paths_into_offsets, body, NULL); /* TODO: move forward, remove when no longer needed */ | ||||
|  | ||||
|     LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry) | ||||
|     { | ||||
|         if (var->modifiers & HLSL_STORAGE_UNIFORM) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user