1 /*/ 2 * Copyright 2013 VMware, Inc. All rights reserved. 3 * 4 * Permission is hereby granted, free of charge, to any person 5 * obtaining a copy of this software and associated documentation 6 * files (the "Software"), to deal in the Software without 7 * restriction, including without limitation the rights to use, copy, 8 * modify, merge, publish, distribute, sublicense, and/or sell copies 9 * of the Software, and to permit persons to whom the Software is 10 * furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be 13 * included in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 26 #include "svga_context.h" 27 #include "svga_link.h" 28 #include "svga_debug.h" 29 30 #include "tgsi/tgsi_strings.h" 31 32 33 #define INVALID_INDEX 255 34 35 36 /** 37 * Examine input and output shaders info to link outputs from the 38 * output shader to inputs from the input shader. 39 * Basically, we'll remap input shader's input slots to new numbers 40 * based on semantic name/index of the outputs from the output shader. 41 */ 42 void 43 svga_link_shaders(const struct tgsi_shader_info *outshader_info, 44 const struct tgsi_shader_info *inshader_info, 45 struct shader_linkage *linkage) 46 { 47 unsigned i, free_slot; 48 49 for (i = 0; i < ARRAY_SIZE(linkage->input_map); i++) { 50 linkage->input_map[i] = INVALID_INDEX; 51 } 52 53 /* Assign input slots for input shader inputs. 54 * Basically, we want to use the same index for the output shader's outputs 55 * and the input shader's inputs that should be linked together. 56 * We'll modify the input shader's inputs to match the output shader. 57 */ 58 assert(inshader_info->num_inputs <= 59 ARRAY_SIZE(inshader_info->input_semantic_name)); 60 61 /* free register index that can be used for built-in varyings */ 62 free_slot = outshader_info->num_outputs + 1; 63 64 for (i = 0; i < inshader_info->num_inputs; i++) { 65 unsigned sem_name = inshader_info->input_semantic_name[i]; 66 unsigned sem_index = inshader_info->input_semantic_index[i]; 67 unsigned j; 68 /** 69 * Get the clip distance inputs from the output shader's 70 * clip distance shadow copy. 71 */ 72 if (sem_name == TGSI_SEMANTIC_CLIPDIST) { 73 linkage->input_map[i] = outshader_info->num_outputs + 1 + sem_index; 74 /* make sure free_slot includes this extra output */ 75 free_slot = MAX2(free_slot, linkage->input_map[i] + 1); 76 } 77 else { 78 /* search output shader outputs for same item */ 79 for (j = 0; j < outshader_info->num_outputs; j++) { 80 assert(j < ARRAY_SIZE(outshader_info->output_semantic_name)); 81 if (outshader_info->output_semantic_name[j] == sem_name && 82 outshader_info->output_semantic_index[j] == sem_index) { 83 linkage->input_map[i] = j; 84 break; 85 } 86 } 87 } 88 } 89 90 linkage->num_inputs = inshader_info->num_inputs; 91 92 /* Things like the front-face register are handled here */ 93 for (i = 0; i < inshader_info->num_inputs; i++) { 94 if (linkage->input_map[i] == INVALID_INDEX) { 95 unsigned j = free_slot++; 96 linkage->input_map[i] = j; 97 } 98 } 99 100 /* Debug */ 101 if (SVGA_DEBUG & DEBUG_TGSI) { 102 unsigned reg = 0; 103 debug_printf("### linkage info:\n"); 104 105 for (i = 0; i < linkage->num_inputs; i++) { 106 107 assert(linkage->input_map[i] != INVALID_INDEX); 108 109 debug_printf(" input[%d] slot %u %s %u %s\n", 110 i, 111 linkage->input_map[i], 112 tgsi_semantic_names[inshader_info->input_semantic_name[i]], 113 inshader_info->input_semantic_index[i], 114 tgsi_interpolate_names[inshader_info->input_interpolate[i]]); 115 116 /* make sure no repeating register index */ 117 if (reg & 1 << linkage->input_map[i]) { 118 assert(0); 119 } 120 reg |= 1 << linkage->input_map[i]; 121 } 122 } 123 } 124