*/
+#include "main/errors.h"
#include "main/imports.h"
#include "main/hash.h"
#include "main/mtypes.h"
#include "program/prog_parameter.h"
#include "program/prog_print.h"
+#include "program/prog_to_nir.h"
#include "program/programopt.h"
#include "compiler/nir/nir.h"
#include "st_cb_bitmap.h"
#include "st_cb_drawpixels.h"
#include "st_context.h"
+#include "st_tgsi_lower_depth_clamp.h"
#include "st_tgsi_lower_yuv.h"
#include "st_program.h"
#include "st_mesa_to_tgsi.h"
break;
case MESA_SHADER_COMPUTE:
- states = &((struct st_compute_program*)prog)->affected_states;
+ states = &((struct st_common_program*)prog)->affected_states;
*states = ST_NEW_CS_STATE;
}
}
+static void
+delete_ir(struct pipe_shader_state *ir)
+{
+ if (ir->tokens) {
+ ureg_free_tokens(ir->tokens);
+ ir->tokens = NULL;
+ }
+
+ /* Note: Any setup of ->ir.nir that has had pipe->create_*_state called on
+ * it has resulted in the driver taking ownership of the NIR. Those
+ * callers should be NULLing out the nir field in any pipe_shader_state
+ * that might have this called in order to indicate that.
+ *
+ * GLSL IR and ARB programs will have set gl_program->nir to the same
+ * shader as ir->ir.nir, so it will be freed by _mesa_delete_program().
+ */
+}
+
/**
* Delete a vertex program variant. Note the caller must unlink
* the variant from the linked list.
static void
delete_vp_variant(struct st_context *st, struct st_vp_variant *vpv)
{
- if (vpv->driver_shader)
- cso_delete_vertex_shader(st->cso_context, vpv->driver_shader);
-
+ if (vpv->driver_shader) {
+ if (st->has_shareable_shaders || vpv->key.st == st) {
+ cso_delete_vertex_shader(st->cso_context, vpv->driver_shader);
+ } else {
+ st_save_zombie_shader(vpv->key.st, PIPE_SHADER_VERTEX,
+ vpv->driver_shader);
+ }
+ }
+
if (vpv->draw_shader)
draw_delete_vertex_shader( st->draw, vpv->draw_shader );
- if (((vpv->tgsi.type == PIPE_SHADER_IR_TGSI)) && vpv->tgsi.tokens)
- ureg_free_tokens(vpv->tgsi.tokens);
+ delete_ir(&vpv->state);
free( vpv );
}
stvp->variants = NULL;
- if ((stvp->tgsi.type == PIPE_SHADER_IR_TGSI) && stvp->tgsi.tokens) {
- tgsi_free_tokens(stvp->tgsi.tokens);
- stvp->tgsi.tokens = NULL;
- }
+ delete_ir(&stvp->state);
}
static void
delete_fp_variant(struct st_context *st, struct st_fp_variant *fpv)
{
- if (fpv->driver_shader)
- cso_delete_fragment_shader(st->cso_context, fpv->driver_shader);
+ if (fpv->driver_shader) {
+ if (st->has_shareable_shaders || fpv->key.st == st) {
+ cso_delete_fragment_shader(st->cso_context, fpv->driver_shader);
+ } else {
+ st_save_zombie_shader(fpv->key.st, PIPE_SHADER_FRAGMENT,
+ fpv->driver_shader);
+ }
+ }
+
free(fpv);
}
stfp->variants = NULL;
- if ((stfp->tgsi.type == PIPE_SHADER_IR_TGSI) && stfp->tgsi.tokens) {
- ureg_free_tokens(stfp->tgsi.tokens);
- stfp->tgsi.tokens = NULL;
- }
+ delete_ir(&stfp->state);
}
* the variant from the linked list.
*/
static void
-delete_basic_variant(struct st_context *st, struct st_basic_variant *v,
+delete_basic_variant(struct st_context *st, struct st_common_variant *v,
GLenum target)
{
if (v->driver_shader) {
- switch (target) {
- case GL_TESS_CONTROL_PROGRAM_NV:
- cso_delete_tessctrl_shader(st->cso_context, v->driver_shader);
- break;
- case GL_TESS_EVALUATION_PROGRAM_NV:
- cso_delete_tesseval_shader(st->cso_context, v->driver_shader);
- break;
- case GL_GEOMETRY_PROGRAM_NV:
- cso_delete_geometry_shader(st->cso_context, v->driver_shader);
- break;
- case GL_COMPUTE_PROGRAM_NV:
- cso_delete_compute_shader(st->cso_context, v->driver_shader);
- break;
- default:
- assert(!"this shouldn't occur");
+ if (st->has_shareable_shaders || v->key.st == st) {
+ /* The shader's context matches the calling context, or we
+ * don't care.
+ */
+ switch (target) {
+ case GL_TESS_CONTROL_PROGRAM_NV:
+ cso_delete_tessctrl_shader(st->cso_context, v->driver_shader);
+ break;
+ case GL_TESS_EVALUATION_PROGRAM_NV:
+ cso_delete_tesseval_shader(st->cso_context, v->driver_shader);
+ break;
+ case GL_GEOMETRY_PROGRAM_NV:
+ cso_delete_geometry_shader(st->cso_context, v->driver_shader);
+ break;
+ case GL_COMPUTE_PROGRAM_NV:
+ cso_delete_compute_shader(st->cso_context, v->driver_shader);
+ break;
+ default:
+ unreachable("bad shader type in delete_basic_variant");
+ }
+ } else {
+ /* We can't delete a shader with a context different from the one
+ * that created it. Add it to the creating context's zombie list.
+ */
+ enum pipe_shader_type type;
+ switch (target) {
+ case GL_TESS_CONTROL_PROGRAM_NV:
+ type = PIPE_SHADER_TESS_CTRL;
+ break;
+ case GL_TESS_EVALUATION_PROGRAM_NV:
+ type = PIPE_SHADER_TESS_EVAL;
+ break;
+ case GL_GEOMETRY_PROGRAM_NV:
+ type = PIPE_SHADER_GEOMETRY;
+ break;
+ default:
+ unreachable("");
+ }
+ st_save_zombie_shader(v->key.st, type, v->driver_shader);
}
}
* Free all basic program variants.
*/
void
-st_release_basic_variants(struct st_context *st, GLenum target,
- struct st_basic_variant **variants,
- struct pipe_shader_state *tgsi)
+st_release_common_variants(struct st_context *st, struct st_common_program *p)
{
- struct st_basic_variant *v;
+ struct st_common_variant *v;
- for (v = *variants; v; ) {
- struct st_basic_variant *next = v->next;
- delete_basic_variant(st, v, target);
+ for (v = p->variants; v; ) {
+ struct st_common_variant *next = v->next;
+ delete_basic_variant(st, v, p->Base.Target);
v = next;
}
- *variants = NULL;
-
- if (tgsi->tokens) {
- ureg_free_tokens(tgsi->tokens);
- tgsi->tokens = NULL;
- }
+ p->variants = NULL;
+ delete_ir(&p->state);
}
/**
- * Free all variants of a compute program.
+ * Translate ARB (asm) program to NIR
*/
+static nir_shader *
+st_translate_prog_to_nir(struct st_context *st, struct gl_program *prog,
+ gl_shader_stage stage)
+{
+ const struct gl_shader_compiler_options *options =
+ &st->ctx->Const.ShaderCompilerOptions[stage];
+
+ /* Translate to NIR */
+ nir_shader *nir = prog_to_nir(prog, options->NirOptions);
+ NIR_PASS_V(nir, nir_lower_regs_to_ssa); /* turn registers into SSA */
+ nir_validate_shader(nir, "after st/ptn lower_regs_to_ssa");
+
+ NIR_PASS_V(nir, st_nir_lower_wpos_ytransform, prog, st->pipe->screen);
+ NIR_PASS_V(nir, nir_lower_system_values);
+
+ /* Optimise NIR */
+ NIR_PASS_V(nir, nir_opt_constant_folding);
+ st_nir_opts(nir);
+ nir_validate_shader(nir, "after st/ptn NIR opts");
+
+ return nir;
+}
+
void
-st_release_cp_variants(struct st_context *st, struct st_compute_program *stcp)
+st_prepare_vertex_program(struct st_vertex_program *stvp)
{
- struct st_basic_variant **variants = &stcp->variants;
- struct st_basic_variant *v;
+ stvp->num_inputs = 0;
+ memset(stvp->input_to_index, ~0, sizeof(stvp->input_to_index));
+ memset(stvp->result_to_output, ~0, sizeof(stvp->result_to_output));
- for (v = *variants; v; ) {
- struct st_basic_variant *next = v->next;
- delete_basic_variant(st, v, stcp->Base.Target);
- v = next;
+ /* Determine number of inputs, the mappings between VERT_ATTRIB_x
+ * and TGSI generic input indexes, plus input attrib semantic info.
+ */
+ for (unsigned attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
+ if ((stvp->Base.info.inputs_read & BITFIELD64_BIT(attr)) != 0) {
+ stvp->input_to_index[attr] = stvp->num_inputs;
+ stvp->index_to_input[stvp->num_inputs] = attr;
+ stvp->num_inputs++;
+
+ if ((stvp->Base.DualSlotInputs & BITFIELD64_BIT(attr)) != 0) {
+ /* add placeholder for second part of a double attribute */
+ stvp->index_to_input[stvp->num_inputs] = ST_DOUBLE_ATTRIB_PLACEHOLDER;
+ stvp->num_inputs++;
+ }
+ }
+ }
+ /* pre-setup 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. */
+ unsigned num_outputs = 0;
+ for (unsigned attr = 0; attr < VARYING_SLOT_MAX; attr++) {
+ if (stvp->Base.info.outputs_written & BITFIELD64_BIT(attr))
+ stvp->result_to_output[attr] = num_outputs++;
}
+ /* pre-setup potentially unused edgeflag output */
+ stvp->result_to_output[VARYING_SLOT_EDGE] = num_outputs;
+}
- *variants = NULL;
+void
+st_translate_stream_output_info(struct gl_program *prog)
+{
+ struct gl_transform_feedback_info *info = prog->sh.LinkedTransformFeedback;
+ if (!info)
+ return;
- if (stcp->tgsi.prog) {
- ureg_free_tokens(stcp->tgsi.prog);
- stcp->tgsi.prog = NULL;
+ /* Determine the (default) output register mapping for each output. */
+ unsigned num_outputs = 0;
+ ubyte output_mapping[VARYING_SLOT_TESS_MAX];
+ memset(output_mapping, 0, sizeof(output_mapping));
+
+ for (unsigned attr = 0; attr < VARYING_SLOT_MAX; attr++) {
+ if (prog->info.outputs_written & BITFIELD64_BIT(attr))
+ output_mapping[attr] = num_outputs++;
+ }
+
+ /* Translate stream output info. */
+ struct pipe_stream_output_info *so_info = NULL;
+ if (prog->info.stage == MESA_SHADER_VERTEX)
+ so_info = &((struct st_vertex_program*)prog)->state.stream_output;
+ else
+ so_info = &((struct st_common_program*)prog)->state.stream_output;
+
+ for (unsigned i = 0; i < info->NumOutputs; i++) {
+ so_info->output[i].register_index =
+ output_mapping[info->Outputs[i].OutputRegister];
+ so_info->output[i].start_component = info->Outputs[i].ComponentOffset;
+ so_info->output[i].num_components = info->Outputs[i].NumComponents;
+ so_info->output[i].output_buffer = info->Outputs[i].OutputBuffer;
+ so_info->output[i].dst_offset = info->Outputs[i].DstOffset;
+ so_info->output[i].stream = info->Outputs[i].StreamId;
}
+
+ for (unsigned i = 0; i < PIPE_MAX_SO_BUFFERS; i++) {
+ so_info->stride[i] = info->Buffers[i].Stride;
+ }
+ so_info->num_outputs = info->NumOutputs;
}
/**
enum pipe_error error;
unsigned num_outputs = 0;
unsigned attr;
- ubyte input_to_index[VERT_ATTRIB_MAX] = {0};
ubyte output_semantic_name[VARYING_SLOT_MAX] = {0};
ubyte output_semantic_index[VARYING_SLOT_MAX] = {0};
- stvp->num_inputs = 0;
-
if (stvp->Base.arb.IsPositionInvariant)
_mesa_insert_mvp_code(st->ctx, &stvp->Base);
- /*
- * 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.info.inputs_read & BITFIELD64_BIT(attr)) != 0) {
- input_to_index[attr] = stvp->num_inputs;
- stvp->index_to_input[stvp->num_inputs] = attr;
- stvp->num_inputs++;
- if ((stvp->Base.info.double_inputs_read &
- BITFIELD64_BIT(attr)) != 0) {
- /* add placeholder for second part of a double attribute */
- stvp->index_to_input[stvp->num_inputs] = ST_DOUBLE_ATTRIB_PLACEHOLDER;
- stvp->num_inputs++;
- }
- }
- }
- /* bit of a hack, presetup potentially unused edgeflag input */
- 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 < VARYING_SLOT_MAX; attr++) {
- if ((stvp->Base.info.outputs_written & BITFIELD64_BIT(attr)) == 0) {
- stvp->result_to_output[attr] = ~0;
- }
- else {
- unsigned slot = num_outputs++;
-
- stvp->result_to_output[attr] = slot;
-
- unsigned semantic_name, semantic_index;
- tgsi_get_gl_varying_semantic(attr, st->needs_texcoord_semantic,
- &semantic_name, &semantic_index);
- output_semantic_name[slot] = semantic_name;
- output_semantic_index[slot] = semantic_index;
- }
- }
- /* similar hack to above, presetup potentially unused edgeflag output */
- stvp->result_to_output[VARYING_SLOT_EDGE] = num_outputs;
- output_semantic_name[num_outputs] = TGSI_SEMANTIC_EDGEFLAG;
- output_semantic_index[num_outputs] = 0;
+ st_prepare_vertex_program(stvp);
/* ARB_vp: */
- if (!stvp->glsl_to_tgsi && !stvp->shader_program) {
+ if (!stvp->glsl_to_tgsi) {
_mesa_remove_output_reads(&stvp->Base, PROGRAM_OUTPUT);
/* This determines which states will be updated when the assembly
/* No samplers are allowed in ARB_vp. */
}
- if (stvp->shader_program) {
- nir_shader *nir = st_glsl_to_nir(st, &stvp->Base, stvp->shader_program,
- MESA_SHADER_VERTEX);
-
- stvp->tgsi.type = PIPE_SHADER_IR_NIR;
- stvp->tgsi.ir.nir = nir;
-
- struct gl_program *prog = stvp->shader_program->last_vert_prog;
- if (prog) {
- st_translate_stream_output_info2(prog->sh.LinkedTransformFeedback,
- stvp->result_to_output,
- &stvp->tgsi.stream_output);
+ /* Get semantic names and indices. */
+ for (attr = 0; attr < VARYING_SLOT_MAX; attr++) {
+ if (stvp->Base.info.outputs_written & BITFIELD64_BIT(attr)) {
+ unsigned slot = num_outputs++;
+ unsigned semantic_name, semantic_index;
+ tgsi_get_gl_varying_semantic(attr, st->needs_texcoord_semantic,
+ &semantic_name, &semantic_index);
+ output_semantic_name[slot] = semantic_name;
+ output_semantic_index[slot] = semantic_index;
}
-
- return true;
}
+ /* pre-setup potentially unused edgeflag output */
+ output_semantic_name[num_outputs] = TGSI_SEMANTIC_EDGEFLAG;
+ output_semantic_index[num_outputs] = 0;
ureg = ureg_create_with_screen(PIPE_SHADER_VERTEX, st->pipe->screen);
if (ureg == NULL)
&stvp->Base,
/* inputs */
stvp->num_inputs,
- input_to_index,
+ stvp->input_to_index,
NULL, /* inputSlotToAttr */
NULL, /* input semantic name */
NULL, /* input semantic index */
output_semantic_name,
output_semantic_index);
- st_translate_stream_output_info(stvp->glsl_to_tgsi,
- stvp->result_to_output,
- &stvp->tgsi.stream_output);
+ st_translate_stream_output_info(&stvp->Base);
free_glsl_to_tgsi_visitor(stvp->glsl_to_tgsi);
} else
&stvp->Base,
/* inputs */
stvp->num_inputs,
- input_to_index,
+ stvp->input_to_index,
NULL, /* input semantic name */
NULL, /* input semantic index */
NULL,
return false;
}
- unsigned num_tokens;
- stvp->tgsi.tokens = ureg_get_tokens(ureg, &num_tokens);
+ stvp->state.tokens = ureg_get_tokens(ureg, NULL);
ureg_destroy(ureg);
if (stvp->glsl_to_tgsi) {
stvp->glsl_to_tgsi = NULL;
- st_store_tgsi_in_disk_cache(st, &stvp->Base, NULL, num_tokens);
+ st_store_ir_in_disk_cache(st, &stvp->Base, false);
+ }
+
+ /* Translate to NIR.
+ *
+ * This must be done after the translation to TGSI is done, because
+ * we'll pass the NIR shader to the driver and the TGSI version to
+ * the draw module for the select/feedback/rasterpos code.
+ */
+ if (st->pipe->screen->get_shader_param(st->pipe->screen,
+ PIPE_SHADER_VERTEX,
+ PIPE_SHADER_CAP_PREFERRED_IR)) {
+ assert(!stvp->glsl_to_tgsi);
+
+ nir_shader *nir =
+ st_translate_prog_to_nir(st, &stvp->Base, MESA_SHADER_VERTEX);
+
+ if (stvp->state.ir.nir)
+ ralloc_free(stvp->state.ir.nir);
+ stvp->state.type = PIPE_SHADER_IR_NIR;
+ stvp->state.ir.nir = nir;
+ stvp->Base.nir = nir;
+ return true;
}
- return stvp->tgsi.tokens != NULL;
+ return stvp->state.tokens != NULL;
}
+static const gl_state_index16 depth_range_state[STATE_LENGTH] =
+ { STATE_DEPTH_RANGE };
+
static struct st_vp_variant *
st_create_vp_variant(struct st_context *st,
struct st_vertex_program *stvp,
- const struct st_vp_variant_key *key)
+ const struct st_common_variant_key *key)
{
struct st_vp_variant *vpv = CALLOC_STRUCT(st_vp_variant);
struct pipe_context *pipe = st->pipe;
+ static const gl_state_index16 point_size_state[STATE_LENGTH] =
+ { STATE_INTERNAL, STATE_POINT_SIZE_CLAMPED, 0 };
+ struct gl_program_parameter_list *params = stvp->Base.Parameters;
+
vpv->key = *key;
- vpv->tgsi.stream_output = stvp->tgsi.stream_output;
+ vpv->state.stream_output = stvp->state.stream_output;
vpv->num_inputs = stvp->num_inputs;
- if (stvp->tgsi.type == PIPE_SHADER_IR_NIR) {
- vpv->tgsi.type = PIPE_SHADER_IR_NIR;
- vpv->tgsi.ir.nir = nir_shader_clone(NULL, stvp->tgsi.ir.nir);
+ /* When generating a NIR program, we usually don't have TGSI tokens.
+ * However, we do create them for ARB_vertex_program / fixed-function VS
+ * programs which we may need to use with the draw module for legacy
+ * feedback/select emulation. If they exist, copy them.
+ */
+ if (stvp->state.tokens)
+ vpv->state.tokens = tgsi_dup_tokens(stvp->state.tokens);
+
+ if (stvp->state.type == PIPE_SHADER_IR_NIR) {
+ vpv->state.type = PIPE_SHADER_IR_NIR;
+ vpv->state.ir.nir = nir_shader_clone(NULL, stvp->state.ir.nir);
if (key->clamp_color)
- NIR_PASS_V(vpv->tgsi.ir.nir, nir_lower_clamp_color_outputs);
+ NIR_PASS_V(vpv->state.ir.nir, nir_lower_clamp_color_outputs);
if (key->passthrough_edgeflags) {
- NIR_PASS_V(vpv->tgsi.ir.nir, nir_lower_passthrough_edgeflags);
+ NIR_PASS_V(vpv->state.ir.nir, nir_lower_passthrough_edgeflags);
vpv->num_inputs++;
}
- st_finalize_nir(st, &stvp->Base, vpv->tgsi.ir.nir);
+ if (key->lower_point_size) {
+ _mesa_add_state_reference(params, point_size_state);
+ NIR_PASS_V(vpv->state.ir.nir, nir_lower_point_size_mov,
+ point_size_state);
+ }
+
+ if (key->lower_ucp) {
+ struct pipe_screen *screen = pipe->screen;
+ bool can_compact = screen->get_param(screen,
+ PIPE_CAP_NIR_COMPACT_ARRAYS);
+
+ bool use_eye = st->ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX] != NULL;
+ gl_state_index16 clipplane_state[MAX_CLIP_PLANES][STATE_LENGTH];
+ for (int i = 0; i < MAX_CLIP_PLANES; ++i) {
+ if (use_eye) {
+ clipplane_state[i][0] = STATE_CLIPPLANE;
+ clipplane_state[i][1] = i;
+ } else {
+ clipplane_state[i][0] = STATE_INTERNAL;
+ clipplane_state[i][1] = STATE_CLIP_INTERNAL;
+ clipplane_state[i][2] = i;
+ }
+ _mesa_add_state_reference(params, clipplane_state[i]);
+ }
- vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi);
+ NIR_PASS_V(vpv->state.ir.nir, nir_lower_clip_vs, key->lower_ucp,
+ true, can_compact, clipplane_state);
+ NIR_PASS_V(vpv->state.ir.nir, nir_lower_io_to_temporaries,
+ nir_shader_get_entrypoint(vpv->state.ir.nir), true, false);
+ }
+
+ st_finalize_nir(st, &stvp->Base, stvp->shader_program,
+ vpv->state.ir.nir);
+
+ vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->state);
/* driver takes ownership of IR: */
- vpv->tgsi.ir.nir = NULL;
+ vpv->state.ir.nir = NULL;
return vpv;
}
- vpv->tgsi.tokens = tgsi_dup_tokens(stvp->tgsi.tokens);
-
/* Emulate features. */
if (key->clamp_color || key->passthrough_edgeflags) {
const struct tgsi_token *tokens;
(key->clamp_color ? TGSI_EMU_CLAMP_COLOR_OUTPUTS : 0) |
(key->passthrough_edgeflags ? TGSI_EMU_PASSTHROUGH_EDGEFLAG : 0);
- tokens = tgsi_emulate(vpv->tgsi.tokens, flags);
+ tokens = tgsi_emulate(vpv->state.tokens, flags);
if (tokens) {
- tgsi_free_tokens(vpv->tgsi.tokens);
- vpv->tgsi.tokens = tokens;
+ tgsi_free_tokens(vpv->state.tokens);
+ vpv->state.tokens = tokens;
if (key->passthrough_edgeflags)
vpv->num_inputs++;
fprintf(stderr, "mesa: cannot emulate deprecated features\n");
}
+ if (key->lower_depth_clamp) {
+ unsigned depth_range_const =
+ _mesa_add_state_reference(params, depth_range_state);
+
+ const struct tgsi_token *tokens;
+ tokens = st_tgsi_lower_depth_clamp(vpv->state.tokens, depth_range_const,
+ key->clip_negative_one_to_one);
+ if (tokens != vpv->state.tokens)
+ tgsi_free_tokens(vpv->state.tokens);
+ vpv->state.tokens = tokens;
+ }
+
if (ST_DEBUG & DEBUG_TGSI) {
- tgsi_dump(vpv->tgsi.tokens, 0);
+ tgsi_dump(vpv->state.tokens, 0);
debug_printf("\n");
}
- vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi);
+ vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->state);
return vpv;
}
struct st_vp_variant *
st_get_vp_variant(struct st_context *st,
struct st_vertex_program *stvp,
- const struct st_vp_variant_key *key)
+ const struct st_common_variant_key *key)
{
struct st_vp_variant *vpv;
/* create now */
vpv = st_create_vp_variant(st, stvp, key);
if (vpv) {
+ for (unsigned index = 0; index < vpv->num_inputs; ++index) {
+ unsigned attr = stvp->index_to_input[index];
+ if (attr == ST_DOUBLE_ATTRIB_PLACEHOLDER)
+ continue;
+ vpv->vert_attrib_mask |= 1u << attr;
+ }
+
/* insert into list */
vpv->next = stvp->variants;
stvp->variants = vpv;
st_translate_fragment_program(struct st_context *st,
struct st_fragment_program *stfp)
{
- ubyte outputMapping[2 * FRAG_RESULT_MAX];
- ubyte inputMapping[VARYING_SLOT_MAX];
- ubyte inputSlotToAttr[VARYING_SLOT_MAX];
- ubyte interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */
- GLuint attr;
- GLbitfield64 inputsRead;
- struct ureg_program *ureg;
-
- GLboolean write_all = GL_FALSE;
-
- 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;
-
- memset(inputSlotToAttr, ~0, sizeof(inputSlotToAttr));
-
/* Non-GLSL programs: */
- if (!stfp->glsl_to_tgsi && !stfp->shader_program) {
+ if (!stfp->glsl_to_tgsi) {
_mesa_remove_output_reads(&stfp->Base, PROGRAM_OUTPUT);
if (st->ctx->Const.GLSLFragCoordIsSysVal)
_mesa_program_fragment_position_to_sysval(&stfp->Base);
stfp->affected_states |= ST_NEW_FS_SAMPLER_VIEWS |
ST_NEW_FS_SAMPLERS;
}
+
+ /* Translate to NIR. */
+ if (!stfp->ati_fs &&
+ st->pipe->screen->get_shader_param(st->pipe->screen,
+ PIPE_SHADER_FRAGMENT,
+ PIPE_SHADER_CAP_PREFERRED_IR)) {
+ nir_shader *nir =
+ st_translate_prog_to_nir(st, &stfp->Base, MESA_SHADER_FRAGMENT);
+
+ if (stfp->state.ir.nir)
+ ralloc_free(stfp->state.ir.nir);
+ stfp->state.type = PIPE_SHADER_IR_NIR;
+ stfp->state.ir.nir = nir;
+ stfp->Base.nir = nir;
+ return true;
+ }
}
+ ubyte outputMapping[2 * FRAG_RESULT_MAX];
+ ubyte inputMapping[VARYING_SLOT_MAX];
+ ubyte inputSlotToAttr[VARYING_SLOT_MAX];
+ ubyte interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */
+ GLuint attr;
+ GLbitfield64 inputsRead;
+ struct ureg_program *ureg;
+
+ GLboolean write_all = GL_FALSE;
+
+ 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;
+
+ memset(inputSlotToAttr, ~0, sizeof(inputSlotToAttr));
+
/*
* Convert Mesa program inputs to TGSI input register semantics.
*/
}
}
- if (stfp->shader_program) {
- nir_shader *nir = st_glsl_to_nir(st, &stfp->Base, stfp->shader_program,
- MESA_SHADER_FRAGMENT);
-
- stfp->tgsi.type = PIPE_SHADER_IR_NIR;
- stfp->tgsi.ir.nir = nir;
-
- return true;
- }
-
ureg = ureg_create_with_screen(PIPE_SHADER_FRAGMENT, st->pipe->screen);
if (ureg == NULL)
return false;
fs_output_semantic_name,
fs_output_semantic_index);
- unsigned num_tokens;
- stfp->tgsi.tokens = ureg_get_tokens(ureg, &num_tokens);
+ stfp->state.tokens = ureg_get_tokens(ureg, NULL);
ureg_destroy(ureg);
if (stfp->glsl_to_tgsi) {
stfp->glsl_to_tgsi = NULL;
- st_store_tgsi_in_disk_cache(st, &stfp->Base, NULL, num_tokens);
+ st_store_ir_in_disk_cache(st, &stfp->Base, false);
}
- return stfp->tgsi.tokens != NULL;
+ return stfp->state.tokens != NULL;
}
static struct st_fp_variant *
struct st_fp_variant *variant = CALLOC_STRUCT(st_fp_variant);
struct pipe_shader_state tgsi = {0};
struct gl_program_parameter_list *params = stfp->Base.Parameters;
- static const gl_state_index texcoord_state[STATE_LENGTH] =
+ static const gl_state_index16 texcoord_state[STATE_LENGTH] =
{ STATE_INTERNAL, STATE_CURRENT_ATTRIB, VERT_ATTRIB_TEX0 };
- static const gl_state_index scale_state[STATE_LENGTH] =
+ static const gl_state_index16 scale_state[STATE_LENGTH] =
{ STATE_INTERNAL, STATE_PT_SCALE };
- static const gl_state_index bias_state[STATE_LENGTH] =
+ static const gl_state_index16 bias_state[STATE_LENGTH] =
{ STATE_INTERNAL, STATE_PT_BIAS };
+ static const gl_state_index16 alpha_ref_state[STATE_LENGTH] =
+ { STATE_INTERNAL, STATE_ALPHA_REF };
if (!variant)
return NULL;
- if (stfp->tgsi.type == PIPE_SHADER_IR_NIR) {
+ if (stfp->state.type == PIPE_SHADER_IR_NIR) {
tgsi.type = PIPE_SHADER_IR_NIR;
- tgsi.ir.nir = nir_shader_clone(NULL, stfp->tgsi.ir.nir);
+ tgsi.ir.nir = nir_shader_clone(NULL, stfp->state.ir.nir);
if (key->clamp_color)
NIR_PASS_V(tgsi.ir.nir, nir_lower_clamp_color_outputs);
+ if (key->lower_flatshade)
+ NIR_PASS_V(tgsi.ir.nir, nir_lower_flatshade);
+
+ if (key->lower_alpha_func != COMPARE_FUNC_NEVER) {
+ _mesa_add_state_reference(params, alpha_ref_state);
+ NIR_PASS_V(tgsi.ir.nir, nir_lower_alpha_test, key->lower_alpha_func,
+ false, alpha_ref_state);
+ }
+
+ if (key->lower_two_sided_color)
+ NIR_PASS_V(tgsi.ir.nir, nir_lower_two_sided_color);
+
if (key->persample_shading) {
nir_shader *shader = tgsi.ir.nir;
nir_foreach_variable(var, &shader->inputs)
variant->bitmap_sampler = ffs(~stfp->Base.SamplersUsed) - 1;
options.sampler = variant->bitmap_sampler;
- options.swizzle_xxxx = (st->bitmap.tex_format == PIPE_FORMAT_L8_UNORM);
+ options.swizzle_xxxx = st->bitmap.tex_format == PIPE_FORMAT_R8_UNORM;
NIR_PASS_V(tgsi.ir.nir, nir_lower_bitmap, &options);
}
NIR_PASS_V(tgsi.ir.nir, nir_lower_drawpixels, &options);
}
- if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv)) {
+ if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv ||
+ key->external.lower_xy_uxvx || key->external.lower_yx_xuxv ||
+ key->external.lower_ayuv || key->external.lower_xyuv)) {
nir_lower_tex_options options = {0};
options.lower_y_uv_external = key->external.lower_nv12;
options.lower_y_u_v_external = key->external.lower_iyuv;
+ options.lower_xy_uxvx_external = key->external.lower_xy_uxvx;
+ options.lower_yx_xuxv_external = key->external.lower_yx_xuxv;
+ options.lower_ayuv_external = key->external.lower_ayuv;
+ options.lower_xyuv_external = key->external.lower_xyuv;
NIR_PASS_V(tgsi.ir.nir, nir_lower_tex, &options);
}
- st_finalize_nir(st, &stfp->Base, tgsi.ir.nir);
+ st_finalize_nir(st, &stfp->Base, stfp->shader_program, tgsi.ir.nir);
- if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv)) {
+ if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv ||
+ key->external.lower_xy_uxvx || key->external.lower_yx_xuxv)) {
/* This pass needs to happen *after* nir_lower_sampler */
NIR_PASS_V(tgsi.ir.nir, st_nir_lower_tex_src_plane,
~stfp->Base.SamplersUsed,
- key->external.lower_nv12,
+ key->external.lower_nv12 || key->external.lower_xy_uxvx ||
+ key->external.lower_yx_xuxv,
key->external.lower_iyuv);
}
+ /* Some of the lowering above may have introduced new varyings */
+ nir_shader_gather_info(tgsi.ir.nir,
+ nir_shader_get_entrypoint(tgsi.ir.nir));
+
variant->driver_shader = pipe->create_fs_state(pipe, &tgsi);
variant->key = *key;
return variant;
}
- tgsi.tokens = stfp->tgsi.tokens;
+ tgsi.tokens = stfp->state.tokens;
assert(!(key->bitmap && key->drawpixels));
tokens = tgsi_emulate(tgsi.tokens, flags);
if (tokens) {
- if (tgsi.tokens != stfp->tgsi.tokens)
+ if (tgsi.tokens != stfp->state.tokens)
tgsi_free_tokens(tgsi.tokens);
tgsi.tokens = tokens;
} else
variant->bitmap_sampler,
st->needs_texcoord_semantic,
st->bitmap.tex_format ==
- PIPE_FORMAT_L8_UNORM);
+ PIPE_FORMAT_R8_UNORM);
if (tokens) {
- if (tgsi.tokens != stfp->tgsi.tokens)
+ if (tgsi.tokens != stfp->state.tokens)
tgsi_free_tokens(tgsi.tokens);
tgsi.tokens = tokens;
} else
texcoord_const, st->internal_target);
if (tokens) {
- if (tgsi.tokens != stfp->tgsi.tokens)
+ if (tgsi.tokens != stfp->state.tokens)
tgsi_free_tokens(tgsi.tokens);
tgsi.tokens = tokens;
} else
fprintf(stderr, "mesa: cannot create a shader for glDrawPixels\n");
}
- if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv)) {
+ if (unlikely(key->external.lower_nv12 || key->external.lower_iyuv ||
+ key->external.lower_xy_uxvx || key->external.lower_yx_xuxv)) {
const struct tgsi_token *tokens;
/* samplers inserted would conflict, but this should be unpossible: */
tokens = st_tgsi_lower_yuv(tgsi.tokens,
~stfp->Base.SamplersUsed,
- key->external.lower_nv12,
+ key->external.lower_nv12 ||
+ key->external.lower_xy_uxvx ||
+ key->external.lower_yx_xuxv,
key->external.lower_iyuv);
if (tokens) {
- if (tgsi.tokens != stfp->tgsi.tokens)
+ if (tgsi.tokens != stfp->state.tokens)
tgsi_free_tokens(tgsi.tokens);
tgsi.tokens = tokens;
} else {
}
}
+ if (key->lower_depth_clamp) {
+ unsigned depth_range_const = _mesa_add_state_reference(params, depth_range_state);
+
+ const struct tgsi_token *tokens;
+ tokens = st_tgsi_lower_depth_clamp_fs(tgsi.tokens, depth_range_const);
+ if (tgsi.tokens != stfp->state.tokens)
+ tgsi_free_tokens(tgsi.tokens);
+ tgsi.tokens = tokens;
+ }
+
if (ST_DEBUG & DEBUG_TGSI) {
tgsi_dump(tgsi.tokens, 0);
debug_printf("\n");
variant->driver_shader = pipe->create_fs_state(pipe, &tgsi);
variant->key = *key;
- if (tgsi.tokens != stfp->tgsi.tokens)
+ if (tgsi.tokens != stfp->state.tokens)
tgsi_free_tokens(tgsi.tokens);
return variant;
}
return fpv;
}
-
/**
* Translate a program. This is common code for geometry and tessellation
* shaders.
*/
-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)
+bool
+st_translate_common_program(struct st_context *st,
+ struct st_common_program *stcp)
{
+ struct gl_program *prog = &stcp->Base;
+ enum pipe_shader_type stage =
+ pipe_shader_type_from_mesa(stcp->Base.info.stage);
+ struct ureg_program *ureg = ureg_create_with_screen(stage, st->pipe->screen);
+
+ if (ureg == NULL)
+ return false;
+
+ switch (stage) {
+ case PIPE_SHADER_TESS_CTRL:
+ ureg_property(ureg, TGSI_PROPERTY_TCS_VERTICES_OUT,
+ stcp->Base.info.tess.tcs_vertices_out);
+ break;
+
+ case PIPE_SHADER_TESS_EVAL:
+ if (stcp->Base.info.tess.primitive_mode == GL_ISOLINES)
+ ureg_property(ureg, TGSI_PROPERTY_TES_PRIM_MODE, GL_LINES);
+ else
+ ureg_property(ureg, TGSI_PROPERTY_TES_PRIM_MODE,
+ stcp->Base.info.tess.primitive_mode);
+
+ STATIC_ASSERT((TESS_SPACING_EQUAL + 1) % 3 == PIPE_TESS_SPACING_EQUAL);
+ STATIC_ASSERT((TESS_SPACING_FRACTIONAL_ODD + 1) % 3 ==
+ PIPE_TESS_SPACING_FRACTIONAL_ODD);
+ STATIC_ASSERT((TESS_SPACING_FRACTIONAL_EVEN + 1) % 3 ==
+ PIPE_TESS_SPACING_FRACTIONAL_EVEN);
+
+ ureg_property(ureg, TGSI_PROPERTY_TES_SPACING,
+ (stcp->Base.info.tess.spacing + 1) % 3);
+
+ ureg_property(ureg, TGSI_PROPERTY_TES_VERTEX_ORDER_CW,
+ !stcp->Base.info.tess.ccw);
+ ureg_property(ureg, TGSI_PROPERTY_TES_POINT_MODE,
+ stcp->Base.info.tess.point_mode);
+ break;
+
+ case PIPE_SHADER_GEOMETRY:
+ ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM,
+ stcp->Base.info.gs.input_primitive);
+ ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM,
+ stcp->Base.info.gs.output_primitive);
+ ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES,
+ stcp->Base.info.gs.vertices_out);
+ ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS,
+ stcp->Base.info.gs.invocations);
+ break;
+
+ default:
+ break;
+ }
+
ubyte inputSlotToAttr[VARYING_SLOT_TESS_MAX];
ubyte inputMapping[VARYING_SLOT_TESS_MAX];
ubyte outputMapping[VARYING_SLOT_TESS_MAX];
memset(inputSlotToAttr, 0, sizeof(inputSlotToAttr));
memset(inputMapping, 0, sizeof(inputMapping));
memset(outputMapping, 0, sizeof(outputMapping));
- memset(out_state, 0, sizeof(*out_state));
+ memset(&stcp->state, 0, sizeof(stcp->state));
if (prog->info.clip_distance_array_size)
ureg_property(ureg, TGSI_PROPERTY_NUM_CLIPDIST_ENABLED,
* Convert Mesa program inputs to TGSI input register semantics.
*/
for (attr = 0; attr < VARYING_SLOT_MAX; attr++) {
- if ((prog->info.inputs_read & BITFIELD64_BIT(attr)) != 0) {
- const GLuint slot = num_inputs++;
+ if ((prog->info.inputs_read & BITFIELD64_BIT(attr)) == 0)
+ continue;
- inputMapping[attr] = slot;
- inputSlotToAttr[slot] = attr;
+ unsigned slot = num_inputs++;
- switch (attr) {
- case VARYING_SLOT_PRIMITIVE_ID:
- assert(tgsi_processor == PIPE_SHADER_GEOMETRY);
- input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID;
- input_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_POS:
- input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
- input_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_COL0:
- input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
- input_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_COL1:
- input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
- input_semantic_index[slot] = 1;
- break;
- case VARYING_SLOT_FOGC:
- input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
- input_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_CLIP_VERTEX:
- input_semantic_name[slot] = TGSI_SEMANTIC_CLIPVERTEX;
- input_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_CLIP_DIST0:
- input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
- input_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_CLIP_DIST1:
- input_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
- input_semantic_index[slot] = 1;
- break;
- case VARYING_SLOT_CULL_DIST0:
- case VARYING_SLOT_CULL_DIST1:
- /* these should have been lowered by GLSL */
- assert(0);
- break;
- case VARYING_SLOT_PSIZ:
- input_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
- input_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_TEX0:
- case VARYING_SLOT_TEX1:
- case VARYING_SLOT_TEX2:
- case VARYING_SLOT_TEX3:
- case VARYING_SLOT_TEX4:
- case VARYING_SLOT_TEX5:
- case VARYING_SLOT_TEX6:
- case VARYING_SLOT_TEX7:
- if (st->needs_texcoord_semantic) {
- input_semantic_name[slot] = TGSI_SEMANTIC_TEXCOORD;
- input_semantic_index[slot] = attr - VARYING_SLOT_TEX0;
- break;
- }
- /* fall through */
- case VARYING_SLOT_VAR0:
- default:
- 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;
- }
- }
+ inputMapping[attr] = slot;
+ inputSlotToAttr[slot] = attr;
+
+ unsigned semantic_name, semantic_index;
+ tgsi_get_gl_varying_semantic(attr, st->needs_texcoord_semantic,
+ &semantic_name, &semantic_index);
+ input_semantic_name[slot] = semantic_name;
+ input_semantic_index[slot] = semantic_index;
}
/* Also add patch inputs. */
outputMapping[attr] = slot;
- switch (attr) {
- case VARYING_SLOT_POS:
- assert(slot == 0);
- output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
- output_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_COL0:
- output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
- output_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_COL1:
- output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
- output_semantic_index[slot] = 1;
- break;
- case VARYING_SLOT_BFC0:
- output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
- output_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_BFC1:
- output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
- output_semantic_index[slot] = 1;
- break;
- case VARYING_SLOT_FOGC:
- output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
- output_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_PSIZ:
- output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
- output_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_CLIP_VERTEX:
- output_semantic_name[slot] = TGSI_SEMANTIC_CLIPVERTEX;
- output_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_CLIP_DIST0:
- output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
- output_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_CLIP_DIST1:
- output_semantic_name[slot] = TGSI_SEMANTIC_CLIPDIST;
- output_semantic_index[slot] = 1;
- break;
- case VARYING_SLOT_CULL_DIST0:
- case VARYING_SLOT_CULL_DIST1:
- /* these should have been lowered by GLSL */
- assert(0);
- break;
- case VARYING_SLOT_LAYER:
- output_semantic_name[slot] = TGSI_SEMANTIC_LAYER;
- output_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_PRIMITIVE_ID:
- output_semantic_name[slot] = TGSI_SEMANTIC_PRIMID;
- output_semantic_index[slot] = 0;
- break;
- case VARYING_SLOT_VIEWPORT:
- 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:
- case VARYING_SLOT_TEX2:
- case VARYING_SLOT_TEX3:
- case VARYING_SLOT_TEX4:
- case VARYING_SLOT_TEX5:
- case VARYING_SLOT_TEX6:
- case VARYING_SLOT_TEX7:
- if (st->needs_texcoord_semantic) {
- 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(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;
- }
+ unsigned semantic_name, semantic_index;
+ tgsi_get_gl_varying_semantic(attr, st->needs_texcoord_semantic,
+ &semantic_name, &semantic_index);
+ output_semantic_name[slot] = semantic_name;
+ output_semantic_index[slot] = semantic_index;
}
}
}
st_translate_program(st->ctx,
- tgsi_processor,
+ stage,
ureg,
- glsl_to_tgsi,
+ stcp->glsl_to_tgsi,
prog,
/* inputs */
num_inputs,
output_semantic_name,
output_semantic_index);
- unsigned num_tokens;
- out_state->tokens = ureg_get_tokens(ureg, &num_tokens);
+ stcp->state.tokens = ureg_get_tokens(ureg, NULL);
+
ureg_destroy(ureg);
- st_translate_stream_output_info(glsl_to_tgsi,
- outputMapping,
- &out_state->stream_output);
+ st_translate_stream_output_info(prog);
- st_store_tgsi_in_disk_cache(st, prog, out_state, num_tokens);
+ st_store_ir_in_disk_cache(st, prog, false);
if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
_mesa_print_program(prog);
}
if (ST_DEBUG & DEBUG_TGSI) {
- tgsi_dump(out_state->tokens, 0);
+ tgsi_dump(stcp->state.tokens, 0);
debug_printf("\n");
}
-}
-
-/**
- * Translate a geometry program to create a new variant.
- */
-bool
-st_translate_geometry_program(struct st_context *st,
- struct st_common_program *stgp)
-{
- struct ureg_program *ureg;
-
- ureg = ureg_create_with_screen(PIPE_SHADER_GEOMETRY, st->pipe->screen);
- if (ureg == NULL)
- return false;
-
- ureg_property(ureg, TGSI_PROPERTY_GS_INPUT_PRIM,
- stgp->Base.info.gs.input_primitive);
- ureg_property(ureg, TGSI_PROPERTY_GS_OUTPUT_PRIM,
- stgp->Base.info.gs.output_primitive);
- ureg_property(ureg, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES,
- stgp->Base.info.gs.vertices_out);
- ureg_property(ureg, TGSI_PROPERTY_GS_INVOCATIONS,
- stgp->Base.info.gs.invocations);
-
- st_translate_program_common(st, &stgp->Base, stgp->glsl_to_tgsi, ureg,
- PIPE_SHADER_GEOMETRY, &stgp->tgsi);
-
- free_glsl_to_tgsi_visitor(stgp->glsl_to_tgsi);
- stgp->glsl_to_tgsi = NULL;
+ free_glsl_to_tgsi_visitor(stcp->glsl_to_tgsi);
+ stcp->glsl_to_tgsi = NULL;
return true;
}
/**
* Get/create a basic program variant.
*/
-struct st_basic_variant *
-st_get_basic_variant(struct st_context *st,
- unsigned pipe_shader,
- struct pipe_shader_state *tgsi,
- struct st_basic_variant **variants)
+struct st_common_variant *
+st_get_common_variant(struct st_context *st,
+ struct st_common_program *prog,
+ const struct st_common_variant_key *key)
{
struct pipe_context *pipe = st->pipe;
- struct st_basic_variant *v;
- struct st_basic_variant_key key;
-
- memset(&key, 0, sizeof(key));
- key.st = st->has_shareable_shaders ? NULL : st;
+ struct st_common_variant *v;
+ struct pipe_shader_state tgsi = {0};
/* Search for existing variant */
- for (v = *variants; v; v = v->next) {
- if (memcmp(&v->key, &key, sizeof(key)) == 0) {
+ for (v = prog->variants; v; v = v->next) {
+ if (memcmp(&v->key, key, sizeof(*key)) == 0) {
break;
}
}
if (!v) {
/* create new */
- v = CALLOC_STRUCT(st_basic_variant);
+ v = CALLOC_STRUCT(st_common_variant);
if (v) {
- /* fill in new variant */
- switch (pipe_shader) {
- case PIPE_SHADER_TESS_CTRL:
- v->driver_shader = pipe->create_tcs_state(pipe, tgsi);
- break;
- case PIPE_SHADER_TESS_EVAL:
- v->driver_shader = pipe->create_tes_state(pipe, tgsi);
- break;
- case PIPE_SHADER_GEOMETRY:
- v->driver_shader = pipe->create_gs_state(pipe, tgsi);
- break;
- default:
- assert(!"unhandled shader type");
- free(v);
- return NULL;
- }
-
- v->key = key;
-
- /* insert into list */
- v->next = *variants;
- *variants = v;
- }
- }
-
- return v;
-}
-
-
-/**
- * Translate a tessellation control program to create a new variant.
- */
-bool
-st_translate_tessctrl_program(struct st_context *st,
- struct st_common_program *sttcp)
-{
- struct ureg_program *ureg;
-
- ureg = ureg_create_with_screen(PIPE_SHADER_TESS_CTRL, st->pipe->screen);
- if (ureg == NULL)
- return false;
-
- ureg_property(ureg, TGSI_PROPERTY_TCS_VERTICES_OUT,
- sttcp->Base.info.tess.tcs_vertices_out);
-
- st_translate_program_common(st, &sttcp->Base, sttcp->glsl_to_tgsi, ureg,
- PIPE_SHADER_TESS_CTRL, &sttcp->tgsi);
-
- free_glsl_to_tgsi_visitor(sttcp->glsl_to_tgsi);
- sttcp->glsl_to_tgsi = NULL;
- return true;
-}
+ if (prog->state.type == PIPE_SHADER_IR_NIR) {
+ tgsi.type = PIPE_SHADER_IR_NIR;
+ tgsi.ir.nir = nir_shader_clone(NULL, prog->state.ir.nir);
-/**
- * Translate a tessellation evaluation program to create a new variant.
- */
-bool
-st_translate_tesseval_program(struct st_context *st,
- struct st_common_program *sttep)
-{
- struct ureg_program *ureg;
+ if (key->clamp_color)
+ NIR_PASS_V(tgsi.ir.nir, nir_lower_clamp_color_outputs);
- ureg = ureg_create_with_screen(PIPE_SHADER_TESS_EVAL, st->pipe->screen);
- if (ureg == NULL)
- return false;
-
- if (sttep->Base.info.tess.primitive_mode == GL_ISOLINES)
- ureg_property(ureg, TGSI_PROPERTY_TES_PRIM_MODE, GL_LINES);
- else
- ureg_property(ureg, TGSI_PROPERTY_TES_PRIM_MODE,
- sttep->Base.info.tess.primitive_mode);
-
- STATIC_ASSERT((TESS_SPACING_EQUAL + 1) % 3 == PIPE_TESS_SPACING_EQUAL);
- STATIC_ASSERT((TESS_SPACING_FRACTIONAL_ODD + 1) % 3 ==
- PIPE_TESS_SPACING_FRACTIONAL_ODD);
- STATIC_ASSERT((TESS_SPACING_FRACTIONAL_EVEN + 1) % 3 ==
- PIPE_TESS_SPACING_FRACTIONAL_EVEN);
+ tgsi.stream_output = prog->state.stream_output;
- ureg_property(ureg, TGSI_PROPERTY_TES_SPACING,
- (sttep->Base.info.tess.spacing + 1) % 3);
+ st_finalize_nir(st, &prog->Base, prog->shader_program,
+ tgsi.ir.nir);
+ } else {
+ if (key->lower_depth_clamp) {
+ struct gl_program_parameter_list *params = prog->Base.Parameters;
- ureg_property(ureg, TGSI_PROPERTY_TES_VERTEX_ORDER_CW,
- !sttep->Base.info.tess.ccw);
- ureg_property(ureg, TGSI_PROPERTY_TES_POINT_MODE,
- sttep->Base.info.tess.point_mode);
+ unsigned depth_range_const =
+ _mesa_add_state_reference(params, depth_range_state);
- st_translate_program_common(st, &sttep->Base, sttep->glsl_to_tgsi,
- ureg, PIPE_SHADER_TESS_EVAL, &sttep->tgsi);
-
- free_glsl_to_tgsi_visitor(sttep->glsl_to_tgsi);
- sttep->glsl_to_tgsi = NULL;
- return true;
-}
+ const struct tgsi_token *tokens;
+ tokens =
+ st_tgsi_lower_depth_clamp(prog->state.tokens,
+ depth_range_const,
+ key->clip_negative_one_to_one);
+ if (tokens != prog->state.tokens)
+ tgsi_free_tokens(prog->state.tokens);
-/**
- * Translate a compute program to create a new variant.
- */
-bool
-st_translate_compute_program(struct st_context *st,
- struct st_compute_program *stcp)
-{
- struct ureg_program *ureg;
- struct pipe_shader_state prog;
-
- if (stcp->shader_program) {
- nir_shader *nir = st_glsl_to_nir(st, &stcp->Base, stcp->shader_program,
- MESA_SHADER_COMPUTE);
-
- /* no compute variants: */
- st_finalize_nir(st, &stcp->Base, nir);
-
- stcp->tgsi.ir_type = PIPE_SHADER_IR_NIR;
- stcp->tgsi.prog = nir;
-
- return true;
- }
-
- ureg = ureg_create_with_screen(PIPE_SHADER_COMPUTE, st->pipe->screen);
- if (ureg == NULL)
- return false;
-
- st_translate_program_common(st, &stcp->Base, stcp->glsl_to_tgsi, ureg,
- PIPE_SHADER_COMPUTE, &prog);
-
- stcp->tgsi.ir_type = PIPE_SHADER_IR_TGSI;
- stcp->tgsi.prog = prog.tokens;
- stcp->tgsi.req_local_mem = stcp->Base.info.cs.shared_size;
- stcp->tgsi.req_private_mem = 0;
- stcp->tgsi.req_input_mem = 0;
-
- free_glsl_to_tgsi_visitor(stcp->glsl_to_tgsi);
- stcp->glsl_to_tgsi = NULL;
- return true;
-}
-
-
-/**
- * Get/create compute program variant.
- */
-struct st_basic_variant *
-st_get_cp_variant(struct st_context *st,
- struct pipe_compute_state *tgsi,
- struct st_basic_variant **variants)
-{
- struct pipe_context *pipe = st->pipe;
- struct st_basic_variant *v;
- struct st_basic_variant_key key;
+ prog->state.tokens = tokens;
+ }
+ tgsi = prog->state;
+ }
+ /* fill in new variant */
+ switch (prog->Base.info.stage) {
+ case MESA_SHADER_TESS_CTRL:
+ v->driver_shader = pipe->create_tcs_state(pipe, &tgsi);
+ break;
+ case MESA_SHADER_TESS_EVAL:
+ v->driver_shader = pipe->create_tes_state(pipe, &tgsi);
+ break;
+ case MESA_SHADER_GEOMETRY:
+ v->driver_shader = pipe->create_gs_state(pipe, &tgsi);
+ break;
+ case MESA_SHADER_COMPUTE: {
+ struct pipe_compute_state cs = {0};
+ cs.ir_type = tgsi.type;
+ cs.req_local_mem = prog->Base.info.cs.shared_size;
- memset(&key, 0, sizeof(key));
- key.st = st->has_shareable_shaders ? NULL : st;
+ if (tgsi.type == PIPE_SHADER_IR_NIR)
+ cs.prog = tgsi.ir.nir;
+ else
+ cs.prog = tgsi.tokens;
- /* Search for existing variant */
- for (v = *variants; v; v = v->next) {
- if (memcmp(&v->key, &key, sizeof(key)) == 0) {
- break;
- }
- }
+ v->driver_shader = pipe->create_compute_state(pipe, &cs);
+ break;
+ }
+ default:
+ assert(!"unhandled shader type");
+ free(v);
+ return NULL;
+ }
- if (!v) {
- /* create new */
- v = CALLOC_STRUCT(st_basic_variant);
- if (v) {
- /* fill in new variant */
- v->driver_shader = pipe->create_compute_state(pipe, tgsi);
- v->key = key;
+ v->key = *key;
/* insert into list */
- v->next = *variants;
- *variants = v;
+ v->next = prog->variants;
+ prog->variants = v;
}
}
case GL_COMPUTE_PROGRAM_NV:
{
struct st_common_program *p = st_common_program(target);
- struct st_compute_program *cp = (struct st_compute_program*)target;
- struct st_basic_variant **variants =
- target->Target == GL_COMPUTE_PROGRAM_NV ? &cp->variants :
- &p->variants;
- struct st_basic_variant *v, **prevPtr = variants;
-
- for (v = *variants; v; ) {
- struct st_basic_variant *next = v->next;
+ struct st_common_variant *v, **prevPtr = &p->variants;
+
+ for (v = p->variants; v; ) {
+ struct st_common_variant *next = v->next;
if (v->key.st == st) {
/* unlink from list */
*prevPtr = next;
for (stv = stvp->variants; stv; stv = stv->next) {
debug_printf("variant %p\n", stv);
- tgsi_dump(stv->tgsi.tokens, 0);
+ tgsi_dump(stv->state.tokens, 0);
}
}
}
switch (prog->Target) {
case GL_VERTEX_PROGRAM_ARB: {
struct st_vertex_program *p = (struct st_vertex_program *)prog;
- struct st_vp_variant_key key;
+ struct st_common_variant_key key;
memset(&key, 0, sizeof(key));
+
key.st = st->has_shareable_shaders ? NULL : st;
st_get_vp_variant(st, p, &key);
break;
}
- case GL_TESS_CONTROL_PROGRAM_NV: {
- struct st_common_program *p = st_common_program(prog);
- st_get_basic_variant(st, PIPE_SHADER_TESS_CTRL, &p->tgsi, &p->variants);
- break;
- }
-
- case GL_TESS_EVALUATION_PROGRAM_NV: {
- struct st_common_program *p = st_common_program(prog);
- st_get_basic_variant(st, PIPE_SHADER_TESS_EVAL, &p->tgsi, &p->variants);
- break;
- }
-
- case GL_GEOMETRY_PROGRAM_NV: {
- struct st_common_program *p = st_common_program(prog);
- st_get_basic_variant(st, PIPE_SHADER_GEOMETRY, &p->tgsi, &p->variants);
- break;
- }
-
case GL_FRAGMENT_PROGRAM_ARB: {
struct st_fragment_program *p = (struct st_fragment_program *)prog;
struct st_fp_variant_key key;
memset(&key, 0, sizeof(key));
+
key.st = st->has_shareable_shaders ? NULL : st;
st_get_fp_variant(st, p, &key);
break;
}
+ case GL_TESS_CONTROL_PROGRAM_NV:
+ case GL_TESS_EVALUATION_PROGRAM_NV:
+ case GL_GEOMETRY_PROGRAM_NV:
case GL_COMPUTE_PROGRAM_NV: {
- struct st_compute_program *p = (struct st_compute_program *)prog;
- st_get_cp_variant(st, &p->tgsi, &p->variants);
+ struct st_common_program *p = st_common_program(prog);
+ struct st_common_variant_key key;
+
+ memset(&key, 0, sizeof(key));
+
+ key.st = st->has_shareable_shaders ? NULL : st;
+ st_get_common_variant(st, p, &key);
break;
}