From: Marek Olšák <marek.ol...@amd.com> At compile time, each shader determines which ST_NEW flags should be set at shader bind time.
This just sets the new field for all shaders. The next commit will use it. --- src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 175 ++++++++++++++++++++++++++++- src/mesa/state_tracker/st_program.c | 37 +++++- src/mesa/state_tracker/st_program.h | 6 + 3 files changed, 215 insertions(+), 3 deletions(-) diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 362559f..fd14766 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -6666,31 +6666,202 @@ get_mesa_program_tgsi(struct gl_context *ctx, static struct gl_program * get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_program, struct gl_linked_shader *shader) { struct pipe_screen *pscreen = ctx->st->pipe->screen; unsigned ptarget = st_shader_stage_to_ptarget(shader->Stage); enum pipe_shader_ir preferred_ir = (enum pipe_shader_ir) pscreen->get_shader_param(pscreen, ptarget, PIPE_SHADER_CAP_PREFERRED_IR); + struct gl_program *prog = NULL; + if (preferred_ir == PIPE_SHADER_IR_NIR) { /* TODO only for GLSL VS/FS for now: */ switch (shader->Stage) { case MESA_SHADER_VERTEX: case MESA_SHADER_FRAGMENT: - return st_nir_get_mesa_program(ctx, shader_program, shader); + prog = st_nir_get_mesa_program(ctx, shader_program, shader); default: break; } + } else { + prog = get_mesa_program_tgsi(ctx, shader_program, shader); + } + + if (prog) { + uint64_t *states; + + /* This determines which states will be updated when the shader is + * bound. + */ + switch (shader->Stage) { + case MESA_SHADER_VERTEX: + states = &((struct st_vertex_program*)prog)->affected_states; + + *states = ST_NEW_VS_STATE | + ST_NEW_RASTERIZER | + ST_NEW_VERTEX_ARRAYS; + + if (prog->Parameters->NumParameters) + *states |= ST_NEW_VS_CONSTANTS; + + if (shader->num_samplers) + *states |= ST_NEW_VS_SAMPLER_VIEWS | + ST_NEW_RENDER_SAMPLERS; + + if (shader->NumImages) + *states |= ST_NEW_VS_IMAGES; + + if (shader->NumUniformBlocks) + *states |= ST_NEW_VS_UBOS; + + if (shader->NumShaderStorageBlocks) + *states |= ST_NEW_VS_SSBOS; + + if (shader->NumAtomicBuffers) + *states |= ST_NEW_VS_ATOMICS; + break; + + case MESA_SHADER_TESS_CTRL: + states = &((struct st_tessctrl_program*)prog)->affected_states; + + *states = ST_NEW_TCS_STATE; + + if (prog->Parameters->NumParameters) + *states |= ST_NEW_TCS_CONSTANTS; + + if (shader->num_samplers) + *states |= ST_NEW_TCS_SAMPLER_VIEWS | + ST_NEW_RENDER_SAMPLERS; + + if (shader->NumImages) + *states |= ST_NEW_TCS_IMAGES; + + if (shader->NumUniformBlocks) + *states |= ST_NEW_TCS_UBOS; + + if (shader->NumShaderStorageBlocks) + *states |= ST_NEW_TCS_SSBOS; + + if (shader->NumAtomicBuffers) + *states |= ST_NEW_TCS_ATOMICS; + break; + + case MESA_SHADER_TESS_EVAL: + states = &((struct st_tesseval_program*)prog)->affected_states; + + *states = ST_NEW_TES_STATE | + ST_NEW_RASTERIZER; + + if (prog->Parameters->NumParameters) + *states |= ST_NEW_TES_CONSTANTS; + + if (shader->num_samplers) + *states |= ST_NEW_TES_SAMPLER_VIEWS | + ST_NEW_RENDER_SAMPLERS; + + if (shader->NumImages) + *states |= ST_NEW_TES_IMAGES; + + if (shader->NumUniformBlocks) + *states |= ST_NEW_TES_UBOS; + + if (shader->NumShaderStorageBlocks) + *states |= ST_NEW_TES_SSBOS; + + if (shader->NumAtomicBuffers) + *states |= ST_NEW_TES_ATOMICS; + break; + + case MESA_SHADER_GEOMETRY: + states = &((struct st_geometry_program*)prog)->affected_states; + + *states = ST_NEW_GS_STATE | + ST_NEW_RASTERIZER; + + if (prog->Parameters->NumParameters) + *states |= ST_NEW_GS_CONSTANTS; + + if (shader->num_samplers) + *states |= ST_NEW_GS_SAMPLER_VIEWS | + ST_NEW_RENDER_SAMPLERS; + + if (shader->NumImages) + *states |= ST_NEW_GS_IMAGES; + + if (shader->NumUniformBlocks) + *states |= ST_NEW_GS_UBOS; + + if (shader->NumShaderStorageBlocks) + *states |= ST_NEW_GS_SSBOS; + + if (shader->NumAtomicBuffers) + *states |= ST_NEW_GS_ATOMICS; + break; + + case MESA_SHADER_FRAGMENT: + states = &((struct st_fragment_program*)prog)->affected_states; + + /* gl_FragCoord and glDrawPixels always use constants. */ + *states = ST_NEW_FS_STATE | + ST_NEW_SAMPLE_SHADING | + ST_NEW_FS_CONSTANTS; + + if (shader->num_samplers) + *states |= ST_NEW_FS_SAMPLER_VIEWS | + ST_NEW_RENDER_SAMPLERS; + + if (shader->NumImages) + *states |= ST_NEW_FS_IMAGES; + + if (shader->NumUniformBlocks) + *states |= ST_NEW_FS_UBOS; + + if (shader->NumShaderStorageBlocks) + *states |= ST_NEW_FS_SSBOS; + + if (shader->NumAtomicBuffers) + *states |= ST_NEW_FS_ATOMICS; + break; + + case MESA_SHADER_COMPUTE: + states = &((struct st_compute_program*)prog)->affected_states; + + *states = ST_NEW_CS_STATE; + + if (prog->Parameters->NumParameters) + *states |= ST_NEW_CS_CONSTANTS; + + if (shader->num_samplers) + *states |= ST_NEW_CS_SAMPLER_VIEWS | + ST_NEW_CS_SAMPLERS; + + if (shader->NumImages) + *states |= ST_NEW_CS_IMAGES; + + if (shader->NumUniformBlocks) + *states |= ST_NEW_CS_UBOS; + + if (shader->NumShaderStorageBlocks) + *states |= ST_NEW_CS_SSBOS; + + if (shader->NumAtomicBuffers) + *states |= ST_NEW_CS_ATOMICS; + break; + + default: + unreachable("unhandled shader stage"); + } } - return get_mesa_program_tgsi(ctx, shader_program, shader); + + return prog; } extern "C" { /** * Link a shader. * Called via ctx->Driver.LinkShader() * This actually involves converting GLSL IR into an intermediate TGSI-like IR * with code lowering and other optimizations. diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index e297bb1..03a685c 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -357,23 +357,37 @@ st_translate_vertex_program(struct st_context *st, st_get_generic_varying_index(st, attr); break; } } } /* 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; - if (!stvp->glsl_to_tgsi && !stvp->shader_program) + /* ARB_vp: */ + if (!stvp->glsl_to_tgsi && !stvp->shader_program) { _mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT); + /* This determines which states will be updated when the assembly + * shader is bound. + */ + stvp->affected_states = ST_NEW_VS_STATE | + ST_NEW_RASTERIZER | + ST_NEW_VERTEX_ARRAYS; + + if (stvp->Base.Base.Parameters->NumParameters) + stvp->affected_states |= ST_NEW_VS_CONSTANTS; + + /* No samplers are allowed in ARB_vp. */ + } + if (stvp->shader_program) { nir_shader *nir = st_glsl_to_nir(st, &stvp->Base.Base, stvp->shader_program, MESA_SHADER_VERTEX); stvp->tgsi.type = PIPE_SHADER_IR_NIR; stvp->tgsi.ir.nir = nir; st_translate_stream_output_info2(&stvp->shader_program->LinkedTransformFeedback, stvp->result_to_output, @@ -586,24 +600,45 @@ st_translate_fragment_program(struct st_context *st, 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) { _mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT); if (st->ctx->Const.GLSLFragCoordIsSysVal) _mesa_program_fragment_position_to_sysval(&stfp->Base.Base); + + /* This determines which states will be updated when the assembly + * shader is bound. + * + * fragment.position and glDrawPixels always use constants. + */ + stfp->affected_states = ST_NEW_FS_STATE | + ST_NEW_SAMPLE_SHADING | + ST_NEW_FS_CONSTANTS; + + if (stfp->ati_fs) { + /* Just set them for ATI_fs unconditionally. */ + stfp->affected_states |= ST_NEW_FS_SAMPLER_VIEWS | + ST_NEW_RENDER_SAMPLERS; + } else { + /* ARB_fp */ + if (stfp->Base.Base.SamplersUsed) + stfp->affected_states |= ST_NEW_FS_SAMPLER_VIEWS | + ST_NEW_RENDER_SAMPLERS; + } } /* * Convert Mesa program inputs to TGSI input register semantics. */ inputsRead = stfp->Base.Base.InputsRead; for (attr = 0; attr < VARYING_SLOT_MAX; attr++) { if ((inputsRead & BITFIELD64_BIT(attr)) != 0) { const GLuint slot = fs_num_inputs++; diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index e6db106..8e11bf0 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -100,20 +100,21 @@ struct st_fp_variant /** * Derived from Mesa gl_fragment_program: */ struct st_fragment_program { struct gl_fragment_program Base; struct pipe_shader_state tgsi; struct glsl_to_tgsi_visitor* glsl_to_tgsi; struct ati_fragment_shader *ati_fs; + uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */ /* used when bypassing glsl_to_tgsi: */ struct gl_shader_program *shader_program; struct st_fp_variant *variants; }; /** Vertex program variant key */ @@ -159,20 +160,21 @@ struct st_vp_variant /** * Derived from Mesa gl_fragment_program: */ struct st_vertex_program { struct gl_vertex_program Base; /**< The Mesa vertex program */ struct pipe_shader_state tgsi; struct glsl_to_tgsi_visitor* glsl_to_tgsi; + uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */ /* used when bypassing glsl_to_tgsi: */ struct gl_shader_program *shader_program; /** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */ /** maps a TGSI input index back to a Mesa VERT_ATTRIB_x */ GLuint index_to_input[PIPE_MAX_SHADER_INPUTS]; GLuint num_inputs; /** Maps VARYING_SLOT_x to slot */ @@ -207,59 +209,63 @@ struct st_basic_variant /** * Derived from Mesa gl_geometry_program: */ struct st_geometry_program { struct gl_geometry_program Base; /**< The Mesa geometry program */ struct pipe_shader_state tgsi; struct glsl_to_tgsi_visitor* glsl_to_tgsi; + uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */ struct st_basic_variant *variants; }; /** * Derived from Mesa gl_tess_ctrl_program: */ struct st_tessctrl_program { struct gl_tess_ctrl_program Base; /**< The Mesa tess ctrl program */ struct pipe_shader_state tgsi; struct glsl_to_tgsi_visitor* glsl_to_tgsi; + uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */ struct st_basic_variant *variants; }; /** * Derived from Mesa gl_tess_eval_program: */ struct st_tesseval_program { struct gl_tess_eval_program Base; /**< The Mesa tess eval program */ struct pipe_shader_state tgsi; struct glsl_to_tgsi_visitor* glsl_to_tgsi; + uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */ struct st_basic_variant *variants; }; /** * Derived from Mesa gl_compute_program: */ struct st_compute_program { struct gl_compute_program Base; /**< The Mesa compute program */ struct pipe_compute_state tgsi; struct glsl_to_tgsi_visitor* glsl_to_tgsi; + uint64_t affected_states; /**< ST_NEW_* flags to mark dirty when binding */ struct st_basic_variant *variants; }; static inline struct st_fragment_program * st_fragment_program( struct gl_fragment_program *fp ) { return (struct st_fragment_program *)fp; } -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev