xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/svga/svga_link.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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