ReactOS 0.4.17-dev-923-g4c9a150
hlsl_codegen.c
Go to the documentation of this file.
1/*
2 * HLSL optimization and code generation
3 *
4 * Copyright 2019-2020 Zebediah Figura for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#include "hlsl.h"
22#include <stdio.h>
23#include <math.h>
24
25/* TODO: remove when no longer needed, only used for new_offset_instr_from_deref() */
27 struct hlsl_type *type, struct hlsl_ir_node *base_offset, struct hlsl_ir_node *idx,
28 enum hlsl_regset regset, unsigned int *offset_component, const struct vkd3d_shader_location *loc)
29{
30 struct hlsl_ir_node *idx_offset = NULL;
31 struct hlsl_ir_node *c;
32
33 switch (type->class)
34 {
36 if (idx->type != HLSL_IR_CONSTANT)
37 {
38 hlsl_fixme(ctx, &idx->loc, "Non-constant vector addressing.");
39 break;
40 }
41 *offset_component += hlsl_ir_constant(idx)->value.u[0].u;
42 break;
43
45 {
46 idx_offset = idx;
47 break;
48 }
49
51 {
52 unsigned int size = hlsl_type_get_array_element_reg_size(type->e.array.type, regset);
53
55 {
56 VKD3D_ASSERT(size % 4 == 0);
57 size /= 4;
58 }
59
61 return NULL;
63
64 if (!(idx_offset = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, c, idx)))
65 return NULL;
66 hlsl_block_add_instr(block, idx_offset);
67
68 break;
69 }
70
72 {
73 unsigned int field_idx = hlsl_ir_constant(idx)->value.u[0].u;
74 struct hlsl_struct_field *field = &type->e.record.fields[field_idx];
75 unsigned int field_offset = field->reg_offset[regset];
76
78 {
79 VKD3D_ASSERT(*offset_component == 0);
80 *offset_component = field_offset % 4;
81 field_offset /= 4;
82 }
83
84 if (!(c = hlsl_new_uint_constant(ctx, field_offset, loc)))
85 return NULL;
87
88 idx_offset = c;
89
90 break;
91 }
92
93 default:
95 }
96
97 if (idx_offset)
98 {
99 if (!(base_offset = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, base_offset, idx_offset)))
100 return NULL;
101 hlsl_block_add_instr(block, base_offset);
102 }
103
104 return base_offset;
105}
106
107/* TODO: remove when no longer needed, only used for replace_deref_path_with_offset() */
109 const struct hlsl_deref *deref, unsigned int *offset_component, const struct vkd3d_shader_location *loc)
110{
112 struct hlsl_ir_node *offset;
113 struct hlsl_type *type;
114 unsigned int i;
115
116 *offset_component = 0;
117
119
120 if (!(offset = hlsl_new_uint_constant(ctx, 0, loc)))
121 return NULL;
123
124 VKD3D_ASSERT(deref->var);
125 type = deref->var->data_type;
126
127 for (i = 0; i < deref->path_len; ++i)
128 {
129 struct hlsl_block idx_block;
130
131 hlsl_block_init(&idx_block);
132
133 if (!(offset = new_offset_from_path_index(ctx, &idx_block, type, offset, deref->path[i].node,
134 regset, offset_component, loc)))
135 {
136 hlsl_block_cleanup(&idx_block);
137 return NULL;
138 }
139
140 hlsl_block_add_block(block, &idx_block);
141
143 }
144
145 return offset;
146}
147
148/* TODO: remove when no longer needed, only used for transform_deref_paths_into_offsets() */
149static bool replace_deref_path_with_offset(struct hlsl_ctx *ctx, struct hlsl_deref *deref,
150 struct hlsl_ir_node *instr)
151{
152 unsigned int offset_component;
153 struct hlsl_ir_node *offset;
154 struct hlsl_block block;
155 struct hlsl_type *type;
156
157 VKD3D_ASSERT(deref->var);
159
160 type = hlsl_deref_get_type(ctx, deref);
161
162 /* Instructions that directly refer to structs or arrays (instead of single-register components)
163 * are removed later by dce. So it is not a problem to just cleanup their derefs. */
164 if (type->class == HLSL_CLASS_STRUCT || type->class == HLSL_CLASS_ARRAY)
165 {
166 hlsl_cleanup_deref(deref);
167 return true;
168 }
169
170 deref->data_type = type;
171
172 if (!(offset = new_offset_instr_from_deref(ctx, &block, deref, &offset_component, &instr->loc)))
173 return false;
174 list_move_before(&instr->entry, &block.instrs);
175
176 hlsl_cleanup_deref(deref);
178 deref->const_offset = offset_component;
179
180 return true;
181}
182
183static bool clean_constant_deref_offset_srcs(struct hlsl_ctx *ctx, struct hlsl_deref *deref,
184 struct hlsl_ir_node *instr)
185{
186 if (deref->rel_offset.node && deref->rel_offset.node->type == HLSL_IR_CONSTANT)
187 {
189
191 deref->const_offset += 4 * hlsl_ir_constant(deref->rel_offset.node)->value.u[0].u;
192 else
193 deref->const_offset += hlsl_ir_constant(deref->rel_offset.node)->value.u[0].u;
195 return true;
196 }
197 return false;
198}
199
200
201/* Split uniforms into two variables representing the constant and temp
202 * registers, and copy the former to the latter, so that writes to uniforms
203 * work. */
204static void prepend_uniform_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_var *temp)
205{
206 struct hlsl_ir_var *uniform;
207 struct hlsl_ir_node *store;
208 struct hlsl_ir_load *load;
209 char *new_name;
210
211 /* Use the synthetic name for the temp, rather than the uniform, so that we
212 * can write the uniform name into the shader reflection data. */
213
214 if (!(uniform = hlsl_new_var(ctx, temp->name, temp->data_type,
215 &temp->loc, NULL, temp->storage_modifiers, &temp->reg_reservation)))
216 return;
217 list_add_before(&temp->scope_entry, &uniform->scope_entry);
218 list_add_tail(&ctx->extern_vars, &uniform->extern_entry);
219 uniform->is_uniform = 1;
220 uniform->is_param = temp->is_param;
221 uniform->buffer = temp->buffer;
222 if (temp->default_values)
223 {
224 /* Transfer default values from the temp to the uniform. */
225 VKD3D_ASSERT(!uniform->default_values);
227 uniform->default_values = temp->default_values;
228 temp->default_values = NULL;
229 }
230
231 if (!(new_name = hlsl_sprintf_alloc(ctx, "<temp-%s>", temp->name)))
232 return;
233 temp->name = new_name;
234
235 if (!(load = hlsl_new_var_load(ctx, uniform, &temp->loc)))
236 return;
237 list_add_head(&block->instrs, &load->node.entry);
238
239 if (!(store = hlsl_new_simple_store(ctx, temp, &load->node)))
240 return;
241 list_add_after(&load->node.entry, &store->entry);
242}
243
245{
247 && !field->semantic.reported_missing)
248 {
250 "Field '%s' is missing a semantic.", field->name);
251 field->semantic.reported_missing = true;
252 }
253}
254
256{
257 if (base == HLSL_TYPE_BOOL)
258 return HLSL_TYPE_UINT;
259 if (base == HLSL_TYPE_INT)
260 return HLSL_TYPE_UINT;
261 if (base == HLSL_TYPE_HALF)
262 return HLSL_TYPE_FLOAT;
263 return base;
264}
265
266static bool types_are_semantic_equivalent(struct hlsl_ctx *ctx, const struct hlsl_type *type1,
267 const struct hlsl_type *type2)
268{
269 if (ctx->profile->major_version < 4)
270 return true;
271
272 if (type1->dimx != type2->dimx)
273 return false;
274
277}
278
280 struct hlsl_ir_var *var, struct hlsl_type *type, uint32_t modifiers, struct hlsl_semantic *semantic,
281 uint32_t index, bool output, bool force_align, const struct vkd3d_shader_location *loc)
282{
283 struct hlsl_semantic new_semantic;
284 struct hlsl_ir_var *ext_var;
285 char *new_name;
286
287 if (!(new_name = hlsl_sprintf_alloc(ctx, "<%s-%s%u>", output ? "output" : "input", semantic->name, index)))
288 return NULL;
289
290 LIST_FOR_EACH_ENTRY(ext_var, &func->extern_vars, struct hlsl_ir_var, extern_entry)
291 {
292 if (!ascii_strcasecmp(ext_var->name, new_name))
293 {
294 if (output)
295 {
296 if (index >= semantic->reported_duplicated_output_next_index)
297 {
299 "Output semantic \"%s%u\" is used multiple times.", semantic->name, index);
301 "First use of \"%s%u\" is here.", semantic->name, index);
302 semantic->reported_duplicated_output_next_index = index + 1;
303 }
304 }
305 else
306 {
307 if (index >= semantic->reported_duplicated_input_incompatible_next_index
309 {
311 "Input semantic \"%s%u\" is used multiple times with incompatible types.",
312 semantic->name, index);
314 "First declaration of \"%s%u\" is here.", semantic->name, index);
315 semantic->reported_duplicated_input_incompatible_next_index = index + 1;
316 }
317 }
318
319 vkd3d_free(new_name);
320 return ext_var;
321 }
322 }
323
324 if (!(hlsl_clone_semantic(ctx, &new_semantic, semantic)))
325 {
326 vkd3d_free(new_name);
327 return NULL;
328 }
329 new_semantic.index = index;
330 if (!(ext_var = hlsl_new_var(ctx, new_name, type, loc, &new_semantic, modifiers, NULL)))
331 {
332 vkd3d_free(new_name);
333 hlsl_cleanup_semantic(&new_semantic);
334 return NULL;
335 }
336 if (output)
337 ext_var->is_output_semantic = 1;
338 else
339 ext_var->is_input_semantic = 1;
340 ext_var->is_param = var->is_param;
341 ext_var->force_align = force_align;
342 list_add_before(&var->scope_entry, &ext_var->scope_entry);
343 list_add_tail(&func->extern_vars, &ext_var->extern_entry);
344
345 return ext_var;
346}
347
349{
350 field_modifiers |= modifiers;
351
352 /* TODO: 'sample' modifier is not supported yet. */
353
354 /* 'nointerpolation' always takes precedence, next the same is done for
355 * 'sample', remaining modifiers are combined. */
356 if (field_modifiers & HLSL_STORAGE_NOINTERPOLATION)
357 {
358 field_modifiers &= ~HLSL_INTERPOLATION_MODIFIERS_MASK;
359 field_modifiers |= HLSL_STORAGE_NOINTERPOLATION;
360 }
361
362 return field_modifiers;
363}
364
365static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_load *lhs,
366 uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align)
367{
368 struct hlsl_type *type = lhs->node.data_type, *vector_type_src, *vector_type_dst;
369 struct vkd3d_shader_location *loc = &lhs->node.loc;
370 struct hlsl_ir_var *var = lhs->src.var;
371 struct hlsl_ir_node *c;
372 unsigned int i;
373
375 {
377 if (!(string = hlsl_type_to_string(ctx, type)))
378 return;
379 hlsl_fixme(ctx, &var->loc, "Input semantics for type %s.", string->buffer);
381 }
382 if (!semantic->name)
383 return;
384
385 vector_type_dst = hlsl_get_vector_type(ctx, type->e.numeric.type, hlsl_type_minor_size(type));
386 vector_type_src = vector_type_dst;
387 if (ctx->profile->major_version < 4 && ctx->profile->type == VKD3D_SHADER_TYPE_VERTEX)
388 vector_type_src = hlsl_get_vector_type(ctx, type->e.numeric.type, 4);
389
390 if (hlsl_type_major_size(type) > 1)
391 force_align = true;
392
393 for (i = 0; i < hlsl_type_major_size(type); ++i)
394 {
395 struct hlsl_ir_node *store, *cast;
396 struct hlsl_ir_var *input;
397 struct hlsl_ir_load *load;
398
399 if (!(input = add_semantic_var(ctx, func, var, vector_type_src,
400 modifiers, semantic, semantic_index + i, false, force_align, loc)))
401 return;
402
403 if (!(load = hlsl_new_var_load(ctx, input, &var->loc)))
404 return;
405 list_add_after(&lhs->node.entry, &load->node.entry);
406
407 if (!(cast = hlsl_new_cast(ctx, &load->node, vector_type_dst, &var->loc)))
408 return;
409 list_add_after(&load->node.entry, &cast->entry);
410
411 if (type->class == HLSL_CLASS_MATRIX)
412 {
413 if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc)))
414 return;
415 list_add_after(&cast->entry, &c->entry);
416
417 if (!(store = hlsl_new_store_index(ctx, &lhs->src, c, cast, 0, &var->loc)))
418 return;
419 list_add_after(&c->entry, &store->entry);
420 }
421 else
422 {
423 VKD3D_ASSERT(i == 0);
424
425 if (!(store = hlsl_new_store_index(ctx, &lhs->src, NULL, cast, 0, &var->loc)))
426 return;
427 list_add_after(&cast->entry, &store->entry);
428 }
429 }
430}
431
433 struct hlsl_ir_function_decl *func, struct hlsl_ir_load *lhs, uint32_t modifiers,
434 struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align)
435{
436 struct vkd3d_shader_location *loc = &lhs->node.loc;
437 struct hlsl_type *type = lhs->node.data_type;
438 struct hlsl_ir_var *var = lhs->src.var;
439 struct hlsl_ir_node *c;
440 unsigned int i;
441
442 if (type->class == HLSL_CLASS_ARRAY || type->class == HLSL_CLASS_STRUCT)
443 {
444 struct hlsl_ir_load *element_load;
445 struct hlsl_struct_field *field;
446 uint32_t elem_semantic_index;
447
448 for (i = 0; i < hlsl_type_element_count(type); ++i)
449 {
450 uint32_t element_modifiers;
451
452 if (type->class == HLSL_CLASS_ARRAY)
453 {
454 elem_semantic_index = semantic_index
456 element_modifiers = modifiers;
457 force_align = true;
458 }
459 else
460 {
461 field = &type->e.record.fields[i];
463 {
464 hlsl_fixme(ctx, &field->loc, "Prepend uniform copies for resource components within structs.");
465 continue;
466 }
468 semantic = &field->semantic;
469 elem_semantic_index = semantic->index;
470 loc = &field->loc;
471 element_modifiers = combine_field_storage_modifiers(modifiers, field->storage_modifiers);
472 force_align = (i == 0);
473 }
474
475 if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc)))
476 return;
477 list_add_after(&lhs->node.entry, &c->entry);
478
479 /* This redundant load is expected to be deleted later by DCE. */
480 if (!(element_load = hlsl_new_load_index(ctx, &lhs->src, c, loc)))
481 return;
482 list_add_after(&c->entry, &element_load->node.entry);
483
484 prepend_input_copy_recurse(ctx, func, element_load, element_modifiers,
485 semantic, elem_semantic_index, force_align);
486 }
487 }
488 else
489 {
490 prepend_input_copy(ctx, func, lhs, modifiers, semantic, semantic_index, force_align);
491 }
492}
493
494/* Split inputs into two variables representing the semantic and temp registers,
495 * and copy the former to the latter, so that writes to input variables work. */
497{
498 struct hlsl_ir_load *load;
499
500 /* This redundant load is expected to be deleted later by DCE. */
501 if (!(load = hlsl_new_var_load(ctx, var, &var->loc)))
502 return;
503 list_add_head(&func->body.instrs, &load->node.entry);
504
505 prepend_input_copy_recurse(ctx, func, load, var->storage_modifiers, &var->semantic, var->semantic.index, false);
506}
507
509 struct hlsl_ir_load *rhs, uint32_t modifiers,
510 struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align)
511{
512 struct hlsl_type *type = rhs->node.data_type, *vector_type;
513 struct vkd3d_shader_location *loc = &rhs->node.loc;
514 struct hlsl_ir_var *var = rhs->src.var;
515 struct hlsl_ir_node *c;
516 unsigned int i;
517
519 {
521 if (!(string = hlsl_type_to_string(ctx, type)))
522 return;
523 hlsl_fixme(ctx, &var->loc, "Output semantics for type %s.", string->buffer);
525 }
526 if (!semantic->name)
527 return;
528
529 vector_type = hlsl_get_vector_type(ctx, type->e.numeric.type, hlsl_type_minor_size(type));
530
531 if (hlsl_type_major_size(type) > 1)
532 force_align = true;
533
534 for (i = 0; i < hlsl_type_major_size(type); ++i)
535 {
536 struct hlsl_ir_node *store;
537 struct hlsl_ir_var *output;
538 struct hlsl_ir_load *load;
539
540 if (!(output = add_semantic_var(ctx, func, var, vector_type,
541 modifiers, semantic, semantic_index + i, true, force_align, loc)))
542 return;
543
544 if (type->class == HLSL_CLASS_MATRIX)
545 {
546 if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc)))
547 return;
548 hlsl_block_add_instr(&func->body, c);
549
550 if (!(load = hlsl_new_load_index(ctx, &rhs->src, c, &var->loc)))
551 return;
552 hlsl_block_add_instr(&func->body, &load->node);
553 }
554 else
555 {
556 VKD3D_ASSERT(i == 0);
557
558 if (!(load = hlsl_new_load_index(ctx, &rhs->src, NULL, &var->loc)))
559 return;
560 hlsl_block_add_instr(&func->body, &load->node);
561 }
562
563 if (!(store = hlsl_new_simple_store(ctx, output, &load->node)))
564 return;
565 hlsl_block_add_instr(&func->body, store);
566 }
567}
568
570 struct hlsl_ir_function_decl *func, struct hlsl_ir_load *rhs, uint32_t modifiers,
571 struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align)
572{
573 struct vkd3d_shader_location *loc = &rhs->node.loc;
574 struct hlsl_type *type = rhs->node.data_type;
575 struct hlsl_ir_var *var = rhs->src.var;
576 struct hlsl_ir_node *c;
577 unsigned int i;
578
579 if (type->class == HLSL_CLASS_ARRAY || type->class == HLSL_CLASS_STRUCT)
580 {
581 struct hlsl_ir_load *element_load;
582 struct hlsl_struct_field *field;
583 uint32_t elem_semantic_index;
584
585 for (i = 0; i < hlsl_type_element_count(type); ++i)
586 {
587 uint32_t element_modifiers;
588
589 if (type->class == HLSL_CLASS_ARRAY)
590 {
591 elem_semantic_index = semantic_index
593 element_modifiers = modifiers;
594 force_align = true;
595 }
596 else
597 {
598 field = &type->e.record.fields[i];
600 continue;
602 semantic = &field->semantic;
603 elem_semantic_index = semantic->index;
604 loc = &field->loc;
605 element_modifiers = combine_field_storage_modifiers(modifiers, field->storage_modifiers);
606 force_align = (i == 0);
607 }
608
609 if (!(c = hlsl_new_uint_constant(ctx, i, &var->loc)))
610 return;
611 hlsl_block_add_instr(&func->body, c);
612
613 if (!(element_load = hlsl_new_load_index(ctx, &rhs->src, c, loc)))
614 return;
615 hlsl_block_add_instr(&func->body, &element_load->node);
616
617 append_output_copy_recurse(ctx, func, element_load, element_modifiers,
618 semantic, elem_semantic_index, force_align);
619 }
620 }
621 else
622 {
623 append_output_copy(ctx, func, rhs, modifiers, semantic, semantic_index, force_align);
624 }
625}
626
627/* Split outputs into two variables representing the temp and semantic
628 * registers, and copy the former to the latter, so that reads from output
629 * variables work. */
631{
632 struct hlsl_ir_load *load;
633
634 /* This redundant load is expected to be deleted later by DCE. */
635 if (!(load = hlsl_new_var_load(ctx, var, &var->loc)))
636 return;
637 hlsl_block_add_instr(&func->body, &load->node);
638
639 append_output_copy_recurse(ctx, func, load, var->storage_modifiers, &var->semantic, var->semantic.index, false);
640}
641
642bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool (*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *),
643 struct hlsl_block *block, void *context)
644{
645 struct hlsl_ir_node *instr, *next;
646 bool progress = false;
647
648 LIST_FOR_EACH_ENTRY_SAFE(instr, next, &block->instrs, struct hlsl_ir_node, entry)
649 {
650 if (instr->type == HLSL_IR_IF)
651 {
652 struct hlsl_ir_if *iff = hlsl_ir_if(instr);
653
656 }
657 else if (instr->type == HLSL_IR_LOOP)
658 {
660 }
661 else if (instr->type == HLSL_IR_SWITCH)
662 {
663 struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
664 struct hlsl_ir_switch_case *c;
665
667 {
669 }
670 }
671
672 progress |= func(ctx, instr, context);
673 }
674
675 return progress;
676}
677
678typedef bool (*PFN_lower_func)(struct hlsl_ctx *, struct hlsl_ir_node *, struct hlsl_block *);
679
680static bool call_lower_func(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
681{
683 struct hlsl_block block;
684
686 if (func(ctx, instr, &block))
687 {
688 struct hlsl_ir_node *replacement = LIST_ENTRY(list_tail(&block.instrs), struct hlsl_ir_node, entry);
689
690 list_move_before(&instr->entry, &block.instrs);
691 hlsl_replace_node(instr, replacement);
692 return true;
693 }
694 else
695 {
697 return false;
698 }
699}
700
701/* Specific form of transform_ir() for passes which convert a single instruction
702 * to a block of one or more instructions. This helper takes care of setting up
703 * the block and calling hlsl_replace_node_with_block(). */
705{
707}
708
709static bool transform_instr_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
710{
711 bool res;
712 bool (*func)(struct hlsl_ctx *ctx, struct hlsl_deref *, struct hlsl_ir_node *) = context;
713
714 switch(instr->type)
715 {
716 case HLSL_IR_LOAD:
717 res = func(ctx, &hlsl_ir_load(instr)->src, instr);
718 return res;
719
720 case HLSL_IR_STORE:
721 res = func(ctx, &hlsl_ir_store(instr)->lhs, instr);
722 return res;
723
725 res = func(ctx, &hlsl_ir_resource_load(instr)->resource, instr);
726 if (hlsl_ir_resource_load(instr)->sampler.var)
727 res |= func(ctx, &hlsl_ir_resource_load(instr)->sampler, instr);
728 return res;
729
731 res = func(ctx, &hlsl_ir_resource_store(instr)->resource, instr);
732 return res;
733
734 default:
735 return false;
736 }
737 return false;
738}
739
740static bool transform_derefs(struct hlsl_ctx *ctx,
741 bool (*func)(struct hlsl_ctx *ctx, struct hlsl_deref *, struct hlsl_ir_node *),
742 struct hlsl_block *block)
743{
745}
746
748{
751};
752
753static bool find_recursive_calls(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
754{
755 struct recursive_call_ctx *call_ctx = context;
756 struct hlsl_ir_function_decl *decl;
757 const struct hlsl_ir_call *call;
758 size_t i;
759
760 if (instr->type != HLSL_IR_CALL)
761 return false;
762 call = hlsl_ir_call(instr);
763 decl = call->decl;
764
765 for (i = 0; i < call_ctx->count; ++i)
766 {
767 if (call_ctx->backtrace[i] == decl)
768 {
770 "Recursive call to \"%s\".", decl->func->name);
771 /* Native returns E_NOTIMPL instead of E_FAIL here. */
773 return false;
774 }
775 }
776
777 if (!hlsl_array_reserve(ctx, (void **)&call_ctx->backtrace, &call_ctx->capacity,
778 call_ctx->count + 1, sizeof(*call_ctx->backtrace)))
779 return false;
780 call_ctx->backtrace[call_ctx->count++] = decl;
781
783
784 --call_ctx->count;
785
786 return false;
787}
788
790 struct hlsl_ir_function_decl *func, struct hlsl_ir_node *cf_instr)
791{
792 struct hlsl_ir_node *iff, *jump;
793 struct hlsl_block then_block;
794 struct hlsl_ir_load *load;
795
796 hlsl_block_init(&then_block);
797
798 if (!(load = hlsl_new_var_load(ctx, func->early_return_var, &cf_instr->loc)))
799 return;
800 list_add_after(&cf_instr->entry, &load->node.entry);
801
802 if (!(jump = hlsl_new_jump(ctx, HLSL_IR_JUMP_BREAK, NULL, &cf_instr->loc)))
803 return;
804 hlsl_block_add_instr(&then_block, jump);
805
806 if (!(iff = hlsl_new_if(ctx, &load->node, &then_block, NULL, &cf_instr->loc)))
807 return;
808 list_add_after(&load->node.entry, &iff->entry);
809}
810
811/* Remove HLSL_IR_JUMP_RETURN calls by altering subsequent control flow. */
813 struct hlsl_block *block, bool in_loop)
814{
815 struct hlsl_ir_node *return_instr = NULL, *cf_instr = NULL;
816 struct hlsl_ir_node *instr, *next;
817 bool has_early_return = false;
818
819 /* SM1 has no function calls. SM4 does, but native d3dcompiler inlines
820 * everything anyway. We are safest following suit.
821 *
822 * The basic idea is to keep track of whether the function has executed an
823 * early return in a synthesized boolean variable (func->early_return_var)
824 * and guard all code after the return on that variable being false. In the
825 * case of loops we also replace the return with a break.
826 *
827 * The following algorithm loops over instructions in a block, recursing
828 * into inferior CF blocks, until it hits one of the following two things:
829 *
830 * - A return statement. In this case, we remove everything after the return
831 * statement in this block. We have to stop and do this in a separate
832 * loop, because instructions must be deleted in reverse order (due to
833 * def-use chains.)
834 *
835 * If we're inside of a loop CF block, we can instead just turn the
836 * return into a break, which offers the right semantics—except that it
837 * won't break out of nested loops.
838 *
839 * - A CF block which contains a return statement. After calling
840 * lower_return() on the CF block body, we stop, pull out everything after
841 * the CF instruction, shove it into an if block, and then lower that if
842 * block.
843 *
844 * (We could return a "did we make progress" boolean like hlsl_transform_ir()
845 * and run this pass multiple times, but we already know the only block
846 * that still needs to be addressed, so there's not much point.)
847 *
848 * If we're inside of a loop CF block, we again do things differently. We
849 * already turned any returns into breaks. If the block we just processed
850 * was conditional, then "break" did our work for us. If it was a loop,
851 * we need to propagate that break to the outer loop.
852 *
853 * We return true if there was an early return anywhere in the block we just
854 * processed (including CF contained inside that block).
855 */
856
857 LIST_FOR_EACH_ENTRY_SAFE(instr, next, &block->instrs, struct hlsl_ir_node, entry)
858 {
859 if (instr->type == HLSL_IR_CALL)
860 {
861 struct hlsl_ir_call *call = hlsl_ir_call(instr);
862
863 lower_return(ctx, call->decl, &call->decl->body, false);
864 }
865 else if (instr->type == HLSL_IR_IF)
866 {
867 struct hlsl_ir_if *iff = hlsl_ir_if(instr);
868
869 has_early_return |= lower_return(ctx, func, &iff->then_block, in_loop);
870 has_early_return |= lower_return(ctx, func, &iff->else_block, in_loop);
871
872 if (has_early_return)
873 {
874 /* If we're in a loop, we don't need to do anything here. We
875 * turned the return into a break, and that will already skip
876 * anything that comes after this "if" block. */
877 if (!in_loop)
878 {
879 cf_instr = instr;
880 break;
881 }
882 }
883 }
884 else if (instr->type == HLSL_IR_LOOP)
885 {
886 has_early_return |= lower_return(ctx, func, &hlsl_ir_loop(instr)->body, true);
887
888 if (has_early_return)
889 {
890 if (in_loop)
891 {
892 /* "instr" is a nested loop. "return" breaks out of all
893 * loops, so break out of this one too now. */
895 }
896 else
897 {
898 cf_instr = instr;
899 break;
900 }
901 }
902 }
903 else if (instr->type == HLSL_IR_JUMP)
904 {
905 struct hlsl_ir_jump *jump = hlsl_ir_jump(instr);
906 struct hlsl_ir_node *constant, *store;
907
908 if (jump->type == HLSL_IR_JUMP_RETURN)
909 {
910 if (!(constant = hlsl_new_bool_constant(ctx, true, &jump->node.loc)))
911 return false;
912 list_add_before(&jump->node.entry, &constant->entry);
913
914 if (!(store = hlsl_new_simple_store(ctx, func->early_return_var, constant)))
915 return false;
916 list_add_after(&constant->entry, &store->entry);
917
918 has_early_return = true;
919 if (in_loop)
920 {
921 jump->type = HLSL_IR_JUMP_BREAK;
922 }
923 else
924 {
925 return_instr = instr;
926 break;
927 }
928 }
929 }
930 else if (instr->type == HLSL_IR_SWITCH)
931 {
932 struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
933 struct hlsl_ir_switch_case *c;
934
936 {
937 has_early_return |= lower_return(ctx, func, &c->body, true);
938 }
939
940 if (has_early_return)
941 {
942 if (in_loop)
943 {
944 /* For a 'switch' nested in a loop append a break after the 'switch'. */
946 }
947 else
948 {
949 cf_instr = instr;
950 break;
951 }
952 }
953 }
954 }
955
956 if (return_instr)
957 {
958 /* If we're in a loop, we should have used "break" instead. */
959 VKD3D_ASSERT(!in_loop);
960
961 /* Iterate in reverse, to avoid use-after-free when unlinking sources from
962 * the "uses" list. */
963 LIST_FOR_EACH_ENTRY_SAFE_REV(instr, next, &block->instrs, struct hlsl_ir_node, entry)
964 {
965 list_remove(&instr->entry);
966 hlsl_free_instr(instr);
967
968 /* Yes, we just freed it, but we're comparing pointers. */
969 if (instr == return_instr)
970 break;
971 }
972 }
973 else if (cf_instr)
974 {
975 struct list *tail = list_tail(&block->instrs);
976 struct hlsl_ir_node *not, *iff;
977 struct hlsl_block then_block;
978 struct hlsl_ir_load *load;
979
980 /* If we're in a loop, we should have used "break" instead. */
981 VKD3D_ASSERT(!in_loop);
982
983 if (tail == &cf_instr->entry)
984 return has_early_return;
985
986 hlsl_block_init(&then_block);
987 list_move_slice_tail(&then_block.instrs, list_next(&block->instrs, &cf_instr->entry), tail);
988 lower_return(ctx, func, &then_block, in_loop);
989
990 if (!(load = hlsl_new_var_load(ctx, func->early_return_var, &cf_instr->loc)))
991 return false;
993
994 if (!(not = hlsl_new_unary_expr(ctx, HLSL_OP1_LOGIC_NOT, &load->node, &cf_instr->loc)))
995 return false;
997
998 if (!(iff = hlsl_new_if(ctx, not, &then_block, NULL, &cf_instr->loc)))
999 return false;
1000 list_add_tail(&block->instrs, &iff->entry);
1001 }
1002
1003 return has_early_return;
1004}
1005
1006/* Remove HLSL_IR_CALL instructions by inlining them. */
1007static bool lower_calls(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
1008{
1009 const struct hlsl_ir_function_decl *decl;
1010 struct hlsl_ir_call *call;
1011 struct hlsl_block block;
1012
1013 if (instr->type != HLSL_IR_CALL)
1014 return false;
1015 call = hlsl_ir_call(instr);
1016 decl = call->decl;
1017
1018 if (!decl->has_body)
1020 "Function \"%s\" is not defined.", decl->func->name);
1021
1022 if (!hlsl_clone_block(ctx, &block, &decl->body))
1023 return false;
1024 list_move_before(&call->node.entry, &block.instrs);
1025
1026 list_remove(&call->node.entry);
1027 hlsl_free_instr(&call->node);
1028 return true;
1029}
1030
1032 const struct vkd3d_shader_location *loc)
1033{
1034 unsigned int dim_count = index->data_type->dimx;
1035 struct hlsl_ir_node *store, *zero;
1036 struct hlsl_ir_load *coords_load;
1037 struct hlsl_deref coords_deref;
1038 struct hlsl_ir_var *coords;
1039
1040 VKD3D_ASSERT(dim_count < 4);
1041
1042 if (!(coords = hlsl_new_synthetic_var(ctx, "coords",
1043 hlsl_get_vector_type(ctx, HLSL_TYPE_UINT, dim_count + 1), loc)))
1044 return NULL;
1045
1047 if (!(store = hlsl_new_store_index(ctx, &coords_deref, NULL, index, (1u << dim_count) - 1, loc)))
1048 return NULL;
1049 list_add_after(&index->entry, &store->entry);
1050
1051 if (!(zero = hlsl_new_uint_constant(ctx, 0, loc)))
1052 return NULL;
1053 list_add_after(&store->entry, &zero->entry);
1054
1055 if (!(store = hlsl_new_store_index(ctx, &coords_deref, NULL, zero, 1u << dim_count, loc)))
1056 return NULL;
1057 list_add_after(&zero->entry, &store->entry);
1058
1059 if (!(coords_load = hlsl_new_var_load(ctx, coords, loc)))
1060 return NULL;
1061 list_add_after(&store->entry, &coords_load->node.entry);
1062
1063 return &coords_load->node;
1064}
1065
1066/* hlsl_ir_swizzle nodes that directly point to a matrix value are only a parse-time construct that
1067 * represents matrix swizzles (e.g. mat._m01_m23) before we know if they will be used in the lhs of
1068 * an assignment or as a value made from different components of the matrix. The former cases should
1069 * have already been split into several separate assignments, but the latter are lowered by this
1070 * pass. */
1071static bool lower_matrix_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
1072{
1073 struct hlsl_ir_swizzle *swizzle;
1074 struct hlsl_ir_load *var_load;
1075 struct hlsl_deref var_deref;
1076 struct hlsl_type *matrix_type;
1077 struct hlsl_ir_var *var;
1078 unsigned int x, y, k, i;
1079
1080 if (instr->type != HLSL_IR_SWIZZLE)
1081 return false;
1082 swizzle = hlsl_ir_swizzle(instr);
1083 matrix_type = swizzle->val.node->data_type;
1084 if (matrix_type->class != HLSL_CLASS_MATRIX)
1085 return false;
1086
1087 if (!(var = hlsl_new_synthetic_var(ctx, "matrix-swizzle", instr->data_type, &instr->loc)))
1088 return false;
1090
1091 for (i = 0; i < instr->data_type->dimx; ++i)
1092 {
1093 struct hlsl_block store_block;
1094 struct hlsl_ir_node *load;
1095
1096 y = (swizzle->swizzle >> (8 * i + 4)) & 0xf;
1097 x = (swizzle->swizzle >> 8 * i) & 0xf;
1098 k = y * matrix_type->dimx + x;
1099
1100 if (!(load = hlsl_add_load_component(ctx, block, swizzle->val.node, k, &instr->loc)))
1101 return false;
1102
1103 if (!hlsl_new_store_component(ctx, &store_block, &var_deref, i, load))
1104 return false;
1105 hlsl_block_add_block(block, &store_block);
1106 }
1107
1108 if (!(var_load = hlsl_new_var_load(ctx, var, &instr->loc)))
1109 return false;
1110 hlsl_block_add_instr(block, &var_load->node);
1111
1112 return true;
1113}
1114
1115/* hlsl_ir_index nodes are a parse-time construct used to represent array indexing and struct
1116 * record access before knowing if they will be used in the lhs of an assignment --in which case
1117 * they are lowered into a deref-- or as the load of an element within a larger value.
1118 * For the latter case, this pass takes care of lowering hlsl_ir_indexes into individual
1119 * hlsl_ir_loads, or individual hlsl_ir_resource_loads, in case the indexing is a
1120 * resource access. */
1121static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
1122{
1123 struct hlsl_ir_node *val, *store;
1124 struct hlsl_deref var_deref;
1125 struct hlsl_ir_index *index;
1126 struct hlsl_ir_load *load;
1127 struct hlsl_ir_var *var;
1128
1129 if (instr->type != HLSL_IR_INDEX)
1130 return false;
1131 index = hlsl_ir_index(instr);
1132 val = index->val.node;
1133
1135 {
1136 unsigned int dim_count = hlsl_sampler_dim_count(val->data_type->sampler_dim);
1137 struct hlsl_ir_node *coords = index->idx.node;
1138 struct hlsl_resource_load_params params = {0};
1139 struct hlsl_ir_node *resource_load;
1140
1141 VKD3D_ASSERT(coords->data_type->class == HLSL_CLASS_VECTOR);
1142 VKD3D_ASSERT(coords->data_type->e.numeric.type == HLSL_TYPE_UINT);
1143 VKD3D_ASSERT(coords->data_type->dimx == dim_count);
1144
1145 if (!(coords = add_zero_mipmap_level(ctx, coords, &instr->loc)))
1146 return false;
1147
1149 params.resource = val;
1150 params.coords = coords;
1151 params.format = val->data_type->e.resource.format;
1152
1153 if (!(resource_load = hlsl_new_resource_load(ctx, &params, &instr->loc)))
1154 return false;
1155 hlsl_block_add_instr(block, resource_load);
1156 return true;
1157 }
1158
1159 if (!(var = hlsl_new_synthetic_var(ctx, "index-val", val->data_type, &instr->loc)))
1160 return false;
1162
1163 if (!(store = hlsl_new_simple_store(ctx, var, val)))
1164 return false;
1166
1168 {
1169 struct hlsl_ir_node *mat = index->val.node;
1170 struct hlsl_deref row_deref;
1171 unsigned int i;
1172
1174
1175 if (!(var = hlsl_new_synthetic_var(ctx, "row", instr->data_type, &instr->loc)))
1176 return false;
1178
1179 for (i = 0; i < mat->data_type->dimx; ++i)
1180 {
1181 struct hlsl_ir_node *c;
1182
1183 if (!(c = hlsl_new_uint_constant(ctx, i, &instr->loc)))
1184 return false;
1186
1187 if (!(load = hlsl_new_load_index(ctx, &var_deref, c, &instr->loc)))
1188 return false;
1190
1191 if (!(load = hlsl_new_load_index(ctx, &load->src, index->idx.node, &instr->loc)))
1192 return false;
1194
1195 if (!(store = hlsl_new_store_index(ctx, &row_deref, c, &load->node, 0, &instr->loc)))
1196 return false;
1198 }
1199
1200 if (!(load = hlsl_new_var_load(ctx, var, &instr->loc)))
1201 return false;
1203 }
1204 else
1205 {
1206 if (!(load = hlsl_new_load_index(ctx, &var_deref, index->idx.node, &instr->loc)))
1207 return false;
1209 }
1210 return true;
1211}
1212
1213/* Lower casts from vec1 to vecN to swizzles. */
1214static bool lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
1215{
1216 const struct hlsl_type *src_type, *dst_type;
1217 struct hlsl_type *dst_scalar_type;
1218 struct hlsl_ir_expr *cast;
1219
1220 if (instr->type != HLSL_IR_EXPR)
1221 return false;
1222 cast = hlsl_ir_expr(instr);
1223 if (cast->op != HLSL_OP1_CAST)
1224 return false;
1225 src_type = cast->operands[0].node->data_type;
1226 dst_type = cast->node.data_type;
1227
1228 if (src_type->class <= HLSL_CLASS_VECTOR && dst_type->class <= HLSL_CLASS_VECTOR && src_type->dimx == 1)
1229 {
1230 struct hlsl_ir_node *new_cast, *swizzle;
1231
1232 dst_scalar_type = hlsl_get_scalar_type(ctx, dst_type->e.numeric.type);
1233 /* We need to preserve the cast since it might be doing more than just
1234 * turning the scalar into a vector. */
1235 if (!(new_cast = hlsl_new_cast(ctx, cast->operands[0].node, dst_scalar_type, &cast->node.loc)))
1236 return false;
1237 hlsl_block_add_instr(block, new_cast);
1238
1239 if (dst_type->dimx != 1)
1240 {
1241 if (!(swizzle = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, X, X, X), dst_type->dimx, new_cast, &cast->node.loc)))
1242 return false;
1244 }
1245
1246 return true;
1247 }
1248
1249 return false;
1250}
1251
1252/* Allocate a unique, ordered index to each instruction, which will be used for
1253 * copy propagation and computing liveness ranges.
1254 * Index 0 means unused; index 1 means function entry, so start at 2. */
1255static unsigned int index_instructions(struct hlsl_block *block, unsigned int index)
1256{
1257 struct hlsl_ir_node *instr;
1258
1259 LIST_FOR_EACH_ENTRY(instr, &block->instrs, struct hlsl_ir_node, entry)
1260 {
1261 instr->index = index++;
1262
1263 if (instr->type == HLSL_IR_IF)
1264 {
1265 struct hlsl_ir_if *iff = hlsl_ir_if(instr);
1268 }
1269 else if (instr->type == HLSL_IR_LOOP)
1270 {
1272 hlsl_ir_loop(instr)->next_index = index;
1273 }
1274 else if (instr->type == HLSL_IR_SWITCH)
1275 {
1276 struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
1277 struct hlsl_ir_switch_case *c;
1278
1280 {
1281 index = index_instructions(&c->body, index);
1282 }
1283 }
1284 }
1285
1286 return index;
1287}
1288
1289/*
1290 * Copy propagation. The basic idea is to recognize instruction sequences of the
1291 * form:
1292 *
1293 * 2: <any instruction>
1294 * 3: v = @2
1295 * 4: load(v)
1296 *
1297 * and replace the load (@4) with the original instruction (@2).
1298 * This works for multiple components, even if they're written using separate
1299 * store instructions, as long as the rhs is the same in every case. This basic
1300 * detection is implemented by copy_propagation_replace_with_single_instr().
1301 *
1302 * In some cases, the load itself might not have a single source, but a
1303 * subsequent swizzle might; hence we also try to replace swizzles of loads.
1304 *
1305 * We use the same infrastructure to implement a more specialized
1306 * transformation. We recognize sequences of the form:
1307 *
1308 * 2: 123
1309 * 3: var.x = @2
1310 * 4: 345
1311 * 5: var.y = @4
1312 * 6: load(var.xy)
1313 *
1314 * where the load (@6) originates from different sources but that are constant,
1315 * and transform it into a single constant vector. This latter pass is done
1316 * by copy_propagation_replace_with_constant_vector().
1317 *
1318 * This is a specialized form of vectorization, and begs the question: why does
1319 * the load need to be involved? Can we just vectorize the stores into a single
1320 * instruction, and then use "normal" copy-prop to convert that into a single
1321 * vector?
1322 *
1323 * In general, the answer is yes, but there is a special case which necessitates
1324 * the use of this transformation: non-uniform control flow. Copy-prop can act
1325 * across some control flow, and in cases like the following:
1326 *
1327 * 2: 123
1328 * 3: var.x = @2
1329 * 4: if (...)
1330 * 5: 456
1331 * 6: var.y = @5
1332 * 7: load(var.xy)
1333 *
1334 * we can copy-prop the load (@7) into a constant vector {123, 456}, but we
1335 * cannot easily vectorize the stores @3 and @6.
1336 */
1337
1339{
1340 unsigned int timestamp;
1341 /* If node is NULL, the value was dynamically written and thus, it is unknown.*/
1343 unsigned int component;
1344};
1345
1347{
1350};
1351
1353{
1357};
1358
1360{
1363};
1364
1365static int copy_propagation_var_def_compare(const void *key, const struct rb_entry *entry)
1366{
1368 uintptr_t key_int = (uintptr_t)key, entry_int = (uintptr_t)var_def->var;
1369
1370 return (key_int > entry_int) - (key_int < entry_int);
1371}
1372
1374{
1376 unsigned int component_count = hlsl_type_component_count(var_def->var->data_type);
1377 unsigned int i;
1378
1379 for (i = 0; i < component_count; ++i)
1380 vkd3d_free(var_def->traces[i].records);
1381 vkd3d_free(var_def);
1382}
1383
1385 struct copy_propagation_component_trace *trace, unsigned int time)
1386{
1387 int r;
1388
1389 for (r = trace->record_count - 1; r >= 0; --r)
1390 {
1391 if (trace->records[r].timestamp < time)
1392 return &trace->records[r];
1393 }
1394
1395 return NULL;
1396}
1397
1399 const struct hlsl_ir_var *var, unsigned int component, unsigned int time)
1400{
1401 for (; state; state = state->parent)
1402 {
1403 struct rb_entry *entry = rb_get(&state->var_defs, var);
1404 if (entry)
1405 {
1407 unsigned int component_count = hlsl_type_component_count(var->data_type);
1409
1412
1413 if (!value)
1414 continue;
1415
1416 if (value->node)
1417 return value;
1418 else
1419 return NULL;
1420 }
1421 }
1422
1423 return NULL;
1424}
1425
1428{
1429 struct rb_entry *entry = rb_get(&state->var_defs, var);
1430 struct copy_propagation_var_def *var_def;
1431 unsigned int component_count = hlsl_type_component_count(var->data_type);
1432 int res;
1433
1434 if (entry)
1436
1438 return NULL;
1439
1440 var_def->var = var;
1441
1442 res = rb_put(&state->var_defs, var, &var_def->entry);
1443 VKD3D_ASSERT(!res);
1444
1445 return var_def;
1446}
1447
1450 unsigned int component, unsigned int time)
1451{
1452 VKD3D_ASSERT(!trace->record_count || trace->records[trace->record_count - 1].timestamp < time);
1453
1454 if (!hlsl_array_reserve(ctx, (void **)&trace->records, &trace->record_capacity,
1455 trace->record_count + 1, sizeof(trace->records[0])))
1456 return;
1457
1458 trace->records[trace->record_count].timestamp = time;
1459 trace->records[trace->record_count].node = node;
1460 trace->records[trace->record_count].component = component;
1461
1462 ++trace->record_count;
1463}
1464
1466 unsigned int comp, unsigned char writemask, unsigned int time)
1467{
1468 unsigned i;
1469
1470 TRACE("Invalidate variable %s[%u]%s.\n", var_def->var->name, comp, debug_hlsl_writemask(writemask));
1471
1472 for (i = 0; i < 4; ++i)
1473 {
1474 if (writemask & (1u << i))
1475 {
1476 struct copy_propagation_component_trace *trace = &var_def->traces[comp + i];
1477
1478 /* Don't add an invalidate record if it is already present. */
1479 if (trace->record_count && trace->records[trace->record_count - 1].timestamp == time)
1480 {
1481 VKD3D_ASSERT(!trace->records[trace->record_count - 1].node);
1482 continue;
1483 }
1484
1486 }
1487 }
1488}
1489
1491 struct copy_propagation_var_def *var_def, const struct hlsl_deref *deref,
1492 struct hlsl_type *type, unsigned int depth, unsigned int comp_start, unsigned char writemask,
1493 unsigned int time)
1494{
1495 unsigned int i, subtype_comp_count;
1496 struct hlsl_ir_node *path_node;
1497 struct hlsl_type *subtype;
1498
1499 if (depth == deref->path_len)
1500 {
1501 copy_propagation_invalidate_variable(ctx, var_def, comp_start, writemask, time);
1502 return;
1503 }
1504
1505 path_node = deref->path[depth].node;
1507
1508 if (type->class == HLSL_CLASS_STRUCT)
1509 {
1510 unsigned int idx = hlsl_ir_constant(path_node)->value.u[0].u;
1511
1512 for (i = 0; i < idx; ++i)
1513 comp_start += hlsl_type_component_count(type->e.record.fields[i].type);
1514
1516 depth + 1, comp_start, writemask, time);
1517 }
1518 else
1519 {
1520 subtype_comp_count = hlsl_type_component_count(subtype);
1521
1522 if (path_node->type == HLSL_IR_CONSTANT)
1523 {
1525 depth + 1, hlsl_ir_constant(path_node)->value.u[0].u * subtype_comp_count,
1526 writemask, time);
1527 }
1528 else
1529 {
1530 for (i = 0; i < hlsl_type_element_count(type); ++i)
1531 {
1533 depth + 1, i * subtype_comp_count, writemask, time);
1534 }
1535 }
1536 }
1537}
1538
1540 struct copy_propagation_var_def *var_def, const struct hlsl_deref *deref,
1541 unsigned char writemask, unsigned int time)
1542{
1543 copy_propagation_invalidate_variable_from_deref_recurse(ctx, var_def, deref, deref->var->data_type,
1544 0, 0, writemask, time);
1545}
1546
1548 unsigned int comp, unsigned char writemask, struct hlsl_ir_node *instr, unsigned int time)
1549{
1550 unsigned int i, j = 0;
1551
1552 for (i = 0; i < 4; ++i)
1553 {
1554 if (writemask & (1u << i))
1555 {
1556 struct copy_propagation_component_trace *trace = &var_def->traces[comp + i];
1557
1558 TRACE("Variable %s[%u] is written by instruction %p%s.\n",
1559 var_def->var->name, comp + i, instr, debug_hlsl_writemask(1u << i));
1560
1562 }
1563 }
1564}
1565
1567 const struct copy_propagation_state *state, const struct hlsl_ir_load *load,
1568 uint32_t swizzle, struct hlsl_ir_node *instr)
1569{
1570 const unsigned int instr_component_count = hlsl_type_component_count(instr->data_type);
1571 const struct hlsl_deref *deref = &load->src;
1572 const struct hlsl_ir_var *var = deref->var;
1573 struct hlsl_ir_node *new_instr = NULL;
1574 unsigned int time = load->node.index;
1575 unsigned int start, count, i;
1576 uint32_t ret_swizzle = 0;
1577
1579 return false;
1580
1581 for (i = 0; i < instr_component_count; ++i)
1582 {
1584
1586 time)))
1587 return false;
1588
1589 if (!new_instr)
1590 {
1591 new_instr = value->node;
1592 }
1593 else if (new_instr != value->node)
1594 {
1595 TRACE("No single source for propagating load from %s[%u-%u]%s\n",
1596 var->name, start, start + count, debug_hlsl_swizzle(swizzle, instr_component_count));
1597 return false;
1598 }
1599 ret_swizzle |= value->component << HLSL_SWIZZLE_SHIFT(i);
1600 }
1601
1602 TRACE("Load from %s[%u-%u]%s propagated as instruction %p%s.\n",
1603 var->name, start, start + count, debug_hlsl_swizzle(swizzle, instr_component_count),
1604 new_instr, debug_hlsl_swizzle(ret_swizzle, instr_component_count));
1605
1606 if (new_instr->data_type->class == HLSL_CLASS_SCALAR || new_instr->data_type->class == HLSL_CLASS_VECTOR)
1607 {
1608 struct hlsl_ir_node *swizzle_node;
1609
1610 if (!(swizzle_node = hlsl_new_swizzle(ctx, ret_swizzle, instr_component_count, new_instr, &instr->loc)))
1611 return false;
1612 list_add_before(&instr->entry, &swizzle_node->entry);
1613 new_instr = swizzle_node;
1614 }
1615
1616 hlsl_replace_node(instr, new_instr);
1617 return true;
1618}
1619
1621 const struct copy_propagation_state *state, const struct hlsl_ir_load *load,
1622 uint32_t swizzle, struct hlsl_ir_node *instr)
1623{
1624 const unsigned int instr_component_count = hlsl_type_component_count(instr->data_type);
1625 const struct hlsl_deref *deref = &load->src;
1626 const struct hlsl_ir_var *var = deref->var;
1627 struct hlsl_constant_value values = {0};
1628 unsigned int time = load->node.index;
1629 unsigned int start, count, i;
1630 struct hlsl_ir_node *cons;
1631
1633 return false;
1634
1635 for (i = 0; i < instr_component_count; ++i)
1636 {
1638
1640 time)) || value->node->type != HLSL_IR_CONSTANT)
1641 return false;
1642
1643 values.u[i] = hlsl_ir_constant(value->node)->value.u[value->component];
1644 }
1645
1646 if (!(cons = hlsl_new_constant(ctx, instr->data_type, &values, &instr->loc)))
1647 return false;
1648 list_add_before(&instr->entry, &cons->entry);
1649
1650 TRACE("Load from %s[%u-%u]%s turned into a constant %p.\n",
1651 var->name, start, start + count, debug_hlsl_swizzle(swizzle, instr_component_count), cons);
1652
1653 hlsl_replace_node(instr, cons);
1654 return true;
1655}
1656
1659{
1660 struct hlsl_type *type = load->node.data_type;
1661
1662 switch (type->class)
1663 {
1665 case HLSL_CLASS_SCALAR:
1666 case HLSL_CLASS_VECTOR:
1669 case HLSL_CLASS_SAMPLER:
1670 case HLSL_CLASS_STRING:
1671 case HLSL_CLASS_TEXTURE:
1672 case HLSL_CLASS_UAV:
1681 case HLSL_CLASS_NULL:
1682 break;
1683
1684 case HLSL_CLASS_MATRIX:
1685 case HLSL_CLASS_ARRAY:
1686 case HLSL_CLASS_STRUCT:
1687 /* We can't handle complex types here.
1688 * They should have been already split anyway by earlier passes,
1689 * but they may not have been deleted yet. We can't rely on DCE to
1690 * solve that problem for us, since we may be called on a partial
1691 * block, but DCE deletes dead stores, so it needs to be able to
1692 * see the whole program. */
1693 case HLSL_CLASS_ERROR:
1694 return false;
1695
1698 case HLSL_CLASS_PASS:
1700 case HLSL_CLASS_VOID:
1702 }
1703
1705 return true;
1706
1708 return true;
1709
1710 return false;
1711}
1712
1715{
1716 struct hlsl_ir_load *load;
1717
1718 if (swizzle->val.node->type != HLSL_IR_LOAD)
1719 return false;
1720 load = hlsl_ir_load(swizzle->val.node);
1721
1723 return true;
1724
1726 return true;
1727
1728 return false;
1729}
1730
1732 struct hlsl_deref *deref, struct copy_propagation_state *state, unsigned int time)
1733{
1735 struct hlsl_ir_load *load;
1736 unsigned int start, count;
1737
1739 return false;
1740 VKD3D_ASSERT(count == 1);
1741
1742 if (!(value = copy_propagation_get_value(state, deref->var, start, time)))
1743 return false;
1744 VKD3D_ASSERT(value->component == 0);
1745
1746 /* Only HLSL_IR_LOAD can produce an object. */
1747 load = hlsl_ir_load(value->node);
1748
1749 /* As we are replacing the instruction's deref (with the one in the hlsl_ir_load) and not the
1750 * instruction itself, we won't be able to rely on the value retrieved by
1751 * copy_propagation_get_value() for the new deref in subsequent iterations of copy propagation.
1752 * This is because another value may be written to that deref between the hlsl_ir_load and
1753 * this instruction.
1754 *
1755 * For this reason, we only replace the new deref when it corresponds to a uniform variable,
1756 * which cannot be written to.
1757 *
1758 * In a valid shader, all object references must resolve statically to a single uniform object.
1759 * If this is the case, we can expect copy propagation on regular store/loads and the other
1760 * compilation passes to replace all hlsl_ir_loads with loads to uniform objects, so this
1761 * implementation is complete, even with this restriction.
1762 */
1763 if (!load->src.var->is_uniform)
1764 {
1765 TRACE("Ignoring load from non-uniform object variable %s\n", load->src.var->name);
1766 return false;
1767 }
1768
1769 hlsl_cleanup_deref(deref);
1770 hlsl_copy_deref(ctx, deref, &load->src);
1771
1772 return true;
1773}
1774
1777{
1778 bool progress = false;
1779
1780 progress |= copy_propagation_transform_object_load(ctx, &load->resource, state, load->node.index);
1781 if (load->sampler.var)
1783 return progress;
1784}
1785
1788{
1789 bool progress = false;
1790
1792 return progress;
1793}
1794
1795static void copy_propagation_record_store(struct hlsl_ctx *ctx, struct hlsl_ir_store *store,
1797{
1798 struct copy_propagation_var_def *var_def;
1799 struct hlsl_deref *lhs = &store->lhs;
1800 struct hlsl_ir_var *var = lhs->var;
1801 unsigned int start, count;
1802
1803 if (!(var_def = copy_propagation_create_var_def(ctx, state, var)))
1804 return;
1805
1807 {
1808 unsigned int writemask = store->writemask;
1809
1810 if (!hlsl_is_numeric_type(store->rhs.node->data_type))
1811 writemask = VKD3DSP_WRITEMASK_0;
1812 copy_propagation_set_value(ctx, var_def, start, writemask, store->rhs.node, store->node.index);
1813 }
1814 else
1815 {
1817 store->node.index);
1818 }
1819}
1820
1823{
1825 state->parent = parent;
1826}
1827
1829{
1831}
1832
1834 struct hlsl_block *block, unsigned int time)
1835{
1836 struct hlsl_ir_node *instr;
1837
1838 LIST_FOR_EACH_ENTRY(instr, &block->instrs, struct hlsl_ir_node, entry)
1839 {
1840 switch (instr->type)
1841 {
1842 case HLSL_IR_STORE:
1843 {
1844 struct hlsl_ir_store *store = hlsl_ir_store(instr);
1845 struct copy_propagation_var_def *var_def;
1846 struct hlsl_deref *lhs = &store->lhs;
1847 struct hlsl_ir_var *var = lhs->var;
1848
1849 if (!(var_def = copy_propagation_create_var_def(ctx, state, var)))
1850 continue;
1851
1853
1854 break;
1855 }
1856
1857 case HLSL_IR_IF:
1858 {
1859 struct hlsl_ir_if *iff = hlsl_ir_if(instr);
1860
1863
1864 break;
1865 }
1866
1867 case HLSL_IR_LOOP:
1868 {
1869 struct hlsl_ir_loop *loop = hlsl_ir_loop(instr);
1870
1872
1873 break;
1874 }
1875
1876 case HLSL_IR_SWITCH:
1877 {
1878 struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
1879 struct hlsl_ir_switch_case *c;
1880
1882 {
1884 }
1885
1886 break;
1887 }
1888
1889 default:
1890 break;
1891 }
1892 }
1893}
1894
1895static bool copy_propagation_transform_block(struct hlsl_ctx *ctx, struct hlsl_block *block,
1897
1898static bool copy_propagation_process_if(struct hlsl_ctx *ctx, struct hlsl_ir_if *iff,
1900{
1901 struct copy_propagation_state inner_state;
1902 bool progress = false;
1903
1904 copy_propagation_state_init(ctx, &inner_state, state);
1906 copy_propagation_state_destroy(&inner_state);
1907
1908 copy_propagation_state_init(ctx, &inner_state, state);
1910 copy_propagation_state_destroy(&inner_state);
1911
1912 /* Ideally we'd invalidate the outer state looking at what was
1913 * touched in the two inner states, but this doesn't work for
1914 * loops (because we need to know what is invalidated in advance),
1915 * so we need copy_propagation_invalidate_from_block() anyway. */
1918
1919 return progress;
1920}
1921
1922static bool copy_propagation_process_loop(struct hlsl_ctx *ctx, struct hlsl_ir_loop *loop,
1924{
1925 struct copy_propagation_state inner_state;
1926 bool progress = false;
1927
1929
1930 copy_propagation_state_init(ctx, &inner_state, state);
1931 progress |= copy_propagation_transform_block(ctx, &loop->body, &inner_state);
1932 copy_propagation_state_destroy(&inner_state);
1933
1934 return progress;
1935}
1936
1939{
1940 struct copy_propagation_state inner_state;
1941 struct hlsl_ir_switch_case *c;
1942 bool progress = false;
1943
1945 {
1946 copy_propagation_state_init(ctx, &inner_state, state);
1947 progress |= copy_propagation_transform_block(ctx, &c->body, &inner_state);
1948 copy_propagation_state_destroy(&inner_state);
1949 }
1950
1952 {
1953 copy_propagation_invalidate_from_block(ctx, state, &c->body, s->node.index);
1954 }
1955
1956 return progress;
1957}
1958
1961{
1962 struct hlsl_ir_node *instr, *next;
1963 bool progress = false;
1964
1965 LIST_FOR_EACH_ENTRY_SAFE(instr, next, &block->instrs, struct hlsl_ir_node, entry)
1966 {
1967 switch (instr->type)
1968 {
1969 case HLSL_IR_LOAD:
1971 break;
1972
1975 break;
1976
1979 break;
1980
1981 case HLSL_IR_STORE:
1983 break;
1984
1985 case HLSL_IR_SWIZZLE:
1987 break;
1988
1989 case HLSL_IR_IF:
1991 break;
1992
1993 case HLSL_IR_LOOP:
1995 break;
1996
1997 case HLSL_IR_SWITCH:
1999 break;
2000
2001 default:
2002 break;
2003 }
2004 }
2005
2006 return progress;
2007}
2008
2010{
2012 bool progress;
2013
2015
2017
2019
2021
2022 return progress;
2023}
2024
2026{
2030};
2031
2033 const struct hlsl_deref *deref)
2034{
2035 struct hlsl_type *type = deref->var->data_type;
2036 unsigned int i;
2037
2038 for (i = 0; i < deref->path_len; ++i)
2039 {
2040 struct hlsl_ir_node *path_node = deref->path[i].node;
2041 unsigned int idx = 0;
2042
2043 VKD3D_ASSERT(path_node);
2044 if (path_node->type != HLSL_IR_CONSTANT)
2046
2047 /* We should always have generated a cast to UINT. */
2048 VKD3D_ASSERT(path_node->data_type->class == HLSL_CLASS_SCALAR
2049 && path_node->data_type->e.numeric.type == HLSL_TYPE_UINT);
2050
2051 idx = hlsl_ir_constant(path_node)->value.u[0].u;
2052
2053 switch (type->class)
2054 {
2055 case HLSL_CLASS_VECTOR:
2056 if (idx >= type->dimx)
2057 {
2059 "Vector index is out of bounds. %u/%u", idx, type->dimx);
2061 }
2062 break;
2063
2064 case HLSL_CLASS_MATRIX:
2066 {
2068 "Matrix index is out of bounds. %u/%u", idx, hlsl_type_major_size(type));
2070 }
2071 break;
2072
2073 case HLSL_CLASS_ARRAY:
2074 if (idx >= type->e.array.elements_count)
2075 {
2077 "Array index is out of bounds. %u/%u", idx, type->e.array.elements_count);
2079 }
2080 break;
2081
2082 case HLSL_CLASS_STRUCT:
2083 break;
2084
2085 default:
2087 }
2088
2090 }
2091
2092 return DEREF_VALIDATION_OK;
2093}
2094
2095static void note_non_static_deref_expressions(struct hlsl_ctx *ctx, const struct hlsl_deref *deref,
2096 const char *usage)
2097{
2098 unsigned int i;
2099
2100 for (i = 0; i < deref->path_len; ++i)
2101 {
2102 struct hlsl_ir_node *path_node = deref->path[i].node;
2103
2104 VKD3D_ASSERT(path_node);
2105 if (path_node->type != HLSL_IR_CONSTANT)
2107 "Expression for %s within \"%s\" cannot be resolved statically.",
2108 usage, deref->var->name);
2109 }
2110}
2111
2112static bool validate_dereferences(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
2113 void *context)
2114{
2115 switch (instr->type)
2116 {
2118 {
2120
2121 if (!load->resource.var->is_uniform)
2122 {
2124 "Loaded resource must have a single uniform source.");
2125 }
2127 {
2129 "Loaded resource from \"%s\" must be determinable at compile time.",
2130 load->resource.var->name);
2131 note_non_static_deref_expressions(ctx, &load->resource, "loaded resource");
2132 }
2133
2134 if (load->sampler.var)
2135 {
2136 if (!load->sampler.var->is_uniform)
2137 {
2139 "Resource load sampler must have a single uniform source.");
2140 }
2142 {
2144 "Resource load sampler from \"%s\" must be determinable at compile time.",
2145 load->sampler.var->name);
2146 note_non_static_deref_expressions(ctx, &load->sampler, "resource load sampler");
2147 }
2148 }
2149 break;
2150 }
2152 {
2153 struct hlsl_ir_resource_store *store = hlsl_ir_resource_store(instr);
2154
2155 if (!store->resource.var->is_uniform)
2156 {
2158 "Accessed resource must have a single uniform source.");
2159 }
2161 {
2163 "Accessed resource from \"%s\" must be determinable at compile time.",
2164 store->resource.var->name);
2165 note_non_static_deref_expressions(ctx, &store->resource, "accessed resource");
2166 }
2167 break;
2168 }
2169 case HLSL_IR_LOAD:
2170 {
2171 struct hlsl_ir_load *load = hlsl_ir_load(instr);
2173 break;
2174 }
2175 case HLSL_IR_STORE:
2176 {
2177 struct hlsl_ir_store *store = hlsl_ir_store(instr);
2179 break;
2180 }
2181 default:
2182 break;
2183 }
2184
2185 return false;
2186}
2187
2188static bool is_vec1(const struct hlsl_type *type)
2189{
2190 return (type->class == HLSL_CLASS_SCALAR) || (type->class == HLSL_CLASS_VECTOR && type->dimx == 1);
2191}
2192
2193static bool fold_redundant_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
2194{
2195 if (instr->type == HLSL_IR_EXPR)
2196 {
2197 struct hlsl_ir_expr *expr = hlsl_ir_expr(instr);
2198 const struct hlsl_type *dst_type = expr->node.data_type;
2199 const struct hlsl_type *src_type;
2200
2201 if (expr->op != HLSL_OP1_CAST)
2202 return false;
2203
2204 src_type = expr->operands[0].node->data_type;
2205
2206 if (hlsl_types_are_equal(src_type, dst_type)
2207 || (src_type->e.numeric.type == dst_type->e.numeric.type && is_vec1(src_type) && is_vec1(dst_type)))
2208 {
2209 hlsl_replace_node(&expr->node, expr->operands[0].node);
2210 return true;
2211 }
2212 }
2213
2214 return false;
2215}
2216
2217/* Copy an element of a complex variable. Helper for
2218 * split_array_copies(), split_struct_copies() and
2219 * split_matrix_copies(). Inserts new instructions right before
2220 * "store". */
2221static bool split_copy(struct hlsl_ctx *ctx, struct hlsl_ir_store *store,
2222 const struct hlsl_ir_load *load, const unsigned int idx, struct hlsl_type *type)
2223{
2224 struct hlsl_ir_node *split_store, *c;
2225 struct hlsl_ir_load *split_load;
2226
2227 if (!(c = hlsl_new_uint_constant(ctx, idx, &store->node.loc)))
2228 return false;
2229 list_add_before(&store->node.entry, &c->entry);
2230
2231 if (!(split_load = hlsl_new_load_index(ctx, &load->src, c, &store->node.loc)))
2232 return false;
2233 list_add_before(&store->node.entry, &split_load->node.entry);
2234
2235 if (!(split_store = hlsl_new_store_index(ctx, &store->lhs, c, &split_load->node, 0, &store->node.loc)))
2236 return false;
2237 list_add_before(&store->node.entry, &split_store->entry);
2238
2239 return true;
2240}
2241
2242static bool split_array_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
2243{
2244 const struct hlsl_ir_node *rhs;
2245 struct hlsl_type *element_type;
2246 const struct hlsl_type *type;
2247 struct hlsl_ir_store *store;
2248 unsigned int i;
2249
2250 if (instr->type != HLSL_IR_STORE)
2251 return false;
2252
2253 store = hlsl_ir_store(instr);
2254 rhs = store->rhs.node;
2255 type = rhs->data_type;
2256 if (type->class != HLSL_CLASS_ARRAY)
2257 return false;
2258 element_type = type->e.array.type;
2259
2260 if (rhs->type != HLSL_IR_LOAD)
2261 {
2262 hlsl_fixme(ctx, &instr->loc, "Array store rhs is not HLSL_IR_LOAD. Broadcast may be missing.");
2263 return false;
2264 }
2265
2266 for (i = 0; i < type->e.array.elements_count; ++i)
2267 {
2268 if (!split_copy(ctx, store, hlsl_ir_load(rhs), i, element_type))
2269 return false;
2270 }
2271
2272 /* Remove the store instruction, so that we can split structs which contain
2273 * other structs. Although assignments produce a value, we don't allow
2274 * HLSL_IR_STORE to be used as a source. */
2275 list_remove(&store->node.entry);
2276 hlsl_free_instr(&store->node);
2277 return true;
2278}
2279
2280static bool split_struct_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
2281{
2282 const struct hlsl_ir_node *rhs;
2283 const struct hlsl_type *type;
2284 struct hlsl_ir_store *store;
2285 size_t i;
2286
2287 if (instr->type != HLSL_IR_STORE)
2288 return false;
2289
2290 store = hlsl_ir_store(instr);
2291 rhs = store->rhs.node;
2292 type = rhs->data_type;
2293 if (type->class != HLSL_CLASS_STRUCT)
2294 return false;
2295
2296 if (rhs->type != HLSL_IR_LOAD)
2297 {
2298 hlsl_fixme(ctx, &instr->loc, "Struct store rhs is not HLSL_IR_LOAD. Broadcast may be missing.");
2299 return false;
2300 }
2301
2302 for (i = 0; i < type->e.record.field_count; ++i)
2303 {
2304 const struct hlsl_struct_field *field = &type->e.record.fields[i];
2305
2306 if (!split_copy(ctx, store, hlsl_ir_load(rhs), i, field->type))
2307 return false;
2308 }
2309
2310 /* Remove the store instruction, so that we can split structs which contain
2311 * other structs. Although assignments produce a value, we don't allow
2312 * HLSL_IR_STORE to be used as a source. */
2313 list_remove(&store->node.entry);
2314 hlsl_free_instr(&store->node);
2315 return true;
2316}
2317
2318static bool split_matrix_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
2319{
2320 const struct hlsl_ir_node *rhs;
2321 struct hlsl_type *element_type;
2322 const struct hlsl_type *type;
2323 unsigned int i;
2324 struct hlsl_ir_store *store;
2325
2326 if (instr->type != HLSL_IR_STORE)
2327 return false;
2328
2329 store = hlsl_ir_store(instr);
2330 rhs = store->rhs.node;
2331 type = rhs->data_type;
2332 if (type->class != HLSL_CLASS_MATRIX)
2333 return false;
2334 element_type = hlsl_get_vector_type(ctx, type->e.numeric.type, hlsl_type_minor_size(type));
2335
2336 if (rhs->type != HLSL_IR_LOAD)
2337 {
2338 hlsl_fixme(ctx, &instr->loc, "Copying from unsupported node type.");
2339 return false;
2340 }
2341
2342 for (i = 0; i < hlsl_type_major_size(type); ++i)
2343 {
2344 if (!split_copy(ctx, store, hlsl_ir_load(rhs), i, element_type))
2345 return false;
2346 }
2347
2348 list_remove(&store->node.entry);
2349 hlsl_free_instr(&store->node);
2350 return true;
2351}
2352
2353static bool lower_narrowing_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
2354{
2355 const struct hlsl_type *src_type, *dst_type;
2356 struct hlsl_type *dst_vector_type;
2357 struct hlsl_ir_expr *cast;
2358
2359 if (instr->type != HLSL_IR_EXPR)
2360 return false;
2361 cast = hlsl_ir_expr(instr);
2362 if (cast->op != HLSL_OP1_CAST)
2363 return false;
2364 src_type = cast->operands[0].node->data_type;
2365 dst_type = cast->node.data_type;
2366
2367 if (src_type->class <= HLSL_CLASS_VECTOR && dst_type->class <= HLSL_CLASS_VECTOR && dst_type->dimx < src_type->dimx)
2368 {
2369 struct hlsl_ir_node *new_cast, *swizzle;
2370
2371 dst_vector_type = hlsl_get_vector_type(ctx, dst_type->e.numeric.type, src_type->dimx);
2372 /* We need to preserve the cast since it might be doing more than just
2373 * narrowing the vector. */
2374 if (!(new_cast = hlsl_new_cast(ctx, cast->operands[0].node, dst_vector_type, &cast->node.loc)))
2375 return false;
2376 hlsl_block_add_instr(block, new_cast);
2377
2378 if (!(swizzle = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, Y, Z, W), dst_type->dimx, new_cast, &cast->node.loc)))
2379 return false;
2381
2382 return true;
2383 }
2384
2385 return false;
2386}
2387
2388static bool fold_swizzle_chains(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
2389{
2390 struct hlsl_ir_swizzle *swizzle;
2391 struct hlsl_ir_node *next_instr;
2392
2393 if (instr->type != HLSL_IR_SWIZZLE)
2394 return false;
2395 swizzle = hlsl_ir_swizzle(instr);
2396
2397 next_instr = swizzle->val.node;
2398
2399 if (next_instr->type == HLSL_IR_SWIZZLE)
2400 {
2401 struct hlsl_ir_node *new_swizzle;
2402 uint32_t combined_swizzle;
2403
2404 combined_swizzle = hlsl_combine_swizzles(hlsl_ir_swizzle(next_instr)->swizzle,
2405 swizzle->swizzle, instr->data_type->dimx);
2406 next_instr = hlsl_ir_swizzle(next_instr)->val.node;
2407
2408 if (!(new_swizzle = hlsl_new_swizzle(ctx, combined_swizzle, instr->data_type->dimx, next_instr, &instr->loc)))
2409 return false;
2410
2411 list_add_before(&instr->entry, &new_swizzle->entry);
2412 hlsl_replace_node(instr, new_swizzle);
2413 return true;
2414 }
2415
2416 return false;
2417}
2418
2419static bool remove_trivial_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
2420{
2421 struct hlsl_ir_swizzle *swizzle;
2422 unsigned int i;
2423
2424 if (instr->type != HLSL_IR_SWIZZLE)
2425 return false;
2426 swizzle = hlsl_ir_swizzle(instr);
2427
2428 if (instr->data_type->dimx != swizzle->val.node->data_type->dimx)
2429 return false;
2430
2431 for (i = 0; i < instr->data_type->dimx; ++i)
2432 if (hlsl_swizzle_get_component(swizzle->swizzle, i) != i)
2433 return false;
2434
2435 hlsl_replace_node(instr, swizzle->val.node);
2436
2437 return true;
2438}
2439
2440static bool remove_trivial_conditional_branches(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
2441{
2443 struct hlsl_ir_if *iff;
2444
2445 if (instr->type != HLSL_IR_IF)
2446 return false;
2447 iff = hlsl_ir_if(instr);
2448 if (iff->condition.node->type != HLSL_IR_CONSTANT)
2449 return false;
2451
2452 list_move_before(&instr->entry, condition->value.u[0].u ? &iff->then_block.instrs : &iff->else_block.instrs);
2453 list_remove(&instr->entry);
2454 hlsl_free_instr(instr);
2455
2456 return true;
2457}
2458
2459static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
2460{
2461 struct hlsl_ir_switch_case *c, *def = NULL;
2462 bool missing_terminal_break = false;
2463 struct hlsl_ir_node *node;
2464 struct hlsl_ir_switch *s;
2465
2466 if (instr->type != HLSL_IR_SWITCH)
2467 return false;
2468 s = hlsl_ir_switch(instr);
2469
2471 {
2472 bool terminal_break = false;
2473
2474 if (list_empty(&c->body.instrs))
2475 {
2476 terminal_break = !!list_next(&s->cases, &c->entry);
2477 }
2478 else
2479 {
2480 node = LIST_ENTRY(list_tail(&c->body.instrs), struct hlsl_ir_node, entry);
2481 if (node->type == HLSL_IR_JUMP)
2482 terminal_break = (hlsl_ir_jump(node)->type == HLSL_IR_JUMP_BREAK);
2483 }
2484
2485 missing_terminal_break |= !terminal_break;
2486
2487 if (!terminal_break)
2488 {
2489 if (c->is_default)
2490 {
2492 "The 'default' case block is not terminated with 'break' or 'return'.");
2493 }
2494 else
2495 {
2497 "Switch case block '%u' is not terminated with 'break' or 'return'.", c->value);
2498 }
2499 }
2500 }
2501
2502 if (missing_terminal_break)
2503 return true;
2504
2506 {
2507 if (c->is_default)
2508 {
2509 def = c;
2510
2511 /* Remove preceding empty cases. */
2512 while (list_prev(&s->cases, &def->entry))
2513 {
2514 c = LIST_ENTRY(list_prev(&s->cases, &def->entry), struct hlsl_ir_switch_case, entry);
2515 if (!list_empty(&c->body.instrs))
2516 break;
2518 }
2519
2520 if (list_empty(&def->body.instrs))
2521 {
2522 /* Remove following empty cases. */
2523 while (list_next(&s->cases, &def->entry))
2524 {
2525 c = LIST_ENTRY(list_next(&s->cases, &def->entry), struct hlsl_ir_switch_case, entry);
2526 if (!list_empty(&c->body.instrs))
2527 break;
2529 }
2530
2531 /* Merge with the next case. */
2532 if (list_next(&s->cases, &def->entry))
2533 {
2534 c = LIST_ENTRY(list_next(&s->cases, &def->entry), struct hlsl_ir_switch_case, entry);
2535 c->is_default = true;
2537 def = c;
2538 }
2539 }
2540
2541 break;
2542 }
2543 }
2544
2545 if (def)
2546 {
2547 list_remove(&def->entry);
2548 }
2549 else
2550 {
2551 struct hlsl_ir_node *jump;
2552
2553 if (!(def = hlsl_new_switch_case(ctx, 0, true, NULL, &s->node.loc)))
2554 return true;
2555 if (!(jump = hlsl_new_jump(ctx, HLSL_IR_JUMP_BREAK, NULL, &s->node.loc)))
2556 {
2558 return true;
2559 }
2560 hlsl_block_add_instr(&def->body, jump);
2561 }
2562 list_add_tail(&s->cases, &def->entry);
2563
2564 return true;
2565}
2566
2567static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
2568{
2569 struct hlsl_ir_node *idx;
2570 struct hlsl_deref *deref;
2571 struct hlsl_type *type;
2572 unsigned int i;
2573
2574 if (instr->type != HLSL_IR_LOAD)
2575 return false;
2576
2577 deref = &hlsl_ir_load(instr)->src;
2578 VKD3D_ASSERT(deref->var);
2579
2580 if (deref->path_len == 0)
2581 return false;
2582
2583 type = deref->var->data_type;
2584 for (i = 0; i < deref->path_len - 1; ++i)
2586
2587 idx = deref->path[deref->path_len - 1].node;
2588
2589 if (type->class == HLSL_CLASS_VECTOR && idx->type != HLSL_IR_CONSTANT)
2590 {
2591 struct hlsl_ir_node *eq, *swizzle, *dot, *c, *operands[HLSL_MAX_OPERANDS] = {0};
2592 struct hlsl_constant_value value;
2593 struct hlsl_ir_load *vector_load;
2594 enum hlsl_ir_expr_op op;
2595
2596 if (!(vector_load = hlsl_new_load_parent(ctx, deref, &instr->loc)))
2597 return false;
2598 hlsl_block_add_instr(block, &vector_load->node);
2599
2600 if (!(swizzle = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, X, X, X), type->dimx, idx, &instr->loc)))
2601 return false;
2603
2604 value.u[0].u = 0;
2605 value.u[1].u = 1;
2606 value.u[2].u = 2;
2607 value.u[3].u = 3;
2609 return false;
2611
2612 operands[0] = swizzle;
2613 operands[1] = c;
2614 if (!(eq = hlsl_new_expr(ctx, HLSL_OP2_EQUAL, operands,
2615 hlsl_get_vector_type(ctx, HLSL_TYPE_BOOL, type->dimx), &instr->loc)))
2616 return false;
2618
2619 if (!(eq = hlsl_new_cast(ctx, eq, type, &instr->loc)))
2620 return false;
2622
2623 op = HLSL_OP2_DOT;
2624 if (type->dimx == 1)
2625 op = type->e.numeric.type == HLSL_TYPE_BOOL ? HLSL_OP2_LOGIC_AND : HLSL_OP2_MUL;
2626
2627 /* Note: We may be creating a DOT for bool vectors here, which we need to lower to
2628 * LOGIC_OR + LOGIC_AND. */
2629 operands[0] = &vector_load->node;
2630 operands[1] = eq;
2631 if (!(dot = hlsl_new_expr(ctx, op, operands, instr->data_type, &instr->loc)))
2632 return false;
2634
2635 return true;
2636 }
2637
2638 return false;
2639}
2640
2642{
2643 struct hlsl_ir_node *idx;
2644 struct hlsl_deref *deref;
2645 struct hlsl_type *type;
2646 unsigned int i;
2647
2648 if (instr->type != HLSL_IR_STORE)
2649 return false;
2650
2651 deref = &hlsl_ir_store(instr)->lhs;
2652 VKD3D_ASSERT(deref->var);
2653
2654 if (deref->path_len == 0)
2655 return false;
2656
2657 type = deref->var->data_type;
2658 for (i = 0; i < deref->path_len - 1; ++i)
2660
2661 idx = deref->path[deref->path_len - 1].node;
2662
2663 if (type->class == HLSL_CLASS_VECTOR && idx->type != HLSL_IR_CONSTANT)
2664 {
2665 /* We should turn this into an hlsl_error after we implement unrolling, because if we get
2666 * here after that, it means that the HLSL is invalid. */
2667 hlsl_fixme(ctx, &instr->loc, "Non-constant vector addressing on store. Unrolling may be missing.");
2668 }
2669
2670 return false;
2671}
2672
2673/* This pass flattens array (and row_major matrix) loads that include the indexing of a non-constant
2674 * index into multiple constant loads, where the value of only one of them ends up in the resulting
2675 * node.
2676 * This is achieved through a synthetic variable. The non-constant index is compared for equality
2677 * with every possible value it can have within the array bounds, and the ternary operator is used
2678 * to update the value of the synthetic var when the equality check passes. */
2679static bool lower_nonconstant_array_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
2680 struct hlsl_block *block)
2681{
2682 struct hlsl_constant_value zero_value = {0};
2683 struct hlsl_ir_node *cut_index, *zero, *store;
2684 unsigned int i, i_cut, element_count;
2685 const struct hlsl_deref *deref;
2686 struct hlsl_type *cut_type;
2687 struct hlsl_ir_load *load;
2688 struct hlsl_ir_var *var;
2689 bool row_major;
2690
2691 if (instr->type != HLSL_IR_LOAD)
2692 return false;
2693 load = hlsl_ir_load(instr);
2694 deref = &load->src;
2695
2696 if (deref->path_len == 0)
2697 return false;
2698
2699 for (i = deref->path_len - 1; ; --i)
2700 {
2701 if (deref->path[i].node->type != HLSL_IR_CONSTANT)
2702 {
2703 i_cut = i;
2704 break;
2705 }
2706
2707 if (i == 0)
2708 return false;
2709 }
2710
2711 cut_index = deref->path[i_cut].node;
2712 cut_type = deref->var->data_type;
2713 for (i = 0; i < i_cut; ++i)
2714 cut_type = hlsl_get_element_type_from_path_index(ctx, cut_type, deref->path[i].node);
2715
2716 row_major = hlsl_type_is_row_major(cut_type);
2717 VKD3D_ASSERT(cut_type->class == HLSL_CLASS_ARRAY || row_major);
2718
2719 if (!(var = hlsl_new_synthetic_var(ctx, row_major ? "row_major-load" : "array-load", instr->data_type, &instr->loc)))
2720 return false;
2721
2722 if (!(zero = hlsl_new_constant(ctx, instr->data_type, &zero_value, &instr->loc)))
2723 return false;
2725
2726 if (!(store = hlsl_new_simple_store(ctx, var, zero)))
2727 return false;
2729
2730 TRACE("Lowering non-constant %s load on variable '%s'.\n", row_major ? "row_major" : "array", deref->var->name);
2731
2733 for (i = 0; i < element_count; ++i)
2734 {
2736 struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0};
2737 struct hlsl_ir_node *const_i, *equals, *ternary, *var_store;
2738 struct hlsl_ir_load *var_load, *specific_load;
2739 struct hlsl_deref deref_copy = {0};
2740
2741 if (!(const_i = hlsl_new_uint_constant(ctx, i, &cut_index->loc)))
2742 return false;
2743 hlsl_block_add_instr(block, const_i);
2744
2745 operands[0] = cut_index;
2746 operands[1] = const_i;
2747 if (!(equals = hlsl_new_expr(ctx, HLSL_OP2_EQUAL, operands, btype, &cut_index->loc)))
2748 return false;
2749 hlsl_block_add_instr(block, equals);
2750
2751 if (!(equals = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, X, X, X), var->data_type->dimx, equals, &cut_index->loc)))
2752 return false;
2753 hlsl_block_add_instr(block, equals);
2754
2755 if (!(var_load = hlsl_new_var_load(ctx, var, &cut_index->loc)))
2756 return false;
2757 hlsl_block_add_instr(block, &var_load->node);
2758
2759 if (!hlsl_copy_deref(ctx, &deref_copy, deref))
2760 return false;
2761 hlsl_src_remove(&deref_copy.path[i_cut]);
2762 hlsl_src_from_node(&deref_copy.path[i_cut], const_i);
2763
2764 if (!(specific_load = hlsl_new_load_index(ctx, &deref_copy, NULL, &cut_index->loc)))
2765 {
2766 hlsl_cleanup_deref(&deref_copy);
2767 return false;
2768 }
2769 hlsl_block_add_instr(block, &specific_load->node);
2770
2771 hlsl_cleanup_deref(&deref_copy);
2772
2773 operands[0] = equals;
2774 operands[1] = &specific_load->node;
2775 operands[2] = &var_load->node;
2776 if (!(ternary = hlsl_new_expr(ctx, HLSL_OP3_TERNARY, operands, instr->data_type, &cut_index->loc)))
2777 return false;
2778 hlsl_block_add_instr(block, ternary);
2779
2780 if (!(var_store = hlsl_new_simple_store(ctx, var, ternary)))
2781 return false;
2782 hlsl_block_add_instr(block, var_store);
2783 }
2784
2785 if (!(load = hlsl_new_var_load(ctx, var, &instr->loc)))
2786 return false;
2788
2789 return true;
2790}
2791/* Lower combined samples and sampler variables to synthesized separated textures and samplers.
2792 * That is, translate SM1-style samples in the source to SM4-style samples in the bytecode. */
2793static bool lower_combined_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
2794{
2796 struct vkd3d_string_buffer *name;
2797 struct hlsl_ir_var *var;
2798 unsigned int i;
2799
2800 if (instr->type != HLSL_IR_RESOURCE_LOAD)
2801 return false;
2802 load = hlsl_ir_resource_load(instr);
2803
2804 switch (load->load_type)
2805 {
2806 case HLSL_RESOURCE_LOAD:
2815 return false;
2816
2822 break;
2823 }
2824 if (load->sampler.var)
2825 return false;
2826
2827 if (!hlsl_type_is_resource(load->resource.var->data_type))
2828 {
2829 hlsl_fixme(ctx, &instr->loc, "Lower combined samplers within structs.");
2830 return false;
2831 }
2832
2834
2836 return false;
2837 vkd3d_string_buffer_printf(name, "<resource>%s", load->resource.var->name);
2838
2839 TRACE("Lowering to separate resource %s.\n", debugstr_a(name->buffer));
2840
2841 if (!(var = hlsl_get_var(ctx->globals, name->buffer)))
2842 {
2843 struct hlsl_type *texture_array_type = hlsl_new_texture_type(ctx, load->sampling_dim,
2845
2846 /* Create (possibly multi-dimensional) texture array type with the same dims as the sampler array. */
2847 struct hlsl_type *arr_type = load->resource.var->data_type;
2848 for (i = 0; i < load->resource.path_len; ++i)
2849 {
2850 VKD3D_ASSERT(arr_type->class == HLSL_CLASS_ARRAY);
2851 texture_array_type = hlsl_new_array_type(ctx, texture_array_type, arr_type->e.array.elements_count);
2852 arr_type = arr_type->e.array.type;
2853 }
2854
2855 if (!(var = hlsl_new_synthetic_var_named(ctx, name->buffer, texture_array_type, &instr->loc, false)))
2856 {
2858 return false;
2859 }
2860 var->is_uniform = 1;
2861 var->is_separated_resource = true;
2862
2863 list_add_tail(&ctx->extern_vars, &var->extern_entry);
2864 }
2866
2867 if (load->sampling_dim != var->data_type->sampler_dim)
2868 {
2870 "Cannot split combined samplers from \"%s\" if they have different usage dimensions.",
2871 load->resource.var->name);
2872 hlsl_note(ctx, &var->loc, VKD3D_SHADER_LOG_ERROR, "First use as combined sampler is here.");
2873 return false;
2874
2875 }
2876
2877 hlsl_copy_deref(ctx, &load->sampler, &load->resource);
2878 load->resource.var = var;
2881
2882 return true;
2883}
2884
2886 enum hlsl_regset regset)
2887{
2888 struct hlsl_ir_var *var;
2889
2891 {
2892 if (var->bind_count[regset] < to_add->bind_count[regset])
2893 {
2894 list_add_before(&var->extern_entry, &to_add->extern_entry);
2895 return;
2896 }
2897 }
2898
2899 list_add_tail(list, &to_add->extern_entry);
2900}
2901
2903{
2904 struct list separated_resources;
2905 struct hlsl_ir_var *var, *next;
2906
2907 list_init(&separated_resources);
2908
2910 {
2911 if (var->is_separated_resource)
2912 {
2913 list_remove(&var->extern_entry);
2915 }
2916 }
2917
2918 list_move_head(&ctx->extern_vars, &separated_resources);
2919
2920 return false;
2921}
2922
2923/* Turn CAST to int or uint into FLOOR + REINTERPRET (which is written as a mere MOV). */
2924static bool lower_casts_to_int(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
2925{
2926 struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = { 0 };
2927 struct hlsl_ir_node *arg, *floor, *res;
2928 struct hlsl_ir_expr *expr;
2929
2930 if (instr->type != HLSL_IR_EXPR)
2931 return false;
2932 expr = hlsl_ir_expr(instr);
2933 if (expr->op != HLSL_OP1_CAST)
2934 return false;
2935
2936 arg = expr->operands[0].node;
2937 if (instr->data_type->e.numeric.type != HLSL_TYPE_INT && instr->data_type->e.numeric.type != HLSL_TYPE_UINT)
2938 return false;
2939 if (arg->data_type->e.numeric.type != HLSL_TYPE_FLOAT && arg->data_type->e.numeric.type != HLSL_TYPE_HALF)
2940 return false;
2941
2942 if (!(floor = hlsl_new_unary_expr(ctx, HLSL_OP1_FLOOR, arg, &instr->loc)))
2943 return false;
2945
2946 memset(operands, 0, sizeof(operands));
2947 operands[0] = floor;
2948 if (!(res = hlsl_new_expr(ctx, HLSL_OP1_REINTERPRET, operands, instr->data_type, &instr->loc)))
2949 return false;
2951
2952 return true;
2953}
2954
2955/* Lower DIV to RCP + MUL. */
2956static bool lower_division(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
2957{
2958 struct hlsl_ir_node *rcp, *mul;
2959 struct hlsl_ir_expr *expr;
2960
2961 if (instr->type != HLSL_IR_EXPR)
2962 return false;
2963 expr = hlsl_ir_expr(instr);
2964 if (expr->op != HLSL_OP2_DIV)
2965 return false;
2966
2967 if (!(rcp = hlsl_new_unary_expr(ctx, HLSL_OP1_RCP, expr->operands[1].node, &instr->loc)))
2968 return false;
2970
2971 if (!(mul = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, expr->operands[0].node, rcp)))
2972 return false;
2974
2975 return true;
2976}
2977
2978/* Lower SQRT to RSQ + RCP. */
2979static bool lower_sqrt(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
2980{
2981 struct hlsl_ir_node *rsq, *rcp;
2982 struct hlsl_ir_expr *expr;
2983
2984 if (instr->type != HLSL_IR_EXPR)
2985 return false;
2986 expr = hlsl_ir_expr(instr);
2987 if (expr->op != HLSL_OP1_SQRT)
2988 return false;
2989
2990 if (!(rsq = hlsl_new_unary_expr(ctx, HLSL_OP1_RSQ, expr->operands[0].node, &instr->loc)))
2991 return false;
2993
2994 if (!(rcp = hlsl_new_unary_expr(ctx, HLSL_OP1_RCP, rsq, &instr->loc)))
2995 return false;
2997 return true;
2998}
2999
3000/* Lower DP2 to MUL + ADD */
3001static bool lower_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3002{
3003 struct hlsl_ir_node *arg1, *arg2, *mul, *replacement, *zero, *add_x, *add_y;
3004 struct hlsl_ir_expr *expr;
3005
3006 if (instr->type != HLSL_IR_EXPR)
3007 return false;
3008 expr = hlsl_ir_expr(instr);
3009 arg1 = expr->operands[0].node;
3010 arg2 = expr->operands[1].node;
3011 if (expr->op != HLSL_OP2_DOT)
3012 return false;
3013 if (arg1->data_type->dimx != 2)
3014 return false;
3015
3016 if (ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL)
3017 {
3018 struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = { 0 };
3019
3020 if (!(zero = hlsl_new_float_constant(ctx, 0.0f, &expr->node.loc)))
3021 return false;
3023
3024 operands[0] = arg1;
3025 operands[1] = arg2;
3026 operands[2] = zero;
3027
3028 if (!(replacement = hlsl_new_expr(ctx, HLSL_OP3_DP2ADD, operands, instr->data_type, &expr->node.loc)))
3029 return false;
3030 }
3031 else
3032 {
3033 if (!(mul = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, expr->operands[0].node, expr->operands[1].node)))
3034 return false;
3036
3037 if (!(add_x = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(X, X, X, X), instr->data_type->dimx, mul, &expr->node.loc)))
3038 return false;
3040
3041 if (!(add_y = hlsl_new_swizzle(ctx, HLSL_SWIZZLE(Y, Y, Y, Y), instr->data_type->dimx, mul, &expr->node.loc)))
3042 return false;
3044
3045 if (!(replacement = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, add_x, add_y)))
3046 return false;
3047 }
3048 hlsl_block_add_instr(block, replacement);
3049
3050 return true;
3051}
3052
3053/* Lower ABS to MAX */
3054static bool lower_abs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3055{
3056 struct hlsl_ir_node *arg, *neg, *replacement;
3057 struct hlsl_ir_expr *expr;
3058
3059 if (instr->type != HLSL_IR_EXPR)
3060 return false;
3061 expr = hlsl_ir_expr(instr);
3062 arg = expr->operands[0].node;
3063 if (expr->op != HLSL_OP1_ABS)
3064 return false;
3065
3066 if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, arg, &instr->loc)))
3067 return false;
3069
3070 if (!(replacement = hlsl_new_binary_expr(ctx, HLSL_OP2_MAX, neg, arg)))
3071 return false;
3072 hlsl_block_add_instr(block, replacement);
3073
3074 return true;
3075}
3076
3077/* Lower ROUND using FRC, ROUND(x) -> ((x + 0.5) - FRC(x + 0.5)). */
3078static bool lower_round(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3079{
3080 struct hlsl_ir_node *arg, *neg, *sum, *frc, *half, *replacement;
3081 struct hlsl_type *type = instr->data_type;
3082 struct hlsl_constant_value half_value;
3083 unsigned int i, component_count;
3084 struct hlsl_ir_expr *expr;
3085
3086 if (instr->type != HLSL_IR_EXPR)
3087 return false;
3088
3089 expr = hlsl_ir_expr(instr);
3090 arg = expr->operands[0].node;
3091 if (expr->op != HLSL_OP1_ROUND)
3092 return false;
3093
3095 for (i = 0; i < component_count; ++i)
3096 half_value.u[i].f = 0.5f;
3097 if (!(half = hlsl_new_constant(ctx, type, &half_value, &expr->node.loc)))
3098 return false;
3100
3101 if (!(sum = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, arg, half)))
3102 return false;
3104
3105 if (!(frc = hlsl_new_unary_expr(ctx, HLSL_OP1_FRACT, sum, &instr->loc)))
3106 return false;
3108
3109 if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, frc, &instr->loc)))
3110 return false;
3112
3113 if (!(replacement = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, sum, neg)))
3114 return false;
3115 hlsl_block_add_instr(block, replacement);
3116
3117 return true;
3118}
3119
3120/* Lower CEIL to FRC */
3121static bool lower_ceil(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3122{
3123 struct hlsl_ir_node *arg, *neg, *sum, *frc;
3124 struct hlsl_ir_expr *expr;
3125
3126 if (instr->type != HLSL_IR_EXPR)
3127 return false;
3128
3129 expr = hlsl_ir_expr(instr);
3130 arg = expr->operands[0].node;
3131 if (expr->op != HLSL_OP1_CEIL)
3132 return false;
3133
3134 if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, arg, &instr->loc)))
3135 return false;
3137
3138 if (!(frc = hlsl_new_unary_expr(ctx, HLSL_OP1_FRACT, neg, &instr->loc)))
3139 return false;
3141
3142 if (!(sum = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, frc, arg)))
3143 return false;
3145
3146 return true;
3147}
3148
3149/* Lower FLOOR to FRC */
3150static bool lower_floor(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3151{
3152 struct hlsl_ir_node *arg, *neg, *sum, *frc;
3153 struct hlsl_ir_expr *expr;
3154
3155 if (instr->type != HLSL_IR_EXPR)
3156 return false;
3157
3158 expr = hlsl_ir_expr(instr);
3159 arg = expr->operands[0].node;
3160 if (expr->op != HLSL_OP1_FLOOR)
3161 return false;
3162
3163 if (!(frc = hlsl_new_unary_expr(ctx, HLSL_OP1_FRACT, arg, &instr->loc)))
3164 return false;
3166
3167 if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, frc, &instr->loc)))
3168 return false;
3170
3171 if (!(sum = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, neg, arg)))
3172 return false;
3174
3175 return true;
3176}
3177
3178/* Lower SIN/COS to SINCOS for SM1. */
3179static bool lower_trig(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3180{
3181 struct hlsl_ir_node *arg, *half, *two_pi, *reciprocal_two_pi, *neg_pi;
3182 struct hlsl_constant_value half_value, two_pi_value, reciprocal_two_pi_value, neg_pi_value;
3183 struct hlsl_ir_node *mad, *frc, *reduced;
3184 struct hlsl_type *type;
3185 struct hlsl_ir_expr *expr;
3186 enum hlsl_ir_expr_op op;
3187 struct hlsl_ir_node *sincos;
3188 int i;
3189
3190 if (instr->type != HLSL_IR_EXPR)
3191 return false;
3192 expr = hlsl_ir_expr(instr);
3193
3194 if (expr->op == HLSL_OP1_SIN)
3196 else if (expr->op == HLSL_OP1_COS)
3198 else
3199 return false;
3200
3201 arg = expr->operands[0].node;
3202 type = arg->data_type;
3203
3204 /* Reduce the range of the input angles to [-pi, pi]. */
3205 for (i = 0; i < type->dimx; ++i)
3206 {
3207 half_value.u[i].f = 0.5;
3208 two_pi_value.u[i].f = 2.0 * M_PI;
3209 reciprocal_two_pi_value.u[i].f = 1.0 / (2.0 * M_PI);
3210 neg_pi_value.u[i].f = -M_PI;
3211 }
3212
3213 if (!(half = hlsl_new_constant(ctx, type, &half_value, &instr->loc))
3214 || !(two_pi = hlsl_new_constant(ctx, type, &two_pi_value, &instr->loc))
3215 || !(reciprocal_two_pi = hlsl_new_constant(ctx, type, &reciprocal_two_pi_value, &instr->loc))
3216 || !(neg_pi = hlsl_new_constant(ctx, type, &neg_pi_value, &instr->loc)))
3217 return false;
3219 hlsl_block_add_instr(block, two_pi);
3220 hlsl_block_add_instr(block, reciprocal_two_pi);
3221 hlsl_block_add_instr(block, neg_pi);
3222
3223 if (!(mad = hlsl_new_ternary_expr(ctx, HLSL_OP3_MAD, arg, reciprocal_two_pi, half)))
3224 return false;
3226 if (!(frc = hlsl_new_unary_expr(ctx, HLSL_OP1_FRACT, mad, &instr->loc)))
3227 return false;
3229 if (!(reduced = hlsl_new_ternary_expr(ctx, HLSL_OP3_MAD, frc, two_pi, neg_pi)))
3230 return false;
3231 hlsl_block_add_instr(block, reduced);
3232
3233 if (type->dimx == 1)
3234 {
3235 if (!(sincos = hlsl_new_unary_expr(ctx, op, reduced, &instr->loc)))
3236 return false;
3238 }
3239 else
3240 {
3241 struct hlsl_ir_node *comps[4] = {0};
3242 struct hlsl_ir_var *var;
3243 struct hlsl_deref var_deref;
3244 struct hlsl_ir_load *var_load;
3245
3246 for (i = 0; i < type->dimx; ++i)
3247 {
3249
3250 if (!(comps[i] = hlsl_new_swizzle(ctx, s, 1, reduced, &instr->loc)))
3251 return false;
3252 hlsl_block_add_instr(block, comps[i]);
3253 }
3254
3255 if (!(var = hlsl_new_synthetic_var(ctx, "sincos", type, &instr->loc)))
3256 return false;
3258
3259 for (i = 0; i < type->dimx; ++i)
3260 {
3261 struct hlsl_block store_block;
3262
3263 if (!(sincos = hlsl_new_unary_expr(ctx, op, comps[i], &instr->loc)))
3264 return false;
3266
3267 if (!hlsl_new_store_component(ctx, &store_block, &var_deref, i, sincos))
3268 return false;
3269 hlsl_block_add_block(block, &store_block);
3270 }
3271
3272 if (!(var_load = hlsl_new_load_index(ctx, &var_deref, NULL, &instr->loc)))
3273 return false;
3274 hlsl_block_add_instr(block, &var_load->node);
3275 }
3276
3277 return true;
3278}
3279
3280static bool lower_logic_not(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3281{
3282 struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS];
3283 struct hlsl_ir_node *arg, *arg_cast, *neg, *one, *sub, *res;
3284 struct hlsl_constant_value one_value;
3285 struct hlsl_type *float_type;
3286 struct hlsl_ir_expr *expr;
3287
3288 if (instr->type != HLSL_IR_EXPR)
3289 return false;
3290 expr = hlsl_ir_expr(instr);
3291 if (expr->op != HLSL_OP1_LOGIC_NOT)
3292 return false;
3293
3294 arg = expr->operands[0].node;
3295 float_type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, arg->data_type->dimx);
3296
3297 /* If this is happens, it means we failed to cast the argument to boolean somewhere. */
3298 VKD3D_ASSERT(arg->data_type->e.numeric.type == HLSL_TYPE_BOOL);
3299
3300 if (!(arg_cast = hlsl_new_cast(ctx, arg, float_type, &arg->loc)))
3301 return false;
3302 hlsl_block_add_instr(block, arg_cast);
3303
3304 if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, arg_cast, &instr->loc)))
3305 return false;
3307
3308 one_value.u[0].f = 1.0;
3309 one_value.u[1].f = 1.0;
3310 one_value.u[2].f = 1.0;
3311 one_value.u[3].f = 1.0;
3312 if (!(one = hlsl_new_constant(ctx, float_type, &one_value, &instr->loc)))
3313 return false;
3315
3316 if (!(sub = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, one, neg)))
3317 return false;
3319
3320 memset(operands, 0, sizeof(operands));
3321 operands[0] = sub;
3322 if (!(res = hlsl_new_expr(ctx, HLSL_OP1_REINTERPRET, operands, instr->data_type, &instr->loc)))
3323 return false;
3325
3326 return true;
3327}
3328
3329/* Lower TERNARY to CMP for SM1. */
3330static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3331{
3332 struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = { 0 }, *replacement;
3333 struct hlsl_ir_node *cond, *first, *second, *float_cond, *neg;
3334 struct hlsl_ir_expr *expr;
3335 struct hlsl_type *type;
3336
3337 if (instr->type != HLSL_IR_EXPR)
3338 return false;
3339
3340 expr = hlsl_ir_expr(instr);
3341 if (expr->op != HLSL_OP3_TERNARY)
3342 return false;
3343
3344 cond = expr->operands[0].node;
3345 first = expr->operands[1].node;
3346 second = expr->operands[2].node;
3347
3348 if (cond->data_type->class > HLSL_CLASS_VECTOR || instr->data_type->class > HLSL_CLASS_VECTOR)
3349 {
3350 hlsl_fixme(ctx, &instr->loc, "Lower ternary of type other than scalar or vector.");
3351 return false;
3352 }
3353
3354 VKD3D_ASSERT(cond->data_type->e.numeric.type == HLSL_TYPE_BOOL);
3355
3357 instr->data_type->dimx, instr->data_type->dimy);
3358
3359 if (!(float_cond = hlsl_new_cast(ctx, cond, type, &instr->loc)))
3360 return false;
3361 hlsl_block_add_instr(block, float_cond);
3362
3363 if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, float_cond, &instr->loc)))
3364 return false;
3366
3367 memset(operands, 0, sizeof(operands));
3368 operands[0] = neg;
3369 operands[1] = second;
3370 operands[2] = first;
3371 if (!(replacement = hlsl_new_expr(ctx, HLSL_OP3_CMP, operands, first->data_type, &instr->loc)))
3372 return false;
3373
3374 hlsl_block_add_instr(block, replacement);
3375 return true;
3376}
3377
3378static bool lower_comparison_operators(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr,
3379 struct hlsl_block *block)
3380{
3381 struct hlsl_ir_node *arg1, *arg1_cast, *arg2, *arg2_cast, *slt, *res, *ret;
3382 struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS];
3383 struct hlsl_type *float_type;
3384 struct hlsl_ir_expr *expr;
3385 bool negate = false;
3386
3387 if (instr->type != HLSL_IR_EXPR)
3388 return false;
3389 expr = hlsl_ir_expr(instr);
3390 if (expr->op != HLSL_OP2_EQUAL && expr->op != HLSL_OP2_NEQUAL && expr->op != HLSL_OP2_LESS
3391 && expr->op != HLSL_OP2_GEQUAL)
3392 return false;
3393
3394 arg1 = expr->operands[0].node;
3395 arg2 = expr->operands[1].node;
3396 float_type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, instr->data_type->dimx);
3397
3398 if (!(arg1_cast = hlsl_new_cast(ctx, arg1, float_type, &instr->loc)))
3399 return false;
3400 hlsl_block_add_instr(block, arg1_cast);
3401
3402 if (!(arg2_cast = hlsl_new_cast(ctx, arg2, float_type, &instr->loc)))
3403 return false;
3404 hlsl_block_add_instr(block, arg2_cast);
3405
3406 switch (expr->op)
3407 {
3408 case HLSL_OP2_EQUAL:
3409 case HLSL_OP2_NEQUAL:
3410 {
3411 struct hlsl_ir_node *neg, *sub, *abs, *abs_neg;
3412
3413 if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, arg2_cast, &instr->loc)))
3414 return false;
3416
3417 if (!(sub = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, arg1_cast, neg)))
3418 return false;
3420
3421 if (ctx->profile->major_version >= 3)
3422 {
3423 if (!(abs = hlsl_new_unary_expr(ctx, HLSL_OP1_ABS, sub, &instr->loc)))
3424 return false;
3426 }
3427 else
3428 {
3429 /* Use MUL as a precarious ABS. */
3430 if (!(abs = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, sub, sub)))
3431 return false;
3433 }
3434
3435 if (!(abs_neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, abs, &instr->loc)))
3436 return false;
3437 hlsl_block_add_instr(block, abs_neg);
3438
3439 if (!(slt = hlsl_new_binary_expr(ctx, HLSL_OP2_SLT, abs_neg, abs)))
3440 return false;
3442
3443 negate = (expr->op == HLSL_OP2_EQUAL);
3444 break;
3445 }
3446
3447 case HLSL_OP2_GEQUAL:
3448 case HLSL_OP2_LESS:
3449 {
3450 if (!(slt = hlsl_new_binary_expr(ctx, HLSL_OP2_SLT, arg1_cast, arg2_cast)))
3451 return false;
3453
3454 negate = (expr->op == HLSL_OP2_GEQUAL);
3455 break;
3456 }
3457
3458 default:
3460 }
3461
3462 if (negate)
3463 {
3464 struct hlsl_constant_value one_value;
3465 struct hlsl_ir_node *one, *slt_neg;
3466
3467 one_value.u[0].f = 1.0;
3468 one_value.u[1].f = 1.0;
3469 one_value.u[2].f = 1.0;
3470 one_value.u[3].f = 1.0;
3471 if (!(one = hlsl_new_constant(ctx, float_type, &one_value, &instr->loc)))
3472 return false;
3474
3475 if (!(slt_neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, slt, &instr->loc)))
3476 return false;
3477 hlsl_block_add_instr(block, slt_neg);
3478
3479 if (!(res = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, one, slt_neg)))
3480 return false;
3482 }
3483 else
3484 {
3485 res = slt;
3486 }
3487
3488 /* We need a REINTERPRET so that the HLSL IR code is valid. SLT and its arguments must be FLOAT,
3489 * and casts to BOOL have already been lowered to "!= 0". */
3490 memset(operands, 0, sizeof(operands));
3491 operands[0] = res;
3492 if (!(ret = hlsl_new_expr(ctx, HLSL_OP1_REINTERPRET, operands, instr->data_type, &instr->loc)))
3493 return false;
3495
3496 return true;
3497}
3498
3499/* Intended to be used for SM1-SM3, lowers SLT instructions (only available in vertex shaders) to
3500 * CMP instructions (only available in pixel shaders).
3501 * Based on the following equivalence:
3502 * SLT(x, y)
3503 * = (x < y) ? 1.0 : 0.0
3504 * = ((x - y) >= 0) ? 0.0 : 1.0
3505 * = CMP(x - y, 0.0, 1.0)
3506 */
3507static bool lower_slt(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3508{
3509 struct hlsl_ir_node *arg1, *arg2, *arg1_cast, *arg2_cast, *neg, *sub, *zero, *one, *cmp;
3510 struct hlsl_constant_value zero_value, one_value;
3511 struct hlsl_type *float_type;
3512 struct hlsl_ir_expr *expr;
3513
3514 if (instr->type != HLSL_IR_EXPR)
3515 return false;
3516 expr = hlsl_ir_expr(instr);
3517 if (expr->op != HLSL_OP2_SLT)
3518 return false;
3519
3520 arg1 = expr->operands[0].node;
3521 arg2 = expr->operands[1].node;
3522 float_type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, instr->data_type->dimx);
3523
3524 if (!(arg1_cast = hlsl_new_cast(ctx, arg1, float_type, &instr->loc)))
3525 return false;
3526 hlsl_block_add_instr(block, arg1_cast);
3527
3528 if (!(arg2_cast = hlsl_new_cast(ctx, arg2, float_type, &instr->loc)))
3529 return false;
3530 hlsl_block_add_instr(block, arg2_cast);
3531
3532 if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, arg2_cast, &instr->loc)))
3533 return false;
3535
3536 if (!(sub = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, arg1_cast, neg)))
3537 return false;
3539
3540 memset(&zero_value, 0, sizeof(zero_value));
3541 if (!(zero = hlsl_new_constant(ctx, float_type, &zero_value, &instr->loc)))
3542 return false;
3544
3545 one_value.u[0].f = 1.0;
3546 one_value.u[1].f = 1.0;
3547 one_value.u[2].f = 1.0;
3548 one_value.u[3].f = 1.0;
3549 if (!(one = hlsl_new_constant(ctx, float_type, &one_value, &instr->loc)))
3550 return false;
3552
3554 return false;
3556
3557 return true;
3558}
3559
3560/* Intended to be used for SM1-SM3, lowers CMP instructions (only available in pixel shaders) to
3561 * SLT instructions (only available in vertex shaders).
3562 * Based on the following equivalence:
3563 * CMP(x, y, z)
3564 * = (x >= 0) ? y : z
3565 * = z * ((x < 0) ? 1.0 : 0.0) + y * ((x < 0) ? 0.0 : 1.0)
3566 * = z * SLT(x, 0.0) + y * (1 - SLT(x, 0.0))
3567 */
3568static bool lower_cmp(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3569{
3570 struct hlsl_ir_node *args[3], *args_cast[3], *slt, *neg_slt, *sub, *zero, *one, *mul1, *mul2, *add;
3571 struct hlsl_constant_value zero_value, one_value;
3572 struct hlsl_type *float_type;
3573 struct hlsl_ir_expr *expr;
3574 unsigned int i;
3575
3576 if (instr->type != HLSL_IR_EXPR)
3577 return false;
3578 expr = hlsl_ir_expr(instr);
3579 if (expr->op != HLSL_OP3_CMP)
3580 return false;
3581
3582 float_type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, instr->data_type->dimx);
3583
3584 for (i = 0; i < 3; ++i)
3585 {
3586 args[i] = expr->operands[i].node;
3587
3588 if (!(args_cast[i] = hlsl_new_cast(ctx, args[i], float_type, &instr->loc)))
3589 return false;
3590 hlsl_block_add_instr(block, args_cast[i]);
3591 }
3592
3593 memset(&zero_value, 0, sizeof(zero_value));
3594 if (!(zero = hlsl_new_constant(ctx, float_type, &zero_value, &instr->loc)))
3595 return false;
3597
3598 one_value.u[0].f = 1.0;
3599 one_value.u[1].f = 1.0;
3600 one_value.u[2].f = 1.0;
3601 one_value.u[3].f = 1.0;
3602 if (!(one = hlsl_new_constant(ctx, float_type, &one_value, &instr->loc)))
3603 return false;
3605
3606 if (!(slt = hlsl_new_binary_expr(ctx, HLSL_OP2_SLT, args_cast[0], zero)))
3607 return false;
3609
3610 if (!(mul1 = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, args_cast[2], slt)))
3611 return false;
3613
3614 if (!(neg_slt = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, slt, &instr->loc)))
3615 return false;
3616 hlsl_block_add_instr(block, neg_slt);
3617
3618 if (!(sub = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, one, neg_slt)))
3619 return false;
3621
3622 if (!(mul2 = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, args_cast[1], sub)))
3623 return false;
3625
3626 if (!(add = hlsl_new_binary_expr(ctx, HLSL_OP2_ADD, mul1, mul2)))
3627 return false;
3629
3630 return true;
3631}
3632
3633static bool lower_casts_to_bool(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3634{
3635 struct hlsl_type *type = instr->data_type, *arg_type;
3636 static const struct hlsl_constant_value zero_value;
3637 struct hlsl_ir_node *zero, *neq;
3638 struct hlsl_ir_expr *expr;
3639
3640 if (instr->type != HLSL_IR_EXPR)
3641 return false;
3642 expr = hlsl_ir_expr(instr);
3643 if (expr->op != HLSL_OP1_CAST)
3644 return false;
3645 arg_type = expr->operands[0].node->data_type;
3646 if (type->class > HLSL_CLASS_VECTOR || arg_type->class > HLSL_CLASS_VECTOR)
3647 return false;
3648 if (type->e.numeric.type != HLSL_TYPE_BOOL)
3649 return false;
3650
3651 /* Narrowing casts should have already been lowered. */
3652 VKD3D_ASSERT(type->dimx == arg_type->dimx);
3653
3654 zero = hlsl_new_constant(ctx, arg_type, &zero_value, &instr->loc);
3655 if (!zero)
3656 return false;
3658
3659 if (!(neq = hlsl_new_binary_expr(ctx, HLSL_OP2_NEQUAL, expr->operands[0].node, zero)))
3660 return false;
3661 neq->data_type = expr->node.data_type;
3663
3664 return true;
3665}
3666
3669{
3670 struct hlsl_type *cond_type = condition->data_type;
3671 struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS];
3672 struct hlsl_ir_node *cond;
3673
3674 VKD3D_ASSERT(hlsl_types_are_equal(if_true->data_type, if_false->data_type));
3675
3676 if (cond_type->e.numeric.type != HLSL_TYPE_BOOL)
3677 {
3678 cond_type = hlsl_get_numeric_type(ctx, cond_type->class, HLSL_TYPE_BOOL, cond_type->dimx, cond_type->dimy);
3679
3680 if (!(condition = hlsl_new_cast(ctx, condition, cond_type, &condition->loc)))
3681 return NULL;
3683 }
3684
3685 operands[0] = condition;
3686 operands[1] = if_true;
3687 operands[2] = if_false;
3688 if (!(cond = hlsl_new_expr(ctx, HLSL_OP3_TERNARY, operands, if_true->data_type, &condition->loc)))
3689 return false;
3690 hlsl_block_add_instr(instrs, cond);
3691
3692 return cond;
3693}
3694
3695static bool lower_int_division(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3696{
3697 struct hlsl_ir_node *arg1, *arg2, *xor, *and, *abs1, *abs2, *div, *neg, *cast1, *cast2, *cast3, *high_bit;
3698 struct hlsl_type *type = instr->data_type, *utype;
3699 struct hlsl_constant_value high_bit_value;
3700 struct hlsl_ir_expr *expr;
3701 unsigned int i;
3702
3703 if (instr->type != HLSL_IR_EXPR)
3704 return false;
3705 expr = hlsl_ir_expr(instr);
3706 arg1 = expr->operands[0].node;
3707 arg2 = expr->operands[1].node;
3708 if (expr->op != HLSL_OP2_DIV)
3709 return false;
3710 if (type->class != HLSL_CLASS_SCALAR && type->class != HLSL_CLASS_VECTOR)
3711 return false;
3712 if (type->e.numeric.type != HLSL_TYPE_INT)
3713 return false;
3714 utype = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_UINT, type->dimx, type->dimy);
3715
3717 return false;
3719
3720 for (i = 0; i < type->dimx; ++i)
3721 high_bit_value.u[i].u = 0x80000000;
3722 if (!(high_bit = hlsl_new_constant(ctx, type, &high_bit_value, &instr->loc)))
3723 return false;
3724 hlsl_block_add_instr(block, high_bit);
3725
3726 if (!(and = hlsl_new_binary_expr(ctx, HLSL_OP2_BIT_AND, xor, high_bit)))
3727 return false;
3729
3730 if (!(abs1 = hlsl_new_unary_expr(ctx, HLSL_OP1_ABS, arg1, &instr->loc)))
3731 return false;
3733
3734 if (!(cast1 = hlsl_new_cast(ctx, abs1, utype, &instr->loc)))
3735 return false;
3737
3738 if (!(abs2 = hlsl_new_unary_expr(ctx, HLSL_OP1_ABS, arg2, &instr->loc)))
3739 return false;
3741
3742 if (!(cast2 = hlsl_new_cast(ctx, abs2, utype, &instr->loc)))
3743 return false;
3745
3746 if (!(div = hlsl_new_binary_expr(ctx, HLSL_OP2_DIV, cast1, cast2)))
3747 return false;
3749
3750 if (!(cast3 = hlsl_new_cast(ctx, div, type, &instr->loc)))
3751 return false;
3753
3754 if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, cast3, &instr->loc)))
3755 return false;
3757
3758 return hlsl_add_conditional(ctx, block, and, neg, cast3);
3759}
3760
3761static bool lower_int_modulus(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3762{
3763 struct hlsl_ir_node *arg1, *arg2, *and, *abs1, *abs2, *div, *neg, *cast1, *cast2, *cast3, *high_bit;
3764 struct hlsl_type *type = instr->data_type, *utype;
3765 struct hlsl_constant_value high_bit_value;
3766 struct hlsl_ir_expr *expr;
3767 unsigned int i;
3768
3769 if (instr->type != HLSL_IR_EXPR)
3770 return false;
3771 expr = hlsl_ir_expr(instr);
3772 arg1 = expr->operands[0].node;
3773 arg2 = expr->operands[1].node;
3774 if (expr->op != HLSL_OP2_MOD)
3775 return false;
3776 if (type->class != HLSL_CLASS_SCALAR && type->class != HLSL_CLASS_VECTOR)
3777 return false;
3778 if (type->e.numeric.type != HLSL_TYPE_INT)
3779 return false;
3780 utype = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_UINT, type->dimx, type->dimy);
3781
3782 for (i = 0; i < type->dimx; ++i)
3783 high_bit_value.u[i].u = 0x80000000;
3784 if (!(high_bit = hlsl_new_constant(ctx, type, &high_bit_value, &instr->loc)))
3785 return false;
3786 hlsl_block_add_instr(block, high_bit);
3787
3788 if (!(and = hlsl_new_binary_expr(ctx, HLSL_OP2_BIT_AND, arg1, high_bit)))
3789 return false;
3791
3792 if (!(abs1 = hlsl_new_unary_expr(ctx, HLSL_OP1_ABS, arg1, &instr->loc)))
3793 return false;
3795
3796 if (!(cast1 = hlsl_new_cast(ctx, abs1, utype, &instr->loc)))
3797 return false;
3799
3800 if (!(abs2 = hlsl_new_unary_expr(ctx, HLSL_OP1_ABS, arg2, &instr->loc)))
3801 return false;
3803
3804 if (!(cast2 = hlsl_new_cast(ctx, abs2, utype, &instr->loc)))
3805 return false;
3807
3808 if (!(div = hlsl_new_binary_expr(ctx, HLSL_OP2_MOD, cast1, cast2)))
3809 return false;
3811
3812 if (!(cast3 = hlsl_new_cast(ctx, div, type, &instr->loc)))
3813 return false;
3815
3816 if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, cast3, &instr->loc)))
3817 return false;
3819
3820 return hlsl_add_conditional(ctx, block, and, neg, cast3);
3821}
3822
3823static bool lower_int_abs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3824{
3825 struct hlsl_type *type = instr->data_type;
3826 struct hlsl_ir_node *arg, *neg, *max;
3827 struct hlsl_ir_expr *expr;
3828
3829 if (instr->type != HLSL_IR_EXPR)
3830 return false;
3831 expr = hlsl_ir_expr(instr);
3832
3833 if (expr->op != HLSL_OP1_ABS)
3834 return false;
3835 if (type->class != HLSL_CLASS_SCALAR && type->class != HLSL_CLASS_VECTOR)
3836 return false;
3837 if (type->e.numeric.type != HLSL_TYPE_INT)
3838 return false;
3839
3840 arg = expr->operands[0].node;
3841
3842 if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, arg, &instr->loc)))
3843 return false;
3845
3846 if (!(max = hlsl_new_binary_expr(ctx, HLSL_OP2_MAX, arg, neg)))
3847 return false;
3849
3850 return true;
3851}
3852
3853static bool lower_int_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3854{
3855 struct hlsl_ir_node *arg1, *arg2, *mult, *comps[4] = {0}, *res;
3856 struct hlsl_type *type = instr->data_type;
3857 struct hlsl_ir_expr *expr;
3858 unsigned int i, dimx;
3859 bool is_bool;
3860
3861 if (instr->type != HLSL_IR_EXPR)
3862 return false;
3863 expr = hlsl_ir_expr(instr);
3864
3865 if (expr->op != HLSL_OP2_DOT)
3866 return false;
3867
3868 if (type->e.numeric.type == HLSL_TYPE_INT || type->e.numeric.type == HLSL_TYPE_UINT
3869 || type->e.numeric.type == HLSL_TYPE_BOOL)
3870 {
3871 arg1 = expr->operands[0].node;
3872 arg2 = expr->operands[1].node;
3873 VKD3D_ASSERT(arg1->data_type->dimx == arg2->data_type->dimx);
3874 dimx = arg1->data_type->dimx;
3875 is_bool = type->e.numeric.type == HLSL_TYPE_BOOL;
3876
3878 return false;
3880
3881 for (i = 0; i < dimx; ++i)
3882 {
3884
3885 if (!(comps[i] = hlsl_new_swizzle(ctx, s, 1, mult, &instr->loc)))
3886 return false;
3887 hlsl_block_add_instr(block, comps[i]);
3888 }
3889
3890 res = comps[0];
3891 for (i = 1; i < dimx; ++i)
3892 {
3894 return false;
3896 }
3897
3898 return true;
3899 }
3900
3901 return false;
3902}
3903
3904static bool lower_float_modulus(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3905{
3906 struct hlsl_ir_node *arg1, *arg2, *mul1, *neg1, *ge, *neg2, *div, *mul2, *frc, *cond, *one, *mul3;
3907 struct hlsl_type *type = instr->data_type, *btype;
3908 struct hlsl_constant_value one_value;
3909 struct hlsl_ir_expr *expr;
3910 unsigned int i;
3911
3912 if (instr->type != HLSL_IR_EXPR)
3913 return false;
3914 expr = hlsl_ir_expr(instr);
3915 arg1 = expr->operands[0].node;
3916 arg2 = expr->operands[1].node;
3917 if (expr->op != HLSL_OP2_MOD)
3918 return false;
3919 if (type->class != HLSL_CLASS_SCALAR && type->class != HLSL_CLASS_VECTOR)
3920 return false;
3921 if (type->e.numeric.type != HLSL_TYPE_FLOAT)
3922 return false;
3923 btype = hlsl_get_numeric_type(ctx, type->class, HLSL_TYPE_BOOL, type->dimx, type->dimy);
3924
3926 return false;
3928
3929 if (!(neg1 = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, mul1, &instr->loc)))
3930 return false;
3932
3933 if (!(ge = hlsl_new_binary_expr(ctx, HLSL_OP2_GEQUAL, mul1, neg1)))
3934 return false;
3935 ge->data_type = btype;
3937
3938 if (!(neg2 = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, arg2, &instr->loc)))
3939 return false;
3941
3942 if (!(cond = hlsl_add_conditional(ctx, block, ge, arg2, neg2)))
3943 return false;
3944
3945 for (i = 0; i < type->dimx; ++i)
3946 one_value.u[i].f = 1.0f;
3947 if (!(one = hlsl_new_constant(ctx, type, &one_value, &instr->loc)))
3948 return false;
3950
3951 if (!(div = hlsl_new_binary_expr(ctx, HLSL_OP2_DIV, one, cond)))
3952 return false;
3954
3955 if (!(mul2 = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, div, arg1)))
3956 return false;
3958
3959 if (!(frc = hlsl_new_unary_expr(ctx, HLSL_OP1_FRACT, mul2, &instr->loc)))
3960 return false;
3962
3963 if (!(mul3 = hlsl_new_binary_expr(ctx, HLSL_OP2_MUL, frc, cond)))
3964 return false;
3966
3967 return true;
3968}
3969
3970static bool lower_nonfloat_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
3971{
3972 struct hlsl_ir_expr *expr;
3973
3974 if (instr->type != HLSL_IR_EXPR)
3975 return false;
3976 expr = hlsl_ir_expr(instr);
3977 if (expr->op == HLSL_OP1_CAST || instr->data_type->e.numeric.type == HLSL_TYPE_FLOAT)
3978 return false;
3979
3980 switch (expr->op)
3981 {
3982 case HLSL_OP1_ABS:
3983 case HLSL_OP1_NEG:
3984 case HLSL_OP2_ADD:
3985 case HLSL_OP2_DIV:
3986 case HLSL_OP2_LOGIC_AND:
3987 case HLSL_OP2_LOGIC_OR:
3988 case HLSL_OP2_MAX:
3989 case HLSL_OP2_MIN:
3990 case HLSL_OP2_MUL:
3991 {
3992 struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = {0};
3993 struct hlsl_ir_node *arg, *arg_cast, *float_expr, *ret;
3994 struct hlsl_type *float_type;
3995 unsigned int i;
3996
3997 for (i = 0; i < HLSL_MAX_OPERANDS; ++i)
3998 {
3999 arg = expr->operands[i].node;
4000 if (!arg)
4001 continue;
4002
4003 float_type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, arg->data_type->dimx);
4004 if (!(arg_cast = hlsl_new_cast(ctx, arg, float_type, &instr->loc)))
4005 return false;
4006 hlsl_block_add_instr(block, arg_cast);
4007
4008 operands[i] = arg_cast;
4009 }
4010
4011 float_type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, instr->data_type->dimx);
4012 if (!(float_expr = hlsl_new_expr(ctx, expr->op, operands, float_type, &instr->loc)))
4013 return false;
4014 hlsl_block_add_instr(block, float_expr);
4015
4016 if (!(ret = hlsl_new_cast(ctx, float_expr, instr->data_type, &instr->loc)))
4017 return false;
4019
4020 return true;
4021 }
4022 default:
4023 return false;
4024 }
4025}
4026
4027static bool lower_discard_neg(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
4028{
4029 struct hlsl_ir_node *zero, *bool_false, *or, *cmp, *load;
4030 static const struct hlsl_constant_value zero_value;
4031 struct hlsl_type *arg_type, *cmp_type;
4032 struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS] = { 0 };
4033 struct hlsl_ir_jump *jump;
4034 struct hlsl_block block;
4035 unsigned int i, count;
4036
4037 if (instr->type != HLSL_IR_JUMP)
4038 return false;
4039 jump = hlsl_ir_jump(instr);
4040 if (jump->type != HLSL_IR_JUMP_DISCARD_NEG)
4041 return false;
4042
4044
4045 arg_type = jump->condition.node->data_type;
4046 if (!(zero = hlsl_new_constant(ctx, arg_type, &zero_value, &instr->loc)))
4047 return false;
4049
4050 operands[0] = jump->condition.node;
4051 operands[1] = zero;
4052 cmp_type = hlsl_get_numeric_type(ctx, arg_type->class, HLSL_TYPE_BOOL, arg_type->dimx, arg_type->dimy);
4053 if (!(cmp = hlsl_new_expr(ctx, HLSL_OP2_LESS, operands, cmp_type, &instr->loc)))
4054 return false;
4056
4057 if (!(bool_false = hlsl_new_constant(ctx, hlsl_get_scalar_type(ctx, HLSL_TYPE_BOOL), &zero_value, &instr->loc)))
4058 return false;
4059 hlsl_block_add_instr(&block, bool_false);
4060
4061 or = bool_false;
4062
4063 count = hlsl_type_component_count(cmp_type);
4064 for (i = 0; i < count; ++i)
4065 {
4066 if (!(load = hlsl_add_load_component(ctx, &block, cmp, i, &instr->loc)))
4067 return false;
4068
4070#ifdef __REACTOS__
4071 return false;
4072#else
4073 return NULL;
4074#endif
4076 }
4077
4078 list_move_tail(&instr->entry, &block.instrs);
4079 hlsl_src_remove(&jump->condition);
4080 hlsl_src_from_node(&jump->condition, or);
4082
4083 return true;
4084}
4085
4086static bool lower_discard_nz(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
4087{
4088 struct hlsl_ir_node *cond, *cond_cast, *abs, *neg;
4089 struct hlsl_type *float_type;
4090 struct hlsl_ir_jump *jump;
4091 struct hlsl_block block;
4092
4093 if (instr->type != HLSL_IR_JUMP)
4094 return false;
4095 jump = hlsl_ir_jump(instr);
4096 if (jump->type != HLSL_IR_JUMP_DISCARD_NZ)
4097 return false;
4098
4099 cond = jump->condition.node;
4100 float_type = hlsl_get_vector_type(ctx, HLSL_TYPE_FLOAT, cond->data_type->dimx);
4101
4103
4104 if (!(cond_cast = hlsl_new_cast(ctx, cond, float_type, &instr->loc)))
4105 return false;
4106 hlsl_block_add_instr(&block, cond_cast);
4107
4108 if (!(abs = hlsl_new_unary_expr(ctx, HLSL_OP1_ABS, cond_cast, &instr->loc)))
4109 return false;
4111
4112 if (!(neg = hlsl_new_unary_expr(ctx, HLSL_OP1_NEG, abs, &instr->loc)))
4113 return false;
4115
4116 list_move_tail(&instr->entry, &block.instrs);
4117 hlsl_src_remove(&jump->condition);
4118 hlsl_src_from_node(&jump->condition, neg);
4120
4121 return true;
4122}
4123
4124static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
4125{
4126 switch (instr->type)
4127 {
4128 case HLSL_IR_CONSTANT:
4129 case HLSL_IR_COMPILE:
4130 case HLSL_IR_EXPR:
4131 case HLSL_IR_INDEX:
4132 case HLSL_IR_LOAD:
4135 case HLSL_IR_SWIZZLE:
4137 if (list_empty(&instr->uses))
4138 {
4139 list_remove(&instr->entry);
4140 hlsl_free_instr(instr);
4141 return true;
4142 }
4143 break;
4144
4145 case HLSL_IR_STORE:
4146 {
4147 struct hlsl_ir_store *store = hlsl_ir_store(instr);
4148 struct hlsl_ir_var *var = store->lhs.var;
4149
4150 if (var->last_read < instr->index)
4151 {
4152 list_remove(&instr->entry);
4153 hlsl_free_instr(instr);
4154 return true;
4155 }
4156 break;
4157 }
4158
4159 case HLSL_IR_CALL:
4160 case HLSL_IR_IF:
4161 case HLSL_IR_JUMP:
4162 case HLSL_IR_LOOP:
4164 case HLSL_IR_SWITCH:
4165 break;
4167 /* Stateblock constants should not appear in the shader program. */
4170 /* HLSL IR nodes are not translated to hlsl_ir_vsir_instruction_ref at this point. */
4172 }
4173
4174 return false;
4175}
4176
4177static void dump_function(struct rb_entry *entry, void *context)
4178{
4180 struct hlsl_ir_function_decl *decl;
4181 struct hlsl_ctx *ctx = context;
4182
4183 LIST_FOR_EACH_ENTRY(decl, &func->overloads, struct hlsl_ir_function_decl, entry)
4184 {
4185 if (decl->has_body)
4186 hlsl_dump_function(ctx, decl);
4187 }
4188}
4189
4190static bool mark_indexable_var(struct hlsl_ctx *ctx, struct hlsl_deref *deref,
4191 struct hlsl_ir_node *instr)
4192{
4193 if (!deref->rel_offset.node)
4194 return false;
4195
4196 VKD3D_ASSERT(deref->var);
4197 VKD3D_ASSERT(deref->rel_offset.node->type != HLSL_IR_CONSTANT);
4198 deref->var->indexable = true;
4199
4200 return true;
4201}
4202
4203static void mark_indexable_vars(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
4204{
4205 struct hlsl_scope *scope;
4206 struct hlsl_ir_var *var;
4207
4208 LIST_FOR_EACH_ENTRY(scope, &ctx->scopes, struct hlsl_scope, entry)
4209 {
4211 var->indexable = false;
4212 }
4213
4215}
4216
4218{
4219 switch (regset)
4220 {
4222 return 's';
4224 return 't';
4225 case HLSL_REGSET_UAVS:
4226 return 'u';
4229 }
4231}
4232
4233static void allocate_register_reservations(struct hlsl_ctx *ctx, struct list *extern_vars)
4234{
4235 struct hlsl_ir_var *var;
4236
4237 LIST_FOR_EACH_ENTRY(var, extern_vars, struct hlsl_ir_var, extern_entry)
4238 {
4239 const struct hlsl_reg_reservation *reservation = &var->reg_reservation;
4240 unsigned int r;
4241
4242 if (reservation->reg_type)
4243 {
4244 for (r = 0; r <= HLSL_REGSET_LAST_OBJECT; ++r)
4245 {
4246 if (var->regs[r].allocation_size > 0)
4247 {
4248 if (reservation->reg_type != get_regset_name(r))
4249 {
4250 struct vkd3d_string_buffer *type_string;
4251
4252 /* We can throw this error because resources can only span across a single
4253 * regset, but we have to check for multiple regsets if we support register
4254 * reservations for structs for SM5. */
4255 type_string = hlsl_type_to_string(ctx, var->data_type);
4257 "Object of type '%s' must be bound to register type '%c'.",
4258 type_string->buffer, get_regset_name(r));
4259 hlsl_release_string_buffer(ctx, type_string);
4260 }
4261 else
4262 {
4263 var->regs[r].allocated = true;
4264 var->regs[r].space = reservation->reg_space;
4265 var->regs[r].index = reservation->reg_index;
4266 }
4267 }
4268 }
4269 }
4270 }
4271}
4272
4273static void deref_mark_last_read(struct hlsl_deref *deref, unsigned int last_read)
4274{
4275 unsigned int i;
4276
4277 if (hlsl_deref_is_lowered(deref))
4278 {
4279 if (deref->rel_offset.node)
4280 deref->rel_offset.node->last_read = last_read;
4281 }
4282 else
4283 {
4284 for (i = 0; i < deref->path_len; ++i)
4285 deref->path[i].node->last_read = last_read;
4286 }
4287}
4288
4289/* Compute the earliest and latest liveness for each variable. In the case that
4290 * a variable is accessed inside of a loop, we promote its liveness to extend
4291 * to at least the range of the entire loop. We also do this for nodes, so that
4292 * nodes produced before the loop have their temp register protected from being
4293 * overridden after the last read within an iteration. */
4294static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop_first, unsigned int loop_last)
4295{
4296 struct hlsl_ir_node *instr;
4297 struct hlsl_ir_var *var;
4298
4299 LIST_FOR_EACH_ENTRY(instr, &block->instrs, struct hlsl_ir_node, entry)
4300 {
4301 const unsigned int last_read = loop_last ? max(instr->index, loop_last) : instr->index;
4302
4303 switch (instr->type)
4304 {
4305 case HLSL_IR_CALL:
4306 /* We should have inlined all calls before computing liveness. */
4309 /* Stateblock constants should not appear in the shader program. */
4312 /* HLSL IR nodes are not translated to hlsl_ir_vsir_instruction_ref at this point. */
4314
4315 case HLSL_IR_STORE:
4316 {
4317 struct hlsl_ir_store *store = hlsl_ir_store(instr);
4318
4319 var = store->lhs.var;
4320 if (!var->first_write)
4321 var->first_write = loop_first ? min(instr->index, loop_first) : instr->index;
4322 store->rhs.node->last_read = last_read;
4323 deref_mark_last_read(&store->lhs, last_read);
4324 break;
4325 }
4326 case HLSL_IR_EXPR:
4327 {
4328 struct hlsl_ir_expr *expr = hlsl_ir_expr(instr);
4329 unsigned int i;
4330
4331 for (i = 0; i < ARRAY_SIZE(expr->operands) && expr->operands[i].node; ++i)
4332 expr->operands[i].node->last_read = last_read;
4333 break;
4334 }
4335 case HLSL_IR_IF:
4336 {
4337 struct hlsl_ir_if *iff = hlsl_ir_if(instr);
4338
4339 compute_liveness_recurse(&iff->then_block, loop_first, loop_last);
4340 compute_liveness_recurse(&iff->else_block, loop_first, loop_last);
4341 iff->condition.node->last_read = last_read;
4342 break;
4343 }
4344 case HLSL_IR_LOAD:
4345 {
4346 struct hlsl_ir_load *load = hlsl_ir_load(instr);
4347
4348 var = load->src.var;
4349 var->last_read = max(var->last_read, last_read);
4350 deref_mark_last_read(&load->src, last_read);
4351 break;
4352 }
4353 case HLSL_IR_LOOP:
4354 {
4355 struct hlsl_ir_loop *loop = hlsl_ir_loop(instr);
4356
4357 compute_liveness_recurse(&loop->body, loop_first ? loop_first : instr->index,
4358 loop_last ? loop_last : loop->next_index);
4359 break;
4360 }
4362 {
4364
4365 var = load->resource.var;
4366 var->last_read = max(var->last_read, last_read);
4367 deref_mark_last_read(&load->resource, last_read);
4368
4369 if ((var = load->sampler.var))
4370 {
4371 var->last_read = max(var->last_read, last_read);
4372 deref_mark_last_read(&load->sampler, last_read);
4373 }
4374
4375 if (load->coords.node)
4376 load->coords.node->last_read = last_read;
4377 if (load->texel_offset.node)
4378 load->texel_offset.node->last_read = last_read;
4379 if (load->lod.node)
4380 load->lod.node->last_read = last_read;
4381 if (load->ddx.node)
4382 load->ddx.node->last_read = last_read;
4383 if (load->ddy.node)
4384 load->ddy.node->last_read = last_read;
4385 if (load->sample_index.node)
4386 load->sample_index.node->last_read = last_read;
4387 if (load->cmp.node)
4388 load->cmp.node->last_read = last_read;
4389 break;
4390 }
4392 {
4393 struct hlsl_ir_resource_store *store = hlsl_ir_resource_store(instr);
4394
4395 var = store->resource.var;
4396 var->last_read = max(var->last_read, last_read);
4397 deref_mark_last_read(&store->resource, last_read);
4398 store->coords.node->last_read = last_read;
4399 store->value.node->last_read = last_read;
4400 break;
4401 }
4402 case HLSL_IR_SWIZZLE:
4403 {
4404 struct hlsl_ir_swizzle *swizzle = hlsl_ir_swizzle(instr);
4405
4406 swizzle->val.node->last_read = last_read;
4407 break;
4408 }
4409 case HLSL_IR_INDEX:
4410 {
4411 struct hlsl_ir_index *index = hlsl_ir_index(instr);
4412
4413 index->val.node->last_read = last_read;
4414 index->idx.node->last_read = last_read;
4415 break;
4416 }
4417 case HLSL_IR_JUMP:
4418 {
4419 struct hlsl_ir_jump *jump = hlsl_ir_jump(instr);
4420
4421 if (jump->condition.node)
4422 jump->condition.node->last_read = last_read;
4423 break;
4424 }
4425 case HLSL_IR_SWITCH:
4426 {
4427 struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
4428 struct hlsl_ir_switch_case *c;
4429
4431 compute_liveness_recurse(&c->body, loop_first, loop_last);
4432 s->selector.node->last_read = last_read;
4433 break;
4434 }
4435 case HLSL_IR_CONSTANT:
4437 break;
4438 case HLSL_IR_COMPILE:
4440 /* These types are skipped as they are only relevant to effects. */
4441 break;
4442 }
4443 }
4444}
4445
4447{
4448 if (var->is_uniform || var->is_input_semantic)
4449 var->first_write = 1;
4450 else if (var->is_output_semantic)
4451 var->last_read = UINT_MAX;
4452}
4453
4454static void compute_liveness(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
4455{
4456 struct hlsl_scope *scope;
4457 struct hlsl_ir_var *var;
4458
4459 index_instructions(&entry_func->body, 2);
4460
4461 LIST_FOR_EACH_ENTRY(scope, &ctx->scopes, struct hlsl_scope, entry)
4462 {
4464 var->first_write = var->last_read = 0;
4465 }
4466
4467 LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
4469
4472
4473 compute_liveness_recurse(&entry_func->body, 0, 0);
4474}
4475
4476static void mark_vars_usage(struct hlsl_ctx *ctx)
4477{
4478 struct hlsl_scope *scope;
4479 struct hlsl_ir_var *var;
4480
4481 LIST_FOR_EACH_ENTRY(scope, &ctx->scopes, struct hlsl_scope, entry)
4482 {
4484 {
4485 if (var->last_read)
4486 var->is_read = true;
4487 }
4488 }
4489}
4490
4492{
4494 {
4496 unsigned int writemask;
4497 unsigned int first_write, last_read;
4498
4499 /* Two allocations with different mode can't share the same register. */
4500 int mode;
4503
4504 /* Indexable temps are allocated separately and always keep their index regardless of their
4505 * lifetime. */
4507
4508 /* Total number of registers allocated so far. Used to declare sm4 temp count. */
4510
4511 /* Special flag so allocations that can share registers prioritize those
4512 * that will result in smaller writemasks.
4513 * For instance, a single-register allocation would prefer to share a register
4514 * whose .xy components are already allocated (becoming .z) instead of a
4515 * register whose .xyz components are already allocated (becoming .w). */
4517};
4518
4519static unsigned int get_available_writemask(const struct register_allocator *allocator,
4520 unsigned int first_write, unsigned int last_read, uint32_t reg_idx, int mode)
4521{
4522 unsigned int writemask = VKD3DSP_WRITEMASK_ALL;
4523 size_t i;
4524
4525 for (i = 0; i < allocator->count; ++i)
4526 {
4527 const struct allocation *allocation = &allocator->allocations[i];
4528
4529 /* We do not overlap if first write == last read:
4530 * this is the case where we are allocating the result of that
4531 * expression, e.g. "add r0, r0, r1". */
4532
4533 if (allocation->reg == reg_idx
4534 && first_write < allocation->last_read && last_read > allocation->first_write)
4535 {
4536 writemask &= ~allocation->writemask;
4537 if (allocation->mode != mode)
4538 writemask = 0;
4539 }
4540
4541 if (!writemask)
4542 break;
4543 }
4544
4545 return writemask;
4546}
4547
4549 unsigned int writemask, unsigned int first_write, unsigned int last_read, int mode)
4550{
4551 struct allocation *allocation;
4552
4553 if (!hlsl_array_reserve(ctx, (void **)&allocator->allocations, &allocator->capacity,
4554 allocator->count + 1, sizeof(*allocator->allocations)))
4555 return;
4556
4557 allocation = &allocator->allocations[allocator->count++];
4558 allocation->reg = reg_idx;
4559 allocation->writemask = writemask;
4560 allocation->first_write = first_write;
4561 allocation->last_read = last_read;
4562 allocation->mode = mode;
4563
4564 allocator->reg_count = max(allocator->reg_count, reg_idx + 1);
4565}
4566
4567/* reg_size is the number of register components to be reserved, while component_count is the number
4568 * of components for the register's writemask. In SM1, floats and vectors allocate the whole
4569 * register, even if they don't use it completely. */
4571 unsigned int first_write, unsigned int last_read, unsigned int reg_size,
4572 unsigned int component_count, int mode, bool force_align)
4573{
4574 struct hlsl_reg ret = {.allocation_size = 1, .allocated = true};
4575 unsigned int required_size = force_align ? 4 : reg_size;
4576 unsigned int pref;
4577
4579
4580 pref = allocator->prioritize_smaller_writemasks ? 4 : required_size;
4581 for (; pref >= required_size; --pref)
4582 {
4583 for (uint32_t reg_idx = 0; reg_idx < allocator->reg_count; ++reg_idx)
4584 {
4585 unsigned int available_writemask = get_available_writemask(allocator,
4586 first_write, last_read, reg_idx, mode);
4587
4588 if (vkd3d_popcount(available_writemask) >= pref)
4589 {
4590 unsigned int writemask = hlsl_combine_writemasks(available_writemask,
4592
4593 ret.id = reg_idx;
4596 record_allocation(ctx, allocator, reg_idx, writemask, first_write, last_read, mode);
4597 return ret;
4598 }
4599 }
4600 }
4601
4602 ret.id = allocator->reg_count;
4605 vkd3d_write_mask_from_component_count(reg_size), first_write, last_read, mode);
4606 return ret;
4607}
4608
4609/* Allocate a register with writemask, while reserving reg_writemask. */
4611 unsigned int first_write, unsigned int last_read, uint32_t reg_writemask, uint32_t writemask, int mode)
4612{
4613 struct hlsl_reg ret = {0};
4614 uint32_t reg_idx;
4615
4616 VKD3D_ASSERT((reg_writemask & writemask) == writemask);
4617
4618 for (reg_idx = 0;; ++reg_idx)
4619 {
4620 if ((get_available_writemask(allocator, first_write, last_read,
4621 reg_idx, mode) & reg_writemask) == reg_writemask)
4622 break;
4623 }
4624
4625 record_allocation(ctx, allocator, reg_idx, reg_writemask, first_write, last_read, mode);
4626
4627 ret.id = reg_idx;
4628 ret.allocation_size = 1;
4629 ret.writemask = writemask;
4630 ret.allocated = true;
4631 return ret;
4632}
4633
4634static bool is_range_available(const struct register_allocator *allocator, unsigned int first_write,
4635 unsigned int last_read, uint32_t reg_idx, unsigned int reg_size, int mode)
4636{
4637 unsigned int last_reg_mask = (1u << (reg_size % 4)) - 1;
4638 unsigned int writemask;
4639 uint32_t i;
4640
4641 for (i = 0; i < (reg_size / 4); ++i)
4642 {
4643 writemask = get_available_writemask(allocator, first_write, last_read, reg_idx + i, mode);
4645 return false;
4646 }
4647 writemask = get_available_writemask(allocator, first_write, last_read, reg_idx + (reg_size / 4), mode);
4648 if ((writemask & last_reg_mask) != last_reg_mask)
4649 return false;
4650 return true;
4651}
4652
4654 unsigned int first_write, unsigned int last_read, unsigned int reg_size, int mode)
4655{
4656 struct hlsl_reg ret = {0};
4657 uint32_t reg_idx;
4658 unsigned int i;
4659
4660 for (reg_idx = 0;; ++reg_idx)
4661 {
4662 if (is_range_available(allocator, first_write, last_read, reg_idx, reg_size, mode))
4663 break;
4664 }
4665
4666 for (i = 0; i < reg_size / 4; ++i)
4667 record_allocation(ctx, allocator, reg_idx + i, VKD3DSP_WRITEMASK_ALL, first_write, last_read, mode);
4668 if (reg_size % 4)
4669 record_allocation(ctx, allocator, reg_idx + (reg_size / 4),
4670 (1u << (reg_size % 4)) - 1, first_write, last_read, mode);
4671
4672 ret.id = reg_idx;
4673 ret.allocation_size = align(reg_size, 4) / 4;
4674 ret.allocated = true;
4675 return ret;
4676}
4677
4679 unsigned int first_write, unsigned int last_read, const struct hlsl_type *type)
4680{
4681 unsigned int reg_size = type->reg_size[HLSL_REGSET_NUMERIC];
4682
4683 /* FIXME: We could potentially pack structs or arrays more efficiently... */
4684
4685 if (type->class <= HLSL_CLASS_VECTOR)
4686 return allocate_register(ctx, allocator, first_write, last_read, type->dimx, type->dimx, 0, false);
4687 else
4688 return allocate_range(ctx, allocator, first_write, last_read, reg_size, 0);
4689}
4690
4691static const char *debug_register(char class, struct hlsl_reg reg, const struct hlsl_type *type)
4692{
4693 static const char writemask_offset[] = {'w','x','y','z'};
4694 unsigned int reg_size = type->reg_size[HLSL_REGSET_NUMERIC];
4695
4696 if (reg_size > 4)
4697 {
4698 if (reg_size & 3)
4699 return vkd3d_dbg_sprintf("%c%u-%c%u.%c", class, reg.id, class, reg.id + (reg_size / 4),
4700 writemask_offset[reg_size & 3]);
4701
4702 return vkd3d_dbg_sprintf("%c%u-%c%u", class, reg.id, class, reg.id + (reg_size / 4) - 1);
4703 }
4704 return vkd3d_dbg_sprintf("%c%u%s", class, reg.id, debug_hlsl_writemask(reg.writemask));
4705}
4706
4707static bool track_object_components_sampler_dim(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
4708{
4710 struct hlsl_ir_var *var;
4711 enum hlsl_regset regset;
4712 unsigned int index;
4713
4714 if (instr->type != HLSL_IR_RESOURCE_LOAD)
4715 return false;
4716
4717 load = hlsl_ir_resource_load(instr);
4718 var = load->resource.var;
4719
4720 regset = hlsl_deref_get_regset(ctx, &load->resource);
4721 if (!hlsl_regset_index_from_deref(ctx, &load->resource, regset, &index))
4722 return false;
4723
4725 {
4726 enum hlsl_sampler_dim dim;
4727
4728 VKD3D_ASSERT(!load->sampler.var);
4729
4730 dim = var->objects_usage[regset][index].sampler_dim;
4731 if (dim != load->sampling_dim)
4732 {
4733 if (dim == HLSL_SAMPLER_DIM_GENERIC)
4734 {
4735 var->objects_usage[regset][index].first_sampler_dim_loc = instr->loc;
4736 }
4737 else
4738 {
4740 "Inconsistent generic sampler usage dimension.");
4741 hlsl_note(ctx, &var->objects_usage[regset][index].first_sampler_dim_loc,
4742 VKD3D_SHADER_LOG_ERROR, "First use is here.");
4743 return false;
4744 }
4745 }
4746 }
4747 var->objects_usage[regset][index].sampler_dim = load->sampling_dim;
4748
4749 return false;
4750}
4751
4752static void register_deref_usage(struct hlsl_ctx *ctx, struct hlsl_deref *deref)
4753{
4754 struct hlsl_ir_var *var = deref->var;
4756 uint32_t required_bind_count;
4757 struct hlsl_type *type;
4758 unsigned int index;
4759
4761 return;
4762
4764 {
4765 var->objects_usage[regset][index].used = true;
4766 var->bind_count[regset] = max(var->bind_count[regset], index + 1);
4767 }
4768 else if (regset == HLSL_REGSET_NUMERIC)
4769 {
4770 type = hlsl_deref_get_type(ctx, deref);
4771
4773 required_bind_count = align(index + type->reg_size[regset], 4) / 4;
4774 var->bind_count[regset] = max(var->bind_count[regset], required_bind_count);
4775 }
4776 else
4777 {
4779 }
4780}
4781
4782static bool track_components_usage(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
4783{
4784 switch (instr->type)
4785 {
4786 case HLSL_IR_LOAD:
4787 {
4788 struct hlsl_ir_load *load = hlsl_ir_load(instr);
4789
4790 if (!load->src.var->is_uniform)
4791 return false;
4792
4793 /* These will are handled by validate_static_object_references(). */
4795 return false;
4796
4798 break;
4799 }
4800
4803 if (hlsl_ir_resource_load(instr)->sampler.var)
4805 break;
4806
4809 break;
4810
4811 default:
4812 break;
4813 }
4814
4815 return false;
4816}
4817
4819{
4820 struct hlsl_ir_var *var;
4821 struct hlsl_type *type;
4822 unsigned int k;
4823
4824 LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
4825 {
4826 type = var->data_type;
4827
4828 for (k = 0; k <= HLSL_REGSET_LAST_OBJECT; ++k)
4829 {
4830 bool is_separated = var->is_separated_resource;
4831
4832 if (var->bind_count[k] > 0)
4833 var->regs[k].allocation_size = (k == HLSL_REGSET_SAMPLERS || is_separated) ? var->bind_count[k] : type->reg_size[k];
4834 }
4835 }
4836}
4837
4839 struct hlsl_ir_node *instr, struct register_allocator *allocator)
4840{
4841 unsigned int reg_writemask = 0, dst_writemask = 0;
4842
4843 if (instr->reg.allocated || !instr->last_read)
4844 return;
4845
4846 if (instr->type == HLSL_IR_EXPR)
4847 {
4848 switch (hlsl_ir_expr(instr)->op)
4849 {
4851 dst_writemask = VKD3DSP_WRITEMASK_0;
4852 reg_writemask = ctx->profile->major_version < 3 ? (1 << 3) - 1 : VKD3DSP_WRITEMASK_0;
4853 break;
4854
4856 dst_writemask = VKD3DSP_WRITEMASK_1;
4857 reg_writemask = ctx->profile->major_version < 3 ? (1 << 3) - 1 : VKD3DSP_WRITEMASK_1;
4858 break;
4859
4860 default:
4861 break;
4862 }
4863 }
4864
4865 if (reg_writemask)
4867 instr->index, instr->last_read, reg_writemask, dst_writemask, 0);
4868 else
4870 instr->index, instr->last_read, instr->data_type);
4871
4872 TRACE("Allocated anonymous expression @%u to %s (liveness %u-%u).\n", instr->index,
4873 debug_register('r', instr->reg, instr->data_type), instr->index, instr->last_read);
4874}
4875
4878{
4879 if (var->is_input_semantic || var->is_output_semantic || var->is_uniform)
4880 return;
4881
4882 if (!var->regs[HLSL_REGSET_NUMERIC].allocated && var->last_read)
4883 {
4884 if (var->indexable)
4885 {
4886 var->regs[HLSL_REGSET_NUMERIC].id = allocator->indexable_count++;
4887 var->regs[HLSL_REGSET_NUMERIC].allocation_size = 1;
4888 var->regs[HLSL_REGSET_NUMERIC].writemask = 0;
4889 var->regs[HLSL_REGSET_NUMERIC].allocated = true;
4890
4891 TRACE("Allocated %s to x%u[].\n", var->name, var->regs[HLSL_REGSET_NUMERIC].id);
4892 }
4893 else
4894 {
4896 var->first_write, var->last_read, var->data_type);
4897
4898 TRACE("Allocated %s to %s (liveness %u-%u).\n", var->name, debug_register('r',
4899 var->regs[HLSL_REGSET_NUMERIC], var->data_type), var->first_write, var->last_read);
4900 }
4901 }
4902}
4903
4906{
4907 struct hlsl_ir_node *instr;
4908
4909 LIST_FOR_EACH_ENTRY(instr, &block->instrs, struct hlsl_ir_node, entry)
4910 {
4911 /* In SM4 all constants are inlined. */
4912 if (ctx->profile->major_version >= 4 && instr->type == HLSL_IR_CONSTANT)
4913 continue;
4914
4916
4917 switch (instr->type)
4918 {
4919 case HLSL_IR_IF:
4920 {
4921 struct hlsl_ir_if *iff = hlsl_ir_if(instr);
4924 break;
4925 }
4926
4927 case HLSL_IR_LOAD:
4928 {
4929 struct hlsl_ir_load *load = hlsl_ir_load(instr);
4930 /* We need to at least allocate a variable for undefs.
4931 * FIXME: We should probably find a way to remove them instead. */
4933 break;
4934 }
4935
4936 case HLSL_IR_LOOP:
4937 {
4938 struct hlsl_ir_loop *loop = hlsl_ir_loop(instr);
4940 break;
4941 }
4942
4943 case HLSL_IR_STORE:
4944 {
4945 struct hlsl_ir_store *store = hlsl_ir_store(instr);
4947 break;
4948 }
4949
4950 case HLSL_IR_SWITCH:
4951 {
4952 struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
4953 struct hlsl_ir_switch_case *c;
4954
4956 {
4958 }
4959 break;
4960 }
4961
4962 default:
4963 break;
4964 }
4965 }
4966}
4967
4968static void record_constant(struct hlsl_ctx *ctx, unsigned int component_index, float f,
4969 const struct vkd3d_shader_location *loc)
4970{
4971 struct hlsl_constant_defs *defs = &ctx->constant_defs;
4972 struct hlsl_constant_register *reg;
4973 size_t i;
4974
4975 for (i = 0; i < defs->count; ++i)
4976 {
4977 reg = &defs->regs[i];
4978 if (reg->index == (component_index / 4))
4979 {
4980 reg->value.f[component_index % 4] = f;
4981 return;
4982 }
4983 }
4984
4985 if (!hlsl_array_reserve(ctx, (void **)&defs->regs, &defs->size, defs->count + 1, sizeof(*defs->regs)))
4986 return;
4987 reg = &defs->regs[defs->count++];
4988 memset(reg, 0, sizeof(*reg));
4989 reg->index = component_index / 4;
4990 reg->value.f[component_index % 4] = f;
4991 reg->loc = *loc;
4992}
4993
4996{
4997 struct hlsl_ir_node *instr;
4998
4999 LIST_FOR_EACH_ENTRY(instr, &block->instrs, struct hlsl_ir_node, entry)
5000 {
5001 switch (instr->type)
5002 {
5003 case HLSL_IR_CONSTANT:
5004 {
5006 const struct hlsl_type *type = instr->data_type;
5007 unsigned int x, i;
5008
5010 TRACE("Allocated constant @%u to %s.\n", instr->index, debug_register('c', constant->reg, type));
5011
5013 VKD3D_ASSERT(type->dimy == 1);
5014 VKD3D_ASSERT(constant->reg.writemask);
5015
5016 for (x = 0, i = 0; x < 4; ++x)
5017 {
5019 float f;
5020
5021 if (!(constant->reg.writemask & (1u << x)))
5022 continue;
5023 value = &constant->value.u[i++];
5024
5025 switch (type->e.numeric.type)
5026 {
5027 case HLSL_TYPE_BOOL:
5028 f = !!value->u;
5029 break;
5030
5031 case HLSL_TYPE_FLOAT:
5032 case HLSL_TYPE_HALF:
5033 f = value->f;
5034 break;
5035
5036 case HLSL_TYPE_INT:
5037 f = value->i;
5038 break;
5039
5040 case HLSL_TYPE_UINT:
5041 f = value->u;
5042 break;
5043
5044 case HLSL_TYPE_DOUBLE:
5045 FIXME("Double constant.\n");
5046 return;
5047
5048 default:
5050 }
5051
5052 record_constant(ctx, constant->reg.id * 4 + x, f, &constant->node.loc);
5053 }
5054
5055 break;
5056 }
5057
5058 case HLSL_IR_IF:
5059 {
5060 struct hlsl_ir_if *iff = hlsl_ir_if(instr);
5063 break;
5064 }
5065
5066 case HLSL_IR_LOOP:
5067 {
5068 struct hlsl_ir_loop *loop = hlsl_ir_loop(instr);
5070 break;
5071 }
5072
5073 case HLSL_IR_SWITCH:
5074 {
5075 struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
5076 struct hlsl_ir_switch_case *c;
5077
5079 {
5081 }
5082 break;
5083 }
5084
5085 default:
5086 break;
5087 }
5088 }
5089}
5090
5091static void sort_uniform_by_numeric_bind_count(struct list *sorted, struct hlsl_ir_var *to_sort)
5092{
5093 struct hlsl_ir_var *var;
5094
5095 list_remove(&to_sort->extern_entry);
5096
5098 {
5099 uint32_t to_sort_size = to_sort->bind_count[HLSL_REGSET_NUMERIC];
5100 uint32_t var_size = var->bind_count[HLSL_REGSET_NUMERIC];
5101
5102 if (to_sort_size > var_size)
5103 {
5104 list_add_before(&var->extern_entry, &to_sort->extern_entry);
5105 return;
5106 }
5107 }
5108
5109 list_add_tail(sorted, &to_sort->extern_entry);
5110}
5111
5113{
5114 struct list sorted = LIST_INIT(sorted);
5115 struct hlsl_ir_var *var, *next;
5116
5118 {
5119 if (var->is_uniform)
5121 }
5122 list_move_tail(&ctx->extern_vars, &sorted);
5123}
5124
5125/* In SM2, 'sincos' expects specific constants as src1 and src2 arguments.
5126 * These have to be referenced directly, i.e. as 'c' not 'r'. */
5129{
5130 const struct hlsl_ir_node *instr;
5131 struct hlsl_type *type;
5132
5133 if (ctx->profile->major_version >= 3)
5134 return;
5135
5136 LIST_FOR_EACH_ENTRY(instr, &block->instrs, struct hlsl_ir_node, entry)
5137 {
5138 if (instr->type == HLSL_IR_EXPR && (hlsl_ir_expr(instr)->op == HLSL_OP1_SIN_REDUCED
5139 || hlsl_ir_expr(instr)->op == HLSL_OP1_COS_REDUCED))
5140 {
5142
5144 TRACE("Allocated D3DSINCOSCONST1 to %s.\n", debug_register('c', ctx->d3dsincosconst1, type));
5145 record_constant(ctx, ctx->d3dsincosconst1.id * 4 + 0, -1.55009923e-06f, &instr->loc);
5146 record_constant(ctx, ctx->d3dsincosconst1.id * 4 + 1, -2.17013894e-05f, &instr->loc);
5147 record_constant(ctx, ctx->d3dsincosconst1.id * 4 + 2, 2.60416674e-03f, &instr->loc);
5148 record_constant(ctx, ctx->d3dsincosconst1.id * 4 + 3, 2.60416680e-04f, &instr->loc);
5149
5151 TRACE("Allocated D3DSINCOSCONST2 to %s.\n", debug_register('c', ctx->d3dsincosconst2, type));
5152 record_constant(ctx, ctx->d3dsincosconst2.id * 4 + 0, -2.08333340e-02f, &instr->loc);
5153 record_constant(ctx, ctx->d3dsincosconst2.id * 4 + 1, -1.25000000e-01f, &instr->loc);
5154 record_constant(ctx, ctx->d3dsincosconst2.id * 4 + 2, 1.00000000e+00f, &instr->loc);
5155 record_constant(ctx, ctx->d3dsincosconst2.id * 4 + 3, 5.00000000e-01f, &instr->loc);
5156
5157 return;
5158 }
5159 }
5160}
5161
5162static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
5163{
5164 struct register_allocator allocator_used = {0};
5165 struct register_allocator allocator = {0};
5166 struct hlsl_ir_var *var;
5167
5169
5170 LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
5171 {
5172 unsigned int reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC];
5173 unsigned int bind_count = var->bind_count[HLSL_REGSET_NUMERIC];
5174
5175 if (!var->is_uniform || reg_size == 0)
5176 continue;
5177
5178 if (var->reg_reservation.reg_type == 'c')
5179 {
5180 unsigned int reg_idx = var->reg_reservation.reg_index;
5181 unsigned int i;
5182
5183 VKD3D_ASSERT(reg_size % 4 == 0);
5184 for (i = 0; i < reg_size / 4; ++i)
5185 {
5186 if (i < bind_count)
5187 {
5188 if (get_available_writemask(&allocator_used, 1, UINT_MAX, reg_idx + i, 0) != VKD3DSP_WRITEMASK_ALL)
5189 {
5191 "Overlapping register() reservations on 'c%u'.", reg_idx + i);
5192 }
5193 record_allocation(ctx, &allocator_used, reg_idx + i, VKD3DSP_WRITEMASK_ALL, 1, UINT_MAX, 0);
5194 }
5196 }
5197
5198 var->regs[HLSL_REGSET_NUMERIC].id = reg_idx;
5199 var->regs[HLSL_REGSET_NUMERIC].allocation_size = reg_size / 4;
5201 var->regs[HLSL_REGSET_NUMERIC].allocated = true;
5202 TRACE("Allocated reserved %s to %s.\n", var->name,
5203 debug_register('c', var->regs[HLSL_REGSET_NUMERIC], var->data_type));
5204 }
5205 }
5206
5207 vkd3d_free(allocator_used.allocations);
5208
5209 LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
5210 {
5211 unsigned int alloc_size = 4 * var->bind_count[HLSL_REGSET_NUMERIC];
5212
5213 if (!var->is_uniform || alloc_size == 0)
5214 continue;
5215
5216 if (!var->regs[HLSL_REGSET_NUMERIC].allocated)
5217 {
5218 var->regs[HLSL_REGSET_NUMERIC] = allocate_range(ctx, &allocator, 1, UINT_MAX, alloc_size, 0);
5219 TRACE("Allocated %s to %s.\n", var->name,
5220 debug_register('c', var->regs[HLSL_REGSET_NUMERIC], var->data_type));
5221 }
5222 }
5223
5225
5227
5228 vkd3d_free(allocator.allocations);
5229}
5230
5231/* Simple greedy temporary register allocation pass that just assigns a unique
5232 * index to all (simultaneously live) variables or intermediate values. Agnostic
5233 * as to how many registers are actually available for the current backend, and
5234 * does not handle constants. */
5236{
5237 struct register_allocator allocator = {0};
5238 struct hlsl_scope *scope;
5239 struct hlsl_ir_var *var;
5240
5241 /* Reset variable temp register allocations. */
5242 LIST_FOR_EACH_ENTRY(scope, &ctx->scopes, struct hlsl_scope, entry)
5243 {
5245 {
5246 if (!(var->is_input_semantic || var->is_output_semantic || var->is_uniform))
5247 memset(var->regs, 0, sizeof(var->regs));
5248 }
5249 }
5250
5251 /* ps_1_* outputs are special and go in temp register 0. */
5252 if (ctx->profile->major_version == 1 && ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL)
5253 {
5254 size_t i;
5255
5256 for (i = 0; i < entry_func->parameters.count; ++i)
5257 {
5258 var = entry_func->parameters.vars[i];
5259 if (var->is_output_semantic)
5260 {
5261 record_allocation(ctx, &allocator, 0, VKD3DSP_WRITEMASK_ALL, var->first_write, var->last_read, 0);
5262 break;
5263 }
5264 }
5265 }
5266
5268 vkd3d_free(allocator.allocations);
5269
5270 return allocator.reg_count;
5271}
5272
5274{
5275 unsigned int i;
5276
5277 static const struct
5278 {
5279 unsigned int modifiers;
5281 }
5282 modes[] =
5283 {
5288 };
5289
5292 return VKD3DSIM_CONSTANT;
5293
5294 for (i = 0; i < ARRAY_SIZE(modes); ++i)
5295 {
5296 if ((storage_modifiers & modes[i].modifiers) == modes[i].modifiers)
5297 return modes[i].mode;
5298 }
5299
5300 return VKD3DSIM_LINEAR;
5301}
5302
5304 struct register_allocator *allocator, bool output, bool optimize, bool is_patch_constant_func)
5305{
5306 static const char *const shader_names[] =
5307 {
5308 [VKD3D_SHADER_TYPE_PIXEL] = "Pixel",
5309 [VKD3D_SHADER_TYPE_VERTEX] = "Vertex",
5310 [VKD3D_SHADER_TYPE_GEOMETRY] = "Geometry",
5311 [VKD3D_SHADER_TYPE_HULL] = "Hull",
5312 [VKD3D_SHADER_TYPE_DOMAIN] = "Domain",
5313 [VKD3D_SHADER_TYPE_COMPUTE] = "Compute",
5314 };
5315
5318 uint32_t reg;
5319 bool builtin;
5320
5321 VKD3D_ASSERT(var->semantic.name);
5322
5323 version.major = ctx->profile->major_version;
5324 version.minor = ctx->profile->minor_version;
5325 version.type = ctx->profile->type;
5326
5327 if (version.major < 4)
5328 {
5331
5332 /* ps_1_* outputs are special and go in temp register 0. */
5333 if (version.major == 1 && output && version.type == VKD3D_SHADER_TYPE_PIXEL)
5334 return;
5335
5337 var->semantic.name, var->semantic.index, output, &type, &reg);
5338 if (!builtin && !sm1_usage_from_semantic_name(var->semantic.name, var->semantic.index, &usage, &usage_idx))
5339 {
5341 "Invalid semantic '%s'.", var->semantic.name);
5342 return;
5343 }
5344
5345 if ((!output && !var->last_read) || (output && !var->first_write))
5346 return;
5347 }
5348 else
5349 {
5350 enum vkd3d_shader_sysval_semantic semantic;
5351 bool has_idx;
5352
5353 if (!sm4_sysval_semantic_from_semantic_name(&semantic, &version, ctx->semantic_compat_mapping,
5354 ctx->domain, var->semantic.name, var->semantic.index, output, is_patch_constant_func))
5355 {
5357 "Invalid semantic '%s'.", var->semantic.name);
5358 return;
5359 }
5360
5361 if ((builtin = sm4_register_from_semantic_name(&version, var->semantic.name, output, &type, &has_idx)))
5362 reg = has_idx ? var->semantic.index : 0;
5363
5364 if (semantic == VKD3D_SHADER_SV_TESS_FACTOR_TRIINT)
5365 {
5366 /* While SV_InsideTessFactor can be declared as 'float' for "tri"
5367 * domains, it is allocated as if it was 'float[1]'. */
5368 var->force_align = true;
5369 }
5370 }
5371
5372 if (builtin)
5373 {
5374 TRACE("%s %s semantic %s[%u] matches predefined register %#x[%u].\n", shader_names[version.type],
5375 output ? "output" : "input", var->semantic.name, var->semantic.index, type, reg);
5376 }
5377 else
5378 {
5379 int mode = (ctx->profile->major_version < 4)
5380 ? 0 : sm4_get_interpolation_mode(var->data_type, var->storage_modifiers);
5381 unsigned int reg_size = optimize ? var->data_type->dimx : 4;
5382
5384 UINT_MAX, reg_size, var->data_type->dimx, mode, var->force_align);
5385
5386 TRACE("Allocated %s to %s (mode %d).\n", var->name, debug_register(output ? 'o' : 'v',
5387 var->regs[HLSL_REGSET_NUMERIC], var->data_type), mode);
5388 }
5389}
5390
5391static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
5392{
5393 struct register_allocator input_allocator = {0}, output_allocator = {0};
5394 bool is_vertex_shader = ctx->profile->type == VKD3D_SHADER_TYPE_VERTEX;
5395 bool is_pixel_shader = ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL;
5396 bool is_patch_constant_func = entry_func == ctx->patch_constant_func;
5397 struct hlsl_ir_var *var;
5398
5399 input_allocator.prioritize_smaller_writemasks = true;
5400 output_allocator.prioritize_smaller_writemasks = true;
5401
5403 {
5404 if (var->is_input_semantic)
5405 allocate_semantic_register(ctx, var, &input_allocator, false, !is_vertex_shader, is_patch_constant_func);
5406 if (var->is_output_semantic)
5407 allocate_semantic_register(ctx, var, &output_allocator, true, !is_pixel_shader, is_patch_constant_func);
5408 }
5409
5410 vkd3d_free(input_allocator.allocations);
5411 vkd3d_free(output_allocator.allocations);
5412}
5413
5414static const struct hlsl_buffer *get_reserved_buffer(struct hlsl_ctx *ctx,
5415 uint32_t space, uint32_t index, bool allocated_only)
5416{
5417 const struct hlsl_buffer *buffer;
5418
5419 LIST_FOR_EACH_ENTRY(buffer, &ctx->buffers, const struct hlsl_buffer, entry)
5420 {
5421 if (buffer->reservation.reg_type == 'b'
5422 && buffer->reservation.reg_space == space && buffer->reservation.reg_index == index)
5423 {
5424 if (allocated_only && !buffer->reg.allocated)
5425 continue;
5426
5427 return buffer;
5428 }
5429 }
5430 return NULL;
5431}
5432
5433static void hlsl_calculate_buffer_offset(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, bool register_reservation)
5434{
5435 unsigned int var_reg_size = var->data_type->reg_size[HLSL_REGSET_NUMERIC];
5436 enum hlsl_type_class var_class = var->data_type->class;
5437 struct hlsl_buffer *buffer = var->buffer;
5438
5439 if (register_reservation)
5440 {
5441 var->buffer_offset = 4 * var->reg_reservation.reg_index;
5442 var->has_explicit_bind_point = 1;
5443 }
5444 else
5445 {
5446 if (var->reg_reservation.offset_type == 'c')
5447 {
5448 if (var->reg_reservation.offset_index % 4)
5449 {
5450 if (var_class == HLSL_CLASS_MATRIX)
5451 {
5453 "packoffset() reservations with matrix types must be aligned with the beginning of a register.");
5454 }
5455 else if (var_class == HLSL_CLASS_ARRAY)
5456 {
5458 "packoffset() reservations with array types must be aligned with the beginning of a register.");
5459 }
5460 else if (var_class == HLSL_CLASS_STRUCT)
5461 {
5463 "packoffset() reservations with struct types must be aligned with the beginning of a register.");
5464 }
5465 else if (var_class == HLSL_CLASS_VECTOR)
5466 {
5467 unsigned int aligned_offset = hlsl_type_get_sm4_offset(var->data_type, var->reg_reservation.offset_index);
5468
5469 if (var->reg_reservation.offset_index != aligned_offset)
5471 "packoffset() reservations with vector types cannot span multiple registers.");
5472 }
5473 }
5474 var->buffer_offset = var->reg_reservation.offset_index;
5475 var->has_explicit_bind_point = 1;
5476 }
5477 else
5478 {
5479 var->buffer_offset = hlsl_type_get_sm4_offset(var->data_type, buffer->size);
5480 }
5481 }
5482
5483 TRACE("Allocated buffer offset %u to %s.\n", var->buffer_offset, var->name);
5484 buffer->size = max(buffer->size, var->buffer_offset + var_reg_size);
5485 if (var->is_read)
5486 buffer->used_size = max(buffer->used_size, var->buffer_offset + var_reg_size);
5487}
5488
5490{
5491 struct hlsl_ir_var *var1, *var2;
5492 struct hlsl_buffer *buffer;
5493
5494 LIST_FOR_EACH_ENTRY(var1, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
5495 {
5496 if (!var1->is_uniform || hlsl_type_is_resource(var1->data_type))
5497 continue;
5498
5499 buffer = var1->buffer;
5500 if (!buffer->used_size)
5501 continue;
5502
5503 LIST_FOR_EACH_ENTRY(var2, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
5504 {
5505 unsigned int var1_reg_size, var2_reg_size;
5506
5507 if (!var2->is_uniform || hlsl_type_is_resource(var2->data_type))
5508 continue;
5509
5510 if (var1 == var2 || var1->buffer != var2->buffer)
5511 continue;
5512
5513 /* This is to avoid reporting the error twice for the same pair of overlapping variables. */
5514 if (strcmp(var1->name, var2->name) >= 0)
5515 continue;
5516
5517 var1_reg_size = var1->data_type->reg_size[HLSL_REGSET_NUMERIC];
5518 var2_reg_size = var2->data_type->reg_size[HLSL_REGSET_NUMERIC];
5519
5520 if (var1->buffer_offset < var2->buffer_offset + var2_reg_size
5521 && var2->buffer_offset < var1->buffer_offset + var1_reg_size)
5523 "Invalid packoffset() reservation: Variables %s and %s overlap.",
5524 var1->name, var2->name);
5525 }
5526 }
5527
5528 LIST_FOR_EACH_ENTRY(var1, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
5529 {
5530 buffer = var1->buffer;
5531 if (!buffer || buffer == ctx->globals_buffer)
5532 continue;
5533
5534 if (var1->reg_reservation.offset_type
5535 || var1->reg_reservation.reg_type == 's'
5536 || var1->reg_reservation.reg_type == 't'
5537 || var1->reg_reservation.reg_type == 'u')
5538 buffer->manually_packed_elements = true;
5539 else
5540 buffer->automatically_packed_elements = true;
5541
5542 if (buffer->manually_packed_elements && buffer->automatically_packed_elements)
5543 {
5545 "packoffset() must be specified for all the buffer elements, or none of them.");
5546 break;
5547 }
5548 }
5549}
5550
5552{
5553 struct hlsl_ir_var *var;
5554
5555 LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
5556 {
5557 if (!var->is_uniform || hlsl_type_is_resource(var->data_type))
5558 continue;
5559
5562 }
5563
5564 LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
5565 {
5566 if (!var->is_uniform || hlsl_type_is_resource(var->data_type))
5567 continue;
5568
5571 }
5572}
5573
5574static unsigned int get_max_cbuffer_reg_index(struct hlsl_ctx *ctx)
5575{
5576 if (hlsl_version_ge(ctx, 5, 1))
5577 return UINT_MAX;
5578
5579 return 13;
5580}
5581
5582static void allocate_buffers(struct hlsl_ctx *ctx)
5583{
5584 struct hlsl_buffer *buffer;
5585 uint32_t index = 0, id = 0;
5586 struct hlsl_ir_var *var;
5587
5588 LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
5589 {
5590 if (!var->is_uniform || hlsl_type_is_resource(var->data_type))
5591 continue;
5592
5593 if (var->is_param)
5594 var->buffer = ctx->params_buffer;
5595 }
5596
5599
5600 LIST_FOR_EACH_ENTRY(buffer, &ctx->buffers, struct hlsl_buffer, entry)
5601 {
5602 if (!buffer->used_size)
5603 continue;
5604
5605 if (buffer->type == HLSL_BUFFER_CONSTANT)
5606 {
5607 const struct hlsl_reg_reservation *reservation = &buffer->reservation;
5608
5609 if (reservation->reg_type == 'b')
5610 {
5611 const struct hlsl_buffer *allocated_buffer = get_reserved_buffer(ctx,
5612 reservation->reg_space, reservation->reg_index, true);
5613 unsigned int max_index = get_max_cbuffer_reg_index(ctx);
5614
5615 if (buffer->reservation.reg_index > max_index)
5617 "Buffer reservation cb%u exceeds target's maximum (cb%u).",
5618 buffer->reservation.reg_index, max_index);
5619
5620 if (allocated_buffer && allocated_buffer != buffer)
5621 {
5623 "Multiple buffers bound to space %u, index %u.",
5624 reservation->reg_space, reservation->reg_index);
5625 hlsl_note(ctx, &allocated_buffer->loc, VKD3D_SHADER_LOG_ERROR,
5626 "Buffer %s is already bound to space %u, index %u.",
5627 allocated_buffer->name, reservation->reg_space, reservation->reg_index);
5628 }
5629
5630 buffer->reg.space = reservation->reg_space;
5631 buffer->reg.index = reservation->reg_index;
5632 if (hlsl_version_ge(ctx, 5, 1))
5633 buffer->reg.id = id++;
5634 else
5635 buffer->reg.id = buffer->reg.index;
5636 buffer->reg.allocation_size = 1;
5637 buffer->reg.allocated = true;
5638 TRACE("Allocated reserved %s to space %u, index %u, id %u.\n",
5639 buffer->name, buffer->reg.space, buffer->reg.index, buffer->reg.id);
5640 }
5641 else if (!reservation->reg_type)
5642 {
5643 unsigned int max_index = get_max_cbuffer_reg_index(ctx);
5644 while (get_reserved_buffer(ctx, 0, index, false))
5645 ++index;
5646
5647 if (index > max_index)
5649 "Too many buffers reserved, target's maximum is %u.", max_index);
5650
5651 buffer->reg.space = 0;
5652 buffer->reg.index = index;
5653 if (hlsl_version_ge(ctx, 5, 1))
5654 buffer->reg.id = id++;
5655 else
5656 buffer->reg.id = buffer->reg.index;
5657 buffer->reg.allocation_size = 1;
5658 buffer->reg.allocated = true;
5659 TRACE("Allocated %s to space 0, index %u, id %u.\n", buffer->name, buffer->reg.index, buffer->reg.id);
5660 ++index;
5661 }
5662 else
5663 {
5665 "Constant buffers must be allocated to register type 'b'.");
5666 }
5667 }
5668 else
5669 {
5670 FIXME("Allocate registers for texture buffers.\n");
5671 }
5672 }
5673}
5674
5676 uint32_t space, uint32_t index, bool allocated_only)
5677{
5678 const struct hlsl_ir_var *var;
5679 unsigned int start, count;
5680
5681 LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, const struct hlsl_ir_var, extern_entry)
5682 {
5683 if (var->reg_reservation.reg_type == get_regset_name(regset)
5684 && var->data_type->reg_size[regset])
5685 {
5686 /* Vars with a reservation prevent non-reserved vars from being
5687 * bound there even if the reserved vars aren't used. */
5688 start = var->reg_reservation.reg_index;
5689 count = var->data_type->reg_size[regset];
5690
5691 if (var->reg_reservation.reg_space != space)
5692 continue;
5693
5694 if (!var->regs[regset].allocated && allocated_only)
5695 continue;
5696 }
5697 else if (var->regs[regset].allocated)
5698 {
5699 if (var->regs[regset].space != space)
5700 continue;
5701
5702 start = var->regs[regset].index;
5703 count = var->regs[regset].allocation_size;
5704 }
5705 else
5706 {
5707 continue;
5708 }
5709
5710 if (start <= index && index < start + count)
5711 return var;
5712 }
5713 return NULL;
5714}
5715
5717{
5718 char regset_name = get_regset_name(regset);
5719 uint32_t min_index = 0, id = 0;
5720 struct hlsl_ir_var *var;
5721
5722 if (regset == HLSL_REGSET_UAVS && ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL)
5723 {
5724 LIST_FOR_EACH_ENTRY(var, &func->extern_vars, struct hlsl_ir_var, extern_entry)
5725 {
5726 if (var->semantic.name && (!ascii_strcasecmp(var->semantic.name, "color")
5727 || !ascii_strcasecmp(var->semantic.name, "sv_target")))
5728 min_index = max(min_index, var->semantic.index + 1);
5729 }
5730 }
5731
5732 LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
5733 {
5734 unsigned int count = var->regs[regset].allocation_size;
5735
5736 if (count == 0)
5737 continue;
5738
5739 /* The variable was already allocated if it has a reservation. */
5740 if (var->regs[regset].allocated)
5741 {
5742 const struct hlsl_ir_var *reserved_object, *last_reported = NULL;
5743 unsigned int i;
5744
5745 if (var->regs[regset].index < min_index)
5746 {
5749 "UAV index (%u) must be higher than the maximum render target index (%u).",
5750 var->regs[regset].index, min_index - 1);
5751 continue;
5752 }
5753
5754 for (i = 0; i < count; ++i)
5755 {
5756 unsigned int space = var->regs[regset].space;
5757 unsigned int index = var->regs[regset].index + i;
5758
5759 /* get_allocated_object() may return "var" itself, but we
5760 * actually want that, otherwise we'll end up reporting the
5761 * same conflict between the same two variables twice. */
5762 reserved_object = get_allocated_object(ctx, regset, space, index, true);
5763 if (reserved_object && reserved_object != var && reserved_object != last_reported)
5764 {
5766 "Multiple variables bound to space %u, %c%u.", regset_name, space, index);
5767 hlsl_note(ctx, &reserved_object->loc, VKD3D_SHADER_LOG_ERROR,
5768 "Variable '%s' is already bound to space %u, %c%u.",
5769 reserved_object->name, regset_name, space, index);
5770 last_reported = reserved_object;
5771 }
5772 }
5773
5774 if (hlsl_version_ge(ctx, 5, 1))
5775 var->regs[regset].id = id++;
5776 else
5777 var->regs[regset].id = var->regs[regset].index;
5778 TRACE("Allocated reserved variable %s to space %u, indices %c%u-%c%u, id %u.\n",
5779 var->name, var->regs[regset].space, regset_name, var->regs[regset].index,
5780 regset_name, var->regs[regset].index + count, var->regs[regset].id);
5781 }
5782 else
5783 {
5784 unsigned int index = min_index;
5785 unsigned int available = 0;
5786
5787 while (available < count)
5788 {
5789 if (get_allocated_object(ctx, regset, 0, index, false))
5790 available = 0;
5791 else
5792 ++available;
5793 ++index;
5794 }
5795 index -= count;
5796
5797 var->regs[regset].space = 0;
5798 var->regs[regset].index = index;
5799 if (hlsl_version_ge(ctx, 5, 1))
5800 var->regs[regset].id = id++;
5801 else
5802 var->regs[regset].id = var->regs[regset].index;
5803 var->regs[regset].allocated = true;
5804 TRACE("Allocated variable %s to space 0, indices %c%u-%c%u, id %u.\n", var->name,
5805 regset_name, index, regset_name, index + count, var->regs[regset].id);
5806 ++index;
5807 }
5808 }
5809}
5810
5812 unsigned int *start, unsigned int *count)
5813{
5814 struct hlsl_type *type = deref->var->data_type;
5815 unsigned int i, k;
5816
5817 *start = 0;
5818 *count = 0;
5819
5820 for (i = 0; i < deref->path_len; ++i)
5821 {
5822 struct hlsl_ir_node *path_node = deref->path[i].node;
5823 unsigned int idx = 0;
5824
5825 VKD3D_ASSERT(path_node);
5826 if (path_node->type != HLSL_IR_CONSTANT)
5827 return false;
5828
5829 /* We should always have generated a cast to UINT. */
5830 VKD3D_ASSERT(path_node->data_type->class == HLSL_CLASS_SCALAR
5831 && path_node->data_type->e.numeric.type == HLSL_TYPE_UINT);
5832
5833 idx = hlsl_ir_constant(path_node)->value.u[0].u;
5834
5835 switch (type->class)
5836 {
5837 case HLSL_CLASS_VECTOR:
5838 if (idx >= type->dimx)
5839 return false;
5840 *start += idx;
5841 break;
5842
5843 case HLSL_CLASS_MATRIX:
5845 return false;
5847 *start += idx * type->dimx;
5848 else
5849 *start += idx * type->dimy;
5850 break;
5851
5852 case HLSL_CLASS_ARRAY:
5853 if (idx >= type->e.array.elements_count)
5854 return false;
5855 *start += idx * hlsl_type_component_count(type->e.array.type);
5856 break;
5857
5858 case HLSL_CLASS_STRUCT:
5859 for (k = 0; k < idx; ++k)
5860 *start += hlsl_type_component_count(type->e.record.fields[k].type);
5861 break;
5862
5863 default:
5865 }
5866
5868 }
5869
5871 return true;
5872}
5873
5874/* Retrieves true if the index is constant, and false otherwise. In the latter case, the maximum
5875 * possible index is retrieved, assuming there is not out-of-bounds access. */
5876bool hlsl_regset_index_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref,
5877 enum hlsl_regset regset, unsigned int *index)
5878{
5879 struct hlsl_type *type = deref->var->data_type;
5880 bool index_is_constant = true;
5881 unsigned int i;
5882
5883 *index = 0;
5884
5885 for (i = 0; i < deref->path_len; ++i)
5886 {
5887 struct hlsl_ir_node *path_node = deref->path[i].node;
5888 unsigned int idx = 0;
5889
5890 VKD3D_ASSERT(path_node);
5891 if (path_node->type == HLSL_IR_CONSTANT)
5892 {
5893 /* We should always have generated a cast to UINT. */
5894 VKD3D_ASSERT(path_node->data_type->class == HLSL_CLASS_SCALAR
5895 && path_node->data_type->e.numeric.type == HLSL_TYPE_UINT);
5896
5897 idx = hlsl_ir_constant(path_node)->value.u[0].u;
5898
5899 switch (type->class)
5900 {
5901 case HLSL_CLASS_ARRAY:
5902 if (idx >= type->e.array.elements_count)
5903 return false;
5904
5905 *index += idx * type->e.array.type->reg_size[regset];
5906 break;
5907
5908 case HLSL_CLASS_STRUCT:
5909 *index += type->e.record.fields[idx].reg_offset[regset];
5910 break;
5911
5912 case HLSL_CLASS_MATRIX:
5913 *index += 4 * idx;
5914 break;
5915
5916 default:
5918 }
5919 }
5920 else
5921 {
5922 index_is_constant = false;
5923
5924 switch (type->class)
5925 {
5926 case HLSL_CLASS_ARRAY:
5927 idx = type->e.array.elements_count - 1;
5928 *index += idx * type->e.array.type->reg_size[regset];
5929 break;
5930
5931 case HLSL_CLASS_MATRIX:
5933 *index += idx * 4;
5934 break;
5935
5936 default:
5938 }
5939 }
5940
5942 }
5943
5944 VKD3D_ASSERT(!(regset <= HLSL_REGSET_LAST_OBJECT) || (type->reg_size[regset] == 1));
5945 VKD3D_ASSERT(!(regset == HLSL_REGSET_NUMERIC) || type->reg_size[regset] <= 4);
5946 return index_is_constant;
5947}
5948
5949bool hlsl_offset_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, unsigned int *offset)
5950{
5952 struct hlsl_ir_node *offset_node = deref->rel_offset.node;
5953 unsigned int size;
5954
5955 *offset = deref->const_offset;
5956
5957 if (offset_node)
5958 {
5959 /* We should always have generated a cast to UINT. */
5960 VKD3D_ASSERT(offset_node->data_type->class == HLSL_CLASS_SCALAR
5961 && offset_node->data_type->e.numeric.type == HLSL_TYPE_UINT);
5962 VKD3D_ASSERT(offset_node->type != HLSL_IR_CONSTANT);
5963 return false;
5964 }
5965
5966 size = deref->var->data_type->reg_size[regset];
5967 if (*offset >= size)
5968 {
5969 /* FIXME: Report a more specific location for the constant deref. */
5971 "Dereference is out of bounds. %u/%u", *offset, size);
5972 return false;
5973 }
5974
5975 return true;
5976}
5977
5978unsigned int hlsl_offset_from_deref_safe(struct hlsl_ctx *ctx, const struct hlsl_deref *deref)
5979{
5980 unsigned int offset;
5981
5982 if (hlsl_offset_from_deref(ctx, deref, &offset))
5983 return offset;
5984
5985 if (deref->rel_offset.node)
5986 hlsl_fixme(ctx, &deref->rel_offset.node->loc, "Dereference with non-constant offset of type %s.",
5987 hlsl_node_type_to_string(deref->rel_offset.node->type));
5988
5989 return 0;
5990}
5991
5993{
5994 const struct hlsl_ir_var *var = deref->var;
5995 struct hlsl_reg ret = var->regs[HLSL_REGSET_NUMERIC];
5996 unsigned int offset = hlsl_offset_from_deref_safe(ctx, deref);
5997
5998 VKD3D_ASSERT(deref->data_type);
5999 VKD3D_ASSERT(hlsl_is_numeric_type(deref->data_type));
6000
6001 ret.index += offset / 4;
6002 ret.id += offset / 4;
6003
6004 ret.writemask = 0xf & (0xf << (offset % 4));
6005 if (var->regs[HLSL_REGSET_NUMERIC].writemask)
6006 ret.writemask = hlsl_combine_writemasks(var->regs[HLSL_REGSET_NUMERIC].writemask, ret.writemask);
6007
6008 return ret;
6009}
6010
6011static const char *get_string_argument_value(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr, unsigned int i)
6012{
6013 const struct hlsl_ir_node *instr = attr->args[i].node;
6014 const struct hlsl_type *type = instr->data_type;
6015
6016 if (type->class != HLSL_CLASS_STRING)
6017 {
6019
6020 if ((string = hlsl_type_to_string(ctx, type)))
6022 "Wrong type for the argument %u of [%s]: expected string, but got %s.",
6023 i, attr->name, string->buffer);
6025 return NULL;
6026 }
6027
6028 return hlsl_ir_string_constant(instr)->string;
6029}
6030
6031static void parse_numthreads_attribute(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr)
6032{
6033 unsigned int i;
6034
6035 ctx->found_numthreads = 1;
6036
6037 if (attr->args_count != 3)
6038 {
6040 "Expected 3 parameters for [numthreads] attribute, but got %u.", attr->args_count);
6041 return;
6042 }
6043
6044 for (i = 0; i < attr->args_count; ++i)
6045 {
6046 const struct hlsl_ir_node *instr = attr->args[i].node;
6047 const struct hlsl_type *type = instr->data_type;
6048 const struct hlsl_ir_constant *constant;
6049
6050 if (type->class != HLSL_CLASS_SCALAR
6051 || (type->e.numeric.type != HLSL_TYPE_INT && type->e.numeric.type != HLSL_TYPE_UINT))
6052 {
6054
6055 if ((string = hlsl_type_to_string(ctx, type)))
6057 "Wrong type for argument %u of [numthreads]: expected int or uint, but got %s.",
6058 i, string->buffer);
6060 break;
6061 }
6062
6063 if (instr->type != HLSL_IR_CONSTANT)
6064 {
6065 hlsl_fixme(ctx, &instr->loc, "Non-constant expression in [numthreads] initializer.");
6066 break;
6067 }
6068 constant = hlsl_ir_constant(instr);
6069
6070 if ((type->e.numeric.type == HLSL_TYPE_INT && constant->value.u[0].i <= 0)
6071 || (type->e.numeric.type == HLSL_TYPE_UINT && !constant->value.u[0].u))
6073 "Thread count must be a positive integer.");
6074
6075 ctx->thread_count[i] = constant->value.u[0].u;
6076 }
6077}
6078
6079static void parse_domain_attribute(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr)
6080{
6081 const char *value;
6082
6083 if (attr->args_count != 1)
6084 {
6086 "Expected 1 parameter for [domain] attribute, but got %u.", attr->args_count);
6087 return;
6088 }
6089
6091 return;
6092
6093 if (!strcmp(value, "isoline"))
6095 else if (!strcmp(value, "tri"))
6097 else if (!strcmp(value, "quad"))
6099 else
6101 "Invalid tessellator domain \"%s\": expected \"isoline\", \"tri\", or \"quad\".",
6102 value);
6103}
6104
6106{
6107 const struct hlsl_ir_node *instr;
6108 const struct hlsl_type *type;
6109 const struct hlsl_ir_constant *constant;
6110
6111 if (attr->args_count != 1)
6112 {
6114 "Expected 1 parameter for [outputcontrolpoints] attribute, but got %u.", attr->args_count);
6115 return;
6116 }
6117
6118 instr = attr->args[0].node;
6119 type = instr->data_type;
6120
6121 if (type->class != HLSL_CLASS_SCALAR
6122 || (type->e.numeric.type != HLSL_TYPE_INT && type->e.numeric.type != HLSL_TYPE_UINT))
6123 {
6125
6126 if ((string = hlsl_type_to_string(ctx, type)))
6128 "Wrong type for argument 0 of [outputcontrolpoints]: expected int or uint, but got %s.",
6129 string->buffer);
6131 return;
6132 }
6133
6134 if (instr->type != HLSL_IR_CONSTANT)
6135 {
6136 hlsl_fixme(ctx, &instr->loc, "Non-constant expression in [outputcontrolpoints] initializer.");
6137 return;
6138 }
6139 constant = hlsl_ir_constant(instr);
6140
6141 if ((type->e.numeric.type == HLSL_TYPE_INT && constant->value.u[0].i < 0)
6142 || constant->value.u[0].u > 32)
6144 "Output control point count must be between 0 and 32.");
6145
6146 ctx->output_control_point_count = constant->value.u[0].u;
6147}
6148
6150{
6151 const char *value;
6152
6153 if (attr->args_count != 1)
6154 {
6156 "Expected 1 parameter for [outputtopology] attribute, but got %u.", attr->args_count);
6157 return;
6158 }
6159
6161 return;
6162
6163 if (!strcmp(value, "point"))
6164 ctx->output_primitive = VKD3D_SHADER_TESSELLATOR_OUTPUT_POINT;
6165 else if (!strcmp(value, "line"))
6166 ctx->output_primitive = VKD3D_SHADER_TESSELLATOR_OUTPUT_LINE;
6167 else if (!strcmp(value, "triangle_cw"))
6169 else if (!strcmp(value, "triangle_ccw"))
6171 else
6173 "Invalid tessellator output topology \"%s\": "
6174 "expected \"point\", \"line\", \"triangle_cw\", or \"triangle_ccw\".", value);
6175}
6176
6178{
6179 const char *value;
6180
6181 if (attr->args_count != 1)
6182 {
6184 "Expected 1 parameter for [partitioning] attribute, but got %u.", attr->args_count);
6185 return;
6186 }
6187
6189 return;
6190
6191 if (!strcmp(value, "integer"))
6193 else if (!strcmp(value, "pow2"))
6195 else if (!strcmp(value, "fractional_even"))
6197 else if (!strcmp(value, "fractional_odd"))
6199 else
6201 "Invalid tessellator partitioning \"%s\": "
6202 "expected \"integer\", \"pow2\", \"fractional_even\", or \"fractional_odd\".", value);
6203}
6204
6206{
6207 const char *name;
6208 struct hlsl_ir_function *func;
6209 struct hlsl_ir_function_decl *decl;
6210
6211 if (attr->args_count != 1)
6212 {
6214 "Expected 1 parameter for [patchconstantfunc] attribute, but got %u.", attr->args_count);
6215 return;
6216 }
6217
6218 if (!(name = get_string_argument_value(ctx, attr, 0)))
6219 return;
6220
6221 ctx->patch_constant_func = NULL;
6222 if ((func = hlsl_get_function(ctx, name)))
6223 {
6224 /* Pick the last overload with a body. */
6225 LIST_FOR_EACH_ENTRY_REV(decl, &func->overloads, struct hlsl_ir_function_decl, entry)
6226 {
6227 if (decl->has_body)
6228 {
6229 ctx->patch_constant_func = decl;
6230 break;
6231 }
6232 }
6233 }
6234
6235 if (!ctx->patch_constant_func)
6237 "Patch constant function \"%s\" is not defined.", name);
6238}
6239
6241{
6242 const struct hlsl_profile_info *profile = ctx->profile;
6243 unsigned int i;
6244
6245 for (i = 0; i < entry_func->attr_count; ++i)
6246 {
6247 const struct hlsl_attribute *attr = entry_func->attrs[i];
6248
6249 if (!strcmp(attr->name, "numthreads") && profile->type == VKD3D_SHADER_TYPE_COMPUTE)
6251 else if (!strcmp(attr->name, "domain")
6254 else if (!strcmp(attr->name, "outputcontrolpoints") && profile->type == VKD3D_SHADER_TYPE_HULL)
6256 else if (!strcmp(attr->name, "outputtopology") && profile->type == VKD3D_SHADER_TYPE_HULL)
6258 else if (!strcmp(attr->name, "partitioning") && profile->type == VKD3D_SHADER_TYPE_HULL)
6260 else if (!strcmp(attr->name, "patchconstantfunc") && profile->type == VKD3D_SHADER_TYPE_HULL)
6262 else if (!strcmp(attr->name, "earlydepthstencil") && profile->type == VKD3D_SHADER_TYPE_PIXEL)
6263 entry_func->early_depth_test = true;
6264 else
6266 "Ignoring unknown attribute \"%s\".", entry_func->attrs[i]->name);
6267 }
6268}
6269
6270static void validate_hull_shader_attributes(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *entry_func)
6271{
6273 {
6275 "Entry point \"%s\" is missing a [domain] attribute.", entry_func->func->name);
6276 }
6277
6278 if (ctx->output_control_point_count == UINT_MAX)
6279 {
6281 "Entry point \"%s\" is missing a [outputcontrolpoints] attribute.", entry_func->func->name);
6282 }
6283
6284 if (!ctx->output_primitive)
6285 {
6287 "Entry point \"%s\" is missing a [outputtopology] attribute.", entry_func->func->name);
6288 }
6289
6290 if (!ctx->partitioning)
6291 {
6293 "Entry point \"%s\" is missing a [partitioning] attribute.", entry_func->func->name);
6294 }
6295
6296 if (!ctx->patch_constant_func)
6297 {
6299 "Entry point \"%s\" is missing a [patchconstantfunc] attribute.", entry_func->func->name);
6300 }
6301 else if (ctx->patch_constant_func == entry_func)
6302 {
6304 "Patch constant function cannot be the entry point function.");
6305 /* Native returns E_NOTIMPL instead of E_FAIL here. */
6307 return;
6308 }
6309
6310 switch (ctx->domain)
6311 {
6313 if (ctx->output_primitive == VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CW
6314 || ctx->output_primitive == VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CCW)
6316 "Triangle output topologies are not available for isoline domains.");
6317 break;
6318
6320 if (ctx->output_primitive == VKD3D_SHADER_TESSELLATOR_OUTPUT_LINE)
6322 "Line output topologies are not available for triangle domains.");
6323 break;
6324
6326 if (ctx->output_primitive == VKD3D_SHADER_TESSELLATOR_OUTPUT_LINE)
6328 "Line output topologies are not available for quad domains.");
6329 break;
6330
6331 default:
6332 break;
6333 }
6334}
6335
6337{
6338 struct hlsl_ir_node *instr, *next;
6339 struct hlsl_block block;
6340 struct list *start;
6341
6342 LIST_FOR_EACH_ENTRY_SAFE(instr, next, &body->instrs, struct hlsl_ir_node, entry)
6343 {
6344 if (instr->type == HLSL_IR_IF)
6345 {
6346 struct hlsl_ir_if *iff = hlsl_ir_if(instr);
6347
6350 }
6351 else if (instr->type == HLSL_IR_LOOP)
6352 {
6353 struct hlsl_ir_loop *loop = hlsl_ir_loop(instr);
6354
6356 }
6357 else if (instr->type == HLSL_IR_SWITCH)
6358 {
6359 struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
6360 struct hlsl_ir_switch_case *c;
6361
6363 {
6364 remove_unreachable_code(ctx, &c->body);
6365 }
6366 }
6367 }
6368
6369 /* Remove instructions past unconditional jumps. */
6370 LIST_FOR_EACH_ENTRY(instr, &body->instrs, struct hlsl_ir_node, entry)
6371 {
6372 struct hlsl_ir_jump *jump;
6373
6374 if (instr->type != HLSL_IR_JUMP)
6375 continue;
6376
6377 jump = hlsl_ir_jump(instr);
6378 if (jump->type != HLSL_IR_JUMP_BREAK && jump->type != HLSL_IR_JUMP_CONTINUE)
6379 continue;
6380
6381 if (!(start = list_next(&body->instrs, &instr->entry)))
6382 break;
6383
6385 list_move_slice_tail(&block.instrs, start, list_tail(&body->instrs));
6387
6388 break;
6389 }
6390}
6391
6393{
6395}
6396
6398{
6399 bool progress;
6400
6402
6405 do
6406 {
6409 }
6410 while (progress);
6412
6421
6422 do
6423 {
6431 } while (progress);
6432}
6433
6435 struct shader_signature *signature, bool output, bool is_patch_constant_func, struct hlsl_ir_var *var)
6436{
6439 unsigned int register_index, mask, use_mask;
6440 const char *name = var->semantic.name;
6442 struct signature_element *element;
6443
6444 if (hlsl_version_ge(ctx, 4, 0))
6445 {
6447 bool has_idx, ret;
6448
6449 ret = sm4_sysval_semantic_from_semantic_name(&sysval, &program->shader_version, ctx->semantic_compat_mapping,
6450 ctx->domain, var->semantic.name, var->semantic.index, output, is_patch_constant_func);
6452 if (sysval == ~0u)
6453 return;
6454
6455 if (sm4_register_from_semantic_name(&program->shader_version, var->semantic.name, output, &type, &has_idx))
6456 {
6457 register_index = has_idx ? var->semantic.index : ~0u;
6458 mask = (1u << var->data_type->dimx) - 1;
6459 }
6460 else
6461 {
6462 VKD3D_ASSERT(var->regs[HLSL_REGSET_NUMERIC].allocated);
6463 register_index = var->regs[HLSL_REGSET_NUMERIC].id;
6464 mask = var->regs[HLSL_REGSET_NUMERIC].writemask;
6465 }
6466
6467 use_mask = mask; /* FIXME: retrieve use mask accurately. */
6468
6469 switch (var->data_type->e.numeric.type)
6470 {
6471 case HLSL_TYPE_FLOAT:
6472 case HLSL_TYPE_HALF:
6474 break;
6475
6476 case HLSL_TYPE_INT:
6478 break;
6479
6480 case HLSL_TYPE_BOOL:
6481 case HLSL_TYPE_UINT:
6483 break;
6484
6485 default:
6486 if ((string = hlsl_type_to_string(ctx, var->data_type)))
6488 "Invalid data type %s for semantic variable %s.", string->buffer, var->name);
6491 break;
6492 }
6493
6495 name = "SV_Target";
6496 else if (sysval == VKD3D_SHADER_SV_DEPTH && !ascii_strcasecmp(name, "depth"))
6497 name ="SV_Depth";
6498 else if (sysval == VKD3D_SHADER_SV_POSITION && !ascii_strcasecmp(name, "position"))
6499 name = "SV_Position";
6500 }
6501 else
6502 {
6503 if ((!output && !var->last_read) || (output && !var->first_write))
6504 return;
6505
6506 if (!sm1_register_from_semantic_name(&program->shader_version,
6507 var->semantic.name, var->semantic.index, output, &type, &register_index))
6508 {
6510 unsigned int usage_idx;
6511 bool ret;
6512
6513 register_index = var->regs[HLSL_REGSET_NUMERIC].id;
6514
6515 ret = sm1_usage_from_semantic_name(var->semantic.name, var->semantic.index, &usage, &usage_idx);
6517 /* With the exception of vertex POSITION output, none of these are
6518 * system values. Pixel POSITION input is not equivalent to
6519 * SV_Position; the closer equivalent is VPOS, which is not declared
6520 * as a semantic. */
6521 if (program->shader_version.type == VKD3D_SHADER_TYPE_VERTEX
6522 && output && usage == VKD3D_DECL_USAGE_POSITION)
6524 }
6525
6526 mask = (1 << var->data_type->dimx) - 1;
6527
6528 if (!ascii_strcasecmp(var->semantic.name, "PSIZE") && output
6529 && program->shader_version.type == VKD3D_SHADER_TYPE_VERTEX)
6530 {
6531 if (var->data_type->dimx > 1)
6533 "PSIZE output must have only 1 component in this shader model.");
6534 /* For some reason the writemask has all components set. */
6536 }
6537 if (!ascii_strcasecmp(var->semantic.name, "FOG") && output && program->shader_version.major < 3
6538 && program->shader_version.type == VKD3D_SHADER_TYPE_VERTEX && var->data_type->dimx > 1)
6540 "FOG output must have only 1 component in this shader model.");
6541
6542 use_mask = mask; /* FIXME: retrieve use mask accurately. */
6544 }
6545
6546 if (!vkd3d_array_reserve((void **)&signature->elements, &signature->elements_capacity,
6547 signature->element_count + 1, sizeof(*signature->elements)))
6548 {
6550 return;
6551 }
6552 element = &signature->elements[signature->element_count++];
6553 memset(element, 0, sizeof(*element));
6554
6555 if (!(element->semantic_name = vkd3d_strdup(name)))
6556 {
6557 --signature->element_count;
6559 return;
6560 }
6561 element->semantic_index = var->semantic.index;
6562 element->sysval_semantic = sysval;
6563 element->component_type = component_type;
6564 element->register_index = register_index;
6565 element->target_location = register_index;
6566 element->register_count = 1;
6567 element->mask = mask;
6568 element->used_mask = use_mask;
6569 if (program->shader_version.type == VKD3D_SHADER_TYPE_PIXEL && !output)
6570 element->interpolation_mode = VKD3DSIM_LINEAR;
6571}
6572
6575{
6576 bool is_domain = program->shader_version.type == VKD3D_SHADER_TYPE_DOMAIN;
6577 bool is_patch_constant_func = func == ctx->patch_constant_func;
6578 struct hlsl_ir_var *var;
6579
6580 LIST_FOR_EACH_ENTRY(var, &func->extern_vars, struct hlsl_ir_var, extern_entry)
6581 {
6582 if (var->is_input_semantic)
6583 {
6584 if (is_patch_constant_func)
6585 generate_vsir_signature_entry(ctx, program, &program->patch_constant_signature, false, true, var);
6586 else if (is_domain)
6587 generate_vsir_signature_entry(ctx, program, &program->patch_constant_signature, false, false, var);
6588 else
6589 generate_vsir_signature_entry(ctx, program, &program->input_signature, false, false, var);
6590 }
6591 if (var->is_output_semantic)
6592 {
6593 if (is_patch_constant_func)
6594 generate_vsir_signature_entry(ctx, program, &program->patch_constant_signature, true, true, var);
6595 else
6596 generate_vsir_signature_entry(ctx, program, &program->output_signature, true, false, var);
6597 }
6598 }
6599}
6600
6602{
6603 if (hlsl_version_lt(ctx, 4, 0))
6604 return VKD3D_DATA_FLOAT;
6605
6606 if (type->class == HLSL_CLASS_ARRAY)
6607 return vsir_data_type_from_hlsl_type(ctx, type->e.array.type);
6608 if (type->class == HLSL_CLASS_STRUCT)
6609 return VKD3D_DATA_MIXED;
6610 if (type->class <= HLSL_CLASS_LAST_NUMERIC)
6611 {
6612 switch (type->e.numeric.type)
6613 {
6614 case HLSL_TYPE_DOUBLE:
6615 return VKD3D_DATA_DOUBLE;
6616 case HLSL_TYPE_FLOAT:
6617 return VKD3D_DATA_FLOAT;
6618 case HLSL_TYPE_HALF:
6619 return VKD3D_DATA_HALF;
6620 case HLSL_TYPE_INT:
6621 return VKD3D_DATA_INT;
6622 case HLSL_TYPE_UINT:
6623 case HLSL_TYPE_BOOL:
6624 return VKD3D_DATA_UINT;
6625 }
6626 }
6627
6629}
6630
6632 const struct hlsl_ir_node *instr)
6633{
6635}
6636
6637static uint32_t generate_vsir_get_src_swizzle(uint32_t src_writemask, uint32_t dst_writemask)
6638{
6640
6641 swizzle = hlsl_swizzle_from_writemask(src_writemask);
6642 swizzle = hlsl_map_swizzle(swizzle, dst_writemask);
6644 return swizzle;
6645}
6646
6648 struct hlsl_block *block)
6649{
6650 struct vkd3d_shader_instruction_array *instructions = &program->instructions;
6651 struct vkd3d_shader_dst_param *dst_param;
6652 struct vkd3d_shader_src_param *src_param;
6653 struct vkd3d_shader_instruction *ins;
6654 unsigned int i, x;
6655
6656 for (i = 0; i < ctx->constant_defs.count; ++i)
6657 {
6658 const struct hlsl_constant_register *constant_reg = &ctx->constant_defs.regs[i];
6659
6660 if (!shader_instruction_array_reserve(instructions, instructions->count + 1))
6661 {
6663 return;
6664 }
6665
6666 ins = &instructions->elements[instructions->count];
6667 if (!vsir_instruction_init_with_params(program, ins, &constant_reg->loc, VKD3DSIH_DEF, 1, 1))
6668 {
6670 return;
6671 }
6672 ++instructions->count;
6673
6674 dst_param = &ins->dst[0];
6676 ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4;
6677 ins->dst[0].reg.idx[0].offset = constant_reg->index;
6678 ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL;
6679
6680 src_param = &ins->src[0];
6682 src_param->reg.type = VKD3DSPR_IMMCONST;
6683 src_param->reg.precision = VKD3D_SHADER_REGISTER_PRECISION_DEFAULT;
6684 src_param->reg.non_uniform = false;
6685 src_param->reg.data_type = VKD3D_DATA_FLOAT;
6686 src_param->reg.dimension = VSIR_DIMENSION_VEC4;
6687 for (x = 0; x < 4; ++x)
6688 src_param->reg.u.immconst_f32[x] = constant_reg->value.f[x];
6689 src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE;
6690 }
6691}
6692
6694 struct vsir_program *program, struct hlsl_block *block)
6695{
6696 struct vkd3d_shader_instruction_array *instructions = &program->instructions;
6697 enum vkd3d_shader_resource_type resource_type;
6699 struct vkd3d_shader_dst_param *dst_param;
6700 struct vkd3d_shader_semantic *semantic;
6701 struct vkd3d_shader_instruction *ins;
6702 enum hlsl_sampler_dim sampler_dim;
6703 struct hlsl_ir_var *var;
6704 unsigned int i, count;
6705
6706 LIST_FOR_EACH_ENTRY(var, &ctx->extern_vars, struct hlsl_ir_var, extern_entry)
6707 {
6708 if (!var->regs[HLSL_REGSET_SAMPLERS].allocated)
6709 continue;
6710
6711 count = var->bind_count[HLSL_REGSET_SAMPLERS];
6712 for (i = 0; i < count; ++i)
6713 {
6714 if (var->objects_usage[HLSL_REGSET_SAMPLERS][i].used)
6715 {
6716 sampler_dim = var->objects_usage[HLSL_REGSET_SAMPLERS][i].sampler_dim;
6717
6718 switch (sampler_dim)
6719 {
6721 resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_2D;
6722 break;
6723
6725 resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_CUBE;
6726 break;
6727
6729 resource_type = VKD3D_SHADER_RESOURCE_TEXTURE_3D;
6730 break;
6731
6733 /* These can appear in sm4-style combined sample instructions. */
6734 hlsl_fixme(ctx, &var->loc, "Generic samplers need to be lowered.");
6735 continue;
6736
6737 default:
6739 break;
6740 }
6741
6742 if (!shader_instruction_array_reserve(instructions, instructions->count + 1))
6743 {
6745 return;
6746 }
6747
6748 ins = &instructions->elements[instructions->count];
6750 {
6752 return;
6753 }
6754 ++instructions->count;
6755
6757 semantic->resource_type = resource_type;
6758
6759 dst_param = &semantic->resource.reg;
6761 dst_param->reg.dimension = VSIR_DIMENSION_NONE;
6762 dst_param->reg.idx[0].offset = var->regs[HLSL_REGSET_SAMPLERS].index + i;
6763 dst_param->write_mask = 0;
6764 range = &semantic->resource.range;
6765 range->space = 0;
6766 range->first = range->last = dst_param->reg.idx[0].offset;
6767 }
6768 }
6769 }
6770}
6771
6773 struct hlsl_ctx *ctx, struct vsir_program *program,
6774 const struct vkd3d_shader_location *loc, enum vkd3d_shader_opcode opcode,
6775 unsigned int dst_count, unsigned int src_count)
6776{
6777 struct vkd3d_shader_instruction_array *instructions = &program->instructions;
6778 struct vkd3d_shader_instruction *ins;
6779
6780 if (!shader_instruction_array_reserve(instructions, instructions->count + 1))
6781 {
6783 return NULL;
6784 }
6785 ins = &instructions->elements[instructions->count];
6787 {
6789 return NULL;
6790 }
6791 ++instructions->count;
6792 return ins;
6793}
6794
6796 struct hlsl_ctx *ctx, const struct hlsl_constant_value *value,
6797 enum vkd3d_data_type type, unsigned int width, unsigned int map_writemask)
6798{
6799 unsigned int i, j;
6800
6802 if (width == 1)
6803 {
6804 src->reg.u.immconst_u32[0] = value->u[0].u;
6805 return;
6806 }
6807
6808 src->reg.dimension = VSIR_DIMENSION_VEC4;
6809 for (i = 0, j = 0; i < 4; ++i)
6810 {
6811 if ((map_writemask & (1u << i)) && (j < width))
6812 src->reg.u.immconst_u32[i] = value->u[j++].u;
6813 else
6814 src->reg.u.immconst_u32[i] = 0;
6815 }
6816}
6817
6819 struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, uint32_t map_writemask)
6820{
6821 struct hlsl_ir_constant *constant;
6822
6823 if (hlsl_version_ge(ctx, 4, 0) && instr->type == HLSL_IR_CONSTANT)
6824 {
6825 /* In SM4 constants are inlined */
6826 constant = hlsl_ir_constant(instr);
6828 vsir_data_type_from_hlsl_instruction(ctx, instr), instr->data_type->dimx, map_writemask);
6829 }
6830 else
6831 {
6833 src->reg.idx[0].offset = instr->reg.id;
6834 src->reg.dimension = VSIR_DIMENSION_VEC4;
6835 src->swizzle = generate_vsir_get_src_swizzle(instr->reg.writemask, map_writemask);
6836 }
6837}
6838
6840 struct hlsl_ctx *ctx, const struct hlsl_ir_node *instr)
6841{
6842 VKD3D_ASSERT(instr->reg.allocated);
6844 dst->reg.idx[0].offset = instr->reg.id;
6845 dst->reg.dimension = VSIR_DIMENSION_VEC4;
6846 dst->write_mask = instr->reg.writemask;
6847}
6848
6851{
6852 struct hlsl_ir_node *instr = &constant->node;
6853 struct vkd3d_shader_dst_param *dst_param;
6854 struct vkd3d_shader_src_param *src_param;
6855 struct vkd3d_shader_instruction *ins;
6856
6857 VKD3D_ASSERT(instr->reg.allocated);
6858 VKD3D_ASSERT(constant->reg.allocated);
6859
6860 if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_MOV, 1, 1)))
6861 return;
6862
6863 src_param = &ins->src[0];
6865 src_param->reg.idx[0].offset = constant->reg.id;
6866 src_param->swizzle = generate_vsir_get_src_swizzle(constant->reg.writemask, instr->reg.writemask);
6867
6868 dst_param = &ins->dst[0];
6870 dst_param->reg.idx[0].offset = instr->reg.id;
6871 dst_param->write_mask = instr->reg.writemask;
6872}
6873
6875 struct vsir_program *program, struct hlsl_ir_expr *expr)
6876{
6877 struct vkd3d_shader_src_param *src_param;
6878 struct hlsl_ir_node *instr = &expr->node;
6879 struct vkd3d_shader_instruction *ins;
6880
6882 return;
6884
6885 vsir_dst_from_hlsl_node(&ins->dst[0], ctx, instr);
6886
6887 src_param = &ins->src[0];
6889 src_param->reg.dimension = VSIR_DIMENSION_VEC4;
6890 src_param->swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X);
6891}
6892
6893/* Translate ops that can be mapped to a single vsir instruction with only one dst register. */
6896 uint32_t src_mod, uint32_t dst_mod, bool map_src_swizzles)
6897{
6898 struct hlsl_ir_node *instr = &expr->node;
6899 struct vkd3d_shader_dst_param *dst_param;
6900 struct vkd3d_shader_src_param *src_param;
6901 struct vkd3d_shader_instruction *ins;
6902 unsigned int i, src_count = 0;
6903
6904 VKD3D_ASSERT(instr->reg.allocated);
6905
6906 for (i = 0; i < HLSL_MAX_OPERANDS; ++i)
6907 {
6908 if (expr->operands[i].node)
6909 src_count = i + 1;
6910 }
6911 VKD3D_ASSERT(!src_mod || src_count == 1);
6912
6914 return;
6915
6916 dst_param = &ins->dst[0];
6917 vsir_dst_from_hlsl_node(dst_param, ctx, instr);
6918 dst_param->modifiers = dst_mod;
6919
6920 for (i = 0; i < src_count; ++i)
6921 {
6922 struct hlsl_ir_node *operand = expr->operands[i].node;
6923
6924 src_param = &ins->src[i];
6925 vsir_src_from_hlsl_node(src_param, ctx, operand,
6926 map_src_swizzles ? dst_param->write_mask : VKD3DSP_WRITEMASK_ALL);
6927 src_param->modifiers = src_mod;
6928 }
6929}
6930
6931/* Translate ops that have 1 src and need one instruction for each component in
6932 * the d3dbc backend. */
6934 struct vsir_program *program, struct hlsl_ir_expr *expr, enum vkd3d_shader_opcode opcode)
6935{
6936 struct hlsl_ir_node *operand = expr->operands[0].node;
6937 struct hlsl_ir_node *instr = &expr->node;
6938 struct vkd3d_shader_dst_param *dst_param;
6939 struct vkd3d_shader_src_param *src_param;
6940 struct vkd3d_shader_instruction *ins;
6941 uint32_t src_swizzle;
6942 unsigned int i, c;
6943
6944 VKD3D_ASSERT(instr->reg.allocated);
6945 VKD3D_ASSERT(operand);
6946
6947 src_swizzle = generate_vsir_get_src_swizzle(operand->reg.writemask, instr->reg.writemask);
6948 for (i = 0; i < 4; ++i)
6949 {
6950 if (instr->reg.writemask & (1u << i))
6951 {
6952 if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, opcode, 1, 1)))
6953 return;
6954
6955 dst_param = &ins->dst[0];
6957 dst_param->reg.idx[0].offset = instr->reg.id;
6958 dst_param->write_mask = 1u << i;
6959
6960 src_param = &ins->src[0];
6962 src_param->reg.idx[0].offset = operand->reg.id;
6963 c = vsir_swizzle_get_component(src_swizzle, i);
6964 src_param->swizzle = vsir_swizzle_from_writemask(1u << c);
6965 }
6966 }
6967}
6968
6970 struct hlsl_ir_expr *expr)
6971{
6972 struct hlsl_ir_node *operand = expr->operands[0].node;
6973 struct hlsl_ir_node *instr = &expr->node;
6974 struct vkd3d_shader_dst_param *dst_param;
6975 struct vkd3d_shader_src_param *src_param;
6976 struct vkd3d_shader_instruction *ins;
6977 unsigned int src_count = 0;
6978
6979 VKD3D_ASSERT(instr->reg.allocated);
6980 src_count = (ctx->profile->major_version < 3) ? 3 : 1;
6981
6983 return;
6984
6985 dst_param = &ins->dst[0];
6987 dst_param->reg.idx[0].offset = instr->reg.id;
6988 dst_param->write_mask = instr->reg.writemask;
6989
6990 src_param = &ins->src[0];
6992 src_param->reg.idx[0].offset = operand->reg.id;
6993 src_param->swizzle = generate_vsir_get_src_swizzle(operand->reg.writemask, VKD3DSP_WRITEMASK_ALL);
6994
6995 if (ctx->profile->major_version < 3)
6996 {
6997 src_param = &ins->src[1];
6999 src_param->reg.idx[0].offset = ctx->d3dsincosconst1.id;
7000 src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE;
7001
7002 src_param = &ins->src[1];
7004 src_param->reg.idx[0].offset = ctx->d3dsincosconst2.id;
7005 src_param->swizzle = VKD3D_SHADER_NO_SWIZZLE;
7006 }
7007}
7008
7010 struct vsir_program *program, struct hlsl_ir_expr *expr)
7011{
7012 const struct hlsl_type *src_type, *dst_type;
7013 const struct hlsl_ir_node *arg1, *instr;
7014
7015 arg1 = expr->operands[0].node;
7016 src_type = arg1->data_type;
7017 instr = &expr->node;
7018 dst_type = instr->data_type;
7019
7020 /* Narrowing casts were already lowered. */
7021 VKD3D_ASSERT(src_type->dimx == dst_type->dimx);
7022
7023 switch (dst_type->e.numeric.type)
7024 {
7025 case HLSL_TYPE_HALF:
7026 case HLSL_TYPE_FLOAT:
7027 switch (src_type->e.numeric.type)
7028 {
7029 case HLSL_TYPE_INT:
7030 case HLSL_TYPE_UINT:
7031 case HLSL_TYPE_BOOL:
7032 /* Integrals are internally represented as floats, so no change is necessary.*/
7033 case HLSL_TYPE_HALF:
7034 case HLSL_TYPE_FLOAT:
7036 return true;
7037
7038 case HLSL_TYPE_DOUBLE:
7039 if (ctx->double_as_float_alias)
7040 {
7042 return true;
7043 }
7045 "The 'double' type is not supported for the %s profile.", ctx->profile->name);
7046 break;
7047
7048 default:
7050 }
7051 break;
7052
7053 case HLSL_TYPE_INT:
7054 case HLSL_TYPE_UINT:
7055 switch(src_type->e.numeric.type)
7056 {
7057 case HLSL_TYPE_HALF:
7058 case HLSL_TYPE_FLOAT:
7059 /* A compilation pass turns these into FLOOR+REINTERPRET, so we should not
7060 * reach this case unless we are missing something. */
7061 hlsl_fixme(ctx, &instr->loc, "Unlowered SM1 cast from float to integer.");
7062 break;
7063
7064 case HLSL_TYPE_INT:
7065 case HLSL_TYPE_UINT:
7067 return true;
7068
7069 case HLSL_TYPE_BOOL:
7070 hlsl_fixme(ctx, &instr->loc, "SM1 cast from bool to integer.");
7071 break;
7072
7073 case HLSL_TYPE_DOUBLE:
7074 hlsl_fixme(ctx, &instr->loc, "SM1 cast from double to integer.");
7075 break;
7076
7077 default:
7079 }
7080 break;
7081
7082 case HLSL_TYPE_DOUBLE:
7083 switch (src_type->e.numeric.type)
7084 {
7085 case HLSL_TYPE_FLOAT:
7086 if (ctx->double_as_float_alias)
7087 {
7089 return true;
7090 }
7092 "The 'double' type is not supported for the %s profile.", ctx->profile->name);
7093 break;
7094
7095 default:
7096 hlsl_fixme(ctx, &instr->loc, "SM1 cast to double.");
7097 break;
7098 }
7099 break;
7100
7101 case HLSL_TYPE_BOOL:
7102 /* Casts to bool should have already been lowered. */
7103 default:
7104 hlsl_fixme(ctx, &expr->node.loc, "SM1 cast from %s to %s.",
7105 debug_hlsl_type(ctx, src_type), debug_hlsl_type(ctx, dst_type));
7106 break;
7107 }
7108
7109 return false;
7110}
7111
7113 struct hlsl_ir_expr *expr)
7114{
7115 struct hlsl_ir_node *instr = &expr->node;
7116
7117 if (expr->op != HLSL_OP1_REINTERPRET && expr->op != HLSL_OP1_CAST
7118 && instr->data_type->e.numeric.type != HLSL_TYPE_FLOAT)
7119 {
7120 /* These need to be lowered. */
7121 hlsl_fixme(ctx, &instr->loc, "SM1 non-float expression.");
7122 return false;
7123 }
7124
7125 switch (expr->op)
7126 {
7127 case HLSL_OP1_ABS:
7129 break;
7130
7131 case HLSL_OP1_CAST:
7133
7135 VKD3D_ASSERT(expr->node.reg.writemask == VKD3DSP_WRITEMASK_0);
7137 break;
7138
7139 case HLSL_OP1_DSX:
7141 break;
7142
7143 case HLSL_OP1_DSY:
7145 break;
7146
7147 case HLSL_OP1_EXP2:
7149 break;
7150
7151 case HLSL_OP1_LOG2:
7153 break;
7154
7155 case HLSL_OP1_NEG:
7157 break;
7158
7159 case HLSL_OP1_RCP:
7161 break;
7162
7165 break;
7166
7167 case HLSL_OP1_RSQ:
7169 break;
7170
7171 case HLSL_OP1_SAT:
7173 break;
7174
7176 VKD3D_ASSERT(expr->node.reg.writemask == VKD3DSP_WRITEMASK_1);
7178 break;
7179
7180 case HLSL_OP2_ADD:
7182 break;
7183
7184 case HLSL_OP2_DOT:
7185 switch (expr->operands[0].node->data_type->dimx)
7186 {
7187 case 3:
7189 break;
7190
7191 case 4:
7193 break;
7194
7195 default:
7197 return false;
7198 }
7199 break;
7200
7201 case HLSL_OP2_MAX:
7203 break;
7204
7205 case HLSL_OP2_MIN:
7207 break;
7208
7209 case HLSL_OP2_MUL:
7211 break;
7212
7213 case HLSL_OP1_FRACT:
7215 break;
7216
7217 case HLSL_OP2_LOGIC_AND:
7219 break;
7220
7221 case HLSL_OP2_LOGIC_OR:
7223 break;
7224
7225 case HLSL_OP2_SLT:
7227 break;
7228
7229 case HLSL_OP3_CMP:
7231 break;
7232
7233 case HLSL_OP3_DP2ADD:
7235 break;
7236
7237 case HLSL_OP3_MAD:
7239 break;
7240
7241 default:
7242 hlsl_fixme(ctx, &instr->loc, "SM1 \"%s\" expression.", debug_hlsl_expr_op(expr->op));
7243 return false;
7244 }
7245
7246 return true;
7247}
7248
7250 struct vkd3d_shader_dst_param *dst_param, struct hlsl_deref *deref,
7251 const struct vkd3d_shader_location *loc, unsigned int writemask)
7252{
7255 uint32_t register_index;
7256 struct hlsl_reg reg;
7257
7258 reg = hlsl_reg_from_deref(ctx, deref);
7259 register_index = reg.id;
7261
7262 if (deref->var->is_output_semantic)
7263 {
7264 const char *semantic_name = deref->var->semantic.name;
7265
7266 version.major = ctx->profile->major_version;
7267 version.minor = ctx->profile->minor_version;
7268 version.type = ctx->profile->type;
7269
7270 if (version.type == VKD3D_SHADER_TYPE_PIXEL && version.major == 1)
7271 {
7273 register_index = 0;
7274 }
7275 else if (!sm1_register_from_semantic_name(&version, semantic_name,
7276 deref->var->semantic.index, true, &type, &register_index))
7277 {
7278 VKD3D_ASSERT(reg.allocated);
7280 register_index = reg.id;
7281 }
7282 else
7283 writemask = (1u << deref->var->data_type->dimx) - 1;
7284
7285 if (version.type == VKD3D_SHADER_TYPE_PIXEL && (!ascii_strcasecmp(semantic_name, "PSIZE")
7286 || (!ascii_strcasecmp(semantic_name, "FOG") && version.major < 3)))
7287 {
7288 /* These are always 1-component, but for some reason are written
7289 * with a writemask containing all components. */
7291 }
7292 }
7293 else
7294 VKD3D_ASSERT(reg.allocated);
7295
7296 vsir_register_init(&dst_param->reg, type, VKD3D_DATA_FLOAT, 1);
7297 dst_param->write_mask = writemask;
7298 dst_param->reg.idx[0].offset = register_index;
7299
7300 if (deref->rel_offset.node)
7301 hlsl_fixme(ctx, loc, "Translate relative addressing on dst register for vsir.");
7302}
7303
7305 struct vkd3d_shader_src_param *src_param, struct hlsl_deref *deref,
7306 unsigned int dst_writemask, const struct vkd3d_shader_location *loc)
7307{
7310 uint32_t register_index;
7311 unsigned int writemask;
7312 struct hlsl_reg reg;
7313
7314 if (hlsl_type_is_resource(deref->var->data_type))
7315 {
7316 unsigned int sampler_offset;
7317
7319
7320 sampler_offset = hlsl_offset_from_deref_safe(ctx, deref);
7321 register_index = deref->var->regs[HLSL_REGSET_SAMPLERS].index + sampler_offset;
7323 }
7324 else if (deref->var->is_uniform)
7325 {
7327
7328 reg = hlsl_reg_from_deref(ctx, deref);
7329 register_index = reg.id;
7330 writemask = reg.writemask;
7331 VKD3D_ASSERT(reg.allocated);
7332 }
7333 else if (deref->var->is_input_semantic)
7334 {
7335 version.major = ctx->profile->major_version;
7336 version.minor = ctx->profile->minor_version;
7337 version.type = ctx->profile->type;
7338 if (sm1_register_from_semantic_name(&version, deref->var->semantic.name,
7339 deref->var->semantic.index, false, &type, &register_index))
7340 {
7341 writemask = (1 << deref->var->data_type->dimx) - 1;
7342 }
7343 else
7344 {
7346
7347 reg = hlsl_reg_from_deref(ctx, deref);
7348 register_index = reg.id;
7349 writemask = reg.writemask;
7350 VKD3D_ASSERT(reg.allocated);
7351 }
7352 }
7353 else
7354 {
7356
7357 reg = hlsl_reg_from_deref(ctx, deref);
7358 register_index = reg.id;
7359 writemask = reg.writemask;
7360 }
7361
7362 vsir_register_init(&src_param->reg, type, VKD3D_DATA_FLOAT, 1);
7363 src_param->reg.idx[0].offset = register_index;
7364 src_param->swizzle = generate_vsir_get_src_swizzle(writemask, dst_writemask);
7365
7366 if (deref->rel_offset.node)
7367 hlsl_fixme(ctx, loc, "Translate relative addressing on src register for vsir.");
7368}
7369
7371 struct hlsl_ir_load *load)
7372{
7373 struct hlsl_ir_node *instr = &load->node;
7374 struct vkd3d_shader_dst_param *dst_param;
7375 struct vkd3d_shader_instruction *ins;
7376
7377 VKD3D_ASSERT(instr->reg.allocated);
7378
7379 if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_MOV, 1, 1)))
7380 return;
7381
7382 dst_param = &ins->dst[0];
7384 dst_param->reg.idx[0].offset = instr->reg.id;
7385 dst_param->write_mask = instr->reg.writemask;
7386
7388 &ins->location);
7389}
7390
7393{
7394 struct hlsl_ir_node *coords = load->coords.node;
7395 struct hlsl_ir_node *ddx = load->ddx.node;
7396 struct hlsl_ir_node *ddy = load->ddy.node;
7397 struct hlsl_ir_node *instr = &load->node;
7398 struct vkd3d_shader_dst_param *dst_param;
7399 struct vkd3d_shader_src_param *src_param;
7400 struct vkd3d_shader_instruction *ins;
7402 unsigned int src_count = 2;
7403 uint32_t flags = 0;
7404
7405 VKD3D_ASSERT(instr->reg.allocated);
7406
7407 switch (load->load_type)
7408 {
7411 break;
7412
7416 break;
7417
7421 break;
7422
7425 src_count += 2;
7426 break;
7427
7428 default:
7429 hlsl_fixme(ctx, &instr->loc, "Resource load type %u.", load->load_type);
7430 return;
7431 }
7432
7434 return;
7435 ins->flags = flags;
7436
7437 dst_param = &ins->dst[0];
7439 dst_param->reg.idx[0].offset = instr->reg.id;
7440 dst_param->write_mask = instr->reg.writemask;
7441
7442 src_param = &ins->src[0];
7444
7447
7448 if (load->load_type == HLSL_RESOURCE_SAMPLE_GRAD)
7449 {
7450 src_param = &ins->src[2];
7452
7453 src_param = &ins->src[3];
7455 }
7456}
7457
7459 struct vsir_program *program, struct hlsl_ir_swizzle *swizzle_instr)
7460{
7461 struct hlsl_ir_node *instr = &swizzle_instr->node, *val = swizzle_instr->val.node;
7462 struct vkd3d_shader_dst_param *dst_param;
7463 struct vkd3d_shader_src_param *src_param;
7464 struct vkd3d_shader_instruction *ins;
7466
7467 VKD3D_ASSERT(instr->reg.allocated);
7468
7469 if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_MOV, 1, 1)))
7470 return;
7471
7472 dst_param = &ins->dst[0];
7474 dst_param->reg.idx[0].offset = instr->reg.id;
7475 dst_param->reg.dimension = VSIR_DIMENSION_VEC4;
7476 dst_param->write_mask = instr->reg.writemask;
7477
7478 swizzle = hlsl_swizzle_from_writemask(val->reg.writemask);
7479 swizzle = hlsl_combine_swizzles(swizzle, swizzle_instr->swizzle, instr->data_type->dimx);
7480 swizzle = hlsl_map_swizzle(swizzle, ins->dst[0].write_mask);
7482
7483 src_param = &ins->src[0];
7486 src_param->reg.idx[0].offset = val->reg.id;
7487 src_param->reg.dimension = VSIR_DIMENSION_VEC4;
7488 src_param->swizzle = swizzle;
7489}
7490
7492 struct hlsl_ir_store *store)
7493{
7494 struct hlsl_ir_node *rhs = store->rhs.node;
7495 struct hlsl_ir_node *instr = &store->node;
7496 struct vkd3d_shader_instruction *ins;
7497 struct vkd3d_shader_src_param *src_param;
7498
7499 if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_MOV, 1, 1)))
7500 return;
7501
7502 sm1_generate_vsir_init_dst_param_from_deref(ctx, &ins->dst[0], &store->lhs, &ins->location, store->writemask);
7503
7504 src_param = &ins->src[0];
7505 vsir_src_from_hlsl_node(src_param, ctx, rhs, ins->dst[0].write_mask);
7506}
7507
7509 struct vsir_program *program, struct hlsl_ir_jump *jump)
7510{
7511 struct hlsl_ir_node *condition = jump->condition.node;
7512 struct hlsl_ir_node *instr = &jump->node;
7513 struct vkd3d_shader_dst_param *dst_param;
7514 struct vkd3d_shader_instruction *ins;
7515
7516 if (jump->type == HLSL_IR_JUMP_DISCARD_NEG)
7517 {
7519 return;
7520
7521 dst_param = &ins->dst[0];
7523 dst_param->reg.idx[0].offset = condition->reg.id;
7524 dst_param->write_mask = condition->reg.writemask;
7525 }
7526 else
7527 {
7528 hlsl_fixme(ctx, &instr->loc, "Jump type %s.", hlsl_jump_type_to_string(jump->type));
7529 }
7530}
7531
7532static void sm1_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *block, struct vsir_program *program);
7533
7534static void sm1_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_if *iff)
7535{
7536 struct hlsl_ir_node *condition = iff->condition.node;
7537 struct vkd3d_shader_src_param *src_param;
7538 struct hlsl_ir_node *instr = &iff->node;
7539 struct vkd3d_shader_instruction *ins;
7540
7541 if (hlsl_version_lt(ctx, 2, 1))
7542 {
7543 hlsl_fixme(ctx, &instr->loc, "Flatten \"if\" conditionals branches.");
7544 return;
7545 }
7546 VKD3D_ASSERT(condition->data_type->dimx == 1 && condition->data_type->dimy == 1);
7547
7548 if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_IFC, 0, 2)))
7549 return;
7551
7552 src_param = &ins->src[0];
7554 src_param->modifiers = 0;
7555
7556 src_param = &ins->src[1];
7558 src_param->modifiers = VKD3DSPSM_NEG;
7559
7561
7562 if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_ELSE, 0, 0)))
7563 return;
7564
7566
7568 return;
7569}
7570
7572{
7573 struct hlsl_ir_node *instr, *next;
7574
7575 LIST_FOR_EACH_ENTRY_SAFE(instr, next, &block->instrs, struct hlsl_ir_node, entry)
7576 {
7577 if (instr->data_type)
7578 {
7579 if (instr->data_type->class != HLSL_CLASS_SCALAR && instr->data_type->class != HLSL_CLASS_VECTOR)
7580 {
7581 hlsl_fixme(ctx, &instr->loc, "Class %#x should have been lowered or removed.", instr->data_type->class);
7582 break;
7583 }
7584 }
7585
7586 switch (instr->type)
7587 {
7588 case HLSL_IR_CALL:
7590
7591 case HLSL_IR_CONSTANT:
7593 break;
7594
7595 case HLSL_IR_EXPR:
7597 break;
7598
7599 case HLSL_IR_IF:
7601 break;
7602
7603 case HLSL_IR_JUMP:
7605 break;
7606
7607 case HLSL_IR_LOAD:
7609 break;
7610
7613 break;
7614
7615 case HLSL_IR_STORE:
7617 break;
7618
7619 case HLSL_IR_SWIZZLE:
7621 break;
7622
7623 default:
7624 hlsl_fixme(ctx, &instr->loc, "Instruction type %s.", hlsl_node_type_to_string(instr->type));
7625 break;
7626 }
7627 }
7628}
7629
7630static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func,
7631 uint64_t config_flags, struct vsir_program *program, struct vkd3d_shader_code *ctab)
7632{
7633 struct vkd3d_shader_version version = {0};
7634 struct vkd3d_bytecode_buffer buffer = {0};
7635 struct hlsl_block block;
7636
7637 version.major = ctx->profile->major_version;
7638 version.minor = ctx->profile->minor_version;
7639 version.type = ctx->profile->type;
7641 {
7643 return;
7644 }
7645
7647 if (buffer.status)
7648 {
7649 vkd3d_free(buffer.data);
7650 ctx->result = buffer.status;
7651 return;
7652 }
7653 ctab->code = buffer.data;
7654 ctab->size = buffer.size;
7655
7656 generate_vsir_signature(ctx, program, entry_func);
7657
7661 list_move_head(&entry_func->body.instrs, &block.instrs);
7662
7663 sm1_generate_vsir_block(ctx, &entry_func->body, program);
7664}
7665
7667{
7668 struct vkd3d_shader_location *loc;
7669 struct hlsl_ir_node *vsir_instr;
7670
7671 loc = &program->instructions.elements[program->instructions.count - 1].location;
7672
7673 if (!(vsir_instr = hlsl_new_vsir_instruction_ref(ctx, program->instructions.count - 1, NULL, NULL, loc)))
7674 {
7676 return;
7677 }
7678 hlsl_block_add_instr(block, vsir_instr);
7679}
7680
7682 struct vsir_program *program, struct hlsl_ir_node *instr)
7683{
7684 struct vkd3d_shader_location *loc;
7685 struct hlsl_ir_node *vsir_instr;
7686
7687 loc = &program->instructions.elements[program->instructions.count - 1].location;
7688
7689 if (!(vsir_instr = hlsl_new_vsir_instruction_ref(ctx,
7690 program->instructions.count - 1, instr->data_type, &instr->reg, loc)))
7691 {
7693 return;
7694 }
7695
7696 list_add_before(&instr->entry, &vsir_instr->entry);
7697 hlsl_replace_node(instr, vsir_instr);
7698}
7699
7701 const struct hlsl_ir_var *var, bool is_patch_constant_func, struct hlsl_block *block,
7702 const struct vkd3d_shader_location *loc)
7703{
7704 const struct vkd3d_shader_version *version = &program->shader_version;
7705 const bool output = var->is_output_semantic;
7706 enum vkd3d_shader_sysval_semantic semantic;
7707 struct vkd3d_shader_dst_param *dst_param;
7708 struct vkd3d_shader_instruction *ins;
7711 unsigned int idx = 0;
7712 uint32_t write_mask;
7713 bool has_idx;
7714
7715 sm4_sysval_semantic_from_semantic_name(&semantic, version, ctx->semantic_compat_mapping,
7716 ctx->domain, var->semantic.name, var->semantic.index, output, is_patch_constant_func);
7717 if (semantic == ~0u)
7719
7720 if (var->is_input_semantic)
7721 {
7722 switch (semantic)
7723 {
7727 break;
7728
7736 break;
7737
7738 default:
7741 break;
7742 }
7743 }
7744 else
7745 {
7748 else
7750 }
7751
7752 if (sm4_register_from_semantic_name(version, var->semantic.name, output, &type, &has_idx))
7753 {
7754 if (has_idx)
7755 idx = var->semantic.index;
7756 write_mask = (1u << var->data_type->dimx) - 1;
7757 }
7758 else
7759 {
7760 if (output)
7762 else if (version->type == VKD3D_SHADER_TYPE_DOMAIN)
7764 else
7766
7767 has_idx = true;
7768 idx = var->regs[HLSL_REGSET_NUMERIC].id;
7769 write_mask = var->regs[HLSL_REGSET_NUMERIC].writemask;
7770 }
7771
7772 if (!(ins = generate_vsir_add_program_instruction(ctx, program, loc, opcode, 0, 0)))
7773 return;
7774
7776 {
7779 dst_param = &ins->declaration.dst;
7780 }
7782 {
7784 dst_param = &ins->declaration.dst;
7785 }
7786 else
7787 {
7790 var->semantic.index);
7791 dst_param = &ins->declaration.register_semantic.reg;
7792 }
7793
7794 if (has_idx)
7795 {
7796 vsir_register_init(&dst_param->reg, type, VKD3D_DATA_FLOAT, 1);
7797 dst_param->reg.idx[0].offset = idx;
7798 }
7799 else
7800 {
7801 vsir_register_init(&dst_param->reg, type, VKD3D_DATA_FLOAT, 0);
7802 }
7803
7804 if (shader_sm4_is_scalar_register(&dst_param->reg))
7805 dst_param->reg.dimension = VSIR_DIMENSION_SCALAR;
7806 else
7807 dst_param->reg.dimension = VSIR_DIMENSION_VEC4;
7808
7809 dst_param->write_mask = write_mask;
7810
7811 if (var->is_input_semantic && version->type == VKD3D_SHADER_TYPE_PIXEL)
7812 ins->flags = sm4_get_interpolation_mode(var->data_type, var->storage_modifiers);
7813
7815}
7816
7818 uint32_t temp_count, struct hlsl_block *block, const struct vkd3d_shader_location *loc)
7819{
7820 struct vkd3d_shader_instruction *ins;
7821
7823 return;
7824
7825 ins->declaration.count = temp_count;
7826
7828}
7829
7831 struct vsir_program *program, struct hlsl_block *block, uint32_t idx,
7832 uint32_t size, uint32_t comp_count, const struct vkd3d_shader_location *loc)
7833{
7834 struct vkd3d_shader_instruction *ins;
7835
7837 return;
7838
7839 ins->declaration.indexable_temp.register_idx = idx;
7840 ins->declaration.indexable_temp.register_size = size;
7841 ins->declaration.indexable_temp.alignment = 0;
7843 ins->declaration.indexable_temp.component_count = comp_count;
7844 ins->declaration.indexable_temp.has_function_scope = false;
7845
7847}
7848
7849static bool type_is_float(const struct hlsl_type *type)
7850{
7851 return type->e.numeric.type == HLSL_TYPE_FLOAT || type->e.numeric.type == HLSL_TYPE_HALF;
7852}
7853
7854static bool type_is_integer(const struct hlsl_type *type)
7855{
7856 return type->e.numeric.type == HLSL_TYPE_BOOL
7857 || type->e.numeric.type == HLSL_TYPE_INT
7858 || type->e.numeric.type == HLSL_TYPE_UINT;
7859}
7860
7862 const struct hlsl_ir_expr *expr, uint32_t bits)
7863{
7864 struct hlsl_ir_node *operand = expr->operands[0].node;
7865 const struct hlsl_ir_node *instr = &expr->node;
7866 struct vkd3d_shader_dst_param *dst_param;
7867 struct hlsl_constant_value value = {0};
7868 struct vkd3d_shader_instruction *ins;
7869
7870 VKD3D_ASSERT(instr->reg.allocated);
7871
7872 if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_AND, 1, 2)))
7873 return;
7874
7875 dst_param = &ins->dst[0];
7876 vsir_dst_from_hlsl_node(dst_param, ctx, instr);
7877
7878 vsir_src_from_hlsl_node(&ins->src[0], ctx, operand, dst_param->write_mask);
7879
7880 value.u[0].u = bits;
7882}
7883
7885 struct vsir_program *program, struct hlsl_ir_expr *expr)
7886{
7887 const struct hlsl_ir_node *arg1 = expr->operands[0].node;
7888 const struct hlsl_type *dst_type = expr->node.data_type;
7889 const struct hlsl_type *src_type = arg1->data_type;
7890
7891 static const union
7892 {
7893 uint32_t u;
7894 float f;
7895 } one = { .f = 1.0 };
7896
7897 /* Narrowing casts were already lowered. */
7898 VKD3D_ASSERT(src_type->dimx == dst_type->dimx);
7899
7900 switch (dst_type->e.numeric.type)
7901 {
7902 case HLSL_TYPE_HALF:
7903 case HLSL_TYPE_FLOAT:
7904 switch (src_type->e.numeric.type)
7905 {
7906 case HLSL_TYPE_HALF:
7907 case HLSL_TYPE_FLOAT:
7909 return true;
7910
7911 case HLSL_TYPE_INT:
7913 return true;
7914
7915 case HLSL_TYPE_UINT:
7917 return true;
7918
7919 case HLSL_TYPE_BOOL:
7921 return true;
7922
7923 case HLSL_TYPE_DOUBLE:
7924 hlsl_fixme(ctx, &expr->node.loc, "SM4 cast from double to float.");
7925 return false;
7926
7927 default:
7929 }
7930 break;
7931
7932 case HLSL_TYPE_INT:
7933 switch (src_type->e.numeric.type)
7934 {
7935 case HLSL_TYPE_HALF:
7936 case HLSL_TYPE_FLOAT:
7938 return true;
7939
7940 case HLSL_TYPE_INT:
7941 case HLSL_TYPE_UINT:
7943 return true;
7944
7945 case HLSL_TYPE_BOOL:
7947 return true;
7948
7949 case HLSL_TYPE_DOUBLE:
7950 hlsl_fixme(ctx, &expr->node.loc, "SM4 cast from double to int.");
7951 return false;
7952
7953 default:
7955 }
7956 break;
7957
7958 case HLSL_TYPE_UINT:
7959 switch (src_type->e.numeric.type)
7960 {
7961 case HLSL_TYPE_HALF:
7962 case HLSL_TYPE_FLOAT:
7964 return true;
7965
7966 case HLSL_TYPE_INT:
7967 case HLSL_TYPE_UINT:
7969 return true;
7970
7971 case HLSL_TYPE_BOOL:
7973 return true;
7974
7975 case HLSL_TYPE_DOUBLE:
7976 hlsl_fixme(ctx, &expr->node.loc, "SM4 cast from double to uint.");
7977 return false;
7978
7979 default:
7981 }
7982 break;
7983
7984 case HLSL_TYPE_DOUBLE:
7985 hlsl_fixme(ctx, &expr->node.loc, "SM4 cast to double.");
7986 return false;
7987
7988 case HLSL_TYPE_BOOL:
7989 /* Casts to bool should have already been lowered. */
7990 default:
7992 }
7993}
7994
7996 enum vkd3d_shader_opcode opcode, const struct hlsl_ir_expr *expr, unsigned int dst_idx)
7997{
7998 struct vkd3d_shader_dst_param *dst_param, *null_param;
7999 const struct hlsl_ir_node *instr = &expr->node;
8000 struct vkd3d_shader_instruction *ins;
8001 unsigned int i, src_count;
8002
8003 VKD3D_ASSERT(instr->reg.allocated);
8004
8005 for (i = 0; i < HLSL_MAX_OPERANDS; ++i)
8006 {
8007 if (expr->operands[i].node)
8008 src_count = i + 1;
8009 }
8010
8012 return;
8013
8014 dst_param = &ins->dst[dst_idx];
8015 vsir_dst_from_hlsl_node(dst_param, ctx, instr);
8016
8017 null_param = &ins->dst[1 - dst_idx];
8019 null_param->reg.dimension = VSIR_DIMENSION_NONE;
8020
8021 for (i = 0; i < src_count; ++i)
8022 vsir_src_from_hlsl_node(&ins->src[i], ctx, expr->operands[i].node, dst_param->write_mask);
8023}
8024
8026 struct vsir_program *program, const struct hlsl_ir_expr *expr)
8027{
8028 struct hlsl_ir_node *operand = expr->operands[0].node;
8029 const struct hlsl_ir_node *instr = &expr->node;
8030 struct vkd3d_shader_dst_param *dst_param;
8031 struct hlsl_constant_value value = {0};
8032 struct vkd3d_shader_instruction *ins;
8033
8034 VKD3D_ASSERT(type_is_float(expr->node.data_type));
8035
8036 if (!(ins = generate_vsir_add_program_instruction(ctx, program, &instr->loc, VKD3DSIH_DIV, 1, 2)))
8037 return;
8038
8039 dst_param = &ins->dst[0];
8040 vsir_dst_from_hlsl_node(dst_param, ctx, instr);
8041
8042 value.u[0].f = 1.0f;
8043 value.u[1].f = 1.0f;
8044 value.u[2].f = 1.0f;
8045 value.u[3].f = 1.0f;
8047 VKD3D_DATA_FLOAT, instr->data_type->dimx, dst_param->write_mask);
8048
8049 vsir_src_from_hlsl_node(&ins->src[1], ctx, operand, dst_param->write_mask);
8050}
8051
8053 struct vsir_program *program, struct hlsl_ir_expr *expr, const char *dst_type_name)
8054{
8055 const struct hlsl_type *dst_type = expr->node.data_type;
8056 const struct hlsl_type *src_type = NULL;
8057
8058 VKD3D_ASSERT(expr->node.reg.allocated);
8059 if (expr->operands[0].node)
8060 src_type = expr->operands[0].node->data_type;
8061
8062 switch (expr->op)
8063 {
8066 return true;
8067
8068 case HLSL_OP1_ABS:
8069 VKD3D_ASSERT(type_is_float(dst_type));
8071 return true;
8072
8073 case HLSL_OP1_BIT_NOT:
8074 VKD3D_ASSERT(type_is_integer(dst_type));
8076 return true;
8077
8078 case HLSL_OP1_CAST:
8080
8081 case HLSL_OP1_CEIL:
8082 VKD3D_ASSERT(type_is_float(dst_type));
8084 return true;
8085
8086 case HLSL_OP1_COS:
8087 VKD3D_ASSERT(type_is_float(dst_type));
8089 return true;
8090
8091 case HLSL_OP1_DSX:
8092 VKD3D_ASSERT(type_is_float(dst_type));
8094 return true;
8095
8097 VKD3D_ASSERT(type_is_float(dst_type));
8099 return true;
8100
8101 case HLSL_OP1_DSX_FINE:
8102 VKD3D_ASSERT(type_is_float(dst_type));
8104 return true;
8105
8106 case HLSL_OP1_DSY:
8107 VKD3D_ASSERT(type_is_float(dst_type));
8109 return true;
8110
8112 VKD3D_ASSERT(type_is_float(dst_type));
8114 return true;
8115
8116 case HLSL_OP1_DSY_FINE:
8117 VKD3D_ASSERT(type_is_float(dst_type));
8119 return true;
8120
8121 case HLSL_OP1_EXP2:
8122 VKD3D_ASSERT(type_is_float(dst_type));
8124 return true;
8125
8126 case HLSL_OP1_F16TOF32:
8127 VKD3D_ASSERT(type_is_float(dst_type));
8130 return true;
8131
8132 case HLSL_OP1_F32TOF16:
8133 VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_UINT);
8136 return true;
8137
8138 case HLSL_OP1_FLOOR:
8139 VKD3D_ASSERT(type_is_float(dst_type));
8141 return true;
8142
8143 case HLSL_OP1_FRACT:
8144 VKD3D_ASSERT(type_is_float(dst_type));
8146 return true;
8147
8148 case HLSL_OP1_LOG2:
8149 VKD3D_ASSERT(type_is_float(dst_type));
8151 return true;
8152
8153 case HLSL_OP1_LOGIC_NOT:
8154 VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
8156 return true;
8157
8158 case HLSL_OP1_NEG:
8159 switch (dst_type->e.numeric.type)
8160 {
8161 case HLSL_TYPE_FLOAT:
8163 return true;
8164
8165 case HLSL_TYPE_INT:
8166 case HLSL_TYPE_UINT:
8168 return true;
8169
8170 default:
8171 hlsl_fixme(ctx, &expr->node.loc, "SM4 %s negation expression.", dst_type_name);
8172 return false;
8173 }
8174
8175 case HLSL_OP1_RCP:
8176 switch (dst_type->e.numeric.type)
8177 {
8178 case HLSL_TYPE_FLOAT:
8179 /* SM5 comes with a RCP opcode */
8180 if (hlsl_version_ge(ctx, 5, 0))
8182 else
8184 return true;
8185
8186 default:
8187 hlsl_fixme(ctx, &expr->node.loc, "SM4 %s rcp expression.", dst_type_name);
8188 return false;
8189 }
8190
8193 return true;
8194
8195 case HLSL_OP1_ROUND:
8196 VKD3D_ASSERT(type_is_float(dst_type));
8198 return true;
8199
8200 case HLSL_OP1_RSQ:
8201 VKD3D_ASSERT(type_is_float(dst_type));
8203 return true;
8204
8205 case HLSL_OP1_SAT:
8206 VKD3D_ASSERT(type_is_float(dst_type));
8208 return true;
8209
8210 case HLSL_OP1_SIN:
8211 VKD3D_ASSERT(type_is_float(dst_type));
8213 return true;
8214
8215 case HLSL_OP1_SQRT:
8216 VKD3D_ASSERT(type_is_float(dst_type));
8218 return true;
8219
8220 case HLSL_OP1_TRUNC:
8221 VKD3D_ASSERT(type_is_float(dst_type));
8223 return true;
8224
8225 case HLSL_OP2_ADD:
8226 switch (dst_type->e.numeric.type)
8227 {
8228 case HLSL_TYPE_FLOAT:
8230 return true;
8231
8232 case HLSL_TYPE_INT:
8233 case HLSL_TYPE_UINT:
8235 return true;
8236
8237 default:
8238 hlsl_fixme(ctx, &expr->node.loc, "SM4 %s addition expression.", dst_type_name);
8239 return false;
8240 }
8241
8242 case HLSL_OP2_BIT_AND:
8243 VKD3D_ASSERT(type_is_integer(dst_type));
8245 return true;
8246
8247 case HLSL_OP2_BIT_OR:
8248 VKD3D_ASSERT(type_is_integer(dst_type));
8250 return true;
8251
8252 case HLSL_OP2_BIT_XOR:
8253 VKD3D_ASSERT(type_is_integer(dst_type));
8255 return true;
8256
8257 case HLSL_OP2_DIV:
8258 switch (dst_type->e.numeric.type)
8259 {
8260 case HLSL_TYPE_FLOAT:
8262 return true;
8263
8264 case HLSL_TYPE_UINT:
8266 return true;
8267
8268 default:
8269 hlsl_fixme(ctx, &expr->node.loc, "SM4 %s division expression.", dst_type_name);
8270 return false;
8271 }
8272
8273 case HLSL_OP2_DOT:
8274 switch (dst_type->e.numeric.type)
8275 {
8276 case HLSL_TYPE_FLOAT:
8277 switch (expr->operands[0].node->data_type->dimx)
8278 {
8279 case 4:
8281 return true;
8282
8283 case 3:
8285 return true;
8286
8287 case 2:
8289 return true;
8290
8291 case 1:
8292 default:
8294 }
8295
8296 default:
8297 hlsl_fixme(ctx, &expr->node.loc, "SM4 %s dot expression.", dst_type_name);
8298 return false;
8299 }
8300
8301 case HLSL_OP2_EQUAL:
8302 VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
8303
8304 switch (src_type->e.numeric.type)
8305 {
8306 case HLSL_TYPE_FLOAT:
8308 return true;
8309
8310 case HLSL_TYPE_BOOL:
8311 case HLSL_TYPE_INT:
8312 case HLSL_TYPE_UINT:
8314 return true;
8315
8316 default:
8317 hlsl_fixme(ctx, &expr->node.loc, "SM4 equality between \"%s\" operands.",
8318 debug_hlsl_type(ctx, src_type));
8319 return false;
8320 }
8321
8322 case HLSL_OP2_GEQUAL:
8323 VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
8324
8325 switch (src_type->e.numeric.type)
8326 {
8327 case HLSL_TYPE_FLOAT:
8329 return true;
8330
8331 case HLSL_TYPE_INT:
8333 return true;
8334
8335 case HLSL_TYPE_BOOL:
8336 case HLSL_TYPE_UINT:
8338 return true;
8339
8340 default:
8341 hlsl_fixme(ctx, &expr->node.loc, "SM4 greater-than-or-equal between \"%s\" operands.",
8342 debug_hlsl_type(ctx, src_type));
8343 return false;
8344 }
8345
8346 case HLSL_OP2_LESS:
8347 VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
8348
8349 switch (src_type->e.numeric.type)
8350 {
8351 case HLSL_TYPE_FLOAT:
8353 return true;
8354
8355 case HLSL_TYPE_INT:
8357 return true;
8358
8359 case HLSL_TYPE_BOOL:
8360 case HLSL_TYPE_UINT:
8362 return true;
8363
8364 default:
8365 hlsl_fixme(ctx, &expr->node.loc, "SM4 less-than between \"%s\" operands.",
8366 debug_hlsl_type(ctx, src_type));
8367 return false;
8368 }
8369
8370 case HLSL_OP2_LOGIC_AND:
8371 VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
8373 return true;
8374
8375 case HLSL_OP2_LOGIC_OR:
8376 VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
8378 return true;
8379
8380 case HLSL_OP2_LSHIFT:
8381 VKD3D_ASSERT(type_is_integer(dst_type));
8382 VKD3D_ASSERT(dst_type->e.numeric.type != HLSL_TYPE_BOOL);
8384 return true;
8385
8386 case HLSL_OP3_MAD:
8387 switch (dst_type->e.numeric.type)
8388 {
8389 case HLSL_TYPE_FLOAT:
8391 return true;
8392
8393 case HLSL_TYPE_INT:
8394 case HLSL_TYPE_UINT:
8396 return true;
8397
8398 default:
8399 hlsl_fixme(ctx, &expr->node.loc, "SM4 %s MAD expression.", dst_type_name);
8400 return false;
8401 }
8402
8403 case HLSL_OP2_MAX:
8404 switch (dst_type->e.numeric.type)
8405 {
8406 case HLSL_TYPE_FLOAT:
8408 return true;
8409
8410 case HLSL_TYPE_INT:
8412 return true;
8413
8414 case HLSL_TYPE_UINT:
8416 return true;
8417
8418 default:
8419 hlsl_fixme(ctx, &expr->node.loc, "SM4 %s maximum expression.", dst_type_name);
8420 return false;
8421 }
8422
8423 case HLSL_OP2_MIN:
8424 switch (dst_type->e.numeric.type)
8425 {
8426 case HLSL_TYPE_FLOAT:
8428 return true;
8429
8430 case HLSL_TYPE_INT:
8432 return true;
8433
8434 case HLSL_TYPE_UINT:
8436 return true;
8437
8438 default:
8439 hlsl_fixme(ctx, &expr->node.loc, "SM4 %s minimum expression.", dst_type_name);
8440 return false;
8441 }
8442
8443 case HLSL_OP2_MOD:
8444 switch (dst_type->e.numeric.type)
8445 {
8446 case HLSL_TYPE_UINT:
8448 return true;
8449
8450 default:
8451 hlsl_fixme(ctx, &expr->node.loc, "SM4 %s modulus expression.", dst_type_name);
8452 return false;
8453 }
8454
8455 case HLSL_OP2_MUL:
8456 switch (dst_type->e.numeric.type)
8457 {
8458 case HLSL_TYPE_FLOAT:
8460 return true;
8461
8462 case HLSL_TYPE_INT:
8463 case HLSL_TYPE_UINT:
8464 /* Using IMUL instead of UMUL because we're taking the low
8465 * bits, and the native compiler generates IMUL. */
8467 return true;
8468
8469 default:
8470 hlsl_fixme(ctx, &expr->node.loc, "SM4 %s multiplication expression.", dst_type_name);
8471 return false;
8472 }
8473
8474 case HLSL_OP2_NEQUAL:
8475 VKD3D_ASSERT(dst_type->e.numeric.type == HLSL_TYPE_BOOL);
8476
8477 switch (src_type->e.numeric.type)
8478 {
8479 case HLSL_TYPE_FLOAT:
8481 return true;
8482
8483 case HLSL_TYPE_BOOL:
8484 case HLSL_TYPE_INT:
8485 case HLSL_TYPE_UINT:
8487 return true;
8488
8489 default:
8490 hlsl_fixme(ctx, &expr->node.loc, "SM4 inequality between \"%s\" operands.",
8491 debug_hlsl_type(ctx, src_type));
8492 return false;
8493 }
8494
8495 case HLSL_OP2_RSHIFT:
8496 VKD3D_ASSERT(type_is_integer(dst_type));
8497 VKD3D_ASSERT(dst_type->e.numeric.type != HLSL_TYPE_BOOL);
8499 dst_type->e.numeric.type == HLSL_TYPE_INT ? VKD3DSIH_ISHR : VKD3DSIH_USHR, 0, 0, true);
8500 return true;
8501
8502 case HLSL_OP3_TERNARY:
8504 return true;
8505
8506 default:
8507 hlsl_fixme(ctx, &expr->node.loc, "SM4 %s expression.", debug_hlsl_expr_op(expr->op));
8508 return false;
8509 }
8510}
8511
8513{
8514 struct vkd3d_string_buffer *dst_type_string;
8515 struct hlsl_ir_node *instr, *next;
8516 struct hlsl_ir_switch_case *c;
8517
8518 LIST_FOR_EACH_ENTRY_SAFE(instr, next, &block->instrs, struct hlsl_ir_node, entry)
8519 {
8520 if (instr->data_type)
8521 {
8522 if (instr->data_type->class != HLSL_CLASS_SCALAR && instr->data_type->class != HLSL_CLASS_VECTOR)
8523 {
8524 hlsl_fixme(ctx, &instr->loc, "Class %#x should have been lowered or removed.", instr->data_type->class);
8525 break;
8526 }
8527 }
8528
8529 switch (instr->type)
8530 {
8531 case HLSL_IR_CALL:
8533
8534 case HLSL_IR_CONSTANT:
8535 /* In SM4 all constants are inlined. */
8536 break;
8537
8538 case HLSL_IR_EXPR:
8539 if (!(dst_type_string = hlsl_type_to_string(ctx, instr->data_type)))
8540 break;
8541
8542 if (sm4_generate_vsir_instr_expr(ctx, program, hlsl_ir_expr(instr), dst_type_string->buffer))
8544
8545 hlsl_release_string_buffer(ctx, dst_type_string);
8546 break;
8547
8548 case HLSL_IR_IF:
8549 sm4_generate_vsir_block(ctx, &hlsl_ir_if(instr)->then_block, program);
8550 sm4_generate_vsir_block(ctx, &hlsl_ir_if(instr)->else_block, program);
8551 break;
8552
8553 case HLSL_IR_LOOP:
8555 break;
8556
8557 case HLSL_IR_SWITCH:
8560 break;
8561
8562 case HLSL_IR_SWIZZLE:
8565 break;
8566
8567 default:
8568 break;
8569 }
8570 }
8571}
8572
8574 struct hlsl_ir_function_decl *func, uint64_t config_flags, struct vsir_program *program)
8575{
8576 bool is_patch_constant_func = func == ctx->patch_constant_func;
8577 struct hlsl_block block = {0};
8578 struct hlsl_scope *scope;
8579 struct hlsl_ir_var *var;
8580 uint32_t temp_count;
8581
8584 temp_count = allocate_temp_registers(ctx, func);
8585 if (ctx->result)
8586 return;
8587 program->temp_count = max(program->temp_count, temp_count);
8588
8590
8591 LIST_FOR_EACH_ENTRY(var, &func->extern_vars, struct hlsl_ir_var, extern_entry)
8592 {
8593 if ((var->is_input_semantic && var->last_read)
8594 || (var->is_output_semantic && var->first_write))
8595 sm4_generate_vsir_instr_dcl_semantic(ctx, program, var, is_patch_constant_func, &block, &var->loc);
8596 }
8597
8598 if (temp_count)
8600
8601 LIST_FOR_EACH_ENTRY(scope, &ctx->scopes, struct hlsl_scope, entry)
8602 {
8604 {
8605 if (var->is_uniform || var->is_input_semantic || var->is_output_semantic)
8606 continue;
8607 if (!var->regs[HLSL_REGSET_NUMERIC].allocated)
8608 continue;
8609
8610 if (var->indexable)
8611 {
8612 unsigned int id = var->regs[HLSL_REGSET_NUMERIC].id;
8613 unsigned int size = align(var->data_type->reg_size[HLSL_REGSET_NUMERIC], 4) / 4;
8614
8616 }
8617 }
8618 }
8619
8620 list_move_head(&func->body.instrs, &block.instrs);
8621
8623
8625}
8626
8627/* OBJECTIVE: Translate all the information from ctx and entry_func to the
8628 * vsir_program, so it can be used as input to tpf_compile() without relying
8629 * on ctx and entry_func. */
8631 uint64_t config_flags, struct vsir_program *program)
8632{
8633 struct vkd3d_shader_version version = {0};
8634
8635 version.major = ctx->profile->major_version;
8636 version.minor = ctx->profile->minor_version;
8637 version.type = ctx->profile->type;
8638
8640 {
8642 return;
8643 }
8644
8646 if (version.type == VKD3D_SHADER_TYPE_HULL)
8647 generate_vsir_signature(ctx, program, ctx->patch_constant_func);
8648
8650 {
8651 program->thread_group_size.x = ctx->thread_count[0];
8652 program->thread_group_size.y = ctx->thread_count[1];
8653 program->thread_group_size.z = ctx->thread_count[2];
8654 }
8655
8657 if (version.type == VKD3D_SHADER_TYPE_HULL)
8658 sm4_generate_vsir_add_function(ctx, ctx->patch_constant_func, config_flags, program);
8659}
8660
8661static struct hlsl_ir_jump *loop_unrolling_find_jump(struct hlsl_block *block, struct hlsl_ir_node *stop_point,
8662 struct hlsl_block **found_block)
8663{
8664 struct hlsl_ir_node *node;
8665
8666 LIST_FOR_EACH_ENTRY(node, &block->instrs, struct hlsl_ir_node, entry)
8667 {
8668 if (node == stop_point)
8669 return NULL;
8670
8671 if (node->type == HLSL_IR_IF)
8672 {
8673 struct hlsl_ir_if *iff = hlsl_ir_if(node);
8674 struct hlsl_ir_jump *jump = NULL;
8675
8676 if ((jump = loop_unrolling_find_jump(&iff->then_block, stop_point, found_block)))
8677 return jump;
8678 if ((jump = loop_unrolling_find_jump(&iff->else_block, stop_point, found_block)))
8679 return jump;
8680 }
8681 else if (node->type == HLSL_IR_JUMP)
8682 {
8683 struct hlsl_ir_jump *jump = hlsl_ir_jump(node);
8684
8685 if (jump->type == HLSL_IR_JUMP_BREAK || jump->type == HLSL_IR_JUMP_CONTINUE)
8686 {
8687 *found_block = block;
8688 return jump;
8689 }
8690 }
8691 }
8692
8693 return NULL;
8694}
8695
8696static unsigned int loop_unrolling_get_max_iterations(struct hlsl_ctx *ctx, struct hlsl_ir_loop *loop)
8697{
8698 /* Always use the explicit limit if it has been passed. */
8699 if (loop->unroll_limit)
8700 return loop->unroll_limit;
8701
8702 /* All SMs will default to 1024 if [unroll] has been specified without an explicit limit. */
8704 return 1024;
8705
8706 /* SM4 limits implicit unrolling to 254 iterations. */
8707 if (hlsl_version_ge(ctx, 4, 0))
8708 return 254;
8709
8710 /* SM<3 implicitly unrolls up to 1024 iterations. */
8711 return 1024;
8712}
8713
8715 struct hlsl_block *loop_parent, struct hlsl_ir_loop *loop)
8716{
8717 unsigned int max_iterations, i;
8718
8719 max_iterations = loop_unrolling_get_max_iterations(ctx, loop);
8720
8721 for (i = 0; i < max_iterations; ++i)
8722 {
8723 struct hlsl_block tmp_dst, *jump_block;
8724 struct hlsl_ir_jump *jump = NULL;
8725
8726 if (!hlsl_clone_block(ctx, &tmp_dst, &loop->body))
8727 return false;
8728 list_move_before(&loop->node.entry, &tmp_dst.instrs);
8729 hlsl_block_cleanup(&tmp_dst);
8730
8732
8733 if ((jump = loop_unrolling_find_jump(loop_parent, &loop->node, &jump_block)))
8734 {
8735 enum hlsl_ir_jump_type type = jump->type;
8736
8737 if (jump_block != loop_parent)
8738 {
8741 "Unable to unroll loop, unrolling loops with conditional jumps is currently not supported.");
8742 return false;
8743 }
8744
8745 list_move_slice_tail(&tmp_dst.instrs, &jump->node.entry, list_prev(&loop_parent->instrs, &loop->node.entry));
8746 hlsl_block_cleanup(&tmp_dst);
8747
8748 if (type == HLSL_IR_JUMP_BREAK)
8749 break;
8750 }
8751 }
8752
8753 /* Native will not emit an error if max_iterations has been reached with an
8754 * explicit limit. It also will not insert a loop if there are iterations left
8755 * i.e [unroll(4)] for (i = 0; i < 8; ++i)) */
8756 if (!loop->unroll_limit && i == max_iterations)
8757 {
8760 "Unable to unroll loop, maximum iterations reached (%u).", max_iterations);
8761 return false;
8762 }
8763
8764 list_remove(&loop->node.entry);
8765 hlsl_free_instr(&loop->node);
8766
8767 return true;
8768}
8769
8770/*
8771 * loop_unrolling_find_unrollable_loop() is not the normal way to do things;
8772 * normal passes simply iterate over the whole block and apply a transformation
8773 * to every relevant instruction. However, loop unrolling can fail, and we want
8774 * to leave the loop in its previous state in that case. That isn't a problem by
8775 * itself, except that loop unrolling needs copy-prop in order to work properly,
8776 * and copy-prop state at the time of the loop depends on the rest of the program
8777 * up to that point. This means we need to clone the whole program, and at that
8778 * point we have to search it again anyway to find the clone of the loop we were
8779 * going to unroll.
8780 *
8781 * FIXME: Ideally we wouldn't clone the whole program; instead we would run copyprop
8782 * up until the loop instruction, clone just that loop, then use copyprop again
8783 * with the saved state after unrolling. However, copyprop currently isn't built
8784 * for that yet [notably, it still relies on indices]. Note also this still doesn't
8785 * really let us use transform_ir() anyway [since we don't have a good way to say
8786 * "copyprop from the beginning of the program up to the instruction we're
8787 * currently processing" from the callback]; we'd have to use a dedicated
8788 * recursive function instead. */
8790 struct hlsl_block **containing_block)
8791{
8792 struct hlsl_ir_node *instr;
8793
8794 LIST_FOR_EACH_ENTRY(instr, &block->instrs, struct hlsl_ir_node, entry)
8795 {
8796 switch (instr->type)
8797 {
8798 case HLSL_IR_LOOP:
8799 {
8800 struct hlsl_ir_loop *nested_loop;
8801 struct hlsl_ir_loop *loop = hlsl_ir_loop(instr);
8802
8803 if ((nested_loop = loop_unrolling_find_unrollable_loop(ctx, &loop->body, containing_block)))
8804 return nested_loop;
8805
8807 {
8808 *containing_block = block;
8809 return loop;
8810 }
8811
8812 break;
8813 }
8814 case HLSL_IR_IF:
8815 {
8816 struct hlsl_ir_loop *loop;
8817 struct hlsl_ir_if *iff = hlsl_ir_if(instr);
8818
8819 if ((loop = loop_unrolling_find_unrollable_loop(ctx, &iff->then_block, containing_block)))
8820 return loop;
8821 if ((loop = loop_unrolling_find_unrollable_loop(ctx, &iff->else_block, containing_block)))
8822 return loop;
8823
8824 break;
8825 }
8826 case HLSL_IR_SWITCH:
8827 {
8828 struct hlsl_ir_switch *s = hlsl_ir_switch(instr);
8829 struct hlsl_ir_switch_case *c;
8830 struct hlsl_ir_loop *loop;
8831
8833 {
8834 if ((loop = loop_unrolling_find_unrollable_loop(ctx, &c->body, containing_block)))
8835 return loop;
8836 }
8837
8838 break;
8839 }
8840 default:
8841 break;
8842 }
8843 }
8844
8845 return NULL;
8846}
8847
8849{
8850 while (true)
8851 {
8852 struct hlsl_block clone, *containing_block;
8853 struct hlsl_ir_loop *loop, *cloned_loop;
8854
8855 if (!(loop = loop_unrolling_find_unrollable_loop(ctx, block, &containing_block)))
8856 return;
8857
8858 if (!hlsl_clone_block(ctx, &clone, block))
8859 return;
8860
8861 cloned_loop = loop_unrolling_find_unrollable_loop(ctx, &clone, &containing_block);
8862 VKD3D_ASSERT(cloned_loop);
8863
8864 if (!loop_unrolling_unroll_loop(ctx, &clone, containing_block, cloned_loop))
8865 {
8866 hlsl_block_cleanup(&clone);
8868 continue;
8869 }
8870
8873 hlsl_block_add_block(block, &clone);
8874 }
8875}
8876
8877static bool lower_f16tof32(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block)
8878{
8879 struct hlsl_ir_node *call, *rhs, *store;
8881 unsigned int component_count;
8882 struct hlsl_ir_load *load;
8883 struct hlsl_ir_expr *expr;
8884 struct hlsl_ir_var *lhs;
8885 char *body;
8886
8887 static const char template[] =
8888 "typedef uint%u uintX;\n"
8889 "float%u soft_f16tof32(uintX x)\n"
8890 "{\n"
8891 " uintX mantissa = x & 0x3ff;\n"
8892 " uintX high2 = mantissa >> 8;\n"
8893 " uintX high2_check = high2 ? high2 : mantissa;\n"
8894 " uintX high6 = high2_check >> 4;\n"
8895 " uintX high6_check = high6 ? high6 : high2_check;\n"
8896 "\n"
8897 " uintX high8 = high6_check >> 2;\n"
8898 " uintX high8_check = (high8 ? high8 : high6_check) >> 1;\n"
8899 " uintX shift = high6 ? (high2 ? 12 : 4) : (high2 ? 8 : 0);\n"
8900 " shift = high8 ? shift + 2 : shift;\n"
8901 " shift = high8_check ? shift + 1 : shift;\n"
8902 " shift = -shift + 10;\n"
8903 " shift = mantissa ? shift : 11;\n"
8904 " uintX subnormal_mantissa = ((mantissa << shift) << 23) & 0x7fe000;\n"
8905 " uintX subnormal_exp = -(shift << 23) + 0x38800000;\n"
8906 " uintX subnormal_val = subnormal_exp + subnormal_mantissa;\n"
8907 " uintX subnormal_or_zero = mantissa ? subnormal_val : 0;\n"
8908 "\n"
8909 " uintX exponent = (((x >> 10) << 23) & 0xf800000) + 0x38000000;\n"
8910 "\n"
8911 " uintX low_3 = (x << 13) & 0x7fe000;\n"
8912 " uintX normalized_val = exponent + low_3;\n"
8913 " uintX inf_nan_val = low_3 + 0x7f800000;\n"
8914 "\n"
8915 " uintX exp_mask = 0x7c00;\n"
8916 " uintX is_inf_nan = (x & exp_mask) == exp_mask;\n"
8917 " uintX is_normalized = x & exp_mask;\n"
8918 "\n"
8919 " uintX check = is_inf_nan ? inf_nan_val : normalized_val;\n"
8920 " uintX exp_mantissa = (is_normalized ? check : subnormal_or_zero) & 0x7fffe000;\n"
8921 " uintX sign_bit = (x << 16) & 0x80000000;\n"
8922 "\n"
8923 " return asfloat(exp_mantissa + sign_bit);\n"
8924 "}\n";
8925
8926
8927 if (node->type != HLSL_IR_EXPR)
8928 return false;
8929
8931
8932 if (expr->op != HLSL_OP1_F16TOF32)
8933 return false;
8934
8935 rhs = expr->operands[0].node;
8937
8939 return false;
8940
8941 if (!(func = hlsl_compile_internal_function(ctx, "soft_f16tof32", body)))
8942 return false;
8943
8944 lhs = func->parameters.vars[0];
8945
8946 if (!(store = hlsl_new_simple_store(ctx, lhs, rhs)))
8947 return false;
8949
8950 if (!(call = hlsl_new_call(ctx, func, &node->loc)))
8951 return false;
8953
8954 if (!(load = hlsl_new_var_load(ctx, func->return_var, &node->loc)))
8955 return false;
8957
8958 return true;
8959}
8960
8961static bool lower_f32tof16(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block)
8962{
8963 struct hlsl_ir_node *call, *rhs, *store;
8965 unsigned int component_count;
8966 struct hlsl_ir_load *load;
8967 struct hlsl_ir_expr *expr;
8968 struct hlsl_ir_var *lhs;
8969 char *body;
8970
8971 static const char template[] =
8972 "typedef uint%u uintX;\n"
8973 "uintX soft_f32tof16(float%u x)\n"
8974 "{\n"
8975 " uintX v = asuint(x);\n"
8976 " uintX v_abs = v & 0x7fffffff;\n"
8977 " uintX sign_bit = (v >> 16) & 0x8000;\n"
8978 " uintX exp = (v >> 23) & 0xff;\n"
8979 " uintX mantissa = v & 0x7fffff;\n"
8980 " uintX nan16;\n"
8981 " uintX nan = (v & 0x7f800000) == 0x7f800000;\n"
8982 " uintX val;\n"
8983 "\n"
8984 " val = 113 - exp;\n"
8985 " val = (mantissa + 0x800000) >> val;\n"
8986 " val >>= 13;\n"
8987 "\n"
8988 " val = (exp - 127) < -38 ? 0 : val;\n"
8989 "\n"
8990 " val = v_abs < 0x38800000 ? val : (v_abs + 0xc8000000) >> 13;\n"
8991 " val = v_abs > 0x47ffe000 ? 0x7bff : val;\n"
8992 "\n"
8993 " nan16 = (((v >> 13) | (v >> 3) | v) & 0x3ff) + 0x7c00;\n"
8994 " val = nan ? nan16 : val;\n"
8995 "\n"
8996 " return (val & 0x7fff) + sign_bit;\n"
8997 "}\n";
8998
8999 if (node->type != HLSL_IR_EXPR)
9000 return false;
9001
9003
9004 if (expr->op != HLSL_OP1_F32TOF16)
9005 return false;
9006
9007 rhs = expr->operands[0].node;
9009
9011 return false;
9012
9013 if (!(func = hlsl_compile_internal_function(ctx, "soft_f32tof16", body)))
9014 return false;
9015
9016 lhs = func->parameters.vars[0];
9017
9018 if (!(store = hlsl_new_simple_store(ctx, lhs, rhs)))
9019 return false;
9021
9022 if (!(call = hlsl_new_call(ctx, func, &node->loc)))
9023 return false;
9025
9026 if (!(load = hlsl_new_var_load(ctx, func->return_var, &node->loc)))
9027 return false;
9029
9030 return true;
9031}
9032
9034 const struct hlsl_block *global_uniform_block, struct hlsl_ir_function_decl *entry_func)
9035{
9036 const struct hlsl_profile_info *profile = ctx->profile;
9037 struct hlsl_block static_initializers, global_uniforms;
9038 struct hlsl_block *const body = &entry_func->body;
9040 struct hlsl_ir_var *var;
9041 unsigned int i;
9042
9043 if (!hlsl_clone_block(ctx, &static_initializers, &ctx->static_initializers))
9044 return;
9045 list_move_head(&body->instrs, &static_initializers.instrs);
9046
9047 if (!hlsl_clone_block(ctx, &global_uniforms, global_uniform_block))
9048 return;
9049 list_move_head(&body->instrs, &global_uniforms.instrs);
9050
9054
9055 /* Avoid going into an infinite loop when processing call instructions.
9056 * lower_return() recurses into inferior calls. */
9057 if (ctx->result)
9058 return;
9059
9060 if (hlsl_version_ge(ctx, 4, 0) && hlsl_version_lt(ctx, 5, 0))
9061 {
9064 }
9065
9066 lower_return(ctx, entry_func, body, false);
9067
9069
9072
9073 for (i = 0; i < entry_func->parameters.count; ++i)
9074 {
9075 var = entry_func->parameters.vars[i];
9076
9077 if (hlsl_type_is_resource(var->data_type))
9078 {
9080 }
9081 else if ((var->storage_modifiers & HLSL_STORAGE_UNIFORM))
9082 {
9083 if (ctx->profile->type == VKD3D_SHADER_TYPE_HULL && entry_func == ctx->patch_constant_func)
9085 "Patch constant function parameter \"%s\" cannot be uniform.", var->name);
9086 else
9088 }
9089 else
9090 {
9092 && !var->semantic.name)
9093 {
9095 "Parameter \"%s\" is missing a semantic.", var->name);
9096 var->semantic.reported_missing = true;
9097 }
9098
9099 if (var->storage_modifiers & HLSL_STORAGE_IN)
9100 prepend_input_var_copy(ctx, entry_func, var);
9101 if (var->storage_modifiers & HLSL_STORAGE_OUT)
9102 append_output_var_copy(ctx, entry_func, var);
9103 }
9104 }
9105 if (entry_func->return_var)
9106 {
9107 if (entry_func->return_var->data_type->class != HLSL_CLASS_STRUCT && !entry_func->return_var->semantic.name)
9109 "Entry point \"%s\" is missing a return value semantic.", entry_func->func->name);
9110
9111 append_output_var_copy(ctx, entry_func, entry_func->return_var);
9112 }
9113
9114 if (profile->major_version >= 4)
9115 {
9117 }
9118 else
9119 {
9121 }
9122
9125
9128
9132
9135 if (profile->major_version >= 4)
9137
9138 do
9139 compute_liveness(ctx, entry_func);
9140 while (hlsl_transform_ir(ctx, dce, body, NULL));
9141
9144
9145 if (profile->major_version < 4)
9146 {
9148
9150
9152 /* Constants casted to float must be folded, and new casts to bool also need to be lowered. */
9155
9166 if (ctx->profile->type == VKD3D_SHADER_TYPE_PIXEL)
9168 else
9170 }
9171
9172 if (profile->major_version < 2)
9173 {
9175 }
9176
9178
9179 do
9180 compute_liveness(ctx, entry_func);
9181 while (hlsl_transform_ir(ctx, dce, body, NULL));
9182
9183 /* TODO: move forward, remove when no longer needed */
9187
9188 do
9189 compute_liveness(ctx, entry_func);
9190 while (hlsl_transform_ir(ctx, dce, body, NULL));
9191
9192 compute_liveness(ctx, entry_func);
9194
9196
9197 allocate_register_reservations(ctx, &ctx->extern_vars);
9199 allocate_semantic_registers(ctx, entry_func);
9200}
9201
9204{
9205 const struct hlsl_profile_info *profile = ctx->profile;
9206 struct hlsl_block global_uniform_block;
9207 struct hlsl_ir_var *var;
9208
9210 if (ctx->result)
9211 return ctx->result;
9212
9213 if (profile->type == VKD3D_SHADER_TYPE_HULL)
9215 else if (profile->type == VKD3D_SHADER_TYPE_COMPUTE && !ctx->found_numthreads)
9217 "Entry point \"%s\" is missing a [numthreads] attribute.", entry_func->func->name);
9220 "Entry point \"%s\" is missing a [domain] attribute.", entry_func->func->name);
9221
9222 hlsl_block_init(&global_uniform_block);
9223
9224 LIST_FOR_EACH_ENTRY(var, &ctx->globals->vars, struct hlsl_ir_var, scope_entry)
9225 {
9226 if (var->storage_modifiers & HLSL_STORAGE_UNIFORM)
9227 prepend_uniform_copy(ctx, &global_uniform_block, var);
9228 }
9229
9230 process_entry_function(ctx, &global_uniform_block, entry_func);
9231 if (ctx->result)
9232 return ctx->result;
9233
9234 if (profile->type == VKD3D_SHADER_TYPE_HULL)
9235 {
9236 process_entry_function(ctx, &global_uniform_block, ctx->patch_constant_func);
9237 if (ctx->result)
9238 return ctx->result;
9239 }
9240
9241 hlsl_block_cleanup(&global_uniform_block);
9242
9243 if (profile->major_version < 4)
9244 {
9245 mark_indexable_vars(ctx, entry_func);
9246 allocate_temp_registers(ctx, entry_func);
9247 allocate_const_registers(ctx, entry_func);
9248 }
9249 else
9250 {
9254 }
9256
9257 if (TRACE_ON())
9258 rb_for_each_entry(&ctx->functions, dump_function, ctx);
9259
9260 if (ctx->result)
9261 return ctx->result;
9262
9263 switch (target_type)
9264 {
9266 {
9268 struct vkd3d_shader_code ctab = {0};
9269 struct vsir_program program;
9270 int result;
9271
9272 sm1_generate_vsir(ctx, entry_func, config_flags, &program, &ctab);
9273 if (ctx->result)
9274 {
9277 return ctx->result;
9278 }
9279
9280 result = d3dbc_compile(&program, config_flags, NULL, &ctab, out, ctx->message_context);
9283 return result;
9284 }
9285
9287 {
9289 struct vsir_program program;
9290 int result;
9291
9292 sm4_generate_vsir(ctx, entry_func, config_flags, &program);
9293 if (ctx->result)
9294 {
9296 return ctx->result;
9297 }
9298
9299 result = tpf_compile(&program, config_flags, out, ctx->message_context, ctx, entry_func);
9301 return result;
9302 }
9303
9304 default:
9305 ERR("Unsupported shader target type %#x.\n", target_type);
9307 }
9308}
#define is_range_available(RangeList, Start, End, pAvail)
struct outqueuenode * tail
Definition: adnsresfilter.c:66
static const unsigned char reg_size[]
Definition: amd64_sup.c:21
static int state
Definition: maze.c:121
#define trace
Definition: atltest.h:70
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
pair cons(caddr_t car, pair cdr)
Definition: tree.c:57
static void list_remove(struct list_entry *entry)
Definition: list.h:90
static int list_empty(struct list_entry *head)
Definition: list.h:58
static void list_add_tail(struct list_entry *head, struct list_entry *entry)
Definition: list.h:83
static void list_add_head(struct list_entry *head, struct list_entry *entry)
Definition: list.h:76
static void list_init(struct list_entry *head)
Definition: list.h:51
#define FIXME(fmt,...)
Definition: precomp.h:53
#define ERR(fmt,...)
Definition: precomp.h:57
cd_progress_ptr progress
Definition: cdjpeg.h:152
Definition: list.h:39
static void xor(unsigned char *dst, const unsigned char *a, const unsigned char *b, const int count)
Definition: crypt_des.c:251
BYTE usage_idx
unsigned int component_count
void write_sm1_uniforms(struct hlsl_ctx *ctx, struct vkd3d_bytecode_buffer *buffer)
Definition: d3dbc.c:1752
bool sm1_register_from_semantic_name(const struct vkd3d_shader_version *version, const char *semantic_name, unsigned int semantic_index, bool output, enum vkd3d_shader_register_type *type, unsigned int *reg)
Definition: d3dbc.c:1401
bool sm1_usage_from_semantic_name(const char *semantic_name, uint32_t semantic_index, enum vkd3d_decl_usage *usage, uint32_t *usage_idx)
Definition: d3dbc.c:1469
int d3dbc_compile(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, const struct vkd3d_shader_code *ctab, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context)
Definition: d3dbc.c:2359
component_type
range
Definition: d3dx9_private.h:58
#define NULL
Definition: types.h:112
UINT32 uint32_t
Definition: types.h:75
UINT64 uint64_t
Definition: types.h:77
UINT op
Definition: effect.c:235
static BOOL is_vertex_shader(DWORD version)
Definition: shader.c:748
unsigned int idx
Definition: utils.c:40
#define Z(I)
#define Y(I)
static WCHAR available[MAX_STRING_RESOURCE_LEN]
Definition: object.c:2402
#define TRACE_ON(x)
Definition: compat.h:75
static const WCHAR version[]
Definition: asmname.c:66
unsigned int uintptr_t
Definition: corecrt.h:185
#define UINT_MAX
Definition: limits.h:27
_ACRTIMP double __cdecl floor(double)
Definition: floor.c:18
_ACRTIMP div_t __cdecl div(int, int)
Definition: math.c:2081
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3324
void sincos(double x, double *s, double *c)
Definition: sincos.c:30
static void list_move_tail(struct list_head *list, struct list_head *head)
Definition: list.h:122
return ret
Definition: mutex.c:147
r parent
Definition: btrfs.c:3010
#define abs(i)
Definition: fconv.c:206
GLuint start
Definition: gl.h:1545
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLint GLint GLsizei width
Definition: gl.h:1546
GLenum func
Definition: glext.h:6028
GLuint res
Definition: glext.h:9613
GLenum src
Definition: glext.h:6340
GLuint GLenum swizzle
Definition: glext.h:9511
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLintptr offset
Definition: glext.h:5920
GLenum condition
Definition: glext.h:9255
GLuint GLuint GLuint GLuint arg1
Definition: glext.h:9513
const GLubyte * c
Definition: glext.h:8905
GLuint sampler
Definition: glext.h:7283
GLuint coords
Definition: glext.h:7368
GLuint index
Definition: glext.h:6031
GLenum GLint GLuint mask
Definition: glext.h:6028
GLuint GLuint GLuint GLuint GLuint GLuint GLuint arg2
Definition: glext.h:9514
GLuint program
Definition: glext.h:6723
GLfloat f
Definition: glext.h:7540
GLenum mode
Definition: glext.h:6217
GLenum const GLfloat * params
Definition: glext.h:5645
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * bits
Definition: glext.h:10929
GLenum GLenum dst
Definition: glext.h:6340
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:5666
GLbitfield flags
Definition: glext.h:7161
const GLint * first
Definition: glext.h:5794
GLuint GLfloat * val
Definition: glext.h:7180
GLuint64EXT * result
Definition: glext.h:11304
GLenum GLenum GLenum input
Definition: glext.h:9031
GLsizeiptr const GLvoid GLenum usage
Definition: glext.h:5919
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble * u
Definition: glfuncs.h:240
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
unsigned int hlsl_type_get_array_element_reg_size(const struct hlsl_type *type, enum hlsl_regset regset)
Definition: hlsl.c:444
struct hlsl_ir_var * hlsl_get_var(struct hlsl_scope *scope, const char *name)
Definition: hlsl.c:123
bool hlsl_clone_block(struct hlsl_ctx *ctx, struct hlsl_block *dst_block, const struct hlsl_block *src_block)
Definition: hlsl.c:2544
struct vkd3d_string_buffer * hlsl_type_to_string(struct hlsl_ctx *ctx, const struct hlsl_type *type)
Definition: hlsl.c:2696
void hlsl_dump_function(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *func)
Definition: hlsl.c:3573
bool hlsl_types_are_equal(const struct hlsl_type *t1, const struct hlsl_type *t2)
Definition: hlsl.c:1095
struct hlsl_ir_node * hlsl_new_float_constant(struct hlsl_ctx *ctx, float f, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1545
bool hlsl_copy_deref(struct hlsl_ctx *ctx, struct hlsl_deref *deref, const struct hlsl_deref *other)
Definition: hlsl.c:1388
unsigned int hlsl_type_get_sm4_offset(const struct hlsl_type *type, unsigned int offset)
Definition: hlsl.c:332
bool hlsl_type_is_resource(const struct hlsl_type *type)
Definition: hlsl.c:240
void hlsl_block_cleanup(struct hlsl_block *block)
Definition: hlsl.c:3675
const char * hlsl_jump_type_to_string(enum hlsl_ir_jump_type type)
Definition: hlsl.c:2979
struct hlsl_ir_var * hlsl_new_synthetic_var(struct hlsl_ctx *ctx, const char *template, struct hlsl_type *type, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1349
struct hlsl_ir_node * hlsl_new_constant(struct hlsl_ctx *ctx, struct hlsl_type *type, const struct hlsl_constant_value *value, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1521
void hlsl_fixme(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc, const char *fmt,...)
Definition: hlsl.c:58
unsigned int hlsl_type_component_count(const struct hlsl_type *type)
Definition: hlsl.c:1042
bool hlsl_type_is_row_major(const struct hlsl_type *type)
Definition: hlsl.c:186
struct hlsl_ir_var * hlsl_new_synthetic_var_named(struct hlsl_ctx *ctx, const char *name, struct hlsl_type *type, const struct vkd3d_shader_location *loc, bool dummy_scope)
Definition: hlsl.c:1363
void hlsl_note(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc, enum vkd3d_shader_log_level level, const char *fmt,...)
Definition: hlsl.c:25
void hlsl_free_ir_switch_case(struct hlsl_ir_switch_case *c)
Definition: hlsl.c:2429
void hlsl_init_simple_deref_from_var(struct hlsl_deref *deref, struct hlsl_ir_var *var)
Definition: hlsl.c:1424
bool hlsl_index_is_noncontiguous(struct hlsl_ir_index *index)
Definition: hlsl.c:1999
struct hlsl_ir_node * hlsl_new_store_index(struct hlsl_ctx *ctx, const struct hlsl_deref *lhs, struct hlsl_ir_node *idx, struct hlsl_ir_node *rhs, unsigned int writemask, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1448
bool hlsl_clone_semantic(struct hlsl_ctx *ctx, struct hlsl_semantic *dst, const struct hlsl_semantic *src)
Definition: hlsl.c:3903
struct hlsl_ir_node * hlsl_new_cast(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_type *type, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1294
bool hlsl_index_is_resource_access(struct hlsl_ir_index *index)
Definition: hlsl.c:2006
const char * debug_hlsl_type(struct hlsl_ctx *ctx, const struct hlsl_type *type)
Definition: hlsl.c:2889
bool hlsl_new_store_component(struct hlsl_ctx *ctx, struct hlsl_block *block, const struct hlsl_deref *lhs, unsigned int comp, struct hlsl_ir_node *rhs)
Definition: hlsl.c:1480
uint32_t hlsl_map_swizzle(uint32_t swizzle, unsigned int writemask)
Definition: hlsl.c:3978
struct hlsl_ir_node * hlsl_new_swizzle(struct hlsl_ctx *ctx, uint32_t s, unsigned int components, struct hlsl_ir_node *val, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1847
const char * debug_hlsl_swizzle(uint32_t swizzle, unsigned int size)
Definition: hlsl.c:3093
struct hlsl_ir_node * hlsl_new_unary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1611
void hlsl_cleanup_deref(struct hlsl_deref *deref)
Definition: hlsl.c:1408
void hlsl_cleanup_semantic(struct hlsl_semantic *semantic)
Definition: hlsl.c:3896
struct hlsl_ir_load * hlsl_new_var_load(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1757
void hlsl_error(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc, enum vkd3d_shader_error error, const char *fmt,...)
Definition: hlsl.c:35
void hlsl_warning(struct hlsl_ctx *ctx, const struct vkd3d_shader_location *loc, enum vkd3d_shader_error error, const char *fmt,...)
Definition: hlsl.c:48
unsigned int hlsl_type_element_count(const struct hlsl_type *type)
Definition: hlsl.c:209
uint32_t hlsl_swizzle_from_writemask(unsigned int writemask)
Definition: hlsl.c:4001
struct hlsl_ir_node * hlsl_new_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *operands[HLSL_MAX_OPERANDS], struct hlsl_type *data_type, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1595
uint32_t hlsl_combine_swizzles(uint32_t first, uint32_t second, unsigned int dim)
Definition: hlsl.c:4042
const struct hlsl_type * hlsl_get_multiarray_element_type(const struct hlsl_type *type)
Definition: hlsl.c:226
struct hlsl_ir_node * hlsl_new_ternary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2, struct hlsl_ir_node *arg3)
Definition: hlsl.c:1627
struct hlsl_ir_node * hlsl_new_uint_constant(struct hlsl_ctx *ctx, unsigned int n, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1562
struct hlsl_type * hlsl_get_element_type_from_path_index(struct hlsl_ctx *ctx, const struct hlsl_type *type, struct hlsl_ir_node *idx)
Definition: hlsl.c:848
struct hlsl_type * hlsl_deref_get_type(struct hlsl_ctx *ctx, const struct hlsl_deref *deref)
Definition: hlsl.c:783
void hlsl_replace_node(struct hlsl_ir_node *old, struct hlsl_ir_node *new)
Definition: hlsl.c:3626
const char * debug_hlsl_writemask(unsigned int writemask)
Definition: hlsl.c:3074
unsigned int hlsl_type_major_size(const struct hlsl_type *type)
Definition: hlsl.c:201
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)
Definition: hlsl.c:1794
const char * hlsl_node_type_to_string(enum hlsl_ir_node_type type)
Definition: hlsl.c:2949
unsigned int hlsl_combine_writemasks(unsigned int first, unsigned int second)
Definition: hlsl.c:4026
struct hlsl_type * hlsl_new_texture_type(struct hlsl_ctx *ctx, enum hlsl_sampler_dim dim, struct hlsl_type *format, unsigned int sample_count)
Definition: hlsl.c:920
struct hlsl_type * hlsl_new_array_type(struct hlsl_ctx *ctx, struct hlsl_type *basic_type, unsigned int array_size)
Definition: hlsl.c:880
struct hlsl_ir_node * hlsl_new_binary_expr(struct hlsl_ctx *ctx, enum hlsl_ir_expr_op op, struct hlsl_ir_node *arg1, struct hlsl_ir_node *arg2)
Definition: hlsl.c:1619
struct hlsl_ir_switch_case * hlsl_new_switch_case(struct hlsl_ctx *ctx, unsigned int value, bool is_default, struct hlsl_block *body, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1664
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)
Definition: hlsl.c:1714
char * hlsl_sprintf_alloc(struct hlsl_ctx *ctx, const char *fmt,...)
Definition: hlsl.c:75
struct hlsl_ir_node * hlsl_new_call(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *decl, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1508
unsigned int hlsl_type_minor_size(const struct hlsl_type *type)
Definition: hlsl.c:193
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, uint32_t modifiers, const struct hlsl_reg_reservation *reg_reservation)
Definition: hlsl.c:1311
const char * debug_hlsl_expr_op(enum hlsl_ir_expr_op op)
Definition: hlsl.c:3176
struct hlsl_ir_node * hlsl_new_vsir_instruction_ref(struct hlsl_ctx *ctx, unsigned int vsir_instr_idx, struct hlsl_type *type, const struct hlsl_reg *reg, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1698
enum hlsl_regset hlsl_deref_get_regset(struct hlsl_ctx *ctx, const struct hlsl_deref *deref)
Definition: hlsl.c:327
struct hlsl_ir_function * hlsl_get_function(struct hlsl_ctx *ctx, const char *name)
Definition: hlsl.c:1019
struct hlsl_ir_node * hlsl_new_jump(struct hlsl_ctx *ctx, enum hlsl_ir_jump_type type, struct hlsl_ir_node *condition, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:2044
void hlsl_free_instr(struct hlsl_ir_node *node)
Definition: hlsl.c:3805
struct hlsl_ir_function_decl * hlsl_compile_internal_function(struct hlsl_ctx *ctx, const char *name, const char *hlsl)
Definition: hlsl.c:4642
struct hlsl_ir_node * hlsl_new_if(struct hlsl_ctx *ctx, struct hlsl_ir_node *condition, struct hlsl_block *then_block, struct hlsl_block *else_block, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1647
struct hlsl_ir_node * hlsl_new_bool_constant(struct hlsl_ctx *ctx, bool b, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1537
struct hlsl_ir_node * hlsl_new_simple_store(struct hlsl_ctx *ctx, struct hlsl_ir_var *lhs, struct hlsl_ir_node *rhs)
Definition: hlsl.c:1440
struct hlsl_ir_load * hlsl_new_load_parent(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, const struct vkd3d_shader_location *loc)
Definition: hlsl.c:1744
#define HLSL_STORAGE_CENTROID
Definition: hlsl.h:411
static void hlsl_src_from_node(struct hlsl_src *src, struct hlsl_ir_node *node)
Definition: hlsl.h:1286
static bool hlsl_array_reserve(struct hlsl_ctx *ctx, void **elements, size_t *capacity, size_t element_count, size_t element_size)
Definition: hlsl.h:1336
hlsl_type_class
Definition: hlsl.h:82
@ HLSL_CLASS_COMPUTE_SHADER
Definition: hlsl.h:102
@ HLSL_CLASS_RASTERIZER_STATE
Definition: hlsl.h:94
@ HLSL_CLASS_RENDER_TARGET_VIEW
Definition: hlsl.h:95
@ HLSL_CLASS_VERTEX_SHADER
Definition: hlsl.h:101
@ HLSL_CLASS_MATRIX
Definition: hlsl.h:85
@ HLSL_CLASS_GEOMETRY_SHADER
Definition: hlsl.h:105
@ HLSL_CLASS_TECHNIQUE
Definition: hlsl.h:98
@ HLSL_CLASS_SAMPLER
Definition: hlsl.h:96
@ HLSL_CLASS_UAV
Definition: hlsl.h:100
@ HLSL_CLASS_VECTOR
Definition: hlsl.h:84
@ HLSL_CLASS_TEXTURE
Definition: hlsl.h:99
@ HLSL_CLASS_DEPTH_STENCIL_VIEW
Definition: hlsl.h:90
@ HLSL_CLASS_STRUCT
Definition: hlsl.h:87
@ HLSL_CLASS_LAST_NUMERIC
Definition: hlsl.h:86
@ HLSL_CLASS_CONSTANT_BUFFER
Definition: hlsl.h:106
@ HLSL_CLASS_VOID
Definition: hlsl.h:108
@ HLSL_CLASS_SCALAR
Definition: hlsl.h:83
@ HLSL_CLASS_EFFECT_GROUP
Definition: hlsl.h:91
@ HLSL_CLASS_PIXEL_SHADER
Definition: hlsl.h:93
@ HLSL_CLASS_BLEND_STATE
Definition: hlsl.h:107
@ HLSL_CLASS_STRING
Definition: hlsl.h:97
@ HLSL_CLASS_HULL_SHADER
Definition: hlsl.h:104
@ HLSL_CLASS_DOMAIN_SHADER
Definition: hlsl.h:103
@ HLSL_CLASS_NULL
Definition: hlsl.h:109
@ HLSL_CLASS_ARRAY
Definition: hlsl.h:88
@ HLSL_CLASS_DEPTH_STENCIL_STATE
Definition: hlsl.h:89
@ HLSL_CLASS_PASS
Definition: hlsl.h:92
@ HLSL_CLASS_ERROR
Definition: hlsl.h:110
@ HLSL_IR_LOOP_UNROLL
Definition: hlsl.h:649
@ HLSL_IR_LOOP_FORCE_UNROLL
Definition: hlsl.h:650
@ HLSL_IR_LOOP_FORCE_LOOP
Definition: hlsl.h:651
static struct hlsl_type * hlsl_get_vector_type(const struct hlsl_ctx *ctx, enum hlsl_base_type base_type, unsigned int dimx)
Definition: hlsl.h:1365
#define HLSL_STORAGE_UNIFORM
Definition: hlsl.h:403
hlsl_regset
Definition: hlsl.h:146
@ HLSL_REGSET_NUMERIC
Definition: hlsl.h:151
@ HLSL_REGSET_UAVS
Definition: hlsl.h:149
@ HLSL_REGSET_TEXTURES
Definition: hlsl.h:148
@ HLSL_REGSET_SAMPLERS
Definition: hlsl.h:147
@ HLSL_REGSET_LAST_OBJECT
Definition: hlsl.h:150
static void hlsl_block_init(struct hlsl_block *block)
Definition: hlsl.h:1268
@ HLSL_BUFFER_CONSTANT
Definition: hlsl.h:985
@ HLSL_IR_LOOP
Definition: hlsl.h:321
@ HLSL_IR_SWIZZLE
Definition: hlsl.h:327
@ HLSL_IR_IF
Definition: hlsl.h:318
@ HLSL_IR_STATEBLOCK_CONSTANT
Definition: hlsl.h:332
@ HLSL_IR_INDEX
Definition: hlsl.h:319
@ HLSL_IR_CALL
Definition: hlsl.h:315
@ HLSL_IR_LOAD
Definition: hlsl.h:320
@ HLSL_IR_CONSTANT
Definition: hlsl.h:316
@ HLSL_IR_VSIR_INSTRUCTION_REF
Definition: hlsl.h:334
@ HLSL_IR_COMPILE
Definition: hlsl.h:330
@ HLSL_IR_RESOURCE_LOAD
Definition: hlsl.h:323
@ HLSL_IR_SAMPLER_STATE
Definition: hlsl.h:331
@ HLSL_IR_SWITCH
Definition: hlsl.h:328
@ HLSL_IR_RESOURCE_STORE
Definition: hlsl.h:324
@ HLSL_IR_STORE
Definition: hlsl.h:326
@ HLSL_IR_EXPR
Definition: hlsl.h:317
@ HLSL_IR_JUMP
Definition: hlsl.h:322
@ HLSL_IR_STRING_CONSTANT
Definition: hlsl.h:325
static unsigned int hlsl_sampler_dim_count(enum hlsl_sampler_dim dim)
Definition: hlsl.h:1393
hlsl_base_type
Definition: hlsl.h:114
@ HLSL_TYPE_HALF
Definition: hlsl.h:116
@ HLSL_TYPE_BOOL
Definition: hlsl.h:120
@ HLSL_TYPE_UINT
Definition: hlsl.h:119
@ HLSL_TYPE_INT
Definition: hlsl.h:118
@ HLSL_TYPE_FLOAT
Definition: hlsl.h:115
@ HLSL_TYPE_DOUBLE
Definition: hlsl.h:117
static struct vkd3d_string_buffer * hlsl_get_string_buffer(struct hlsl_ctx *ctx)
Definition: hlsl.h:1346
#define HLSL_SWIZZLE(x, y, z, w)
Definition: hlsl.h:59
static struct hlsl_type * hlsl_get_scalar_type(const struct hlsl_ctx *ctx, enum hlsl_base_type base_type)
Definition: hlsl.h:1360
#define HLSL_STORAGE_OUT
Definition: hlsl.h:409
#define HLSL_SWIZZLE_SHIFT(idx)
Definition: hlsl.h:66
static struct hlsl_type * hlsl_get_numeric_type(const struct hlsl_ctx *ctx, enum hlsl_type_class type, enum hlsl_base_type base_type, unsigned int dimx, unsigned int dimy)
Definition: hlsl.h:1377
static void hlsl_block_add_instr(struct hlsl_block *block, struct hlsl_ir_node *instr)
Definition: hlsl.h:1274
bool hlsl_fold_constant_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static bool hlsl_var_has_buffer_offset_register_reservation(struct hlsl_ctx *ctx, const struct hlsl_ir_var *var)
Definition: hlsl.h:1418
@ HLSL_RESOURCE_SAMPLE
Definition: hlsl.h:836
@ HLSL_RESOURCE_GATHER_BLUE
Definition: hlsl.h:845
@ HLSL_RESOURCE_SAMPLE_GRAD
Definition: hlsl.h:841
@ HLSL_RESOURCE_SAMPLE_CMP
Definition: hlsl.h:837
@ HLSL_RESOURCE_SAMPLE_CMP_LZ
Definition: hlsl.h:838
@ HLSL_RESOURCE_RESINFO
Definition: hlsl.h:848
@ HLSL_RESOURCE_SAMPLE_LOD_BIAS
Definition: hlsl.h:840
@ HLSL_RESOURCE_SAMPLE_PROJ
Definition: hlsl.h:842
@ HLSL_RESOURCE_SAMPLE_INFO
Definition: hlsl.h:847
@ HLSL_RESOURCE_GATHER_GREEN
Definition: hlsl.h:844
@ HLSL_RESOURCE_GATHER_RED
Definition: hlsl.h:843
@ HLSL_RESOURCE_SAMPLE_LOD
Definition: hlsl.h:839
@ HLSL_RESOURCE_LOAD
Definition: hlsl.h:835
@ HLSL_RESOURCE_GATHER_ALPHA
Definition: hlsl.h:846
int tpf_compile(struct vsir_program *program, uint64_t config_flags, struct vkd3d_shader_code *out, struct vkd3d_shader_message_context *message_context, struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
Definition: tpf.c:6046
static void * hlsl_alloc(struct hlsl_ctx *ctx, size_t size)
Definition: hlsl.h:1300
static bool hlsl_is_numeric_type(const struct hlsl_type *type)
Definition: hlsl.h:1388
static void hlsl_block_add_block(struct hlsl_block *block, struct hlsl_block *add)
Definition: hlsl.h:1280
static bool hlsl_version_ge(const struct hlsl_ctx *ctx, unsigned int major, unsigned int minor)
Definition: hlsl.h:1141
bool hlsl_fold_constant_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
#define HLSL_STORAGE_LINEAR
Definition: hlsl.h:413
struct hlsl_ir_node * hlsl_add_load_component(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_node *var_instr, unsigned int comp, const struct vkd3d_shader_location *loc)
hlsl_sampler_dim
Definition: hlsl.h:125
@ HLSL_SAMPLER_DIM_GENERIC
Definition: hlsl.h:126
@ HLSL_SAMPLER_DIM_CUBE
Definition: hlsl.h:131
@ HLSL_SAMPLER_DIM_3D
Definition: hlsl.h:130
@ HLSL_SAMPLER_DIM_2D
Definition: hlsl.h:129
static bool hlsl_deref_is_lowered(const struct hlsl_deref *deref)
Definition: hlsl.h:822
static void hlsl_src_remove(struct hlsl_src *src)
Definition: hlsl.h:1293
#define HLSL_MAX_OPERANDS
Definition: hlsl.h:750
#define HLSL_STORAGE_IN
Definition: hlsl.h:408
static bool hlsl_version_lt(const struct hlsl_ctx *ctx, unsigned int major, unsigned int minor)
Definition: hlsl.h:1146
hlsl_ir_expr_op
Definition: hlsl.h:681
@ HLSL_OP2_LESS
Definition: hlsl.h:727
@ HLSL_OP1_DSY
Definition: hlsl.h:695
@ HLSL_OP2_LOGIC_AND
Definition: hlsl.h:728
@ HLSL_OP2_LOGIC_OR
Definition: hlsl.h:729
@ HLSL_OP1_NEG
Definition: hlsl.h:705
@ HLSL_OP1_F32TOF16
Definition: hlsl.h:700
@ HLSL_OP2_DIV
Definition: hlsl.h:723
@ HLSL_OP1_DSY_COARSE
Definition: hlsl.h:696
@ HLSL_OP1_DSY_FINE
Definition: hlsl.h:697
@ HLSL_OP2_LSHIFT
Definition: hlsl.h:730
@ HLSL_OP2_ADD
Definition: hlsl.h:718
@ HLSL_OP1_SAT
Definition: hlsl.h:711
@ HLSL_OP1_F16TOF32
Definition: hlsl.h:699
@ HLSL_OP2_NEQUAL
Definition: hlsl.h:735
@ HLSL_OP1_DSX_FINE
Definition: hlsl.h:694
@ HLSL_OP1_COS_REDUCED
Definition: hlsl.h:691
@ HLSL_OP2_MIN
Definition: hlsl.h:732
@ HLSL_OP1_BIT_NOT
Definition: hlsl.h:687
@ HLSL_OP1_ABS
Definition: hlsl.h:686
@ HLSL_OP1_CEIL
Definition: hlsl.h:689
@ HLSL_OP2_MAX
Definition: hlsl.h:731
@ HLSL_OP1_TRUNC
Definition: hlsl.h:716
@ HLSL_OP1_FRACT
Definition: hlsl.h:702
@ HLSL_OP2_BIT_XOR
Definition: hlsl.h:721
@ HLSL_OP0_RASTERIZER_SAMPLE_COUNT
Definition: hlsl.h:684
@ HLSL_OP2_BIT_AND
Definition: hlsl.h:719
@ HLSL_OP2_MOD
Definition: hlsl.h:733
@ HLSL_OP3_MAD
Definition: hlsl.h:747
@ HLSL_OP2_RSHIFT
Definition: hlsl.h:736
@ HLSL_OP1_FLOOR
Definition: hlsl.h:701
@ HLSL_OP1_COS
Definition: hlsl.h:690
@ HLSL_OP2_MUL
Definition: hlsl.h:734
@ HLSL_OP2_GEQUAL
Definition: hlsl.h:726
@ HLSL_OP2_SLT
Definition: hlsl.h:738
@ HLSL_OP2_EQUAL
Definition: hlsl.h:725
@ HLSL_OP1_ROUND
Definition: hlsl.h:709
@ HLSL_OP1_RCP
Definition: hlsl.h:707
@ HLSL_OP1_DSX
Definition: hlsl.h:692
@ HLSL_OP3_TERNARY
Definition: hlsl.h:746
@ HLSL_OP1_LOG2
Definition: hlsl.h:703
@ HLSL_OP1_EXP2
Definition: hlsl.h:698
@ HLSL_OP3_DP2ADD
Definition: hlsl.h:742
@ HLSL_OP3_CMP
Definition: hlsl.h:745
@ HLSL_OP1_LOGIC_NOT
Definition: hlsl.h:704
@ HLSL_OP1_RSQ
Definition: hlsl.h:710
@ HLSL_OP1_DSX_COARSE
Definition: hlsl.h:693
@ HLSL_OP1_SQRT
Definition: hlsl.h:715
@ HLSL_OP2_DOT
Definition: hlsl.h:724
@ HLSL_OP1_SIN
Definition: hlsl.h:713
@ HLSL_OP2_BIT_OR
Definition: hlsl.h:720
@ HLSL_OP1_CAST
Definition: hlsl.h:688
@ HLSL_OP1_SIN_REDUCED
Definition: hlsl.h:714
@ HLSL_OP1_REINTERPRET
Definition: hlsl.h:708
static uint32_t vsir_swizzle_from_hlsl(uint32_t swizzle)
Definition: hlsl.h:73
static unsigned int hlsl_swizzle_get_component(uint32_t swizzle, unsigned int idx)
Definition: hlsl.h:68
hlsl_ir_jump_type
Definition: hlsl.h:760
@ HLSL_IR_JUMP_DISCARD_NZ
Definition: hlsl.h:764
@ HLSL_IR_JUMP_RETURN
Definition: hlsl.h:765
@ HLSL_IR_JUMP_CONTINUE
Definition: hlsl.h:762
@ HLSL_IR_JUMP_DISCARD_NEG
Definition: hlsl.h:763
@ HLSL_IR_JUMP_BREAK
Definition: hlsl.h:761
static void hlsl_release_string_buffer(struct hlsl_ctx *ctx, struct vkd3d_string_buffer *buffer)
Definition: hlsl.h:1355
#define HLSL_STORAGE_NOINTERPOLATION
Definition: hlsl.h:398
bool hlsl_fold_constant_identities(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
#define HLSL_STORAGE_NOPERSPECTIVE
Definition: hlsl.h:412
static bool remove_trivial_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static bool lower_narrowing_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static void transform_unroll_loops(struct hlsl_ctx *ctx, struct hlsl_block *block)
static enum vkd3d_data_type vsir_data_type_from_hlsl_instruction(struct hlsl_ctx *ctx, const struct hlsl_ir_node *instr)
static void generate_vsir_signature_entry(struct hlsl_ctx *ctx, struct vsir_program *program, struct shader_signature *signature, bool output, bool is_patch_constant_func, struct hlsl_ir_var *var)
static void allocate_const_registers_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, struct register_allocator *allocator)
static void allocate_objects(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, enum hlsl_regset regset)
static void parse_partitioning_attribute(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr)
static void sm1_generate_vsir_instr_if(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_if *iff)
static bool lower_int_division(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static void sm1_generate_vsir_instr_expr_per_component_instr_op(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_expr *expr, enum vkd3d_shader_opcode opcode)
static void sm4_generate_vsir_instr_dcl_semantic(struct hlsl_ctx *ctx, struct vsir_program *program, const struct hlsl_ir_var *var, bool is_patch_constant_func, struct hlsl_block *block, const struct vkd3d_shader_location *loc)
static void calculate_resource_register_counts(struct hlsl_ctx *ctx)
void hlsl_lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_block *body)
static bool validate_dereferences(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static bool copy_propagation_transform_load(struct hlsl_ctx *ctx, struct hlsl_ir_load *load, struct copy_propagation_state *state)
static bool dce(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static bool copy_propagation_replace_with_constant_vector(struct hlsl_ctx *ctx, const struct copy_propagation_state *state, const struct hlsl_ir_load *load, uint32_t swizzle, struct hlsl_ir_node *instr)
static void prepend_uniform_copy(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_ir_var *temp)
Definition: hlsl_codegen.c:204
static struct copy_propagation_value * copy_propagation_get_value_at_time(struct copy_propagation_component_trace *trace, unsigned int time)
static void record_allocation(struct hlsl_ctx *ctx, struct register_allocator *allocator, uint32_t reg_idx, unsigned int writemask, unsigned int first_write, unsigned int last_read, int mode)
static void vsir_src_from_hlsl_node(struct vkd3d_shader_src_param *src, struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, uint32_t map_writemask)
static void process_entry_function(struct hlsl_ctx *ctx, const struct hlsl_block *global_uniform_block, struct hlsl_ir_function_decl *entry_func)
static void dump_function(struct rb_entry *entry, void *context)
bool hlsl_component_index_range_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, unsigned int *start, unsigned int *count)
static struct hlsl_reg allocate_numeric_registers_for_type(struct hlsl_ctx *ctx, struct register_allocator *allocator, unsigned int first_write, unsigned int last_read, const struct hlsl_type *type)
static bool track_object_components_sampler_dim(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static bool find_recursive_calls(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
Definition: hlsl_codegen.c:753
static unsigned int get_available_writemask(const struct register_allocator *allocator, unsigned int first_write, unsigned int last_read, uint32_t reg_idx, int mode)
static void mark_vars_usage(struct hlsl_ctx *ctx)
static void note_non_static_deref_expressions(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, const char *usage)
static bool copy_propagation_process_if(struct hlsl_ctx *ctx, struct hlsl_ir_if *iff, struct copy_propagation_state *state)
static bool transform_instr_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
Definition: hlsl_codegen.c:709
static uint32_t combine_field_storage_modifiers(uint32_t modifiers, uint32_t field_modifiers)
Definition: hlsl_codegen.c:348
static const struct hlsl_buffer * get_reserved_buffer(struct hlsl_ctx *ctx, uint32_t space, uint32_t index, bool allocated_only)
static bool lower_ternary(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static void copy_propagation_invalidate_variable_from_deref(struct hlsl_ctx *ctx, struct copy_propagation_var_def *var_def, const struct hlsl_deref *deref, unsigned char writemask, unsigned int time)
static void allocate_instr_temp_register(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct register_allocator *allocator)
static struct hlsl_ir_node * add_zero_mipmap_level(struct hlsl_ctx *ctx, struct hlsl_ir_node *index, const struct vkd3d_shader_location *loc)
static void sm1_generate_vsir_instr_load(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_load *load)
static enum hlsl_base_type base_type_get_semantic_equivalent(enum hlsl_base_type base)
Definition: hlsl_codegen.c:255
static const char * debug_register(char class, struct hlsl_reg reg, const struct hlsl_type *type)
static void sort_uniforms_by_numeric_bind_count(struct hlsl_ctx *ctx)
static bool copy_propagation_process_loop(struct hlsl_ctx *ctx, struct hlsl_ir_loop *loop, struct copy_propagation_state *state)
static void sm1_generate_vsir_instr_resource_load(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_resource_load *load)
static bool lower_nonfloat_exprs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static bool lower_nonconstant_array_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static void allocate_temp_registers_recurse(struct hlsl_ctx *ctx, struct hlsl_block *block, struct register_allocator *allocator)
static void sm1_generate_vsir_constant_defs(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_block *block)
static char get_regset_name(enum hlsl_regset regset)
static struct hlsl_reg allocate_register(struct hlsl_ctx *ctx, struct register_allocator *allocator, unsigned int first_write, unsigned int last_read, unsigned int reg_size, unsigned int component_count, int mode, bool force_align)
static bool sm1_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_expr *expr)
static bool lower_calls(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static void allocate_semantic_register(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct register_allocator *allocator, bool output, bool optimize, bool is_patch_constant_func)
static void validate_hull_shader_attributes(struct hlsl_ctx *ctx, const struct hlsl_ir_function_decl *entry_func)
static bool transform_derefs(struct hlsl_ctx *ctx, bool(*func)(struct hlsl_ctx *ctx, struct hlsl_deref *, struct hlsl_ir_node *), struct hlsl_block *block)
Definition: hlsl_codegen.c:740
static void generate_vsir_signature(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_function_decl *func)
static enum vkd3d_data_type vsir_data_type_from_hlsl_type(struct hlsl_ctx *ctx, const struct hlsl_type *type)
static void copy_propagation_state_destroy(struct copy_propagation_state *state)
static void sm1_generate_vsir_instr_constant(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_constant *constant)
static struct hlsl_ir_jump * loop_unrolling_find_jump(struct hlsl_block *block, struct hlsl_ir_node *stop_point, struct hlsl_block **found_block)
static void copy_propagation_invalidate_variable(struct hlsl_ctx *ctx, struct copy_propagation_var_def *var_def, unsigned int comp, unsigned char writemask, unsigned int time)
static void validate_field_semantic(struct hlsl_ctx *ctx, struct hlsl_struct_field *field)
Definition: hlsl_codegen.c:244
static void copy_propagation_trace_record_value(struct hlsl_ctx *ctx, struct copy_propagation_component_trace *trace, struct hlsl_ir_node *node, unsigned int component, unsigned int time)
bool hlsl_regset_index_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, enum hlsl_regset regset, unsigned int *index)
static bool fold_swizzle_chains(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static void sm4_generate_vsir_add_function(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, uint64_t config_flags, struct vsir_program *program)
static bool lower_f16tof32(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block)
static void compute_liveness(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
static bool copy_propagation_transform_swizzle(struct hlsl_ctx *ctx, struct hlsl_ir_swizzle *swizzle, struct copy_propagation_state *state)
static void sm4_generate_vsir_instr_dcl_temps(struct hlsl_ctx *ctx, struct vsir_program *program, uint32_t temp_count, struct hlsl_block *block, const struct vkd3d_shader_location *loc)
static bool lower_slt(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static void validate_buffer_offsets(struct hlsl_ctx *ctx)
static bool lower_abs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
bool hlsl_offset_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref, unsigned int *offset)
static bool clean_constant_deref_offset_srcs(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *instr)
Definition: hlsl_codegen.c:183
static bool loop_unrolling_unroll_loop(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_block *loop_parent, struct hlsl_ir_loop *loop)
static struct hlsl_reg allocate_register_with_masks(struct hlsl_ctx *ctx, struct register_allocator *allocator, unsigned int first_write, unsigned int last_read, uint32_t reg_writemask, uint32_t writemask, int mode)
static bool type_is_integer(const struct hlsl_type *type)
static void copy_propagation_set_value(struct hlsl_ctx *ctx, struct copy_propagation_var_def *var_def, unsigned int comp, unsigned char writemask, struct hlsl_ir_node *instr, unsigned int time)
static bool copy_propagation_process_switch(struct hlsl_ctx *ctx, struct hlsl_ir_switch *s, struct copy_propagation_state *state)
static void vsir_dst_from_hlsl_node(struct vkd3d_shader_dst_param *dst, struct hlsl_ctx *ctx, const struct hlsl_ir_node *instr)
static void copy_propagation_invalidate_from_block(struct hlsl_ctx *ctx, struct copy_propagation_state *state, struct hlsl_block *block, unsigned int time)
static bool lower_casts_to_bool(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static bool lower_cmp(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
void hlsl_calculate_buffer_offsets(struct hlsl_ctx *ctx)
static bool lower_logic_not(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
bool hlsl_copy_propagation_execute(struct hlsl_ctx *ctx, struct hlsl_block *block)
static bool lower_sqrt(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static bool split_copy(struct hlsl_ctx *ctx, struct hlsl_ir_store *store, const struct hlsl_ir_load *load, const unsigned int idx, struct hlsl_type *type)
static void parse_outputcontrolpoints_attribute(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr)
static struct copy_propagation_value * copy_propagation_get_value(const struct copy_propagation_state *state, const struct hlsl_ir_var *var, unsigned int component, unsigned int time)
static bool sm4_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_expr *expr, const char *dst_type_name)
static void allocate_variable_temp_register(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, struct register_allocator *allocator)
static void sm1_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func, uint64_t config_flags, struct vsir_program *program, struct vkd3d_shader_code *ctab)
static bool lower_casts_to_int(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static bool lower_floor(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
enum vkd3d_shader_interpolation_mode sm4_get_interpolation_mode(struct hlsl_type *type, unsigned int storage_modifiers)
static void parse_domain_attribute(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr)
static bool sm1_generate_vsir_instr_expr(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_expr *expr)
static void record_constant(struct hlsl_ctx *ctx, unsigned int component_index, float f, const struct vkd3d_shader_location *loc)
static bool lower_discard_neg(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static void allocate_semantic_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
static void sm4_generate_vsir_rcp_using_div(struct hlsl_ctx *ctx, struct vsir_program *program, const struct hlsl_ir_expr *expr)
static void prepend_input_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_var *var)
Definition: hlsl_codegen.c:496
static void sm4_generate_vsir_instr_dcl_indexable_temp(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_block *block, uint32_t idx, uint32_t size, uint32_t comp_count, const struct vkd3d_shader_location *loc)
static bool lower_trig(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static void sm4_generate_vsir_rasterizer_sample_count(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_expr *expr)
static bool lower_comparison_operators(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static unsigned int loop_unrolling_get_max_iterations(struct hlsl_ctx *ctx, struct hlsl_ir_loop *loop)
static bool track_components_usage(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static void copy_propagation_state_init(struct hlsl_ctx *ctx, struct copy_propagation_state *state, struct copy_propagation_state *parent)
bool hlsl_transform_ir(struct hlsl_ctx *ctx, bool(*func)(struct hlsl_ctx *ctx, struct hlsl_ir_node *, void *), struct hlsl_block *block, void *context)
Definition: hlsl_codegen.c:642
static void sm1_generate_vsir_instr_jump(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_jump *jump)
static void parse_outputtopology_attribute(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr)
static bool split_struct_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static bool lower_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
struct hlsl_reg hlsl_reg_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref)
static bool copy_propagation_transform_resource_store(struct hlsl_ctx *ctx, struct hlsl_ir_resource_store *store, struct copy_propagation_state *state)
static bool copy_propagation_transform_object_load(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct copy_propagation_state *state, unsigned int time)
static bool lower_division(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static void allocate_const_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
static void add_last_vsir_instr_to_block(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_block *block)
static void prepend_input_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_load *lhs, uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align)
Definition: hlsl_codegen.c:365
static void prepend_input_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_load *lhs, uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align)
Definition: hlsl_codegen.c:432
static bool lower_f32tof16(struct hlsl_ctx *ctx, struct hlsl_ir_node *node, struct hlsl_block *block)
static bool is_vec1(const struct hlsl_type *type)
static bool sort_synthetic_separated_samplers_first(struct hlsl_ctx *ctx)
static bool lower_ir(struct hlsl_ctx *ctx, PFN_lower_func func, struct hlsl_block *block)
Definition: hlsl_codegen.c:704
static bool split_matrix_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static void sort_uniform_by_numeric_bind_count(struct list *sorted, struct hlsl_ir_var *to_sort)
static bool copy_propagation_transform_resource_load(struct hlsl_ctx *ctx, struct hlsl_ir_resource_load *load, struct copy_propagation_state *state)
static void sm1_generate_vsir_init_src_param_from_deref(struct hlsl_ctx *ctx, struct vkd3d_shader_src_param *src_param, struct hlsl_deref *deref, unsigned int dst_writemask, const struct vkd3d_shader_location *loc)
static bool lower_int_abs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
validation_result
@ DEREF_VALIDATION_OK
@ DEREF_VALIDATION_OUT_OF_BOUNDS
@ DEREF_VALIDATION_NOT_CONSTANT
static bool validate_nonconstant_vector_store_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static struct hlsl_reg allocate_range(struct hlsl_ctx *ctx, struct register_allocator *allocator, unsigned int first_write, unsigned int last_read, unsigned int reg_size, int mode)
static void sm4_generate_vsir(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, uint64_t config_flags, struct vsir_program *program)
static const struct hlsl_ir_var * get_allocated_object(struct hlsl_ctx *ctx, enum hlsl_regset regset, uint32_t space, uint32_t index, bool allocated_only)
static void sm4_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *block, struct vsir_program *program)
static bool copy_propagation_transform_block(struct hlsl_ctx *ctx, struct hlsl_block *block, struct copy_propagation_state *state)
static uint32_t generate_vsir_get_src_swizzle(uint32_t src_writemask, uint32_t dst_writemask)
static void vsir_src_from_hlsl_constant_value(struct vkd3d_shader_src_param *src, struct hlsl_ctx *ctx, const struct hlsl_constant_value *value, enum vkd3d_data_type type, unsigned int width, unsigned int map_writemask)
static bool lower_index_loads(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static void append_output_var_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_var *var)
Definition: hlsl_codegen.c:630
static void deref_mark_last_read(struct hlsl_deref *deref, unsigned int last_read)
static void mark_indexable_vars(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
static void append_output_copy(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_load *rhs, uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align)
Definition: hlsl_codegen.c:508
static void compute_liveness_recurse(struct hlsl_block *block, unsigned int loop_first, unsigned int loop_last)
static unsigned int index_instructions(struct hlsl_block *block, unsigned int index)
static const char * get_string_argument_value(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr, unsigned int i)
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)
static void replace_instr_with_last_vsir_instr(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_node *instr)
static enum validation_result validate_component_index_range_from_deref(struct hlsl_ctx *ctx, const struct hlsl_deref *deref)
static bool lower_broadcasts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static bool lower_float_modulus(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static bool lower_nonconstant_vector_derefs(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static bool type_is_float(const struct hlsl_type *type)
static void append_output_copy_recurse(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_load *rhs, uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t semantic_index, bool force_align)
Definition: hlsl_codegen.c:569
static void init_var_liveness(struct hlsl_ir_var *var)
static void sm1_generate_vsir_init_dst_param_from_deref(struct hlsl_ctx *ctx, struct vkd3d_shader_dst_param *dst_param, struct hlsl_deref *deref, const struct vkd3d_shader_location *loc, unsigned int writemask)
static void allocate_buffers(struct hlsl_ctx *ctx)
static unsigned int get_max_cbuffer_reg_index(struct hlsl_ctx *ctx)
static bool lower_matrix_swizzles(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static bool lower_discard_nz(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
unsigned int hlsl_offset_from_deref_safe(struct hlsl_ctx *ctx, const struct hlsl_deref *deref)
static void parse_numthreads_attribute(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr)
static struct hlsl_ir_var * add_semantic_var(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_var *var, struct hlsl_type *type, uint32_t modifiers, struct hlsl_semantic *semantic, uint32_t index, bool output, bool force_align, const struct vkd3d_shader_location *loc)
Definition: hlsl_codegen.c:279
static bool lower_int_modulus(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
bool(* PFN_lower_func)(struct hlsl_ctx *, struct hlsl_ir_node *, struct hlsl_block *)
Definition: hlsl_codegen.c:678
static bool split_array_copies(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static void copy_propagation_invalidate_variable_from_deref_recurse(struct hlsl_ctx *ctx, struct copy_propagation_var_def *var_def, const struct hlsl_deref *deref, struct hlsl_type *type, unsigned int depth, unsigned int comp_start, unsigned char writemask, unsigned int time)
static bool lower_combined_samples(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static bool lower_return(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_block *block, bool in_loop)
Definition: hlsl_codegen.c:812
static struct hlsl_ir_node * new_offset_instr_from_deref(struct hlsl_ctx *ctx, struct hlsl_block *block, const struct hlsl_deref *deref, unsigned int *offset_component, const struct vkd3d_shader_location *loc)
Definition: hlsl_codegen.c:108
static bool lower_ceil(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static bool sm4_generate_vsir_instr_expr_cast(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_expr *expr)
static struct vkd3d_shader_instruction * generate_vsir_add_program_instruction(struct hlsl_ctx *ctx, struct vsir_program *program, const struct vkd3d_shader_location *loc, enum vkd3d_shader_opcode opcode, unsigned int dst_count, unsigned int src_count)
static void parse_entry_function_attributes(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
static bool copy_propagation_replace_with_single_instr(struct hlsl_ctx *ctx, const struct copy_propagation_state *state, const struct hlsl_ir_load *load, uint32_t swizzle, struct hlsl_ir_node *instr)
static bool mark_indexable_var(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *instr)
static bool lower_round(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static int copy_propagation_var_def_compare(const void *key, const struct rb_entry *entry)
struct hlsl_ir_node * hlsl_add_conditional(struct hlsl_ctx *ctx, struct hlsl_block *instrs, struct hlsl_ir_node *condition, struct hlsl_ir_node *if_true, struct hlsl_ir_node *if_false)
static void register_deref_usage(struct hlsl_ctx *ctx, struct hlsl_deref *deref)
static void sm1_generate_vsir_sampler_dcls(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_block *block)
static void insert_ensuring_decreasing_bind_count(struct list *list, struct hlsl_ir_var *to_add, enum hlsl_regset regset)
static struct hlsl_ir_node * new_offset_from_path_index(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_type *type, struct hlsl_ir_node *base_offset, struct hlsl_ir_node *idx, enum hlsl_regset regset, unsigned int *offset_component, const struct vkd3d_shader_location *loc)
Definition: hlsl_codegen.c:26
static void parse_patchconstantfunc_attribute(struct hlsl_ctx *ctx, const struct hlsl_attribute *attr)
static bool remove_trivial_conditional_branches(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static struct hlsl_ir_loop * loop_unrolling_find_unrollable_loop(struct hlsl_ctx *ctx, struct hlsl_block *block, struct hlsl_block **containing_block)
static void generate_vsir_instr_swizzle(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_swizzle *swizzle_instr)
static void copy_propagation_record_store(struct hlsl_ctx *ctx, struct hlsl_ir_store *store, struct copy_propagation_state *state)
static void sm4_generate_vsir_cast_from_bool(struct hlsl_ctx *ctx, struct vsir_program *program, const struct hlsl_ir_expr *expr, uint32_t bits)
static bool lower_int_dot(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, struct hlsl_block *block)
static void remove_unreachable_code(struct hlsl_ctx *ctx, struct hlsl_block *body)
static void sm1_generate_vsir_instr_expr_sincos(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_expr *expr)
static void allocate_sincos_const_registers(struct hlsl_ctx *ctx, struct hlsl_block *block, struct register_allocator *allocator)
static void sm4_generate_vsir_expr_with_two_destinations(struct hlsl_ctx *ctx, struct vsir_program *program, enum vkd3d_shader_opcode opcode, const struct hlsl_ir_expr *expr, unsigned int dst_idx)
void hlsl_run_const_passes(struct hlsl_ctx *ctx, struct hlsl_block *body)
static void hlsl_calculate_buffer_offset(struct hlsl_ctx *ctx, struct hlsl_ir_var *var, bool register_reservation)
static void generate_vsir_instr_expr_single_instr_op(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_expr *expr, enum vkd3d_shader_opcode opcode, uint32_t src_mod, uint32_t dst_mod, bool map_src_swizzles)
static void sm1_generate_vsir_block(struct hlsl_ctx *ctx, struct hlsl_block *block, struct vsir_program *program)
static void allocate_register_reservations(struct hlsl_ctx *ctx, struct list *extern_vars)
static bool types_are_semantic_equivalent(struct hlsl_ctx *ctx, const struct hlsl_type *type1, const struct hlsl_type *type2)
Definition: hlsl_codegen.c:266
static struct copy_propagation_var_def * copy_propagation_create_var_def(struct hlsl_ctx *ctx, struct copy_propagation_state *state, struct hlsl_ir_var *var)
static bool call_lower_func(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
Definition: hlsl_codegen.c:680
static bool fold_redundant_casts(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static uint32_t allocate_temp_registers(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *entry_func)
static void copy_propagation_var_def_destroy(struct rb_entry *entry, void *context)
static void insert_early_return_break(struct hlsl_ctx *ctx, struct hlsl_ir_function_decl *func, struct hlsl_ir_node *cf_instr)
Definition: hlsl_codegen.c:789
static bool normalize_switch_cases(struct hlsl_ctx *ctx, struct hlsl_ir_node *instr, void *context)
static bool replace_deref_path_with_offset(struct hlsl_ctx *ctx, struct hlsl_deref *deref, struct hlsl_ir_node *instr)
Definition: hlsl_codegen.c:149
static void sm1_generate_vsir_instr_store(struct hlsl_ctx *ctx, struct vsir_program *program, struct hlsl_ir_store *store)
static int reg
Definition: i386-dis.c:1290
#define bits
Definition: infblock.c:15
bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info, const struct vkd3d_shader_version *version, unsigned int reserve, enum vsir_control_flow_type cf_type, enum vsir_normalisation_level normalisation_level)
Definition: ir.c:76
void vsir_program_cleanup(struct vsir_program *program)
Definition: ir.c:105
void vsir_register_init(struct vkd3d_shader_register *reg, enum vkd3d_shader_register_type reg_type, enum vkd3d_data_type data_type, unsigned int idx_count)
Definition: ir.c:164
bool vsir_instruction_init_with_params(struct vsir_program *program, struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, enum vkd3d_shader_opcode opcode, unsigned int dst_count, unsigned int src_count)
Definition: ir.c:329
void vsir_src_param_init(struct vkd3d_shader_src_param *param, enum vkd3d_shader_register_type reg_type, enum vkd3d_data_type data_type, unsigned int idx_count)
Definition: ir.c:190
void vsir_dst_param_init(struct vkd3d_shader_dst_param *param, enum vkd3d_shader_register_type reg_type, enum vkd3d_data_type data_type, unsigned int idx_count)
Definition: ir.c:272
uint32_t entry
Definition: isohybrid.c:63
static BOOL is_bool(jsval_t v)
Definition: jsval.h:214
#define f
Definition: ke_i.h:83
#define c
Definition: ke_i.h:80
#define debugstr_a
Definition: kernel32.h:31
#define profile
Definition: kernel32.h:12
if(dx< 0)
Definition: linetemp.h:194
#define M_PI
Definition: macros.h:263
__u16 time
Definition: mkdosfs.c:8
char string[160]
Definition: util.h:11
const char * var
Definition: shader.c:5879
D3DXREGISTER_SET regset
Definition: shader.c:5881
static const MAT2 mat
Definition: font.c:51
#define eq(received, expected, label, type)
Definition: locale.c:179
#define cmp(status, error)
Definition: error.c:118
static ULONG ** element_count
Definition: exception.c:124
static const char * target_type(DWORD dwType)
Definition: mixer.c:95
#define min(a, b)
Definition: monoChain.cc:55
const GUID * subtype
Definition: mpegvideo.c:120
int k
Definition: mpi.c:3369
int load
Definition: msacm.c:1365
MV_U8 mul1(MV_U8 aa, MV_U8 bb)
Definition: mvAesAlg.c:27
#define mul(aa, bb)
Definition: mvAesAlg.c:25
#define bool
Definition: nsiface.idl:72
static int sum(int x_, int y_)
Definition: ptr2_test.cpp:35
static unsigned __int64 next
Definition: rand_nt.c:6
static calc_node_t temp
Definition: rpn_ieee.c:38
#define offsetof(TYPE, MEMBER)
#define LIST_FOR_EACH_ENTRY(elem, list, type, field)
Definition: list.h:236
__WINE_SERVER_LIST_INLINE struct list * list_prev(const struct list *list, const struct list *elem)
Definition: list.h:125
#define LIST_FOR_EACH_ENTRY_SAFE(cursor, cursor2, list, type, field)
Definition: list.h:242
__WINE_SERVER_LIST_INLINE void list_move_head(struct list *dst, struct list *src)
Definition: list.h:196
__WINE_SERVER_LIST_INLINE struct list * list_next(const struct list *list, const struct list *elem)
Definition: list.h:117
__WINE_SERVER_LIST_INLINE void list_move_before(struct list *dst, struct list *src)
Definition: list.h:166
#define LIST_FOR_EACH_ENTRY_REV(elem, list, type, field)
Definition: list.h:260
__WINE_SERVER_LIST_INLINE void list_add_before(struct list *elem, struct list *to_add)
Definition: list.h:89
__WINE_SERVER_LIST_INLINE void list_add_after(struct list *elem, struct list *to_add)
Definition: list.h:80
__WINE_SERVER_LIST_INLINE void list_move_slice_tail(struct list *dst, struct list *begin, struct list *end)
Definition: list.h:214
#define LIST_FOR_EACH_ENTRY_SAFE_REV(cursor, cursor2, list, type, field)
Definition: list.h:266
__WINE_SERVER_LIST_INLINE struct list * list_tail(const struct list *list)
Definition: list.h:139
#define RB_ENTRY_VALUE(element, type, field)
Definition: rbtree.h:26
static void rb_destroy(struct rb_tree *tree, rb_traverse_func_t *callback, void *context)
Definition: rbtree.h:185
static void rb_for_each_entry(struct rb_tree *tree, rb_traverse_func_t *callback, void *context)
Definition: rbtree.h:179
static int rb_put(struct rb_tree *tree, const void *key, struct rb_entry *entry)
Definition: rbtree.h:204
static struct rb_entry * rb_get(const struct rb_tree *tree, const void *key)
Definition: rbtree.h:192
static void rb_init(struct rb_tree *tree, rb_compare_func_t compare)
Definition: rbtree.h:173
static const void * body(MD5_CTX *ctx, const void *data, unsigned long size)
Definition: md5.c:100
#define memset(x, y, z)
Definition: compat.h:39
int one
Definition: sehframes.cpp:28
int zero
Definition: sehframes.cpp:29
#define TRACE(s)
Definition: solgame.cpp:4
enum vkd3d_shader_sysval_semantic sysval
Definition: spirv.c:4839
enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval_indexed(enum vkd3d_shader_sysval_semantic sysval, unsigned int index)
Definition: spirv.c:199
struct vkd3d_spirv_builtin builtin
Definition: spirv.c:4840
Definition: polytest.cpp:36
Definition: match.c:390
Definition: cookie.c:202
WCHAR * name
Definition: cookie.c:203
union constant::@270 value[4]
Definition: http.c:7252
struct copy_propagation_value * records
struct copy_propagation_state * parent
struct rb_tree var_defs
struct hlsl_ir_node * node
struct copy_propagation_component_trace traces[]
struct hlsl_ir_var * var
Definition: query.h:86
Definition: parser.c:44
struct list instrs
Definition: hlsl.h:369
struct hlsl_reg_reservation reservation
Definition: hlsl.h:1001
struct vkd3d_shader_location loc
Definition: hlsl.h:994
const char * name
Definition: hlsl.h:996
struct hlsl_type * data_type
Definition: hlsl.h:818
unsigned int path_len
Definition: hlsl.h:805
struct hlsl_src rel_offset
Definition: hlsl.h:816
struct hlsl_src * path
Definition: hlsl.h:806
unsigned int const_offset
Definition: hlsl.h:817
struct hlsl_ir_var * var
Definition: hlsl.h:796
struct hlsl_ir_node node
Definition: hlsl.h:635
struct hlsl_ir_function_decl * decl
Definition: hlsl.h:636
struct hlsl_ir_constant::hlsl_constant_value value
struct hlsl_ir_node node
Definition: hlsl.h:754
struct hlsl_src operands[HLSL_MAX_OPERANDS]
Definition: hlsl.h:756
enum hlsl_ir_expr_op op
Definition: hlsl.h:755
const struct hlsl_attribute *const * attrs
Definition: hlsl.h:617
struct hlsl_func_parameters parameters
Definition: hlsl.h:610
bool early_depth_test
Definition: hlsl.h:619
struct hlsl_ir_function * func
Definition: hlsl.h:608
struct hlsl_ir_var * return_var
Definition: hlsl.h:601
unsigned int attr_count
Definition: hlsl.h:616
struct list extern_vars
Definition: hlsl.h:630
struct vkd3d_shader_location loc
Definition: hlsl.h:603
struct hlsl_block body
Definition: hlsl.h:612
struct hlsl_block then_block
Definition: hlsl.h:643
struct hlsl_src condition
Definition: hlsl.h:642
struct hlsl_ir_node node
Definition: hlsl.h:641
struct hlsl_block else_block
Definition: hlsl.h:644
struct hlsl_ir_node node
Definition: hlsl.h:774
struct hlsl_src condition
Definition: hlsl.h:777
enum hlsl_ir_jump_type type
Definition: hlsl.h:775
struct hlsl_ir_node node
Definition: hlsl.h:829
struct hlsl_deref src
Definition: hlsl.h:830
enum hlsl_ir_loop_unroll_type unroll_type
Definition: hlsl.h:661
unsigned int next_index
Definition: hlsl.h:659
unsigned int unroll_limit
Definition: hlsl.h:660
struct hlsl_ir_node node
Definition: hlsl.h:656
struct hlsl_block body
Definition: hlsl.h:658
unsigned int index
Definition: hlsl.h:361
struct list entry
Definition: hlsl.h:341
enum hlsl_ir_node_type type
Definition: hlsl.h:345
struct hlsl_reg reg
Definition: hlsl.h:363
struct list uses
Definition: hlsl.h:353
struct hlsl_type * data_type
Definition: hlsl.h:349
struct vkd3d_shader_location loc
Definition: hlsl.h:355
unsigned int last_read
Definition: hlsl.h:361
struct hlsl_ir_node node
Definition: hlsl.h:862
struct hlsl_src coords value
Definition: hlsl.h:864
struct hlsl_deref resource
Definition: hlsl.h:863
struct hlsl_src rhs
Definition: hlsl.h:871
struct hlsl_deref lhs
Definition: hlsl.h:870
struct hlsl_ir_node node
Definition: hlsl.h:869
unsigned char writemask
Definition: hlsl.h:872
struct hlsl_block body
Definition: hlsl.h:668
struct vkd3d_shader_location loc
Definition: hlsl.h:670
struct list entry
Definition: hlsl.h:669
struct hlsl_ir_node node
Definition: hlsl.h:782
struct hlsl_src val
Definition: hlsl.h:783
uint32_t swizzle
Definition: hlsl.h:784
unsigned int buffer_offset
Definition: hlsl.h:501
uint32_t is_output_semantic
Definition: hlsl.h:528
const char * name
Definition: hlsl.h:456
struct hlsl_ir_var::hlsl_default_value * default_values
struct hlsl_scope * scope
Definition: hlsl.h:470
struct hlsl_semantic semantic
Definition: hlsl.h:457
unsigned int last_read
Definition: hlsl.h:496
uint32_t is_param
Definition: hlsl.h:530
struct hlsl_reg_reservation reg_reservation
Definition: hlsl.h:463
unsigned int bind_count[HLSL_REGSET_LAST+1]
Definition: hlsl.h:519
struct hlsl_type * data_type
Definition: hlsl.h:454
uint32_t storage_modifiers
Definition: hlsl.h:461
struct vkd3d_shader_location loc
Definition: hlsl.h:455
uint32_t is_uniform
Definition: hlsl.h:529
enum hlsl_sampler_dim sampler_dim
Definition: hlsl.h:513
struct hlsl_buffer * buffer
Definition: hlsl.h:459
struct list scope_entry
Definition: hlsl.h:466
struct list extern_entry
Definition: hlsl.h:468
bool force_align
Definition: hlsl.h:525
uint32_t is_input_semantic
Definition: hlsl.h:527
unsigned int reg_space
Definition: hlsl.h:438
unsigned int reg_index
Definition: hlsl.h:438
Definition: hlsl.h:282
unsigned int writemask
Definition: hlsl.h:303
uint32_t index
Definition: hlsl.h:242
const char * name
Definition: hlsl.h:241
struct hlsl_semantic semantic
Definition: hlsl.h:263
struct vkd3d_shader_location loc
Definition: hlsl.h:260
unsigned int dimx
Definition: hlsl.h:187
struct hlsl_type::@5997::@5998 numeric
struct hlsl_type::@5997::@6000 array
union hlsl_type::@5997 e
enum hlsl_type_class class
Definition: hlsl.h:163
unsigned int dimy
Definition: hlsl.h:188
Definition: copy.c:22
Definition: name.c:39
Definition: rbtree.h:30
Definition: rbtree.h:40
const struct hlsl_ir_function_decl ** backtrace
Definition: hlsl_codegen.c:749
struct register_allocator::allocation * allocations
bool prioritize_smaller_writemasks
const void * code
Definition: vkd3d_shader.h:413
struct vkd3d_shader_register reg
struct vkd3d_shader_instruction * elements
struct vkd3d_shader_src_param * src
struct vkd3d_shader_location location
struct vkd3d_shader_register_semantic register_semantic
struct vkd3d_shader_indexable_temp indexable_temp
union vkd3d_shader_instruction::@6020 declaration
enum vkd3d_shader_opcode opcode
struct vkd3d_shader_semantic semantic
struct vkd3d_shader_dst_param * dst
struct vkd3d_shader_register reg
enum vkd3d_shader_src_modifier modifiers
#define max(a, b)
Definition: svc.c:63
#define LIST_INIT(head)
Definition: queue.h:197
#define LIST_ENTRY(type)
Definition: queue.h:175
bool shader_sm4_is_scalar_register(const struct vkd3d_shader_register *reg)
Definition: tpf.c:2238
bool sm4_register_from_semantic_name(const struct vkd3d_shader_version *version, const char *semantic_name, bool output, enum vkd3d_shader_register_type *type, bool *has_idx)
Definition: tpf.c:2998
bool sm4_sysval_semantic_from_semantic_name(enum vkd3d_shader_sysval_semantic *sysval_semantic, const struct vkd3d_shader_version *version, bool semantic_compat_mapping, enum vkd3d_tessellator_domain domain, const char *semantic_name, unsigned int semantic_idx, bool output, bool is_patch_constant_func)
Definition: tpf.c:3100
Definition: dlist.c:348
Definition: pdh_main.c:64
static unsigned int vkd3d_popcount(unsigned int v)
Definition: vkd3d_common.h:280
const char * vkd3d_dbg_sprintf(const char *fmt,...) VKD3D_PRINTF_FUNC(1
#define vkd3d_unreachable()
Definition: vkd3d_common.h:119
#define VKD3D_ASSERT(cond)
Definition: vkd3d_common.h:49
static int ascii_strcasecmp(const char *a, const char *b)
Definition: vkd3d_common.h:437
static char * vkd3d_strdup(const char *string)
Definition: vkd3d_memory.h:57
static void vkd3d_free(void *ptr)
Definition: vkd3d_memory.h:52
bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t element_count, size_t element_size)
Definition: memory.c:22
VKD3D_SHADER_API void vkd3d_shader_free_shader_code(struct vkd3d_shader_code *code)
vkd3d_shader_sysval_semantic
@ VKD3D_SHADER_SV_VERTEX_ID
@ VKD3D_SHADER_SV_PRIMITIVE_ID
@ VKD3D_SHADER_SV_DEPTH
@ VKD3D_SHADER_SV_TARGET
@ VKD3D_SHADER_SV_NONE
@ VKD3D_SHADER_SV_IS_FRONT_FACE
@ VKD3D_SHADER_SV_TESS_FACTOR_TRIINT
@ VKD3D_SHADER_SV_INSTANCE_ID
@ VKD3D_SHADER_SV_SAMPLE_INDEX
@ VKD3D_SHADER_SV_POSITION
@ VKD3D_SHADER_LOG_ERROR
@ VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CW
@ VKD3D_SHADER_TESSELLATOR_OUTPUT_POINT
@ VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CCW
@ VKD3D_SHADER_TESSELLATOR_OUTPUT_LINE
vkd3d_shader_component_type
@ VKD3D_SHADER_COMPONENT_INT
@ VKD3D_SHADER_COMPONENT_UINT
@ VKD3D_SHADER_COMPONENT_FLOAT
@ VKD3D_SHADER_COMPONENT_VOID
vkd3d_shader_resource_type
@ VKD3D_SHADER_RESOURCE_TEXTURE_3D
@ VKD3D_SHADER_RESOURCE_TEXTURE_CUBE
@ VKD3D_SHADER_RESOURCE_TEXTURE_2D
@ VKD3D_SHADER_TESSELLATOR_PARTITIONING_INTEGER
@ VKD3D_SHADER_TESSELLATOR_PARTITIONING_POW2
@ VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_ODD
@ VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN
#define VKD3D_SHADER_SWIZZLE(x, y, z, w)
#define VKD3D_SHADER_NO_SWIZZLE
vkd3d_shader_target_type
@ VKD3D_SHADER_TARGET_DXBC_TPF
@ VKD3D_SHADER_TARGET_D3D_BYTECODE
uint64_t vkd3d_shader_init_config_flags(void)
bool shader_instruction_array_reserve(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve)
int vkd3d_string_buffer_printf(struct vkd3d_string_buffer *buffer, const char *format,...)
@ VKD3DSPSM_ABS
@ VKD3DSPSM_NEG
@ VKD3D_SHADER_TYPE_VERTEX
@ VKD3D_SHADER_TYPE_HULL
@ VKD3D_SHADER_TYPE_GEOMETRY
@ VKD3D_SHADER_TYPE_COMPUTE
@ VKD3D_SHADER_TYPE_PIXEL
@ VKD3D_SHADER_TYPE_DOMAIN
vkd3d_shader_interpolation_mode
@ VKD3DSIM_CONSTANT
@ VKD3DSIM_LINEAR_NOPERSPECTIVE_CENTROID
@ VKD3DSIM_LINEAR_CENTROID
@ VKD3DSIM_LINEAR
@ VKD3DSIM_LINEAR_NOPERSPECTIVE
static uint32_t vsir_swizzle_from_writemask(unsigned int writemask)
#define VKD3DSI_TEXLD_BIAS
vkd3d_shader_register_type
@ VKD3DSPR_RASTERIZER
@ VKD3DSPR_IMMCONST
@ VKD3DSPR_NULL
@ VKD3DSPR_CONST
@ VKD3DSPR_TEMP
@ VKD3DSPR_COMBINED_SAMPLER
@ VKD3DSPR_OUTPUT
@ VKD3DSPR_SAMPLER
@ VKD3DSPR_PATCHCONST
@ VKD3DSPR_INPUT
@ VKD3D_SHADER_ERROR_HLSL_INVALID_SEMANTIC
@ VKD3D_SHADER_ERROR_HLSL_INVALID_PARTITIONING
@ VKD3D_SHADER_WARNING_HLSL_UNKNOWN_ATTRIBUTE
@ VKD3D_SHADER_ERROR_HLSL_MISSING_ATTRIBUTE
@ VKD3D_SHADER_ERROR_HLSL_INVALID_TYPE
@ VKD3D_SHADER_ERROR_HLSL_INVALID_MODIFIER
@ VKD3D_SHADER_ERROR_HLSL_INCONSISTENT_SAMPLER
@ VKD3D_SHADER_ERROR_HLSL_NON_STATIC_OBJECT_REF
@ VKD3D_SHADER_ERROR_HLSL_FAILED_FORCED_UNROLL
@ VKD3D_SHADER_ERROR_HLSL_INVALID_OUTPUT_PRIMITIVE
@ VKD3D_SHADER_ERROR_HLSL_MISSING_SEMANTIC
@ VKD3D_SHADER_ERROR_HLSL_INVALID_RESERVATION
@ VKD3D_SHADER_ERROR_HLSL_WRONG_PARAMETER_COUNT
@ VKD3D_SHADER_ERROR_HLSL_INVALID_THREAD_COUNT
@ VKD3D_SHADER_ERROR_HLSL_RECURSIVE_CALL
@ VKD3D_SHADER_ERROR_HLSL_NOT_DEFINED
@ VKD3D_SHADER_ERROR_HLSL_OVERLAPPING_RESERVATIONS
@ VKD3D_SHADER_ERROR_HLSL_INVALID_DOMAIN
@ VKD3D_SHADER_ERROR_HLSL_INVALID_CONTROL_POINT_COUNT
@ VKD3D_SHADER_ERROR_HLSL_OFFSET_OUT_OF_BOUNDS
@ VKD3D_SHADER_ERROR_HLSL_INVALID_SYNTAX
static unsigned int vkd3d_write_mask_from_component_count(unsigned int component_count)
#define VKD3DSP_WRITEMASK_ALL
@ VSIR_DIMENSION_SCALAR
@ VSIR_DIMENSION_VEC4
@ VSIR_DIMENSION_NONE
@ VKD3D_DATA_INT
@ VKD3D_DATA_UNUSED
@ VKD3D_DATA_DOUBLE
@ VKD3D_DATA_HALF
@ VKD3D_DATA_UINT
@ VKD3D_DATA_FLOAT
@ VKD3D_DATA_MIXED
@ VSIR_NOT_NORMALISED
#define VKD3DSI_TEXLD_PROJECT
static unsigned int vsir_swizzle_get_component(uint32_t swizzle, unsigned int idx)
vkd3d_shader_opcode
@ VKD3DSIH_DP2
@ VKD3DSIH_IMAD
@ VKD3DSIH_TEX
@ VKD3DSIH_F16TOF32
@ VKD3DSIH_AND
@ VKD3DSIH_ISHL
@ VKD3DSIH_IMUL
@ VKD3DSIH_SAMPLE_INFO
@ VKD3DSIH_ROUND_PI
@ VKD3DSIH_DCL_INPUT_PS
@ VKD3DSIH_UGE
@ VKD3DSIH_DSX_COARSE
@ VKD3DSIH_IADD
@ VKD3DSIH_DP4
@ VKD3DSIH_DIV
@ VKD3DSIH_IEQ
@ VKD3DSIH_DCL_OUTPUT
@ VKD3DSIH_XOR
@ VKD3DSIH_UMAX
@ VKD3DSIH_TEXKILL
@ VKD3DSIH_DCL_OUTPUT_SIV
@ VKD3DSIH_DSY_FINE
@ VKD3DSIH_ISHR
@ VKD3DSIH_NEU
@ VKD3DSIH_DCL_INPUT_SGV
@ VKD3DSIH_ROUND_NE
@ VKD3DSIH_MUL
@ VKD3DSIH_EXP
@ VKD3DSIH_IFC
@ VKD3DSIH_MIN
@ VKD3DSIH_RCP
@ VKD3DSIH_UDIV
@ VKD3DSIH_RSQ
@ VKD3DSIH_ENDIF
@ VKD3DSIH_DCL_TEMPS
@ VKD3DSIH_IMAX
@ VKD3DSIH_SLT
@ VKD3DSIH_FTOI
@ VKD3DSIH_DCL_INPUT
@ VKD3DSIH_LOG
@ VKD3DSIH_ROUND_NI
@ VKD3DSIH_EQO
@ VKD3DSIH_DCL_INPUT_PS_SIV
@ VKD3DSIH_TEXLDD
@ VKD3DSIH_F32TOF16
@ VKD3DSIH_UTOF
@ VKD3DSIH_LTO
@ VKD3DSIH_NOT
@ VKD3DSIH_MAD
@ VKD3DSIH_ADD
@ VKD3DSIH_DEF
@ VKD3DSIH_DSY_COARSE
@ VKD3DSIH_INE
@ VKD3DSIH_DCL_INPUT_SIV
@ VKD3DSIH_MOVC
@ VKD3DSIH_DSY
@ VKD3DSIH_MOV
@ VKD3DSIH_MAX
@ VKD3DSIH_ULT
@ VKD3DSIH_IMIN
@ VKD3DSIH_FTOU
@ VKD3DSIH_DSX_FINE
@ VKD3DSIH_OR
@ VKD3DSIH_CMP
@ VKD3DSIH_ILT
@ VKD3DSIH_USHR
@ VKD3DSIH_DCL
@ VKD3DSIH_FRC
@ VKD3DSIH_ELSE
@ VKD3DSIH_DCL_INPUT_PS_SGV
@ VKD3DSIH_DCL_INDEXABLE_TEMP
@ VKD3DSIH_GEO
@ VKD3DSIH_DP2ADD
@ VKD3DSIH_INEG
@ VKD3DSIH_ITOF
@ VKD3DSIH_ROUND_Z
@ VKD3DSIH_IGE
@ VKD3DSIH_SINCOS
@ VKD3DSIH_UMIN
@ VKD3DSIH_DP3
@ VKD3DSIH_DSX
@ VKD3DSIH_ABS
@ VKD3DSIH_SQRT
#define VKD3DSI_SAMPLE_INFO_UINT
@ VKD3D_SHADER_REGISTER_PRECISION_DEFAULT
@ VKD3D_TESSELLATOR_DOMAIN_INVALID
@ VKD3D_TESSELLATOR_DOMAIN_TRIANGLE
@ VKD3D_TESSELLATOR_DOMAIN_LINE
@ VKD3D_TESSELLATOR_DOMAIN_QUAD
@ VKD3D_DECL_USAGE_POSITION
@ VKD3DSPDM_SATURATE
#define VKD3DSP_WRITEMASK_0
#define VKD3DSP_WRITEMASK_1
@ VSIR_CF_STRUCTURED
@ VKD3D_SHADER_REL_OP_NE
@ VKD3D_ERROR_INVALID_ARGUMENT
Definition: vkd3d_types.h:51
@ VKD3D_ERROR_NOT_IMPLEMENTED
Definition: vkd3d_types.h:55
@ VKD3D_ERROR_OUT_OF_MEMORY
Definition: vkd3d_types.h:49
wchar_t tm const _CrtWcstime_Writes_and_advances_ptr_ count wchar_t ** out
Definition: wcsftime.cpp:383
void * arg
Definition: msvc.h:10
static size_t align(size_t addr, size_t alignment)
@ if_true
Definition: wpp_private.h:102
@ if_false
Definition: wpp_private.h:101
static unsigned int block
Definition: xmlmemory.c:101