1 /*
2 * Copyright (c) 2013-2024 Broadcom. All Rights Reserved.
3 * The term “Broadcom” refers to Broadcom Inc.
4 * and/or its subsidiaries.
5 * SPDX-License-Identifier: MIT
6 */
7
8
9 #include "svga_context.h"
10 #include "svga_link.h"
11 #include "svga_debug.h"
12
13 #include "tgsi/tgsi_scan.h"
14 #include "tgsi/tgsi_strings.h"
15
16
17 #define INVALID_INDEX 255
18
19
20 /**
21 * Examine input and output shaders info to link outputs from the
22 * output shader to inputs from the input shader.
23 * Basically, we'll remap input shader's input slots to new numbers
24 * based on semantic name/index of the outputs from the output shader.
25 */
26 void
svga_link_shaders(const struct tgsi_shader_info * outshader_info,const struct tgsi_shader_info * inshader_info,struct shader_linkage * linkage)27 svga_link_shaders(const struct tgsi_shader_info *outshader_info,
28 const struct tgsi_shader_info *inshader_info,
29 struct shader_linkage *linkage)
30 {
31 unsigned i, free_slot;
32
33 for (i = 0; i < ARRAY_SIZE(linkage->input_map); i++) {
34 linkage->input_map[i] = INVALID_INDEX;
35 }
36
37 for (i = 0; i < ARRAY_SIZE(linkage->prevShader.output_map); i++) {
38 linkage->prevShader.output_map[i] = INVALID_INDEX;
39 }
40
41 /* Assign input slots for input shader inputs.
42 * Basically, we want to use the same index for the output shader's outputs
43 * and the input shader's inputs that should be linked together.
44 * We'll modify the input shader's inputs to match the output shader.
45 */
46 assert(inshader_info->num_inputs <=
47 ARRAY_SIZE(inshader_info->input_semantic_name));
48
49 /* free register index that can be used for built-in varyings */
50 free_slot = outshader_info->num_outputs + 1;
51
52 for (i = 0; i < inshader_info->num_inputs; i++) {
53 enum tgsi_semantic sem_name = inshader_info->input_semantic_name[i];
54 unsigned sem_index = inshader_info->input_semantic_index[i];
55 unsigned j;
56 unsigned out_index;
57
58 if (sem_name == TGSI_SEMANTIC_PCOORD) {
59 sem_name = TGSI_SEMANTIC_TEXCOORD;
60 sem_index = 0;
61 }
62
63 /* search output shader outputs for same item */
64 for (j = 0; j < outshader_info->num_outputs; j++) {
65 assert(j < ARRAY_SIZE(outshader_info->output_semantic_name));
66 if (outshader_info->output_semantic_name[j] == sem_name &&
67 outshader_info->output_semantic_index[j] == sem_index) {
68 linkage->input_map[i] = j;
69 linkage->prevShader.output_map[j] = i;
70 break;
71 }
72 }
73
74 /**
75 * The clip distance inputs come from the output shader's
76 * clip distance shadow copy, so mark the input index to match
77 * the index of the shadow copy.
78 */
79 if (sem_name == TGSI_SEMANTIC_CLIPDIST) {
80 out_index = outshader_info->num_outputs + 1 + sem_index;
81 linkage->input_map[i] = out_index;
82 linkage->prevShader.output_map[out_index] = i;
83 /* make sure free_slot includes this extra output */
84 free_slot = MAX2(free_slot, linkage->input_map[i] + 1);
85 }
86 }
87
88 /* Find the index for position */
89 linkage->position_index = 0;
90 for (i = 0; i < outshader_info->num_outputs; i++) {
91 if (outshader_info->output_semantic_name[i] == TGSI_SEMANTIC_POSITION) {
92 linkage->position_index = i;
93 break;
94 }
95 }
96
97 linkage->num_inputs = inshader_info->num_inputs;
98 linkage->prevShader.num_outputs = outshader_info->num_outputs;
99
100 /* Things like the front-face register are handled here */
101 for (i = 0; i < inshader_info->num_inputs; i++) {
102 if (linkage->input_map[i] == INVALID_INDEX) {
103 unsigned j = free_slot++;
104 linkage->input_map[i] = j;
105 linkage->prevShader.output_map[j] = i;
106 }
107 }
108 linkage->input_map_max = free_slot - 1;
109
110 /* Debug */
111 if (SVGA_DEBUG & DEBUG_TGSI) {
112 uint64_t reg = 0;
113 uint64_t one = 1;
114
115 debug_printf(
116 "### linkage info: num_inputs=%d input_map_max=%d prevShader.num_outputs=%d\n",
117 linkage->num_inputs, linkage->input_map_max,
118 linkage->prevShader.num_outputs);
119
120 for (i = 0; i < linkage->num_inputs; i++) {
121
122 assert(linkage->input_map[i] != INVALID_INDEX);
123
124 debug_printf(" input[%d] slot %u %s %u %s\n",
125 i,
126 linkage->input_map[i],
127 tgsi_semantic_names[inshader_info->input_semantic_name[i]],
128 inshader_info->input_semantic_index[i],
129 tgsi_interpolate_names[inshader_info->input_interpolate[i]]);
130
131 /* make sure no repeating register index */
132 assert((reg & (one << linkage->input_map[i])) == 0);
133 reg |= one << linkage->input_map[i];
134 }
135 }
136 }
137