ReactOS 0.4.17-dev-934-g091855f
ir.c
Go to the documentation of this file.
1/*
2 * Copyright 2023 Conor McCarthy for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
20#include "vkd3d_types.h"
21
23{
29};
30
31static int convert_parameter_info(const struct vkd3d_shader_compile_info *compile_info,
32 unsigned int *ret_count, const struct vkd3d_shader_parameter1 **ret_parameters)
33{
34 const struct vkd3d_shader_spirv_target_info *spirv_info;
36
37 *ret_count = 0;
38 *ret_parameters = NULL;
39
40 if (!(spirv_info = vkd3d_find_struct(compile_info->next, SPIRV_TARGET_INFO)) || !spirv_info->parameter_count)
41 return VKD3D_OK;
42
43 if (!(parameters = vkd3d_calloc(spirv_info->parameter_count, sizeof(*parameters))))
45
46 for (unsigned int i = 0; i < spirv_info->parameter_count; ++i)
47 {
48 const struct vkd3d_shader_parameter *src = &spirv_info->parameters[i];
50
51 dst->name = src->name;
52 dst->type = src->type;
53 dst->data_type = src->data_type;
54
56 {
57 dst->u.immediate_constant.u.u32 = src->u.immediate_constant.u.u32;
58 }
60 {
61 dst->u.specialization_constant = src->u.specialization_constant;
62 }
63 else
64 {
65 ERR("Invalid parameter type %#x.\n", src->type);
67 }
68 }
69
70 *ret_count = spirv_info->parameter_count;
71 *ret_parameters = parameters;
72
73 return VKD3D_OK;
74}
75
76bool vsir_program_init(struct vsir_program *program, const struct vkd3d_shader_compile_info *compile_info,
77 const struct vkd3d_shader_version *version, unsigned int reserve, enum vsir_control_flow_type cf_type,
78 enum vsir_normalisation_level normalisation_level)
79{
80 memset(program, 0, sizeof(*program));
81
82 if (compile_info)
83 {
84 const struct vkd3d_shader_parameter_info *parameter_info;
85
86 if ((parameter_info = vkd3d_find_struct(compile_info->next, PARAMETER_INFO)))
87 {
88 program->parameter_count = parameter_info->parameter_count;
89 program->parameters = parameter_info->parameters;
90 }
91 else
92 {
93 if (convert_parameter_info(compile_info, &program->parameter_count, &program->parameters) < 0)
94 return false;
95 program->free_parameters = true;
96 }
97 }
98
99 program->shader_version = *version;
100 program->cf_type = cf_type;
101 program->normalisation_level = normalisation_level;
102 return shader_instruction_array_init(&program->instructions, reserve);
103}
104
106{
107 size_t i;
108
109 if (program->free_parameters)
110 vkd3d_free((void *)program->parameters);
111 for (i = 0; i < program->block_name_count; ++i)
112 vkd3d_free((void *)program->block_names[i]);
113 vkd3d_free(program->block_names);
115 shader_signature_cleanup(&program->input_signature);
116 shader_signature_cleanup(&program->output_signature);
117 shader_signature_cleanup(&program->patch_constant_signature);
118}
119
122{
123 for (unsigned int i = 0; i < program->parameter_count; ++i)
124 {
125 if (program->parameters[i].name == name)
126 return &program->parameters[i];
127 }
128
129 return NULL;
130}
131
133 const struct shader_signature *signature, const char *semantic_name, unsigned int semantic_index)
134{
135 for (unsigned int i = 0; i < signature->element_count; ++i)
136 {
137 if (!ascii_strcasecmp(signature->elements[i].semantic_name, semantic_name)
138 && signature->elements[i].semantic_index == semantic_index)
139 return &signature->elements[i];
140 }
141
142 return NULL;
143}
144
146 enum vkd3d_shader_sysval_semantic sysval, unsigned int semantic_index, unsigned int *element_index)
147{
148 const struct signature_element *e;
149 unsigned int i;
150
151 for (i = 0; i < signature->element_count; ++i)
152 {
153 e = &signature->elements[i];
154 if (e->sysval_semantic == sysval && e->semantic_index == semantic_index)
155 {
156 *element_index = i;
157 return true;
158 }
159 }
160
161 return false;
162}
163
165 enum vkd3d_data_type data_type, unsigned int idx_count)
166{
167 reg->type = reg_type;
169 reg->non_uniform = false;
170 reg->data_type = data_type;
171 reg->idx[0].offset = ~0u;
172 reg->idx[0].rel_addr = NULL;
173 reg->idx[0].is_in_bounds = false;
174 reg->idx[1].offset = ~0u;
175 reg->idx[1].rel_addr = NULL;
176 reg->idx[1].is_in_bounds = false;
177 reg->idx[2].offset = ~0u;
178 reg->idx[2].rel_addr = NULL;
179 reg->idx[2].is_in_bounds = false;
180 reg->idx_count = idx_count;
181 reg->dimension = VSIR_DIMENSION_SCALAR;
182 reg->alignment = 0;
183}
184
186{
187 return reg->type == VKD3DSPR_FORKINSTID || reg->type == VKD3DSPR_JOININSTID;
188}
189
191 enum vkd3d_data_type data_type, unsigned int idx_count)
192{
193 vsir_register_init(&param->reg, reg_type, data_type, idx_count);
194 param->swizzle = 0;
195 param->modifiers = VKD3DSPSM_NONE;
196}
197
199{
201 src->reg.u.immconst_u32[0] = value;
202}
203
204void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id)
205{
207 param->reg.dimension = VSIR_DIMENSION_NONE;
208 param->reg.idx[0].offset = label_id;
209}
210
212{
214 src->reg.idx[0].offset = idx;
215}
216
217static void vsir_src_param_init_resource(struct vkd3d_shader_src_param *src, unsigned int id, unsigned int idx)
218{
220 src->reg.idx[0].offset = id;
221 src->reg.idx[1].offset = idx;
222 src->reg.dimension = VSIR_DIMENSION_VEC4;
223 src->swizzle = VKD3D_SHADER_NO_SWIZZLE;
224}
225
226static void vsir_src_param_init_sampler(struct vkd3d_shader_src_param *src, unsigned int id, unsigned int idx)
227{
229 src->reg.idx[0].offset = id;
230 src->reg.idx[1].offset = idx;
231 src->reg.dimension = VSIR_DIMENSION_NONE;
232}
233
234static void src_param_init_ssa_bool(struct vkd3d_shader_src_param *src, unsigned int idx)
235{
237 src->reg.idx[0].offset = idx;
238}
239
240static void src_param_init_ssa_float(struct vkd3d_shader_src_param *src, unsigned int idx)
241{
243 src->reg.idx[0].offset = idx;
244}
245
246static void src_param_init_temp_bool(struct vkd3d_shader_src_param *src, unsigned int idx)
247{
249 src->reg.idx[0].offset = idx;
250}
251
252static void src_param_init_temp_float(struct vkd3d_shader_src_param *src, unsigned int idx)
253{
255 src->reg.idx[0].offset = idx;
256}
257
259{
261 src->reg.dimension = VSIR_DIMENSION_VEC4;
262 src->swizzle = VKD3D_SHADER_NO_SWIZZLE;
263 src->reg.idx[0].offset = idx;
264}
265
266static void src_param_init_temp_uint(struct vkd3d_shader_src_param *src, unsigned int idx)
267{
269 src->reg.idx[0].offset = idx;
270}
271
273 enum vkd3d_data_type data_type, unsigned int idx_count)
274{
275 vsir_register_init(&param->reg, reg_type, data_type, idx_count);
276 param->write_mask = VKD3DSP_WRITEMASK_0;
277 param->modifiers = VKD3DSPDM_NONE;
278 param->shift = 0;
279}
280
281static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx)
282{
284 dst->reg.idx[0].offset = idx;
285}
286
287static void dst_param_init_ssa_float(struct vkd3d_shader_dst_param *dst, unsigned int idx)
288{
290 dst->reg.idx[0].offset = idx;
291}
292
293static void dst_param_init_temp_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx)
294{
296 dst->reg.idx[0].offset = idx;
297}
298
300{
302 dst->reg.idx[0].offset = idx;
303 dst->reg.dimension = VSIR_DIMENSION_VEC4;
304}
305
306static void dst_param_init_temp_uint(struct vkd3d_shader_dst_param *dst, unsigned int idx)
307{
309 dst->reg.idx[0].offset = idx;
310}
311
314{
316 dst->reg.idx[0].offset = idx;
317 dst->reg.dimension = VSIR_DIMENSION_VEC4;
318 dst->write_mask = write_mask;
319}
320
322 enum vkd3d_shader_opcode opcode)
323{
324 memset(ins, 0, sizeof(*ins));
325 ins->location = *location;
326 ins->opcode = opcode;
327}
328
331 enum vkd3d_shader_opcode opcode, unsigned int dst_count, unsigned int src_count)
332{
333 vsir_instruction_init(ins, location, opcode);
334 ins->dst_count = dst_count;
335 ins->src_count = src_count;
336
338 {
339 ERR("Failed to allocate %u destination parameters.\n", dst_count);
340 return false;
341 }
342
344 {
345 ERR("Failed to allocate %u source parameters.\n", src_count);
346 return false;
347 }
348
349 memset(ins->dst, 0, sizeof(*ins->dst) * ins->dst_count);
350 memset(ins->src, 0, sizeof(*ins->src) * ins->src_count);
351 return true;
352}
353
355 const struct vkd3d_shader_location *location, unsigned int label_id, struct vsir_program *program)
356{
357 struct vkd3d_shader_src_param *src_param;
358
359 if (!(src_param = vsir_program_get_src_params(program, 1)))
360 return false;
361
362 vsir_src_param_init_label(src_param, label_id);
363
365 ins->src = src_param;
366 ins->src_count = 1;
367
368 return true;
369}
370
372{
374 return (VKD3DSIH_DCL <= opcode && opcode <= VKD3DSIH_DCL_VERTICES_OUT)
375 || opcode == VKD3DSIH_HS_DECLS;
376}
377
379{
381
383}
384
386 enum vkd3d_shader_opcode *opcode, bool *requires_swap)
387{
388 switch (rel_op)
389 {
392 *requires_swap = (rel_op == VKD3D_SHADER_REL_OP_GT);
394 {
395 *opcode = VKD3DSIH_LTO;
396 return true;
397 }
398 break;
399
402 *requires_swap = (rel_op == VKD3D_SHADER_REL_OP_LE);
404 {
405 *opcode = VKD3DSIH_GEO;
406 return true;
407 }
408 break;
409
411 *requires_swap = false;
413 {
414 *opcode = VKD3DSIH_EQO;
415 return true;
416 }
417 break;
418
420 *requires_swap = false;
422 {
423 *opcode = VKD3DSIH_NEO;
424 return true;
425 }
426 break;
427 }
428 return false;
429}
430
432 struct vkd3d_shader_instruction *ifc, unsigned int *tmp_idx,
433 struct vkd3d_shader_message_context *message_context)
434{
435 struct vkd3d_shader_instruction_array *instructions = &program->instructions;
436 size_t pos = ifc - instructions->elements;
437 struct vkd3d_shader_instruction *ins;
439 bool swap;
440
441 if (!shader_instruction_array_insert_at(instructions, pos + 1, 2))
443
444 if (*tmp_idx == ~0u)
445 *tmp_idx = program->temp_count++;
446
447 /* Replace ifc comparison with actual comparison, saving the result in the tmp register. */
448 if (!(get_opcode_from_rel_op(ifc->flags, ifc->src[0].reg.data_type, &opcode, &swap)))
449 {
451 "Aborting due to not yet implemented feature: opcode for rel_op %u and data type %u.",
452 ifc->flags, ifc->src[0].reg.data_type);
454 }
455
456 ins = &instructions->elements[pos + 1];
459
461 ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4;
462 ins->dst[0].reg.idx[0].offset = *tmp_idx;
463 ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0;
464
465 ins->src[0] = ifc->src[swap];
466 ins->src[1] = ifc->src[!swap];
467
468 /* Create new if instruction using the previous result. */
469 ins = &instructions->elements[pos + 2];
473
475 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4;
476 ins->src[0].reg.idx[0].offset = *tmp_idx;
477 ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X);
478
479 /* Make the original instruction no-op */
481
482 return VKD3D_OK;
483}
484
486 struct vkd3d_shader_instruction *texkill, unsigned int *tmp_idx)
487{
488 const unsigned int components_read = 3 + (program->shader_version.major >= 2);
489 struct vkd3d_shader_instruction_array *instructions = &program->instructions;
490 size_t pos = texkill - instructions->elements;
491 struct vkd3d_shader_instruction *ins;
492 unsigned int j;
493
494 if (!shader_instruction_array_insert_at(instructions, pos + 1, components_read + 1))
496
497 if (*tmp_idx == ~0u)
498 *tmp_idx = program->temp_count++;
499
500 /* tmp = ins->dst[0] < 0 */
501
502 ins = &instructions->elements[pos + 1];
505
507 ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4;
508 ins->dst[0].reg.idx[0].offset = *tmp_idx;
509 ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL;
510
511 ins->src[0].reg = texkill->dst[0].reg;
512 ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE;
514 ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4;
515 ins->src[1].reg.u.immconst_f32[0] = 0.0f;
516 ins->src[1].reg.u.immconst_f32[1] = 0.0f;
517 ins->src[1].reg.u.immconst_f32[2] = 0.0f;
518 ins->src[1].reg.u.immconst_f32[3] = 0.0f;
519
520 /* tmp.x = tmp.x || tmp.y */
521 /* tmp.x = tmp.x || tmp.z */
522 /* tmp.x = tmp.x || tmp.w, if sm >= 2.0 */
523
524 for (j = 1; j < components_read; ++j)
525 {
526 ins = &instructions->elements[pos + 1 + j];
527 if (!(vsir_instruction_init_with_params(program, ins, &texkill->location, VKD3DSIH_OR, 1, 2)))
529
531 ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4;
532 ins->dst[0].reg.idx[0].offset = *tmp_idx;
533 ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0;
534
536 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4;
537 ins->src[0].reg.idx[0].offset = *tmp_idx;
538 ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X);
540 ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4;
541 ins->src[1].reg.idx[0].offset = *tmp_idx;
542 ins->src[1].swizzle = vkd3d_shader_create_swizzle(j, j, j, j);
543 }
544
545 /* discard_nz tmp.x */
546
547 ins = &instructions->elements[pos + 1 + components_read];
551
553 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4;
554 ins->src[0].reg.idx[0].offset = *tmp_idx;
555 ins->src[0].swizzle = VKD3D_SHADER_SWIZZLE(X, X, X, X);
556
557 /* Make the original instruction no-op */
559
560 return VKD3D_OK;
561}
562
563/* The Shader Model 5 Assembly documentation states: "If components of a mad
564 * instruction are tagged as precise, the hardware must execute a mad instruction
565 * or the exact equivalent, and it cannot split it into a multiply followed by an add."
566 * But DXIL.rst states the opposite: "Floating point multiply & add. This operation is
567 * not fused for "precise" operations."
568 * Windows drivers seem to conform with the latter, for SM 4-5 and SM 6. */
570 struct vkd3d_shader_instruction *mad, unsigned int *tmp_idx)
571{
572 struct vkd3d_shader_instruction_array *instructions = &program->instructions;
573 struct vkd3d_shader_instruction *mul_ins, *add_ins;
574 size_t pos = mad - instructions->elements;
575 struct vkd3d_shader_dst_param *mul_dst;
576
577 if (!(mad->flags & VKD3DSI_PRECISE_XYZW))
578 return VKD3D_OK;
579
580 if (!shader_instruction_array_insert_at(instructions, pos + 1, 1))
582
583 if (*tmp_idx == ~0u)
584 *tmp_idx = program->temp_count++;
585
586 mul_ins = &instructions->elements[pos];
587 add_ins = &instructions->elements[pos + 1];
588
589 mul_ins->opcode = VKD3DSIH_MUL;
590 mul_ins->src_count = 2;
591
592 if (!(vsir_instruction_init_with_params(program, add_ins, &mul_ins->location, VKD3DSIH_ADD, 1, 2)))
594
595 add_ins->flags = mul_ins->flags & VKD3DSI_PRECISE_XYZW;
596
597 mul_dst = mul_ins->dst;
598 *add_ins->dst = *mul_dst;
599
600 mul_dst->modifiers = 0;
601 vsir_register_init(&mul_dst->reg, VKD3DSPR_TEMP, mul_ins->src[0].reg.data_type, 1);
602 mul_dst->reg.dimension = add_ins->dst->reg.dimension;
603 mul_dst->reg.idx[0].offset = *tmp_idx;
604
605 add_ins->src[0].reg = mul_dst->reg;
606 add_ins->src[0].swizzle = vsir_swizzle_from_writemask(mul_dst->write_mask);
607 add_ins->src[0].modifiers = 0;
608 add_ins->src[1] = mul_ins->src[2];
609
610 return VKD3D_OK;
611}
612
615{
616 struct vkd3d_shader_instruction_array *instructions = &program->instructions;
617 size_t pos = sincos - instructions->elements;
618 struct vkd3d_shader_instruction *ins;
619 unsigned int s;
620
621 if (sincos->dst_count != 1)
622 return VKD3D_OK;
623
624 if (!shader_instruction_array_insert_at(instructions, pos + 1, 1))
626
627 ins = &instructions->elements[pos + 1];
628
629 if (!(vsir_instruction_init_with_params(program, ins, &sincos->location, VKD3DSIH_SINCOS, 2, 1)))
631
632 ins->flags = sincos->flags;
633
634 *ins->src = *sincos->src;
635 /* Set the source swizzle to replicate the first component. */
636 s = vsir_swizzle_get_component(sincos->src->swizzle, 0);
637 ins->src->swizzle = vkd3d_shader_create_swizzle(s, s, s, s);
638
639 if (sincos->dst->write_mask & VKD3DSP_WRITEMASK_1)
640 {
641 ins->dst[0] = *sincos->dst;
642 ins->dst[0].write_mask = VKD3DSP_WRITEMASK_1;
643 }
644 else
645 {
647 }
648
649 if (sincos->dst->write_mask & VKD3DSP_WRITEMASK_0)
650 {
651 ins->dst[1] = *sincos->dst;
652 ins->dst[1].write_mask = VKD3DSP_WRITEMASK_0;
653 }
654 else
655 {
657 }
658
659 /* Make the original instruction no-op */
661
662 return VKD3D_OK;
663}
664
666{
667 unsigned int idx = tex->src[1].reg.idx[0].offset;
668 struct vkd3d_shader_src_param *srcs;
669
670 VKD3D_ASSERT(tex->src[1].reg.idx_count == 1);
671 VKD3D_ASSERT(!tex->src[1].reg.idx[0].rel_addr);
672
673 if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 3)))
675
676 srcs[0] = tex->src[0];
679
680 tex->opcode = VKD3DSIH_SAMPLE;
681 tex->src = srcs;
682 tex->src_count = 3;
683
684 return VKD3D_OK;
685}
686
688 struct vkd3d_shader_instruction *texldd)
689{
690 unsigned int idx = texldd->src[1].reg.idx[0].offset;
691 struct vkd3d_shader_src_param *srcs;
692
693 VKD3D_ASSERT(texldd->src[1].reg.idx_count == 1);
694 VKD3D_ASSERT(!texldd->src[1].reg.idx[0].rel_addr);
695
696 if (!(srcs = shader_src_param_allocator_get(&program->instructions.src_params, 5)))
698
699 srcs[0] = texldd->src[0];
702 srcs[3] = texldd->src[2];
703 srcs[4] = texldd->src[3];
704
706 texldd->src = srcs;
707 texldd->src_count = 5;
708
709 return VKD3D_OK;
710}
711
714{
715 struct vkd3d_shader_instruction_array *instructions = &program->instructions;
716 struct vkd3d_shader_message_context *message_context = ctx->message_context;
717 unsigned int tmp_idx = ~0u, i;
718 enum vkd3d_result ret;
719
720 for (i = 0; i < instructions->count; ++i)
721 {
722 struct vkd3d_shader_instruction *ins = &instructions->elements[i];
723
724 switch (ins->opcode)
725 {
726 case VKD3DSIH_IFC:
727 if ((ret = vsir_program_lower_ifc(program, ins, &tmp_idx, message_context)) < 0)
728 return ret;
729 break;
730
731 case VKD3DSIH_TEXKILL:
732 if ((ret = vsir_program_lower_texkill(program, ins, &tmp_idx)) < 0)
733 return ret;
734 break;
735
736 case VKD3DSIH_MAD:
737 if ((ret = vsir_program_lower_precise_mad(program, ins, &tmp_idx)) < 0)
738 return ret;
739 break;
740
741 case VKD3DSIH_DCL:
749 break;
750
751 case VKD3DSIH_SINCOS:
752 if ((ret = vsir_program_lower_sm1_sincos(program, ins)) < 0)
753 return ret;
754 break;
755
756 case VKD3DSIH_TEX:
757 if ((ret = vsir_program_lower_tex(program, ins)) < 0)
758 return ret;
759 break;
760
761 case VKD3DSIH_TEXLDD:
762 if ((ret = vsir_program_lower_texldd(program, ins)) < 0)
763 return ret;
764 break;
765
766 case VKD3DSIH_TEXBEM:
767 case VKD3DSIH_TEXBEML:
770 case VKD3DSIH_TEXDP3:
772 case VKD3DSIH_TEXLDL:
784 "Aborting due to unimplemented feature: Combined sampler instruction %#x.",
785 ins->opcode);
787
788 default:
789 break;
790 }
791 }
792
793 return VKD3D_OK;
794}
795
797 unsigned int instance_id)
798{
799 unsigned int i;
800
801 for (i = 0; i < reg->idx_count; ++i)
802 {
803 if (reg->idx[i].rel_addr && shader_register_is_phase_instance_id(&reg->idx[i].rel_addr->reg))
804 {
805 reg->idx[i].rel_addr = NULL;
806 reg->idx[i].offset += instance_id;
807 }
808 }
809}
810
812 unsigned int instance_id)
813{
815 unsigned int i;
816
817 for (i = 0; i < ins->src_count; ++i)
818 {
819 reg = (struct vkd3d_shader_register *)&ins->src[i].reg;
821 {
823 reg->u.immconst_u32[0] = instance_id;
824 continue;
825 }
827 }
828
829 for (i = 0; i < ins->dst_count; ++i)
830 shader_register_eliminate_phase_addressing(&ins->dst[i].reg, instance_id);
831}
832
833/* Ensure that the program closes with a ret. sm1 programs do not, by default.
834 * Many of our IR passes rely on this in order to insert instructions at the
835 * end of execution. */
838{
839 static const struct vkd3d_shader_location no_loc;
840 if (program->instructions.count
841 && program->instructions.elements[program->instructions.count - 1].opcode == VKD3DSIH_RET)
842 return VKD3D_OK;
843
844 if (!shader_instruction_array_insert_at(&program->instructions, program->instructions.count, 1))
846 vsir_instruction_init(&program->instructions.elements[program->instructions.count - 1], &no_loc, VKD3DSIH_RET);
847 return VKD3D_OK;
848}
849
852{
853 struct shader_signature *signature = &program->output_signature;
854 struct signature_element *new_elements, *e;
855
856 if (program->shader_version.type != VKD3D_SHADER_TYPE_VERTEX)
857 return VKD3D_OK;
858
860 {
861 program->diffuse_written_mask = e->mask;
862 e->mask = VKD3DSP_WRITEMASK_ALL;
863
864 return VKD3D_OK;
865 }
866
867 if (!(new_elements = vkd3d_realloc(signature->elements,
868 (signature->element_count + 1) * sizeof(*signature->elements))))
870 signature->elements = new_elements;
871 e = &signature->elements[signature->element_count++];
872 memset(e, 0, sizeof(*e));
873 e->semantic_name = vkd3d_strdup("COLOR");
874 e->sysval_semantic = VKD3D_SHADER_SV_NONE;
875 e->component_type = VKD3D_SHADER_COMPONENT_FLOAT;
876 e->register_count = 1;
877 e->mask = VKD3DSP_WRITEMASK_ALL;
878 e->used_mask = VKD3DSP_WRITEMASK_ALL;
879 e->register_index = SM1_COLOR_REGISTER_OFFSET;
880 e->target_location = SM1_COLOR_REGISTER_OFFSET;
881 e->interpolation_mode = VKD3DSIM_NONE;
882
883 return VKD3D_OK;
884}
885
886/* Uninitialized components of diffuse yield 1.0 in SM1-2. Implement this by
887 * always writing diffuse in those versions, even if the PS doesn't read it. */
890{
891 static const struct vkd3d_shader_location no_loc;
892 struct vkd3d_shader_instruction *ins;
893 unsigned int i;
894
895 if (program->shader_version.type != VKD3D_SHADER_TYPE_VERTEX
896 || program->diffuse_written_mask == VKD3DSP_WRITEMASK_ALL)
897 return VKD3D_OK;
898
899 /* Write the instruction after all LABEL, DCL, and NOP instructions.
900 * We need to skip NOP instructions because they might result from removed
901 * DCLs, and there could still be DCLs after NOPs. */
902 for (i = 0; i < program->instructions.count; ++i)
903 {
904 ins = &program->instructions.elements[i];
905
906 if (!vsir_instruction_is_dcl(ins) && ins->opcode != VKD3DSIH_LABEL && ins->opcode != VKD3DSIH_NOP)
907 break;
908 }
909
910 if (!shader_instruction_array_insert_at(&program->instructions, i, 1))
912 ins = &program->instructions.elements[i];
915 ins->dst[0].reg.idx[0].offset = 0;
916 ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4;
917 ins->dst[0].write_mask = VKD3DSP_WRITEMASK_ALL & ~program->diffuse_written_mask;
919 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4;
920 for (i = 0; i < 4; ++i)
921 ins->src[0].reg.u.immconst_f32[i] = 1.0f;
922 return VKD3D_OK;
923}
924
926 const struct vkd3d_shader_varying_map_info *varying_map, unsigned int signature_idx)
927{
928 unsigned int i;
929
930 for (i = 0; i < varying_map->varying_count; ++i)
931 {
932 if (varying_map->varying_map[i].output_signature_index == signature_idx)
933 return &varying_map->varying_map[i];
934 }
935
936 return NULL;
937}
938
940{
941 const struct vkd3d_shader_spirv_target_info *spirv_info;
943
944 switch (info->target_type)
945 {
947 spirv_info = vkd3d_find_struct(info->next, SPIRV_TARGET_INFO);
949
950 switch (environment)
951 {
953 return true;
954
957 /* FIXME: Allow KHR_maintenance4. */
958 return false;
959
960 default:
961 FIXME("Unrecognized environment %#x.\n", environment);
962 return false;
963 }
964
965 default:
966 return true;
967 }
968}
969
972{
973 const struct signature_element *e;
974
975 switch (dst->reg.type)
976 {
977 case VKD3DSPR_OUTPUT:
978 e = vsir_signature_find_element_for_reg(signature, dst->reg.idx[0].offset, 0);
979 break;
980
981 case VKD3DSPR_ATTROUT:
983 SM1_COLOR_REGISTER_OFFSET + dst->reg.idx[0].offset, 0);
984 break;
985
986 case VKD3DSPR_RASTOUT:
988 SM1_RASTOUT_REGISTER_OFFSET + dst->reg.idx[0].offset, 0);
989 break;
990
991 default:
992 return;
993 }
994
995 /* We already changed the mask earlier. */
996 dst->write_mask &= e->mask;
997
998 if (!dst->write_mask)
999 {
1000 if (ins->dst_count == 1)
1002 else
1004 }
1005}
1006
1009{
1010 const struct vkd3d_shader_location location = {.source_name = ctx->compile_info->source_name};
1011 struct vkd3d_shader_message_context *message_context = ctx->message_context;
1012 const struct vkd3d_shader_compile_info *compile_info = ctx->compile_info;
1013 bool allows_subset_masks = target_allows_subset_masks(compile_info);
1014 struct shader_signature *signature = &program->output_signature;
1015 unsigned int orig_element_count = signature->element_count;
1017 struct signature_element *new_elements, *e;
1018 unsigned int uninit_varying_count = 0;
1019 unsigned int subset_varying_count = 0;
1020 unsigned int new_register_count = 0;
1021 unsigned int i;
1022
1023 if (!(varying_map = vkd3d_find_struct(compile_info->next, VARYING_MAP_INFO)))
1024 return VKD3D_OK;
1025
1026 for (i = 0; i < signature->element_count; ++i)
1027 {
1028 const struct vkd3d_shader_varying_map *map = find_varying_map(varying_map, i);
1029
1030 e = &signature->elements[i];
1031 if (map)
1032 {
1033 unsigned int input_mask = map->input_mask;
1034
1035 e->target_location = map->input_register_index;
1036
1037 if ((input_mask & e->mask) == input_mask)
1038 {
1039 ++subset_varying_count;
1040 if (!allows_subset_masks)
1041 {
1042 e->mask = input_mask;
1043 e->used_mask &= input_mask;
1044 }
1045 }
1046 else if (input_mask && input_mask != e->mask)
1047 {
1049 "Aborting due to not yet implemented feature: "
1050 "Input mask %#x reads components not written in output mask %#x.",
1051 input_mask, e->mask);
1053 }
1054 }
1055 else
1056 {
1057 e->target_location = SIGNATURE_TARGET_LOCATION_UNUSED;
1058 }
1059
1060 new_register_count = max(new_register_count, e->register_index + 1);
1061 }
1062
1063 /* Handle uninitialized varyings by writing them before every ret.
1064 *
1065 * As far as sm1-sm3 is concerned, drivers disagree on what uninitialized
1066 * varyings contain.
1067 *
1068 * - Diffuse (COLOR0) reliably contains (1, 1, 1, 1) in SM1/2.
1069 * In SM3 it may contain (0, 0, 0, 0), (0, 0, 0, 1), or (1, 1, 1, 1).
1070 *
1071 * - Specular (COLOR1) contains (0, 0, 0, 0) or (0, 0, 0, 1).
1072 * WARP writes (1, 1, 1, 1).
1073 *
1074 * - Anything else contains (0, 0, 0, 0) or (0, 0, 0, 1).
1075 *
1076 * We don't have enough knowledge to identify diffuse here. Instead we deal
1077 * with that in vsir_program_ensure_diffuse(), by always writing diffuse if
1078 * the shader doesn't.
1079 */
1080
1081 for (i = 0; i < varying_map->varying_count; ++i)
1082 {
1083 if (varying_map->varying_map[i].output_signature_index >= signature->element_count)
1084 ++uninit_varying_count;
1085 }
1086
1087 if (!(new_elements = vkd3d_realloc(signature->elements,
1088 (signature->element_count + uninit_varying_count) * sizeof(*signature->elements))))
1090 signature->elements = new_elements;
1091
1092 for (i = 0; i < varying_map->varying_count; ++i)
1093 {
1094 const struct vkd3d_shader_varying_map *map = &varying_map->varying_map[i];
1095
1096 if (map->output_signature_index < orig_element_count)
1097 continue;
1098
1099 TRACE("Synthesizing zero value for uninitialized output %u (mask %u).\n",
1100 map->input_register_index, map->input_mask);
1101 e = &signature->elements[signature->element_count++];
1102 memset(e, 0, sizeof(*e));
1103 e->sysval_semantic = VKD3D_SHADER_SV_NONE;
1104 e->component_type = VKD3D_SHADER_COMPONENT_FLOAT;
1105 e->register_count = 1;
1106 e->mask = map->input_mask;
1107 e->used_mask = map->input_mask;
1108 e->register_index = new_register_count++;
1109 e->target_location = map->input_register_index;
1110 e->interpolation_mode = VKD3DSIM_LINEAR;
1111 }
1112
1113 /* Write each uninitialized varying before each ret. */
1114 for (i = 0; i < program->instructions.count; ++i)
1115 {
1116 struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
1117 struct vkd3d_shader_location loc;
1118
1119 if (ins->opcode != VKD3DSIH_RET)
1120 continue;
1121
1122 loc = ins->location;
1123 if (!shader_instruction_array_insert_at(&program->instructions, i, uninit_varying_count))
1125
1126 ins = &program->instructions.elements[i];
1127
1128 for (unsigned int j = signature->element_count - uninit_varying_count; j < signature->element_count; ++j)
1129 {
1130 e = &signature->elements[j];
1131
1133 dst_param_init_output(&ins->dst[0], VKD3D_DATA_FLOAT, e->register_index, e->mask);
1135 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4;
1136 ++ins;
1137 }
1138
1139 i += uninit_varying_count;
1140 }
1141
1142 /* Vulkan (without KHR_maintenance4) disallows any mismatching masks,
1143 * including when the input mask is a proper subset of the output mask.
1144 * Resolve this by rewriting the shader to remove unread components from
1145 * any writes to the output variable. */
1146
1147 if (!subset_varying_count || allows_subset_masks)
1148 return VKD3D_OK;
1149
1150 for (i = 0; i < program->instructions.count; ++i)
1151 {
1152 struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
1153
1154 for (unsigned int j = 0; j < ins->dst_count; ++j)
1156 }
1157
1158 return VKD3D_OK;
1159}
1160
1162{
1164
1165 unsigned int instance_count;
1166 unsigned int phase_body_idx;
1169};
1170
1171static bool flattener_is_in_fork_or_join_phase(const struct hull_flattener *flattener)
1172{
1173 return flattener->phase == VKD3DSIH_HS_FORK_PHASE || flattener->phase == VKD3DSIH_HS_JOIN_PHASE;
1174}
1175
1177{
1178 unsigned int index;
1179 unsigned int instance_count;
1180 unsigned int instruction_count;
1181};
1182
1184{
1185 /* Unlikely worst case: one phase for each component of each output register. */
1187 unsigned int count;
1188};
1189
1191 unsigned int index, struct shader_phase_location_array *locations)
1192{
1193 struct vkd3d_shader_instruction *ins = &normaliser->instructions.elements[index];
1194 struct shader_phase_location *loc;
1195 bool b;
1196
1198 {
1200 /* Reset the phase info. */
1201 normaliser->phase_body_idx = ~0u;
1202 normaliser->phase = ins->opcode;
1203 normaliser->instance_count = 1;
1204 /* Leave the first occurrence and delete the rest. */
1205 if (b)
1207 return;
1208 }
1211 {
1212 normaliser->instance_count = ins->declaration.count + !ins->declaration.count;
1214 return;
1215 }
1217 &ins->declaration.dst.reg))
1218 {
1220 return;
1221 }
1222
1223 if (normaliser->phase == VKD3DSIH_INVALID || vsir_instruction_is_dcl(ins))
1224 return;
1225
1226 if (normaliser->phase_body_idx == ~0u)
1227 normaliser->phase_body_idx = index;
1228
1229 if (ins->opcode == VKD3DSIH_RET)
1230 {
1231 normaliser->last_ret_location = ins->location;
1233 if (locations->count >= ARRAY_SIZE(locations->locations))
1234 {
1235 FIXME("Insufficient space for phase location.\n");
1236 return;
1237 }
1238 loc = &locations->locations[locations->count++];
1239 loc->index = normaliser->phase_body_idx;
1240 loc->instance_count = normaliser->instance_count;
1241 loc->instruction_count = index - normaliser->phase_body_idx;
1242 }
1243}
1244
1247{
1248 struct shader_phase_location *loc;
1249 unsigned int i, j, k, end, count;
1250
1251 for (i = 0, count = 0; i < locations->count; ++i)
1252 count += (locations->locations[i].instance_count - 1) * locations->locations[i].instruction_count;
1253
1254 if (!shader_instruction_array_reserve(&normaliser->instructions, normaliser->instructions.count + count))
1256 end = normaliser->instructions.count;
1257 normaliser->instructions.count += count;
1258
1259 for (i = locations->count; i > 0; --i)
1260 {
1261 loc = &locations->locations[i - 1];
1262 j = loc->index + loc->instruction_count;
1263 memmove(&normaliser->instructions.elements[j + count], &normaliser->instructions.elements[j],
1264 (end - j) * sizeof(*normaliser->instructions.elements));
1265 end = j;
1266 count -= (loc->instance_count - 1) * loc->instruction_count;
1267 loc->index += count;
1268 }
1269
1270 for (i = 0, count = 0; i < locations->count; ++i)
1271 {
1272 loc = &locations->locations[i];
1273 /* Make a copy of the non-dcl instructions for each instance. */
1274 for (j = 1; j < loc->instance_count; ++j)
1275 {
1276 for (k = 0; k < loc->instruction_count; ++k)
1277 {
1279 loc->index + loc->instruction_count * j + k, loc->index + k))
1281 }
1282 }
1283 /* Replace each reference to the instance id with a constant instance id. */
1284 for (j = 0; j < loc->instance_count; ++j)
1285 {
1286 for (k = 0; k < loc->instruction_count; ++k)
1288 &normaliser->instructions.elements[loc->index + loc->instruction_count * j + k], j);
1289 }
1290 }
1291
1292 return VKD3D_OK;
1293}
1294
1297{
1298 struct hull_flattener flattener = {program->instructions};
1299 struct vkd3d_shader_instruction_array *instructions;
1302 unsigned int i;
1303
1304 instructions = &flattener.instructions;
1305
1306 flattener.phase = VKD3DSIH_INVALID;
1307 for (i = 0, locations.count = 0; i < instructions->count; ++i)
1309
1310 if ((result = flattener_flatten_phases(&flattener, &locations)) < 0)
1311 return result;
1312
1313 if (flattener.phase != VKD3DSIH_INVALID)
1314 {
1315 if (!shader_instruction_array_reserve(&flattener.instructions, flattener.instructions.count + 1))
1317 vsir_instruction_init(&instructions->elements[instructions->count++], &flattener.last_ret_location, VKD3DSIH_RET);
1318 }
1319
1320 program->instructions = flattener.instructions;
1321 return result;
1322}
1323
1325{
1329};
1330
1332{
1333 return normaliser->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE;
1334}
1335
1337{
1338 struct vkd3d_shader_instruction_array *instructions = &program->instructions;
1339 struct vkd3d_shader_src_param *rel_addr;
1340
1341 if (instructions->outpointid_param)
1342 return instructions->outpointid_param;
1343
1344 if (!(rel_addr = shader_src_param_allocator_get(&instructions->src_params, 1)))
1345 return NULL;
1346
1348 rel_addr->swizzle = 0;
1349 rel_addr->modifiers = 0;
1350
1351 instructions->outpointid_param = rel_addr;
1352 return rel_addr;
1353}
1354
1356 struct control_point_normaliser *normaliser)
1357{
1358 struct vkd3d_shader_register *reg = &dst_param->reg;
1359
1361 {
1362 /* The TPF reader validates idx_count. */
1363 VKD3D_ASSERT(reg->idx_count == 1);
1364 reg->idx[1] = reg->idx[0];
1365 /* The control point id param is implicit here. Avoid later complications by inserting it. */
1366 reg->idx[0].offset = 0;
1367 reg->idx[0].rel_addr = normaliser->outpointid_param;
1368 ++reg->idx_count;
1369 }
1370}
1371
1374{
1375 param->write_mask = e->mask;
1376 param->modifiers = 0;
1377 param->shift = 0;
1379}
1380
1382 const struct shader_signature *s, unsigned int input_control_point_count, unsigned int dst,
1383 const struct vkd3d_shader_location *location)
1384{
1385 struct vkd3d_shader_instruction *ins;
1387 const struct signature_element *e;
1388 unsigned int i, count;
1389
1390 for (i = 0, count = 1; i < s->element_count; ++i)
1391 count += !!s->elements[i].used_mask;
1392
1393 if (!shader_instruction_array_reserve(&normaliser->instructions, normaliser->instructions.count + count))
1395
1396 memmove(&normaliser->instructions.elements[dst + count], &normaliser->instructions.elements[dst],
1397 (normaliser->instructions.count - dst) * sizeof(*normaliser->instructions.elements));
1398 normaliser->instructions.count += count;
1399
1400 ins = &normaliser->instructions.elements[dst];
1402 ins->flags = 1;
1403 ++ins;
1404
1405 for (i = 0; i < s->element_count; ++i)
1406 {
1407 e = &s->elements[i];
1408 if (!e->used_mask)
1409 continue;
1410
1411 if (e->sysval_semantic != VKD3D_SHADER_SV_NONE)
1412 {
1415 ins->declaration.register_semantic.sysval_semantic = vkd3d_siv_from_sysval(e->sysval_semantic);
1416 }
1417 else
1418 {
1420 param = &ins->declaration.dst;
1421 }
1422
1424 param->reg.idx[0].offset = input_control_point_count;
1425 param->reg.idx[1].offset = e->register_index;
1426 param->write_mask = e->mask;
1427
1428 ++ins;
1429 }
1430
1431 return VKD3D_OK;
1432}
1433
1436{
1437 struct vkd3d_shader_instruction_array *instructions;
1438 struct control_point_normaliser normaliser;
1439 unsigned int input_control_point_count;
1441 struct vkd3d_shader_instruction *ins;
1442 enum vkd3d_result ret;
1443 unsigned int i, j;
1444
1445 VKD3D_ASSERT(program->normalisation_level == VSIR_NOT_NORMALISED);
1446
1447 if (program->shader_version.type != VKD3D_SHADER_TYPE_HULL)
1448 {
1449 program->normalisation_level = VSIR_NORMALISED_HULL_CONTROL_POINT_IO;
1450 return VKD3D_OK;
1451 }
1452
1454 {
1455 ERR("Failed to allocate src param.\n");
1457 }
1458 normaliser.instructions = program->instructions;
1459 instructions = &normaliser.instructions;
1460 normaliser.phase = VKD3DSIH_INVALID;
1461
1462 for (i = 0; i < normaliser.instructions.count; ++i)
1463 {
1464 ins = &instructions->elements[i];
1465
1466 switch (ins->opcode)
1467 {
1471 normaliser.phase = ins->opcode;
1472 break;
1473 default:
1474 if (vsir_instruction_is_dcl(ins))
1475 break;
1476 for (j = 0; j < ins->dst_count; ++j)
1477 shader_dst_param_normalise_outpointid(&ins->dst[j], &normaliser);
1478 break;
1479 }
1480 }
1481
1482 normaliser.phase = VKD3DSIH_INVALID;
1483 input_control_point_count = 1;
1484
1485 for (i = 0; i < instructions->count; ++i)
1486 {
1487 ins = &instructions->elements[i];
1488
1489 switch (ins->opcode)
1490 {
1492 input_control_point_count = ins->declaration.count;
1493 break;
1495 program->instructions = normaliser.instructions;
1496 program->normalisation_level = VSIR_NORMALISED_HULL_CONTROL_POINT_IO;
1497 return VKD3D_OK;
1500 /* ins may be relocated if the instruction array expands. */
1501 location = ins->location;
1502 ret = control_point_normaliser_emit_hs_input(&normaliser, &program->input_signature,
1503 input_control_point_count, i, &location);
1504 program->instructions = normaliser.instructions;
1505 program->normalisation_level = VSIR_NORMALISED_HULL_CONTROL_POINT_IO;
1506 return ret;
1507 default:
1508 break;
1509 }
1510 }
1511
1512 program->instructions = normaliser.instructions;
1513 program->normalisation_level = VSIR_NORMALISED_HULL_CONTROL_POINT_IO;
1514 return VKD3D_OK;
1515}
1516
1518{
1525
1526 unsigned int instance_count;
1527 unsigned int phase_body_idx;
1530
1532
1539
1541};
1542
1543static bool io_normaliser_is_in_fork_or_join_phase(const struct io_normaliser *normaliser)
1544{
1545 return normaliser->phase == VKD3DSIH_HS_FORK_PHASE || normaliser->phase == VKD3DSIH_HS_JOIN_PHASE;
1546}
1547
1548static bool io_normaliser_is_in_control_point_phase(const struct io_normaliser *normaliser)
1549{
1550 return normaliser->phase == VKD3DSIH_HS_CONTROL_POINT_PHASE;
1551}
1552
1554 unsigned int reg_idx, unsigned int write_mask, unsigned int *element_idx)
1555{
1556 const struct signature_element *e;
1557 unsigned int i;
1558
1559 for (i = 0; i < signature->element_count; ++i)
1560 {
1561 e = &signature->elements[i];
1562 if (e->register_index <= reg_idx && e->register_count > reg_idx - e->register_index
1563 && (e->mask & write_mask) == write_mask)
1564 {
1565 *element_idx = i;
1566 return true;
1567 }
1568 }
1569
1570 return false;
1571}
1572
1574 unsigned int reg_idx, unsigned int write_mask)
1575{
1576 unsigned int element_idx;
1577
1578 if (shader_signature_find_element_for_reg(signature, reg_idx, write_mask, &element_idx))
1579 return &signature->elements[element_idx];
1580
1581 return NULL;
1582}
1583
1585 unsigned int register_idx, uint32_t write_mask)
1586{
1587 return range_map[register_idx][vsir_write_mask_get_component_idx(write_mask)];
1588}
1589
1590static void range_map_set_register_range(uint8_t range_map[][VKD3D_VEC4_SIZE], unsigned int register_idx,
1591 unsigned int register_count, uint32_t write_mask, bool is_dcl_indexrange)
1592{
1593 unsigned int i, j, r, c, component_idx, component_count;
1594
1595 VKD3D_ASSERT(write_mask <= VKD3DSP_WRITEMASK_ALL);
1596 component_idx = vsir_write_mask_get_component_idx(write_mask);
1598
1599 VKD3D_ASSERT(register_idx < MAX_REG_OUTPUT && MAX_REG_OUTPUT - register_idx >= register_count);
1600
1601 if (range_map[register_idx][component_idx] > register_count && is_dcl_indexrange)
1602 {
1603 /* Validated in the TPF reader. */
1604 VKD3D_ASSERT(range_map[register_idx][component_idx] != UINT8_MAX);
1605 return;
1606 }
1607 if (range_map[register_idx][component_idx] == register_count)
1608 {
1609 /* Already done. This happens when fxc splits a register declaration by
1610 * component(s). The dcl_indexrange instructions are split too. */
1611 return;
1612 }
1613 range_map[register_idx][component_idx] = register_count;
1614
1615 for (i = 0; i < register_count; ++i)
1616 {
1617 r = register_idx + i;
1618 for (j = !i; j < component_count; ++j)
1619 {
1620 c = component_idx + j;
1621 /* A synthetic patch constant range which overlaps an existing range can start upstream of it
1622 * for fork/join phase instancing, but ranges declared by dcl_indexrange should not overlap.
1623 * The latter is validated in the TPF reader. */
1624 VKD3D_ASSERT(!range_map[r][c] || !is_dcl_indexrange);
1625 range_map[r][c] = UINT8_MAX;
1626 }
1627 }
1628}
1629
1630static void io_normaliser_add_index_range(struct io_normaliser *normaliser,
1631 const struct vkd3d_shader_instruction *ins)
1632{
1634 const struct vkd3d_shader_register *reg = &range->dst.reg;
1635 const struct shader_signature *signature;
1636 uint8_t (*range_map)[VKD3D_VEC4_SIZE];
1637 struct signature_element *element;
1638 unsigned int reg_idx, write_mask;
1639
1640 switch (reg->type)
1641 {
1642 case VKD3DSPR_INPUT:
1644 range_map = normaliser->input_range_map;
1645 signature = normaliser->input_signature;
1646 break;
1648 range_map = normaliser->output_range_map;
1649 signature = normaliser->output_signature;
1650 break;
1651 case VKD3DSPR_OUTPUT:
1653 {
1654 range_map = normaliser->output_range_map;
1655 signature = normaliser->output_signature;
1656 break;
1657 }
1658 /* fall through */
1660 range_map = normaliser->pc_range_map;
1661 signature = normaliser->patch_constant_signature;
1662 break;
1663 default:
1664 /* Validated in the TPF reader. */
1666 }
1667
1668 reg_idx = reg->idx[reg->idx_count - 1].offset;
1669 write_mask = range->dst.write_mask;
1671 range_map_set_register_range(range_map, reg_idx, range->register_count, element->mask, true);
1672}
1673
1674static int signature_element_mask_compare(const void *a, const void *b)
1675{
1676 const struct signature_element *e = a, *f = b;
1677 int ret;
1678
1679 return (ret = vkd3d_u32_compare(e->mask, f->mask)) ? ret : vkd3d_u32_compare(e->register_index, f->register_index);
1680}
1681
1683{
1684 if (e->sysval_semantic < VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE
1685 || e->sysval_semantic > VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN)
1686 return false;
1687
1688 return e->sysval_semantic == f->sysval_semantic
1689 /* Line detail and density must be merged together to match the SPIR-V array.
1690 * This deletes one of the two sysvals, but these are not used. */
1691 || (e->sysval_semantic == VKD3D_SHADER_SV_TESS_FACTOR_LINEDET
1692 && f->sysval_semantic == VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN)
1693 || (e->sysval_semantic == VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN
1694 && f->sysval_semantic == VKD3D_SHADER_SV_TESS_FACTOR_LINEDET);
1695}
1696
1697/* Merge tess factor sysvals because they are an array in SPIR-V. */
1699 uint8_t range_map[][VKD3D_VEC4_SIZE])
1700{
1701 struct signature_element *e, *f;
1702 unsigned int i, j, register_count;
1703
1704 qsort(s->elements, s->element_count, sizeof(s->elements[0]), signature_element_mask_compare);
1705
1706 for (i = 0; i < s->element_count; i += register_count)
1707 {
1708 e = &s->elements[i];
1709 register_count = 1;
1710
1711 if (!e->sysval_semantic)
1712 continue;
1713
1714 for (j = i + 1; j < s->element_count; ++j, ++register_count)
1715 {
1716 f = &s->elements[j];
1717 if (f->register_index != e->register_index + register_count || !sysval_semantics_should_merge(e, f))
1718 break;
1719 }
1720 if (register_count < 2)
1721 continue;
1722
1723 range_map_set_register_range(range_map, e->register_index, register_count, e->mask, false);
1724 }
1725}
1726
1727static int signature_element_register_compare(const void *a, const void *b)
1728{
1729 const struct signature_element *e = a, *f = b;
1730 int ret;
1731
1732 if ((ret = vkd3d_u32_compare(e->register_index, f->register_index)))
1733 return ret;
1734
1735 /* System values like SV_RenderTargetArrayIndex and SV_ViewPortArrayIndex
1736 * can get packed into the same I/O register as non-system values, but
1737 * only at the end. E.g.:
1738 *
1739 * vs_4_0
1740 * ...
1741 * .output
1742 * ...
1743 * .param B.x, o1.x, uint
1744 * .param C.y, o1.y, uint
1745 * .param SV_RenderTargetArrayIndex.z, o1.z, uint, RTINDEX
1746 * .text
1747 * ...
1748 * mov o1.xy, v1.xyxx
1749 * mov o1.z, v1.z
1750 * ret
1751 *
1752 * Because I/O normalisation doesn't split writes like the mov to o1.xy
1753 * above, we want to make sure that o1.x and o1.y continue to be packed
1754 * into a single register after I/O normalisation, so we order system
1755 * values after non-system values here, allowing the non-system values to
1756 * get merged into a single register. */
1757 return vkd3d_u32_compare(f->sysval_semantic, e->sysval_semantic);
1758}
1759
1760static int signature_element_index_compare(const void *a, const void *b)
1761{
1762 const struct signature_element *e = a, *f = b;
1763
1764 return vkd3d_u32_compare(e->sort_index, f->sort_index);
1765}
1766
1768 uint8_t range_map[][VKD3D_VEC4_SIZE])
1769{
1770 unsigned int i, j, component_idx, component_count, merged_write_mask = e->mask;
1771
1772 /* dcl_indexrange instructions can declare a subset of the full mask, and the masks of
1773 * the elements within the range may differ. TPF's handling of arrayed inputs with
1774 * dcl_indexrange is really just a hack. Here we create a mask which covers all element
1775 * masks, and check for collisions with other ranges. */
1776
1777 for (i = 1; i < register_count; ++i)
1778 merged_write_mask |= e[i].mask;
1779
1780 if (merged_write_mask == e->mask)
1781 return merged_write_mask;
1782
1783 /* Reaching this point is very rare to begin with, and collisions are even rarer or
1784 * impossible. If the latter shows up, the fallback in shader_signature_find_element_for_reg()
1785 * may be sufficient. */
1786
1787 component_idx = vsir_write_mask_get_component_idx(e->mask);
1789
1790 for (i = e->register_index; i < e->register_index + register_count; ++i)
1791 {
1792 for (j = 0; j < component_idx; ++j)
1793 if (range_map[i][j])
1794 break;
1795 for (j = component_idx + component_count; j < VKD3D_VEC4_SIZE; ++j)
1796 if (range_map[i][j])
1797 break;
1798 }
1799
1800 if (i == register_count)
1801 {
1802 WARN("Expanding mask %#x to %#x for %s, base reg %u, count %u.\n", e->mask, merged_write_mask,
1803 e->semantic_name, e->register_index, register_count);
1804 return merged_write_mask;
1805 }
1806
1807 WARN("Cannot expand mask %#x to %#x for %s, base reg %u, count %u.\n", e->mask, merged_write_mask,
1808 e->semantic_name, e->register_index, register_count);
1809 return e->mask;
1810}
1811
1813 bool is_patch_constant)
1814{
1815 unsigned int i, j, element_count, new_count, register_count;
1816 struct signature_element *elements;
1817 struct signature_element *e, *f;
1818 bool used;
1819
1820 element_count = s->element_count;
1821 if (!(elements = vkd3d_malloc(element_count * sizeof(*elements))))
1822 return false;
1823 memcpy(elements, s->elements, element_count * sizeof(*elements));
1824
1825 for (i = 0; i < element_count; ++i)
1826 elements[i].sort_index = i;
1827
1828 qsort(elements, element_count, sizeof(elements[0]), signature_element_register_compare);
1829
1830 for (i = 0, new_count = 0; i < element_count; i = j, elements[new_count++] = *e)
1831 {
1832 e = &elements[i];
1833 j = i + 1;
1834
1835 if (e->register_index == ~0u)
1836 continue;
1837
1838 /* Do not merge if the register index will be relative-addressed. */
1839 if (range_map_get_register_count(range_map, e->register_index, e->mask) > 1)
1840 continue;
1841
1842 used = e->used_mask;
1843
1844 for (; j < element_count; ++j)
1845 {
1846 f = &elements[j];
1847
1848 /* Merge different components of the same register unless sysvals are different,
1849 * or it will be relative-addressed. */
1850 if (f->register_index != e->register_index || f->sysval_semantic != e->sysval_semantic
1851 || range_map_get_register_count(range_map, f->register_index, f->mask) > 1)
1852 break;
1853
1854 TRACE("Merging %s, reg %u, mask %#x, sysval %#x with %s, mask %#x, sysval %#x.\n", e->semantic_name,
1855 e->register_index, e->mask, e->sysval_semantic, f->semantic_name, f->mask, f->sysval_semantic);
1856 VKD3D_ASSERT(!(e->mask & f->mask));
1857
1858 e->mask |= f->mask;
1859 e->used_mask |= f->used_mask;
1860 e->semantic_index = min(e->semantic_index, f->semantic_index);
1861
1862 /* The first element may have no interpolation mode if it is unused. Elements which
1863 * actually have different interpolation modes are assigned different registers. */
1864 if (f->used_mask && !used)
1865 {
1866 if (e->interpolation_mode && e->interpolation_mode != f->interpolation_mode)
1867 FIXME("Mismatching interpolation modes %u and %u.\n", e->interpolation_mode, f->interpolation_mode);
1868 else
1869 e->interpolation_mode = f->interpolation_mode;
1870 }
1871
1872 vkd3d_free((void *)f->semantic_name);
1873 }
1874 }
1875 element_count = new_count;
1876 vkd3d_free(s->elements);
1877 s->elements = elements;
1878 s->element_count = element_count;
1879
1880 if (is_patch_constant)
1882
1883 for (i = 0, new_count = 0; i < element_count; i += register_count, elements[new_count++] = *e)
1884 {
1885 e = &elements[i];
1886 register_count = 1;
1887
1888 if (e->register_index >= MAX_REG_OUTPUT)
1889 continue;
1890
1891 register_count = range_map_get_register_count(range_map, e->register_index, e->mask);
1894
1895 if (register_count > 1)
1896 {
1897 TRACE("Merging %s, base reg %u, count %u.\n", e->semantic_name, e->register_index, register_count);
1898 e->register_count = register_count;
1900
1901 for (j = 1; j < register_count; ++j)
1902 {
1903 f = &elements[i + j];
1904 vkd3d_free((void *)f->semantic_name);
1905 }
1906 }
1907 }
1908 element_count = new_count;
1909
1910 /* Restoring the original order is required for sensible trace output. */
1911 qsort(elements, element_count, sizeof(elements[0]), signature_element_index_compare);
1912
1913 s->element_count = element_count;
1914
1915 return true;
1916}
1917
1919 unsigned int id_idx, unsigned int register_index)
1920{
1921 VKD3D_ASSERT(id_idx < ARRAY_SIZE(reg->idx) - 1);
1922
1923 /* For a relative-addressed register index, move the id up a slot to separate it from the address,
1924 * because rel_addr can be replaced with a constant offset in some cases. */
1925 if (reg->idx[id_idx].rel_addr)
1926 {
1927 reg->idx[id_idx + 1].rel_addr = NULL;
1928 reg->idx[id_idx + 1].offset = reg->idx[id_idx].offset;
1929 reg->idx[id_idx].offset -= register_index;
1930 if (id_idx)
1931 {
1932 /* idx[id_idx] now contains the array index, which must be moved below the control point id. */
1933 struct vkd3d_shader_register_index tmp = reg->idx[id_idx];
1934 reg->idx[id_idx] = reg->idx[id_idx - 1];
1935 reg->idx[id_idx - 1] = tmp;
1936 }
1937 ++id_idx;
1938 }
1939 /* Otherwise we have no address for the arrayed register, so insert one. This happens e.g. where
1940 * tessellation level registers are merged into an array because they're an array in SPIR-V. */
1941 else
1942 {
1943 ++id_idx;
1944 memmove(&reg->idx[1], &reg->idx[0], id_idx * sizeof(reg->idx[0]));
1945 reg->idx[0].rel_addr = NULL;
1946 reg->idx[0].offset = reg->idx[id_idx].offset - register_index;
1947 }
1948
1949 return id_idx;
1950}
1951
1952static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_param, bool is_io_dcl,
1953 struct io_normaliser *normaliser)
1954 {
1955 unsigned int id_idx, reg_idx, write_mask, element_idx;
1956 struct vkd3d_shader_register *reg = &dst_param->reg;
1957 struct vkd3d_shader_dst_param **dcl_params;
1958 const struct shader_signature *signature;
1959 const struct signature_element *e;
1960
1961 write_mask = dst_param->write_mask;
1962
1963 switch (reg->type)
1964 {
1965 case VKD3DSPR_OUTPUT:
1966 reg_idx = reg->idx[reg->idx_count - 1].offset;
1968 {
1969 signature = normaliser->patch_constant_signature;
1970 /* Convert patch constant outputs to the patch constant register type to avoid the need
1971 * to convert compiler symbols when accessed as inputs in a later stage. */
1972 reg->type = VKD3DSPR_PATCHCONST;
1973 dcl_params = normaliser->pc_dcl_params;
1974 }
1975 else
1976 {
1977 signature = normaliser->output_signature;
1978 dcl_params = normaliser->output_dcl_params;
1979 }
1980 break;
1981
1983 reg_idx = reg->idx[reg->idx_count - 1].offset;
1984 signature = normaliser->patch_constant_signature;
1985 dcl_params = normaliser->pc_dcl_params;
1986 break;
1987
1988 case VKD3DSPR_COLOROUT:
1989 reg_idx = reg->idx[0].offset;
1990 signature = normaliser->output_signature;
1991 reg->type = VKD3DSPR_OUTPUT;
1992 dcl_params = normaliser->output_dcl_params;
1993 break;
1994
1996 case VKD3DSPR_INPUT:
1997 reg_idx = reg->idx[reg->idx_count - 1].offset;
1998 signature = normaliser->input_signature;
1999 reg->type = VKD3DSPR_INPUT;
2000 dcl_params = normaliser->input_dcl_params;
2001 break;
2002
2003 case VKD3DSPR_ATTROUT:
2004 reg_idx = SM1_COLOR_REGISTER_OFFSET + reg->idx[0].offset;
2005 signature = normaliser->output_signature;
2006 reg->type = VKD3DSPR_OUTPUT;
2007 dcl_params = normaliser->output_dcl_params;
2008 break;
2009
2010 case VKD3DSPR_RASTOUT:
2011 /* Leave point size as a system value for the backends to consume. */
2012 if (reg->idx[0].offset == VSIR_RASTOUT_POINT_SIZE)
2013 return true;
2014 reg_idx = SM1_RASTOUT_REGISTER_OFFSET + reg->idx[0].offset;
2015 signature = normaliser->output_signature;
2016 reg->type = VKD3DSPR_OUTPUT;
2017 dcl_params = normaliser->output_dcl_params;
2018 /* Fog and point size are scalar, but fxc/d3dcompiler emits a full
2019 * write mask when writing to them. */
2020 if (reg->idx[0].offset > 0)
2021 write_mask = VKD3DSP_WRITEMASK_0;
2022 break;
2023
2024 default:
2025 return true;
2026 }
2027
2028 id_idx = reg->idx_count - 1;
2029 if (!shader_signature_find_element_for_reg(signature, reg_idx, write_mask, &element_idx))
2031 e = &signature->elements[element_idx];
2032
2033 if (is_io_dcl)
2034 {
2035 /* Validated in the TPF reader. */
2036 VKD3D_ASSERT(element_idx < ARRAY_SIZE(normaliser->input_dcl_params));
2037
2038 if (dcl_params[element_idx])
2039 {
2040 /* Merge split declarations into a single one. */
2041 dcl_params[element_idx]->write_mask |= dst_param->write_mask;
2042 /* Turn this into a nop. */
2043 return false;
2044 }
2045 else
2046 {
2047 dcl_params[element_idx] = dst_param;
2048 }
2049 }
2050
2052 {
2053 if (is_io_dcl)
2054 {
2055 /* Emit an array size for the control points for consistency with inputs. */
2056 reg->idx[0].offset = normaliser->output_control_point_count;
2057 }
2058 else
2059 {
2060 /* The control point id param. */
2061 VKD3D_ASSERT(reg->idx[0].rel_addr);
2062 }
2063 id_idx = 1;
2064 }
2065
2066 if ((e->register_count > 1 || vsir_sysval_semantic_is_tess_factor(e->sysval_semantic)))
2067 {
2068 if (is_io_dcl)
2069 {
2070 /* For control point I/O, idx 0 contains the control point count.
2071 * Ensure it is moved up to the next slot. */
2072 reg->idx[id_idx].offset = reg->idx[0].offset;
2073 reg->idx[0].offset = e->register_count;
2074 ++id_idx;
2075 }
2076 else
2077 {
2078 id_idx = shader_register_normalise_arrayed_addressing(reg, id_idx, e->register_index);
2079 }
2080 }
2081
2082 /* Replace the register index with the signature element index */
2083 reg->idx[id_idx].offset = element_idx;
2084 reg->idx_count = id_idx + 1;
2085
2086 return true;
2087}
2088
2090 struct io_normaliser *normaliser)
2091{
2092 unsigned int i, id_idx, reg_idx, write_mask, element_idx, component_idx;
2093 struct vkd3d_shader_register *reg = &src_param->reg;
2094 const struct shader_signature *signature;
2095 const struct signature_element *e;
2096
2097 /* Input/output registers from one phase can be used as inputs in
2098 * subsequent phases. Specifically:
2099 *
2100 * - Control phase inputs are available as "vicp" in fork and join
2101 * phases.
2102 * - Control phase outputs are available as "vocp" in fork and join
2103 * phases.
2104 * - Fork phase patch constants are available as "vpc" in join
2105 * phases.
2106 *
2107 * We handle "vicp" here by converting INCONTROLPOINT src registers to
2108 * type INPUT so they match the control phase declarations. We handle
2109 * "vocp" by converting OUTCONTROLPOINT registers to type OUTPUT.
2110 * Merging fork and join phases handles "vpc". */
2111
2112 switch (reg->type)
2113 {
2115 reg_idx = reg->idx[reg->idx_count - 1].offset;
2116 signature = normaliser->patch_constant_signature;
2117 break;
2118
2120 reg->type = VKD3DSPR_INPUT;
2121 /* fall through */
2122 case VKD3DSPR_INPUT:
2123 if (normaliser->major < 3 && normaliser->shader_type == VKD3D_SHADER_TYPE_PIXEL)
2124 reg_idx = SM1_COLOR_REGISTER_OFFSET + reg->idx[0].offset;
2125 else
2126 reg_idx = reg->idx[reg->idx_count - 1].offset;
2127 signature = normaliser->input_signature;
2128 break;
2129
2131 reg->type = VKD3DSPR_OUTPUT;
2132 /* fall through */
2133 case VKD3DSPR_OUTPUT:
2134 reg_idx = reg->idx[reg->idx_count - 1].offset;
2135 signature = normaliser->output_signature;
2136 break;
2137
2138 case VKD3DSPR_TEXTURE:
2139 if (normaliser->shader_type != VKD3D_SHADER_TYPE_PIXEL)
2140 return;
2141 reg->type = VKD3DSPR_INPUT;
2142 reg_idx = reg->idx[0].offset;
2143 signature = normaliser->input_signature;
2144 break;
2145
2146 default:
2147 return;
2148 }
2149
2150 id_idx = reg->idx_count - 1;
2151 write_mask = VKD3DSP_WRITEMASK_0 << vsir_swizzle_get_component(src_param->swizzle, 0);
2152 if (!shader_signature_find_element_for_reg(signature, reg_idx, write_mask, &element_idx))
2154
2155 e = &signature->elements[element_idx];
2156 if ((e->register_count > 1 || vsir_sysval_semantic_is_tess_factor(e->sysval_semantic)))
2157 id_idx = shader_register_normalise_arrayed_addressing(reg, id_idx, e->register_index);
2158 reg->idx[id_idx].offset = element_idx;
2159 reg->idx_count = id_idx + 1;
2160
2161 if ((component_idx = vsir_write_mask_get_component_idx(e->mask)))
2162 {
2163 for (i = 0; i < VKD3D_VEC4_SIZE; ++i)
2164 if (vsir_swizzle_get_component(src_param->swizzle, i))
2165 src_param->swizzle -= component_idx << VKD3D_SHADER_SWIZZLE_SHIFT(i);
2166 }
2167}
2168
2170 struct io_normaliser *normaliser)
2171{
2172 struct vkd3d_shader_register *reg;
2173 unsigned int i;
2174
2175 switch (ins->opcode)
2176 {
2177 case VKD3DSIH_DCL_INPUT:
2178 if (normaliser->shader_type == VKD3D_SHADER_TYPE_HULL)
2179 {
2180 reg = &ins->declaration.dst.reg;
2181
2182 if (reg->type == VKD3DSPR_OUTCONTROLPOINT)
2183 normaliser->use_vocp = true;
2184
2185 /* We don't need to keep OUTCONTROLPOINT or PATCHCONST input declarations since their
2186 * equivalents were declared earlier, but INCONTROLPOINT may be the first occurrence. */
2187 if (reg->type == VKD3DSPR_OUTCONTROLPOINT || reg->type == VKD3DSPR_PATCHCONST)
2189 else if (reg->type == VKD3DSPR_INCONTROLPOINT)
2190 reg->type = VKD3DSPR_INPUT;
2191 }
2192 /* fall through */
2195 if (!shader_dst_param_io_normalise(&ins->declaration.dst, true, normaliser))
2197 break;
2203 if (!shader_dst_param_io_normalise(&ins->declaration.register_semantic.reg, true, normaliser))
2205 break;
2209 normaliser->phase = ins->opcode;
2210 memset(normaliser->input_dcl_params, 0, sizeof(normaliser->input_dcl_params));
2211 memset(normaliser->output_dcl_params, 0, sizeof(normaliser->output_dcl_params));
2212 memset(normaliser->pc_dcl_params, 0, sizeof(normaliser->pc_dcl_params));
2213 break;
2214 default:
2215 if (vsir_instruction_is_dcl(ins))
2216 break;
2217 for (i = 0; i < ins->dst_count; ++i)
2218 shader_dst_param_io_normalise(&ins->dst[i], false, normaliser);
2219 for (i = 0; i < ins->src_count; ++i)
2220 shader_src_param_io_normalise(&ins->src[i], normaliser);
2221 break;
2222 }
2223}
2224
2227{
2228 struct io_normaliser normaliser = {program->instructions};
2229 struct vkd3d_shader_instruction *ins;
2230 unsigned int i;
2231
2233
2234 normaliser.phase = VKD3DSIH_INVALID;
2235 normaliser.shader_type = program->shader_version.type;
2236 normaliser.major = program->shader_version.major;
2237 normaliser.input_signature = &program->input_signature;
2238 normaliser.output_signature = &program->output_signature;
2239 normaliser.patch_constant_signature = &program->patch_constant_signature;
2240
2241 for (i = 0; i < program->instructions.count; ++i)
2242 {
2243 ins = &program->instructions.elements[i];
2244
2245 switch (ins->opcode)
2246 {
2249 break;
2251 io_normaliser_add_index_range(&normaliser, ins);
2253 break;
2257 normaliser.phase = ins->opcode;
2258 break;
2259 default:
2260 break;
2261 }
2262 }
2263
2264 if (!shader_signature_merge(&program->input_signature, normaliser.input_range_map, false)
2265 || !shader_signature_merge(&program->output_signature, normaliser.output_range_map, false)
2266 || !shader_signature_merge(&program->patch_constant_signature, normaliser.pc_range_map, true))
2267 {
2268 program->instructions = normaliser.instructions;
2270 }
2271
2272 normaliser.phase = VKD3DSIH_INVALID;
2273 for (i = 0; i < normaliser.instructions.count; ++i)
2274 shader_instruction_normalise_io_params(&normaliser.instructions.elements[i], &normaliser);
2275
2276 program->instructions = normaliser.instructions;
2277 program->use_vocp = normaliser.use_vocp;
2278 program->normalisation_level = VSIR_FULLY_NORMALISED_IO;
2279 return VKD3D_OK;
2280}
2281
2283{
2287};
2288
2290{
2293};
2294
2297{
2298 static const struct
2299 {
2303 }
2304 regs[] =
2305 {
2312 };
2313
2314 unsigned int i;
2315
2316 for (i = 0; i < ARRAY_SIZE(regs); ++i)
2317 {
2318 if (reg->type == regs[i].type)
2319 {
2320 if (reg->idx[0].rel_addr)
2321 {
2322 FIXME("Unhandled relative address.\n");
2323 return false;
2324 }
2325
2326 *set = regs[i].set;
2327 *index = regs[i].offset + reg->idx[0].offset;
2328 return true;
2329 }
2330 }
2331
2332 return false;
2333}
2334
2336 const struct flat_constants_normaliser *normaliser)
2337{
2340 size_t i, j;
2341
2343 return;
2344
2345 for (i = 0; i < normaliser->def_count; ++i)
2346 {
2347 if (normaliser->defs[i].set == set && normaliser->defs[i].index == index)
2348 {
2349 param->reg.type = VKD3DSPR_IMMCONST;
2350 param->reg.idx_count = 0;
2351 param->reg.dimension = VSIR_DIMENSION_VEC4;
2352 for (j = 0; j < 4; ++j)
2353 param->reg.u.immconst_u32[j] = normaliser->defs[i].value[j];
2354 return;
2355 }
2356 }
2357
2358 param->reg.type = VKD3DSPR_CONSTBUFFER;
2359 param->reg.idx[0].offset = set; /* register ID */
2360 param->reg.idx[1].offset = set; /* register index */
2361 param->reg.idx[2].offset = index; /* buffer index */
2362 param->reg.idx_count = 3;
2363}
2364
2367{
2368 struct flat_constants_normaliser normaliser = {0};
2369 unsigned int i, j;
2370
2371 for (i = 0; i < program->instructions.count; ++i)
2372 {
2373 struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
2374
2375 if (ins->opcode == VKD3DSIH_DEF || ins->opcode == VKD3DSIH_DEFI || ins->opcode == VKD3DSIH_DEFB)
2376 {
2377 struct flat_constant_def *def;
2378
2379 if (!vkd3d_array_reserve((void **)&normaliser.defs, &normaliser.defs_capacity,
2380 normaliser.def_count + 1, sizeof(*normaliser.defs)))
2381 {
2382 vkd3d_free(normaliser.defs);
2384 }
2385
2386 def = &normaliser.defs[normaliser.def_count++];
2387
2388 get_flat_constant_register_type((struct vkd3d_shader_register *)&ins->dst[0].reg, &def->set, &def->index);
2389 for (j = 0; j < 4; ++j)
2390 def->value[j] = ins->src[0].reg.u.immconst_u32[j];
2391
2393 }
2394 else
2395 {
2396 for (j = 0; j < ins->src_count; ++j)
2397 shader_register_normalise_flat_constants(&ins->src[j], &normaliser);
2398 }
2399 }
2400
2401 vkd3d_free(normaliser.defs);
2402 return VKD3D_OK;
2403}
2404
2407{
2408 size_t i, depth = 0;
2409 bool dead = false;
2410
2411 for (i = 0; i < program->instructions.count; ++i)
2412 {
2413 struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
2414
2415 switch (ins->opcode)
2416 {
2417 case VKD3DSIH_IF:
2418 case VKD3DSIH_LOOP:
2419 case VKD3DSIH_SWITCH:
2420 if (dead)
2421 {
2423 ++depth;
2424 }
2425 break;
2426
2427 case VKD3DSIH_ENDIF:
2428 case VKD3DSIH_ENDLOOP:
2429 case VKD3DSIH_ENDSWITCH:
2430 case VKD3DSIH_ELSE:
2431 if (dead)
2432 {
2433 if (depth > 0)
2434 {
2435 if (ins->opcode != VKD3DSIH_ELSE)
2436 --depth;
2438 }
2439 else
2440 {
2441 dead = false;
2442 }
2443 }
2444 break;
2445
2446 /* `depth' is counted with respect to where the dead code
2447 * segment began. So it starts at zero and it signals the
2448 * termination of the dead code segment when it would
2449 * become negative. */
2450 case VKD3DSIH_BREAK:
2451 case VKD3DSIH_RET:
2452 case VKD3DSIH_CONTINUE:
2453 if (dead)
2454 {
2456 }
2457 else
2458 {
2459 dead = true;
2460 depth = 0;
2461 }
2462 break;
2463
2464 /* If `case' or `default' appears at zero depth, it means
2465 * that they are a possible target for the corresponding
2466 * switch, so the code is live again. */
2467 case VKD3DSIH_CASE:
2468 case VKD3DSIH_DEFAULT:
2469 if (dead)
2470 {
2471 if (depth == 0)
2472 dead = false;
2473 else
2475 }
2476 break;
2477
2478 /* Phase instructions can only appear in hull shaders and
2479 * outside of any block. When a phase returns, control is
2480 * moved to the following phase, so they make code live
2481 * again. */
2485 dead = false;
2486 break;
2487
2488 default:
2489 if (dead)
2491 break;
2492 }
2493 }
2494
2495 return VKD3D_OK;
2496}
2497
2499{
2501 unsigned int id;
2503 unsigned int else_block_id;
2504};
2505
2507{
2508 unsigned int header_block_id;
2509 unsigned int continue_block_id;
2511};
2512
2514{
2515 unsigned int value;
2516 unsigned int block_id;
2517};
2518
2520{
2523 unsigned int id;
2524 unsigned int merge_block_id;
2525 unsigned int default_block_id;
2528 unsigned int cases_count;
2529};
2530
2532{
2533 union
2534 {
2538 } u;
2539
2540 enum
2541 {
2547};
2548
2550{
2552
2555
2559
2560 unsigned int block_id;
2561 const char **block_names;
2564
2565 unsigned int branch_id;
2566 unsigned int loop_id;
2567 unsigned int switch_id;
2568
2572};
2573
2574static void cf_flattener_set_error(struct cf_flattener *flattener, enum vkd3d_result error)
2575{
2576 if (flattener->status != VKD3D_OK)
2577 return;
2578 flattener->status = error;
2579}
2580
2582{
2583 if (!vkd3d_array_reserve((void **)&flattener->instructions, &flattener->instruction_capacity,
2584 flattener->instruction_count + count, sizeof(*flattener->instructions)))
2585 {
2586 ERR("Failed to allocate instructions.\n");
2588 return NULL;
2589 }
2590 return &flattener->instructions[flattener->instruction_count];
2591}
2592
2593static bool cf_flattener_copy_instruction(struct cf_flattener *flattener,
2595{
2596 struct vkd3d_shader_instruction *dst_ins;
2597
2599 return true;
2600
2601 if (!(dst_ins = cf_flattener_require_space(flattener, 1)))
2602 return false;
2603
2604 *dst_ins = *instruction;
2605 ++flattener->instruction_count;
2606 return true;
2607}
2608
2609static unsigned int cf_flattener_alloc_block_id(struct cf_flattener *flattener)
2610{
2611 return ++flattener->block_id;
2612}
2613
2615 unsigned int count, struct cf_flattener *flattener)
2616{
2618
2619 if (!(params = vsir_program_get_src_params(flattener->program, count)))
2620 {
2622 return NULL;
2623 }
2624 ins->src = params;
2625 ins->src_count = count;
2626 return params;
2627}
2628
2629static void cf_flattener_emit_label(struct cf_flattener *flattener, unsigned int label_id)
2630{
2631 struct vkd3d_shader_instruction *ins;
2632
2633 if (!(ins = cf_flattener_require_space(flattener, 1)))
2634 return;
2635 if (vsir_instruction_init_label(ins, &flattener->location, label_id, flattener->program))
2636 ++flattener->instruction_count;
2637 else
2639}
2640
2641/* For conditional branches, this returns the false target branch parameter. */
2643 unsigned int merge_block_id, unsigned int continue_block_id,
2644 const struct vkd3d_shader_src_param *condition, unsigned int true_id, unsigned int false_id,
2645 unsigned int flags)
2646{
2647 struct vkd3d_shader_src_param *src_params, *false_branch_param;
2648 struct vkd3d_shader_instruction *ins;
2649
2650 if (!(ins = cf_flattener_require_space(flattener, 1)))
2651 return NULL;
2653
2654 if (condition)
2655 {
2656 if (!(src_params = instruction_src_params_alloc(ins, 4 + !!continue_block_id, flattener)))
2657 return NULL;
2658 src_params[0] = *condition;
2660 {
2661 vsir_src_param_init_label(&src_params[1], false_id);
2662 vsir_src_param_init_label(&src_params[2], true_id);
2663 false_branch_param = &src_params[1];
2664 }
2665 else
2666 {
2667 vsir_src_param_init_label(&src_params[1], true_id);
2668 vsir_src_param_init_label(&src_params[2], false_id);
2669 false_branch_param = &src_params[2];
2670 }
2671 vsir_src_param_init_label(&src_params[3], merge_block_id);
2672 if (continue_block_id)
2673 vsir_src_param_init_label(&src_params[4], continue_block_id);
2674 }
2675 else
2676 {
2677 if (!(src_params = instruction_src_params_alloc(ins, merge_block_id ? 3 : 1, flattener)))
2678 return NULL;
2679 vsir_src_param_init_label(&src_params[0], true_id);
2680 if (merge_block_id)
2681 {
2682 /* An unconditional branch may only have merge information for a loop, which
2683 * must have both a merge block and continue block. */
2684 vsir_src_param_init_label(&src_params[1], merge_block_id);
2685 vsir_src_param_init_label(&src_params[2], continue_block_id);
2686 }
2687 false_branch_param = NULL;
2688 }
2689
2690 ++flattener->instruction_count;
2691
2692 return false_branch_param;
2693}
2694
2696 const struct vkd3d_shader_src_param *condition, unsigned int true_id, unsigned int flags)
2697{
2698 unsigned int merge_block_id;
2699
2700 merge_block_id = cf_flattener_alloc_block_id(flattener);
2701 cf_flattener_emit_branch(flattener, merge_block_id, 0, condition, true_id, merge_block_id, flags);
2702 cf_flattener_emit_label(flattener, merge_block_id);
2703}
2704
2705static void cf_flattener_emit_unconditional_branch(struct cf_flattener *flattener, unsigned int target_block_id)
2706{
2707 cf_flattener_emit_branch(flattener, 0, 0, NULL, target_block_id, 0, 0);
2708}
2709
2711{
2712 if (!vkd3d_array_reserve((void **)&flattener->control_flow_info, &flattener->control_flow_info_size,
2713 flattener->control_flow_depth + 1, sizeof(*flattener->control_flow_info)))
2714 {
2715 ERR("Failed to allocate control flow info structure.\n");
2717 return NULL;
2718 }
2719
2720 return &flattener->control_flow_info[flattener->control_flow_depth++];
2721}
2722
2724{
2725 struct cf_flattener_info *cf_info;
2726
2727 cf_info = &flattener->control_flow_info[--flattener->control_flow_depth];
2728 memset(cf_info, 0, sizeof(*cf_info));
2729}
2730
2732{
2733 int depth;
2734
2735 for (depth = flattener->control_flow_depth - 1; depth >= 0; --depth)
2736 {
2737 if (flattener->control_flow_info[depth].current_block == VKD3D_BLOCK_LOOP)
2738 return &flattener->control_flow_info[depth];
2739 }
2740
2741 return NULL;
2742}
2743
2745{
2746 int depth;
2747
2748 for (depth = flattener->control_flow_depth - 1; depth >= 0; --depth)
2749 {
2750 if (flattener->control_flow_info[depth].current_block == VKD3D_BLOCK_LOOP
2751 || flattener->control_flow_info[depth].current_block == VKD3D_BLOCK_SWITCH)
2752 return &flattener->control_flow_info[depth];
2753 }
2754
2755 return NULL;
2756}
2757
2758static void VKD3D_PRINTF_FUNC(3, 4) cf_flattener_create_block_name(struct cf_flattener *flattener,
2759 unsigned int block_id, const char *fmt, ...)
2760{
2762 size_t block_name_count;
2763 va_list args;
2764
2765 --block_id;
2766
2767 block_name_count = max(flattener->block_name_count, block_id + 1);
2768 if (!vkd3d_array_reserve((void **)&flattener->block_names, &flattener->block_name_capacity,
2769 block_name_count, sizeof(*flattener->block_names)))
2770 return;
2771 memset(&flattener->block_names[flattener->block_name_count], 0,
2772 (block_name_count - flattener->block_name_count) * sizeof(*flattener->block_names));
2773 flattener->block_name_count = block_name_count;
2774
2776 va_start(args, fmt);
2778 va_end(args);
2779
2780 flattener->block_names[block_id] = buffer.buffer;
2781}
2782
2784 struct vkd3d_shader_message_context *message_context)
2785{
2786 struct vkd3d_shader_instruction_array *instructions;
2787 struct vsir_program *program = flattener->program;
2788 bool is_hull_shader, after_declarations_section;
2789 struct vkd3d_shader_instruction *dst_ins;
2790 size_t i;
2791
2792 instructions = &program->instructions;
2793 is_hull_shader = program->shader_version.type == VKD3D_SHADER_TYPE_HULL;
2794 after_declarations_section = is_hull_shader;
2795
2796 if (!cf_flattener_require_space(flattener, instructions->count + 1))
2798
2799 for (i = 0; i < instructions->count; ++i)
2800 {
2801 unsigned int loop_header_block_id, loop_body_block_id, continue_block_id, merge_block_id, true_block_id;
2802 const struct vkd3d_shader_instruction *instruction = &instructions->elements[i];
2803 const struct vkd3d_shader_src_param *src = instruction->src;
2804 struct cf_flattener_info *cf_info;
2805
2806 flattener->location = instruction->location;
2807
2808 /* Declarations should occur before the first code block, which in hull shaders is marked by the first
2809 * phase instruction, and in all other shader types begins with the first label instruction.
2810 * Declaring an indexable temp with function scope is not considered a declaration,
2811 * because it needs to live inside a function. */
2812 if (!after_declarations_section && instruction->opcode != VKD3DSIH_NOP)
2813 {
2814 bool is_function_indexable = instruction->opcode == VKD3DSIH_DCL_INDEXABLE_TEMP
2815 && instruction->declaration.indexable_temp.has_function_scope;
2816
2817 if (!vsir_instruction_is_dcl(instruction) || is_function_indexable)
2818 {
2819 after_declarations_section = true;
2821 }
2822 }
2823
2824 cf_info = flattener->control_flow_depth
2825 ? &flattener->control_flow_info[flattener->control_flow_depth - 1] : NULL;
2826
2827 switch (instruction->opcode)
2828 {
2835 after_declarations_section = false;
2836 break;
2837
2838 case VKD3DSIH_LABEL:
2839 vkd3d_shader_error(message_context, &instruction->location,
2841 "Aborting due to not yet implemented feature: Label instruction.");
2843
2844 case VKD3DSIH_IF:
2845 if (!(cf_info = cf_flattener_push_control_flow_level(flattener)))
2847
2848 true_block_id = cf_flattener_alloc_block_id(flattener);
2849 merge_block_id = cf_flattener_alloc_block_id(flattener);
2850 cf_info->u.if_.false_param = cf_flattener_emit_branch(flattener, merge_block_id, 0,
2851 src, true_block_id, merge_block_id, instruction->flags);
2852 if (!cf_info->u.if_.false_param)
2854
2855 cf_flattener_emit_label(flattener, true_block_id);
2856
2857 cf_info->u.if_.id = flattener->branch_id;
2858 cf_info->u.if_.merge_block_id = merge_block_id;
2859 cf_info->u.if_.else_block_id = 0;
2860 cf_info->inside_block = true;
2861 cf_info->current_block = VKD3D_BLOCK_IF;
2862
2863 cf_flattener_create_block_name(flattener, merge_block_id, "branch%u_merge", flattener->branch_id);
2864 cf_flattener_create_block_name(flattener, true_block_id, "branch%u_true", flattener->branch_id);
2865 ++flattener->branch_id;
2866 break;
2867
2868 case VKD3DSIH_ELSE:
2869 if (cf_info->inside_block)
2870 cf_flattener_emit_unconditional_branch(flattener, cf_info->u.if_.merge_block_id);
2871
2872 cf_info->u.if_.else_block_id = cf_flattener_alloc_block_id(flattener);
2873 cf_info->u.if_.false_param->reg.idx[0].offset = cf_info->u.if_.else_block_id;
2874
2875 cf_flattener_create_block_name(flattener,
2876 cf_info->u.if_.else_block_id, "branch%u_false", cf_info->u.if_.id);
2877 cf_flattener_emit_label(flattener, cf_info->u.if_.else_block_id);
2878
2879 cf_info->inside_block = true;
2880 break;
2881
2882 case VKD3DSIH_ENDIF:
2883 if (cf_info->inside_block)
2884 cf_flattener_emit_unconditional_branch(flattener, cf_info->u.if_.merge_block_id);
2885
2886 cf_flattener_emit_label(flattener, cf_info->u.if_.merge_block_id);
2887
2889 break;
2890
2891 case VKD3DSIH_LOOP:
2892 if (!(cf_info = cf_flattener_push_control_flow_level(flattener)))
2894
2895 loop_header_block_id = cf_flattener_alloc_block_id(flattener);
2896 loop_body_block_id = cf_flattener_alloc_block_id(flattener);
2897 continue_block_id = cf_flattener_alloc_block_id(flattener);
2898 merge_block_id = cf_flattener_alloc_block_id(flattener);
2899
2900 cf_flattener_emit_unconditional_branch(flattener, loop_header_block_id);
2901 cf_flattener_emit_label(flattener, loop_header_block_id);
2902 cf_flattener_emit_branch(flattener, merge_block_id, continue_block_id,
2903 NULL, loop_body_block_id, 0, 0);
2904
2905 cf_flattener_emit_label(flattener, loop_body_block_id);
2906
2907 cf_info->u.loop.header_block_id = loop_header_block_id;
2908 cf_info->u.loop.continue_block_id = continue_block_id;
2909 cf_info->u.loop.merge_block_id = merge_block_id;
2911 cf_info->inside_block = true;
2912
2913 cf_flattener_create_block_name(flattener, loop_header_block_id, "loop%u_header", flattener->loop_id);
2914 cf_flattener_create_block_name(flattener, loop_body_block_id, "loop%u_body", flattener->loop_id);
2915 cf_flattener_create_block_name(flattener, continue_block_id, "loop%u_continue", flattener->loop_id);
2916 cf_flattener_create_block_name(flattener, merge_block_id, "loop%u_merge", flattener->loop_id);
2917 ++flattener->loop_id;
2918 break;
2919
2920 case VKD3DSIH_ENDLOOP:
2921 if (cf_info->inside_block)
2922 cf_flattener_emit_unconditional_branch(flattener, cf_info->u.loop.continue_block_id);
2923
2924 cf_flattener_emit_label(flattener, cf_info->u.loop.continue_block_id);
2925 cf_flattener_emit_unconditional_branch(flattener, cf_info->u.loop.header_block_id);
2926 cf_flattener_emit_label(flattener, cf_info->u.loop.merge_block_id);
2927
2929 break;
2930
2931 case VKD3DSIH_SWITCH:
2932 if (!(cf_info = cf_flattener_push_control_flow_level(flattener)))
2934
2935 merge_block_id = cf_flattener_alloc_block_id(flattener);
2936
2937 cf_info->u.switch_.ins_location = flattener->instruction_count;
2938 cf_info->u.switch_.condition = src;
2939
2940 if (!(dst_ins = cf_flattener_require_space(flattener, 1)))
2943 ++flattener->instruction_count;
2944
2945 cf_info->u.switch_.id = flattener->switch_id;
2946 cf_info->u.switch_.merge_block_id = merge_block_id;
2947 cf_info->u.switch_.cases = NULL;
2948 cf_info->u.switch_.cases_size = 0;
2949 cf_info->u.switch_.cases_count = 0;
2950 cf_info->u.switch_.default_block_id = 0;
2951 cf_info->inside_block = false;
2953
2954 cf_flattener_create_block_name(flattener, merge_block_id, "switch%u_merge", flattener->switch_id);
2955 ++flattener->switch_id;
2956
2957 if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.cases, &cf_info->u.switch_.cases_size,
2958 10, sizeof(*cf_info->u.switch_.cases)))
2960
2961 break;
2962
2963 case VKD3DSIH_ENDSWITCH:
2964 {
2965 struct vkd3d_shader_src_param *src_params;
2966 unsigned int j;
2967
2968 if (!cf_info->u.switch_.default_block_id)
2969 cf_info->u.switch_.default_block_id = cf_info->u.switch_.merge_block_id;
2970
2971 cf_flattener_emit_label(flattener, cf_info->u.switch_.merge_block_id);
2972
2973 /* The SWITCH instruction is completed when the endswitch
2974 * instruction is processed because we do not know the number
2975 * of case statements or the default block id in advance.*/
2976 dst_ins = &flattener->instructions[cf_info->u.switch_.ins_location];
2977 if (!(src_params = instruction_src_params_alloc(dst_ins, cf_info->u.switch_.cases_count * 2 + 3, flattener)))
2978 {
2979 vkd3d_free(cf_info->u.switch_.cases);
2981 }
2982 src_params[0] = *cf_info->u.switch_.condition;
2983 vsir_src_param_init_label(&src_params[1], cf_info->u.switch_.default_block_id);
2984 vsir_src_param_init_label(&src_params[2], cf_info->u.switch_.merge_block_id);
2985 for (j = 0; j < cf_info->u.switch_.cases_count; ++j)
2986 {
2987 unsigned int index = j * 2 + 3;
2989 src_params[index].reg.u.immconst_u32[0] = cf_info->u.switch_.cases[j].value;
2990 vsir_src_param_init_label(&src_params[index + 1], cf_info->u.switch_.cases[j].block_id);
2991 }
2992 vkd3d_free(cf_info->u.switch_.cases);
2993
2995 break;
2996 }
2997
2998 case VKD3DSIH_CASE:
2999 {
3000 unsigned int label_id, value;
3001
3002 if (src->swizzle != VKD3D_SHADER_SWIZZLE(X, X, X, X))
3003 {
3004 WARN("Unexpected src swizzle %#x.\n", src->swizzle);
3005 vkd3d_shader_error(message_context, &instruction->location,
3007 "The swizzle for a switch case value is not scalar X.");
3009 }
3010 value = *src->reg.u.immconst_u32;
3011
3012 if (!vkd3d_array_reserve((void **)&cf_info->u.switch_.cases, &cf_info->u.switch_.cases_size,
3013 cf_info->u.switch_.cases_count + 1, sizeof(*cf_info->u.switch_.cases)))
3015
3016 label_id = cf_flattener_alloc_block_id(flattener);
3017 if (cf_info->inside_block) /* fall-through */
3018 cf_flattener_emit_unconditional_branch(flattener, label_id);
3019
3020 cf_info->u.switch_.cases[cf_info->u.switch_.cases_count].value = value;
3021 cf_info->u.switch_.cases[cf_info->u.switch_.cases_count].block_id = label_id;
3022 ++cf_info->u.switch_.cases_count;
3023
3024 cf_flattener_emit_label(flattener, label_id);
3025 cf_flattener_create_block_name(flattener, label_id, "switch%u_case%u", cf_info->u.switch_.id, value);
3026 cf_info->inside_block = true;
3027 break;
3028 }
3029
3030 case VKD3DSIH_DEFAULT:
3031 cf_info->u.switch_.default_block_id = cf_flattener_alloc_block_id(flattener);
3032 if (cf_info->inside_block) /* fall-through */
3033 cf_flattener_emit_unconditional_branch(flattener, cf_info->u.switch_.default_block_id);
3034
3035 cf_flattener_emit_label(flattener, cf_info->u.switch_.default_block_id);
3036
3037 cf_flattener_create_block_name(flattener, cf_info->u.switch_.default_block_id,
3038 "switch%u_default", cf_info->u.switch_.id);
3039 cf_info->inside_block = true;
3040 break;
3041
3042 case VKD3DSIH_BREAK:
3043 {
3044 struct cf_flattener_info *breakable_cf_info;
3045
3046 if (!(breakable_cf_info = cf_flattener_find_innermost_breakable_cf_construct(flattener)))
3047 {
3048 FIXME("Unhandled break instruction.\n");
3050 }
3051
3052 if (breakable_cf_info->current_block == VKD3D_BLOCK_LOOP)
3053 {
3054 cf_flattener_emit_unconditional_branch(flattener, breakable_cf_info->u.loop.merge_block_id);
3055 }
3056 else if (breakable_cf_info->current_block == VKD3D_BLOCK_SWITCH)
3057 {
3058 cf_flattener_emit_unconditional_branch(flattener, breakable_cf_info->u.switch_.merge_block_id);
3059 }
3060
3061 cf_info->inside_block = false;
3062 break;
3063 }
3064
3065 case VKD3DSIH_BREAKP:
3066 {
3067 struct cf_flattener_info *loop_cf_info;
3068
3069 if (!(loop_cf_info = cf_flattener_find_innermost_loop(flattener)))
3070 {
3071 ERR("Invalid 'breakc' instruction outside loop.\n");
3073 }
3074
3076 src, loop_cf_info->u.loop.merge_block_id, instruction->flags);
3077 break;
3078 }
3079
3080 case VKD3DSIH_CONTINUE:
3081 {
3082 struct cf_flattener_info *loop_cf_info;
3083
3084 if (!(loop_cf_info = cf_flattener_find_innermost_loop(flattener)))
3085 {
3086 ERR("Invalid 'continue' instruction outside loop.\n");
3088 }
3089
3090 cf_flattener_emit_unconditional_branch(flattener, loop_cf_info->u.loop.continue_block_id);
3091
3092 cf_info->inside_block = false;
3093 break;
3094 }
3095
3096 case VKD3DSIH_CONTINUEP:
3097 {
3098 struct cf_flattener_info *loop_cf_info;
3099
3100 if (!(loop_cf_info = cf_flattener_find_innermost_loop(flattener)))
3101 {
3102 ERR("Invalid 'continuec' instruction outside loop.\n");
3104 }
3105
3107 src, loop_cf_info->u.loop.continue_block_id, instruction->flags);
3108 break;
3109 }
3110
3111 case VKD3DSIH_RET:
3114
3115 if (cf_info)
3116 cf_info->inside_block = false;
3117 break;
3118
3119 default:
3122 break;
3123 }
3124 }
3125
3126 return flattener->status;
3127}
3128
3131{
3132 struct vkd3d_shader_message_context *message_context = ctx->message_context;
3133 struct cf_flattener flattener = {.program = program};
3134 enum vkd3d_result result;
3135
3137
3138 if ((result = cf_flattener_iterate_instruction_array(&flattener, message_context)) >= 0)
3139 {
3140 vkd3d_free(program->instructions.elements);
3141 program->instructions.elements = flattener.instructions;
3142 program->instructions.capacity = flattener.instruction_capacity;
3143 program->instructions.count = flattener.instruction_count;
3144 program->block_count = flattener.block_id;
3145 program->cf_type = VSIR_CF_BLOCKS;
3146 }
3147 else
3148 {
3149 vkd3d_free(flattener.instructions);
3150 }
3151
3152 vkd3d_free(flattener.control_flow_info);
3153 /* Simpler to always free these in vsir_program_cleanup(). */
3154 program->block_names = flattener.block_names;
3155 program->block_name_count = flattener.block_name_count;
3156
3157 return result;
3158}
3159
3160static unsigned int label_from_src_param(const struct vkd3d_shader_src_param *param)
3161{
3162 VKD3D_ASSERT(param->reg.type == VKD3DSPR_LABEL);
3163 return param->reg.idx[0].offset;
3164}
3165
3166static bool reserve_instructions(struct vkd3d_shader_instruction **instructions, size_t *capacity, size_t count)
3167{
3168 if (!vkd3d_array_reserve((void **)instructions, capacity, count, sizeof(**instructions)))
3169 {
3170 ERR("Failed to allocate instructions.\n");
3171 return false;
3172 }
3173
3174 return true;
3175}
3176
3177/* A record represents replacing a jump from block `switch_label' to
3178 * block `target_label' with a jump from block `if_label' to block
3179 * `target_label'. */
3181{
3182 unsigned int switch_label;
3183 unsigned int if_label;
3184 unsigned int target_label;
3185};
3186
3188 size_t *map_capacity, size_t *map_count, unsigned int switch_label, unsigned int if_label, unsigned int target_label)
3189{
3190 if (!vkd3d_array_reserve((void **)block_map, map_capacity, *map_count + 1, sizeof(**block_map)))
3191 {
3192 ERR("Failed to allocate block mapping.\n");
3193 return false;
3194 }
3195
3196 (*block_map)[*map_count].switch_label = switch_label;
3197 (*block_map)[*map_count].if_label = if_label;
3198 (*block_map)[*map_count].target_label = target_label;
3199
3200 *map_count += 1;
3201
3202 return true;
3203}
3204
3207{
3208 unsigned int block_count = program->block_count, ssa_count = program->ssa_count, current_label = 0, if_label;
3209 size_t ins_capacity = 0, ins_count = 0, i, map_capacity = 0, map_count = 0;
3210 struct vkd3d_shader_instruction *instructions = NULL;
3212
3213 VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS);
3214
3215 if (!reserve_instructions(&instructions, &ins_capacity, program->instructions.count))
3216 goto fail;
3217
3218 /* First subpass: convert SWITCH_MONOLITHIC instructions to
3219 * selection ladders, keeping a map between blocks before and
3220 * after the subpass. */
3221 for (i = 0; i < program->instructions.count; ++i)
3222 {
3223 struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
3224 unsigned int case_count, j, default_label;
3225
3226 switch (ins->opcode)
3227 {
3228 case VKD3DSIH_LABEL:
3229 current_label = label_from_src_param(&ins->src[0]);
3230 if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1))
3231 goto fail;
3232 instructions[ins_count++] = *ins;
3233 continue;
3234
3236 break;
3237
3238 default:
3239 if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1))
3240 goto fail;
3241 instructions[ins_count++] = *ins;
3242 continue;
3243 }
3244
3245 case_count = (ins->src_count - 3) / 2;
3246 default_label = label_from_src_param(&ins->src[1]);
3247
3248 /* In principle we can have a switch with no cases, and we
3249 * just have to jump to the default label. */
3250 if (case_count == 0)
3251 {
3252 if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 1))
3253 goto fail;
3254
3255 if (!vsir_instruction_init_with_params(program, &instructions[ins_count],
3256 &ins->location, VKD3DSIH_BRANCH, 0, 1))
3257 goto fail;
3258 vsir_src_param_init_label(&instructions[ins_count].src[0], default_label);
3259 ++ins_count;
3260 }
3261
3262 if (!reserve_instructions(&instructions, &ins_capacity, ins_count + 3 * case_count - 1))
3263 goto fail;
3264
3265 if_label = current_label;
3266
3267 for (j = 0; j < case_count; ++j)
3268 {
3269 unsigned int fallthrough_label, case_label = label_from_src_param(&ins->src[3 + 2 * j + 1]);
3270
3272 &instructions[ins_count], &ins->location, VKD3DSIH_IEQ, 1, 2))
3273 goto fail;
3274 dst_param_init_ssa_bool(&instructions[ins_count].dst[0], ssa_count);
3275 instructions[ins_count].src[0] = ins->src[0];
3276 instructions[ins_count].src[1] = ins->src[3 + 2 * j];
3277 ++ins_count;
3278
3279 /* For all cases except the last one we fall through to
3280 * the following case; the last one has to jump to the
3281 * default label. */
3282 if (j == case_count - 1)
3283 fallthrough_label = default_label;
3284 else
3285 fallthrough_label = block_count + 1;
3286
3287 if (!vsir_instruction_init_with_params(program, &instructions[ins_count],
3288 &ins->location, VKD3DSIH_BRANCH, 0, 3))
3289 goto fail;
3290 src_param_init_ssa_bool(&instructions[ins_count].src[0], ssa_count);
3291 vsir_src_param_init_label(&instructions[ins_count].src[1], case_label);
3292 vsir_src_param_init_label(&instructions[ins_count].src[2], fallthrough_label);
3293 ++ins_count;
3294
3295 ++ssa_count;
3296
3297 if (!lower_switch_to_if_ladder_add_block_mapping(&block_map, &map_capacity, &map_count,
3298 current_label, if_label, case_label))
3299 goto fail;
3300
3301 if (j == case_count - 1)
3302 {
3303 if (!lower_switch_to_if_ladder_add_block_mapping(&block_map, &map_capacity, &map_count,
3304 current_label, if_label, default_label))
3305 goto fail;
3306 }
3307 else
3308 {
3310 &instructions[ins_count], &ins->location, VKD3DSIH_LABEL, 0, 1))
3311 goto fail;
3312 vsir_src_param_init_label(&instructions[ins_count].src[0], ++block_count);
3313 ++ins_count;
3314
3315 if_label = block_count;
3316 }
3317 }
3318 }
3319
3320 vkd3d_free(program->instructions.elements);
3321 vkd3d_free(block_map);
3322 program->instructions.elements = instructions;
3323 program->instructions.capacity = ins_capacity;
3324 program->instructions.count = ins_count;
3325 program->block_count = block_count;
3326 program->ssa_count = ssa_count;
3327
3328 return VKD3D_OK;
3329
3330fail:
3331 vkd3d_free(instructions);
3332 vkd3d_free(block_map);
3333
3335}
3336
3338{
3339 unsigned int *table;
3340 unsigned int next_temp_idx;
3341};
3342
3343static bool ssas_to_temps_alloc_init(struct ssas_to_temps_alloc *alloc, unsigned int ssa_count, unsigned int temp_count)
3344{
3345 size_t i = ssa_count * sizeof(*alloc->table);
3346
3347 if (!(alloc->table = vkd3d_malloc(i)))
3348 {
3349 ERR("Failed to allocate SSA table.\n");
3350 return false;
3351 }
3352 memset(alloc->table, 0xff, i);
3353
3354 alloc->next_temp_idx = temp_count;
3355 return true;
3356}
3357
3358/* This is idempotent: it can be safely applied more than once on the
3359 * same register. */
3361 struct vkd3d_shader_register *reg)
3362{
3363 unsigned int i;
3364
3365 if (reg->type == VKD3DSPR_SSA && alloc->table[reg->idx[0].offset] != UINT_MAX)
3366 {
3367 reg->type = VKD3DSPR_TEMP;
3368 reg->idx[0].offset = alloc->table[reg->idx[0].offset];
3369 }
3370
3371 for (i = 0; i < reg->idx_count; ++i)
3372 if (reg->idx[i].rel_addr)
3374}
3375
3377{
3379 {
3385};
3386
3388 size_t count)
3389{
3390 size_t i;
3391
3392 for (i = 0; i < count; ++i)
3393 vkd3d_free(block_info[i].incomings);
3394
3395 vkd3d_free(block_info);
3396}
3397
3400{
3401 size_t ins_capacity = 0, ins_count = 0, phi_count, incoming_count, i;
3402 struct ssas_to_temps_block_info *info, *block_info = NULL;
3403 struct vkd3d_shader_instruction *instructions = NULL;
3404 struct ssas_to_temps_alloc alloc = {0};
3405 unsigned int current_label = 0;
3406
3407 VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS);
3408
3409 if (!(block_info = vkd3d_calloc(program->block_count, sizeof(*block_info))))
3410 {
3411 ERR("Failed to allocate block info array.\n");
3412 goto fail;
3413 }
3414
3415 if (!ssas_to_temps_alloc_init(&alloc, program->ssa_count, program->temp_count))
3416 goto fail;
3417
3418 for (i = 0, phi_count = 0, incoming_count = 0; i < program->instructions.count; ++i)
3419 {
3420 struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
3421 unsigned int j, temp_idx;
3422
3423 /* Only phi src/dst SSA values need be converted here. Structurisation may
3424 * introduce new cases of undominated SSA use, which will be handled later. */
3425 if (ins->opcode != VKD3DSIH_PHI)
3426 continue;
3427 ++phi_count;
3428
3429 temp_idx = alloc.next_temp_idx++;
3430
3431 for (j = 0; j < ins->src_count; j += 2)
3432 {
3433 struct phi_incoming_to_temp *incoming;
3434 unsigned int label;
3435
3436 label = label_from_src_param(&ins->src[j + 1]);
3438
3439 info = &block_info[label - 1];
3440
3441 if (!(vkd3d_array_reserve((void **)&info->incomings, &info->incoming_capacity, info->incoming_count + 1,
3442 sizeof(*info->incomings))))
3443 goto fail;
3444
3445 incoming = &info->incomings[info->incoming_count++];
3446 incoming->src = &ins->src[j];
3447 incoming->dst = ins->dst;
3448
3449 alloc.table[ins->dst->reg.idx[0].offset] = temp_idx;
3450
3451 ++incoming_count;
3452 }
3453
3455 }
3456
3457 if (!phi_count)
3458 goto done;
3459
3460 if (!reserve_instructions(&instructions, &ins_capacity, program->instructions.count + incoming_count - phi_count))
3461 goto fail;
3462
3463 for (i = 0; i < program->instructions.count; ++i)
3464 {
3465 struct vkd3d_shader_instruction *mov_ins, *ins = &program->instructions.elements[i];
3466 size_t j;
3467
3468 for (j = 0; j < ins->dst_count; ++j)
3470
3471 for (j = 0; j < ins->src_count; ++j)
3473
3474 switch (ins->opcode)
3475 {
3476 case VKD3DSIH_LABEL:
3477 current_label = label_from_src_param(&ins->src[0]);
3478 break;
3479
3480 case VKD3DSIH_BRANCH:
3482 info = &block_info[current_label - 1];
3483
3484 for (j = 0; j < info->incoming_count; ++j)
3485 {
3486 struct phi_incoming_to_temp *incoming = &info->incomings[j];
3487
3488 mov_ins = &instructions[ins_count++];
3490 goto fail;
3491 *mov_ins->dst = *incoming->dst;
3492 mov_ins->src = incoming->src;
3493 mov_ins->src_count = 1;
3494 }
3495 break;
3496
3497 case VKD3DSIH_PHI:
3498 continue;
3499
3500 default:
3501 break;
3502 }
3503
3504 instructions[ins_count++] = *ins;
3505 }
3506
3507 vkd3d_free(program->instructions.elements);
3508 program->instructions.elements = instructions;
3509 program->instructions.capacity = ins_capacity;
3510 program->instructions.count = ins_count;
3511 program->temp_count = alloc.next_temp_idx;
3512done:
3513 ssas_to_temps_block_info_cleanup(block_info, program->block_count);
3514 vkd3d_free(alloc.table);
3515
3516 return VKD3D_OK;
3517
3518fail:
3519 vkd3d_free(instructions);
3520 ssas_to_temps_block_info_cleanup(block_info, program->block_count);
3521 vkd3d_free(alloc.table);
3522
3524}
3525
3527{
3530};
3531
3533{
3534 memset(list, 0, sizeof(*list));
3535}
3536
3538{
3539 vkd3d_free(list->blocks);
3540}
3541
3543{
3544 if (!vkd3d_array_reserve((void **)&list->blocks, &list->capacity, list->count + 1, sizeof(*list->blocks)))
3545 {
3546 ERR("Cannot extend block list.\n");
3548 }
3549
3550 list->blocks[list->count++] = block;
3551
3552 return VKD3D_OK;
3553}
3554
3556{
3557 size_t i;
3558
3559 for (i = 0; i < list->count; ++i)
3560 if (block == list->blocks[i])
3561 return VKD3D_FALSE;
3562
3564}
3565
3566/* It is guaranteed that the relative order is kept. */
3568{
3569 --list->count;
3570 memmove(&list->blocks[idx], &list->blocks[idx + 1], (list->count - idx) * sizeof(*list->blocks));
3571}
3572
3574{
3575 unsigned int label, order_pos;
3576 /* `begin' points to the instruction immediately following the
3577 * LABEL that introduces the block. `end' points to the terminator
3578 * instruction (either BRANCH or RET). They can coincide, meaning
3579 * that the block is empty. */
3581 struct vsir_block_list predecessors, successors;
3583};
3584
3585static enum vkd3d_result vsir_block_init(struct vsir_block *block, unsigned int label, size_t block_count)
3586{
3587 size_t byte_count;
3588
3589 if (block_count > SIZE_MAX - (sizeof(*block->dominates) * CHAR_BIT - 1))
3591
3592 byte_count = VKD3D_BITMAP_SIZE(block_count) * sizeof(*block->dominates);
3593
3595 memset(block, 0, sizeof(*block));
3596 block->label = label;
3597 vsir_block_list_init(&block->predecessors);
3598 vsir_block_list_init(&block->successors);
3599
3600 if (!(block->dominates = vkd3d_malloc(byte_count)))
3602
3603 memset(block->dominates, 0xff, byte_count);
3604
3605 return VKD3D_OK;
3606}
3607
3609{
3610 if (block->label == 0)
3611 return;
3612 vsir_block_list_cleanup(&block->predecessors);
3613 vsir_block_list_cleanup(&block->successors);
3614 vkd3d_free(block->dominates);
3615}
3616
3617static int block_compare(const void *ptr1, const void *ptr2)
3618{
3619 const struct vsir_block *block1 = *(const struct vsir_block **)ptr1;
3620 const struct vsir_block *block2 = *(const struct vsir_block **)ptr2;
3621
3622 return vkd3d_u32_compare(block1->label, block2->label);
3623}
3624
3626{
3627 qsort(list->blocks, list->count, sizeof(*list->blocks), block_compare);
3628}
3629
3631{
3632 return !!bsearch(&block, list->blocks, list->count, sizeof(*list->blocks), block_compare);
3633}
3634
3636{
3639 unsigned int end;
3640};
3641
3643{
3645 {
3646 /* Execute a block of the original VSIR program. */
3648 /* Execute a loop, which is identified by an index. */
3650 /* Execute a selection construct. */
3652 /* Execute a `return' or a (possibly) multilevel `break' or
3653 * `continue', targeting a loop by its index. If `condition'
3654 * is non-NULL, then the jump is conditional (this is
3655 * currently not allowed for `return'). */
3658 union
3659 {
3661 struct vsir_cfg_structure_loop
3662 {
3664 unsigned idx;
3668 struct vsir_cfg_structure_selection
3669 {
3672 struct vsir_cfg_structure_list else_body;
3675 struct vsir_cfg_structure_jump
3676 {
3677 enum vsir_cfg_jump_type
3678 {
3679 /* NONE is available as an intermediate value, but it
3680 * is not allowed in valid structured programs. */
3686 unsigned int target;
3688 bool invert_condition;
3691 } u;
3692};
3693
3694static void vsir_cfg_structure_init(struct vsir_cfg_structure *structure, enum vsir_cfg_structure_type type);
3695static void vsir_cfg_structure_cleanup(struct vsir_cfg_structure *structure);
3696
3698{
3699 unsigned int i;
3700
3701 for (i = 0; i < list->count; ++i)
3702 vsir_cfg_structure_cleanup(&list->structures[i]);
3703 vkd3d_free(list->structures);
3704}
3705
3708{
3709 struct vsir_cfg_structure *ret;
3710
3711 if (!vkd3d_array_reserve((void **)&list->structures, &list->capacity, list->count + 1,
3712 sizeof(*list->structures)))
3713 return NULL;
3714
3715 ret = &list->structures[list->count++];
3716
3718
3719 return ret;
3720}
3721
3723 struct vsir_cfg_structure *begin, size_t size)
3724{
3725 if (!vkd3d_array_reserve((void **)&list->structures, &list->capacity, list->count + size,
3726 sizeof(*list->structures)))
3728
3729 memcpy(&list->structures[list->count], begin, size * sizeof(*begin));
3730
3731 list->count += size;
3732
3733 return VKD3D_OK;
3734}
3735
3737{
3738 memset(structure, 0, sizeof(*structure));
3739 structure->type = type;
3740}
3741
3743{
3744 switch (structure->type)
3745 {
3747 vsir_cfg_structure_list_cleanup(&structure->u.loop.body);
3748 break;
3749
3751 vsir_cfg_structure_list_cleanup(&structure->u.selection.if_body);
3752 vsir_cfg_structure_list_cleanup(&structure->u.selection.else_body);
3753 break;
3754
3755 default:
3756 break;
3757 }
3758}
3759
3761{
3765 unsigned int temp_count;
3766};
3767
3769{
3778
3782
3785 {
3786 /* `begin' is the position of the first block of the loop in
3787 * the topological sort; `end' is the position of the first
3788 * block after the loop. In other words, `begin' is where a
3789 * `continue' instruction would jump and `end' is where a
3790 * `break' instruction would jump. */
3791 unsigned int begin, end;
3792 /* Each loop interval can be natural or synthetic. Natural
3793 * intervals are added to represent loops given by CFG back
3794 * edges. Synthetic intervals do not correspond to loops in
3795 * the input CFG, but are added to leverage their `break'
3796 * instruction in order to execute forward edges.
3797 *
3798 * For a synthetic loop interval it's not really important
3799 * which one is the `begin' block, since we don't need to
3800 * execute `continue' for them. So we have some leeway for
3801 * moving it provided that these conditions are met: 1. the
3802 * interval must contain all `break' instructions that target
3803 * it, which in practice means that `begin' can be moved
3804 * backward and not forward; 2. intervals must remain properly
3805 * nested (for each pair of intervals, either one contains the
3806 * other or they are disjoint).
3807 *
3808 * Subject to these conditions, we try to reuse the same loop
3809 * as much as possible (if many forward edges target the same
3810 * block), but we still try to keep `begin' as forward as
3811 * possible, to keep the loop scope as small as possible. */
3813 /* The number of jump instructions (both conditional and
3814 * unconditional) that target this loop. */
3815 unsigned int target_count;
3818
3820
3822};
3823
3824static void vsir_cfg_cleanup(struct vsir_cfg *cfg)
3825{
3826 size_t i;
3827
3828 for (i = 0; i < cfg->block_count; ++i)
3829 vsir_block_cleanup(&cfg->blocks[i]);
3830
3831 for (i = 0; i < cfg->loops_count; ++i)
3833
3835
3837
3838 vkd3d_free(cfg->blocks);
3839 vkd3d_free(cfg->loops);
3842
3843 if (TRACE_ON())
3845}
3846
3847static enum vkd3d_result vsir_cfg_add_loop_interval(struct vsir_cfg *cfg, unsigned int begin,
3848 unsigned int end, bool synthetic)
3849{
3850 struct cfg_loop_interval *interval;
3851
3853 cfg->loop_interval_count + 1, sizeof(*cfg->loop_intervals)))
3855
3857
3858 interval->begin = begin;
3859 interval->end = end;
3860 interval->synthetic = synthetic;
3861 interval->target_count = 0;
3862
3863 return VKD3D_OK;
3864}
3865
3866static bool vsir_block_dominates(struct vsir_block *b1, struct vsir_block *b2)
3867{
3868 return bitmap_is_set(b1->dominates, b2->label - 1);
3869}
3870
3871static enum vkd3d_result vsir_cfg_add_edge(struct vsir_cfg *cfg, struct vsir_block *block,
3872 struct vkd3d_shader_src_param *successor_param)
3873{
3874 unsigned int target = label_from_src_param(successor_param);
3875 struct vsir_block *successor = &cfg->blocks[target - 1];
3876 enum vkd3d_result ret;
3877
3878 VKD3D_ASSERT(successor->label != 0);
3879
3880 if ((ret = vsir_block_list_add(&block->successors, successor)) < 0)
3881 return ret;
3882
3883 if ((ret = vsir_block_list_add(&successor->predecessors, block)) < 0)
3884 return ret;
3885
3886 return VKD3D_OK;
3887}
3888
3889static void vsir_cfg_dump_dot(struct vsir_cfg *cfg)
3890{
3891 size_t i, j;
3892
3893 TRACE("digraph cfg {\n");
3894
3895 for (i = 0; i < cfg->block_count; ++i)
3896 {
3897 struct vsir_block *block = &cfg->blocks[i];
3898 const char *shape;
3899
3900 if (block->label == 0)
3901 continue;
3902
3903 switch (block->end->opcode)
3904 {
3905 case VKD3DSIH_RET:
3906 shape = "trapezium";
3907 break;
3908
3909 case VKD3DSIH_BRANCH:
3910 shape = vsir_register_is_label(&block->end->src[0].reg) ? "ellipse" : "box";
3911 break;
3912
3913 default:
3915 }
3916
3917 TRACE(" n%u [label=\"%u\", shape=\"%s\"];\n", block->label, block->label, shape);
3918
3919 for (j = 0; j < block->successors.count; ++j)
3920 TRACE(" n%u -> n%u;\n", block->label, block->successors.blocks[j]->label);
3921 }
3922
3923 TRACE("}\n");
3924}
3925
3926static void vsir_cfg_structure_list_dump(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list);
3927
3928static void vsir_cfg_structure_dump(struct vsir_cfg *cfg, struct vsir_cfg_structure *structure)
3929{
3930 switch (structure->type)
3931 {
3932 case STRUCTURE_TYPE_BLOCK:
3933 TRACE("%sblock %u\n", cfg->debug_buffer.buffer, structure->u.block->label);
3934 break;
3935
3936 case STRUCTURE_TYPE_LOOP:
3937 TRACE("%s%u : loop {\n", cfg->debug_buffer.buffer, structure->u.loop.idx);
3938
3939 vsir_cfg_structure_list_dump(cfg, &structure->u.loop.body);
3940
3941 TRACE("%s} # %u%s\n", cfg->debug_buffer.buffer, structure->u.loop.idx,
3942 structure->u.loop.needs_trampoline ? ", tramp" : "");
3943 break;
3944
3945 case STRUCTURE_TYPE_SELECTION:
3946 TRACE("%sif {\n", cfg->debug_buffer.buffer);
3947
3948 vsir_cfg_structure_list_dump(cfg, &structure->u.selection.if_body);
3949
3950 if (structure->u.selection.else_body.count == 0)
3951 {
3952 TRACE("%s}\n", cfg->debug_buffer.buffer);
3953 }
3954 else
3955 {
3956 TRACE("%s} else {\n", cfg->debug_buffer.buffer);
3957
3958 vsir_cfg_structure_list_dump(cfg, &structure->u.selection.else_body);
3959
3960 TRACE("%s}\n", cfg->debug_buffer.buffer);
3961 }
3962 break;
3963
3964 case STRUCTURE_TYPE_JUMP:
3965 {
3966 const char *type_str;
3967
3968 switch (structure->u.jump.type)
3969 {
3970 case JUMP_RET:
3971 TRACE("%sret\n", cfg->debug_buffer.buffer);
3972 return;
3973
3974 case JUMP_BREAK:
3975 type_str = "break";
3976 break;
3977
3978 case JUMP_CONTINUE:
3979 type_str = "continue";
3980 break;
3981
3982 default:
3984 }
3985
3986 TRACE("%s%s%s %u%s\n", cfg->debug_buffer.buffer, type_str,
3987 structure->u.jump.condition ? "c" : "", structure->u.jump.target,
3988 structure->u.jump.needs_launcher ? " # launch" : "");
3989 break;
3990 }
3991
3992 default:
3994 }
3995}
3996
3998{
3999 unsigned int i;
4000
4002
4003 for (i = 0; i < list->count; ++i)
4004 vsir_cfg_structure_dump(cfg, &list->structures[i]);
4005
4006 vkd3d_string_buffer_truncate(&cfg->debug_buffer, cfg->debug_buffer.content_size - 2);
4007}
4008
4010{
4011 unsigned int i;
4012
4013 for (i = 0; i < cfg->structured_program.count; ++i)
4014 vsir_cfg_structure_dump(cfg, &cfg->structured_program.structures[i]);
4015}
4016
4017static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program *program,
4018 struct vkd3d_shader_message_context *message_context, struct vsir_cfg_emit_target *target,
4019 size_t *pos)
4020{
4021 struct vsir_block *current_block = NULL;
4022 enum vkd3d_result ret;
4023 size_t i;
4024
4025 memset(cfg, 0, sizeof(*cfg));
4026 cfg->message_context = message_context;
4027 cfg->program = program;
4028 cfg->block_count = program->block_count;
4029 cfg->target = target;
4030 cfg->function_begin = *pos;
4031
4033
4034 if (!(cfg->blocks = vkd3d_calloc(cfg->block_count, sizeof(*cfg->blocks))))
4036
4037 if (TRACE_ON())
4039
4040 for (i = *pos; i < program->instructions.count; ++i)
4041 {
4042 struct vkd3d_shader_instruction *instruction = &program->instructions.elements[i];
4043 bool finish = false;
4044
4045 switch (instruction->opcode)
4046 {
4047 case VKD3DSIH_PHI:
4050
4051 case VKD3DSIH_LABEL:
4052 {
4053 unsigned int label = label_from_src_param(&instruction->src[0]);
4054
4055 VKD3D_ASSERT(!current_block);
4056 VKD3D_ASSERT(label > 0);
4057 VKD3D_ASSERT(label <= cfg->block_count);
4058 current_block = &cfg->blocks[label - 1];
4059 VKD3D_ASSERT(current_block->label == 0);
4060 if ((ret = vsir_block_init(current_block, label, program->block_count)) < 0)
4061 goto fail;
4062 current_block->begin = &program->instructions.elements[i + 1];
4063 if (!cfg->entry)
4064 cfg->entry = current_block;
4065 break;
4066 }
4067
4068 case VKD3DSIH_BRANCH:
4069 case VKD3DSIH_RET:
4070 VKD3D_ASSERT(current_block);
4071 current_block->end = instruction;
4072 current_block = NULL;
4073 break;
4074
4078 VKD3D_ASSERT(!current_block);
4079 finish = true;
4080 break;
4081
4082 default:
4083 break;
4084 }
4085
4086 if (finish)
4087 break;
4088 }
4089
4090 *pos = i;
4091 cfg->function_end = *pos;
4092
4093 for (i = 0; i < cfg->block_count; ++i)
4094 {
4095 struct vsir_block *block = &cfg->blocks[i];
4096
4097 if (block->label == 0)
4098 continue;
4099
4100 switch (block->end->opcode)
4101 {
4102 case VKD3DSIH_RET:
4103 break;
4104
4105 case VKD3DSIH_BRANCH:
4106 if (vsir_register_is_label(&block->end->src[0].reg))
4107 {
4108 if ((ret = vsir_cfg_add_edge(cfg, block, &block->end->src[0])) < 0)
4109 goto fail;
4110 }
4111 else
4112 {
4113 if ((ret = vsir_cfg_add_edge(cfg, block, &block->end->src[1])) < 0)
4114 goto fail;
4115
4116 if ((ret = vsir_cfg_add_edge(cfg, block, &block->end->src[2])) < 0)
4117 goto fail;
4118 }
4119 break;
4120
4121 default:
4123 }
4124 }
4125
4126 if (TRACE_ON())
4127 vsir_cfg_dump_dot(cfg);
4128
4129 return VKD3D_OK;
4130
4131fail:
4132 vsir_cfg_cleanup(cfg);
4133
4134 return ret;
4135}
4136
4137/* Block A dominates block B if every path from the entry point to B
4138 * must pass through A. Naively compute the set of blocks that are
4139 * dominated by `reference' by running a graph visit starting from the
4140 * entry point (which must be the initial value of `current') and
4141 * avoiding `reference'. Running this for all the blocks takes
4142 * quadratic time: if in the future something better is sought after,
4143 * the standard tool seems to be the Lengauer-Tarjan algorithm. */
4145{
4146 size_t i;
4147
4148 VKD3D_ASSERT(current->label != 0);
4149
4150 if (current == reference)
4151 return;
4152
4153 if (!bitmap_is_set(reference->dominates, current->label - 1))
4154 return;
4155
4156 bitmap_clear(reference->dominates, current->label - 1);
4157
4158 for (i = 0; i < current->successors.count; ++i)
4160}
4161
4163{
4164 size_t i, j;
4165
4166 for (i = 0; i < cfg->block_count; ++i)
4167 {
4168 struct vsir_block *block = &cfg->blocks[i];
4169
4170 if (block->label == 0)
4171 continue;
4172
4174
4175 if (TRACE_ON())
4176 {
4177 vkd3d_string_buffer_printf(&cfg->debug_buffer, "Block %u dominates:", block->label);
4178 for (j = 0; j < cfg->block_count; j++)
4179 {
4180 struct vsir_block *block2 = &cfg->blocks[j];
4181
4182 if (block2->label == 0 || !vsir_block_dominates(block, block2))
4183 continue;
4184
4185 if (cfg->debug_buffer.content_size > 512)
4186 {
4187 TRACE("%s...\n", cfg->debug_buffer.buffer);
4189 vkd3d_string_buffer_printf(&cfg->debug_buffer, "Block %u dominates: ...", block->label);
4190 }
4191 vkd3d_string_buffer_printf(&cfg->debug_buffer, " %u", block2->label);
4192 }
4193 TRACE("%s\n", cfg->debug_buffer.buffer);
4195 }
4196 }
4197}
4198
4199/* A back edge is an edge X -> Y for which block Y dominates block
4200 * X. All the other edges are forward edges, and it is required that
4201 * the input CFG is reducible, i.e., it is acyclic once you strip away
4202 * the back edges.
4203 *
4204 * Each back edge X -> Y defines a loop: block X is the header block,
4205 * block Y is the back edge block, and the loop consists of all the
4206 * blocks which are dominated by the header block and have a path to
4207 * the back edge block that doesn't pass through the header block
4208 * (including the header block itself). It can be proved that all the
4209 * blocks in such a path (connecting a loop block to the back edge
4210 * block without passing through the header block) belong to the same
4211 * loop.
4212 *
4213 * If the input CFG is reducible its loops are properly nested (i.e.,
4214 * each two loops are either disjoint or one is contained in the
4215 * other), provided that each block has at most one incoming back
4216 * edge. If this condition does not hold, a synthetic block can be
4217 * introduced as the only back edge block for the given header block,
4218 * with all the previous back edge now being forward edges to the
4219 * synthetic block. This is not currently implemented (but it is
4220 * rarely found in practice anyway). */
4222 struct vsir_block *header)
4223{
4224 enum vkd3d_result ret;
4225 size_t i;
4226
4227 if ((ret = vsir_block_list_add(loop, block)) < 0)
4228 return ret;
4229
4230 if (ret == VKD3D_FALSE || block == header)
4231 return VKD3D_OK;
4232
4233 for (i = 0; i < block->predecessors.count; ++i)
4234 {
4235 if ((ret = vsir_cfg_scan_loop(loop, block->predecessors.blocks[i], header)) < 0)
4236 return ret;
4237 }
4238
4239 return VKD3D_OK;
4240}
4241
4243{
4244 size_t i, j, k;
4245
4246 if (!(cfg->loops_by_header = vkd3d_calloc(cfg->block_count, sizeof(*cfg->loops_by_header))))
4248 memset(cfg->loops_by_header, 0xff, cfg->block_count * sizeof(*cfg->loops_by_header));
4249
4250 for (i = 0; i < cfg->block_count; ++i)
4251 {
4252 struct vsir_block *block = &cfg->blocks[i];
4253
4254 if (block->label == 0)
4255 continue;
4256
4257 for (j = 0; j < block->successors.count; ++j)
4258 {
4259 struct vsir_block *header = block->successors.blocks[j];
4260 struct vsir_block_list *loop;
4261 enum vkd3d_result ret;
4262
4263 /* Is this a back edge? */
4265 continue;
4266
4267 if (!vkd3d_array_reserve((void **)&cfg->loops, &cfg->loops_capacity, cfg->loops_count + 1, sizeof(*cfg->loops)))
4269
4270 loop = &cfg->loops[cfg->loops_count];
4272
4273 if ((ret = vsir_cfg_scan_loop(loop, block, header)) < 0)
4274 return ret;
4275
4277
4278 if (TRACE_ON())
4279 {
4280 vkd3d_string_buffer_printf(&cfg->debug_buffer, "Back edge %u -> %u with loop:", block->label, header->label);
4281
4282 for (k = 0; k < loop->count; ++k)
4283 {
4284 if (cfg->debug_buffer.content_size > 512)
4285 {
4286 TRACE("%s...\n", cfg->debug_buffer.buffer);
4288 vkd3d_string_buffer_printf(&cfg->debug_buffer, "Back edge %u -> %u with loop: ...",
4289 block->label, header->label);
4290 }
4291 vkd3d_string_buffer_printf(&cfg->debug_buffer, " %u", loop->blocks[k]->label);
4292 }
4293
4294 TRACE("%s\n", cfg->debug_buffer.buffer);
4296 }
4297
4298 if (cfg->loops_by_header[header->label - 1] != SIZE_MAX)
4299 {
4300 FIXME("Block %u is header to more than one loop, this is not implemented.\n", header->label);
4302 "Block %u is header to more than one loop, this is not implemented.", header->label);
4304 }
4305
4306 cfg->loops_by_header[header->label - 1] = cfg->loops_count;
4307
4308 ++cfg->loops_count;
4309 }
4310 }
4311
4312 return VKD3D_OK;
4313}
4314
4316{
4317 struct vsir_cfg *cfg;
4319 {
4321 unsigned int seen_count;
4322 unsigned int begin;
4326};
4327
4328/* Topologically sort the blocks according to the forward edges. By
4329 * definition if the input CFG is reducible then its forward edges
4330 * form a DAG, so a topological sorting exists. In order to compute it
4331 * we keep an array with the incoming degree for each block and an
4332 * available list of all the blocks whose incoming degree has reached
4333 * zero. At each step we pick a block from the available list and
4334 * strip it away from the graph, updating the incoming degrees and
4335 * available list.
4336 *
4337 * In principle at each step we can pick whatever node we want from
4338 * the available list, and will get a topological sort
4339 * anyway. However, we use these two criteria to give to the computed
4340 * order additional properties:
4341 *
4342 * 1. we keep track of which loops we're into, and pick blocks
4343 * belonging to the current innermost loop, so that loops are kept
4344 * contiguous in the order; this can always be done when the input
4345 * CFG is reducible;
4346 *
4347 * 2. subject to the requirement above, we always pick the most
4348 * recently added block to the available list, because this tends
4349 * to keep related blocks and require fewer control flow
4350 * primitives.
4351 */
4353{
4354 struct vsir_cfg_node_sorter sorter = { .cfg = cfg };
4355 unsigned int *in_degrees = NULL;
4356 enum vkd3d_result ret;
4357 size_t i;
4358
4359 if (!(in_degrees = vkd3d_calloc(cfg->block_count, sizeof(*in_degrees))))
4361
4362 for (i = 0; i < cfg->block_count; ++i)
4363 {
4364 struct vsir_block *block = &cfg->blocks[i];
4365
4366 if (block->label == 0)
4367 {
4368 in_degrees[i] = UINT_MAX;
4369 continue;
4370 }
4371
4372 in_degrees[i] = block->predecessors.count;
4373
4374 /* Do not count back edges. */
4375 if (cfg->loops_by_header[i] != SIZE_MAX)
4376 {
4377 VKD3D_ASSERT(in_degrees[i] > 0);
4378 in_degrees[i] -= 1;
4379 }
4380
4381 if (in_degrees[i] == 0 && block != cfg->entry)
4382 {
4383 WARN("Unexpected entry point %u.\n", block->label);
4385 "Block %u is unreachable from the entry point.", block->label);
4387 goto fail;
4388 }
4389 }
4390
4391 if (in_degrees[cfg->entry->label - 1] != 0)
4392 {
4393 WARN("Entry point has %u incoming forward edges.\n", in_degrees[cfg->entry->label - 1]);
4395 "The entry point block has %u incoming forward edges.", in_degrees[cfg->entry->label - 1]);
4397 goto fail;
4398 }
4399
4401
4402 if ((ret = vsir_block_list_add_checked(&sorter.available_blocks, cfg->entry)) < 0)
4403 goto fail;
4404
4405 while (sorter.available_blocks.count != 0)
4406 {
4407 struct vsir_cfg_node_sorter_stack_item *inner_stack_item = NULL;
4408 struct vsir_block *block;
4409 size_t new_seen_count;
4410
4411 if (sorter.stack_count != 0)
4412 inner_stack_item = &sorter.stack[sorter.stack_count - 1];
4413
4414 for (i = sorter.available_blocks.count - 1; ; --i)
4415 {
4416 if (i == SIZE_MAX)
4417 {
4418 ERR("Couldn't find any viable next block, is the input CFG reducible?\n");
4420 goto fail;
4421 }
4422
4423 block = sorter.available_blocks.blocks[i];
4424
4425 if (!inner_stack_item || vsir_block_list_search(inner_stack_item->loop, block))
4426 break;
4427 }
4428
4429 /* If the node is a loop header, open the loop. */
4430 if (sorter.cfg->loops_by_header[block->label - 1] != SIZE_MAX)
4431 {
4432 struct vsir_block_list *loop = &sorter.cfg->loops[sorter.cfg->loops_by_header[block->label - 1]];
4433
4434 if (loop)
4435 {
4436 if (!vkd3d_array_reserve((void **)&sorter.stack, &sorter.stack_capacity,
4437 sorter.stack_count + 1, sizeof(*sorter.stack)))
4439
4440 inner_stack_item = &sorter.stack[sorter.stack_count++];
4441 inner_stack_item->loop = loop;
4442 inner_stack_item->seen_count = 0;
4443 inner_stack_item->begin = sorter.cfg->order.count;
4444 }
4445 }
4446
4448 block->order_pos = cfg->order.count;
4449 if ((ret = vsir_block_list_add_checked(&cfg->order, block)) < 0)
4450 goto fail;
4451
4452 /* Close loops: since each loop is a strict subset of any
4453 * outer loop, we just need to track how many blocks we've
4454 * seen; when I close a loop I mark the same number of seen
4455 * blocks for the next outer loop. */
4456 new_seen_count = 1;
4457 while (sorter.stack_count != 0)
4458 {
4459 inner_stack_item = &sorter.stack[sorter.stack_count - 1];
4460
4461 inner_stack_item->seen_count += new_seen_count;
4462
4463 VKD3D_ASSERT(inner_stack_item->seen_count <= inner_stack_item->loop->count);
4464 if (inner_stack_item->seen_count != inner_stack_item->loop->count)
4465 break;
4466
4467 if ((ret = vsir_cfg_add_loop_interval(cfg, inner_stack_item->begin,
4468 cfg->order.count, false)) < 0)
4469 goto fail;
4470
4471 new_seen_count = inner_stack_item->loop->count;
4472 --sorter.stack_count;
4473 }
4474
4475 /* Remove (forward) edges and make new nodes available. */
4476 for (i = 0; i < block->successors.count; ++i)
4477 {
4478 struct vsir_block *successor = block->successors.blocks[i];
4479
4480 if (vsir_block_dominates(successor, block))
4481 continue;
4482
4483 VKD3D_ASSERT(in_degrees[successor->label - 1] > 0);
4484 --in_degrees[successor->label - 1];
4485
4486 if (in_degrees[successor->label - 1] == 0)
4487 {
4488 if ((ret = vsir_block_list_add_checked(&sorter.available_blocks, successor)) < 0)
4489 goto fail;
4490 }
4491 }
4492 }
4493
4494 if (cfg->order.count != cfg->block_count)
4495 {
4496 /* There is a cycle of forward edges. */
4497 WARN("The control flow graph is not reducible.\n");
4499 "The control flow graph is not reducible.");
4501 goto fail;
4502 }
4503
4504 VKD3D_ASSERT(sorter.stack_count == 0);
4505
4506 vkd3d_free(in_degrees);
4507 vkd3d_free(sorter.stack);
4509
4510 if (TRACE_ON())
4511 {
4512 vkd3d_string_buffer_printf(&cfg->debug_buffer, "Block order:");
4513
4514 for (i = 0; i < cfg->order.count; ++i)
4515 {
4516 if (cfg->debug_buffer.content_size > 512)
4517 {
4518 TRACE("%s...\n", cfg->debug_buffer.buffer);
4520 vkd3d_string_buffer_printf(&cfg->debug_buffer, "Block order: ...");
4521 }
4522 vkd3d_string_buffer_printf(&cfg->debug_buffer, " %u", cfg->order.blocks[i]->label);
4523 }
4524
4525 TRACE("%s\n", cfg->debug_buffer.buffer);
4527 }
4528
4529 return VKD3D_OK;
4530
4531fail:
4532 vkd3d_free(in_degrees);
4533 vkd3d_free(sorter.stack);
4535
4536 return ret;
4537}
4538
4539/* Sort loop intervals first by ascending begin time and then by
4540 * descending end time, so that inner intervals appear after outer
4541 * ones and disjoint intervals appear in their proper order. */
4542static int compare_loop_intervals(const void *ptr1, const void *ptr2)
4543{
4544 const struct cfg_loop_interval *interval1 = ptr1;
4545 const struct cfg_loop_interval *interval2 = ptr2;
4546
4547 if (interval1->begin != interval2->begin)
4548 return vkd3d_u32_compare(interval1->begin, interval2->begin);
4549
4550 return -vkd3d_u32_compare(interval1->end, interval2->end);
4551}
4552
4554{
4555 enum vkd3d_result ret;
4556 size_t i, j, k;
4557
4558 for (i = 0; i < cfg->block_count; ++i)
4559 {
4560 struct vsir_block *block = &cfg->blocks[i];
4561
4562 if (block->label == 0)
4563 continue;
4564
4565 for (j = 0; j < block->successors.count; ++j)
4566 {
4567 struct vsir_block *successor = block->successors.blocks[j];
4568 struct cfg_loop_interval *extend = NULL;
4569 unsigned int begin;
4570 enum
4571 {
4572 ACTION_DO_NOTHING,
4573 ACTION_CREATE_NEW,
4574 ACTION_EXTEND,
4575 } action = ACTION_CREATE_NEW;
4576
4577 /* We've already constructed loop intervals for the back
4578 * edges, there's nothing more to do. */
4579 if (vsir_block_dominates(successor, block))
4580 continue;
4581
4582 VKD3D_ASSERT(block->order_pos < successor->order_pos);
4583
4584 /* Jumping from a block to the following one is always
4585 * possible, so nothing to do. */
4586 if (block->order_pos + 1 == successor->order_pos)
4587 continue;
4588
4589 /* Let's look for a loop interval that already breaks at
4590 * `successor' and either contains or can be extended to
4591 * contain `block'. */
4592 for (k = 0; k < cfg->loop_interval_count; ++k)
4593 {
4594 struct cfg_loop_interval *interval = &cfg->loop_intervals[k];
4595
4596 if (interval->end != successor->order_pos)
4597 continue;
4598
4599 if (interval->begin <= block->order_pos)
4600 {
4601 action = ACTION_DO_NOTHING;
4602 break;
4603 }
4604
4605 if (interval->synthetic)
4606 {
4607 action = ACTION_EXTEND;
4608 extend = interval;
4609 break;
4610 }
4611 }
4612
4613 if (action == ACTION_DO_NOTHING)
4614 continue;
4615
4616 /* Ok, we have to decide where the new or replacing
4617 * interval has to begin. These are the rules: 1. it must
4618 * begin before `block'; 2. intervals must be properly
4619 * nested; 3. the new interval should begin as late as
4620 * possible, to limit control flow depth and extension. */
4621 begin = block->order_pos;
4622
4623 /* Our candidate interval is always [begin,
4624 * successor->order_pos), and we move `begin' backward
4625 * until the candidate interval contains all the intervals
4626 * whose endpoint lies in the candidate interval
4627 * itself. */
4628 for (k = 0; k < cfg->loop_interval_count; ++k)
4629 {
4630 struct cfg_loop_interval *interval = &cfg->loop_intervals[k];
4631
4632 if (begin < interval->end && interval->end < successor->order_pos)
4633 begin = min(begin, interval->begin);
4634 }
4635
4636 /* New we have to care about the intervals whose begin
4637 * point lies in the candidate interval. We cannot move
4638 * the candidate interval endpoint, because it is
4639 * important that the loop break target matches
4640 * `successor'. So we have to move that interval's begin
4641 * point to the begin point of the candidate interval,
4642 * i.e. `begin'. But what if the interval we should extend
4643 * backward is not synthetic? This cannot happen,
4644 * fortunately, because it would mean that there is a jump
4645 * entering a loop via a block which is not the loop
4646 * header, so the CFG would not be reducible. */
4647 for (k = 0; k < cfg->loop_interval_count; ++k)
4648 {
4649 struct cfg_loop_interval *interval = &cfg->loop_intervals[k];
4650
4651 if (interval->begin < successor->order_pos && successor->order_pos < interval->end)
4652 {
4653 if (interval->synthetic)
4654 interval->begin = min(begin, interval->begin);
4655 VKD3D_ASSERT(begin >= interval->begin);
4656 }
4657 }
4658
4659 if (action == ACTION_EXTEND)
4660 extend->begin = begin;
4661 else if ((ret = vsir_cfg_add_loop_interval(cfg, begin, successor->order_pos, true)) < 0)
4662 return ret;
4663 }
4664 }
4665
4667
4668 if (TRACE_ON())
4669 for (i = 0; i < cfg->loop_interval_count; ++i)
4670 TRACE("%s loop interval %u - %u\n", cfg->loop_intervals[i].synthetic ? "Synthetic" : "Natural",
4671 cfg->loop_intervals[i].begin, cfg->loop_intervals[i].end);
4672
4673 return VKD3D_OK;
4674}
4675
4677{
4678 enum vsir_cfg_jump_type jump_type;
4679 unsigned int target;
4681};
4682
4684 struct vsir_block *successor, struct vsir_cfg_edge_action *action)
4685{
4686 unsigned int i;
4687
4688 action->target = UINT_MAX;
4689 action->successor = successor;
4690
4691 if (successor->order_pos <= block->order_pos)
4692 {
4693 /* The successor is before the current block, so we have to
4694 * use `continue'. The target loop is the innermost that
4695 * contains the current block and has the successor as
4696 * `continue' target. */
4697 for (i = 0; i < cfg->loop_interval_count; ++i)
4698 {
4699 struct cfg_loop_interval *interval = &cfg->loop_intervals[i];
4700
4701 if (interval->begin == successor->order_pos && block->order_pos < interval->end)
4702 action->target = i;
4703
4704 if (interval->begin > successor->order_pos)
4705 break;
4706 }
4707
4708 VKD3D_ASSERT(action->target != UINT_MAX);
4709 action->jump_type = JUMP_CONTINUE;
4710 }
4711 else
4712 {
4713 /* The successor is after the current block, so we have to use
4714 * `break', or possibly just jump to the following block. The
4715 * target loop is the outermost that contains the current
4716 * block and has the successor as `break' target. */
4717 for (i = 0; i < cfg->loop_interval_count; ++i)
4718 {
4719 struct cfg_loop_interval *interval = &cfg->loop_intervals[i];
4720
4721 if (interval->begin <= block->order_pos && interval->end == successor->order_pos)
4722 {
4723 action->target = i;
4724 break;
4725 }
4726 }
4727
4728 if (action->target == UINT_MAX)
4729 {
4730 VKD3D_ASSERT(successor->order_pos == block->order_pos + 1);
4731 action->jump_type = JUMP_NONE;
4732 }
4733 else
4734 {
4735 action->jump_type = JUMP_BREAK;
4736 }
4737 }
4738}
4739
4741{
4742 unsigned int i, stack_depth = 1, open_interval_idx = 0;
4744
4745 /* It's enough to allocate up to the maximum interval stacking
4746 * depth (plus one for the full program), but this is simpler. */
4747 if (!(stack = vkd3d_calloc(cfg->loop_interval_count + 1, sizeof(*stack))))
4748 goto fail;
4749 cfg->structured_program.end = cfg->order.count;
4750 stack[0] = &cfg->structured_program;
4751
4752 for (i = 0; i < cfg->order.count; ++i)
4753 {
4754 struct vsir_block *block = cfg->order.blocks[i];
4755 struct vsir_cfg_structure *structure;
4756
4757 VKD3D_ASSERT(stack_depth > 0);
4758
4759 /* Open loop intervals. */
4760 while (open_interval_idx < cfg->loop_interval_count)
4761 {
4762 struct cfg_loop_interval *interval = &cfg->loop_intervals[open_interval_idx];
4763
4764 if (interval->begin != i)
4765 break;
4766
4767 if (!(structure = vsir_cfg_structure_list_append(stack[stack_depth - 1], STRUCTURE_TYPE_LOOP)))
4768 goto fail;
4769 structure->u.loop.idx = open_interval_idx++;
4770
4771 structure->u.loop.body.end = interval->end;
4772 stack[stack_depth++] = &structure->u.loop.body;
4773 }
4774
4775 /* Execute the block. */
4776 if (!(structure = vsir_cfg_structure_list_append(stack[stack_depth - 1], STRUCTURE_TYPE_BLOCK)))
4777 goto fail;
4778 structure->u.block = block;
4779
4780 /* Generate between zero and two jump instructions. */
4781 switch (block->end->opcode)
4782 {
4783 case VKD3DSIH_BRANCH:
4784 {
4785 struct vsir_cfg_edge_action action_true, action_false;
4786 bool invert_condition = false;
4787
4788 if (vsir_register_is_label(&block->end->src[0].reg))
4789 {
4790 unsigned int target = label_from_src_param(&block->end->src[0]);
4791 struct vsir_block *successor = &cfg->blocks[target - 1];
4792
4793 vsir_cfg_compute_edge_action(cfg, block, successor, &action_true);
4794 action_false = action_true;
4795 }
4796 else
4797 {
4798 unsigned int target = label_from_src_param(&block->end->src[1]);
4799 struct vsir_block *successor = &cfg->blocks[target - 1];
4800
4801 vsir_cfg_compute_edge_action(cfg, block, successor, &action_true);
4802
4803 target = label_from_src_param(&block->end->src[2]);
4804 successor = &cfg->blocks[target - 1];
4805
4806 vsir_cfg_compute_edge_action(cfg, block, successor, &action_false);
4807 }
4808
4809 /* This will happen if the branch is unconditional,
4810 * but also if it's conditional with the same target
4811 * in both branches, which can happen in some corner
4812 * cases, e.g. when converting switch instructions to
4813 * selection ladders. */
4814 if (action_true.successor == action_false.successor)
4815 {
4816 VKD3D_ASSERT(action_true.jump_type == action_false.jump_type);
4817 }
4818 else
4819 {
4820 /* At most one branch can just fall through to the
4821 * next block, in which case we make sure it's the
4822 * false branch. */
4823 if (action_true.jump_type == JUMP_NONE)
4824 {
4825 invert_condition = true;
4826 }
4827 else if (stack_depth >= 2)
4828 {
4829 struct vsir_cfg_structure_list *inner_loop_frame = stack[stack_depth - 2];
4830 struct vsir_cfg_structure *inner_loop = &inner_loop_frame->structures[inner_loop_frame->count - 1];
4831
4832 VKD3D_ASSERT(inner_loop->type == STRUCTURE_TYPE_LOOP);
4833
4834 /* Otherwise, if one of the branches is
4835 * continue-ing the inner loop we're inside,
4836 * make sure it's the false branch (because it
4837 * will be optimized out later). */
4838 if (action_true.jump_type == JUMP_CONTINUE && action_true.target == inner_loop->u.loop.idx)
4839 invert_condition = true;
4840 }
4841
4842 if (invert_condition)
4843 {
4844 struct vsir_cfg_edge_action tmp = action_true;
4845 action_true = action_false;
4846 action_false = tmp;
4847 }
4848
4849 VKD3D_ASSERT(action_true.jump_type != JUMP_NONE);
4850
4851 if (!(structure = vsir_cfg_structure_list_append(stack[stack_depth - 1], STRUCTURE_TYPE_JUMP)))
4852 goto fail;
4853 structure->u.jump.type = action_true.jump_type;
4854 structure->u.jump.target = action_true.target;
4855 structure->u.jump.condition = &block->end->src[0];
4856 structure->u.jump.invert_condition = invert_condition;
4857 }
4858
4859 if (action_false.jump_type != JUMP_NONE)
4860 {
4861 if (!(structure = vsir_cfg_structure_list_append(stack[stack_depth - 1], STRUCTURE_TYPE_JUMP)))
4862 goto fail;
4863 structure->u.jump.type = action_false.jump_type;
4864 structure->u.jump.target = action_false.target;
4865 }
4866 break;
4867 }
4868
4869 case VKD3DSIH_RET:
4870 if (!(structure = vsir_cfg_structure_list_append(stack[stack_depth - 1], STRUCTURE_TYPE_JUMP)))
4871 goto fail;
4872 structure->u.jump.type = JUMP_RET;
4873 break;
4874
4875 default:
4877 }
4878
4879 /* Close loop intervals. */
4880 while (stack_depth > 0)
4881 {
4882 if (stack[stack_depth - 1]->end != i + 1)
4883 break;
4884
4885 --stack_depth;
4886 }
4887 }
4888
4889 VKD3D_ASSERT(stack_depth == 0);
4890 VKD3D_ASSERT(open_interval_idx == cfg->loop_interval_count);
4891
4892 if (TRACE_ON())
4894
4896
4897 return VKD3D_OK;
4898
4899fail:
4901
4903}
4904
4906 struct vsir_cfg_structure_list *list, unsigned int target)
4907{
4908 struct vsir_cfg_structure *last = &list->structures[list->count - 1];
4909
4910 if (last->type == STRUCTURE_TYPE_JUMP && last->u.jump.type == JUMP_CONTINUE
4911 && !last->u.jump.condition && last->u.jump.target == target)
4912 {
4913 --list->count;
4914 VKD3D_ASSERT(cfg->loop_intervals[target].target_count > 0);
4915 --cfg->loop_intervals[target].target_count;
4916 }
4917}
4918
4920{
4921 struct vsir_cfg_structure *structure;
4922 size_t count = list->count;
4923
4924 if (count == 0)
4925 return NULL;
4926
4927 structure = &list->structures[count - 1];
4928
4929 if (structure->type != STRUCTURE_TYPE_JUMP || structure->u.jump.type != JUMP_BREAK
4930 || structure->u.jump.condition)
4931 return NULL;
4932
4933 return structure;
4934}
4935
4936/* When the last instruction in both branches of a selection construct
4937 * is an unconditional break, any of them can be moved after the
4938 * selection construct. If they break the same loop both of them can
4939 * be moved out, otherwise we can choose which one: we choose the one
4940 * that breaks the innermost loop, because we hope to eventually
4941 * remove the loop itself.
4942 *
4943 * In principle a similar movement could be done when the last
4944 * instructions are continue and continue, or continue and break. But
4945 * in practice I don't think those situations can happen given the
4946 * previous passes we do on the program, so we don't care. */
4949{
4950 struct vsir_cfg_structure *selection, *if_break, *else_break, *new_break;
4951 unsigned int if_target, else_target, max_target;
4952 size_t pos = list->count - 1;
4953
4954 selection = &list->structures[pos];
4956
4957 if_break = vsir_cfg_get_trailing_break(&selection->u.selection.if_body);
4958 else_break = vsir_cfg_get_trailing_break(&selection->u.selection.else_body);
4959
4960 if (!if_break || !else_break)
4961 return VKD3D_OK;
4962
4963 if_target = if_break->u.jump.target;
4964 else_target = else_break->u.jump.target;
4965 max_target = max(if_target, else_target);
4966
4969 new_break->u.jump.type = JUMP_BREAK;
4970 new_break->u.jump.target = max_target;
4971 ++cfg->loop_intervals[max_target].target_count;
4972
4973 /* Pointer `selection' could have been invalidated by the append
4974 * operation. */
4975 selection = &list->structures[pos];
4977
4978 if (if_target == max_target)
4979 {
4980 --selection->u.selection.if_body.count;
4981 VKD3D_ASSERT(cfg->loop_intervals[if_target].target_count > 0);
4982 --cfg->loop_intervals[if_target].target_count;
4983 }
4984
4985 if (else_target == max_target)
4986 {
4987 --selection->u.selection.else_body.count;
4988 VKD3D_ASSERT(cfg->loop_intervals[else_target].target_count > 0);
4989 --cfg->loop_intervals[else_target].target_count;
4990 }
4991
4992 /* If a branch becomes empty, make it the else branch, so we save a block. */
4993 if (selection->u.selection.if_body.count == 0)
4994 {
4995 struct vsir_cfg_structure_list tmp;
4996
4997 selection->u.selection.invert_condition = !selection->u.selection.invert_condition;
4998 tmp = selection->u.selection.if_body;
4999 selection->u.selection.if_body = selection->u.selection.else_body;
5000 selection->u.selection.else_body = tmp;
5001 }
5002
5003 return VKD3D_OK;
5004}
5005
5008{
5010
5011 if (list->count == 0)
5012 return VKD3D_OK;
5013
5014 trailing = &list->structures[list->count - 1];
5015
5017 return VKD3D_OK;
5018
5021
5023}
5024
5027{
5028 enum vkd3d_result ret;
5029 size_t i;
5030
5031 for (i = 0; i < list->count; ++i)
5032 {
5033 struct vsir_cfg_structure *structure = &list->structures[i], new_selection, *new_jump;
5034
5035 if (structure->type != STRUCTURE_TYPE_JUMP || !structure->u.jump.condition)
5036 continue;
5037
5039 new_selection.u.selection.condition = structure->u.jump.condition;
5040 new_selection.u.selection.invert_condition = structure->u.jump.invert_condition;
5041
5042 if (!(new_jump = vsir_cfg_structure_list_append(&new_selection.u.selection.if_body,
5045 new_jump->u.jump.type = structure->u.jump.type;
5046 new_jump->u.jump.target = structure->u.jump.target;
5047
5048 /* Move the rest of the structure list in the else branch
5049 * rather than leaving it after the selection construct. The
5050 * reason is that this is more conducive to further
5051 * optimization, because all the conditional `break's appear
5052 * as the last instruction of a branch of a cascade of
5053 * selection constructs at the end of the structure list we're
5054 * processing, instead of being buried in the middle of the
5055 * structure list itself. */
5056 if ((ret = vsir_cfg_structure_list_append_from_region(&new_selection.u.selection.else_body,
5057 &list->structures[i + 1], list->count - i - 1)) < 0)
5058 return ret;
5059
5060 *structure = new_selection;
5061 list->count = i + 1;
5062
5063 if ((ret = vsir_cfg_synthesize_selections(cfg, &structure->u.selection.else_body)) < 0)
5064 return ret;
5065
5067 return ret;
5068
5069 break;
5070 }
5071
5072 return VKD3D_OK;
5073}
5074
5076 struct vsir_cfg_structure_list *new_list, struct vsir_cfg_structure *loop)
5077{
5078 struct vsir_cfg_structure_list *loop_body = &loop->u.loop.body;
5079 unsigned int target, loop_idx = loop->u.loop.idx;
5080 struct vsir_cfg_structure *trailing_break;
5081 enum vkd3d_result ret;
5082
5083 trailing_break = vsir_cfg_get_trailing_break(loop_body);
5084
5085 /* If the loop's last instruction is not a break, we cannot remove
5086 * the loop itself. */
5087 if (!trailing_break)
5088 {
5089 if ((ret = vsir_cfg_structure_list_append_from_region(new_list, loop, 1)) < 0)
5090 return ret;
5091 memset(loop, 0, sizeof(*loop));
5092 return VKD3D_OK;
5093 }
5094
5095 target = trailing_break->u.jump.target;
5096 VKD3D_ASSERT(cfg->loop_intervals[target].target_count > 0);
5097
5098 /* If the loop is not targeted by any jump, we can remove it. The
5099 * trailing `break' then targets another loop, so we have to keep
5100 * it. */
5101 if (cfg->loop_intervals[loop_idx].target_count == 0)
5102 {
5104 &loop_body->structures[0], loop_body->count)) < 0)
5105 return ret;
5106 loop_body->count = 0;
5107 return VKD3D_OK;
5108 }
5109
5110 /* If the loop is targeted only by its own trailing `break'
5111 * instruction, then we can remove it together with the `break'
5112 * itself. */
5113 if (target == loop_idx && cfg->loop_intervals[loop_idx].target_count == 1)
5114 {
5115 --cfg->loop_intervals[loop_idx].target_count;
5117 &loop_body->structures[0], loop_body->count - 1)) < 0)
5118 return ret;
5119 loop_body->count = 0;
5120 return VKD3D_OK;
5121 }
5122
5123 if ((ret = vsir_cfg_structure_list_append_from_region(new_list, loop, 1)) < 0)
5124 return ret;
5125 memset(loop, 0, sizeof(*loop));
5126
5127 return VKD3D_OK;
5128}
5129
5131{
5132 struct vsir_cfg_structure_list old_list = *list, *new_list = list;
5133 enum vkd3d_result ret;
5134 size_t i;
5135
5136 memset(new_list, 0, sizeof(*new_list));
5137
5138 for (i = 0; i < old_list.count; ++i)
5139 {
5140 struct vsir_cfg_structure *loop = &old_list.structures[i], *selection;
5141 struct vsir_cfg_structure_list *loop_body;
5142
5143 if (loop->type != STRUCTURE_TYPE_LOOP)
5144 {
5145 if ((ret = vsir_cfg_structure_list_append_from_region(new_list, loop, 1)) < 0)
5146 goto out;
5147 memset(loop, 0, sizeof(*loop));
5148 continue;
5149 }
5150
5151 loop_body = &loop->u.loop.body;
5152
5153 if (loop_body->count == 0)
5154 {
5155 if ((ret = vsir_cfg_structure_list_append_from_region(new_list, loop, 1)) < 0)
5156 goto out;
5157 memset(loop, 0, sizeof(*loop));
5158 continue;
5159 }
5160
5161 vsir_cfg_remove_trailing_continue(cfg, loop_body, loop->u.loop.idx);
5162
5163 if ((ret = vsir_cfg_optimize_recurse(cfg, loop_body)) < 0)
5164 goto out;
5165
5166 if ((ret = vsir_cfg_synthesize_selections(cfg, loop_body)) < 0)
5167 goto out;
5168
5169 if ((ret = vsir_cfg_append_loop(cfg, new_list, loop)) < 0)
5170 goto out;
5171
5172 /* If the last pushed instruction is a selection and one of the branches terminates with a
5173 * `break', start pushing to the other branch, in the hope of eventually push a `break'
5174 * there too and be able to remove a loop. */
5175 if (new_list->count == 0)
5176 continue;
5177
5178 selection = &new_list->structures[new_list->count - 1];
5179
5180 if (selection->type == STRUCTURE_TYPE_SELECTION)
5181 {
5182 if (vsir_cfg_get_trailing_break(&selection->u.selection.if_body))
5183 new_list = &selection->u.selection.else_body;
5184 else if (vsir_cfg_get_trailing_break(&selection->u.selection.else_body))
5185 new_list = &selection->u.selection.if_body;
5186 }
5187 }
5188
5190
5191out:
5193
5194 return ret;
5195}
5196
5198{
5199 size_t i;
5200
5201 for (i = 0; i < list->count; ++i)
5202 {
5203 struct vsir_cfg_structure *structure = &list->structures[i];
5204
5205 switch (structure->type)
5206 {
5208 break;
5209
5211 vsir_cfg_count_targets(cfg, &structure->u.loop.body);
5212 break;
5213
5215 vsir_cfg_count_targets(cfg, &structure->u.selection.if_body);
5216 vsir_cfg_count_targets(cfg, &structure->u.selection.else_body);
5217 break;
5218
5220 if (structure->u.jump.type == JUMP_BREAK || structure->u.jump.type == JUMP_CONTINUE)
5221 ++cfg->loop_intervals[structure->u.jump.target].target_count;
5222 break;
5223 }
5224 }
5225}
5226
5227/* Trampolines are code gadgets used to emulate multilevel jumps (which are not natively supported
5228 * by SPIR-V). A trampoline is inserted just after a loop and checks whether control has reached the
5229 * intended site (i.e., we just jumped out of the target block) or if other levels of jumping are
5230 * needed. For each jump a trampoline is required for all the loops between the jump itself and the
5231 * target loop, excluding the target loop itself. */
5233 struct vsir_cfg_structure *loop)
5234{
5235 size_t i;
5236
5237 for (i = 0; i < list->count; ++i)
5238 {
5239 struct vsir_cfg_structure *structure = &list->structures[i];
5240
5241 switch (structure->type)
5242 {
5244 break;
5245
5247 structure->u.loop.outer_loop = loop;
5248 vsir_cfg_mark_trampolines(cfg, &structure->u.loop.body, structure);
5249 break;
5250
5252 vsir_cfg_mark_trampolines(cfg, &structure->u.selection.if_body, loop);
5253 vsir_cfg_mark_trampolines(cfg, &structure->u.selection.else_body, loop);
5254 break;
5255
5257 {
5258 struct vsir_cfg_structure *l;
5259 if (structure->u.jump.type != JUMP_BREAK && structure->u.jump.type != JUMP_CONTINUE)
5260 break;
5261 for (l = loop; l && l->u.loop.idx != structure->u.jump.target; l = l->u.loop.outer_loop)
5262 {
5264 l->u.loop.needs_trampoline = true;
5265 }
5266 break;
5267 }
5268 }
5269 }
5270}
5271
5272/* Launchers are the counterpart of trampolines. A launcher is inserted just before a jump, and
5273 * writes in a well-known variable what is the target of the jump. Trampolines will then read that
5274 * variable to decide how to redirect the jump to its intended target. A launcher is needed each
5275 * time the innermost loop containing the jump itself has a trampoline (independently of whether the
5276 * jump is targeting that loop or not). */
5278 struct vsir_cfg_structure *loop)
5279{
5280 size_t i;
5281
5282 for (i = 0; i < list->count; ++i)
5283 {
5284 struct vsir_cfg_structure *structure = &list->structures[i];
5285
5286 switch (structure->type)
5287 {
5289 break;
5290
5292 vsir_cfg_mark_launchers(cfg, &structure->u.loop.body, structure);
5293 break;
5294
5296 vsir_cfg_mark_launchers(cfg, &structure->u.selection.if_body, loop);
5297 vsir_cfg_mark_launchers(cfg, &structure->u.selection.else_body, loop);
5298 break;
5299
5301 if (structure->u.jump.type != JUMP_BREAK && structure->u.jump.type != JUMP_CONTINUE)
5302 break;
5304 if (loop->u.loop.needs_trampoline)
5305 structure->u.jump.needs_launcher = true;
5306 break;
5307 }
5308 }
5309}
5310
5312{
5313 enum vkd3d_result ret;
5314
5316
5318
5319 /* Trampolines and launchers cannot be marked with the same pass,
5320 * because a jump might have to be marked as launcher even when it
5321 * targets its innermost loop, if other jumps in the same loop
5322 * need a trampoline anyway. So launchers can be discovered only
5323 * once all the trampolines are known. */
5326
5327 if (TRACE_ON())
5329
5330 return ret;
5331}
5332
5333static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg,
5334 struct vsir_cfg_structure_list *list, unsigned int loop_idx);
5335
5337 struct vsir_block *block)
5338{
5339 struct vsir_cfg_emit_target *target = cfg->target;
5340
5341 if (!reserve_instructions(&target->instructions, &target->ins_capacity,
5342 target->ins_count + (block->end - block->begin)))
5344
5345 memcpy(&target->instructions[target->ins_count], block->begin,
5346 (char *)block->end - (char *)block->begin);
5347
5348 target->ins_count += block->end - block->begin;
5349
5350 return VKD3D_OK;
5351}
5352
5354 struct vsir_cfg_structure_loop *loop, unsigned int loop_idx)
5355{
5356 struct vsir_cfg_emit_target *target = cfg->target;
5357 const struct vkd3d_shader_location no_loc = {0};
5358 enum vkd3d_result ret;
5359
5360 if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1))
5362
5363 vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_LOOP);
5364
5365 if ((ret = vsir_cfg_structure_list_emit(cfg, &loop->body, loop->idx)) < 0)
5366 return ret;
5367
5368 if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 5))
5370
5371 vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_ENDLOOP);
5372
5373 /* Add a trampoline to implement multilevel jumping depending on the stored
5374 * jump_target value. */
5375 if (loop->needs_trampoline)
5376 {
5377 /* If the multilevel jump is a `continue' and the target is the loop we're inside
5378 * right now, then we can finally do the `continue'. */
5379 const unsigned int outer_continue_target = loop_idx << 1 | 1;
5380 /* If the multilevel jump is a `continue' to any other target, or if it is a `break'
5381 * and the target is not the loop we just finished emitting, then it means that
5382 * we have to reach an outer loop, so we keep breaking. */
5383 const unsigned int inner_break_target = loop->idx << 1;
5384
5385 if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count],
5386 &no_loc, VKD3DSIH_IEQ, 1, 2))
5388
5389 dst_param_init_temp_bool(&target->instructions[target->ins_count].dst[0], target->temp_count);
5390 src_param_init_temp_uint(&target->instructions[target->ins_count].src[0], target->jump_target_temp_idx);
5391 src_param_init_const_uint(&target->instructions[target->ins_count].src[1], outer_continue_target);
5392
5393 ++target->ins_count;
5394
5395 if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count],
5396 &no_loc, VKD3DSIH_CONTINUEP, 0, 1))
5398
5399 src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count);
5400
5401 ++target->ins_count;
5402 ++target->temp_count;
5403
5404 if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count],
5405 &no_loc, VKD3DSIH_IEQ, 1, 2))
5407
5408 dst_param_init_temp_bool(&target->instructions[target->ins_count].dst[0], target->temp_count);
5409 src_param_init_temp_uint(&target->instructions[target->ins_count].src[0], target->jump_target_temp_idx);
5410 src_param_init_const_uint(&target->instructions[target->ins_count].src[1], inner_break_target);
5411
5412 ++target->ins_count;
5413
5414 if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count],
5415 &no_loc, VKD3DSIH_BREAKP, 0, 1))
5417 target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z;
5418
5419 src_param_init_temp_bool(&target->instructions[target->ins_count].src[0], target->temp_count);
5420
5421 ++target->ins_count;
5422 ++target->temp_count;
5423 }
5424
5425 return VKD3D_OK;
5426}
5427
5429 struct vsir_cfg_structure_selection *selection, unsigned int loop_idx)
5430{
5431 struct vsir_cfg_emit_target *target = cfg->target;
5432 const struct vkd3d_shader_location no_loc = {0};
5433 enum vkd3d_result ret;
5434
5435 if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1))
5437
5438 if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count],
5439 &no_loc, VKD3DSIH_IF, 0, 1))
5441
5442 target->instructions[target->ins_count].src[0] = *selection->condition;
5443
5444 if (selection->invert_condition)
5445 target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z;
5446
5447 ++target->ins_count;
5448
5449 if ((ret = vsir_cfg_structure_list_emit(cfg, &selection->if_body, loop_idx)) < 0)
5450 return ret;
5451
5452 if (selection->else_body.count != 0)
5453 {
5454 if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1))
5456
5457 vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_ELSE);
5458
5459 if ((ret = vsir_cfg_structure_list_emit(cfg, &selection->else_body, loop_idx)) < 0)
5460 return ret;
5461 }
5462
5463 if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 1))
5465
5466 vsir_instruction_init(&target->instructions[target->ins_count++], &no_loc, VKD3DSIH_ENDIF);
5467
5468 return VKD3D_OK;
5469}
5470
5472 struct vsir_cfg_structure_jump *jump, unsigned int loop_idx)
5473{
5474 struct vsir_cfg_emit_target *target = cfg->target;
5475 const struct vkd3d_shader_location no_loc = {0};
5476 /* Encode the jump target as the loop index plus a bit to remember whether
5477 * we're breaking or continue-ing. */
5478 unsigned int jump_target = jump->target << 1;
5479 enum vkd3d_shader_opcode opcode;
5480
5481 switch (jump->type)
5482 {
5483 case JUMP_CONTINUE:
5484 /* If we're continue-ing the loop we're directly inside, then we can emit a
5485 * `continue'. Otherwise we first have to break all the loops between here
5486 * and the loop to continue, recording our intention to continue
5487 * in the lowest bit of jump_target. */
5488 if (jump->target == loop_idx)
5489 {
5490 opcode = jump->condition ? VKD3DSIH_CONTINUEP : VKD3DSIH_CONTINUE;
5491 break;
5492 }
5493 jump_target |= 1;
5494 /* fall through */
5495
5496 case JUMP_BREAK:
5497 opcode = jump->condition ? VKD3DSIH_BREAKP : VKD3DSIH_BREAK;
5498 break;
5499
5500 case JUMP_RET:
5501 VKD3D_ASSERT(!jump->condition);
5502 opcode = VKD3DSIH_RET;
5503 break;
5504
5505 default:
5507 }
5508
5509 if (!reserve_instructions(&target->instructions, &target->ins_capacity, target->ins_count + 2))
5511
5512 if (jump->needs_launcher)
5513 {
5514 if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count],
5515 &no_loc, VKD3DSIH_MOV, 1, 1))
5517
5518 dst_param_init_temp_uint(&target->instructions[target->ins_count].dst[0], target->jump_target_temp_idx);
5519 src_param_init_const_uint(&target->instructions[target->ins_count].src[0], jump_target);
5520
5521 ++target->ins_count;
5522 }
5523
5524 if (!vsir_instruction_init_with_params(cfg->program, &target->instructions[target->ins_count],
5525 &no_loc, opcode, 0, !!jump->condition))
5527
5528 if (jump->invert_condition)
5529 target->instructions[target->ins_count].flags |= VKD3D_SHADER_CONDITIONAL_OP_Z;
5530
5531 if (jump->condition)
5532 target->instructions[target->ins_count].src[0] = *jump->condition;
5533
5534 ++target->ins_count;
5535
5536 return VKD3D_OK;
5537}
5538
5540 struct vsir_cfg_structure_list *list, unsigned int loop_idx)
5541{
5542 enum vkd3d_result ret;
5543 size_t i;
5544
5545 for (i = 0; i < list->count; ++i)
5546 {
5547 struct vsir_cfg_structure *structure = &list->structures[i];
5548
5549 switch (structure->type)
5550 {
5552 if ((ret = vsir_cfg_structure_list_emit_block(cfg, structure->u.block)) < 0)
5553 return ret;
5554 break;
5555
5557 if ((ret = vsir_cfg_structure_list_emit_loop(cfg, &structure->u.loop, loop_idx)) < 0)
5558 return ret;
5559 break;
5560
5562 if ((ret = vsir_cfg_structure_list_emit_selection(cfg, &structure->u.selection,
5563 loop_idx)) < 0)
5564 return ret;
5565 break;
5566
5568 if ((ret = vsir_cfg_structure_list_emit_jump(cfg, &structure->u.jump,
5569 loop_idx)) < 0)
5570 return ret;
5571 break;
5572
5573 default:
5575 }
5576 }
5577
5578 return VKD3D_OK;
5579}
5580
5582{
5584}
5585
5587 struct vkd3d_shader_message_context *message_context, struct vsir_cfg_emit_target *target,
5588 size_t *pos)
5589{
5590 enum vkd3d_result ret;
5591 struct vsir_cfg cfg;
5592
5593 if ((ret = vsir_cfg_init(&cfg, program, message_context, target, pos)) < 0)
5594 return ret;
5595
5597
5598 if ((ret = vsir_cfg_compute_loops(&cfg)) < 0)
5599 goto out;
5600
5601 if ((ret = vsir_cfg_sort_nodes(&cfg)) < 0)
5602 goto out;
5603
5605 goto out;
5606
5607 if ((ret = vsir_cfg_build_structured_program(&cfg)) < 0)
5608 goto out;
5609
5610 if ((ret = vsir_cfg_optimize(&cfg)) < 0)
5611 goto out;
5612
5614
5615out:
5616 vsir_cfg_cleanup(&cfg);
5617
5618 return ret;
5619}
5620
5623{
5624 struct vkd3d_shader_message_context *message_context = ctx->message_context;
5625 struct vsir_cfg_emit_target target = {0};
5626 enum vkd3d_result ret;
5627 size_t i;
5628
5629 VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS);
5630
5631 target.jump_target_temp_idx = program->temp_count;
5632 target.temp_count = program->temp_count + 1;
5633
5634 if (!reserve_instructions(&target.instructions, &target.ins_capacity, program->instructions.count))
5636
5637 for (i = 0; i < program->instructions.count;)
5638 {
5639 struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
5640
5641 switch (ins->opcode)
5642 {
5643 case VKD3DSIH_LABEL:
5644 VKD3D_ASSERT(program->shader_version.type != VKD3D_SHADER_TYPE_HULL);
5645 TRACE("Structurizing a non-hull shader.\n");
5646 if ((ret = vsir_program_structurize_function(program, message_context,
5647 &target, &i)) < 0)
5648 goto fail;
5649 VKD3D_ASSERT(i == program->instructions.count);
5650 break;
5651
5655 VKD3D_ASSERT(program->shader_version.type == VKD3D_SHADER_TYPE_HULL);
5656 TRACE("Structurizing phase %u of a hull shader.\n", ins->opcode);
5657 target.instructions[target.ins_count++] = *ins;
5658 ++i;
5659 if ((ret = vsir_program_structurize_function(program, message_context,
5660 &target, &i)) < 0)
5661 goto fail;
5662 break;
5663
5664 default:
5665 if (!reserve_instructions(&target.instructions, &target.ins_capacity, target.ins_count + 1))
5667 target.instructions[target.ins_count++] = *ins;
5668 ++i;
5669 break;
5670 }
5671 }
5672
5673 vkd3d_free(program->instructions.elements);
5674 program->instructions.elements = target.instructions;
5675 program->instructions.capacity = target.ins_capacity;
5676 program->instructions.count = target.ins_count;
5677 program->temp_count = target.temp_count;
5678 program->cf_type = VSIR_CF_STRUCTURED;
5679
5680 return VKD3D_OK;
5681
5682fail:
5683 vkd3d_free(target.instructions);
5684
5685 return ret;
5686}
5687
5689 struct vsir_block *block, struct vsir_block **origin_blocks)
5690{
5691 unsigned int i;
5692
5693 if (register_is_ssa(reg))
5694 {
5695 i = reg->idx[0].offset;
5696 if (alloc->table[i] == UINT_MAX && !vsir_block_dominates(origin_blocks[i], block))
5697 alloc->table[i] = alloc->next_temp_idx++;
5698 }
5699
5700 for (i = 0; i < reg->idx_count; ++i)
5701 if (reg->idx[i].rel_addr)
5702 register_map_undominated_use(&reg->idx[i].rel_addr->reg, alloc, block, origin_blocks);
5703}
5704
5705/* Drivers are not necessarily optimised to handle very large numbers of temps. For example,
5706 * using them only where necessary fixes stuttering issues in Horizon Zero Dawn on RADV.
5707 * This can also result in the backend emitting less code because temps typically need an
5708 * access chain and a load/store. Conversion of phi SSA values to temps should eliminate all
5709 * undominated SSA use, but structurisation may create new occurrences. */
5711{
5712 struct vsir_program *program = cfg->program;
5713 struct ssas_to_temps_alloc alloc = {0};
5714 struct vsir_block **origin_blocks;
5715 unsigned int j;
5716 size_t i;
5717
5718 if (!(origin_blocks = vkd3d_calloc(program->ssa_count, sizeof(*origin_blocks))))
5719 {
5720 ERR("Failed to allocate origin block array.\n");
5722 }
5723 if (!ssas_to_temps_alloc_init(&alloc, program->ssa_count, program->temp_count))
5724 {
5725 vkd3d_free(origin_blocks);
5727 }
5728
5729 for (i = 0; i < cfg->block_count; ++i)
5730 {
5731 struct vsir_block *block = &cfg->blocks[i];
5732 struct vkd3d_shader_instruction *ins;
5733
5734 if (block->label == 0)
5735 continue;
5736
5737 for (ins = block->begin; ins <= block->end; ++ins)
5738 {
5739 for (j = 0; j < ins->dst_count; ++j)
5740 {
5741 if (register_is_ssa(&ins->dst[j].reg))
5742 origin_blocks[ins->dst[j].reg.idx[0].offset] = block;
5743 }
5744 }
5745 }
5746
5747 for (i = 0; i < cfg->block_count; ++i)
5748 {
5749 struct vsir_block *block = &cfg->blocks[i];
5750 struct vkd3d_shader_instruction *ins;
5751
5752 if (block->label == 0)
5753 continue;
5754
5755 for (ins = block->begin; ins <= block->end; ++ins)
5756 {
5757 for (j = 0; j < ins->src_count; ++j)
5758 register_map_undominated_use(&ins->src[j].reg, &alloc, block, origin_blocks);
5759 }
5760 }
5761
5762 if (alloc.next_temp_idx == program->temp_count)
5763 goto done;
5764
5765 TRACE("Emitting temps for %u values with undominated usage.\n", alloc.next_temp_idx - program->temp_count);
5766
5767 for (i = cfg->function_begin; i < cfg->function_end; ++i)
5768 {
5769 struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
5770
5771 for (j = 0; j < ins->dst_count; ++j)
5773
5774 for (j = 0; j < ins->src_count; ++j)
5776 }
5777
5778 program->temp_count = alloc.next_temp_idx;
5779done:
5780 vkd3d_free(origin_blocks);
5781 vkd3d_free(alloc.table);
5782
5783 return VKD3D_OK;
5784}
5785
5787 struct vsir_program *program, struct vkd3d_shader_message_context *message_context,
5788 size_t *pos)
5789{
5790 enum vkd3d_result ret;
5791 struct vsir_cfg cfg;
5792
5793 if ((ret = vsir_cfg_init(&cfg, program, message_context, NULL, pos)) < 0)
5794 return ret;
5795
5797
5799
5800 vsir_cfg_cleanup(&cfg);
5801
5802 return ret;
5803}
5804
5807{
5808 struct vkd3d_shader_message_context *message_context = ctx->message_context;
5809 enum vkd3d_result ret;
5810 size_t i;
5811
5812 VKD3D_ASSERT(program->cf_type == VSIR_CF_BLOCKS);
5813
5814 for (i = 0; i < program->instructions.count;)
5815 {
5816 struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
5817
5818 switch (ins->opcode)
5819 {
5820 case VKD3DSIH_LABEL:
5821 VKD3D_ASSERT(program->shader_version.type != VKD3D_SHADER_TYPE_HULL);
5822 TRACE("Materializing undominated SSAs in a non-hull shader.\n");
5824 program, message_context, &i)) < 0)
5825 return ret;
5826 VKD3D_ASSERT(i == program->instructions.count);
5827 break;
5828
5832 VKD3D_ASSERT(program->shader_version.type == VKD3D_SHADER_TYPE_HULL);
5833 TRACE("Materializing undominated SSAs in phase %u of a hull shader.\n", ins->opcode);
5834 ++i;
5836 program, message_context, &i)) < 0)
5837 return ret;
5838 break;
5839
5840 default:
5841 ++i;
5842 break;
5843 }
5844 }
5845
5846 return VKD3D_OK;
5847}
5848
5850 struct vkd3d_shader_message_context *message_context, bool *flat)
5851{
5852 static const struct vkd3d_shader_location no_loc;
5853 const struct vkd3d_shader_parameter1 *parameter;
5854
5855 *flat = false;
5856
5858 return true;
5859
5861 {
5863 "Unsupported flat interpolation parameter type %#x.", parameter->type);
5864 return false;
5865 }
5867 {
5869 "Invalid flat interpolation parameter data type %#x.", parameter->data_type);
5870 return false;
5871 }
5872
5873 *flat = parameter->u.immediate_constant.u.u32;
5874 return true;
5875}
5876
5879{
5880 unsigned int i;
5881 bool flat;
5882
5883 if (program->shader_version.type != VKD3D_SHADER_TYPE_PIXEL || program->shader_version.major >= 4)
5884 return VKD3D_OK;
5885
5886 if (!use_flat_interpolation(program, ctx->message_context, &flat))
5888
5889 if (!flat)
5890 return VKD3D_OK;
5891
5892 for (i = 0; i < program->input_signature.element_count; ++i)
5893 {
5894 struct signature_element *element = &program->input_signature.elements[i];
5895
5896 if (!ascii_strcasecmp(element->semantic_name, "COLOR"))
5897 element->interpolation_mode = VKD3DSIM_CONSTANT;
5898 }
5899
5900 return VKD3D_OK;
5901}
5902
5904 const struct vkd3d_shader_instruction *ret, enum vkd3d_shader_comparison_func compare_func,
5905 const struct vkd3d_shader_parameter1 *ref, uint32_t colour_signature_idx,
5906 uint32_t colour_temp, size_t *ret_pos, struct vkd3d_shader_message_context *message_context)
5907{
5908 struct vkd3d_shader_instruction_array *instructions = &program->instructions;
5909 static const struct vkd3d_shader_location no_loc;
5910 size_t pos = ret - instructions->elements;
5911 struct vkd3d_shader_instruction *ins;
5912
5913 static const struct
5914 {
5915 enum vkd3d_shader_opcode float_opcode;
5916 enum vkd3d_shader_opcode uint_opcode;
5917 bool swap;
5918 }
5919 opcodes[] =
5920 {
5927 };
5928
5929 if (compare_func == VKD3D_SHADER_COMPARISON_FUNC_NEVER)
5930 {
5931 if (!shader_instruction_array_insert_at(&program->instructions, pos, 1))
5933 ins = &program->instructions.elements[pos];
5934
5937 src_param_init_const_uint(&ins->src[0], 0);
5938
5939 *ret_pos = pos + 1;
5940 return VKD3D_OK;
5941 }
5942
5943 if (!shader_instruction_array_insert_at(&program->instructions, pos, 3))
5945
5946 ins = &program->instructions.elements[pos];
5947
5948 switch (ref->data_type)
5949 {
5951 vsir_instruction_init_with_params(program, ins, &ret->location, opcodes[compare_func].float_opcode, 1, 2);
5952 src_param_init_temp_float(&ins->src[opcodes[compare_func].swap ? 1 : 0], colour_temp);
5953 src_param_init_parameter(&ins->src[opcodes[compare_func].swap ? 0 : 1],
5955 break;
5956
5958 vsir_instruction_init_with_params(program, ins, &ret->location, opcodes[compare_func].uint_opcode, 1, 2);
5959 src_param_init_temp_uint(&ins->src[opcodes[compare_func].swap ? 1 : 0], colour_temp);
5960 src_param_init_parameter(&ins->src[opcodes[compare_func].swap ? 0 : 1],
5962 break;
5963
5966 "Alpha test reference data type must be a single component.");
5968
5969 default:
5970 FIXME("Unhandled parameter data type %#x.\n", ref->data_type);
5972 }
5973
5974 dst_param_init_ssa_bool(&ins->dst[0], program->ssa_count);
5975 ins->src[opcodes[compare_func].swap ? 1 : 0].reg.dimension = VSIR_DIMENSION_VEC4;
5976 ins->src[opcodes[compare_func].swap ? 1 : 0].swizzle = VKD3D_SHADER_SWIZZLE(W, W, W, W);
5977
5978 ++ins;
5981 src_param_init_ssa_bool(&ins->src[0], program->ssa_count);
5982
5983 ++program->ssa_count;
5984
5985 ++ins;
5988 ins->dst[0].reg.idx[0].offset = colour_signature_idx;
5989 ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4;
5990 ins->dst[0].write_mask = program->output_signature.elements[colour_signature_idx].mask;
5991 src_param_init_temp_float(&ins->src[0], colour_temp);
5992 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4;
5993 ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE;
5994
5995 *ret_pos = pos + 3;
5996 return VKD3D_OK;
5997}
5998
6001{
6002 struct vkd3d_shader_message_context *message_context = ctx->message_context;
6003 const struct vkd3d_shader_parameter1 *func = NULL, *ref = NULL;
6004 uint32_t colour_signature_idx, colour_temp = ~0u;
6005 static const struct vkd3d_shader_location no_loc;
6006 enum vkd3d_shader_comparison_func compare_func;
6007 struct vkd3d_shader_instruction *ins;
6008 size_t new_pos;
6009 int ret;
6010
6011 if (program->shader_version.type != VKD3D_SHADER_TYPE_PIXEL)
6012 return VKD3D_OK;
6013
6014 if (!vsir_signature_find_sysval(&program->output_signature, VKD3D_SHADER_SV_TARGET, 0, &colour_signature_idx)
6015 || !(program->output_signature.elements[colour_signature_idx].mask & VKD3DSP_WRITEMASK_3))
6016 return VKD3D_OK;
6017
6020 return VKD3D_OK;
6021
6023 {
6025 "Unsupported alpha test function parameter type %#x.", func->type);
6027 }
6029 {
6031 "Invalid alpha test function parameter data type %#x.", func->data_type);
6033 }
6034 compare_func = func->u.immediate_constant.u.u32;
6035
6036 if (compare_func == VKD3D_SHADER_COMPARISON_FUNC_ALWAYS)
6037 return VKD3D_OK;
6038
6039 /* We're going to be reading from the output, so we need to go
6040 * through the whole shader and convert it to a temp. */
6041
6042 if (compare_func != VKD3D_SHADER_COMPARISON_FUNC_NEVER)
6043 colour_temp = program->temp_count++;
6044
6045 for (size_t i = 0; i < program->instructions.count; ++i)
6046 {
6047 ins = &program->instructions.elements[i];
6048
6049 if (vsir_instruction_is_dcl(ins))
6050 continue;
6051
6052 if (ins->opcode == VKD3DSIH_RET)
6053 {
6054 if ((ret = insert_alpha_test_before_ret(program, ins, compare_func,
6055 ref, colour_signature_idx, colour_temp, &new_pos, message_context)) < 0)
6056 return ret;
6057 i = new_pos;
6058 continue;
6059 }
6060
6061 /* No need to convert it if the comparison func is NEVER; we don't
6062 * read from the output in that case. */
6063 if (compare_func == VKD3D_SHADER_COMPARISON_FUNC_NEVER)
6064 continue;
6065
6066 for (size_t j = 0; j < ins->dst_count; ++j)
6067 {
6068 struct vkd3d_shader_dst_param *dst = &ins->dst[j];
6069
6070 /* Note we run after I/O normalization. */
6071 if (dst->reg.type == VKD3DSPR_OUTPUT && dst->reg.idx[0].offset == colour_signature_idx)
6072 {
6073 dst->reg.type = VKD3DSPR_TEMP;
6074 dst->reg.idx[0].offset = colour_temp;
6075 }
6076 }
6077 }
6078
6079 return VKD3D_OK;
6080}
6081
6083 const struct vkd3d_shader_instruction *ret, uint32_t mask, uint32_t position_signature_idx,
6084 uint32_t position_temp, uint32_t low_signature_idx, uint32_t high_signature_idx, size_t *ret_pos)
6085{
6086 struct vkd3d_shader_instruction_array *instructions = &program->instructions;
6087 size_t pos = ret - instructions->elements;
6088 struct vkd3d_shader_instruction *ins;
6089 unsigned int output_idx = 0;
6090
6093
6094 ins = &program->instructions.elements[pos];
6095
6096 for (unsigned int i = 0; i < 8; ++i)
6097 {
6098 if (!(mask & (1u << i)))
6099 continue;
6100
6102 src_param_init_temp_float4(&ins->src[0], position_temp);
6104 ins->src[1].swizzle = VKD3D_SHADER_NO_SWIZZLE;
6105 ins->src[1].reg.dimension = VSIR_DIMENSION_VEC4;
6106
6108 if (output_idx < 4)
6109 ins->dst[0].reg.idx[0].offset = low_signature_idx;
6110 else
6111 ins->dst[0].reg.idx[0].offset = high_signature_idx;
6112 ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4;
6113 ins->dst[0].write_mask = (1u << (output_idx % 4));
6114 ++output_idx;
6115
6116 ++ins;
6117 }
6118
6121 ins->dst[0].reg.idx[0].offset = position_signature_idx;
6122 ins->dst[0].reg.dimension = VSIR_DIMENSION_VEC4;
6123 ins->dst[0].write_mask = program->output_signature.elements[position_signature_idx].mask;
6124 src_param_init_temp_float(&ins->src[0], position_temp);
6125 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4;
6126 ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE;
6127
6128 *ret_pos = pos + vkd3d_popcount(mask) + 1;
6129 return VKD3D_OK;
6130}
6131
6134{
6135 struct shader_signature *signature = &program->output_signature;
6136 unsigned int low_signature_idx = ~0u, high_signature_idx = ~0u;
6137 const struct vkd3d_shader_parameter1 *mask_parameter = NULL;
6138 struct signature_element *new_elements, *clip_element;
6139 uint32_t position_signature_idx, position_temp, mask;
6140 static const struct vkd3d_shader_location no_loc;
6141 struct vkd3d_shader_instruction *ins;
6142 unsigned int plane_count;
6143 size_t new_pos;
6144 int ret;
6145
6146 if (program->shader_version.type != VKD3D_SHADER_TYPE_VERTEX)
6147 return VKD3D_OK;
6148
6149 for (unsigned int i = 0; i < program->parameter_count; ++i)
6150 {
6151 const struct vkd3d_shader_parameter1 *parameter = &program->parameters[i];
6152
6154 mask_parameter = parameter;
6155 }
6156
6157 if (!mask_parameter)
6158 return VKD3D_OK;
6159
6161 {
6163 "Unsupported clip plane mask parameter type %#x.", mask_parameter->type);
6165 }
6167 {
6169 "Invalid clip plane mask parameter data type %#x.", mask_parameter->data_type);
6171 }
6172 mask = mask_parameter->u.immediate_constant.u.u32;
6173
6174 if (!mask)
6175 return VKD3D_OK;
6176
6177 for (unsigned int i = 0; i < signature->element_count; ++i)
6178 {
6179 if (signature->elements[i].sysval_semantic == VKD3D_SHADER_SV_CLIP_DISTANCE)
6180 {
6182 "Clip planes cannot be used if the shader writes clip distance.");
6184 }
6185 }
6186
6187 if (!vsir_signature_find_sysval(signature, VKD3D_SHADER_SV_POSITION, 0, &position_signature_idx))
6188 {
6190 "Shader does not write position.");
6192 }
6193
6194 /* Append the clip plane signature indices. */
6195
6196 plane_count = vkd3d_popcount(mask);
6197
6198 if (!(new_elements = vkd3d_realloc(signature->elements,
6199 (signature->element_count + 2) * sizeof(*signature->elements))))
6201 signature->elements = new_elements;
6202
6203 low_signature_idx = signature->element_count;
6204 clip_element = &signature->elements[signature->element_count++];
6205 memset(clip_element, 0, sizeof(*clip_element));
6208 clip_element->register_count = 1;
6209 clip_element->mask = vkd3d_write_mask_from_component_count(min(plane_count, 4));
6210 clip_element->used_mask = clip_element->mask;
6212
6213 if (plane_count > 4)
6214 {
6215 high_signature_idx = signature->element_count;
6216 clip_element = &signature->elements[signature->element_count++];
6217 memset(clip_element, 0, sizeof(*clip_element));
6219 clip_element->semantic_index = 1;
6221 clip_element->register_count = 1;
6222 clip_element->mask = vkd3d_write_mask_from_component_count(plane_count - 4);
6223 clip_element->used_mask = clip_element->mask;
6225 }
6226
6227 /* We're going to be reading from the output position, so we need to go
6228 * through the whole shader and convert it to a temp. */
6229
6230 position_temp = program->temp_count++;
6231
6232 for (size_t i = 0; i < program->instructions.count; ++i)
6233 {
6234 ins = &program->instructions.elements[i];
6235
6236 if (vsir_instruction_is_dcl(ins))
6237 continue;
6238
6239 if (ins->opcode == VKD3DSIH_RET)
6240 {
6241 if ((ret = insert_clip_planes_before_ret(program, ins, mask, position_signature_idx,
6242 position_temp, low_signature_idx, high_signature_idx, &new_pos)) < 0)
6243 return ret;
6244 i = new_pos;
6245 continue;
6246 }
6247
6248 for (size_t j = 0; j < ins->dst_count; ++j)
6249 {
6250 struct vkd3d_shader_dst_param *dst = &ins->dst[j];
6251
6252 /* Note we run after I/O normalization. */
6253 if (dst->reg.type == VKD3DSPR_OUTPUT && dst->reg.idx[0].offset == position_signature_idx)
6254 {
6255 dst->reg.type = VKD3DSPR_TEMP;
6256 dst->reg.idx[0].offset = position_temp;
6257 }
6258 }
6259 }
6260
6261 return VKD3D_OK;
6262}
6263
6265{
6270}
6271
6273 const struct vkd3d_shader_instruction *ret, size_t *ret_pos)
6274{
6275 struct vkd3d_shader_instruction_array *instructions = &program->instructions;
6276 size_t pos = ret - instructions->elements;
6277 struct vkd3d_shader_instruction *ins;
6278
6279 if (!shader_instruction_array_insert_at(&program->instructions, pos, 1))
6281
6282 ins = &program->instructions.elements[pos];
6283
6286 ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE;
6288
6289 *ret_pos = pos + 1;
6290 return VKD3D_OK;
6291}
6292
6295{
6296 const struct vkd3d_shader_parameter1 *size_parameter = NULL;
6297 static const struct vkd3d_shader_location no_loc;
6298
6299 if (program->has_point_size)
6300 return VKD3D_OK;
6301
6302 if (!is_pre_rasterization_shader(program->shader_version.type))
6303 return VKD3D_OK;
6304
6305 for (unsigned int i = 0; i < program->parameter_count; ++i)
6306 {
6307 const struct vkd3d_shader_parameter1 *parameter = &program->parameters[i];
6308
6310 size_parameter = parameter;
6311 }
6312
6313 if (!size_parameter)
6314 return VKD3D_OK;
6315
6317 {
6319 "Invalid point size parameter data type %#x.", size_parameter->data_type);
6321 }
6322
6323 program->has_point_size = true;
6324
6325 /* Append a point size write before each ret. */
6326 for (size_t i = 0; i < program->instructions.count; ++i)
6327 {
6328 struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
6329
6330 if (ins->opcode == VKD3DSIH_RET)
6331 {
6332 size_t new_pos;
6333 int ret;
6334
6335 if ((ret = insert_point_size_before_ret(program, ins, &new_pos)) < 0)
6336 return ret;
6337 i = new_pos;
6338 }
6339 }
6340
6341 return VKD3D_OK;
6342}
6343
6346{
6347 const struct vkd3d_shader_parameter1 *min_parameter = NULL, *max_parameter = NULL;
6348 static const struct vkd3d_shader_location no_loc;
6349
6350 if (!program->has_point_size)
6351 return VKD3D_OK;
6352
6353 if (!is_pre_rasterization_shader(program->shader_version.type))
6354 return VKD3D_OK;
6355
6356 for (unsigned int i = 0; i < program->parameter_count; ++i)
6357 {
6358 const struct vkd3d_shader_parameter1 *parameter = &program->parameters[i];
6359
6361 min_parameter = parameter;
6362 else if (parameter->name == VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MAX)
6363 max_parameter = parameter;
6364 }
6365
6366 if (!min_parameter && !max_parameter)
6367 return VKD3D_OK;
6368
6369 if (min_parameter && min_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32)
6370 {
6372 "Invalid minimum point size parameter data type %#x.", min_parameter->data_type);
6374 }
6375
6376 if (max_parameter && max_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32)
6377 {
6379 "Invalid maximum point size parameter data type %#x.", max_parameter->data_type);
6381 }
6382
6383 /* Replace writes to the point size by inserting a clamp before each write. */
6384
6385 for (size_t i = 0; i < program->instructions.count; ++i)
6386 {
6387 struct vkd3d_shader_instruction *ins = &program->instructions.elements[i];
6388 const struct vkd3d_shader_location *loc;
6389 unsigned int ssa_value;
6390 bool clamp = false;
6391
6392 if (vsir_instruction_is_dcl(ins))
6393 continue;
6394
6395 for (size_t j = 0; j < ins->dst_count; ++j)
6396 {
6397 struct vkd3d_shader_dst_param *dst = &ins->dst[j];
6398
6399 /* Note we run after I/O normalization. */
6400 if (dst->reg.type == VKD3DSPR_RASTOUT)
6401 {
6403 ssa_value = program->ssa_count++;
6404 clamp = true;
6405 }
6406 }
6407
6408 if (!clamp)
6409 continue;
6410
6411 if (!shader_instruction_array_insert_at(&program->instructions, i + 1, !!min_parameter + !!max_parameter))
6413
6414 loc = &program->instructions.elements[i].location;
6415 ins = &program->instructions.elements[i + 1];
6416
6417 if (min_parameter)
6418 {
6420 src_param_init_ssa_float(&ins->src[0], ssa_value);
6422 if (max_parameter)
6423 {
6424 dst_param_init_ssa_float(&ins->dst[0], program->ssa_count);
6425 ssa_value = program->ssa_count++;
6426 }
6427 else
6428 {
6430 ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE;
6431 }
6432 ++ins;
6433 ++i;
6434 }
6435
6436 if (max_parameter)
6437 {
6439 src_param_init_ssa_float(&ins->src[0], ssa_value);
6442 ins->dst[0].reg.idx[0].offset = VSIR_RASTOUT_POINT_SIZE;
6443
6444 ++i;
6445 }
6446 }
6447
6448 return VKD3D_OK;
6449}
6450
6452{
6453 for (size_t i = 0; i < signature->element_count; ++i)
6454 {
6455 if (!ascii_strcasecmp(signature->elements[i].semantic_name, "TEXCOORD"))
6456 return true;
6457 }
6458 return false;
6459}
6460
6461/* Returns true if replacement was done. */
6463 struct vkd3d_shader_src_param *src, unsigned int coord_temp)
6464{
6465 uint32_t prev_swizzle = src->swizzle;
6466 const struct signature_element *e;
6467
6468 /* The input semantic may have a nontrivial mask, which we need to
6469 * correct for. E.g. if the mask is .yz, and we read from .y, that needs
6470 * to become .x. */
6471 static const uint32_t inverse_swizzles[16] =
6472 {
6473 /* Use _ for "undefined" components, for clarity. */
6474#define VKD3D_SHADER_SWIZZLE__ VKD3D_SHADER_SWIZZLE_X
6475 0,
6476 /* .x */ VKD3D_SHADER_SWIZZLE(X, _, _, _),
6477 /* .y */ VKD3D_SHADER_SWIZZLE(_, X, _, _),
6478 /* .xy */ VKD3D_SHADER_SWIZZLE(X, Y, _, _),
6479 /* .z */ VKD3D_SHADER_SWIZZLE(_, _, X, _),
6480 /* .xz */ VKD3D_SHADER_SWIZZLE(X, _, Y, _),
6481 /* .yz */ VKD3D_SHADER_SWIZZLE(_, X, Y, _),
6482 /* .xyz */ VKD3D_SHADER_SWIZZLE(X, Y, Z, _),
6483 /* .w */ VKD3D_SHADER_SWIZZLE(_, _, _, X),
6484 /* .xw */ VKD3D_SHADER_SWIZZLE(X, _, _, Y),
6485 /* .yw */ VKD3D_SHADER_SWIZZLE(_, X, _, Y),
6486 /* .xyw */ VKD3D_SHADER_SWIZZLE(X, Y, _, Z),
6487 /* .zw */ VKD3D_SHADER_SWIZZLE(_, _, X, Y),
6488 /* .xzw */ VKD3D_SHADER_SWIZZLE(X, _, Y, Z),
6489 /* .yzw */ VKD3D_SHADER_SWIZZLE(_, X, Y, Z),
6490 /* .xyzw */ VKD3D_SHADER_SWIZZLE(X, Y, Z, W),
6491#undef VKD3D_SHADER_SWIZZLE__
6492 };
6493
6494 if (src->reg.type != VKD3DSPR_INPUT)
6495 return false;
6496 e = &program->input_signature.elements[src->reg.idx[0].offset];
6497
6498 if (ascii_strcasecmp(e->semantic_name, "TEXCOORD"))
6499 return false;
6500
6501 src->reg.type = VKD3DSPR_TEMP;
6502 src->reg.idx[0].offset = coord_temp;
6503
6504 /* If the mask is already contiguous and zero-based, no need to remap
6505 * the swizzle. */
6506 if (!(e->mask & (e->mask + 1)))
6507 return true;
6508
6509 src->swizzle = 0;
6510 for (unsigned int i = 0; i < 4; ++i)
6511 {
6512 src->swizzle |= vsir_swizzle_get_component(inverse_swizzles[e->mask],
6514 }
6515
6516 return true;
6517}
6518
6521{
6522 const struct vkd3d_shader_parameter1 *sprite_parameter = NULL;
6523 static const struct vkd3d_shader_location no_loc;
6524 struct vkd3d_shader_instruction *ins;
6525 bool used_texcoord = false;
6526 unsigned int coord_temp;
6527 size_t i, insert_pos;
6528
6529 if (program->shader_version.type != VKD3D_SHADER_TYPE_PIXEL)
6530 return VKD3D_OK;
6531
6532 for (i = 0; i < program->parameter_count; ++i)
6533 {
6534 const struct vkd3d_shader_parameter1 *parameter = &program->parameters[i];
6535
6537 sprite_parameter = parameter;
6538 }
6539
6540 if (!sprite_parameter)
6541 return VKD3D_OK;
6542
6544 {
6546 "Unsupported point sprite parameter type %#x.", sprite_parameter->type);
6548 }
6549 if (sprite_parameter->data_type != VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32)
6550 {
6552 "Invalid point sprite parameter data type %#x.", sprite_parameter->data_type);
6554 }
6555 if (!sprite_parameter->u.immediate_constant.u.u32)
6556 return VKD3D_OK;
6557
6558 if (!has_texcoord_signature_element(&program->input_signature))
6559 return VKD3D_OK;
6560
6561 /* VKD3DSPR_POINTCOORD is a two-component value; fill the remaining two
6562 * components with zeroes. */
6563 coord_temp = program->temp_count++;
6564
6565 /* Construct the new temp after all LABEL, DCL, and NOP instructions.
6566 * We need to skip NOP instructions because they might result from removed
6567 * DCLs, and there could still be DCLs after NOPs. */
6568 for (i = 0; i < program->instructions.count; ++i)
6569 {
6570 ins = &program->instructions.elements[i];
6571
6572 if (!vsir_instruction_is_dcl(ins) && ins->opcode != VKD3DSIH_LABEL && ins->opcode != VKD3DSIH_NOP)
6573 break;
6574 }
6575
6576 insert_pos = i;
6577
6578 /* Replace each texcoord read with a read from the point coord. */
6579 for (; i < program->instructions.count; ++i)
6580 {
6581 ins = &program->instructions.elements[i];
6582
6583 if (vsir_instruction_is_dcl(ins))
6584 continue;
6585
6586 for (unsigned int j = 0; j < ins->src_count; ++j)
6587 {
6588 used_texcoord |= replace_texcoord_with_point_coord(program, &ins->src[j], coord_temp);
6589
6590 for (unsigned int k = 0; k < ins->src[j].reg.idx_count; ++k)
6591 {
6592 if (ins->src[j].reg.idx[k].rel_addr)
6594 ins->src[j].reg.idx[k].rel_addr, coord_temp);
6595 }
6596 }
6597
6598 for (unsigned int j = 0; j < ins->dst_count; ++j)
6599 {
6600 for (unsigned int k = 0; k < ins->dst[j].reg.idx_count; ++k)
6601 {
6602 if (ins->dst[j].reg.idx[k].rel_addr)
6604 ins->dst[j].reg.idx[k].rel_addr, coord_temp);
6605 }
6606 }
6607 }
6608
6609 if (used_texcoord)
6610 {
6611 if (!shader_instruction_array_insert_at(&program->instructions, insert_pos, 2))
6613
6614 ins = &program->instructions.elements[insert_pos];
6615
6617 dst_param_init_temp_float4(&ins->dst[0], coord_temp);
6618 ins->dst[0].write_mask = VKD3DSP_WRITEMASK_0 | VKD3DSP_WRITEMASK_1;
6620 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4;
6621 ins->src[0].swizzle = VKD3D_SHADER_NO_SWIZZLE;
6622 ++ins;
6623
6625 dst_param_init_temp_float4(&ins->dst[0], coord_temp);
6626 ins->dst[0].write_mask = VKD3DSP_WRITEMASK_2 | VKD3DSP_WRITEMASK_3;
6628 ins->src[0].reg.dimension = VSIR_DIMENSION_VEC4;
6629 ++ins;
6630
6631 program->has_point_coord = true;
6632 }
6633
6634 return VKD3D_OK;
6635}
6636
6638{
6640 const struct vsir_program *program;
6648
6650 {
6654
6656 {
6664
6666 size_t depth;
6668};
6669
6670static void VKD3D_PRINTF_FUNC(3, 4) validator_error(struct validation_context *ctx,
6672{
6673 struct vkd3d_string_buffer buf;
6674 va_list args;
6675
6677
6680 va_end(args);
6681
6682 if (ctx->invalid_instruction_idx)
6683 {
6684 vkd3d_shader_error(ctx->message_context, &ctx->null_location, error, "%s", buf.buffer);
6685 WARN("VSIR validation error: %s\n", buf.buffer);
6686 }
6687 else
6688 {
6689 const struct vkd3d_shader_instruction *ins = &ctx->program->instructions.elements[ctx->instruction_idx];
6690 vkd3d_shader_error(ctx->message_context, &ins->location, error,
6691 "instruction %zu: %s", ctx->instruction_idx + 1, buf.buffer);
6692 WARN("VSIR validation error: instruction %zu: %s\n", ctx->instruction_idx + 1, buf.buffer);
6693 }
6694
6696
6697 if (!ctx->status)
6699}
6700
6702 const struct vkd3d_shader_register *reg)
6703{
6704 if (reg->idx_count != 0)
6706 "Invalid index count %u for a register of type %#x.",
6707 reg->idx_count, reg->type);
6708}
6709
6711 const struct vkd3d_shader_register *reg)
6712{
6713 const struct shader_signature *signature;
6714 bool has_control_point = false;
6715
6716 switch (reg->type)
6717 {
6718 case VKD3DSPR_INPUT:
6719 signature = &ctx->program->input_signature;
6720
6721 switch (ctx->program->shader_version.type)
6722 {
6726 has_control_point = true;
6727 break;
6728
6729 default:
6730 break;
6731 }
6732 break;
6733
6734 case VKD3DSPR_OUTPUT:
6735 switch (ctx->program->shader_version.type)
6736 {
6739 || ctx->program->normalisation_level >= VSIR_FULLY_NORMALISED_IO)
6740 {
6741 signature = &ctx->program->output_signature;
6742 has_control_point = ctx->program->normalisation_level >= VSIR_NORMALISED_HULL_CONTROL_POINT_IO;
6743 }
6744 else
6745 {
6746 signature = &ctx->program->patch_constant_signature;
6747 }
6748 break;
6749
6750 default:
6751 signature = &ctx->program->output_signature;
6752 break;
6753 }
6754 break;
6755
6757 signature = &ctx->program->input_signature;
6758 has_control_point = true;
6759 break;
6760
6762 signature = &ctx->program->output_signature;
6763 has_control_point = true;
6764 break;
6765
6767 signature = &ctx->program->patch_constant_signature;
6768 break;
6769
6770 default:
6772 }
6773
6774 if (ctx->program->normalisation_level < VSIR_FULLY_NORMALISED_IO)
6775 {
6776 /* Indices are [register] or [control point, register]. Both are
6777 * allowed to have a relative address. */
6778 unsigned int expected_idx_count = 1 + !!has_control_point;
6779
6780 if (reg->idx_count != expected_idx_count)
6781 {
6783 "Invalid index count %u for a register of type %#x.",
6784 reg->idx_count, reg->type);
6785 return;
6786 }
6787 }
6788 else
6789 {
6790 struct signature_element *element;
6791 unsigned int expected_idx_count;
6792 unsigned int signature_idx;
6793 bool is_array = false;
6794
6795 /* If the signature element is not an array, indices are
6796 * [signature] or [control point, signature]. If the signature
6797 * element is an array, indices are [array, signature] or
6798 * [control point, array, signature]. In any case `signature' is
6799 * not allowed to have a relative address, while the others are.
6800 */
6801 if (reg->idx_count < 1)
6802 {
6804 "Invalid index count %u for a register of type %#x.",
6805 reg->idx_count, reg->type);
6806 return;
6807 }
6808
6809 if (reg->idx[reg->idx_count - 1].rel_addr)
6810 {
6812 "Non-NULL relative address for the signature index of a register of type %#x.",
6813 reg->type);
6814 return;
6815 }
6816
6817 signature_idx = reg->idx[reg->idx_count - 1].offset;
6818
6819 if (signature_idx >= signature->element_count)
6820 {
6822 "Signature index %u exceeds the signature size %u in a register of type %#x.",
6823 signature_idx, signature->element_count, reg->type);
6824 return;
6825 }
6826
6827 element = &signature->elements[signature_idx];
6828 if (element->register_count > 1 || vsir_sysval_semantic_is_tess_factor(element->sysval_semantic))
6829 is_array = true;
6830
6831 expected_idx_count = 1 + !!has_control_point + !!is_array;
6832
6833 if (reg->idx_count != expected_idx_count)
6834 {
6836 "Invalid index count %u for a register of type %#x.",
6837 reg->idx_count, reg->type);
6838 return;
6839 }
6840 }
6841}
6842
6844 const struct vkd3d_shader_register *reg)
6845{
6846 struct validation_context_temp_data *data;
6847
6848 if (reg->idx_count != 1)
6849 {
6851 "Invalid index count %u for a TEMP register.",
6852 reg->idx_count);
6853 return;
6854 }
6855
6856 if (reg->idx[0].rel_addr)
6858 "Non-NULL relative address for a TEMP register.");
6859
6860 if (reg->idx[0].offset >= ctx->program->temp_count)
6861 {
6863 "TEMP register index %u exceeds the maximum count %u.",
6864 reg->idx[0].offset, ctx->program->temp_count);
6865 return;
6866 }
6867
6868 data = &ctx->temps[reg->idx[0].offset];
6869
6870 if (reg->dimension == VSIR_DIMENSION_NONE)
6871 {
6873 "Invalid dimension NONE for a TEMP register.");
6874 return;
6875 }
6876
6877 /* TEMP registers can be scalar or vec4, provided that
6878 * each individual register always appears with the same
6879 * dimension. */
6880 if (data->dimension == VSIR_DIMENSION_NONE)
6881 {
6882 data->dimension = reg->dimension;
6883 data->first_seen = ctx->instruction_idx;
6884 }
6885 else if (data->dimension != reg->dimension)
6886 {
6888 "Invalid dimension %#x for a TEMP register: "
6889 "it has already been seen with dimension %#x at instruction %zu.",
6890 reg->dimension, data->dimension, data->first_seen);
6891 }
6892}
6893
6895 const struct vkd3d_shader_register *reg)
6896{
6897 if (reg->idx_count != 1)
6898 {
6900 "Invalid index count %u for a RASTOUT register.",
6901 reg->idx_count);
6902 return;
6903 }
6904
6905 if (reg->idx[0].rel_addr)
6907 "Non-NULL relative address for a RASTOUT register.");
6908
6909 if (reg->idx[0].offset >= 3)
6911 "Invalid offset for a RASTOUT register.");
6912}
6913
6915 const struct vkd3d_shader_register *reg)
6916{
6917 if (reg->idx_count != 1)
6918 {
6920 "Invalid index count %u for a MISCTYPE register.",
6921 reg->idx_count);
6922 return;
6923 }
6924
6925 if (reg->idx[0].rel_addr)
6927 "Non-NULL relative address for a MISCTYPE register.");
6928
6929 if (reg->idx[0].offset >= 2)
6931 "Invalid offset for a MISCTYPE register.");
6932}
6933
6935 const struct vkd3d_shader_register *reg)
6936{
6939 "Invalid precision %#x for a LABEL register.", reg->precision);
6940
6941 if (reg->data_type != VKD3D_DATA_UNUSED)
6943 "Invalid data type %#x for a LABEL register.", reg->data_type);
6944
6945 if (reg->dimension != VSIR_DIMENSION_NONE)
6947 "Invalid dimension %#x for a LABEL register.", reg->dimension);
6948
6949 if (reg->idx_count != 1)
6950 {
6952 "Invalid index count %u for a LABEL register.", reg->idx_count);
6953 return;
6954 }
6955
6956 if (reg->idx[0].rel_addr)
6958 "Non-NULL relative address for a LABEL register.");
6959
6960 /* Index == 0 is invalid, but it is temporarily allowed
6961 * for intermediate stages. Once we support validation
6962 * dialects we can selectively check for that. */
6963 if (reg->idx[0].offset > ctx->program->block_count)
6965 "LABEL register index %u exceeds the maximum count %u.",
6966 reg->idx[0].offset, ctx->program->block_count);
6967}
6968
6970 const struct vkd3d_shader_register *reg)
6971{
6974 "Invalid precision %#x for a SAMPLER register.", reg->precision);
6975
6976 if (reg->data_type != VKD3D_DATA_UNUSED)
6978 "Invalid data type %#x for a SAMPLER register.", reg->data_type);
6979
6980 /* VEC4 is allowed in gather operations. */
6981 if (reg->dimension == VSIR_DIMENSION_SCALAR)
6983 "Invalid dimension SCALAR for a SAMPLER register.");
6984
6985 if (reg->idx_count != 2)
6986 {
6988 "Invalid index count %u for a SAMPLER register.", reg->idx_count);
6989 return;
6990 }
6991
6992 if (reg->idx[0].rel_addr)
6994 "Non-NULL relative address for the descriptor index of a SAMPLER register.");
6995}
6996
6998 const struct vkd3d_shader_register *reg)
6999{
7002 "Invalid precision %#x for a RESOURCE register.", reg->precision);
7003
7004 if (reg->data_type != VKD3D_DATA_UNUSED)
7006 "Invalid data type %#x for a RESOURCE register.", reg->data_type);
7007
7008 if (reg->dimension != VSIR_DIMENSION_VEC4)
7010 "Invalid dimension %#x for a RESOURCE register.", reg->dimension);
7011
7012 if (reg->idx_count != 2)
7013 {
7015 "Invalid index count %u for a RESOURCE register.", reg->idx_count);
7016 return;
7017 }
7018
7019 if (reg->idx[0].rel_addr)
7021 "Non-NULL relative address for the descriptor index of a RESOURCE register.");
7022}
7023
7025 const struct vkd3d_shader_register *reg)
7026{
7029 "Invalid precision %#x for a UAV register.",
7030 reg->precision);
7031
7032 if (reg->data_type != VKD3D_DATA_UNUSED)
7034 "Invalid data type %#x for a UAV register.",
7035 reg->data_type);
7036
7037 /* NONE is allowed in counter operations. */
7038 if (reg->dimension == VSIR_DIMENSION_SCALAR)
7040 "Invalid dimension %#x for a UAV register.",
7041 reg->dimension);
7042
7043 if (reg->idx_count != 2)
7044 {
7046 "Invalid index count %u for a UAV register.",
7047 reg->idx_count);
7048 return;
7049 }
7050
7051 if (reg->idx[0].rel_addr)
7053 "Non-NULL relative address for the descriptor index of a UAV register.");
7054}
7055
7057 const struct vkd3d_shader_register *reg)
7058{
7059 struct validation_context_ssa_data *data;
7060
7061 if (reg->idx_count != 1)
7062 {
7064 "Invalid index count %u for a SSA register.",
7065 reg->idx_count);
7066 return;
7067 }
7068
7069 if (reg->idx[0].rel_addr)
7071 "Non-NULL relative address for a SSA register.");
7072
7073 if (reg->idx[0].offset >= ctx->program->ssa_count)
7074 {
7076 "SSA register index %u exceeds the maximum count %u.",
7077 reg->idx[0].offset, ctx->program->ssa_count);
7078 return;
7079 }
7080
7081 data = &ctx->ssas[reg->idx[0].offset];
7082
7083 if (reg->dimension == VSIR_DIMENSION_NONE)
7084 {
7086 "Invalid dimension NONE for a SSA register.");
7087 return;
7088 }
7089
7090 /* SSA registers can be scalar or vec4, provided that each
7091 * individual register always appears with the same
7092 * dimension. */
7093 if (data->dimension == VSIR_DIMENSION_NONE)
7094 {
7095 data->dimension = reg->dimension;
7096 data->data_type = reg->data_type;
7097 data->first_seen = ctx->instruction_idx;
7098 }
7099 else
7100 {
7101 if (data->dimension != reg->dimension)
7103 "Invalid dimension %#x for a SSA register: "
7104 "it has already been seen with dimension %#x at instruction %zu.",
7105 reg->dimension, data->dimension, data->first_seen);
7106
7107 if (data_type_is_64_bit(data->data_type) != data_type_is_64_bit(reg->data_type))
7109 "Invalid data type %#x for a SSA register: "
7110 "it has already been seen with data type %#x at instruction %zu.",
7111 reg->data_type, data->data_type, data->first_seen);
7112 }
7113}
7114
7116 const struct vkd3d_shader_src_param *src);
7117
7119 const struct vkd3d_shader_register *reg)
7120{
7121 unsigned int i;
7122
7123 if (reg->type >= VKD3DSPR_COUNT)
7124 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE, "Invalid register type %#x.",
7125 reg->type);
7126
7128 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION, "Invalid register precision %#x.",
7129 reg->precision);
7130
7131 if (reg->data_type >= VKD3D_DATA_COUNT)
7132 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE, "Invalid register data type %#x.",
7133 reg->data_type);
7134
7135 if (reg->dimension >= VSIR_DIMENSION_COUNT)
7136 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION, "Invalid register dimension %#x.",
7137 reg->dimension);
7138
7139 if (reg->idx_count > ARRAY_SIZE(reg->idx))
7140 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT, "Invalid register index count %u.",
7141 reg->idx_count);
7142
7143 for (i = 0; i < min(reg->idx_count, ARRAY_SIZE(reg->idx)); ++i)
7144 {
7145 const struct vkd3d_shader_src_param *param = reg->idx[i].rel_addr;
7146 if (reg->idx[i].rel_addr)
7148 }
7149
7150 switch (reg->type)
7151 {
7152 case VKD3DSPR_TEMP:
7154 break;
7155
7156 case VKD3DSPR_INPUT:
7158 break;
7159
7160 case VKD3DSPR_RASTOUT:
7162 break;
7163
7164 case VKD3DSPR_OUTPUT:
7166 break;
7167
7168 case VKD3DSPR_DEPTHOUT:
7170 break;
7171
7172 case VKD3DSPR_MISCTYPE:
7174 break;
7175
7176 case VKD3DSPR_LABEL:
7178 break;
7179
7180 case VKD3DSPR_IMMCONST:
7182 break;
7183
7186 break;
7187
7188 case VKD3DSPR_NULL:
7190 break;
7191
7192 case VKD3DSPR_SAMPLER:
7194 break;
7195
7196 case VKD3DSPR_RESOURCE:
7198 break;
7199
7200 case VKD3DSPR_UAV:
7202 break;
7203
7206 break;
7207
7210 break;
7211
7214 break;
7215
7218 break;
7219
7222 break;
7223
7224 case VKD3DSPR_SSA:
7226 break;
7227
7228 default:
7229 break;
7230 }
7231}
7232
7234 const struct vkd3d_shader_dst_param *dst)
7235{
7237
7238 if (dst->write_mask & ~VKD3DSP_WRITEMASK_ALL)
7239 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Destination has invalid write mask %#x.",
7240 dst->write_mask);
7241
7242 switch (dst->reg.dimension)
7243 {
7245 if (dst->write_mask != VKD3DSP_WRITEMASK_0)
7246 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Scalar destination has invalid write mask %#x.",
7247 dst->write_mask);
7248 break;
7249
7251 if (dst->write_mask == 0)
7252 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Vec4 destination has empty write mask.");
7253 break;
7254
7255 default:
7256 if (dst->write_mask != 0)
7257 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK, "Destination of dimension %u has invalid write mask %#x.",
7258 dst->reg.dimension, dst->write_mask);
7259 break;
7260 }
7261
7262 if (dst->modifiers & ~VKD3DSPDM_MASK)
7263 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Destination has invalid modifiers %#x.",
7264 dst->modifiers);
7265
7266 switch (dst->shift)
7267 {
7268 case 0:
7269 case 1:
7270 case 2:
7271 case 3:
7272 case 13:
7273 case 14:
7274 case 15:
7275 break;
7276
7277 default:
7278 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SHIFT, "Destination has invalid shift %#x.",
7279 dst->shift);
7280 }
7281
7282 switch (dst->reg.type)
7283 {
7284 case VKD3DSPR_SSA:
7285 if (dst->reg.idx[0].offset < ctx->program->ssa_count)
7286 {
7287 struct validation_context_ssa_data *data = &ctx->ssas[dst->reg.idx[0].offset];
7288
7289 if (data->write_mask == 0)
7290 {
7291 data->write_mask = dst->write_mask;
7292 data->first_assigned = ctx->instruction_idx;
7293 }
7294 else
7295 {
7297 "SSA register is already assigned at instruction %zu.",
7298 data->first_assigned);
7299 }
7300 }
7301 break;
7302
7303 case VKD3DSPR_IMMCONST:
7305 case VKD3DSPR_SAMPLER:
7306 case VKD3DSPR_RESOURCE:
7307 case VKD3DSPR_INPUT:
7309 "Invalid %#x register used as destination parameter.", dst->reg.type);
7310 break;
7311
7313 if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL)
7315 "PATCHCONST register used as destination parameters are only allowed in Hull Shaders.");
7316 break;
7317
7318 default:
7319 break;
7320 }
7321}
7322
7324 const struct vkd3d_shader_src_param *src)
7325{
7327
7328 if (src->swizzle & ~0x03030303u)
7329 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, "Source has invalid swizzle %#x.",
7330 src->swizzle);
7331
7332 if (src->reg.dimension != VSIR_DIMENSION_VEC4 && src->swizzle != 0)
7333 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE, "Source of dimension %u has invalid swizzle %#x.",
7334 src->reg.dimension, src->swizzle);
7335
7336 if (src->modifiers >= VKD3DSPSM_COUNT)
7337 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS, "Source has invalid modifiers %#x.",
7338 src->modifiers);
7339
7340 switch (src->reg.type)
7341 {
7342 case VKD3DSPR_SSA:
7343 if (src->reg.idx[0].offset < ctx->program->ssa_count)
7344 {
7345 struct validation_context_ssa_data *data = &ctx->ssas[src->reg.idx[0].offset];
7346 unsigned int i;
7347
7348 for (i = 0; i < VKD3D_VEC4_SIZE; ++i)
7349 data->read_mask |= (1u << vsir_swizzle_get_component(src->swizzle, i));
7350 }
7351 break;
7352
7353 case VKD3DSPR_NULL:
7355 "Invalid NULL register used as source parameter.");
7356 break;
7357
7358 case VKD3DSPR_OUTPUT:
7359 if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL
7360 || (ctx->phase != VKD3DSIH_HS_FORK_PHASE && ctx->phase != VKD3DSIH_HS_JOIN_PHASE))
7362 "Invalid OUTPUT register used as source parameter.");
7363 break;
7364
7366 if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_DOMAIN
7367 && ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL)
7369 "PATCHCONST register used as source parameters are only allowed in Hull and Domain Shaders.");
7370 break;
7371
7372 default:
7373 break;
7374 }
7375}
7376
7378 const struct vkd3d_shader_instruction *instruction, unsigned int count)
7379{
7380 if (instruction->dst_count != count)
7382 "Invalid destination count %u for an instruction of type %#x, expected %u.",
7383 instruction->dst_count, instruction->opcode, count);
7384}
7385
7387 const struct vkd3d_shader_instruction *instruction, unsigned int count)
7388{
7389 if (instruction->src_count != count)
7391 "Invalid source count %u for an instruction of type %#x, expected %u.",
7392 instruction->src_count, instruction->opcode, count);
7393}
7394
7396 const struct vkd3d_shader_instruction *instruction, unsigned int count)
7397{
7398 if (instruction->src_count < count)
7399 {
7401 "Invalid source count %u for an instruction of type %#x, expected at least %u.",
7402 instruction->src_count, instruction->opcode, count);
7403 return false;
7404 }
7405
7406 return true;
7407}
7408
7410 const struct vkd3d_shader_instruction *instruction, unsigned int count)
7411{
7412 if (instruction->src_count > count)
7413 {
7415 "Invalid source count %u for an instruction of type %#x, expected at most %u.",
7416 instruction->src_count, instruction->opcode, count);
7417 return false;
7418 }
7419
7420 return true;
7421}
7422
7424{
7428};
7429
7430static const char * const signature_type_names[] =
7431{
7432 [SIGNATURE_TYPE_INPUT] = "input",
7433 [SIGNATURE_TYPE_OUTPUT] = "output",
7434 [SIGNATURE_TYPE_PATCH_CONSTANT] = "patch constant",
7435};
7436
7437#define PS_BIT (1u << VKD3D_SHADER_TYPE_PIXEL)
7438#define VS_BIT (1u << VKD3D_SHADER_TYPE_VERTEX)
7439#define GS_BIT (1u << VKD3D_SHADER_TYPE_GEOMETRY)
7440#define HS_BIT (1u << VKD3D_SHADER_TYPE_HULL)
7441#define DS_BIT (1u << VKD3D_SHADER_TYPE_DOMAIN)
7442#define CS_BIT (1u << VKD3D_SHADER_TYPE_COMPUTE)
7443
7445{
7446 unsigned int input;
7447 unsigned int output;
7448 unsigned int patch_constant;
7450 unsigned int component_count;
7451}
7453{
7467
7469 const struct shader_signature *signature, enum vsir_signature_type signature_type,
7470 unsigned int idx)
7471{
7472 const char *signature_type_name = signature_type_names[signature_type];
7473 const struct signature_element *element = &signature->elements[idx];
7474 bool integer_type = false;
7475
7476 if (element->register_count == 0)
7478 "element %u of %s signature: Invalid zero register count.", idx, signature_type_name);
7479
7480 if (element->mask == 0 || (element->mask & ~0xf))
7482 "element %u of %s signature: Invalid mask %#x.", idx, signature_type_name, element->mask);
7483
7486 "element %u of %s signature: Non-contiguous mask %#x.",
7487 idx, signature_type_name, element->mask);
7488
7489 /* Here we'd likely want to validate that the usage mask is a subset of the
7490 * signature mask. Unfortunately the D3DBC parser sometimes violates this.
7491 * For example I've seen a shader like this:
7492 * ps_3_0
7493 * [...]
7494 * dcl_texcoord0 v0
7495 * [...]
7496 * texld r2.xyzw, v0.xyzw, s1.xyzw
7497 * [...]
7498 *
7499 * The dcl_textcoord0 instruction secretly has a .xy mask, which is used to
7500 * compute the signature mask, but the texld instruction apparently uses all
7501 * the components. Of course the last two components are ignored, but
7502 * formally they seem to be used. So we end up with a signature element with
7503 * mask .xy and usage mask .xyzw.
7504 *
7505 * The correct fix would probably be to make the D3DBC parser aware of which
7506 * components are really used for each instruction, but that would take some
7507 * time. */
7508 if (element->used_mask & ~0xf)
7510 "element %u of %s signature: Invalid usage mask %#x.",
7511 idx, signature_type_name, element->used_mask);
7512
7513 switch (element->sysval_semantic)
7514 {
7538 break;
7539
7540 default:
7542 "element %u of %s signature: Invalid system value semantic %#x.",
7543 idx, signature_type_name, element->sysval_semantic);
7544 break;
7545 }
7546
7547 if (element->sysval_semantic < ARRAY_SIZE(sysval_validation_data))
7548 {
7549 const struct sysval_validation_data_element *data = &sysval_validation_data[element->sysval_semantic];
7550
7551 if (data->input || data->output || data->patch_constant)
7552 {
7553 unsigned int mask;
7554
7555 switch (signature_type)
7556 {
7558 mask = data->input;
7559 break;
7560
7562 mask = data->output;
7563 break;
7564
7566 mask = data->patch_constant;
7567 break;
7568
7569 default:
7571 }
7572
7573 if (!(mask & (1u << ctx->program->shader_version.type)))
7575 "element %u of %s signature: Invalid system value semantic %#x.",
7576 idx, signature_type_name, element->sysval_semantic);
7577 }
7578
7579 if (data->component_count != 0)
7580 {
7581 if (element->component_type != data->data_type)
7583 "element %u of %s signature: Invalid data type %#x for system value semantic %#x.",
7584 idx, signature_type_name, element->component_type, element->sysval_semantic);
7585
7586 if (vsir_write_mask_component_count(element->mask) > data->component_count)
7588 "element %u of %s signature: Invalid mask %#x for system value semantic %#x.",
7589 idx, signature_type_name, element->mask, element->sysval_semantic);
7590 }
7591 }
7592
7593 switch (element->component_type)
7594 {
7597 integer_type = true;
7598 break;
7599
7601 break;
7602
7603 default:
7605 "element %u of %s signature: Invalid component type %#x.",
7606 idx, signature_type_name, element->component_type);
7607 break;
7608 }
7609
7610 if (element->min_precision >= VKD3D_SHADER_MINIMUM_PRECISION_COUNT)
7612 "element %u of %s signature: Invalid minimum precision %#x.",
7613 idx, signature_type_name, element->min_precision);
7614
7615 if (element->interpolation_mode >= VKD3DSIM_COUNT)
7617 "element %u of %s signature: Invalid interpolation mode %#x.",
7618 idx, signature_type_name, element->interpolation_mode);
7619
7620 if (integer_type && element->interpolation_mode != VKD3DSIM_NONE
7621 && element->interpolation_mode != VKD3DSIM_CONSTANT)
7623 "element %u of %s signature: Invalid interpolation mode %#x for integer component type.",
7624 idx, signature_type_name, element->interpolation_mode);
7625}
7626
7627static const unsigned int allowed_signature_phases[] =
7628{
7632};
7633
7635 const struct shader_signature *signature, enum vsir_signature_type signature_type)
7636{
7637 unsigned int i;
7638
7639 if (signature->element_count != 0 && !(allowed_signature_phases[signature_type]
7640 & (1u << ctx->program->shader_version.type)))
7642 "Unexpected %s signature.", signature_type_names[signature_type]);
7643
7644 for (i = 0; i < signature->element_count; ++i)
7646}
7647
7649{
7650 switch (type)
7651 {
7652 case VSIR_CF_STRUCTURED:
7653 return "structured";
7654 case VSIR_CF_BLOCKS:
7655 return "block-based";
7656 default:
7658 }
7659}
7660
7662 const struct vkd3d_shader_instruction *instruction, enum vsir_control_flow_type expected_type)
7663{
7664 if (ctx->program->cf_type != expected_type)
7665 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Invalid instruction %#x in %s shader.",
7666 instruction->opcode, name_from_cf_type(ctx->program->cf_type));
7667}
7668
7670{
7671 if (!vkd3d_array_reserve((void **)&ctx->blocks, &ctx->blocks_capacity, ctx->depth + 1, sizeof(*ctx->blocks)))
7672 {
7674 return;
7675 }
7676 ctx->blocks[ctx->depth++] = opcode;
7677}
7678
7681{
7682 if (ctx->program->shader_version.type != VKD3D_SHADER_TYPE_HULL)
7684 "Phase instruction %#x is only valid in a hull shader.",
7686 if (ctx->depth != 0)
7688 "Phase instruction %#x must appear to top level.",
7690 ctx->phase = instruction->opcode;
7691 ctx->dcl_temps_found = false;
7692}
7693
7695{
7696 size_t i;
7697
7700
7702 return;
7703
7705 {
7706 /* Unconditional branch: parameters are jump label,
7707 * optional merge label, optional continue label. */
7709
7710 for (i = 0; i < instruction->src_count; ++i)
7711 {
7714 "Invalid register of type %#x in unconditional BRANCH instruction, expected LABEL.",
7715 instruction->src[i].reg.type);
7716 }
7717 }
7718 else
7719 {
7720 /* Conditional branch: parameters are condition, true
7721 * jump label, false jump label, optional merge label,
7722 * optional continue label. */
7725
7726 for (i = 1; i < instruction->src_count; ++i)
7727 {
7730 "Invalid register of type %#x in conditional BRANCH instruction, expected LABEL.",
7731 instruction->src[i].reg.type);
7732 }
7733 }
7734
7735 ctx->inside_block = false;
7736}
7737
7740{
7741 if (!instruction->declaration.count || instruction->declaration.count > 32)
7742 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS instance count %u is invalid.",
7743 instruction->declaration.count);
7744}
7745
7748{
7749 /* Exclude non-finite values. */
7750 if (!(instruction->declaration.max_tessellation_factor >= 1.0f
7751 && instruction->declaration.max_tessellation_factor <= 64.0f))
7753 "Max tessellation factor %f is invalid.",
7754 instruction->declaration.max_tessellation_factor);
7755}
7756
7759{
7760 if (instruction->declaration.primitive_type.type == VKD3D_PT_UNDEFINED
7761 || instruction->declaration.primitive_type.type >= VKD3D_PT_COUNT)
7762 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS input primitive %u is invalid.",
7763 instruction->declaration.primitive_type.type);
7764}
7765
7768{
7769 if (!instruction->declaration.count || instruction->declaration.count > 32)
7771 "Output control point count %u is invalid.",
7772 instruction->declaration.count);
7773}
7774
7777{
7778 if (instruction->declaration.primitive_type.type == VKD3D_PT_UNDEFINED
7779 || instruction->declaration.primitive_type.type >= VKD3D_PT_COUNT)
7780 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS output primitive %u is invalid.",
7781 instruction->declaration.primitive_type.type);
7782}
7783
7786{
7787 if (ctx->dcl_temps_found)
7789 "Duplicate DCL_TEMPS instruction.");
7790 if (instruction->declaration.count > ctx->program->temp_count)
7792 "Invalid DCL_TEMPS count %u, expected at most %u.",
7793 instruction->declaration.count, ctx->program->temp_count);
7794 ctx->dcl_temps_found = true;
7795}
7796
7799{
7800 if (instruction->declaration.tessellator_domain == VKD3D_TESSELLATOR_DOMAIN_INVALID
7801 || instruction->declaration.tessellator_domain >= VKD3D_TESSELLATOR_DOMAIN_COUNT)
7803 "Tessellator domain %#x is invalid.", instruction->declaration.tessellator_domain);
7804}
7805
7808{
7809 if (!instruction->declaration.tessellator_output_primitive
7810 || instruction->declaration.tessellator_output_primitive
7813 "Tessellator output primitive %#x is invalid.",
7814 instruction->declaration.tessellator_output_primitive);
7815}
7816
7819{
7820 if (!instruction->declaration.tessellator_partitioning
7821 || instruction->declaration.tessellator_partitioning
7824 "Tessellator partitioning %#x is invalid.",
7825 instruction->declaration.tessellator_partitioning);
7826}
7827
7830{
7831 if (instruction->declaration.count > 1024)
7832 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_GS, "GS output vertex count %u is invalid.",
7833 instruction->declaration.count);
7834}
7835
7837{
7839 if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_IF)
7841 "ELSE instruction doesn't terminate IF block.");
7842 else
7843 ctx->blocks[ctx->depth - 1] = VKD3DSIH_ELSE;
7844}
7845
7847{
7849 if (ctx->depth == 0 || (ctx->blocks[ctx->depth - 1] != VKD3DSIH_IF
7850 && ctx->blocks[ctx->depth - 1] != VKD3DSIH_ELSE))
7852 "ENDIF instruction doesn't terminate IF/ELSE block.");
7853 else
7854 --ctx->depth;
7855}
7856
7858{
7860 if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_LOOP)
7862 "ENDLOOP instruction doesn't terminate LOOP block.");
7863 else
7864 --ctx->depth;
7865}
7866
7868{
7870 if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_REP)
7872 "ENDREP instruction doesn't terminate REP block.");
7873 else
7874 --ctx->depth;
7875}
7876
7878{
7880 if (ctx->depth == 0 || ctx->blocks[ctx->depth - 1] != VKD3DSIH_SWITCH)
7882 "ENDSWITCH instruction doesn't terminate SWITCH block.");
7883 else
7884 --ctx->depth;
7885}
7886
7888{
7891}
7892
7894{
7897}
7898
7900{
7902 if (instruction->src_count >= 1 && !vsir_register_is_label(&instruction->src[0].reg))
7904 "Invalid register of type %#x in a LABEL instruction, expected LABEL.",
7905 instruction->src[0].reg.type);
7906
7907 if (ctx->inside_block)
7909 "Invalid LABEL instruction inside a block.");
7910 ctx->inside_block = true;
7911}
7912
7914{
7916 vsir_validate_src_count(ctx, instruction, ctx->program->shader_version.major <= 3 ? 2 : 0);
7918}
7919
7921{
7922}
7923
7925{
7926 unsigned int i, incoming_count;
7927
7929
7931
7932 if (instruction->src_count % 2 != 0)
7934 "Invalid source count %u for a PHI instruction, it must be an even number.",
7935 instruction->src_count);
7936 incoming_count = instruction->src_count / 2;
7937
7938 for (i = 0; i < incoming_count; ++i)
7939 {
7940 unsigned int value_idx = 2 * i;
7941 unsigned int label_idx = 2 * i + 1;
7942
7943 if (!register_is_constant_or_undef(&instruction->src[value_idx].reg)
7944 && !register_is_ssa(&instruction->src[value_idx].reg))
7946 "Invalid value register for incoming %u of type %#x in PHI instruction, "
7947 "expected SSA, IMMCONST or IMMCONST64.", i, instruction->src[value_idx].reg.type);
7948
7949 if (instruction->src[value_idx].reg.dimension != VSIR_DIMENSION_SCALAR)
7951 "Invalid value dimension %#x for incoming %u in PHI instruction, expected scalar.",
7952 instruction->src[value_idx].reg.dimension, i);
7953
7954 if (!vsir_register_is_label(&instruction->src[label_idx].reg))
7956 "Invalid label register for case %u of type %#x in PHI instruction, "
7957 "expected LABEL.", i, instruction->src[value_idx].reg.type);
7958 }
7959
7960 if (instruction->dst_count < 1)
7961 return;
7962
7963 if (!register_is_ssa(&instruction->dst[0].reg))
7965 "Invalid destination of type %#x in PHI instruction, expected SSA.",
7966 instruction->dst[0].reg.type);
7967
7968 if (instruction->dst[0].reg.dimension != VSIR_DIMENSION_SCALAR)
7970 "Invalid destination dimension %#x in PHI instruction, expected scalar.",
7971 instruction->dst[0].reg.dimension);
7972
7973 if (instruction->dst[0].modifiers != VKD3DSPDM_NONE)
7975 "Invalid modifiers %#x for the destination of a PHI instruction, expected none.",
7976 instruction->dst[0].modifiers);
7977
7978 if (instruction->dst[0].shift != 0)
7980 "Invalid shift %#x for the destination of a PHI instruction, expected none.",
7981 instruction->dst[0].shift);
7982}
7983
7985{
7988}
7989
7991{
7992 ctx->inside_block = false;
7993}
7994
7996{
7999}
8000
8003{
8004 unsigned int i, case_count;
8005
8007
8008 /* Parameters are source, default label, merge label and
8009 * then pairs of constant value and case label. */
8010
8012 return;
8013
8014 if (instruction->src_count % 2 != 1)
8016 "Invalid source count %u for a monolithic SWITCH instruction, it must be an odd number.",
8017 instruction->src_count);
8018
8019 if (!vsir_register_is_label(&instruction->src[1].reg))
8021 "Invalid default label register of type %#x in monolithic SWITCH instruction, expected LABEL.",
8022 instruction->src[1].reg.type);
8023
8024 if (!vsir_register_is_label(&instruction->src[2].reg))
8026 "Invalid merge label register of type %#x in monolithic SWITCH instruction, expected LABEL.",
8027 instruction->src[2].reg.type);
8028
8029 case_count = (instruction->src_count - 3) / 2;
8030
8031 for (i = 0; i < case_count; ++i)
8032 {
8033 unsigned int value_idx = 3 + 2 * i;
8034 unsigned int label_idx = 3 + 2 * i + 1;
8035
8036 if (!register_is_constant(&instruction->src[value_idx].reg))
8038 "Invalid value register for case %u of type %#x in monolithic SWITCH instruction, "
8039 "expected IMMCONST or IMMCONST64.", i, instruction->src[value_idx].reg.type);
8040
8041 if (!vsir_register_is_label(&instruction->src[label_idx].reg))
8043 "Invalid label register for case %u of type %#x in monolithic SWITCH instruction, "
8044 "expected LABEL.", i, instruction->src[value_idx].reg.type);
8045 }
8046
8047 ctx->inside_block = false;
8048}
8049
8051{
8052 unsigned int dst_param_count;
8053 unsigned int src_param_count;
8055};
8056
8058{
8079 [VKD3DSIH_IF] = {0, 1, vsir_validate_if},
8080 [VKD3DSIH_IFC] = {0, 2, vsir_validate_ifc},
8083 [VKD3DSIH_NOP] = {0, 0, vsir_validate_nop},
8084 [VKD3DSIH_PHI] = {1, ~0u, vsir_validate_phi},
8085 [VKD3DSIH_REP] = {0, 1, vsir_validate_rep},
8086 [VKD3DSIH_RET] = {0, 0, vsir_validate_ret},
8089};
8090
8092{
8093 const struct vkd3d_shader_version *version = &ctx->program->shader_version;
8095 size_t i;
8096
8097 instruction = &ctx->program->instructions.elements[ctx->instruction_idx];
8098
8099 for (i = 0; i < instruction->dst_count; ++i)
8101
8102 for (i = 0; i < instruction->src_count; ++i)
8104
8106 {
8107 validator_error(ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER, "Invalid instruction handler %#x.",
8109 }
8110
8111 if (version->type == VKD3D_SHADER_TYPE_HULL && ctx->phase == VKD3DSIH_INVALID)
8112 {
8113 switch (instruction->opcode)
8114 {
8115 case VKD3DSIH_NOP:
8116 case VKD3DSIH_HS_DECLS:
8120 break;
8121
8122 default:
8125 "Instruction %#x appear before any phase instruction in a hull shader.",
8127 break;
8128 }
8129 }
8130
8131 if (ctx->program->cf_type == VSIR_CF_BLOCKS && !ctx->inside_block)
8132 {
8133 switch (instruction->opcode)
8134 {
8135 case VKD3DSIH_NOP:
8136 case VKD3DSIH_LABEL:
8137 case VKD3DSIH_HS_DECLS:
8141 break;
8142
8143 default:
8146 "Invalid instruction %#x outside any block.",
8148 break;
8149 }
8150 }
8151
8153 {
8155
8157
8158 if (desc->validate)
8159 {
8160 if (desc->dst_param_count != ~0u)
8161 vsir_validate_dst_count(ctx, instruction, desc->dst_param_count);
8162 if (desc->src_param_count != ~0u)
8163 vsir_validate_src_count(ctx, instruction, desc->src_param_count);
8164 desc->validate(ctx, instruction);
8165 }
8166 }
8167}
8168
8170 const char *source_name, struct vkd3d_shader_message_context *message_context)
8171{
8172 struct validation_context ctx =
8173 {
8174 .message_context = message_context,
8175 .program = program,
8176 .null_location = {.source_name = source_name},
8177 .status = VKD3D_OK,
8178 .phase = VKD3DSIH_INVALID,
8179 .invalid_instruction_idx = true,
8180 };
8181 unsigned int i;
8182
8183 if (!(config_flags & VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION))
8184 return VKD3D_OK;
8185
8186 switch (program->shader_version.type)
8187 {
8190 break;
8191
8192 default:
8193 if (program->patch_constant_signature.element_count != 0)
8195 "Patch constant signature is only valid for hull and domain shaders.");
8196 }
8197
8198 switch (program->shader_version.type)
8199 {
8201 break;
8202
8205 if (program->input_control_point_count == 0)
8207 "Invalid zero input control point count.");
8208 break;
8209
8210 default:
8211 if (program->input_control_point_count != 0)
8213 "Invalid input control point count %u.",
8214 program->input_control_point_count);
8215 }
8216
8217 switch (program->shader_version.type)
8218 {
8220 break;
8221
8222 default:
8223 if (program->output_control_point_count != 0)
8225 "Invalid output control point count %u.",
8226 program->output_control_point_count);
8227 }
8228
8232
8233 if (!(ctx.temps = vkd3d_calloc(ctx.program->temp_count, sizeof(*ctx.temps))))
8234 goto fail;
8235
8236 if (!(ctx.ssas = vkd3d_calloc(ctx.program->ssa_count, sizeof(*ctx.ssas))))
8237 goto fail;
8238
8239 ctx.invalid_instruction_idx = false;
8240
8241 for (ctx.instruction_idx = 0; ctx.instruction_idx < program->instructions.count
8242 && ctx.status != VKD3D_ERROR_OUT_OF_MEMORY; ++ctx.instruction_idx)
8244
8245 ctx.invalid_instruction_idx = true;
8246
8247 if (ctx.depth != 0)
8248 validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "%zu nested blocks were not closed.", ctx.depth);
8249
8250 if (ctx.inside_block)
8251 validator_error(&ctx, VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW, "Last block was not closed.");
8252
8253 for (i = 0; i < ctx.program->ssa_count; ++i)
8254 {
8255 struct validation_context_ssa_data *data = &ctx.ssas[i];
8256
8257 if ((data->write_mask | data->read_mask) != data->write_mask)
8259 "SSA register %u has invalid read mask %#x, which is not a subset of the write mask %#x "
8260 "at the point of definition.", i, data->read_mask, data->write_mask);
8261 }
8262
8263 vkd3d_free(ctx.blocks);
8264 vkd3d_free(ctx.temps);
8265 vkd3d_free(ctx.ssas);
8266
8267 return ctx.status;
8268
8269fail:
8270 vkd3d_free(ctx.blocks);
8271 vkd3d_free(ctx.temps);
8272 vkd3d_free(ctx.ssas);
8273
8275}
8276
8277#define vsir_transform(ctx, step) vsir_transform_(ctx, #step, step)
8279 struct vsir_transformation_context *ctx, const char *step_name,
8280 enum vkd3d_result (*step)(struct vsir_program *program, struct vsir_transformation_context *ctx))
8281{
8282 if (ctx->result < 0)
8283 return;
8284
8285 if ((ctx->result = step(ctx->program, ctx)) < 0)
8286 {
8287 WARN("Transformation \"%s\" failed with result %d.\n", step_name, ctx->result);
8288 return;
8289 }
8290
8291 if ((ctx->result = vsir_program_validate(ctx->program, ctx->config_flags,
8292 ctx->compile_info->source_name, ctx->message_context)) < 0)
8293 {
8294 WARN("Validation failed with result %d after transformation \"%s\".\n", ctx->result, step_name);
8295 return;
8296 }
8297}
8298
8299/* Transformations which should happen at parse time, i.e. before scan
8300 * information is returned to the user.
8301 *
8302 * In particular, some passes need to modify the signature, and
8303 * vkd3d_shader_scan() should report the modified signature for the given
8304 * target. */
8306 const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context)
8307{
8309 {
8310 .result = VKD3D_OK,
8311 .program = program,
8312 .config_flags = config_flags,
8313 .compile_info = compile_info,
8314 .message_context = message_context,
8315 };
8316
8317 /* For vsir_program_ensure_diffuse(). */
8318 if (program->shader_version.major <= 2)
8320
8321 return ctx.result;
8322}
8323
8326{
8328 {
8329 .result = VKD3D_OK,
8330 .program = program,
8331 .config_flags = config_flags,
8332 .compile_info = compile_info,
8333 .message_context = message_context,
8334 };
8335
8337
8338 if (program->shader_version.major >= 6)
8339 {
8345 }
8346 else
8347 {
8349
8350 if (program->shader_version.major <= 2)
8352
8353 if (program->shader_version.type != VKD3D_SHADER_TYPE_PIXEL)
8355
8356 if (program->shader_version.type == VKD3D_SHADER_TYPE_HULL)
8358
8363
8364 if (compile_info->target_type != VKD3D_SHADER_TARGET_GLSL
8365 && compile_info->target_type != VKD3D_SHADER_TARGET_MSL)
8367 }
8368
8375
8376 if (TRACE_ON())
8378
8379 return ctx.result;
8380}
static int used
Definition: adh-main.c:39
#define index(s, c)
Definition: various.h:29
#define ARRAY_SIZE(A)
Definition: main.h:20
#define FIXME(fmt,...)
Definition: precomp.h:53
#define WARN(fmt,...)
Definition: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
static void else_break(short *before, short class)
Definition: breaking.c:71
r l[0]
Definition: byte_order.h:168
Definition: list.h:39
Definition: _map.h:48
Definition: _set.h:50
set(const _Compare &__comp=_Compare(), const allocator_type &__a=allocator_type())
Definition: _set.h:89
int selection
Definition: ctm.c:92
unsigned int component_count
void vsir_program_trace(const struct vsir_program *program)
Definition: d3d_asm.c:2550
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
static BOOL reserve(struct dynamic_array *array, int count, int itemsize)
Definition: mesh.c:5499
unsigned int idx
Definition: utils.c:40
#define Z(I)
#define Y(I)
#define CHAR_BIT
Definition: cabinet.h:45
#define TRACE_ON(x)
Definition: compat.h:75
static const WCHAR version[]
Definition: asmname.c:66
#define SIZE_MAX
Definition: limits.h:49
#define UINT_MAX
Definition: limits.h:27
_ACRTIMP void __cdecl qsort(void *, size_t, size_t, int(__cdecl *)(const void *, const void *))
#define va_end(v)
Definition: stdarg.h:28
#define va_start(v, l)
Definition: stdarg.h:26
unsigned char uint8_t
Definition: stdint.h:33
#define UINT8_MAX
Definition: stdint.h:83
char * va_list
Definition: vadefs.h:50
void sincos(double x, double *s, double *c)
Definition: sincos.c:30
return ret
Definition: mutex.c:147
action
Definition: namespace.c:707
#define _(op)
Definition: opcodes.c:24
GLint GLint GLsizei GLsizei GLsizei depth
Definition: gl.h:1546
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLdouble s
Definition: gl.h:2039
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLenum func
Definition: glext.h:6028
GLenum src
Definition: glext.h:6340
GLsizei const GLint * locations
Definition: glext.h:10542
GLuint buffer
Definition: glext.h:5915
GLsizeiptr size
Definition: glext.h:5919
GLenum clamp
Definition: glext.h:6216
GLintptr offset
Definition: glext.h:5920
GLenum condition
Definition: glext.h:9255
const GLubyte * c
Definition: glext.h:8905
GLuint index
Definition: glext.h:6031
GLenum GLint GLuint mask
Definition: glext.h:6028
GLuint program
Definition: glext.h:6723
GLfloat f
Definition: glext.h:7540
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum const GLfloat * params
Definition: glext.h:5645
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLint reference
Definition: glext.h:11729
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLuint64EXT * result
Definition: glext.h:11304
GLfloat param
Definition: glext.h:5796
GLuint GLdouble GLdouble GLint GLint order
Definition: glext.h:11194
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLuint id
Definition: glext.h:5910
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
enum wined3d_data_type data_type
Definition: glsl_shader.c:71
static int reg
Definition: i386-dis.c:1290
vsir_signature_type
Definition: ir.c:7424
@ SIGNATURE_TYPE_OUTPUT
Definition: ir.c:7426
@ SIGNATURE_TYPE_INPUT
Definition: ir.c:7425
@ SIGNATURE_TYPE_PATCH_CONSTANT
Definition: ir.c:7427
static void vsir_cfg_remove_trailing_continue(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list, unsigned int target)
Definition: ir.c:4905
static bool use_flat_interpolation(const struct vsir_program *program, struct vkd3d_shader_message_context *message_context, bool *flat)
Definition: ir.c:5849
static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:5805
static void shader_dst_param_normalise_outpointid(struct vkd3d_shader_dst_param *dst_param, struct control_point_normaliser *normaliser)
Definition: ir.c:1355
static struct vkd3d_shader_src_param * instruction_src_params_alloc(struct vkd3d_shader_instruction *ins, unsigned int count, struct cf_flattener *flattener)
Definition: ir.c:2614
static struct vkd3d_shader_src_param * cf_flattener_emit_branch(struct cf_flattener *flattener, unsigned int merge_block_id, unsigned int continue_block_id, const struct vkd3d_shader_src_param *condition, unsigned int true_id, unsigned int false_id, unsigned int flags)
Definition: ir.c:2642
static void vsir_validate_switch_monolithic(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:8001
static struct vsir_cfg_structure * vsir_cfg_get_trailing_break(struct vsir_cfg_structure_list *list)
Definition: ir.c:4919
static void vsir_cfg_dump_structured_program(struct vsir_cfg *cfg)
Definition: ir.c:4009
static void src_param_init_temp_float(struct vkd3d_shader_src_param *src, unsigned int idx)
Definition: ir.c:252
struct signature_element * vsir_signature_find_element_for_reg(const struct shader_signature *signature, unsigned int reg_idx, unsigned int write_mask)
Definition: ir.c:1573
static enum vkd3d_result vsir_program_lower_precise_mad(struct vsir_program *program, struct vkd3d_shader_instruction *mad, unsigned int *tmp_idx)
Definition: ir.c:569
static enum vkd3d_result vsir_program_lower_tex(struct vsir_program *program, struct vkd3d_shader_instruction *tex)
Definition: ir.c:665
static void vsir_validate_endrep(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7867
static void vsir_validate_dcl_temps(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7784
static void shader_register_eliminate_phase_addressing(struct vkd3d_shader_register *reg, unsigned int instance_id)
Definition: ir.c:796
static enum vkd3d_result vsir_program_structurize_function(struct vsir_program *program, struct vkd3d_shader_message_context *message_context, struct vsir_cfg_emit_target *target, size_t *pos)
Definition: ir.c:5586
static void vsir_cfg_count_targets(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list)
Definition: ir.c:5197
static enum vkd3d_result vsir_block_list_add(struct vsir_block_list *list, struct vsir_block *block)
Definition: ir.c:3555
static void vsir_src_param_init_sampler(struct vkd3d_shader_src_param *src, unsigned int id, unsigned int idx)
Definition: ir.c:226
static bool is_pre_rasterization_shader(enum vkd3d_shader_type type)
Definition: ir.c:6264
static int block_compare(const void *ptr1, const void *ptr2)
Definition: ir.c:3617
static enum vkd3d_result vsir_cfg_init(struct vsir_cfg *cfg, struct vsir_program *program, struct vkd3d_shader_message_context *message_context, struct vsir_cfg_emit_target *target, size_t *pos)
Definition: ir.c:4017
static const struct vsir_validator_instruction_desc vsir_validator_instructions[]
Definition: ir.c:8057
static enum vkd3d_result control_point_normaliser_emit_hs_input(struct control_point_normaliser *normaliser, const struct shader_signature *s, unsigned int input_control_point_count, unsigned int dst, const struct vkd3d_shader_location *location)
Definition: ir.c:1381
static void range_map_set_register_range(uint8_t range_map[][VKD3D_VEC4_SIZE], unsigned int register_idx, unsigned int register_count, uint32_t write_mask, bool is_dcl_indexrange)
Definition: ir.c:1590
static enum vkd3d_result instruction_array_normalise_hull_shader_control_point_io(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:1434
static void vsir_validate_endswitch(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7877
static enum vkd3d_result vsir_cfg_move_breaks_out_of_selections_recursively(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list)
Definition: ir.c:5006
static void vsir_validate_resource_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg)
Definition: ir.c:6997
static void vsir_validate_endloop(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7857
static bool vsir_block_dominates(struct vsir_block *b1, struct vsir_block *b2)
Definition: ir.c:3866
static bool sysval_semantics_should_merge(const struct signature_element *e, const struct signature_element *f)
Definition: ir.c:1682
static bool lower_switch_to_if_ladder_add_block_mapping(struct lower_switch_to_if_ladder_block_mapping **block_map, size_t *map_capacity, size_t *map_count, unsigned int switch_label, unsigned int if_label, unsigned int target_label)
Definition: ir.c:3187
static void vsir_validate_label_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg)
Definition: ir.c:6934
static void vsir_validate_switch(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7995
const struct vkd3d_shader_parameter1 * vsir_program_get_parameter(const struct vsir_program *program, enum vkd3d_shader_parameter_name name)
Definition: ir.c:120
static bool flattener_is_in_fork_or_join_phase(const struct hull_flattener *flattener)
Definition: ir.c:1171
static void vsir_src_param_init_resource(struct vkd3d_shader_src_param *src, unsigned int id, unsigned int idx)
Definition: ir.c:217
static void vsir_cfg_dump_dot(struct vsir_cfg *cfg)
Definition: ir.c:3889
static enum vkd3d_result vsir_program_materialize_undominated_ssas_to_temps_in_function(struct vsir_program *program, struct vkd3d_shader_message_context *message_context, size_t *pos)
Definition: ir.c:5786
static void vsir_block_list_remove_index(struct vsir_block_list *list, size_t idx)
Definition: ir.c:3567
static bool vsir_instruction_is_dcl(const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:371
static void vsir_validate_dcl_gs_instances(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7738
static unsigned int shader_register_normalise_arrayed_addressing(struct vkd3d_shader_register *reg, unsigned int id_idx, unsigned int register_index)
Definition: ir.c:1918
static enum vkd3d_result vsir_cfg_structure_list_emit_selection(struct vsir_cfg *cfg, struct vsir_cfg_structure_selection *selection, unsigned int loop_idx)
Definition: ir.c:5428
static int compare_loop_intervals(const void *ptr1, const void *ptr2)
Definition: ir.c:4542
static void cf_flattener_emit_unconditional_branch(struct cf_flattener *flattener, unsigned int target_block_id)
Definition: ir.c:2705
static enum vkd3d_result vsir_program_add_diffuse_output(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:850
static enum vkd3d_result flattener_flatten_phases(struct hull_flattener *normaliser, struct shader_phase_location_array *locations)
Definition: ir.c:1245
static enum vkd3d_result insert_point_size_before_ret(struct vsir_program *program, const struct vkd3d_shader_instruction *ret, size_t *ret_pos)
Definition: ir.c:6272
static enum vkd3d_result vsir_program_apply_flat_interpolation(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:5877
static void cf_flattener_emit_conditional_branch_and_merge(struct cf_flattener *flattener, const struct vkd3d_shader_src_param *condition, unsigned int true_id, unsigned int flags)
Definition: ir.c:2695
static void vsir_validate_cf_type(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction, enum vsir_control_flow_type expected_type)
Definition: ir.c:7661
static struct cf_flattener_info * cf_flattener_find_innermost_loop(struct cf_flattener *flattener)
Definition: ir.c:2731
static void vsir_validate_dcl_vertices_out(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7828
static void materialize_ssas_to_temps_process_reg(struct vsir_program *program, struct ssas_to_temps_alloc *alloc, struct vkd3d_shader_register *reg)
Definition: ir.c:3360
static void vsir_validate_else(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7836
static void shader_signature_map_patch_constant_index_ranges(struct shader_signature *s, uint8_t range_map[][VKD3D_VEC4_SIZE])
Definition: ir.c:1698
static bool replace_texcoord_with_point_coord(struct vsir_program *program, struct vkd3d_shader_src_param *src, unsigned int coord_temp)
Definition: ir.c:6462
static bool shader_dst_param_io_normalise(struct vkd3d_shader_dst_param *dst_param, bool is_io_dcl, struct io_normaliser *normaliser)
Definition: ir.c:1952
static void vsir_validate_signature(struct validation_context *ctx, const struct shader_signature *signature, enum vsir_signature_type signature_type)
Definition: ir.c:7634
static void vsir_validate_dcl_hs_max_tessfactor(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7746
static void vsir_cfg_compute_edge_action(struct vsir_cfg *cfg, struct vsir_block *block, struct vsir_block *successor, struct vsir_cfg_edge_action *action)
Definition: ir.c:4683
static void vsir_validate_phi(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7924
static unsigned int cf_flattener_alloc_block_id(struct cf_flattener *flattener)
Definition: ir.c:2609
static void vsir_cfg_mark_launchers(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list, struct vsir_cfg_structure *loop)
Definition: ir.c:5277
static void flattener_eliminate_phase_related_dcls(struct hull_flattener *normaliser, unsigned int index, struct shader_phase_location_array *locations)
Definition: ir.c:1190
static void vsir_validate_rep(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7984
static void src_param_init_temp_uint(struct vkd3d_shader_src_param *src, unsigned int idx)
Definition: ir.c:266
static bool vsir_block_list_search(struct vsir_block_list *list, struct vsir_block *block)
Definition: ir.c:3630
static void vsir_validate_dcl_input_primitive(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7757
static void vsir_validate_ret(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7990
static void vsir_cfg_cleanup(struct vsir_cfg *cfg)
Definition: ir.c:3824
static void vsir_validator_push_block(struct validation_context *ctx, enum vkd3d_shader_opcode opcode)
Definition: ir.c:7669
static void src_param_init_temp_float4(struct vkd3d_shader_src_param *src, unsigned int idx)
Definition: ir.c:258
static void vsir_validate_signature_element(struct validation_context *ctx, const struct shader_signature *signature, enum vsir_signature_type signature_type, unsigned int idx)
Definition: ir.c:7468
static enum vkd3d_result vsir_program_insert_point_size_clamp(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:6344
static bool control_point_normaliser_is_in_control_point_phase(const struct control_point_normaliser *normaliser)
Definition: ir.c:1331
static void vsir_validate_dst_count(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction, unsigned int count)
Definition: ir.c:7377
static bool cf_flattener_copy_instruction(struct cf_flattener *flattener, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:2593
static void shader_src_param_io_normalise(struct vkd3d_shader_src_param *src_param, struct io_normaliser *normaliser)
Definition: ir.c:2089
static enum vkd3d_result insert_clip_planes_before_ret(struct vsir_program *program, const struct vkd3d_shader_instruction *ret, uint32_t mask, uint32_t position_signature_idx, uint32_t position_temp, uint32_t low_signature_idx, uint32_t high_signature_idx, size_t *ret_pos)
Definition: ir.c:6082
static bool vsir_instruction_init_label(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, unsigned int label_id, struct vsir_program *program)
Definition: ir.c:354
static struct cf_flattener_info * cf_flattener_push_control_flow_level(struct cf_flattener *flattener)
Definition: ir.c:2710
static void dst_param_init_temp_uint(struct vkd3d_shader_dst_param *dst, unsigned int idx)
Definition: ir.c:306
#define VS_BIT
Definition: ir.c:7438
static void cf_flattener_set_error(struct cf_flattener *flattener, enum vkd3d_result error)
Definition: ir.c:2574
static struct cf_flattener_info * cf_flattener_find_innermost_breakable_cf_construct(struct cf_flattener *flattener)
Definition: ir.c:2744
static enum vkd3d_result cf_flattener_iterate_instruction_array(struct cf_flattener *flattener, struct vkd3d_shader_message_context *message_context)
Definition: ir.c:2783
static bool io_normaliser_is_in_fork_or_join_phase(const struct io_normaliser *normaliser)
Definition: ir.c:1543
static struct vkd3d_shader_instruction * cf_flattener_require_space(struct cf_flattener *flattener, size_t count)
Definition: ir.c:2581
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
static enum vkd3d_result vsir_program_materialise_phi_ssas_to_temps(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:3398
static void cf_flattener_emit_label(struct cf_flattener *flattener, unsigned int label_id)
Definition: ir.c:2629
static void vsir_validate_dcl_tessellator_domain(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7797
static void vsir_validate_dcl_tessellator_output_primitive(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7806
static void src_param_init_parameter(struct vkd3d_shader_src_param *src, uint32_t idx, enum vkd3d_data_type type)
Definition: ir.c:211
static unsigned int label_from_src_param(const struct vkd3d_shader_src_param *param)
Definition: ir.c:3160
static void vsir_validate_ifc(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7893
static enum vkd3d_result vsir_program_lower_ifc(struct vsir_program *program, struct vkd3d_shader_instruction *ifc, unsigned int *tmp_idx, struct vkd3d_shader_message_context *message_context)
Definition: ir.c:431
static bool target_allows_subset_masks(const struct vkd3d_shader_compile_info *info)
Definition: ir.c:939
static void vsir_validate_label(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7899
static enum vkd3d_result vsir_program_lower_sm1_sincos(struct vsir_program *program, struct vkd3d_shader_instruction *sincos)
Definition: ir.c:613
static enum vkd3d_result vsir_program_flatten_control_flow_constructs(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:3129
static void dst_param_init_ssa_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx)
Definition: ir.c:281
static enum vkd3d_result vsir_program_ensure_ret(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:836
static bool get_opcode_from_rel_op(enum vkd3d_shader_rel_op rel_op, enum vkd3d_data_type data_type, enum vkd3d_shader_opcode *opcode, bool *requires_swap)
Definition: ir.c:385
struct vkd3d_shader_src_param * vsir_program_create_outpointid_param(struct vsir_program *program)
Definition: ir.c:1336
static enum vkd3d_result vsir_cfg_sort_nodes(struct vsir_cfg *cfg)
Definition: ir.c:4352
static void vsir_validate_register_without_indices(struct validation_context *ctx, const struct vkd3d_shader_register *reg)
Definition: ir.c:6701
static void vkd3d_shader_instruction_make_nop(struct vkd3d_shader_instruction *ins)
Definition: ir.c:378
static void vsir_block_list_sort(struct vsir_block_list *list)
Definition: ir.c:3625
static bool ssas_to_temps_alloc_init(struct ssas_to_temps_alloc *alloc, unsigned int ssa_count, unsigned int temp_count)
Definition: ir.c:3343
static enum vkd3d_result vsir_program_insert_alpha_test(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:5999
static void shader_register_normalise_flat_constants(struct vkd3d_shader_src_param *param, const struct flat_constants_normaliser *normaliser)
Definition: ir.c:2335
static void vsir_cfg_structure_init(struct vsir_cfg_structure *structure, enum vsir_cfg_structure_type type)
Definition: ir.c:3736
static void vsir_validate_src_count(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction, unsigned int count)
Definition: ir.c:7386
static enum vkd3d_result vsir_cfg_add_edge(struct vsir_cfg *cfg, struct vsir_block *block, struct vkd3d_shader_src_param *successor_param)
Definition: ir.c:3871
static enum vkd3d_result vsir_program_ensure_diffuse(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:888
static void vsir_validate_uav_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg)
Definition: ir.c:7024
static void shader_instruction_eliminate_phase_instance_id(struct vkd3d_shader_instruction *ins, unsigned int instance_id)
Definition: ir.c:811
void vsir_src_param_init_label(struct vkd3d_shader_src_param *param, unsigned int label_id)
Definition: ir.c:204
static enum vkd3d_result vsir_cfg_compute_loops(struct vsir_cfg *cfg)
Definition: ir.c:4242
static void vsir_validate_src_param(struct validation_context *ctx, const struct vkd3d_shader_src_param *src)
Definition: ir.c:7323
void vsir_program_cleanup(struct vsir_program *program)
Definition: ir.c:105
static void dst_param_init_ssa_float(struct vkd3d_shader_dst_param *dst, unsigned int idx)
Definition: ir.c:287
static unsigned int signature_element_range_expand_mask(struct signature_element *e, unsigned int register_count, uint8_t range_map[][VKD3D_VEC4_SIZE])
Definition: ir.c:1767
static void dst_param_init_temp_float4(struct vkd3d_shader_dst_param *dst, unsigned int idx)
Definition: ir.c:299
static unsigned int range_map_get_register_count(uint8_t range_map[][VKD3D_VEC4_SIZE], unsigned int register_idx, uint32_t write_mask)
Definition: ir.c:1584
static void vsir_transform_(struct vsir_transformation_context *ctx, const char *step_name, enum vkd3d_result(*step)(struct vsir_program *program, struct vsir_transformation_context *ctx))
Definition: ir.c:8278
static void vsir_validate_dst_param(struct validation_context *ctx, const struct vkd3d_shader_dst_param *dst)
Definition: ir.c:7233
static enum vkd3d_result vsir_program_insert_point_coord(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:6519
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
static bool vsir_validate_src_max_count(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction, unsigned int count)
Definition: ir.c:7409
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
static void shader_instruction_normalise_io_params(struct vkd3d_shader_instruction *ins, struct io_normaliser *normaliser)
Definition: ir.c:2169
static bool shader_signature_merge(struct shader_signature *s, uint8_t range_map[][VKD3D_VEC4_SIZE], bool is_patch_constant)
Definition: ir.c:1812
static void vsir_validate_misctype_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg)
Definition: ir.c:6914
static enum vkd3d_result vsir_program_lower_instructions(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:712
static void vsir_cfg_structure_cleanup(struct vsir_cfg_structure *structure)
Definition: ir.c:3742
static enum vkd3d_result vsir_cfg_emit_structured_program(struct vsir_cfg *cfg)
Definition: ir.c:5581
static enum vkd3d_result vsir_program_normalise_flat_constants(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:2365
static struct signature_element * vsir_signature_find_element_by_name(const struct shader_signature *signature, const char *semantic_name, unsigned int semantic_index)
Definition: ir.c:132
static enum vkd3d_result vsir_program_remap_output_signature(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:1007
#define DS_BIT
Definition: ir.c:7441
bool vsir_signature_find_sysval(const struct shader_signature *signature, enum vkd3d_shader_sysval_semantic sysval, unsigned int semantic_index, unsigned int *element_index)
Definition: ir.c:145
static bool reserve_instructions(struct vkd3d_shader_instruction **instructions, size_t *capacity, size_t count)
Definition: ir.c:3166
static void vsir_validate_temp_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg)
Definition: ir.c:6843
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
static void vsir_cfg_structure_dump(struct vsir_cfg *cfg, struct vsir_cfg_structure *structure)
Definition: ir.c:3928
static void vsir_validate_hull_shader_phase(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7679
static void vsir_validate_branch(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7694
static void vsir_cfg_mark_trampolines(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list, struct vsir_cfg_structure *loop)
Definition: ir.c:5232
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
static void vsir_validate_nop(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7920
static enum vkd3d_result vsir_block_list_add_checked(struct vsir_block_list *list, struct vsir_block *block)
Definition: ir.c:3542
static enum vkd3d_result vsir_cfg_synthesize_selections(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list)
Definition: ir.c:5025
static void register_map_undominated_use(struct vkd3d_shader_register *reg, struct ssas_to_temps_alloc *alloc, struct vsir_block *block, struct vsir_block **origin_blocks)
Definition: ir.c:5688
static void vsir_cfg_structure_list_cleanup(struct vsir_cfg_structure_list *list)
Definition: ir.c:3697
static void vsir_validate_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg)
Definition: ir.c:7118
static enum vkd3d_result vsir_cfg_generate_synthetic_loop_intervals(struct vsir_cfg *cfg)
Definition: ir.c:4553
static enum vkd3d_result vsir_cfg_structure_list_append_from_region(struct vsir_cfg_structure_list *list, struct vsir_cfg_structure *begin, size_t size)
Definition: ir.c:3722
static void src_param_init_temp_bool(struct vkd3d_shader_src_param *src, unsigned int idx)
Definition: ir.c:246
enum vkd3d_result vsir_program_transform(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context)
Definition: ir.c:8324
static void vsir_validate_dcl_output_topology(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7775
static void ssas_to_temps_block_info_cleanup(struct ssas_to_temps_block_info *block_info, size_t count)
Definition: ir.c:3387
#define vsir_transform(ctx, step)
Definition: ir.c:8277
static bool has_texcoord_signature_element(const struct shader_signature *signature)
Definition: ir.c:6451
static enum vkd3d_result vsir_block_init(struct vsir_block *block, unsigned int label, size_t block_count)
Definition: ir.c:3585
static const struct sysval_validation_data_element sysval_validation_data[]
static int signature_element_mask_compare(const void *a, const void *b)
Definition: ir.c:1674
static void vsir_validate_ssa_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg)
Definition: ir.c:7056
static void vsir_validate_rastout_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg)
Definition: ir.c:6894
static enum vkd3d_result vsir_program_lower_texkill(struct vsir_program *program, struct vkd3d_shader_instruction *texkill, unsigned int *tmp_idx)
Definition: ir.c:485
static enum vkd3d_result vsir_cfg_materialize_undominated_ssas_to_temps(struct vsir_cfg *cfg)
Definition: ir.c:5710
static void vsir_validate_endif(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7846
static enum vkd3d_result vsir_program_lower_switch_to_selection_ladder(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:3205
static enum vkd3d_result vsir_cfg_structure_list_emit(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list, unsigned int loop_idx)
Definition: ir.c:5539
static const struct vkd3d_shader_varying_map * find_varying_map(const struct vkd3d_shader_varying_map_info *varying_map, unsigned int signature_idx)
Definition: ir.c:925
static enum vkd3d_result insert_alpha_test_before_ret(struct vsir_program *program, const struct vkd3d_shader_instruction *ret, enum vkd3d_shader_comparison_func compare_func, const struct vkd3d_shader_parameter1 *ref, uint32_t colour_signature_idx, uint32_t colour_temp, size_t *ret_pos, struct vkd3d_shader_message_context *message_context)
Definition: ir.c:5903
static bool shader_register_is_phase_instance_id(const struct vkd3d_shader_register *reg)
Definition: ir.c:185
static enum vkd3d_result vsir_program_insert_point_size(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:6293
static void remove_unread_output_components(const struct shader_signature *signature, struct vkd3d_shader_instruction *ins, struct vkd3d_shader_dst_param *dst)
Definition: ir.c:970
static void vsir_validate_instruction(struct validation_context *ctx)
Definition: ir.c:8091
static enum vkd3d_result vsir_cfg_build_structured_program(struct vsir_cfg *cfg)
Definition: ir.c:4740
static void vsir_cfg_compute_dominators(struct vsir_cfg *cfg)
Definition: ir.c:4162
static int convert_parameter_info(const struct vkd3d_shader_compile_info *compile_info, unsigned int *ret_count, const struct vkd3d_shader_parameter1 **ret_parameters)
Definition: ir.c:31
static const unsigned int allowed_signature_phases[]
Definition: ir.c:7627
#define PS_BIT
Definition: ir.c:7437
static void vsir_validate_sampler_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg)
Definition: ir.c:6969
static const char *const signature_type_names[]
Definition: ir.c:7430
static void vsir_cfg_structure_list_dump(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list)
Definition: ir.c:3997
#define HS_BIT
Definition: ir.c:7440
static enum vkd3d_result vsir_cfg_append_loop(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *new_list, struct vsir_cfg_structure *loop)
Definition: ir.c:5075
static enum vkd3d_result vsir_program_remove_dead_code(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:2405
static struct vsir_cfg_structure * vsir_cfg_structure_list_append(struct vsir_cfg_structure_list *list, enum vsir_cfg_structure_type type)
Definition: ir.c:3706
static enum vkd3d_result vsir_cfg_optimize(struct vsir_cfg *cfg)
Definition: ir.c:5311
static void vsir_validate_if(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7887
static void dst_param_init_temp_bool(struct vkd3d_shader_dst_param *dst, unsigned int idx)
Definition: ir.c:293
static void vsir_validate_dcl_tessellator_partitioning(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7817
void vsir_instruction_init(struct vkd3d_shader_instruction *ins, const struct vkd3d_shader_location *location, enum vkd3d_shader_opcode opcode)
Definition: ir.c:321
static enum vkd3d_result vsir_cfg_add_loop_interval(struct vsir_cfg *cfg, unsigned int begin, unsigned int end, bool synthetic)
Definition: ir.c:3847
static void vsir_block_list_init(struct vsir_block_list *list)
Definition: ir.c:3532
static const char * name_from_cf_type(enum vsir_control_flow_type type)
Definition: ir.c:7648
static void cf_flattener_pop_control_flow_level(struct cf_flattener *flattener)
Definition: ir.c:2723
static enum vkd3d_result vsir_program_structurize(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:5621
static enum vkd3d_result vsir_cfg_optimize_recurse(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list)
Definition: ir.c:5130
static void src_param_init_ssa_float(struct vkd3d_shader_src_param *src, unsigned int idx)
Definition: ir.c:240
static bool shader_signature_find_element_for_reg(const struct shader_signature *signature, unsigned int reg_idx, unsigned int write_mask, unsigned int *element_idx)
Definition: ir.c:1553
static void src_param_init_const_uint(struct vkd3d_shader_src_param *src, uint32_t value)
Definition: ir.c:198
static enum vkd3d_result vsir_cfg_structure_list_emit_block(struct vsir_cfg *cfg, struct vsir_block *block)
Definition: ir.c:5336
static void vsir_block_list_cleanup(struct vsir_block_list *list)
Definition: ir.c:3537
static bool io_normaliser_is_in_control_point_phase(const struct io_normaliser *normaliser)
Definition: ir.c:1548
static void vsir_validate_io_register(struct validation_context *ctx, const struct vkd3d_shader_register *reg)
Definition: ir.c:6710
#define GS_BIT
Definition: ir.c:7439
static enum vkd3d_result vsir_program_normalise_io_registers(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:2225
static bool vsir_validate_src_min_count(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction, unsigned int count)
Definition: ir.c:7395
static enum vkd3d_result vsir_cfg_scan_loop(struct vsir_block_list *loop, struct vsir_block *block, struct vsir_block *header)
Definition: ir.c:4221
static void dst_param_init_output(struct vkd3d_shader_dst_param *dst, enum vkd3d_data_type data_type, uint32_t idx, uint32_t write_mask)
Definition: ir.c:312
enum vkd3d_result vsir_program_validate(struct vsir_program *program, uint64_t config_flags, const char *source_name, struct vkd3d_shader_message_context *message_context)
Definition: ir.c:8169
static enum vkd3d_result vsir_program_flatten_hull_shader_phases(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:1295
static void vsir_validate_loop(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7913
static void vsir_block_cleanup(struct vsir_block *block)
Definition: ir.c:3608
static enum vkd3d_result vsir_cfg_move_breaks_out_of_selections(struct vsir_cfg *cfg, struct vsir_cfg_structure_list *list)
Definition: ir.c:4947
static void shader_dst_param_io_init(struct vkd3d_shader_dst_param *param, const struct signature_element *e, enum vkd3d_shader_register_type reg_type, unsigned int idx_count)
Definition: ir.c:1372
enum vkd3d_result vsir_program_transform_early(struct vsir_program *program, uint64_t config_flags, const struct vkd3d_shader_compile_info *compile_info, struct vkd3d_shader_message_context *message_context)
Definition: ir.c:8305
static bool get_flat_constant_register_type(const struct vkd3d_shader_register *reg, enum vkd3d_shader_d3dbc_constant_register *set, uint32_t *index)
Definition: ir.c:2295
static enum vkd3d_result vsir_cfg_structure_list_emit_jump(struct vsir_cfg *cfg, struct vsir_cfg_structure_jump *jump, unsigned int loop_idx)
Definition: ir.c:5471
static void vsir_cfg_compute_dominators_recurse(struct vsir_block *current, struct vsir_block *reference)
Definition: ir.c:4144
static enum vkd3d_result vsir_program_lower_texldd(struct vsir_program *program, struct vkd3d_shader_instruction *texldd)
Definition: ir.c:687
static void src_param_init_ssa_bool(struct vkd3d_shader_src_param *src, unsigned int idx)
Definition: ir.c:234
static void vsir_validate_dcl_output_control_point_count(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:7766
static enum vkd3d_result vsir_program_insert_clip_planes(struct vsir_program *program, struct vsir_transformation_context *ctx)
Definition: ir.c:6132
static int signature_element_index_compare(const void *a, const void *b)
Definition: ir.c:1760
static enum vkd3d_result vsir_cfg_structure_list_emit_loop(struct vsir_cfg *cfg, struct vsir_cfg_structure_loop *loop, unsigned int loop_idx)
Definition: ir.c:5353
static int signature_element_register_compare(const void *a, const void *b)
Definition: ir.c:1727
static void io_normaliser_add_index_range(struct io_normaliser *normaliser, const struct vkd3d_shader_instruction *ins)
Definition: ir.c:1630
#define e
Definition: ke_i.h:82
#define f
Definition: ke_i.h:83
#define a
Definition: ke_i.h:78
#define c
Definition: ke_i.h:80
#define b
Definition: ke_i.h:79
#define location(file, line)
Definition: kmtest.h:18
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define memmove(s1, s2, n)
Definition: mkisofs.h:881
struct task_struct * current
Definition: linux.c:32
static const WCHAR label[]
Definition: itemdlg.c:1608
static CRYPT_DATA_BLOB b2[]
Definition: msg.c:538
static CRYPT_DATA_BLOB b1[]
Definition: msg.c:529
D3D11_SHADER_VARIABLE_DESC desc
Definition: reflection.c:1683
static const LARGE_INTEGER *static const HANDLE const LARGE_INTEGER *static PSLIST_ENTRY PSLIST_ENTRY last
Definition: sync.c:64
static ULONG ** element_count
Definition: exception.c:124
static const struct metadata_block block1[]
Definition: metadata.c:3634
static const struct metadata_block block2[]
Definition: metadata.c:3639
static BYTE parameters[]
Definition: asn.c:558
#define min(a, b)
Definition: monoChain.cc:55
int k
Definition: mpi.c:3369
#define uint8_t
Definition: nsiface.idl:59
#define swap(a, b)
Definition: qsort.c:63
#define alloc
Definition: rosglue.h:13
#define list
Definition: rosglue.h:35
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
#define args
Definition: format.c:66
static int is_array(const type_t *t)
Definition: header.h:60
#define finish()
Definition: seh0024.c:15
#define TRACE(s)
Definition: solgame.cpp:4
enum vkd3d_shader_spirv_environment environment
Definition: spirv.c:4841
enum vkd3d_shader_register_type reg_type
Definition: spirv.c:4885
enum vkd3d_shader_sysval_semantic sysval
Definition: spirv.c:4839
Definition: polytest.cpp:36
Definition: match.c:390
struct vkd3d_shader_src_param * false_param
Definition: ir.c:2500
uint32_t merge_block_id
Definition: ir.c:2502
unsigned int else_block_id
Definition: ir.c:2503
unsigned int id
Definition: ir.c:2501
@ VKD3D_BLOCK_SWITCH
Definition: ir.c:2544
@ VKD3D_BLOCK_IF
Definition: ir.c:2542
@ VKD3D_BLOCK_LOOP
Definition: ir.c:2543
bool inside_block
Definition: ir.c:2546
enum cf_flattener_info::@6005 current_block
struct cf_flattener_switch_info switch_
Definition: ir.c:2537
struct cf_flattener_loop_info loop
Definition: ir.c:2536
union cf_flattener_info::@6004 u
struct cf_flattener_if_info if_
Definition: ir.c:2535
unsigned int continue_block_id
Definition: ir.c:2509
uint32_t merge_block_id
Definition: ir.c:2510
unsigned int header_block_id
Definition: ir.c:2508
unsigned int block_id
Definition: ir.c:2516
unsigned int value
Definition: ir.c:2515
const struct vkd3d_shader_src_param * condition
Definition: ir.c:2522
unsigned int merge_block_id
Definition: ir.c:2524
unsigned int cases_count
Definition: ir.c:2528
struct cf_flattener_switch_case * cases
Definition: ir.c:2526
unsigned int default_block_id
Definition: ir.c:2525
unsigned int id
Definition: ir.c:2523
unsigned int loop_id
Definition: ir.c:2566
size_t control_flow_info_size
Definition: ir.c:2571
struct vkd3d_shader_location location
Definition: ir.c:2553
struct vkd3d_shader_instruction * instructions
Definition: ir.c:2556
unsigned int control_flow_depth
Definition: ir.c:2569
enum vkd3d_result status
Definition: ir.c:2554
size_t instruction_capacity
Definition: ir.c:2557
unsigned int branch_id
Definition: ir.c:2565
size_t instruction_count
Definition: ir.c:2558
struct cf_flattener_info * control_flow_info
Definition: ir.c:2570
size_t block_name_capacity
Definition: ir.c:2562
unsigned int block_id
Definition: ir.c:2560
struct vsir_program * program
Definition: ir.c:2551
const char ** block_names
Definition: ir.c:2561
size_t block_name_count
Definition: ir.c:2563
unsigned int switch_id
Definition: ir.c:2567
struct vkd3d_shader_instruction_array instructions
Definition: ir.c:1326
struct vkd3d_shader_src_param * outpointid_param
Definition: ir.c:1328
enum vkd3d_shader_opcode phase
Definition: ir.c:1327
uint32_t value[4]
Definition: ir.c:2286
uint32_t index
Definition: ir.c:2285
enum vkd3d_shader_d3dbc_constant_register set
Definition: ir.c:2284
struct flat_constant_def * defs
Definition: ir.c:2291
Definition: dsound.c:943
struct vkd3d_shader_location last_ret_location
Definition: ir.c:1168
unsigned int instance_count
Definition: ir.c:1165
enum vkd3d_shader_opcode phase
Definition: ir.c:1167
struct vkd3d_shader_instruction_array instructions
Definition: ir.c:1163
unsigned int phase_body_idx
Definition: ir.c:1166
struct shader_reg * src
struct shader_reg dst
struct shader_signature * patch_constant_signature
Definition: ir.c:1524
struct vkd3d_shader_instruction_array instructions
Definition: ir.c:1519
unsigned int phase_body_idx
Definition: ir.c:1527
struct vkd3d_shader_dst_param * pc_dcl_params[MAX_REG_OUTPUT]
Definition: ir.c:1535
uint8_t pc_range_map[MAX_REG_OUTPUT][VKD3D_VEC4_SIZE]
Definition: ir.c:1538
bool use_vocp
Definition: ir.c:1540
struct vkd3d_shader_src_param * outpointid_param
Definition: ir.c:1531
unsigned int output_control_point_count
Definition: ir.c:1529
uint8_t output_range_map[MAX_REG_OUTPUT][VKD3D_VEC4_SIZE]
Definition: ir.c:1537
struct shader_signature * output_signature
Definition: ir.c:1523
struct vkd3d_shader_dst_param * output_dcl_params[MAX_REG_OUTPUT]
Definition: ir.c:1534
uint8_t major
Definition: ir.c:1521
enum vkd3d_shader_type shader_type
Definition: ir.c:1520
enum vkd3d_shader_opcode phase
Definition: ir.c:1528
struct shader_signature * input_signature
Definition: ir.c:1522
struct vkd3d_shader_dst_param * input_dcl_params[MAX_REG_OUTPUT]
Definition: ir.c:1533
unsigned int instance_count
Definition: ir.c:1526
uint8_t input_range_map[MAX_REG_OUTPUT][VKD3D_VEC4_SIZE]
Definition: ir.c:1536
Definition: name.c:39
Definition: send.c:48
unsigned int count
Definition: ir.c:1187
unsigned int instance_count
Definition: ir.c:1179
unsigned int instruction_count
Definition: ir.c:1180
unsigned int index
Definition: ir.c:1178
enum vkd3d_shader_minimum_precision min_precision
enum vkd3d_shader_component_type component_type
enum vkd3d_shader_sysval_semantic sysval_semantic
unsigned int next_temp_idx
Definition: ir.c:3340
unsigned int * table
Definition: ir.c:3339
struct vkd3d_shader_src_param * src
Definition: ir.c:3380
struct vkd3d_shader_dst_param * dst
Definition: ir.c:3381
size_t incoming_capacity
Definition: ir.c:3383
size_t incoming_count
Definition: ir.c:3384
struct ssas_to_temps_block_info::phi_incoming_to_temp * incomings
Definition: format.c:80
enum vkd3d_shader_component_type data_type
Definition: ir.c:7449
unsigned int patch_constant
Definition: ir.c:7448
unsigned int component_count
Definition: ir.c:7450
Definition: tools.h:99
bool invalid_instruction_idx
Definition: ir.c:6643
enum vkd3d_shader_opcode * blocks
Definition: ir.c:6665
struct validation_context::validation_context_temp_data * temps
bool dcl_temps_found
Definition: ir.c:6645
enum vkd3d_result status
Definition: ir.c:6644
const struct vsir_program * program
Definition: ir.c:6640
size_t instruction_idx
Definition: ir.c:6641
size_t blocks_capacity
Definition: ir.c:6667
struct vkd3d_shader_message_context * message_context
Definition: ir.c:6639
size_t depth
Definition: ir.c:6666
struct vkd3d_shader_location null_location
Definition: ir.c:6642
bool inside_block
Definition: ir.c:6647
struct validation_context::validation_context_ssa_data * ssas
enum vkd3d_shader_opcode phase
Definition: ir.c:6646
struct vkd3d_shader_register reg
struct vkd3d_shader_src_param * outpointid_param
struct vkd3d_shader_param_allocator src_params
struct vkd3d_shader_instruction * elements
struct vkd3d_shader_src_param * src
struct vkd3d_shader_location location
struct vkd3d_shader_register_semantic register_semantic
union vkd3d_shader_instruction::@6020 declaration
enum vkd3d_shader_opcode opcode
struct vkd3d_shader_dst_param * dst
struct vkd3d_shader_index_range index_range
enum vkd3d_shader_parameter_type type
Definition: vkd3d_shader.h:875
struct vkd3d_shader_parameter_immediate_constant1 immediate_constant
Definition: vkd3d_shader.h:887
enum vkd3d_shader_parameter_data_type data_type
Definition: vkd3d_shader.h:880
enum vkd3d_shader_parameter_name name
Definition: vkd3d_shader.h:873
union vkd3d_shader_parameter1::@5986 u
const struct vkd3d_shader_parameter1 * parameters
const struct vkd3d_shader_parameter * parameters
enum vkd3d_shader_spirv_environment environment
struct vkd3d_shader_register reg
enum vkd3d_shader_src_modifier modifiers
const struct vkd3d_shader_varying_map * varying_map
size_t capacity
Definition: ir.c:3529
struct vsir_block ** blocks
Definition: ir.c:3528
size_t count
Definition: ir.c:3529
struct vkd3d_shader_instruction * end
Definition: ir.c:3580
struct vkd3d_shader_instruction * begin
Definition: ir.c:3580
uint32_t * dominates
Definition: ir.c:3582
struct vsir_block_list predecessors successors
Definition: ir.c:3581
unsigned int order_pos
Definition: ir.c:3575
unsigned int label
Definition: ir.c:3575
unsigned int begin
Definition: ir.c:3791
unsigned int end
Definition: ir.c:3791
unsigned int target_count
Definition: ir.c:3815
struct vsir_block * successor
Definition: ir.c:4680
unsigned int target
Definition: ir.c:4679
enum vsir_cfg_jump_type jump_type
Definition: ir.c:4678
unsigned int temp_count
Definition: ir.c:3765
size_t ins_capacity
Definition: ir.c:3763
unsigned int jump_target_temp_idx
Definition: ir.c:3764
struct vkd3d_shader_instruction * instructions
Definition: ir.c:3762
size_t ins_count
Definition: ir.c:3763
size_t stack_count
Definition: ir.c:4324
struct vsir_block_list available_blocks
Definition: ir.c:4325
struct vsir_cfg * cfg
Definition: ir.c:4317
size_t stack_capacity
Definition: ir.c:4324
struct vsir_cfg_node_sorter::vsir_cfg_node_sorter_stack_item * stack
struct vsir_cfg_structure * structures
Definition: ir.c:3637
unsigned int end
Definition: ir.c:3639
unsigned idx
Definition: ir.c:3664
struct vsir_cfg_structure::@6006::vsir_cfg_structure_selection selection
struct vsir_block * block
Definition: ir.c:3660
bool needs_trampoline
Definition: ir.c:3665
union vsir_cfg_structure::@6006 u
vsir_cfg_structure_type
Definition: ir.c:3645
@ STRUCTURE_TYPE_LOOP
Definition: ir.c:3649
@ STRUCTURE_TYPE_SELECTION
Definition: ir.c:3651
@ STRUCTURE_TYPE_BLOCK
Definition: ir.c:3647
@ STRUCTURE_TYPE_JUMP
Definition: ir.c:3656
struct vsir_cfg_structure::@6006::vsir_cfg_structure_loop loop
struct vsir_cfg_structure * outer_loop
Definition: ir.c:3666
unsigned int target
Definition: ir.c:3686
struct vsir_cfg_structure::@6006::vsir_cfg_structure_jump jump
bool invert_condition
Definition: ir.c:3673
struct vkd3d_shader_src_param * condition
Definition: ir.c:3670
enum vsir_cfg_structure::vsir_cfg_structure_type type
bool needs_launcher
Definition: ir.c:3689
Definition: ir.c:3769
struct vsir_block * blocks
Definition: ir.c:3774
struct vsir_cfg_structure_list structured_program
Definition: ir.c:3819
struct vkd3d_shader_message_context * message_context
Definition: ir.c:3770
size_t loops_count
Definition: ir.c:3780
size_t loop_interval_count
Definition: ir.c:3817
struct vkd3d_string_buffer debug_buffer
Definition: ir.c:3777
size_t loop_interval_capacity
Definition: ir.c:3817
struct vsir_block_list * loops
Definition: ir.c:3779
struct vsir_cfg_emit_target * target
Definition: ir.c:3821
size_t block_count
Definition: ir.c:3776
struct vsir_block * entry
Definition: ir.c:3775
struct vsir_block_list order
Definition: ir.c:3783
size_t loops_capacity
Definition: ir.c:3780
struct vsir_program * program
Definition: ir.c:3771
size_t * loops_by_header
Definition: ir.c:3781
size_t function_begin
Definition: ir.c:3772
struct vsir_cfg::cfg_loop_interval * loop_intervals
size_t function_end
Definition: ir.c:3773
enum vkd3d_result result
Definition: ir.c:24
struct vkd3d_shader_message_context * message_context
Definition: ir.c:28
struct vsir_program * program
Definition: ir.c:25
uint64_t config_flags
Definition: ir.c:26
const struct vkd3d_shader_compile_info * compile_info
Definition: ir.c:27
unsigned int src_param_count
Definition: ir.c:8053
unsigned int dst_param_count
Definition: ir.c:8052
void(* validate)(struct validation_context *ctx, const struct vkd3d_shader_instruction *instruction)
Definition: ir.c:8054
#define max(a, b)
Definition: svc.c:63
#define bsearch
struct _LARGE_INTEGER::@2736 u
Definition: pdh_main.c:64
static unsigned int vkd3d_popcount(unsigned int v)
Definition: vkd3d_common.h:280
#define VKD3D_PRINTF_FUNC(fmt, args)
Definition: vkd3d_common.h:114
static bool bitmap_is_set(const uint32_t *map, unsigned int idx)
Definition: vkd3d_common.h:408
#define vkd3d_unreachable()
Definition: vkd3d_common.h:119
#define VKD3D_BITMAP_SIZE(x)
Definition: vkd3d_common.h:396
static bool vkd3d_bitmask_is_contiguous(unsigned int mask)
Definition: vkd3d_common.h:293
#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 int vkd3d_u32_compare(uint32_t x, uint32_t y)
Definition: vkd3d_common.h:386
static bool bitmap_clear(uint32_t *map, unsigned int idx)
Definition: vkd3d_common.h:398
static void * vkd3d_calloc(size_t count, size_t size)
Definition: vkd3d_memory.h:43
static char * vkd3d_strdup(const char *string)
Definition: vkd3d_memory.h:57
static void * vkd3d_realloc(void *ptr, size_t size)
Definition: vkd3d_memory.h:36
static void vkd3d_free(void *ptr)
Definition: vkd3d_memory.h:52
static void * vkd3d_malloc(size_t size)
Definition: vkd3d_memory.h:28
bool vkd3d_array_reserve(void **elements, size_t *capacity, size_t element_count, size_t element_size)
Definition: memory.c:22
vkd3d_shader_d3dbc_constant_register
Definition: vkd3d_shader.h:913
@ VKD3D_SHADER_D3DBC_BOOL_CONSTANT_REGISTER
Definition: vkd3d_shader.h:919
@ VKD3D_SHADER_D3DBC_FLOAT_CONSTANT_REGISTER
Definition: vkd3d_shader.h:915
@ VKD3D_SHADER_D3DBC_INT_CONSTANT_REGISTER
Definition: vkd3d_shader.h:917
static uint32_t vkd3d_shader_create_swizzle(enum vkd3d_shader_swizzle_component x, enum vkd3d_shader_swizzle_component y, enum vkd3d_shader_swizzle_component z, enum vkd3d_shader_swizzle_component w)
vkd3d_shader_comparison_func
@ VKD3D_SHADER_COMPARISON_FUNC_EQUAL
@ VKD3D_SHADER_COMPARISON_FUNC_GREATER_EQUAL
@ VKD3D_SHADER_COMPARISON_FUNC_ALWAYS
@ VKD3D_SHADER_COMPARISON_FUNC_NEVER
@ VKD3D_SHADER_COMPARISON_FUNC_GREATER
@ VKD3D_SHADER_COMPARISON_FUNC_NOT_EQUAL
@ VKD3D_SHADER_COMPARISON_FUNC_LESS
@ VKD3D_SHADER_COMPARISON_FUNC_LESS_EQUAL
@ VKD3D_SHADER_PARAMETER_TYPE_SPECIALIZATION_CONSTANT
Definition: vkd3d_shader.h:487
@ VKD3D_SHADER_PARAMETER_TYPE_IMMEDIATE_CONSTANT
Definition: vkd3d_shader.h:482
@ VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32_VEC4
Definition: vkd3d_shader.h:516
@ VKD3D_SHADER_PARAMETER_DATA_TYPE_UINT32
Definition: vkd3d_shader.h:507
@ VKD3D_SHADER_PARAMETER_DATA_TYPE_FLOAT32
Definition: vkd3d_shader.h:509
vkd3d_shader_sysval_semantic
@ VKD3D_SHADER_SV_VERTEX_ID
@ VKD3D_SHADER_SV_RENDER_TARGET_ARRAY_INDEX
@ VKD3D_SHADER_SV_DEPTH_LESS_EQUAL
@ VKD3D_SHADER_SV_PRIMITIVE_ID
@ VKD3D_SHADER_SV_COVERAGE
@ VKD3D_SHADER_SV_CULL_DISTANCE
@ VKD3D_SHADER_SV_DEPTH
@ VKD3D_SHADER_SV_TESS_FACTOR_TRIEDGE
@ VKD3D_SHADER_SV_TARGET
@ VKD3D_SHADER_SV_NONE
@ VKD3D_SHADER_SV_TESS_FACTOR_LINEDET
@ VKD3D_SHADER_SV_TESS_FACTOR_QUADEDGE
@ VKD3D_SHADER_SV_IS_FRONT_FACE
@ VKD3D_SHADER_SV_VIEWPORT_ARRAY_INDEX
@ VKD3D_SHADER_SV_TESS_FACTOR_QUADINT
@ VKD3D_SHADER_SV_TESS_FACTOR_TRIINT
@ VKD3D_SHADER_SV_TESS_FACTOR_LINEDEN
@ VKD3D_SHADER_SV_DEPTH_GREATER_EQUAL
@ VKD3D_SHADER_SV_INSTANCE_ID
@ VKD3D_SHADER_SV_CLIP_DISTANCE
@ VKD3D_SHADER_SV_SAMPLE_INDEX
@ VKD3D_SHADER_SV_STENCIL_REF
@ VKD3D_SHADER_SV_POSITION
@ VKD3D_SHADER_TESSELLATOR_OUTPUT_TRIANGLE_CCW
vkd3d_shader_component_type
@ VKD3D_SHADER_COMPONENT_INT
@ VKD3D_SHADER_COMPONENT_UINT
@ VKD3D_SHADER_COMPONENT_FLOAT
@ VKD3D_SHADER_TESSELLATOR_PARTITIONING_FRACTIONAL_EVEN
#define VKD3D_SHADER_SWIZZLE_SHIFT(idx)
@ VKD3D_SHADER_MINIMUM_PRECISION_NONE
#define VKD3D_SHADER_SWIZZLE(x, y, z, w)
#define VKD3D_SHADER_NO_SWIZZLE
@ VKD3D_SHADER_TARGET_SPIRV_BINARY
@ VKD3D_SHADER_TARGET_GLSL
@ VKD3D_SHADER_TARGET_MSL
vkd3d_shader_spirv_environment
@ VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_0
@ VKD3D_SHADER_SPIRV_ENVIRONMENT_OPENGL_4_5
@ VKD3D_SHADER_SPIRV_ENVIRONMENT_VULKAN_1_1
vkd3d_shader_parameter_name
Definition: vkd3d_shader.h:526
@ VKD3D_SHADER_PARAMETER_NAME_POINT_SPRITE
Definition: vkd3d_shader.h:736
@ VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_FUNC
Definition: vkd3d_shader.h:565
@ VKD3D_SHADER_PARAMETER_NAME_ALPHA_TEST_REF
Definition: vkd3d_shader.h:575
@ VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MAX
Definition: vkd3d_shader.h:703
@ VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE_MIN
Definition: vkd3d_shader.h:693
@ VKD3D_SHADER_PARAMETER_NAME_POINT_SIZE
Definition: vkd3d_shader.h:670
@ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_0
Definition: vkd3d_shader.h:644
@ VKD3D_SHADER_PARAMETER_NAME_FLAT_INTERPOLATION
Definition: vkd3d_shader.h:599
@ VKD3D_SHADER_PARAMETER_NAME_CLIP_PLANE_MASK
Definition: vkd3d_shader.h:627
bool shader_instruction_array_init(struct vkd3d_shader_instruction_array *instructions, unsigned int reserve)
void vkd3d_string_buffer_init(struct vkd3d_string_buffer *buffer)
int vkd3d_string_buffer_vprintf(struct vkd3d_string_buffer *buffer, const char *format, va_list args)
bool shader_instruction_array_insert_at(struct vkd3d_shader_instruction_array *instructions, unsigned int idx, unsigned int count)
void vkd3d_string_buffer_cleanup(struct vkd3d_string_buffer *buffer)
void vkd3d_string_buffer_truncate(struct vkd3d_string_buffer *buffer, size_t size)
void shader_instruction_array_destroy(struct vkd3d_shader_instruction_array *instructions)
void vkd3d_string_buffer_clear(struct vkd3d_string_buffer *buffer)
void shader_signature_cleanup(struct shader_signature *signature)
bool shader_instruction_array_clone_instruction(struct vkd3d_shader_instruction_array *instructions, unsigned int dst, unsigned int src)
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,...)
#define vkd3d_find_struct(c, t)
#define VKD3DSI_PRECISE_XYZW
@ VKD3DSPSM_NONE
@ VKD3DSPSM_COUNT
static bool data_type_is_64_bit(enum vkd3d_data_type data_type)
vkd3d_shader_type
@ VKD3D_SHADER_TYPE_VERTEX
@ VKD3D_SHADER_TYPE_HULL
@ VKD3D_SHADER_TYPE_GEOMETRY
@ VKD3D_SHADER_TYPE_PIXEL
@ VKD3D_SHADER_TYPE_DOMAIN
@ VKD3DSIM_CONSTANT
@ VKD3DSIM_NONE
@ VKD3DSIM_LINEAR
@ VKD3DSIM_COUNT
static uint32_t vsir_swizzle_from_writemask(unsigned int writemask)
static struct vkd3d_shader_dst_param * vsir_program_get_dst_params(struct vsir_program *program, unsigned int count)
#define VKD3DSP_WRITEMASK_3
static unsigned int vsir_write_mask_component_count(uint32_t write_mask)
vkd3d_shader_register_type
@ VKD3DSPR_DEPTHOUTGE
@ VKD3DSPR_PARAMETER
@ VKD3DSPR_POINT_COORD
@ VKD3DSPR_INCONTROLPOINT
@ VKD3DSPR_LABEL
@ VKD3DSPR_IMMCONST
@ VKD3DSPR_CONSTBOOL
@ VKD3DSPR_NULL
@ VKD3DSPR_CONSTBUFFER
@ VKD3DSPR_CONST4
@ VKD3DSPR_SSA
@ VKD3DSPR_RASTOUT
@ VKD3DSPR_RESOURCE
@ VKD3DSPR_COUNT
@ VKD3DSPR_COLOROUT
@ VKD3DSPR_MISCTYPE
@ VKD3DSPR_DEPTHOUT
@ VKD3DSPR_DEPTHOUTLE
@ VKD3DSPR_CONSTINT
@ VKD3DSPR_CONST
@ VKD3DSPR_JOININSTID
@ VKD3DSPR_IMMCONST64
@ VKD3DSPR_UAV
@ VKD3DSPR_TEMP
@ VKD3DSPR_CONST2
@ VKD3DSPR_CONST3
@ VKD3DSPR_OUTPUT
@ VKD3DSPR_SAMPLER
@ VKD3DSPR_FORKINSTID
@ VKD3DSPR_OUTCONTROLPOINT
@ VKD3DSPR_OUTPOINTID
@ VKD3DSPR_TEXTURE
@ VKD3DSPR_ATTROUT
@ VKD3DSPR_PATCHCONST
@ VKD3DSPR_INPUT
vkd3d_shader_error
@ VKD3D_SHADER_ERROR_VSIR_INVALID_DATA_TYPE
@ VKD3D_SHADER_ERROR_VSIR_INVALID_SSA_USAGE
@ VKD3D_SHADER_ERROR_VSIR_INVALID_DEST_COUNT
@ VKD3D_SHADER_ERROR_VSIR_INVALID_REGISTER_TYPE
@ VKD3D_SHADER_ERROR_VSIR_INVALID_GS
@ VKD3D_SHADER_ERROR_VSIR_INVALID_PRECISION
@ VKD3D_SHADER_ERROR_VSIR_INVALID_WRITE_MASK
@ VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX_COUNT
@ VKD3D_SHADER_ERROR_VSIR_MISSING_SEMANTIC
@ VKD3D_SHADER_ERROR_VSIR_INVALID_PARAMETER
@ VKD3D_SHADER_ERROR_VSIR_INVALID_INDEX
@ VKD3D_SHADER_ERROR_VSIR_INVALID_MODIFIERS
@ VKD3D_SHADER_ERROR_VSIR_INVALID_DCL_TEMPS
@ VKD3D_SHADER_ERROR_VSIR_INVALID_HANDLER
@ VKD3D_SHADER_ERROR_VSIR_INVALID_SHIFT
@ VKD3D_SHADER_ERROR_VSIR_INVALID_SIGNATURE
@ VKD3D_SHADER_ERROR_VSIR_NOT_IMPLEMENTED
@ VKD3D_SHADER_ERROR_VSIR_DUPLICATE_DCL_TEMPS
@ VKD3D_SHADER_ERROR_VSIR_INVALID_SWIZZLE
@ VKD3D_SHADER_ERROR_VSIR_INVALID_CONTROL_FLOW
@ VKD3D_SHADER_ERROR_VSIR_INVALID_TESSELLATION
@ VKD3D_SHADER_ERROR_VSIR_INVALID_DIMENSION
@ VKD3D_SHADER_ERROR_VSIR_INVALID_SOURCE_COUNT
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_COUNT
@ VSIR_DIMENSION_NONE
@ VKD3D_DATA_COUNT
@ VKD3D_DATA_BOOL
@ VKD3D_DATA_UNUSED
@ VKD3D_DATA_UINT
@ VKD3D_DATA_FLOAT
vsir_normalisation_level
@ VSIR_NOT_NORMALISED
@ VSIR_FULLY_NORMALISED_IO
@ VSIR_NORMALISED_HULL_CONTROL_POINT_IO
static struct vkd3d_shader_src_param * vsir_program_get_src_params(struct vsir_program *program, unsigned int count)
static bool register_is_constant_or_undef(const struct vkd3d_shader_register *reg)
static unsigned int vsir_write_mask_get_component_idx(uint32_t write_mask)
@ VSIR_RASTOUT_POINT_SIZE
static unsigned int vsir_swizzle_get_component(uint32_t swizzle, unsigned int idx)
vkd3d_shader_opcode
@ VKD3DSIH_NOP
@ VKD3DSIH_ENDSWITCH
@ VKD3DSIH_TEXM3x3SPEC
@ VKD3DSIH_HS_JOIN_PHASE
@ VKD3DSIH_TEXREG2RGB
@ VKD3DSIH_TEXDP3TEX
@ VKD3DSIH_TEX
@ VKD3DSIH_TEXM3x3PAD
@ VKD3DSIH_DCL_HS_JOIN_PHASE_INSTANCE_COUNT
@ VKD3DSIH_DCL_TESSELLATOR_OUTPUT_PRIMITIVE
@ VKD3DSIH_DCL_INPUT_CONTROL_POINT_COUNT
@ VKD3DSIH_LOOP
@ VKD3DSIH_TEXDP3
@ VKD3DSIH_TEXREG2AR
@ VKD3DSIH_DCL_INPUT_PS
@ VKD3DSIH_NEO
@ VKD3DSIH_TEXM3x3DIFF
@ VKD3DSIH_SWITCH
@ VKD3DSIH_UGE
@ VKD3DSIH_TEXM3x2PAD
@ VKD3DSIH_DCL_INPUT_PRIMITIVE
@ VKD3DSIH_DP4
@ VKD3DSIH_IEQ
@ VKD3DSIH_DCL_OUTPUT
@ VKD3DSIH_DCL_GS_INSTANCES
@ VKD3DSIH_SAMPLE
@ VKD3DSIH_TEXKILL
@ VKD3DSIH_ENDREP
@ VKD3DSIH_DCL_OUTPUT_SIV
@ VKD3DSIH_TEXCOORD
@ VKD3DSIH_DCL_VERTICES_OUT
@ VKD3DSIH_DCL_SAMPLER
@ VKD3DSIH_DCL_INPUT_SGV
@ VKD3DSIH_DCL_OUTPUT_TOPOLOGY
@ VKD3DSIH_TEXREG2GB
@ VKD3DSIH_MUL
@ VKD3DSIH_BREAK
@ VKD3DSIH_TEXBEM
@ VKD3DSIH_DISCARD
@ VKD3DSIH_IFC
@ VKD3DSIH_HS_DECLS
@ VKD3DSIH_CASE
@ VKD3DSIH_MIN
@ VKD3DSIH_CONTINUE
@ VKD3DSIH_INVALID
@ VKD3DSIH_DCL_GLOBAL_FLAGS
@ VKD3DSIH_IF
@ VKD3DSIH_TEXM3x2TEX
@ VKD3DSIH_ENDIF
@ VKD3DSIH_REP
@ VKD3DSIH_DCL_HS_MAX_TESSFACTOR
@ VKD3DSIH_DCL_TEMPS
@ VKD3DSIH_DCL_INPUT
@ VKD3DSIH_HS_CONTROL_POINT_PHASE
@ VKD3DSIH_EQO
@ VKD3DSIH_DCL_INPUT_PS_SIV
@ VKD3DSIH_DCL_HS_FORK_PHASE_INSTANCE_COUNT
@ VKD3DSIH_TEXLDD
@ VKD3DSIH_DCL_THREAD_GROUP
@ VKD3DSIH_TEXM3x3VSPEC
@ VKD3DSIH_LTO
@ VKD3DSIH_CONTINUEP
@ VKD3DSIH_DEFB
@ VKD3DSIH_MAD
@ VKD3DSIH_TEXDEPTH
@ VKD3DSIH_ADD
@ VKD3DSIH_DEF
@ VKD3DSIH_TEXBEML
@ VKD3DSIH_DEFI
@ VKD3DSIH_INE
@ VKD3DSIH_DCL_INPUT_SIV
@ VKD3DSIH_HS_FORK_PHASE
@ VKD3DSIH_MOV
@ VKD3DSIH_MAX
@ VKD3DSIH_ULT
@ VKD3DSIH_SWITCH_MONOLITHIC
@ VKD3DSIH_PHI
@ VKD3DSIH_TEXLDL
@ VKD3DSIH_OR
@ VKD3DSIH_DCL_TESSELLATOR_DOMAIN
@ VKD3DSIH_DCL_OUTPUT_CONTROL_POINT_COUNT
@ VKD3DSIH_ENDLOOP
@ VKD3DSIH_DCL
@ VKD3DSIH_DCL_UAV_TYPED
@ VKD3DSIH_TEXM3x3TEX
@ VKD3DSIH_DCL_INDEX_RANGE
@ VKD3DSIH_SAMPLE_GRAD
@ VKD3DSIH_ELSE
@ VKD3DSIH_DCL_INPUT_PS_SGV
@ VKD3DSIH_DCL_CONSTANT_BUFFER
@ VKD3DSIH_DCL_INDEXABLE_TEMP
@ VKD3DSIH_LABEL
@ VKD3DSIH_BREAKP
@ VKD3DSIH_GEO
@ VKD3DSIH_SINCOS
@ VKD3DSIH_DEFAULT
@ VKD3DSIH_RET
@ VKD3DSIH_BRANCH
@ VKD3DSIH_DCL_TESSELLATOR_PARTITIONING
#define SM1_COLOR_REGISTER_OFFSET
@ VKD3D_SHADER_REGISTER_PRECISION_DEFAULT
@ VKD3D_SHADER_REGISTER_PRECISION_COUNT
@ VKD3D_TESSELLATOR_DOMAIN_INVALID
@ VKD3D_TESSELLATOR_DOMAIN_COUNT
static bool register_is_ssa(const struct vkd3d_shader_register *reg)
static enum vkd3d_data_type vkd3d_data_type_from_component_type(enum vkd3d_shader_component_type component_type)
static bool register_is_constant(const struct vkd3d_shader_register *reg)
@ VKD3D_SHADER_CONFIG_FLAG_FORCE_VALIDATION
static bool vsir_sysval_semantic_is_tess_factor(enum vkd3d_shader_sysval_semantic sysval_semantic)
@ VKD3D_PT_COUNT
@ VKD3D_PT_UNDEFINED
@ VKD3D_SHADER_CONDITIONAL_OP_NZ
@ VKD3D_SHADER_CONDITIONAL_OP_Z
#define VKD3D_SHADER_MINIMUM_PRECISION_COUNT
@ VKD3DSPDM_NONE
@ VKD3DSPDM_MASK
static bool vsir_register_is_label(const struct vkd3d_shader_register *reg)
#define VKD3DSP_WRITEMASK_0
#define SM1_RASTOUT_REGISTER_OFFSET
#define VKD3DSP_WRITEMASK_1
vsir_control_flow_type
@ VSIR_CF_BLOCKS
@ VSIR_CF_STRUCTURED
static struct vkd3d_shader_src_param * shader_src_param_allocator_get(struct vkd3d_shader_param_allocator *allocator, unsigned int count)
#define SIGNATURE_TARGET_LOCATION_UNUSED
static enum vkd3d_shader_input_sysval_semantic vkd3d_siv_from_sysval(enum vkd3d_shader_sysval_semantic sysval)
#define VKD3DSP_WRITEMASK_2
vkd3d_shader_rel_op
@ VKD3D_SHADER_REL_OP_LT
@ VKD3D_SHADER_REL_OP_GT
@ VKD3D_SHADER_REL_OP_EQ
@ VKD3D_SHADER_REL_OP_GE
@ VKD3D_SHADER_REL_OP_NE
@ VKD3D_SHADER_REL_OP_LE
#define VKD3D_VEC4_SIZE
vkd3d_result
Definition: vkd3d_types.h:41
@ VKD3D_ERROR_INVALID_ARGUMENT
Definition: vkd3d_types.h:51
@ VKD3D_ERROR_NOT_IMPLEMENTED
Definition: vkd3d_types.h:55
@ VKD3D_ERROR_INVALID_SHADER
Definition: vkd3d_types.h:53
@ VKD3D_FALSE
Definition: vkd3d_types.h:45
@ VKD3D_OK
Definition: vkd3d_types.h:43
@ 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
#define MAX_REG_OUTPUT
static unsigned int block
Definition: xmlmemory.c:101
#define const
Definition: zconf.h:233