svga_tgsi.c revision 279492386ffe741c2f5b91919b37068562b6a282
1/********************************************************** 2 * Copyright 2008-2009 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 27#include "pipe/p_compiler.h" 28#include "pipe/p_shader_tokens.h" 29#include "pipe/p_defines.h" 30#include "tgsi/tgsi_parse.h" 31#include "tgsi/tgsi_dump.h" 32#include "tgsi/tgsi_scan.h" 33#include "util/u_memory.h" 34#include "util/u_bitmask.h" 35 36#include "svgadump/svga_shader_dump.h" 37 38#include "svga_context.h" 39#include "svga_tgsi.h" 40#include "svga_tgsi_emit.h" 41#include "svga_debug.h" 42 43#include "svga_hw_reg.h" 44#include "svga3d_shaderdefs.h" 45 46 47/* Sinkhole used only in error conditions. 48 */ 49static char err_buf[128]; 50 51#if 0 52static void svga_destroy_shader_emitter( struct svga_shader_emitter *emit ) 53{ 54 if (emit->buf != err_buf) 55 FREE(emit->buf); 56} 57#endif 58 59 60static boolean svga_shader_expand( struct svga_shader_emitter *emit ) 61{ 62 char *new_buf; 63 unsigned newsize = emit->size * 2; 64 65 if(emit->buf != err_buf) 66 new_buf = REALLOC(emit->buf, emit->size, newsize); 67 else 68 new_buf = NULL; 69 70 if (new_buf == NULL) { 71 emit->ptr = err_buf; 72 emit->buf = err_buf; 73 emit->size = sizeof(err_buf); 74 return FALSE; 75 } 76 77 emit->size = newsize; 78 emit->ptr = new_buf + (emit->ptr - emit->buf); 79 emit->buf = new_buf; 80 return TRUE; 81} 82 83static INLINE boolean reserve( struct svga_shader_emitter *emit, 84 unsigned nr_dwords ) 85{ 86 if (emit->ptr - emit->buf + nr_dwords * sizeof(unsigned) >= emit->size) { 87 if (!svga_shader_expand( emit )) 88 return FALSE; 89 } 90 91 return TRUE; 92} 93 94boolean svga_shader_emit_dword( struct svga_shader_emitter *emit, 95 unsigned dword ) 96{ 97 if (!reserve(emit, 1)) 98 return FALSE; 99 100 *(unsigned *)emit->ptr = dword; 101 emit->ptr += sizeof dword; 102 return TRUE; 103} 104 105boolean svga_shader_emit_dwords( struct svga_shader_emitter *emit, 106 const unsigned *dwords, 107 unsigned nr ) 108{ 109 if (!reserve(emit, nr)) 110 return FALSE; 111 112 memcpy( emit->ptr, dwords, nr * sizeof *dwords ); 113 emit->ptr += nr * sizeof *dwords; 114 return TRUE; 115} 116 117boolean svga_shader_emit_opcode( struct svga_shader_emitter *emit, 118 unsigned opcode ) 119{ 120 SVGA3dShaderInstToken *here; 121 122 if (!reserve(emit, 1)) 123 return FALSE; 124 125 here = (SVGA3dShaderInstToken *)emit->ptr; 126 here->value = opcode; 127 128 if (emit->insn_offset) { 129 SVGA3dShaderInstToken *prev = (SVGA3dShaderInstToken *)(emit->buf + 130 emit->insn_offset); 131 prev->size = (here - prev) - 1; 132 } 133 134 emit->insn_offset = emit->ptr - emit->buf; 135 emit->ptr += sizeof(unsigned); 136 return TRUE; 137} 138 139#define SVGA3D_PS_2X (SVGA3D_PS_20 | 1) 140#define SVGA3D_VS_2X (SVGA3D_VS_20 | 1) 141 142static boolean svga_shader_emit_header( struct svga_shader_emitter *emit ) 143{ 144 SVGA3dShaderVersion header; 145 146 memset( &header, 0, sizeof header ); 147 148 switch (emit->unit) { 149 case PIPE_SHADER_FRAGMENT: 150 header.value = emit->use_sm30 ? SVGA3D_PS_30 : SVGA3D_PS_2X; 151 break; 152 case PIPE_SHADER_VERTEX: 153 header.value = emit->use_sm30 ? SVGA3D_VS_30 : SVGA3D_VS_2X; 154 break; 155 } 156 157 return svga_shader_emit_dword( emit, header.value ); 158} 159 160 161 162 163 164/* Parse TGSI shader and translate to SVGA/DX9 serialized 165 * representation. 166 * 167 * In this function SVGA shader is emitted to an in-memory buffer that 168 * can be dynamically grown. Once we've finished and know how large 169 * it is, it will be copied to a hardware buffer for upload. 170 */ 171static struct svga_shader_result * 172svga_tgsi_translate( const struct svga_shader *shader, 173 union svga_compile_key key, 174 unsigned unit ) 175{ 176 struct svga_shader_result *result = NULL; 177 struct svga_shader_emitter emit; 178 int ret = 0; 179 180 memset(&emit, 0, sizeof(emit)); 181 182 emit.use_sm30 = shader->use_sm30; 183 emit.size = 1024; 184 emit.buf = MALLOC(emit.size); 185 if (emit.buf == NULL) { 186 ret = PIPE_ERROR_OUT_OF_MEMORY; 187 goto fail; 188 } 189 190 emit.ptr = emit.buf; 191 emit.unit = unit; 192 emit.key = key; 193 194 tgsi_scan_shader( shader->tokens, &emit.info); 195 196 emit.imm_start = emit.info.file_max[TGSI_FILE_CONSTANT] + 1; 197 198 if (unit == PIPE_SHADER_FRAGMENT) 199 emit.imm_start += key.fkey.num_unnormalized_coords; 200 201 if (unit == PIPE_SHADER_VERTEX) { 202 emit.imm_start += key.vkey.need_prescale ? 2 : 0; 203 emit.imm_start += key.vkey.num_zero_stride_vertex_elements; 204 } 205 206 emit.nr_hw_float_const = (emit.imm_start + emit.info.file_max[TGSI_FILE_IMMEDIATE] + 1); 207 208 emit.nr_hw_temp = emit.info.file_max[TGSI_FILE_TEMPORARY] + 1; 209 emit.in_main_func = TRUE; 210 211 if (!svga_shader_emit_header( &emit )) 212 goto fail; 213 214 if (!svga_shader_emit_instructions( &emit, shader->tokens )) 215 goto fail; 216 217 result = CALLOC_STRUCT(svga_shader_result); 218 if (result == NULL) 219 goto fail; 220 221 result->shader = shader; 222 result->tokens = (const unsigned *)emit.buf; 223 result->nr_tokens = (emit.ptr - emit.buf) / sizeof(unsigned); 224 memcpy(&result->key, &key, sizeof key); 225 result->id = UTIL_BITMASK_INVALID_INDEX; 226 227 if (SVGA_DEBUG & DEBUG_TGSI) 228 { 229 debug_printf( "#####################################\n" ); 230 debug_printf( "Shader %u below\n", shader->id ); 231 tgsi_dump( shader->tokens, 0 ); 232 if (SVGA_DEBUG & DEBUG_TGSI) { 233 debug_printf( "Shader %u compiled below\n", shader->id ); 234 svga_shader_dump( result->tokens, 235 result->nr_tokens , 236 FALSE ); 237 } 238 debug_printf( "#####################################\n" ); 239 } 240 241 return result; 242 243fail: 244 FREE(result); 245 FREE(emit.buf); 246 return NULL; 247} 248 249 250 251 252struct svga_shader_result * 253svga_translate_fragment_program( const struct svga_fragment_shader *fs, 254 const struct svga_fs_compile_key *fkey ) 255{ 256 union svga_compile_key key; 257 memcpy(&key.fkey, fkey, sizeof *fkey); 258 259 return svga_tgsi_translate( &fs->base, 260 key, 261 PIPE_SHADER_FRAGMENT ); 262} 263 264struct svga_shader_result * 265svga_translate_vertex_program( const struct svga_vertex_shader *vs, 266 const struct svga_vs_compile_key *vkey ) 267{ 268 union svga_compile_key key; 269 memcpy(&key.vkey, vkey, sizeof *vkey); 270 271 return svga_tgsi_translate( &vs->base, 272 key, 273 PIPE_SHADER_VERTEX ); 274} 275 276 277void svga_destroy_shader_result( struct svga_shader_result *result ) 278{ 279 FREE((unsigned *)result->tokens); 280 FREE(result); 281} 282 283