1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**********************************************************
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright 2008-2009 VMware, Inc.  All rights reserved.
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * obtaining a copy of this software and associated documentation
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * files (the "Software"), to deal in the Software without
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * restriction, including without limitation the rights to use, copy,
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * modify, merge, publish, distribute, sublicense, and/or sell copies
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * of the Software, and to permit persons to whom the Software is
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * furnished to do so, subject to the following conditions:
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice shall be
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * included in all copies or substantial portions of the Software.
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * SOFTWARE.
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org **********************************************************/
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "pipe/p_compiler.h"
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "pipe/p_shader_tokens.h"
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "pipe/p_defines.h"
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "tgsi/tgsi_parse.h"
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "tgsi/tgsi_dump.h"
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "tgsi/tgsi_scan.h"
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_math.h"
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_memory.h"
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "util/u_bitmask.h"
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "svgadump/svga_shader_dump.h"
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "svga_context.h"
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "svga_tgsi.h"
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "svga_tgsi_emit.h"
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "svga_debug.h"
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "svga_hw_reg.h"
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "svga3d_shaderdefs.h"
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Sinkhole used only in error conditions.
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic char err_buf[128];
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#if 0
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void svga_destroy_shader_emitter( struct svga_shader_emitter *emit )
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (emit->buf != err_buf)
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      FREE(emit->buf);
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic boolean svga_shader_expand( struct svga_shader_emitter *emit )
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   char *new_buf;
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned newsize = emit->size * 2;
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if(emit->buf != err_buf)
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      new_buf = REALLOC(emit->buf, emit->size, newsize);
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      new_buf = NULL;
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (new_buf == NULL) {
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      emit->ptr = err_buf;
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      emit->buf = err_buf;
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      emit->size = sizeof(err_buf);
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return FALSE;
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit->size = newsize;
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit->ptr = new_buf + (emit->ptr - emit->buf);
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit->buf = new_buf;
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return TRUE;
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic INLINE boolean reserve(  struct svga_shader_emitter *emit,
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                unsigned nr_dwords )
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (emit->ptr - emit->buf + nr_dwords * sizeof(unsigned) >= emit->size) {
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!svga_shader_expand( emit ))
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return FALSE;
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return TRUE;
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgboolean svga_shader_emit_dword( struct svga_shader_emitter *emit,
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                unsigned dword )
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!reserve(emit, 1))
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return FALSE;
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   *(unsigned *)emit->ptr = dword;
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit->ptr += sizeof dword;
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return TRUE;
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgboolean svga_shader_emit_dwords( struct svga_shader_emitter *emit,
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 const unsigned *dwords,
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 unsigned nr )
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!reserve(emit, nr))
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return FALSE;
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memcpy( emit->ptr, dwords, nr * sizeof *dwords );
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit->ptr += nr * sizeof *dwords;
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return TRUE;
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgboolean svga_shader_emit_opcode( struct svga_shader_emitter *emit,
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 unsigned opcode )
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   SVGA3dShaderInstToken *here;
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!reserve(emit, 1))
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return FALSE;
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   here = (SVGA3dShaderInstToken *)emit->ptr;
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   here->value = opcode;
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (emit->insn_offset) {
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      SVGA3dShaderInstToken *prev = (SVGA3dShaderInstToken *)(emit->buf +
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                                              emit->insn_offset);
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      prev->size = (here - prev) - 1;
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit->insn_offset = emit->ptr - emit->buf;
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit->ptr += sizeof(unsigned);
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return TRUE;
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic boolean svga_shader_emit_header( struct svga_shader_emitter *emit )
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   SVGA3dShaderVersion header;
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset( &header, 0, sizeof header );
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (emit->unit) {
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case PIPE_SHADER_FRAGMENT:
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      header.value = SVGA3D_PS_30;
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case PIPE_SHADER_VERTEX:
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      header.value = SVGA3D_VS_30;
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      break;
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return svga_shader_emit_dword( emit, header.value );
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Use the shader info to generate a bitmask indicating which generic
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * inputs are used by the shader.  A set bit indicates that GENERIC[i]
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is used.
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgunsigned
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgsvga_get_generic_inputs_mask(const struct tgsi_shader_info *info)
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned i, mask = 0x0;
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < info->num_inputs; i++) {
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (info->input_semantic_name[i] == TGSI_SEMANTIC_GENERIC) {
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         unsigned j = info->input_semantic_index[i];
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(j < sizeof(mask) * 8);
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         mask |= 1 << j;
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return mask;
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Given a mask of used generic variables (as returned by the above functions)
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * fill in a table which maps those indexes to small integers.
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This table is used by the remap_generic_index() function in
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * svga_tgsi_decl_sm30.c
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Example: if generics_mask = binary(1010) it means that GENERIC[1] and
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * GENERIC[3] are used.  The remap_table will contain:
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *   table[1] = 0;
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *   table[3] = 1;
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The remaining table entries will be filled in with the next unused
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * generic index (in this example, 2).
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgsvga_remap_generics(unsigned generics_mask,
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    int8_t remap_table[MAX_GENERIC_VARYING])
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Note texcoord[0] is reserved so start at 1 */
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned count = 1, i;
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (i = 0; i < MAX_GENERIC_VARYING; i++) {
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      remap_table[i] = -1;
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* for each bit set in generic_mask */
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   while (generics_mask) {
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      unsigned index = ffs(generics_mask) - 1;
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      remap_table[index] = count++;
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      generics_mask &= ~(1 << index);
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Use the generic remap table to map a TGSI generic varying variable
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * index to a small integer.  If the remapping table doesn't have a
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * valid value for the given index (the table entry is -1) it means
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the fragment shader doesn't use that VS output.  Just allocate
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the next free value in that case.  Alternately, we could cull
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * VS instructions that write to register, or replace the register
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * with a dummy temp register.
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * XXX TODO: we should do one of the later as it would save precious
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * texcoord registers.
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgsvga_remap_generic_index(int8_t remap_table[MAX_GENERIC_VARYING],
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         int generic_index)
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(generic_index < MAX_GENERIC_VARYING);
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (generic_index >= MAX_GENERIC_VARYING) {
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* just don't return a random/garbage value */
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      generic_index = MAX_GENERIC_VARYING - 1;
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (remap_table[generic_index] == -1) {
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* This is a VS output that has no matching PS input.  Find a
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * free index.
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      int i, max = 0;
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (i = 0; i < MAX_GENERIC_VARYING; i++) {
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         max = MAX2(max, remap_table[i]);
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      remap_table[generic_index] = max + 1;
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return remap_table[generic_index];
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* Parse TGSI shader and translate to SVGA/DX9 serialized
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * representation.
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * In this function SVGA shader is emitted to an in-memory buffer that
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * can be dynamically grown.  Once we've finished and know how large
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * it is, it will be copied to a hardware buffer for upload.
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct svga_shader_result *
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgsvga_tgsi_translate( const struct svga_shader *shader,
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     struct svga_compile_key key,
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     unsigned unit )
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct svga_shader_result *result = NULL;
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct svga_shader_emitter emit;
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&emit, 0, sizeof(emit));
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit.size = 1024;
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit.buf = MALLOC(emit.size);
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (emit.buf == NULL) {
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      goto fail;
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit.ptr = emit.buf;
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit.unit = unit;
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit.key = key;
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   tgsi_scan_shader( shader->tokens, &emit.info);
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit.imm_start = emit.info.file_max[TGSI_FILE_CONSTANT] + 1;
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (unit == PIPE_SHADER_FRAGMENT)
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      emit.imm_start += key.fkey.num_unnormalized_coords;
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (unit == PIPE_SHADER_VERTEX) {
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      emit.imm_start += key.vkey.need_prescale ? 2 : 0;
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit.nr_hw_float_const = (emit.imm_start + emit.info.file_max[TGSI_FILE_IMMEDIATE] + 1);
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit.nr_hw_temp = emit.info.file_max[TGSI_FILE_TEMPORARY] + 1;
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (emit.nr_hw_temp >= SVGA3D_TEMPREG_MAX) {
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      debug_printf("svga: too many temporary registers (%u)\n", emit.nr_hw_temp);
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      goto fail;
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   emit.in_main_func = TRUE;
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!svga_shader_emit_header( &emit )) {
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      debug_printf("svga: emit header failed\n");
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      goto fail;
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!svga_shader_emit_instructions( &emit, shader->tokens )) {
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      debug_printf("svga: emit instructions failed\n");
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      goto fail;
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   result = CALLOC_STRUCT(svga_shader_result);
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (result == NULL)
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      goto fail;
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   result->shader = shader;
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   result->tokens = (const unsigned *)emit.buf;
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   result->nr_tokens = (emit.ptr - emit.buf) / sizeof(unsigned);
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memcpy(&result->key, &key, sizeof key);
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   result->id = UTIL_BITMASK_INVALID_INDEX;
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (SVGA_DEBUG & DEBUG_TGSI)
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      debug_printf( "#####################################\n" );
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      debug_printf( "Shader %u below\n", shader->id );
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tgsi_dump( shader->tokens, 0 );
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (SVGA_DEBUG & DEBUG_TGSI) {
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         debug_printf( "Shader %u compiled below\n", shader->id );
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         svga_shader_dump( result->tokens,
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           result->nr_tokens ,
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           FALSE );
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      debug_printf( "#####################################\n" );
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return result;
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgfail:
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   FREE(result);
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   FREE(emit.buf);
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return NULL;
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct svga_shader_result *
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgsvga_translate_fragment_program( const struct svga_fragment_shader *fs,
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 const struct svga_fs_compile_key *fkey )
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct svga_compile_key key;
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&key, 0, sizeof(key));
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memcpy(&key.fkey, fkey, sizeof *fkey);
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memcpy(key.generic_remap_table, fs->generic_remap_table,
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          sizeof(fs->generic_remap_table));
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return svga_tgsi_translate( &fs->base,
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               key,
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               PIPE_SHADER_FRAGMENT );
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstruct svga_shader_result *
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgsvga_translate_vertex_program( const struct svga_vertex_shader *vs,
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               const struct svga_vs_compile_key *vkey )
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct svga_compile_key key;
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&key, 0, sizeof(key));
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memcpy(&key.vkey, vkey, sizeof *vkey);
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Note: we could alternately store the remap table in the vkey but
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * that would make it larger.  We just regenerate it here instead.
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   svga_remap_generics(vkey->fs_generic_inputs, key.generic_remap_table);
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return svga_tgsi_translate( &vs->base,
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               key,
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                               PIPE_SHADER_VERTEX );
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid svga_destroy_shader_result( struct svga_shader_result *result )
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   FREE((unsigned *)result->tokens);
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   FREE(result);
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
390