0,0 → 1,761 |
/************************************************************************** |
* |
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. |
* 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, sub license, 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 (including the |
* next paragraph) 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 NON-INFRINGEMENT. |
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. |
* |
**************************************************************************/ |
/* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
* Brian Paul |
*/ |
|
|
#include "main/imports.h" |
#include "main/mtypes.h" |
#include "program/prog_print.h" |
#include "program/programopt.h" |
|
#include "pipe/p_context.h" |
#include "pipe/p_defines.h" |
#include "pipe/p_shader_tokens.h" |
#include "draw/draw_context.h" |
#include "tgsi/tgsi_dump.h" |
#include "tgsi/tgsi_ureg.h" |
|
#include "st_debug.h" |
#include "st_context.h" |
#include "st_program.h" |
#include "st_mesa_to_tgsi.h" |
#include "cso_cache/cso_context.h" |
|
|
|
/** |
* Clean out any old compilations: |
*/ |
void |
st_vp_release_varients( struct st_context *st, |
struct st_vertex_program *stvp ) |
{ |
struct st_vp_varient *vpv; |
|
for (vpv = stvp->varients; vpv; ) { |
struct st_vp_varient *next = vpv->next; |
|
if (vpv->driver_shader) |
cso_delete_vertex_shader(st->cso_context, vpv->driver_shader); |
|
#if FEATURE_feedback || FEATURE_rastpos |
if (vpv->draw_shader) |
draw_delete_vertex_shader( st->draw, vpv->draw_shader ); |
#endif |
|
if (vpv->tgsi.tokens) |
st_free_tokens(vpv->tgsi.tokens); |
|
FREE( vpv ); |
|
vpv = next; |
} |
|
stvp->varients = NULL; |
} |
|
|
|
|
/** |
* Translate a Mesa vertex shader into a TGSI shader. |
* \param outputMapping to map vertex program output registers (VERT_RESULT_x) |
* to TGSI output slots |
* \param tokensOut destination for TGSI tokens |
* \return pointer to cached pipe_shader object. |
*/ |
void |
st_prepare_vertex_program(struct st_context *st, |
struct st_vertex_program *stvp) |
{ |
GLuint attr; |
|
stvp->num_inputs = 0; |
stvp->num_outputs = 0; |
|
if (stvp->Base.IsPositionInvariant) |
_mesa_insert_mvp_code(st->ctx, &stvp->Base); |
|
assert(stvp->Base.Base.NumInstructions > 1); |
|
/* |
* Determine number of inputs, the mappings between VERT_ATTRIB_x |
* and TGSI generic input indexes, plus input attrib semantic info. |
*/ |
for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { |
if (stvp->Base.Base.InputsRead & (1 << attr)) { |
stvp->input_to_index[attr] = stvp->num_inputs; |
stvp->index_to_input[stvp->num_inputs] = attr; |
stvp->num_inputs++; |
} |
} |
/* bit of a hack, presetup potentially unused edgeflag input */ |
stvp->input_to_index[VERT_ATTRIB_EDGEFLAG] = stvp->num_inputs; |
stvp->index_to_input[stvp->num_inputs] = VERT_ATTRIB_EDGEFLAG; |
|
/* Compute mapping of vertex program outputs to slots. |
*/ |
for (attr = 0; attr < VERT_RESULT_MAX; attr++) { |
if ((stvp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) == 0) { |
stvp->result_to_output[attr] = ~0; |
} |
else { |
unsigned slot = stvp->num_outputs++; |
|
stvp->result_to_output[attr] = slot; |
|
switch (attr) { |
case VERT_RESULT_HPOS: |
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; |
stvp->output_semantic_index[slot] = 0; |
break; |
case VERT_RESULT_COL0: |
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; |
stvp->output_semantic_index[slot] = 0; |
break; |
case VERT_RESULT_COL1: |
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; |
stvp->output_semantic_index[slot] = 1; |
break; |
case VERT_RESULT_BFC0: |
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; |
stvp->output_semantic_index[slot] = 0; |
break; |
case VERT_RESULT_BFC1: |
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; |
stvp->output_semantic_index[slot] = 1; |
break; |
case VERT_RESULT_FOGC: |
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_FOG; |
stvp->output_semantic_index[slot] = 0; |
break; |
case VERT_RESULT_PSIZ: |
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; |
stvp->output_semantic_index[slot] = 0; |
break; |
case VERT_RESULT_EDGE: |
assert(0); |
break; |
|
case VERT_RESULT_TEX0: |
case VERT_RESULT_TEX1: |
case VERT_RESULT_TEX2: |
case VERT_RESULT_TEX3: |
case VERT_RESULT_TEX4: |
case VERT_RESULT_TEX5: |
case VERT_RESULT_TEX6: |
case VERT_RESULT_TEX7: |
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; |
stvp->output_semantic_index[slot] = attr - VERT_RESULT_TEX0; |
break; |
|
case VERT_RESULT_VAR0: |
default: |
assert(attr < VERT_RESULT_MAX); |
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; |
stvp->output_semantic_index[slot] = (FRAG_ATTRIB_VAR0 - |
FRAG_ATTRIB_TEX0 + |
attr - |
VERT_RESULT_VAR0); |
break; |
} |
} |
} |
/* similar hack to above, presetup potentially unused edgeflag output */ |
stvp->result_to_output[VERT_RESULT_EDGE] = stvp->num_outputs; |
stvp->output_semantic_name[stvp->num_outputs] = TGSI_SEMANTIC_EDGEFLAG; |
stvp->output_semantic_index[stvp->num_outputs] = 0; |
} |
|
|
struct st_vp_varient * |
st_translate_vertex_program(struct st_context *st, |
struct st_vertex_program *stvp, |
const struct st_vp_varient_key *key) |
{ |
struct st_vp_varient *vpv = CALLOC_STRUCT(st_vp_varient); |
struct pipe_context *pipe = st->pipe; |
struct ureg_program *ureg; |
enum pipe_error error; |
unsigned num_outputs; |
|
_mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT); |
_mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING); |
|
ureg = ureg_create( TGSI_PROCESSOR_VERTEX ); |
if (ureg == NULL) { |
FREE(vpv); |
return NULL; |
} |
|
vpv->key = *key; |
|
vpv->num_inputs = stvp->num_inputs; |
num_outputs = stvp->num_outputs; |
if (key->passthrough_edgeflags) { |
vpv->num_inputs++; |
num_outputs++; |
} |
|
if (ST_DEBUG & DEBUG_MESA) { |
_mesa_print_program(&stvp->Base.Base); |
_mesa_print_program_parameters(st->ctx, &stvp->Base.Base); |
debug_printf("\n"); |
} |
|
error = |
st_translate_mesa_program(st->ctx, |
TGSI_PROCESSOR_VERTEX, |
ureg, |
&stvp->Base.Base, |
/* inputs */ |
vpv->num_inputs, |
stvp->input_to_index, |
NULL, /* input semantic name */ |
NULL, /* input semantic index */ |
NULL, |
/* outputs */ |
num_outputs, |
stvp->result_to_output, |
stvp->output_semantic_name, |
stvp->output_semantic_index, |
key->passthrough_edgeflags ); |
|
if (error) |
goto fail; |
|
vpv->tgsi.tokens = ureg_get_tokens( ureg, NULL ); |
if (!vpv->tgsi.tokens) |
goto fail; |
|
ureg_destroy( ureg ); |
|
vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi); |
|
if (ST_DEBUG & DEBUG_TGSI) { |
tgsi_dump( vpv->tgsi.tokens, 0 ); |
debug_printf("\n"); |
} |
|
return vpv; |
|
fail: |
debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__); |
_mesa_print_program(&stvp->Base.Base); |
debug_assert(0); |
|
ureg_destroy( ureg ); |
return NULL; |
} |
|
|
|
/** |
* Translate a Mesa fragment shader into a TGSI shader. |
* \return pointer to cached pipe_shader object. |
*/ |
void |
st_translate_fragment_program(struct st_context *st, |
struct st_fragment_program *stfp ) |
{ |
struct pipe_context *pipe = st->pipe; |
GLuint outputMapping[FRAG_RESULT_MAX]; |
GLuint inputMapping[FRAG_ATTRIB_MAX]; |
GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */ |
GLuint attr; |
enum pipe_error error; |
const GLbitfield inputsRead = stfp->Base.Base.InputsRead; |
struct ureg_program *ureg; |
|
ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; |
ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS]; |
uint fs_num_inputs = 0; |
|
ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; |
ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; |
uint fs_num_outputs = 0; |
|
_mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT); |
|
/* |
* Convert Mesa program inputs to TGSI input register semantics. |
*/ |
for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) { |
if (inputsRead & (1 << attr)) { |
const GLuint slot = fs_num_inputs++; |
|
inputMapping[attr] = slot; |
|
switch (attr) { |
case FRAG_ATTRIB_WPOS: |
input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; |
input_semantic_index[slot] = 0; |
interpMode[slot] = TGSI_INTERPOLATE_LINEAR; |
break; |
case FRAG_ATTRIB_COL0: |
input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; |
input_semantic_index[slot] = 0; |
interpMode[slot] = TGSI_INTERPOLATE_LINEAR; |
break; |
case FRAG_ATTRIB_COL1: |
input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; |
input_semantic_index[slot] = 1; |
interpMode[slot] = TGSI_INTERPOLATE_LINEAR; |
break; |
case FRAG_ATTRIB_FOGC: |
input_semantic_name[slot] = TGSI_SEMANTIC_FOG; |
input_semantic_index[slot] = 0; |
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; |
break; |
case FRAG_ATTRIB_FACE: |
input_semantic_name[slot] = TGSI_SEMANTIC_FACE; |
input_semantic_index[slot] = 0; |
interpMode[slot] = TGSI_INTERPOLATE_CONSTANT; |
break; |
/* In most cases, there is nothing special about these |
* inputs, so adopt a convention to use the generic |
* semantic name and the mesa FRAG_ATTRIB_ number as the |
* index. |
* |
* All that is required is that the vertex shader labels |
* its own outputs similarly, and that the vertex shader |
* generates at least every output required by the |
* fragment shader plus fixed-function hardware (such as |
* BFC). |
* |
* There is no requirement that semantic indexes start at |
* zero or be restricted to a particular range -- nobody |
* should be building tables based on semantic index. |
*/ |
case FRAG_ATTRIB_PNTC: |
case FRAG_ATTRIB_TEX0: |
case FRAG_ATTRIB_TEX1: |
case FRAG_ATTRIB_TEX2: |
case FRAG_ATTRIB_TEX3: |
case FRAG_ATTRIB_TEX4: |
case FRAG_ATTRIB_TEX5: |
case FRAG_ATTRIB_TEX6: |
case FRAG_ATTRIB_TEX7: |
case FRAG_ATTRIB_VAR0: |
default: |
/* Actually, let's try and zero-base this just for |
* readability of the generated TGSI. |
*/ |
assert(attr >= FRAG_ATTRIB_TEX0); |
input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0); |
input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; |
if (attr == FRAG_ATTRIB_PNTC) |
interpMode[slot] = TGSI_INTERPOLATE_LINEAR; |
else |
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE; |
break; |
} |
} |
else { |
inputMapping[attr] = -1; |
} |
} |
|
/* |
* Semantics and mapping for outputs |
*/ |
{ |
uint numColors = 0; |
GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten; |
|
/* if z is written, emit that first */ |
if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) { |
fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION; |
fs_output_semantic_index[fs_num_outputs] = 0; |
outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs; |
fs_num_outputs++; |
outputsWritten &= ~(1 << FRAG_RESULT_DEPTH); |
} |
|
if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) { |
fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL; |
fs_output_semantic_index[fs_num_outputs] = 0; |
outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs; |
fs_num_outputs++; |
outputsWritten &= ~(1 << FRAG_RESULT_STENCIL); |
} |
|
/* handle remaning outputs (color) */ |
for (attr = 0; attr < FRAG_RESULT_MAX; attr++) { |
if (outputsWritten & BITFIELD64_BIT(attr)) { |
switch (attr) { |
case FRAG_RESULT_DEPTH: |
case FRAG_RESULT_STENCIL: |
/* handled above */ |
assert(0); |
break; |
default: |
assert(attr == FRAG_RESULT_COLOR || |
(FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX)); |
fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR; |
fs_output_semantic_index[fs_num_outputs] = numColors; |
outputMapping[attr] = fs_num_outputs; |
numColors++; |
break; |
} |
|
fs_num_outputs++; |
} |
} |
} |
|
ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT ); |
if (ureg == NULL) |
return; |
|
if (ST_DEBUG & DEBUG_MESA) { |
_mesa_print_program(&stfp->Base.Base); |
_mesa_print_program_parameters(st->ctx, &stfp->Base.Base); |
debug_printf("\n"); |
} |
|
error = |
st_translate_mesa_program(st->ctx, |
TGSI_PROCESSOR_FRAGMENT, |
ureg, |
&stfp->Base.Base, |
/* inputs */ |
fs_num_inputs, |
inputMapping, |
input_semantic_name, |
input_semantic_index, |
interpMode, |
/* outputs */ |
fs_num_outputs, |
outputMapping, |
fs_output_semantic_name, |
fs_output_semantic_index, FALSE ); |
|
stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); |
ureg_destroy( ureg ); |
stfp->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi); |
|
if (ST_DEBUG & DEBUG_TGSI) { |
tgsi_dump( stfp->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ ); |
debug_printf("\n"); |
} |
} |
|
void |
st_translate_geometry_program(struct st_context *st, |
struct st_geometry_program *stgp) |
{ |
GLuint inputMapping[GEOM_ATTRIB_MAX]; |
GLuint outputMapping[GEOM_RESULT_MAX]; |
struct pipe_context *pipe = st->pipe; |
enum pipe_error error; |
GLuint attr; |
const GLbitfield inputsRead = stgp->Base.Base.InputsRead; |
GLuint vslot = 0; |
GLuint num_generic = 0; |
|
uint gs_num_inputs = 0; |
uint gs_builtin_inputs = 0; |
uint gs_array_offset = 0; |
|
ubyte gs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; |
ubyte gs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS]; |
uint gs_num_outputs = 0; |
|
GLint i; |
GLuint maxSlot = 0; |
struct ureg_program *ureg; |
|
_mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT); |
_mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING); |
|
ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY ); |
if (ureg == NULL) { |
return; |
} |
|
/* which vertex output goes to the first geometry input */ |
vslot = 0; |
|
memset(inputMapping, 0, sizeof(inputMapping)); |
memset(outputMapping, 0, sizeof(outputMapping)); |
|
/* |
* Convert Mesa program inputs to TGSI input register semantics. |
*/ |
for (attr = 0; attr < GEOM_ATTRIB_MAX; attr++) { |
if (inputsRead & (1 << attr)) { |
const GLuint slot = gs_num_inputs; |
|
gs_num_inputs++; |
|
inputMapping[attr] = slot; |
|
stgp->input_map[slot + gs_array_offset] = vslot - gs_builtin_inputs; |
stgp->input_to_index[attr] = vslot; |
stgp->index_to_input[vslot] = attr; |
++vslot; |
|
if (attr != GEOM_ATTRIB_PRIMITIVE_ID) { |
gs_array_offset += 2; |
} else |
++gs_builtin_inputs; |
|
#if 1 |
debug_printf("input map at %d = %d\n", |
slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]); |
#endif |
|
switch (attr) { |
case GEOM_ATTRIB_PRIMITIVE_ID: |
stgp->input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID; |
stgp->input_semantic_index[slot] = 0; |
break; |
case GEOM_ATTRIB_POSITION: |
stgp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION; |
stgp->input_semantic_index[slot] = 0; |
break; |
case GEOM_ATTRIB_COLOR0: |
stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; |
stgp->input_semantic_index[slot] = 0; |
break; |
case GEOM_ATTRIB_COLOR1: |
stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR; |
stgp->input_semantic_index[slot] = 1; |
break; |
case GEOM_ATTRIB_FOG_FRAG_COORD: |
stgp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG; |
stgp->input_semantic_index[slot] = 0; |
break; |
case GEOM_ATTRIB_TEX_COORD: |
stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; |
stgp->input_semantic_index[slot] = num_generic++; |
break; |
case GEOM_ATTRIB_VAR0: |
/* fall-through */ |
default: |
stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; |
stgp->input_semantic_index[slot] = num_generic++; |
} |
} |
} |
|
/* initialize output semantics to defaults */ |
for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) { |
gs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC; |
gs_output_semantic_index[i] = 0; |
} |
|
num_generic = 0; |
/* |
* Determine number of outputs, the (default) output register |
* mapping and the semantic information for each output. |
*/ |
for (attr = 0; attr < GEOM_RESULT_MAX; attr++) { |
if (stgp->Base.Base.OutputsWritten & (1 << attr)) { |
GLuint slot; |
|
slot = gs_num_outputs; |
gs_num_outputs++; |
outputMapping[attr] = slot; |
|
switch (attr) { |
case GEOM_RESULT_POS: |
assert(slot == 0); |
gs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION; |
gs_output_semantic_index[slot] = 0; |
break; |
case GEOM_RESULT_COL0: |
gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; |
gs_output_semantic_index[slot] = 0; |
break; |
case GEOM_RESULT_COL1: |
gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR; |
gs_output_semantic_index[slot] = 1; |
break; |
case GEOM_RESULT_SCOL0: |
gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; |
gs_output_semantic_index[slot] = 0; |
break; |
case GEOM_RESULT_SCOL1: |
gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR; |
gs_output_semantic_index[slot] = 1; |
break; |
case GEOM_RESULT_FOGC: |
gs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG; |
gs_output_semantic_index[slot] = 0; |
break; |
case GEOM_RESULT_PSIZ: |
gs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE; |
gs_output_semantic_index[slot] = 0; |
break; |
case GEOM_RESULT_TEX0: |
case GEOM_RESULT_TEX1: |
case GEOM_RESULT_TEX2: |
case GEOM_RESULT_TEX3: |
case GEOM_RESULT_TEX4: |
case GEOM_RESULT_TEX5: |
case GEOM_RESULT_TEX6: |
case GEOM_RESULT_TEX7: |
/* fall-through */ |
case GEOM_RESULT_VAR0: |
/* fall-through */ |
default: |
assert(slot < Elements(gs_output_semantic_name)); |
/* use default semantic info */ |
gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC; |
gs_output_semantic_index[slot] = num_generic++; |
} |
} |
} |
|
assert(gs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION); |
|
/* find max output slot referenced to compute gs_num_outputs */ |
for (attr = 0; attr < GEOM_RESULT_MAX; attr++) { |
if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot) |
maxSlot = outputMapping[attr]; |
} |
gs_num_outputs = maxSlot + 1; |
|
#if 0 /* debug */ |
{ |
GLuint i; |
printf("outputMapping? %d\n", outputMapping ? 1 : 0); |
if (outputMapping) { |
printf("attr -> slot\n"); |
for (i = 0; i < 16; i++) { |
printf(" %2d %3d\n", i, outputMapping[i]); |
} |
} |
printf("slot sem_name sem_index\n"); |
for (i = 0; i < gs_num_outputs; i++) { |
printf(" %2d %d %d\n", |
i, |
gs_output_semantic_name[i], |
gs_output_semantic_index[i]); |
} |
} |
#endif |
|
/* free old shader state, if any */ |
if (stgp->tgsi.tokens) { |
st_free_tokens(stgp->tgsi.tokens); |
stgp->tgsi.tokens = NULL; |
} |
if (stgp->driver_shader) { |
cso_delete_geometry_shader(st->cso_context, stgp->driver_shader); |
stgp->driver_shader = NULL; |
} |
|
ureg_property_gs_input_prim(ureg, stgp->Base.InputType); |
ureg_property_gs_output_prim(ureg, stgp->Base.OutputType); |
ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut); |
|
error = st_translate_mesa_program(st->ctx, |
TGSI_PROCESSOR_GEOMETRY, |
ureg, |
&stgp->Base.Base, |
/* inputs */ |
gs_num_inputs, |
inputMapping, |
stgp->input_semantic_name, |
stgp->input_semantic_index, |
NULL, |
/* outputs */ |
gs_num_outputs, |
outputMapping, |
gs_output_semantic_name, |
gs_output_semantic_index, |
FALSE); |
|
|
stgp->num_inputs = gs_num_inputs; |
stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL ); |
ureg_destroy( ureg ); |
stgp->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi); |
|
if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) { |
_mesa_print_program(&stgp->Base.Base); |
debug_printf("\n"); |
} |
|
if (ST_DEBUG & DEBUG_TGSI) { |
tgsi_dump(stgp->tgsi.tokens, 0); |
debug_printf("\n"); |
} |
} |
|
/** |
* Debug- print current shader text |
*/ |
void |
st_print_shaders(struct gl_context *ctx) |
{ |
struct gl_shader_program *shProg[3] = { |
ctx->Shader.CurrentVertexProgram, |
ctx->Shader.CurrentGeometryProgram, |
ctx->Shader.CurrentFragmentProgram, |
}; |
unsigned j; |
|
for (j = 0; j < 3; j++) { |
unsigned i; |
|
if (shProg[j] == NULL) |
continue; |
|
for (i = 0; i < shProg[j]->NumShaders; i++) { |
struct gl_shader *sh; |
|
switch (shProg[j]->Shaders[i]->Type) { |
case GL_VERTEX_SHADER: |
sh = (i != 0) ? NULL : shProg[j]->Shaders[i]; |
break; |
case GL_GEOMETRY_SHADER_ARB: |
sh = (i != 1) ? NULL : shProg[j]->Shaders[i]; |
break; |
case GL_FRAGMENT_SHADER: |
sh = (i != 2) ? NULL : shProg[j]->Shaders[i]; |
break; |
default: |
assert(0); |
sh = NULL; |
break; |
} |
|
if (sh != NULL) { |
printf("GLSL shader %u of %u:\n", i, shProg[j]->NumShaders); |
printf("%s\n", sh->Source); |
} |
} |
} |
} |