pvr: Add stencil support in render job setup

The implementation here assumes separate depth and stencil attachments
are not possible, as they are in Vulkan without VK_KHR_dynamic_rendering
and before core 1.3.

Signed-off-by: Matt Coster <matt.coster@imgtec.com>
Reviewed-by: Karmjit Mahil <Karmjit.Mahil@imgtec.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20160>
This commit is contained in:
Matt Coster 2022-11-28 15:00:03 +00:00 committed by Marge Bot
parent ff928d9567
commit 6404eee627
3 changed files with 108 additions and 95 deletions

View file

@ -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) {

View file

@ -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)

View file

@ -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;