zink: add a workaround for a nir_assign_io_var_locations bug

drivers that use nir_assign_io_var_locations() with EXT_shader_object all
have the same bug with a shader interface that looks like this:

shader output block:
* PSIZ
* VAR0
* VAR8

shader input block:
* VAR0
* VAR8

in this case, output driver locations will be assigned like:
* PSIZ=0
* VAR0=1
* VAR8=2

and input driver locations will be:
* VAR0=0
* VAR8=1

which breaks the shaders even though this is a totally legitimate thing
to do

thus, a second set of shaders have to be created without PSIZ to work around
the bug since I've already spent 18+ hours trying to fix it and have only succeeded
in breaking every driver that uses it

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/22725>
This commit is contained in:
Mike Blumenkrantz
2023-04-07 08:12:42 -04:00
committed by Marge Bot
parent 697ed61e7c
commit bf746b5921
3 changed files with 36 additions and 9 deletions
+30 -8
View File
@@ -3783,15 +3783,36 @@ zink_shader_compile_separate(struct zink_screen *screen, struct zink_shader *zs)
optimize_nir(nir, zs);
zink_descriptor_shader_init(screen, zs);
zs->sinfo.last_vertex = zs->sinfo.have_xfb;
nir_shader *nir_clone = NULL;
if (screen->info.have_EXT_shader_object)
nir_clone = nir_shader_clone(nir, nir);
struct zink_shader_object obj = compile_module(screen, zs, nir, true);
/* always try to pre-generate a tcs in case it's needed */
if (zs->info.stage == MESA_SHADER_TESS_EVAL && screen->info.have_EXT_shader_object && !zs->info.internal) {
nir_shader *nir_tcs = NULL;
/* use max pcp for compat */
zs->non_fs.generated_tcs = zink_shader_tcs_create(screen, nir, 32, &nir_tcs);
nir_tcs->info.separate_shader = true;
zs->non_fs.generated_tcs->precompile.obj = zink_shader_compile_separate(screen, zs->non_fs.generated_tcs);
ralloc_free(nir_tcs);
if (screen->info.have_EXT_shader_object && !zs->info.internal) {
/* always try to pre-generate a tcs in case it's needed */
if (zs->info.stage == MESA_SHADER_TESS_EVAL) {
nir_shader *nir_tcs = NULL;
/* use max pcp for compat */
zs->non_fs.generated_tcs = zink_shader_tcs_create(screen, nir_clone, 32, &nir_tcs);
nir_tcs->info.separate_shader = true;
zs->non_fs.generated_tcs->precompile.obj = zink_shader_compile_separate(screen, zs->non_fs.generated_tcs);
ralloc_free(nir_tcs);
}
if (zs->info.stage == MESA_SHADER_VERTEX || zs->info.stage == MESA_SHADER_TESS_EVAL) {
/* create a second variant with PSIZ removed:
* this works around a bug in drivers using nir_assign_io_var_locations()
* where builtins that aren't read by following stages get assigned
* driver locations before varyings and break the i/o interface between shaders even
* though zink has correctly assigned all locations
*/
nir_variable *var = nir_find_variable_with_location(nir_clone, nir_var_shader_out, VARYING_SLOT_PSIZ);
if (var && !var->data.explicit_location) {
var->data.mode = nir_var_shader_temp;
nir_fixup_deref_modes(nir_clone);
NIR_PASS_V(nir_clone, nir_remove_dead_variables, nir_var_shader_temp, NULL);
optimize_nir(nir_clone, NULL);
zs->precompile.no_psiz_obj = compile_module(screen, zs, nir_clone, true);
}
}
}
ralloc_free(nir);
return obj;
@@ -5127,6 +5148,7 @@ zink_shader_free(struct zink_screen *screen, struct zink_shader *shader)
zink_descriptor_shader_deinit(screen, shader);
if (screen->info.have_EXT_shader_object) {
VKSCR(DestroyShaderEXT)(screen->dev, shader->precompile.obj.obj, NULL);
VKSCR(DestroyShaderEXT)(screen->dev, shader->precompile.no_psiz_obj.obj, NULL);
} else {
if (shader->precompile.obj.mod)
VKSCR(DestroyShaderModule)(screen->dev, shader->precompile.obj.mod, NULL);
+5 -1
View File
@@ -1180,7 +1180,11 @@ create_gfx_program_separable(struct zink_context *ctx, struct zink_shader **stag
_mesa_set_add(prog->shaders[i]->programs, prog);
simple_mtx_unlock(&prog->shaders[i]->lock);
if (screen->info.have_EXT_shader_object) {
prog->objects[i] = prog->shaders[i]->precompile.obj.obj;
/* FIXME: delete this if nir_assign_io_var_locations is ever fixed */
if (prog->last_vertex_stage != prog->shaders[i] && (i == MESA_SHADER_VERTEX || i == MESA_SHADER_TESS_EVAL))
prog->objects[i] = prog->shaders[i]->precompile.no_psiz_obj.obj;
if (!prog->objects[i])
prog->objects[i] = prog->shaders[i]->precompile.obj.obj;
}
refs++;
}
+1
View File
@@ -768,6 +768,7 @@ struct zink_shader {
struct {
struct util_queue_fence fence;
struct zink_shader_object obj;
struct zink_shader_object no_psiz_obj; //avoid a crippling bug in nir_assign_io_var_locations()
VkDescriptorSetLayout dsl;
VkPipelineLayout layout;
VkPipeline gpl;