st/mesa: add conversion for tessellation shaders
Based on code from Ilia Mirkin <imirkin@alum.mit.edu>.
This commit is contained in:
@@ -932,61 +932,52 @@ st_get_fp_variant(struct st_context *st,
|
||||
|
||||
|
||||
/**
|
||||
* Translate a geometry program to create a new variant.
|
||||
* Translate a program. This is common code for geometry and tessellation
|
||||
* shaders.
|
||||
*/
|
||||
static struct st_gp_variant *
|
||||
st_translate_geometry_program(struct st_context *st,
|
||||
struct st_geometry_program *stgp,
|
||||
const struct st_gp_variant_key *key)
|
||||
static void
|
||||
st_translate_program_common(struct st_context *st,
|
||||
struct gl_program *prog,
|
||||
struct glsl_to_tgsi_visitor *glsl_to_tgsi,
|
||||
struct ureg_program *ureg,
|
||||
unsigned tgsi_processor,
|
||||
struct pipe_shader_state *out_state)
|
||||
{
|
||||
GLuint inputSlotToAttr[VARYING_SLOT_MAX];
|
||||
GLuint inputMapping[VARYING_SLOT_MAX];
|
||||
GLuint outputSlotToAttr[VARYING_SLOT_MAX];
|
||||
GLuint outputMapping[VARYING_SLOT_MAX];
|
||||
struct pipe_context *pipe = st->pipe;
|
||||
GLuint inputSlotToAttr[VARYING_SLOT_TESS_MAX];
|
||||
GLuint inputMapping[VARYING_SLOT_TESS_MAX];
|
||||
GLuint outputSlotToAttr[VARYING_SLOT_TESS_MAX];
|
||||
GLuint outputMapping[VARYING_SLOT_TESS_MAX];
|
||||
GLuint attr;
|
||||
|
||||
uint gs_num_inputs = 0;
|
||||
|
||||
ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
|
||||
ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
|
||||
uint num_inputs = 0;
|
||||
|
||||
ubyte gs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
|
||||
ubyte gs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
|
||||
uint gs_num_outputs = 0;
|
||||
ubyte output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
|
||||
ubyte output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
|
||||
uint num_outputs = 0;
|
||||
|
||||
GLint i;
|
||||
struct ureg_program *ureg;
|
||||
struct pipe_shader_state state = {0};
|
||||
struct st_gp_variant *gpv;
|
||||
|
||||
gpv = CALLOC_STRUCT(st_gp_variant);
|
||||
if (!gpv)
|
||||
return NULL;
|
||||
|
||||
ureg = ureg_create_with_screen(TGSI_PROCESSOR_GEOMETRY, st->pipe->screen);
|
||||
if (ureg == NULL) {
|
||||
free(gpv);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(inputSlotToAttr, 0, sizeof(inputSlotToAttr));
|
||||
memset(inputMapping, 0, sizeof(inputMapping));
|
||||
memset(outputSlotToAttr, 0, sizeof(outputSlotToAttr));
|
||||
memset(outputMapping, 0, sizeof(outputMapping));
|
||||
memset(out_state, 0, sizeof(*out_state));
|
||||
|
||||
/*
|
||||
* Convert Mesa program inputs to TGSI input register semantics.
|
||||
*/
|
||||
for (attr = 0; attr < VARYING_SLOT_MAX; attr++) {
|
||||
if ((stgp->Base.Base.InputsRead & BITFIELD64_BIT(attr)) != 0) {
|
||||
const GLuint slot = gs_num_inputs++;
|
||||
if ((prog->InputsRead & BITFIELD64_BIT(attr)) != 0) {
|
||||
const GLuint slot = num_inputs++;
|
||||
|
||||
inputMapping[attr] = slot;
|
||||
inputSlotToAttr[slot] = attr;
|
||||
|
||||
switch (attr) {
|
||||
case VARYING_SLOT_PRIMITIVE_ID:
|
||||
assert(tgsi_processor == TGSI_PROCESSOR_GEOMETRY);
|
||||
input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID;
|
||||
input_semantic_index[slot] = 0;
|
||||
break;
|
||||
@@ -1038,19 +1029,33 @@ st_translate_geometry_program(struct st_context *st,
|
||||
/* fall through */
|
||||
case VARYING_SLOT_VAR0:
|
||||
default:
|
||||
assert(attr >= VARYING_SLOT_VAR0 && attr < VARYING_SLOT_MAX);
|
||||
assert(attr >= VARYING_SLOT_VAR0 ||
|
||||
(attr >= VARYING_SLOT_TEX0 && attr <= VARYING_SLOT_TEX7));
|
||||
input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
|
||||
input_semantic_index[slot] =
|
||||
st_get_generic_varying_index(st, attr);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Also add patch inputs. */
|
||||
for (attr = 0; attr < 32; attr++) {
|
||||
if (prog->PatchInputsRead & (1 << attr)) {
|
||||
GLuint slot = num_inputs++;
|
||||
GLuint patch_attr = VARYING_SLOT_PATCH0 + attr;
|
||||
|
||||
inputMapping[patch_attr] = slot;
|
||||
inputSlotToAttr[slot] = patch_attr;
|
||||
input_semantic_name[slot] = TGSI_SEMANTIC_PATCH;
|
||||
input_semantic_index[slot] = attr;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
|
||||
output_semantic_index[i] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1058,8 +1063,8 @@ st_translate_geometry_program(struct st_context *st,
|
||||
* mapping and the semantic information for each output.
|
||||
*/
|
||||
for (attr = 0; attr < VARYING_SLOT_MAX; attr++) {
|
||||
if (stgp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) {
|
||||
GLuint slot = gs_num_outputs++;
|
||||
if (prog->OutputsWritten & BITFIELD64_BIT(attr)) {
|
||||
GLuint slot = num_outputs++;
|
||||
|
||||
outputMapping[attr] = slot;
|
||||
outputSlotToAttr[slot] = attr;
|
||||
@@ -1067,56 +1072,64 @@ st_translate_geometry_program(struct st_context *st,
|
||||
switch (attr) {
|
||||
case VARYING_SLOT_POS:
|
||||
assert(slot == 0);
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
|
||||
gs_output_semantic_index[slot] = 0;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
|
||||
output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VARYING_SLOT_COL0:
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
|
||||
gs_output_semantic_index[slot] = 0;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
|
||||
output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VARYING_SLOT_COL1:
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
|
||||
gs_output_semantic_index[slot] = 1;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
|
||||
output_semantic_index[slot] = 1;
|
||||
break;
|
||||
case VARYING_SLOT_BFC0:
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
|
||||
gs_output_semantic_index[slot] = 0;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
|
||||
output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VARYING_SLOT_BFC1:
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
|
||||
gs_output_semantic_index[slot] = 1;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
|
||||
output_semantic_index[slot] = 1;
|
||||
break;
|
||||
case VARYING_SLOT_FOGC:
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
|
||||
gs_output_semantic_index[slot] = 0;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
|
||||
output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VARYING_SLOT_PSIZ:
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
|
||||
gs_output_semantic_index[slot] = 0;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
|
||||
output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VARYING_SLOT_CLIP_VERTEX:
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_CLIPVERTEX;
|
||||
gs_output_semantic_index[slot] = 0;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_CLIPVERTEX;
|
||||
output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VARYING_SLOT_CLIP_DIST0:
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
|
||||
gs_output_semantic_index[slot] = 0;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
|
||||
output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VARYING_SLOT_CLIP_DIST1:
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
|
||||
gs_output_semantic_index[slot] = 1;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
|
||||
output_semantic_index[slot] = 1;
|
||||
break;
|
||||
case VARYING_SLOT_LAYER:
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_LAYER;
|
||||
gs_output_semantic_index[slot] = 0;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_LAYER;
|
||||
output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VARYING_SLOT_PRIMITIVE_ID:
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_PRIMID;
|
||||
gs_output_semantic_index[slot] = 0;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_PRIMID;
|
||||
output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VARYING_SLOT_VIEWPORT:
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_VIEWPORT_INDEX;
|
||||
gs_output_semantic_index[slot] = 0;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_VIEWPORT_INDEX;
|
||||
output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VARYING_SLOT_TESS_LEVEL_OUTER:
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_TESSOUTER;
|
||||
output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VARYING_SLOT_TESS_LEVEL_INNER:
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_TESSINNER;
|
||||
output_semantic_index[slot] = 0;
|
||||
break;
|
||||
case VARYING_SLOT_TEX0:
|
||||
case VARYING_SLOT_TEX1:
|
||||
@@ -1127,36 +1140,44 @@ st_translate_geometry_program(struct st_context *st,
|
||||
case VARYING_SLOT_TEX6:
|
||||
case VARYING_SLOT_TEX7:
|
||||
if (st->needs_texcoord_semantic) {
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_TEXCOORD;
|
||||
gs_output_semantic_index[slot] = attr - VARYING_SLOT_TEX0;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_TEXCOORD;
|
||||
output_semantic_index[slot] = attr - VARYING_SLOT_TEX0;
|
||||
break;
|
||||
}
|
||||
/* fall through */
|
||||
case VARYING_SLOT_VAR0:
|
||||
default:
|
||||
assert(slot < ARRAY_SIZE(gs_output_semantic_name));
|
||||
assert(attr >= VARYING_SLOT_VAR0);
|
||||
gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
|
||||
gs_output_semantic_index[slot] =
|
||||
assert(slot < ARRAY_SIZE(output_semantic_name));
|
||||
assert(attr >= VARYING_SLOT_VAR0 ||
|
||||
(attr >= VARYING_SLOT_TEX0 && attr <= VARYING_SLOT_TEX7));
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
|
||||
output_semantic_index[slot] =
|
||||
st_get_generic_varying_index(st, attr);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, stgp->Base.InputType);
|
||||
ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, stgp->Base.OutputType);
|
||||
ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES,
|
||||
stgp->Base.VerticesOut);
|
||||
ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS, stgp->Base.Invocations);
|
||||
/* Also add patch outputs. */
|
||||
for (attr = 0; attr < 32; attr++) {
|
||||
if (prog->PatchOutputsWritten & (1 << attr)) {
|
||||
GLuint slot = num_outputs++;
|
||||
GLuint patch_attr = VARYING_SLOT_PATCH0 + attr;
|
||||
|
||||
outputMapping[patch_attr] = slot;
|
||||
outputSlotToAttr[slot] = patch_attr;
|
||||
output_semantic_name[slot] = TGSI_SEMANTIC_PATCH;
|
||||
output_semantic_index[slot] = attr;
|
||||
}
|
||||
}
|
||||
|
||||
st_translate_program(st->ctx,
|
||||
TGSI_PROCESSOR_GEOMETRY,
|
||||
tgsi_processor,
|
||||
ureg,
|
||||
stgp->glsl_to_tgsi,
|
||||
&stgp->Base.Base,
|
||||
glsl_to_tgsi,
|
||||
prog,
|
||||
/* inputs */
|
||||
gs_num_inputs,
|
||||
num_inputs,
|
||||
inputMapping,
|
||||
inputSlotToAttr,
|
||||
input_semantic_name,
|
||||
@@ -1164,30 +1185,64 @@ st_translate_geometry_program(struct st_context *st,
|
||||
NULL,
|
||||
NULL,
|
||||
/* outputs */
|
||||
gs_num_outputs,
|
||||
num_outputs,
|
||||
outputMapping,
|
||||
outputSlotToAttr,
|
||||
gs_output_semantic_name,
|
||||
gs_output_semantic_index,
|
||||
output_semantic_name,
|
||||
output_semantic_index,
|
||||
FALSE,
|
||||
FALSE);
|
||||
|
||||
state.tokens = ureg_get_tokens(ureg, NULL);
|
||||
out_state->tokens = ureg_get_tokens(ureg, NULL);
|
||||
ureg_destroy(ureg);
|
||||
|
||||
st_translate_stream_output_info(stgp->glsl_to_tgsi,
|
||||
st_translate_stream_output_info(glsl_to_tgsi,
|
||||
outputMapping,
|
||||
&state.stream_output);
|
||||
&out_state->stream_output);
|
||||
|
||||
if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
|
||||
_mesa_print_program(&stgp->Base.Base);
|
||||
_mesa_print_program(prog);
|
||||
debug_printf("\n");
|
||||
}
|
||||
|
||||
if (ST_DEBUG & DEBUG_TGSI) {
|
||||
tgsi_dump(state.tokens, 0);
|
||||
tgsi_dump(out_state->tokens, 0);
|
||||
debug_printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Translate a geometry program to create a new variant.
|
||||
*/
|
||||
static struct st_gp_variant *
|
||||
st_translate_geometry_program(struct st_context *st,
|
||||
struct st_geometry_program *stgp,
|
||||
const struct st_gp_variant_key *key)
|
||||
{
|
||||
struct pipe_context *pipe = st->pipe;
|
||||
struct ureg_program *ureg;
|
||||
struct st_gp_variant *gpv;
|
||||
struct pipe_shader_state state;
|
||||
|
||||
ureg = ureg_create_with_screen(TGSI_PROCESSOR_GEOMETRY, st->pipe->screen);
|
||||
if (ureg == NULL)
|
||||
return NULL;
|
||||
|
||||
ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM, stgp->Base.InputType);
|
||||
ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM, stgp->Base.OutputType);
|
||||
ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES,
|
||||
stgp->Base.VerticesOut);
|
||||
ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS, stgp->Base.Invocations);
|
||||
|
||||
st_translate_program_common(st, &stgp->Base.Base, stgp->glsl_to_tgsi, ureg,
|
||||
TGSI_PROCESSOR_GEOMETRY, &state);
|
||||
|
||||
gpv = CALLOC_STRUCT(st_gp_variant);
|
||||
if (!gpv) {
|
||||
ureg_free_tokens(state.tokens);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fill in new variant */
|
||||
gpv->driver_shader = pipe->create_gs_state(pipe, &state);
|
||||
@@ -1237,7 +1292,34 @@ st_translate_tessctrl_program(struct st_context *st,
|
||||
struct st_tessctrl_program *sttcp,
|
||||
const struct st_tcp_variant_key *key)
|
||||
{
|
||||
return NULL; /* will be updated in the next commit */
|
||||
struct pipe_context *pipe = st->pipe;
|
||||
struct ureg_program *ureg;
|
||||
struct st_tcp_variant *tcpv;
|
||||
struct pipe_shader_state state;
|
||||
|
||||
ureg = ureg_create_with_screen(TGSI_PROCESSOR_TESS_CTRL, pipe->screen);
|
||||
if (ureg == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ureg_property(ureg, TGSI_PROPERTY_TCS_VERTICES_OUT,
|
||||
sttcp->Base.VerticesOut);
|
||||
|
||||
st_translate_program_common(st, &sttcp->Base.Base, sttcp->glsl_to_tgsi,
|
||||
ureg, TGSI_PROCESSOR_TESS_CTRL, &state);
|
||||
|
||||
tcpv = CALLOC_STRUCT(st_tcp_variant);
|
||||
if (!tcpv) {
|
||||
ureg_free_tokens(state.tokens);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fill in new variant */
|
||||
tcpv->driver_shader = pipe->create_tcs_state(pipe, &state);
|
||||
tcpv->key = *key;
|
||||
|
||||
ureg_free_tokens(state.tokens);
|
||||
return tcpv;
|
||||
}
|
||||
|
||||
|
||||
@@ -1280,7 +1362,56 @@ st_translate_tesseval_program(struct st_context *st,
|
||||
struct st_tesseval_program *sttep,
|
||||
const struct st_tep_variant_key *key)
|
||||
{
|
||||
return NULL; /* will be updated in the next commit */
|
||||
struct pipe_context *pipe = st->pipe;
|
||||
struct ureg_program *ureg;
|
||||
struct st_tep_variant *tepv;
|
||||
struct pipe_shader_state state;
|
||||
|
||||
ureg = ureg_create_with_screen(TGSI_PROCESSOR_TESS_EVAL, pipe->screen);
|
||||
if (ureg == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (sttep->Base.PrimitiveMode == GL_ISOLINES)
|
||||
ureg_property(ureg, TGSI_PROPERTY_TES_PRIM_MODE, GL_LINES);
|
||||
else
|
||||
ureg_property(ureg, TGSI_PROPERTY_TES_PRIM_MODE, sttep->Base.PrimitiveMode);
|
||||
|
||||
switch (sttep->Base.Spacing) {
|
||||
case GL_EQUAL:
|
||||
ureg_property(ureg, TGSI_PROPERTY_TES_SPACING, PIPE_TESS_SPACING_EQUAL);
|
||||
break;
|
||||
case GL_FRACTIONAL_EVEN:
|
||||
ureg_property(ureg, TGSI_PROPERTY_TES_SPACING,
|
||||
PIPE_TESS_SPACING_FRACTIONAL_EVEN);
|
||||
break;
|
||||
case GL_FRACTIONAL_ODD:
|
||||
ureg_property(ureg, TGSI_PROPERTY_TES_SPACING,
|
||||
PIPE_TESS_SPACING_FRACTIONAL_ODD);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
ureg_property(ureg, TGSI_PROPERTY_TES_VERTEX_ORDER_CW,
|
||||
sttep->Base.VertexOrder == GL_CW);
|
||||
ureg_property(ureg, TGSI_PROPERTY_TES_POINT_MODE, sttep->Base.PointMode);
|
||||
|
||||
st_translate_program_common(st, &sttep->Base.Base, sttep->glsl_to_tgsi,
|
||||
ureg, TGSI_PROCESSOR_TESS_EVAL, &state);
|
||||
|
||||
tepv = CALLOC_STRUCT(st_tep_variant);
|
||||
if (!tepv) {
|
||||
ureg_free_tokens(state.tokens);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* fill in new variant */
|
||||
tepv->driver_shader = pipe->create_tes_state(pipe, &state);
|
||||
tepv->key = *key;
|
||||
|
||||
ureg_free_tokens(state.tokens);
|
||||
return tepv;
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user