From 31a786c80addde6a4d9fd6b1f66b96f8cc3a72ef Mon Sep 17 00:00:00 2001 From: Iago Toral Quiroga Date: Thu, 1 Jul 2021 09:39:17 +0200 Subject: [PATCH] v3dv: handle QUNIFORM_FB_LAYERS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is a bit of a corner case here for secondary buffers that don't inherit framebuffer information, since those won't have access to the number of layers in the framebuffer by the time we get here. Since we only emit this to sanitize the value of gl_Layer produced from geometry shaders, I think it is probably fine to lie about it and just use the maximum number of layers we support. The only issue with that is that broken shaders that emit out of bounds layer indices (which the spect states may lead to unfined shading results) may cause undefined results. In the future we could do better and patch the uniform streams later when the secondary is executed inside a primary, since we will have the required framebuffer information at that point, but for now this seems like a reasonable compromise. Reviewed-by: Alejandro PiƱeiro Part-of: --- src/broadcom/vulkan/v3dv_uniforms.c | 39 +++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/broadcom/vulkan/v3dv_uniforms.c b/src/broadcom/vulkan/v3dv_uniforms.c index b4ee96a3092..db575426a68 100644 --- a/src/broadcom/vulkan/v3dv_uniforms.c +++ b/src/broadcom/vulkan/v3dv_uniforms.c @@ -487,6 +487,45 @@ v3dv_write_uniforms_wg_offsets(struct v3dv_cmd_buffer *cmd_buffer, data)); break; + /* We generate this from geometry shaders to cap the generated gl_Layer + * to be within the number of layers of the framebuffer so we prevent the + * binner from trying to access tile state memory out of bounds (for + * layers that don't exist). + * + * Unfortunately, for secondary command buffers we may not know the + * number of layers in the framebuffer at this stage. Since we are + * only using this to sanitize the shader and it should not have any + * impact on correct shaders that emit valid values for gl_Layer, + * we just work around it by using the largest number of layers we + * support. + * + * FIXME: we could do better than this by recording in the job that + * the value at this uniform offset is not correct, and patch it when + * we execute the secondary command buffer into a primary, since we do + * have the correct number of layers at that point, but again, since this + * is only for sanityzing the shader and it only affects the specific case + * of secondary command buffers without framebuffer info available it + * might not be worth the trouble. + */ + case QUNIFORM_FB_LAYERS: { + uint32_t num_layers; + if (job->frame_tiling.layers != 0) { + num_layers = job->frame_tiling.layers; + } else if (job->cmd_buffer && + job->cmd_buffer->state.framebuffer) { + num_layers = job->cmd_buffer->state.framebuffer->layers; + } else { + assert(job->cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY); + num_layers = 2048; +#if DEBUG + fprintf(stderr, "Skipping gl_LayerID shader sanity check for " + "secondary command buffer\n"); +#endif + } + cl_aligned_u32(&uniforms, num_layers); + break; + } + case QUNIFORM_NUM_WORK_GROUPS: assert(job->type == V3DV_JOB_TYPE_GPU_CSD); assert(job->csd.wg_count[data] > 0);