summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/svga/svga_tgsi_decl_sm30.c')
-rw-r--r--src/gallium/drivers/svga/svga_tgsi_decl_sm30.c385
1 files changed, 385 insertions, 0 deletions
diff --git a/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c b/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c
new file mode 100644
index 00000000000..08e7dfb117c
--- /dev/null
+++ b/src/gallium/drivers/svga/svga_tgsi_decl_sm30.c
@@ -0,0 +1,385 @@
+/**********************************************************
+ * 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 translate_vs_ps_semantic( struct tgsi_declaration_semantic semantic,
+ unsigned *usage,
+ unsigned *idx )
+{
+ switch (semantic.SemanticName) {
+ case TGSI_SEMANTIC_POSITION:
+ *idx = semantic.SemanticIndex;
+ *usage = SVGA3D_DECLUSAGE_POSITION;
+ break;
+ case TGSI_SEMANTIC_COLOR:
+
+ *idx = semantic.SemanticIndex;
+ *usage = SVGA3D_DECLUSAGE_COLOR;
+ break;
+ case TGSI_SEMANTIC_BCOLOR:
+ *idx = semantic.SemanticIndex + 2; /* sharing with COLOR */
+ *usage = SVGA3D_DECLUSAGE_COLOR;
+ break;
+ case TGSI_SEMANTIC_FOG:
+ *idx = 0;
+ assert(semantic.SemanticIndex == 0);
+ *usage = SVGA3D_DECLUSAGE_TEXCOORD;
+ break;
+ case TGSI_SEMANTIC_PSIZE:
+ *idx = semantic.SemanticIndex;
+ *usage = SVGA3D_DECLUSAGE_PSIZE;
+ break;
+ case TGSI_SEMANTIC_GENERIC:
+ *idx = semantic.SemanticIndex + 1; /* texcoord[0] is reserved for fog */
+ *usage = SVGA3D_DECLUSAGE_TEXCOORD;
+ break;
+ case TGSI_SEMANTIC_NORMAL:
+ *idx = semantic.SemanticIndex;
+ *usage = SVGA3D_DECLUSAGE_NORMAL;
+ break;
+ default:
+ assert(0);
+ *usage = SVGA3D_DECLUSAGE_TEXCOORD;
+ *idx = 0;
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+static boolean emit_decl( struct svga_shader_emitter *emit,
+ SVGA3dShaderDestToken reg,
+ unsigned usage,
+ unsigned index )
+{
+ SVGA3DOpDclArgs dcl;
+ SVGA3dShaderInstToken opcode;
+
+ opcode = inst_token( SVGA3DOP_DCL );
+ dcl.values[0] = 0;
+ dcl.values[1] = 0;
+
+ dcl.dst = reg;
+ dcl.usage = usage;
+ dcl.index = index;
+ dcl.values[0] |= 1<<31;
+
+ return (emit_instruction(emit, opcode) &&
+ svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
+}
+
+static boolean emit_vface_decl( struct svga_shader_emitter *emit )
+{
+ if (!emit->emitted_vface) {
+ SVGA3dShaderDestToken reg =
+ dst_register( SVGA3DREG_MISCTYPE,
+ SVGA3DMISCREG_FACE );
+
+ if (!emit_decl( emit, reg, 0, 0 ))
+ return FALSE;
+
+ emit->emitted_vface = TRUE;
+ }
+ return TRUE;
+}
+
+static boolean ps30_input( struct svga_shader_emitter *emit,
+ struct tgsi_declaration_semantic semantic,
+ unsigned idx )
+{
+ unsigned usage, index;
+ SVGA3dShaderDestToken reg;
+
+ if (semantic.SemanticName == TGSI_SEMANTIC_POSITION) {
+ emit->input_map[idx] = src_register( SVGA3DREG_MISCTYPE,
+ SVGA3DMISCREG_POSITION );
+
+ emit->input_map[idx].base.swizzle = TRANSLATE_SWIZZLE( TGSI_SWIZZLE_X,
+ TGSI_SWIZZLE_Y,
+ TGSI_SWIZZLE_Y,
+ TGSI_SWIZZLE_Y );
+
+ reg = writemask( dst(emit->input_map[idx]),
+ TGSI_WRITEMASK_XY );
+
+ return emit_decl( emit, reg, 0, 0 );
+ }
+ else if (emit->key.fkey.light_twoside &&
+ (semantic.SemanticName == TGSI_SEMANTIC_COLOR)) {
+
+ if (!translate_vs_ps_semantic( semantic, &usage, &index ))
+ return FALSE;
+
+ emit->internal_color_idx[emit->internal_color_count] = idx;
+ emit->input_map[idx] = src_register( SVGA3DREG_INPUT, emit->ps30_input_count );
+ emit->ps30_input_count++;
+ emit->internal_color_count++;
+
+ reg = dst( emit->input_map[idx] );
+
+ if (!emit_decl( emit, reg, usage, index ))
+ return FALSE;
+
+ semantic.SemanticName = TGSI_SEMANTIC_BCOLOR;
+ if (!translate_vs_ps_semantic( semantic, &usage, &index ))
+ return FALSE;
+
+ reg = dst_register( SVGA3DREG_INPUT, emit->ps30_input_count++ );
+
+ if (!emit_decl( emit, reg, usage, index ))
+ return FALSE;
+
+ if (!emit_vface_decl( emit ))
+ return FALSE;
+
+ return TRUE;
+ }
+ else if (semantic.SemanticName == TGSI_SEMANTIC_FACE) {
+ if (!emit_vface_decl( emit ))
+ return FALSE;
+ emit->emit_frontface = TRUE;
+ emit->internal_frontface_idx = idx;
+ return TRUE;
+ }
+ else {
+
+ if (!translate_vs_ps_semantic( semantic, &usage, &index ))
+ return FALSE;
+
+ emit->input_map[idx] = src_register( SVGA3DREG_INPUT, emit->ps30_input_count++ );
+ reg = dst( emit->input_map[idx] );
+
+ return emit_decl( emit, reg, usage, index );
+ }
+
+}
+
+
+/* PS output registers are the same as 2.0
+ */
+static boolean ps30_output( struct svga_shader_emitter *emit,
+ struct tgsi_declaration_semantic semantic,
+ unsigned idx )
+{
+ SVGA3dShaderDestToken reg;
+
+ switch (semantic.SemanticName) {
+ case TGSI_SEMANTIC_COLOR:
+ emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT,
+ semantic.SemanticIndex );
+ 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.SemanticIndex );
+ break;
+ default:
+ assert(0);
+ reg = dst_register( SVGA3DREG_COLOROUT, 0 );
+ break;
+ }
+
+ return TRUE;
+}
+
+
+/* We still make up the input semantics the same as in 2.0
+ */
+static boolean vs30_input( struct svga_shader_emitter *emit,
+ struct tgsi_declaration_semantic semantic,
+ unsigned idx )
+{
+ SVGA3DOpDclArgs dcl;
+ SVGA3dShaderInstToken opcode;
+ unsigned usage, index;
+
+ opcode = inst_token( SVGA3DOP_DCL );
+ dcl.values[0] = 0;
+ dcl.values[1] = 0;
+
+ if (emit->key.vkey.zero_stride_vertex_elements & (1 << idx)) {
+ unsigned i;
+ unsigned offset = 0;
+ unsigned start_idx = emit->info.file_max[TGSI_FILE_CONSTANT] + 1;
+ /* adjust for prescale constants */
+ start_idx += emit->key.vkey.need_prescale ? 2 : 0;
+ /* compute the offset from the start of zero stride constants */
+ for (i = 0; i < PIPE_MAX_ATTRIBS && i < idx; ++i) {
+ if (emit->key.vkey.zero_stride_vertex_elements & (1<<i))
+ ++offset;
+ }
+ emit->input_map[idx] = src_register( SVGA3DREG_CONST,
+ start_idx + offset );
+ } else {
+ emit->input_map[idx] = src_register( SVGA3DREG_INPUT, idx );
+ dcl.dst = dst_register( SVGA3DREG_INPUT, idx );
+
+ assert(dcl.dst.reserved0);
+
+ svga_generate_vdecl_semantics( idx, &usage, &index );
+
+ dcl.usage = usage;
+ dcl.index = index;
+ dcl.values[0] |= 1<<31;
+
+ return (emit_instruction(emit, opcode) &&
+ svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
+ }
+ return TRUE;
+}
+
+/* VS3.0 outputs have proper declarations and semantic info for
+ * matching against PS inputs.
+ */
+static boolean vs30_output( struct svga_shader_emitter *emit,
+ struct tgsi_declaration_semantic semantic,
+ unsigned idx )
+{
+ SVGA3DOpDclArgs dcl;
+ SVGA3dShaderInstToken opcode;
+ unsigned usage, index;
+
+ opcode = inst_token( SVGA3DOP_DCL );
+ dcl.values[0] = 0;
+ dcl.values[1] = 0;
+
+ if (!translate_vs_ps_semantic( semantic, &usage, &index ))
+ return FALSE;
+
+ dcl.dst = dst_register( SVGA3DREG_OUTPUT, idx );
+ dcl.usage = usage;
+ dcl.index = index;
+ dcl.values[0] |= 1<<31;
+
+ if (semantic.SemanticName == TGSI_SEMANTIC_POSITION) {
+ assert(idx == 0);
+ emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
+ emit->nr_hw_temp++ );
+ emit->temp_pos = emit->output_map[idx];
+ emit->true_pos = dcl.dst;
+ }
+ else if (semantic.SemanticName == TGSI_SEMANTIC_PSIZE) {
+ emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
+ emit->nr_hw_temp++ );
+ emit->temp_psiz = emit->output_map[idx];
+
+ /* This has the effect of not declaring psiz (below) and not
+ * emitting the final MOV to true_psiz in the postamble.
+ */
+ if (!emit->key.vkey.allow_psiz)
+ return TRUE;
+
+ emit->true_psiz = dcl.dst;
+ }
+ else {
+ emit->output_map[idx] = dcl.dst;
+ }
+
+
+ return (emit_instruction(emit, opcode) &&
+ svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
+}
+
+static boolean ps30_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 );
+ dcl.values[0] |= 1<<31;
+
+ return (emit_instruction(emit, opcode) &&
+ svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
+}
+
+
+boolean svga_translate_decl_sm30( struct svga_shader_emitter *emit,
+ const struct tgsi_full_declaration *decl )
+{
+ unsigned first = decl->DeclarationRange.First;
+ unsigned last = decl->DeclarationRange.Last;
+ unsigned semantic = 0;
+ unsigned semantic_idx = 0;
+ unsigned idx;
+
+ if (decl->Declaration.Semantic) {
+ semantic = decl->Semantic.SemanticName;
+ semantic_idx = decl->Semantic.SemanticIndex;
+ }
+
+ for( idx = first; idx <= last; idx++ ) {
+ boolean ok;
+
+ switch (decl->Declaration.File) {
+ case TGSI_FILE_SAMPLER:
+ assert (emit->unit == PIPE_SHADER_FRAGMENT);
+ ok = ps30_sampler( emit, decl->Semantic, idx );
+ break;
+
+ case TGSI_FILE_INPUT:
+ if (emit->unit == PIPE_SHADER_VERTEX)
+ ok = vs30_input( emit, decl->Semantic, idx );
+ else
+ ok = ps30_input( emit, decl->Semantic, idx );
+ break;
+
+ case TGSI_FILE_OUTPUT:
+ if (emit->unit == PIPE_SHADER_VERTEX)
+ ok = vs30_output( emit, decl->Semantic, idx );
+ else
+ ok = ps30_output( emit, decl->Semantic, idx );
+ break;
+
+ default:
+ /* don't need to declare other vars */
+ ok = TRUE;
+ }
+
+ if (!ok)
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+