From: Marek Olšák Date: Tue, 2 Aug 2016 14:40:50 +0000 (+0200) Subject: st/mesa: determine states used or affected by shaders at compile time X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8c1775c14caf934bf56e9511099033477853d568;p=mesa.git st/mesa: determine states used or affected by shaders at compile time 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. v2: small code unification Tested-by: Edmondo Tommasina Reviewed-by: Nicolai Hähnle (v1) --- diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp index 362559fbe0d..3e5b322b9d1 100644 --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp @@ -6664,6 +6664,37 @@ get_mesa_program_tgsi(struct gl_context *ctx, return prog; } +static void +set_affected_state_flags(uint64_t *states, + struct gl_program *prog, + struct gl_linked_shader *shader, + uint64_t new_constants, + uint64_t new_sampler_views, + uint64_t new_samplers, + uint64_t new_images, + uint64_t new_ubos, + uint64_t new_ssbos, + uint64_t new_atomics) +{ + if (prog->Parameters->NumParameters) + *states |= new_constants; + + if (shader->num_samplers) + *states |= new_sampler_views | new_samplers; + + if (shader->NumImages) + *states |= new_images; + + if (shader->NumUniformBlocks) + *states |= new_ubos; + + if (shader->NumShaderStorageBlocks) + *states |= new_ssbos; + + if (shader->NumAtomicBuffers) + *states |= new_atomics; +} + static struct gl_program * get_mesa_program(struct gl_context *ctx, struct gl_shader_program *shader_program, @@ -6673,17 +6704,131 @@ get_mesa_program(struct gl_context *ctx, 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; + + set_affected_state_flags(states, prog, shader, + ST_NEW_VS_CONSTANTS, + ST_NEW_VS_SAMPLER_VIEWS, + ST_NEW_RENDER_SAMPLERS, + ST_NEW_VS_IMAGES, + ST_NEW_VS_UBOS, + ST_NEW_VS_SSBOS, + ST_NEW_VS_ATOMICS); + break; + + case MESA_SHADER_TESS_CTRL: + states = &((struct st_tessctrl_program*)prog)->affected_states; + + *states = ST_NEW_TCS_STATE; + + set_affected_state_flags(states, prog, shader, + ST_NEW_TCS_CONSTANTS, + ST_NEW_TCS_SAMPLER_VIEWS, + ST_NEW_RENDER_SAMPLERS, + ST_NEW_TCS_IMAGES, + ST_NEW_TCS_UBOS, + ST_NEW_TCS_SSBOS, + 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; + + set_affected_state_flags(states, prog, shader, + ST_NEW_TES_CONSTANTS, + ST_NEW_TES_SAMPLER_VIEWS, + ST_NEW_RENDER_SAMPLERS, + ST_NEW_TES_IMAGES, + ST_NEW_TES_UBOS, + ST_NEW_TES_SSBOS, + 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; + + set_affected_state_flags(states, prog, shader, + ST_NEW_GS_CONSTANTS, + ST_NEW_GS_SAMPLER_VIEWS, + ST_NEW_RENDER_SAMPLERS, + ST_NEW_GS_IMAGES, + ST_NEW_GS_UBOS, + ST_NEW_GS_SSBOS, + 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; + + set_affected_state_flags(states, prog, shader, + ST_NEW_FS_CONSTANTS, + ST_NEW_FS_SAMPLER_VIEWS, + ST_NEW_RENDER_SAMPLERS, + ST_NEW_FS_IMAGES, + ST_NEW_FS_UBOS, + ST_NEW_FS_SSBOS, + ST_NEW_FS_ATOMICS); + break; + + case MESA_SHADER_COMPUTE: + states = &((struct st_compute_program*)prog)->affected_states; + + *states = ST_NEW_CS_STATE; + + set_affected_state_flags(states, prog, shader, + ST_NEW_CS_CONSTANTS, + ST_NEW_CS_SAMPLER_VIEWS, + ST_NEW_CS_SAMPLERS, + ST_NEW_CS_IMAGES, + ST_NEW_CS_UBOS, + ST_NEW_CS_SSBOS, + ST_NEW_CS_ATOMICS); + break; + + default: + unreachable("unhandled shader stage"); + } } - return get_mesa_program_tgsi(ctx, shader_program, shader); + + return prog; } diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index e297bb1d5d5..03a685c4db6 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -364,9 +364,23 @@ st_translate_vertex_program(struct st_context *st, 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, @@ -593,10 +607,31 @@ st_translate_fragment_program(struct st_context *st, 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; + } } /* diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h index e6db1069025..8e11bf02fa9 100644 --- a/src/mesa/state_tracker/st_program.h +++ b/src/mesa/state_tracker/st_program.h @@ -107,6 +107,7 @@ struct st_fragment_program 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; @@ -166,6 +167,7 @@ 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; @@ -214,6 +216,7 @@ 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; }; @@ -227,6 +230,7 @@ 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; }; @@ -240,6 +244,7 @@ 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; }; @@ -253,6 +258,7 @@ 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; };