| /********************************************************** |
| * Copyright 2008-2009 VMware, Inc. All rights reserved. |
| * |
| * Permission is hereby granted, free of charge, to any person |
| * obtaining a copy of this software and associated documentation |
| * files (the "Software"), to deal in the Software without |
| * restriction, including without limitation the rights to use, copy, |
| * modify, merge, publish, distribute, sublicense, and/or sell copies |
| * of the Software, and to permit persons to whom the Software is |
| * furnished to do so, subject to the following conditions: |
| * |
| * The above copyright notice and this permission notice shall be |
| * included in all copies or substantial portions of the Software. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| * SOFTWARE. |
| * |
| **********************************************************/ |
| |
| |
| #include "pipe/p_shader_tokens.h" |
| #include "tgsi/tgsi_parse.h" |
| #include "util/u_memory.h" |
| |
| #include "svga_tgsi_emit.h" |
| #include "svga_context.h" |
| |
| |
| |
| |
| static boolean ps20_input( struct svga_shader_emitter *emit, |
| struct tgsi_declaration_semantic semantic, |
| unsigned idx ) |
| { |
| struct src_register reg; |
| SVGA3DOpDclArgs dcl; |
| SVGA3dShaderInstToken opcode; |
| |
| opcode = inst_token( SVGA3DOP_DCL ); |
| dcl.values[0] = 0; |
| dcl.values[1] = 0; |
| |
| switch (semantic.Name) { |
| case TGSI_SEMANTIC_POSITION: |
| /* Special case: |
| */ |
| reg = src_register( SVGA3DREG_MISCTYPE, |
| SVGA3DMISCREG_POSITION ); |
| break; |
| case TGSI_SEMANTIC_COLOR: |
| reg = src_register( SVGA3DREG_INPUT, |
| semantic.Index ); |
| break; |
| case TGSI_SEMANTIC_FOG: |
| assert(semantic.Index == 0); |
| reg = src_register( SVGA3DREG_TEXTURE, 0 ); |
| break; |
| case TGSI_SEMANTIC_GENERIC: |
| reg = src_register( SVGA3DREG_TEXTURE, |
| semantic.Index + 1 ); |
| break; |
| default: |
| assert(0); |
| return TRUE; |
| } |
| |
| emit->input_map[idx] = reg; |
| |
| dcl.dst = dst( reg ); |
| |
| dcl.usage = 0; |
| dcl.index = 0; |
| |
| dcl.values[0] |= 1<<31; |
| |
| return (emit_instruction(emit, opcode) && |
| svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); |
| } |
| |
| |
| static boolean ps20_output( struct svga_shader_emitter *emit, |
| struct tgsi_declaration_semantic semantic, |
| unsigned idx ) |
| { |
| SVGA3dShaderDestToken reg; |
| |
| switch (semantic.Name) { |
| case TGSI_SEMANTIC_COLOR: |
| if (semantic.Index < PIPE_MAX_COLOR_BUFS) { |
| unsigned cbuf = semantic.Index; |
| |
| emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, |
| emit->nr_hw_temp++ ); |
| emit->temp_col[cbuf] = emit->output_map[idx]; |
| emit->true_col[cbuf] = dst_register( SVGA3DREG_COLOROUT, |
| semantic.Index ); |
| } |
| else { |
| assert(0); |
| reg = dst_register( SVGA3DREG_COLOROUT, 0 ); |
| } |
| break; |
| case TGSI_SEMANTIC_POSITION: |
| emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, |
| emit->nr_hw_temp++ ); |
| emit->temp_pos = emit->output_map[idx]; |
| emit->true_pos = dst_register( SVGA3DREG_DEPTHOUT, |
| semantic.Index ); |
| break; |
| default: |
| assert(0); |
| reg = dst_register( SVGA3DREG_COLOROUT, 0 ); |
| break; |
| } |
| |
| return TRUE; |
| } |
| |
| |
| static boolean vs20_input( struct svga_shader_emitter *emit, |
| struct tgsi_declaration_semantic semantic, |
| unsigned idx ) |
| { |
| SVGA3DOpDclArgs dcl; |
| SVGA3dShaderInstToken opcode; |
| |
| opcode = inst_token( SVGA3DOP_DCL ); |
| dcl.values[0] = 0; |
| dcl.values[1] = 0; |
| |
| emit->input_map[idx] = src_register( SVGA3DREG_INPUT, idx ); |
| dcl.dst = dst_register( SVGA3DREG_INPUT, idx ); |
| |
| assert(dcl.dst.reserved0); |
| |
| /* Mesa doesn't provide use with VS input semantics (they're |
| * actually pretty meaningless), so we just generate some plausible |
| * ones here. This has to match what we declare in the vdecl code |
| * in svga_pipe_vertex.c. |
| */ |
| if (idx == 0) { |
| dcl.usage = SVGA3D_DECLUSAGE_POSITION; |
| dcl.index = 0; |
| } |
| else { |
| dcl.usage = SVGA3D_DECLUSAGE_TEXCOORD; |
| dcl.index = idx - 1; |
| } |
| |
| dcl.values[0] |= 1<<31; |
| |
| return (emit_instruction(emit, opcode) && |
| svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); |
| } |
| |
| |
| static boolean vs20_output( struct svga_shader_emitter *emit, |
| struct tgsi_declaration_semantic semantic, |
| unsigned idx ) |
| { |
| /* Don't emit dcl instruction for vs20 inputs |
| */ |
| |
| /* Just build the register map table: |
| */ |
| switch (semantic.Name) { |
| case TGSI_SEMANTIC_POSITION: |
| assert(semantic.Index == 0); |
| emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, |
| emit->nr_hw_temp++ ); |
| emit->temp_pos = emit->output_map[idx]; |
| emit->true_pos = dst_register( SVGA3DREG_RASTOUT, |
| SVGA3DRASTOUT_POSITION); |
| break; |
| case TGSI_SEMANTIC_PSIZE: |
| assert(semantic.Index == 0); |
| emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, |
| emit->nr_hw_temp++ ); |
| emit->temp_psiz = emit->output_map[idx]; |
| emit->true_psiz = dst_register( SVGA3DREG_RASTOUT, |
| SVGA3DRASTOUT_PSIZE ); |
| break; |
| case TGSI_SEMANTIC_FOG: |
| assert(semantic.Index == 0); |
| emit->output_map[idx] = dst_register( SVGA3DREG_TEXCRDOUT, 0 ); |
| break; |
| case TGSI_SEMANTIC_COLOR: |
| /* oD0 */ |
| emit->output_map[idx] = dst_register( SVGA3DREG_ATTROUT, |
| semantic.Index ); |
| break; |
| case TGSI_SEMANTIC_GENERIC: |
| emit->output_map[idx] = dst_register( SVGA3DREG_TEXCRDOUT, |
| semantic.Index + 1 ); |
| break; |
| default: |
| assert(0); |
| emit->output_map[idx] = dst_register( SVGA3DREG_TEMP, 0 ); |
| return FALSE; |
| } |
| |
| return TRUE; |
| } |
| |
| static boolean ps20_sampler( struct svga_shader_emitter *emit, |
| struct tgsi_declaration_semantic semantic, |
| unsigned idx ) |
| { |
| SVGA3DOpDclArgs dcl; |
| SVGA3dShaderInstToken opcode; |
| |
| opcode = inst_token( SVGA3DOP_DCL ); |
| dcl.values[0] = 0; |
| dcl.values[1] = 0; |
| |
| dcl.dst = dst_register( SVGA3DREG_SAMPLER, idx ); |
| dcl.type = svga_tgsi_sampler_type( emit, idx ); |
| |
| return (emit_instruction(emit, opcode) && |
| svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values))); |
| } |
| |
| |
| boolean svga_translate_decl_sm20( struct svga_shader_emitter *emit, |
| const struct tgsi_full_declaration *decl ) |
| { |
| unsigned first = decl->Range.First; |
| unsigned last = decl->Range.Last; |
| unsigned semantic = 0; |
| unsigned semantic_idx = 0; |
| unsigned idx; |
| |
| if (decl->Declaration.Semantic) { |
| semantic = decl->Semantic.Name; |
| semantic_idx = decl->Semantic.Index; |
| } |
| |
| for( idx = first; idx <= last; idx++ ) { |
| boolean ok; |
| |
| switch (decl->Declaration.File) { |
| case TGSI_FILE_SAMPLER: |
| assert (emit->unit == PIPE_SHADER_FRAGMENT); |
| ok = ps20_sampler( emit, decl->Semantic, idx ); |
| break; |
| |
| case TGSI_FILE_INPUT: |
| if (emit->unit == PIPE_SHADER_VERTEX) |
| ok = vs20_input( emit, decl->Semantic, idx ); |
| else |
| ok = ps20_input( emit, decl->Semantic, idx ); |
| break; |
| |
| case TGSI_FILE_OUTPUT: |
| if (emit->unit == PIPE_SHADER_VERTEX) |
| ok = vs20_output( emit, decl->Semantic, idx ); |
| else |
| ok = ps20_output( emit, decl->Semantic, idx ); |
| break; |
| |
| default: |
| /* don't need to declare other vars */ |
| ok = TRUE; |
| } |
| |
| if (!ok) |
| return FALSE; |
| } |
| |
| return TRUE; |
| } |
| |
| |
| |