diff --git a/src/imagination/vulkan/pvr_cmd_buffer.c b/src/imagination/vulkan/pvr_cmd_buffer.c index 6fcca92ec79..fe820782ce7 100644 --- a/src/imagination/vulkan/pvr_cmd_buffer.c +++ b/src/imagination/vulkan/pvr_cmd_buffer.c @@ -910,6 +910,11 @@ static VkResult pvr_sub_cmd_gfx_job_init(const struct pvr_device_info *dev_info, struct pvr_cmd_buffer *cmd_buffer, struct pvr_sub_cmd_gfx *sub_cmd) { + static const VkClearDepthStencilValue default_ds_clear_value = { + .depth = 1.0f, + .stencil = 0xFFFFFFFF, + }; + const struct vk_dynamic_graphics_state *dynamic_state = &cmd_buffer->vk.dynamic_graphics_state; struct pvr_render_pass_info *render_pass_info = @@ -1028,64 +1033,44 @@ static VkResult pvr_sub_cmd_gfx_job_init(const struct pvr_device_info *dev_info, render_pass_info->attachments[hw_render->ds_attach_idx]; const struct pvr_image *image = vk_to_pvr_image(iview->vk.image); - if (vk_format_has_depth(image->vk.format)) { + job->has_depth_attachment = vk_format_has_depth(image->vk.format); + job->has_stencil_attachment = vk_format_has_stencil(image->vk.format); + + if (job->has_depth_attachment || job->has_stencil_attachment) { uint32_t level_pitch = image->mip_levels[iview->vk.base_mip_level].pitch; - /* FIXME: Is this sufficient for depth buffers? */ - job->depth_addr = image->dev_addr; + job->ds.addr = image->dev_addr; - job->depth_stride = - pvr_stride_from_pitch(level_pitch, iview->vk.format); - job->depth_height = iview->vk.extent.height; - job->depth_physical_width = + job->ds.stride = pvr_stride_from_pitch(level_pitch, iview->vk.format); + job->ds.height = iview->vk.extent.height; + job->ds.physical_width = u_minify(image->physical_extent.width, iview->vk.base_mip_level); - job->depth_physical_height = + job->ds.physical_height = u_minify(image->physical_extent.height, iview->vk.base_mip_level); - job->depth_layer_size = image->layer_size; + job->ds.layer_size = image->layer_size; + + job->ds_clear_value = default_ds_clear_value; if (hw_render->ds_attach_idx < render_pass_info->clear_value_count) { - VkClearValue *clear_values = - &render_pass_info->clear_values[hw_render->ds_attach_idx]; + const VkClearDepthStencilValue *const clear_values = + &render_pass_info->clear_values[hw_render->ds_attach_idx] + .depthStencil; - job->depth_clear_value = clear_values->depthStencil.depth; - } else { - job->depth_clear_value = 1.0f; + if (job->has_depth_attachment) + job->ds_clear_value.depth = clear_values->depth; + + if (job->has_stencil_attachment) + job->ds_clear_value.stencil = clear_values->stencil; } - job->depth_vk_format = iview->vk.format; - - job->depth_memlayout = image->memlayout; - } else { - job->depth_addr = PVR_DEV_ADDR_INVALID; - job->depth_stride = 0; - job->depth_height = 0; - job->depth_physical_width = 0; - job->depth_physical_height = 0; - job->depth_layer_size = 0; - job->depth_clear_value = 1.0f; - job->depth_vk_format = VK_FORMAT_UNDEFINED; - job->depth_memlayout = PVR_MEMLAYOUT_LINEAR; - } - - if (vk_format_has_stencil(image->vk.format)) { - /* FIXME: Is this sufficient for stencil buffers? */ - job->stencil_addr = image->dev_addr; - } else { - job->stencil_addr = PVR_DEV_ADDR_INVALID; + job->ds.vk_format = iview->vk.format; + job->ds.memlayout = image->memlayout; } } else { - job->depth_addr = PVR_DEV_ADDR_INVALID; - job->depth_stride = 0; - job->depth_height = 0; - job->depth_physical_width = 0; - job->depth_physical_height = 0; - job->depth_layer_size = 0; - job->depth_clear_value = 1.0f; - job->depth_vk_format = VK_FORMAT_UNDEFINED; - job->depth_memlayout = PVR_MEMLAYOUT_LINEAR; - - job->stencil_addr = PVR_DEV_ADDR_INVALID; + job->has_depth_attachment = false; + job->has_stencil_attachment = false; + job->ds_clear_value = default_ds_clear_value; } if (hw_render->ds_attach_idx != VK_ATTACHMENT_UNUSED) { diff --git a/src/imagination/vulkan/pvr_job_render.c b/src/imagination/vulkan/pvr_job_render.c index 7db4e7b8678..fdcd5eae273 100644 --- a/src/imagination/vulkan/pvr_job_render.c +++ b/src/imagination/vulkan/pvr_job_render.c @@ -1372,48 +1372,56 @@ static void pvr_frag_state_stream_init(struct pvr_render_ctx *ctx, } stream_ptr += pvr_cmd_length(CR_ISP_OCLQRY_BASE); - /* FIXME: Some additional set up needed to support depth and stencil - * load/store operations. + /* FIXME: Some additional set up needed to support depth/stencil load/store + * operations. */ pvr_csb_pack ((uint64_t *)stream_ptr, CR_ISP_ZLSCTL, value) { - uint32_t aligned_width = - ALIGN_POT(job->depth_physical_width, ROGUE_IPF_TILE_SIZE_PIXELS); - uint32_t aligned_height = - ALIGN_POT(job->depth_physical_height, ROGUE_IPF_TILE_SIZE_PIXELS); + if (job->has_depth_attachment) { + uint32_t aligned_width = + ALIGN_POT(job->ds.physical_width, ROGUE_IPF_TILE_SIZE_PIXELS); + uint32_t aligned_height = + ALIGN_POT(job->ds.physical_height, ROGUE_IPF_TILE_SIZE_PIXELS); - pvr_get_isp_num_tiles_xy(dev_info, - job->samples, - aligned_width, - aligned_height, - &value.zlsextent_x_z, - &value.zlsextent_y_z); - value.zlsextent_x_z -= 1; - value.zlsextent_y_z -= 1; + pvr_get_isp_num_tiles_xy(dev_info, + job->samples, + aligned_width, + aligned_height, + &value.zlsextent_x_z, + &value.zlsextent_y_z); + value.zlsextent_x_z -= 1; + value.zlsextent_y_z -= 1; - if (job->depth_memlayout == PVR_MEMLAYOUT_TWIDDLED) { - value.loadtwiddled = true; - value.storetwiddled = true; - } + if (job->ds.memlayout == PVR_MEMLAYOUT_TWIDDLED) { + value.loadtwiddled = true; + value.storetwiddled = true; + } /* FIXME: This is suitable for the single depth format the driver * currently supports, but may need updating to handle other depth * formats. */ - assert(job->depth_vk_format == VK_FORMAT_D32_SFLOAT); + assert(job->ds.vk_format == VK_FORMAT_D32_SFLOAT); value.zloadformat = PVRX(CR_ZLOADFORMAT_TYPE_F32Z); value.zstoreformat = PVRX(CR_ZSTOREFORMAT_TYPE_F32Z); } stream_ptr += pvr_cmd_length(CR_ISP_ZLSCTL); pvr_csb_pack ((uint64_t *)stream_ptr, CR_ISP_ZLOAD_BASE, value) { - value.addr = job->depth_addr; + if (job->has_depth_attachment) + value.addr = job->ds.addr; } stream_ptr += pvr_cmd_length(CR_ISP_ZLOAD_BASE); pvr_csb_pack ((uint64_t *)stream_ptr, CR_ISP_STENCIL_LOAD_BASE, value) { - value.addr = job->stencil_addr; + if (job->has_stencil_attachment) { + value.addr = job->ds.addr; - /* FIXME: May need to set value.enable to true. */ + /* This should be set iff we only have a stencil attachment; all + * currently supported formats with a stencil component also contain + * depth. + */ + value.enable = false; + } } stream_ptr += pvr_cmd_length(CR_ISP_STENCIL_LOAD_BASE); @@ -1456,7 +1464,7 @@ static void pvr_frag_state_stream_init(struct pvr_render_ctx *ctx, * currently supports, but may need updating to handle other depth * formats. */ - value.value = fui(job->depth_clear_value); + value.value = fui(job->ds_clear_value.depth); } stream_ptr += pvr_cmd_length(CR_ISP_BGOBJDEPTH); @@ -1465,10 +1473,12 @@ static void pvr_frag_state_stream_init(struct pvr_render_ctx *ctx, value.mask = true; - /* FIXME: Hard code this for now as we don't currently support any - * stencil image formats. - */ - value.stencil = 0xFF; + if (job->has_stencil_attachment && + job->ds.vk_format != VK_FORMAT_D24_UNORM_S8_UINT) { + unreachable("Unsupported stencil format"); + } + + value.stencil = job->ds_clear_value.stencil & 0xFF; } stream_ptr += pvr_cmd_length(CR_ISP_BGOBJVALS); @@ -1484,6 +1494,14 @@ static void pvr_frag_state_stream_init(struct pvr_render_ctx *ctx, * is just one of them. */ value.process_empty_tiles = job->process_empty_tiles; + + /* For integer depth formats we'll convert the specified floating point + * depth bias values and specify them as integers. In this mode a depth + * bias factor of 1.0 equates to 1 ULP of increase to the depth value. + */ + value.dbias_is_int = PVR_HAS_ERN(dev_info, 42307) && + (job->ds.vk_format == VK_FORMAT_D16_UNORM || + job->ds.vk_format == VK_FORMAT_D24_UNORM_S8_UINT); } /* FIXME: When pvr_setup_tiles_in_flight() is refactored it might be * possible to fully pack CR_ISP_CTL above rather than having to OR in part @@ -1540,18 +1558,20 @@ static void pvr_frag_state_stream_init(struct pvr_render_ctx *ctx, if (PVR_HAS_FEATURE(dev_info, zls_subtile)) { pvr_csb_pack (stream_ptr, CR_ISP_ZLS_PIXELS, value) { - value.x = job->depth_stride - 1; - value.y = job->depth_height - 1; + if (job->has_depth_attachment) { + value.x = job->ds.stride - 1; + value.y = job->ds.height - 1; + } } stream_ptr += pvr_cmd_length(CR_ISP_ZLS_PIXELS); } /* zls_stride */ - *stream_ptr = job->depth_layer_size; + *stream_ptr = job->has_depth_attachment ? job->ds.layer_size : 0; stream_ptr++; /* sls_stride */ - *stream_ptr = job->depth_layer_size; + *stream_ptr = job->has_stencil_attachment ? job->ds.layer_size : 0; stream_ptr++; if (PVR_HAS_FEATURE(dev_info, gpu_multicore_support)) { @@ -1612,10 +1632,10 @@ pvr_render_job_ws_fragment_state_init(struct pvr_render_ctx *ctx, /* FIXME: move to its own function? */ state->flags = 0; - if (job->depth_addr.addr) + if (job->has_depth_attachment) state->flags |= PVR_WINSYS_FRAG_FLAG_DEPTH_BUFFER_PRESENT; - if (job->stencil_addr.addr) + if (job->has_stencil_attachment) state->flags |= PVR_WINSYS_FRAG_FLAG_STENCIL_BUFFER_PRESENT; if (job->disable_compute_overlap) diff --git a/src/imagination/vulkan/pvr_job_render.h b/src/imagination/vulkan/pvr_job_render.h index bb122931bdc..c7afd446bc6 100644 --- a/src/imagination/vulkan/pvr_job_render.h +++ b/src/imagination/vulkan/pvr_job_render.h @@ -52,6 +52,8 @@ struct pvr_render_job { bool enable_bg_tag; bool process_empty_tiles; bool get_vis_results; + bool has_depth_attachment; + bool has_stencil_attachment; uint32_t pds_pixel_event_data_offset; @@ -61,25 +63,31 @@ struct pvr_render_job { pvr_dev_addr_t depth_bias_table_addr; pvr_dev_addr_t scissor_table_addr; - pvr_dev_addr_t depth_addr; - uint32_t depth_stride; - uint32_t depth_height; - uint32_t depth_physical_width; - uint32_t depth_physical_height; - uint32_t depth_layer_size; - float depth_clear_value; - VkFormat depth_vk_format; - /* FIXME: This should be of type 'enum pvr_memlayout', but this is defined - * in pvr_private.h, which causes a circular include dependency. For now, - * treat it has a uint32_t. A couple of ways to possibly fix this: - * - * 1. Merge the contents of this header file into pvr_private.h. - * 2. Move 'enum pvr_memlayout' into it a new header that can be included - * by both this header and pvr_private.h. + /* Unless VK_KHR_dynamic_rendering or core 1.3 is supported, Vulkan does not + * allow for separate depth and stencil attachments. We don't bother storing + * separate parameters for them here (yet). If both has_depth_attachment and + * has_stencil_attachment are false, the contents are undefined. */ - uint32_t depth_memlayout; + struct pvr_ds_attachment { + pvr_dev_addr_t addr; + uint32_t stride; + uint32_t height; + uint32_t physical_width; + uint32_t physical_height; + uint32_t layer_size; + VkFormat vk_format; + /* FIXME: This should be of type 'enum pvr_memlayout', but this is defined + * in pvr_private.h, which causes a circular include dependency. For now, + * treat it as a uint32_t. A couple of ways to possibly fix this: + * + * 1. Merge the contents of this header file into pvr_private.h. + * 2. Move 'enum pvr_memlayout' into it a new header that can be + * included by both this header and pvr_private.h. + */ + uint32_t memlayout; + } ds; - pvr_dev_addr_t stencil_addr; + VkClearDepthStencilValue ds_clear_value; uint32_t samples;