pvr: add support for VK_KHR_dynamic_rendering

Signed-off-by: Luigi Santivetti <luigi.santivetti@imgtec.com>
Co-authored-by: Ella Stanforth <ella@igalia.com>
Acked-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38744>
This commit is contained in:
Luigi Santivetti 2025-11-13 10:54:49 +00:00 committed by Marge Bot
parent 5b752ccab0
commit 146364ab9f
13 changed files with 1699 additions and 106 deletions

View file

@ -1834,7 +1834,7 @@ static VkResult pvr_add_deferred_rta_clear(struct pvr_cmd_buffer *cmd_buffer,
struct pvr_render_pass_info *pass_info = &cmd_buffer->state.render_pass_info; struct pvr_render_pass_info *pass_info = &cmd_buffer->state.render_pass_info;
struct pvr_sub_cmd_gfx *sub_cmd = &cmd_buffer->state.current_sub_cmd->gfx; struct pvr_sub_cmd_gfx *sub_cmd = &cmd_buffer->state.current_sub_cmd->gfx;
const struct pvr_renderpass_hwsetup_render *hw_render = const struct pvr_renderpass_hwsetup_render *hw_render =
&pass_info->pass->hw_setup->renders[sub_cmd->hw_render_idx]; pvr_pass_info_get_hw_render(pass_info, sub_cmd->hw_render_idx);
const struct pvr_image_view *image_view; const struct pvr_image_view *image_view;
const struct pvr_image *image; const struct pvr_image *image;
uint32_t base_layer; uint32_t base_layer;
@ -1872,6 +1872,12 @@ static VkResult pvr_add_deferred_rta_clear(struct pvr_cmd_buffer *cmd_buffer,
assert(attachment->colorAttachment < hw_render->color_init_count); assert(attachment->colorAttachment < hw_render->color_init_count);
index = hw_render->color_init[attachment->colorAttachment].index; index = hw_render->color_init[attachment->colorAttachment].index;
image_view = pass_info->attachments[index];
} else if (cmd_buffer->state.current_sub_cmd->is_dynamic_render) {
const struct pvr_dynamic_render_info *dr_info = pass_info->dr_info;
const uint32_t index =
dr_info->color_attachments[attachment->colorAttachment].index_color;
image_view = pass_info->attachments[index]; image_view = pass_info->attachments[index];
} else { } else {
const struct pvr_renderpass_hwsetup_subpass *hw_pass = const struct pvr_renderpass_hwsetup_subpass *hw_pass =
@ -1938,19 +1944,25 @@ static void pvr_clear_attachments(struct pvr_cmd_buffer *cmd_buffer,
{ {
const struct pvr_render_pass *pass = cmd_buffer->state.render_pass_info.pass; const struct pvr_render_pass *pass = cmd_buffer->state.render_pass_info.pass;
struct pvr_render_pass_info *pass_info = &cmd_buffer->state.render_pass_info; struct pvr_render_pass_info *pass_info = &cmd_buffer->state.render_pass_info;
const struct pvr_renderpass_hwsetup_subpass *hw_pass =
pvr_get_hw_subpass(pass, pass_info->subpass_idx);
struct pvr_sub_cmd_gfx *sub_cmd = &cmd_buffer->state.current_sub_cmd->gfx; struct pvr_sub_cmd_gfx *sub_cmd = &cmd_buffer->state.current_sub_cmd->gfx;
struct pvr_device_info *dev_info = &cmd_buffer->device->pdevice->dev_info; struct pvr_device_info *dev_info = &cmd_buffer->device->pdevice->dev_info;
struct pvr_render_subpass *sub_pass = &pass->subpasses[hw_pass->index]; const struct pvr_renderpass_hwsetup_subpass *hw_pass;
bool vs_has_rt_id_output, multiview_enabled;
uint32_t vs_output_size_in_bytes; uint32_t vs_output_size_in_bytes;
bool vs_has_rt_id_output;
/* TODO: This function can be optimized so that most of the device memory /* TODO: This function can be optimized so that most of the device memory
* gets allocated together in one go and then filled as needed. There might * gets allocated together in one go and then filled as needed. There might
* also be opportunities to reuse pds code and data segments. * also be opportunities to reuse pds code and data segments.
*/ */
if (pass) {
hw_pass = pvr_get_hw_subpass(pass, pass_info->subpass_idx);
multiview_enabled = pass->multiview_enabled;
} else {
multiview_enabled = pass_info->dr_info->hw_render.multiview_enabled;
hw_pass = NULL;
}
assert(cmd_buffer->state.current_sub_cmd->type == PVR_SUB_CMD_TYPE_GRAPHICS); assert(cmd_buffer->state.current_sub_cmd->type == PVR_SUB_CMD_TYPE_GRAPHICS);
pvr_reset_graphics_dirty_state(cmd_buffer, false); pvr_reset_graphics_dirty_state(cmd_buffer, false);
@ -1959,7 +1971,7 @@ static void pvr_clear_attachments(struct pvr_cmd_buffer *cmd_buffer,
sub_cmd->empty_cmd = false; sub_cmd->empty_cmd = false;
vs_has_rt_id_output = pvr_clear_needs_rt_id_output(dev_info, vs_has_rt_id_output = pvr_clear_needs_rt_id_output(dev_info,
pass->multiview_enabled, multiview_enabled,
rect_count, rect_count,
rects); rects);
@ -1978,6 +1990,7 @@ static void pvr_clear_attachments(struct pvr_cmd_buffer *cmd_buffer,
if (attachment->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) { if (attachment->aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) {
uint32_t packed_clear_color[PVR_CLEAR_COLOR_ARRAY_SIZE]; uint32_t packed_clear_color[PVR_CLEAR_COLOR_ARRAY_SIZE];
struct pvr_renderpass_hwsetup_render *hw_render;
const struct usc_mrt_resource *mrt_resource; const struct usc_mrt_resource *mrt_resource;
uint32_t global_attachment_idx; uint32_t global_attachment_idx;
uint32_t local_attachment_idx; uint32_t local_attachment_idx;
@ -1985,19 +1998,31 @@ static void pvr_clear_attachments(struct pvr_cmd_buffer *cmd_buffer,
local_attachment_idx = attachment->colorAttachment; local_attachment_idx = attachment->colorAttachment;
assert(cmd_buffer->state.current_sub_cmd->is_dynamic_render ||
pass->hw_setup->render_count > 0);
hw_render =
pvr_pass_info_get_hw_render(&cmd_buffer->state.render_pass_info, 0);
/* TODO: verify that the hw_render if is_render_init is true is exclusive to
* a non dynamic rendering path.
*/
if (is_render_init) { if (is_render_init) {
struct pvr_renderpass_hwsetup_render *hw_render;
assert(pass->hw_setup->render_count > 0);
hw_render = &pass->hw_setup->renders[0];
mrt_resource = mrt_resource =
&hw_render->init_setup.mrt_resources[local_attachment_idx]; &hw_render->init_setup.mrt_resources[local_attachment_idx];
assert(local_attachment_idx < hw_render->color_init_count); assert(local_attachment_idx < hw_render->color_init_count);
global_attachment_idx = global_attachment_idx =
hw_render->color_init[local_attachment_idx].index; hw_render->color_init[local_attachment_idx].index;
} else if (cmd_buffer->state.current_sub_cmd->is_dynamic_render) {
const struct pvr_dynamic_render_info *dr_info = pass_info->dr_info;
mrt_resource =
&dr_info->mrt_setup->mrt_resources[local_attachment_idx];
global_attachment_idx =
dr_info->color_attachments[local_attachment_idx].index_color;
} else { } else {
struct pvr_render_subpass *sub_pass = &pass->subpasses[hw_pass->index];
mrt_resource = &hw_pass->setup.mrt_resources[local_attachment_idx]; mrt_resource = &hw_pass->setup.mrt_resources[local_attachment_idx];
assert(local_attachment_idx < sub_pass->color_count); assert(local_attachment_idx < sub_pass->color_count);
@ -2008,8 +2033,14 @@ static void pvr_clear_attachments(struct pvr_cmd_buffer *cmd_buffer,
if (global_attachment_idx == VK_ATTACHMENT_UNUSED) if (global_attachment_idx == VK_ATTACHMENT_UNUSED)
continue; continue;
if (cmd_buffer->state.current_sub_cmd->is_dynamic_render) {
const struct pvr_dynamic_render_info *dr_info = pass_info->dr_info;
format = dr_info->attachments[global_attachment_idx].vk_format;
} else {
assert(global_attachment_idx < pass->attachment_count); assert(global_attachment_idx < pass->attachment_count);
format = pass->attachments[global_attachment_idx].vk_format; format = pass->attachments[global_attachment_idx].vk_format;
}
assert(format != VK_FORMAT_UNDEFINED); assert(format != VK_FORMAT_UNDEFINED);
@ -2026,7 +2057,7 @@ static void pvr_clear_attachments(struct pvr_cmd_buffer *cmd_buffer,
vs_has_rt_id_output); vs_has_rt_id_output);
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
return; return;
} else if (hw_pass->z_replicate != -1 && } else if (pass && hw_pass->z_replicate != -1 &&
attachment->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) { attachment->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) {
const VkClearColorValue clear_color = { const VkClearColorValue clear_color = {
.float32 = { [0] = attachment->clearValue.depthStencil.depth, }, .float32 = { [0] = attachment->clearValue.depthStencil.depth, },
@ -2140,6 +2171,8 @@ static void pvr_clear_attachments(struct pvr_cmd_buffer *cmd_buffer,
if (!PVR_HAS_FEATURE(dev_info, gs_rta_support) && if (!PVR_HAS_FEATURE(dev_info, gs_rta_support) &&
(clear_rect->baseArrayLayer != 0 || clear_rect->layerCount > 1)) { (clear_rect->baseArrayLayer != 0 || clear_rect->layerCount > 1)) {
if (pass_info->attachments) {
result = pvr_add_deferred_rta_clear(cmd_buffer, result = pvr_add_deferred_rta_clear(cmd_buffer,
attachment, attachment,
clear_rect, clear_rect,
@ -2148,6 +2181,9 @@ static void pvr_clear_attachments(struct pvr_cmd_buffer *cmd_buffer,
return; return;
continue; continue;
} else {
pvr_finishme("incomplete support for deferred (emulated) RTA clears");
}
} }
/* TODO: Allocate all the buffers in one go before the loop, and add /* TODO: Allocate all the buffers in one go before the loop, and add

File diff suppressed because it is too large Load diff

View file

@ -19,6 +19,7 @@
#include "pvr_common.h" #include "pvr_common.h"
#include "pvr_framebuffer.h" #include "pvr_framebuffer.h"
#include "pvr_job_render.h" #include "pvr_job_render.h"
#include "pvr_hw_pass.h"
#include "pvr_types.h" #include "pvr_types.h"
struct pvr_pds_upload; struct pvr_pds_upload;
@ -113,7 +114,30 @@ struct pvr_transfer_cmd {
struct pvr_cmd_buffer *cmd_buffer; struct pvr_cmd_buffer *cmd_buffer;
}; };
struct pvr_color_attachment_output_map {
uint32_t index_color;
uint32_t index_resolve;
};
struct pvr_dynamic_render_info {
/* Inputs */
struct pvr_render_pass_attachment *attachments;
uint32_t attachment_count;
/* Outputs */
struct pvr_color_attachment_output_map *color_attachments;
uint32_t color_attachment_count;
struct usc_mrt_setup *mrt_setup;
struct pvr_renderpass_hwsetup_render hw_render;
};
struct pvr_sub_cmd_gfx { struct pvr_sub_cmd_gfx {
struct pvr_dynamic_render_info *dr_info;
struct pvr_renderpass_hwsetup_render *hw_render;
uint32_t attachment_count;
const struct pvr_render_state *rstate; const struct pvr_render_state *rstate;
struct pvr_render_job job; struct pvr_render_job job;
@ -249,11 +273,16 @@ struct pvr_sub_cmd {
enum pvr_sub_cmd_type type; enum pvr_sub_cmd_type type;
struct {
/* True if the sub_cmd is owned by this command buffer. False if taken from /* True if the sub_cmd is owned by this command buffer. False if taken from
* a secondary command buffer, in that case we are not supposed to free any * a secondary command buffer, in that case we are not supposed to free any
* resources associated with the sub_cmd. * resources associated with the sub_cmd.
*/ */
bool owned; bool owned : 1;
bool is_dynamic_render : 1;
bool is_suspend : 1;
bool is_resume : 1;
};
union { union {
struct pvr_sub_cmd_gfx gfx; struct pvr_sub_cmd_gfx gfx;
@ -267,6 +296,8 @@ struct pvr_render_pass_info {
const struct pvr_render_pass *pass; const struct pvr_render_pass *pass;
struct pvr_framebuffer *framebuffer; struct pvr_framebuffer *framebuffer;
struct pvr_dynamic_render_info *dr_info;
struct pvr_renderpass_hwsetup_render *hw_render;
struct pvr_render_state *rstate; struct pvr_render_state *rstate;
uint32_t attachment_count; uint32_t attachment_count;
@ -274,6 +305,7 @@ struct pvr_render_pass_info {
uint32_t subpass_idx; uint32_t subpass_idx;
uint32_t current_hw_subpass; uint32_t current_hw_subpass;
uint32_t sample_count;
VkRect2D render_area; VkRect2D render_area;
@ -285,6 +317,10 @@ struct pvr_render_pass_info {
bool process_empty_tiles; bool process_empty_tiles;
bool enable_bg_tag; bool enable_bg_tag;
uint32_t isp_userpass; uint32_t isp_userpass;
bool dynamic_render;
bool suspend;
bool resume;
}; };
struct pvr_ppp_state { struct pvr_ppp_state {
@ -627,4 +663,8 @@ void pvr_calculate_vertex_cam_size(const struct pvr_device_info *dev_info,
const struct pvr_renderpass_hwsetup_subpass * const struct pvr_renderpass_hwsetup_subpass *
pvr_get_hw_subpass(const struct pvr_render_pass *pass, const uint32_t subpass); pvr_get_hw_subpass(const struct pvr_render_pass *pass, const uint32_t subpass);
struct pvr_renderpass_hwsetup_render *
pvr_pass_info_get_hw_render(const struct pvr_render_pass_info *render_pass_info,
uint32_t idx);
#endif /* PVR_CMD_BUFFER_H */ #endif /* PVR_CMD_BUFFER_H */

View file

@ -991,6 +991,9 @@ pvr_create_device(struct pvr_physical_device *pdevice,
device->global_cmd_buffer_submit_count = 0; device->global_cmd_buffer_submit_count = 0;
device->global_queue_present_count = 0; device->global_queue_present_count = 0;
simple_mtx_init(&device->rs_mtx, mtx_plain);
list_inithead(&device->render_states);
*pDevice = pvr_device_to_handle(device); *pDevice = pvr_device_to_handle(device);
return VK_SUCCESS; return VK_SUCCESS;
@ -1057,6 +1060,36 @@ err_out:
return result; return result;
} }
void pvr_rstate_entry_add(struct pvr_device *device,
struct pvr_render_state *rstate)
{
simple_mtx_lock(&device->rs_mtx);
list_addtail(&rstate->link, &device->render_states);
simple_mtx_unlock(&device->rs_mtx);
}
void pvr_rstate_entry_remove(struct pvr_device *device,
const struct pvr_render_state *rstate)
{
simple_mtx_lock(&device->rs_mtx);
assert(rstate);
list_for_each_entry_safe (struct pvr_render_state,
entry,
&device->render_states,
link) {
if (entry != rstate)
continue;
pvr_render_state_cleanup(device, rstate);
list_del(&entry->link);
vk_free(&device->vk.alloc, entry);
}
simple_mtx_unlock(&device->rs_mtx);
}
void void
pvr_destroy_device(struct pvr_device *device, pvr_destroy_device(struct pvr_device *device,
const VkAllocationCallbacks *pAllocator) const VkAllocationCallbacks *pAllocator)
@ -1064,6 +1097,19 @@ pvr_destroy_device(struct pvr_device *device,
if (!device) if (!device)
return; return;
simple_mtx_lock(&device->rs_mtx);
list_for_each_entry_safe (struct pvr_render_state,
rstate,
&device->render_states,
link) {
pvr_render_state_cleanup(device, rstate);
list_del(&rstate->link);
vk_free(&device->vk.alloc, rstate);
}
simple_mtx_unlock(&device->rs_mtx);
simple_mtx_destroy(&device->rs_mtx);
pvr_border_color_table_finish(device); pvr_border_color_table_finish(device);
pvr_robustness_buffer_finish(device); pvr_robustness_buffer_finish(device);
pvr_spm_finish_scratch_buffer_store(device); pvr_spm_finish_scratch_buffer_store(device);
@ -1929,6 +1975,7 @@ void pvr_render_state_cleanup(struct pvr_device *device,
pvr_render_targets_fini(rstate->render_targets, pvr_render_targets_fini(rstate->render_targets,
rstate->render_targets_count); rstate->render_targets_count);
pvr_bo_suballoc_free(rstate->ppp_state_bo); pvr_bo_suballoc_free(rstate->ppp_state_bo);
vk_free(&device->vk.alloc, rstate->render_targets);
} }
VkResult pvr_render_state_setup( VkResult pvr_render_state_setup(
@ -2128,6 +2175,7 @@ void pvr_DestroyFramebuffer(VkDevice _device,
return; return;
pvr_render_state_cleanup(device, framebuffer->rstate); pvr_render_state_cleanup(device, framebuffer->rstate);
/* the render state is freed with the framebuffer */
vk_object_base_finish(&framebuffer->base); vk_object_base_finish(&framebuffer->base);
vk_free2(&device->vk.alloc, pAllocator, framebuffer); vk_free2(&device->vk.alloc, pAllocator, framebuffer);

View file

@ -142,6 +142,9 @@ struct pvr_device {
struct vk_sync *presignaled_sync; struct vk_sync *presignaled_sync;
struct pvr_border_color_table *border_color_table; struct pvr_border_color_table *border_color_table;
simple_mtx_t rs_mtx;
struct list_head render_states;
}; };
struct pvr_device_memory { struct pvr_device_memory {
@ -221,4 +224,10 @@ VkResult pvr_gpu_upload_usc(struct pvr_device *device,
uint64_t code_alignment, uint64_t code_alignment,
struct pvr_suballoc_bo **const pvr_bo_out); struct pvr_suballoc_bo **const pvr_bo_out);
void pvr_rstate_entry_add(struct pvr_device *device,
struct pvr_render_state *rstate);
void pvr_rstate_entry_remove(struct pvr_device *device,
const struct pvr_render_state *rstate);
#endif /* PVR_DEVICE_H */ #endif /* PVR_DEVICE_H */

View file

@ -23,6 +23,8 @@ struct pvr_render_target {
}; };
struct pvr_render_state { struct pvr_render_state {
struct list_head link;
uint32_t width; uint32_t width;
uint32_t height; uint32_t height;
uint32_t layers; uint32_t layers;
@ -51,29 +53,7 @@ struct pvr_framebuffer {
uint32_t attachment_count; uint32_t attachment_count;
struct pvr_image_view **attachments; struct pvr_image_view **attachments;
#if 0
/* Saved information from pCreateInfo. */
uint32_t width;
uint32_t height;
uint32_t layers;
/* Derived and other state. */
struct pvr_suballoc_bo *ppp_state_bo;
/* PPP state size in dwords. */
size_t ppp_state_size;
uint32_t render_targets_count;
struct pvr_render_target *render_targets;
struct pvr_spm_scratch_buffer *scratch_buffer;
uint32_t render_count;
struct pvr_spm_eot_state *spm_eot_state_per_render;
struct pvr_spm_bgobj_state *spm_bgobj_state_per_render;
#else
struct pvr_render_state *rstate; struct pvr_render_state *rstate;
#endif
}; };
struct pvr_device; struct pvr_device;

View file

@ -189,6 +189,8 @@ struct pvr_renderpass_hwsetup_render {
bool requires_frag_pr; bool requires_frag_pr;
bool multiview_enabled;
/* View mask for multiview. */ /* View mask for multiview. */
uint32_t view_mask; uint32_t view_mask;

View file

@ -8,15 +8,20 @@
#include "vk_log.h" #include "vk_log.h"
#include "pvr_cmd_buffer.h"
#include "pvr_csb.h" #include "pvr_csb.h"
#include "pvr_device.h" #include "pvr_device.h"
#include "pvr_formats.h" #include "pvr_formats.h"
#include "pvr_image.h"
#include "pvr_mrt.h"
#include "pvr_pass.h"
#include "pvr_physical_device.h" #include "pvr_physical_device.h"
#include "hwdef/rogue_hw_utils.h" #include "hwdef/rogue_hw_utils.h"
#include "util/macros.h" #include "util/macros.h"
#include "vulkan/vulkan_core.h"
#include "pvr_mrt.h" #include "vulkan/runtime/vk_graphics_state.h"
#include "vulkan/runtime/vk_image.h"
/* Which parts of the output registers/a tile buffer are currently allocated. */ /* Which parts of the output registers/a tile buffer are currently allocated. */
struct pvr_mrt_alloc_mask { struct pvr_mrt_alloc_mask {
@ -237,6 +242,246 @@ pvr_destroy_mrt_setup(const struct pvr_device *device,
vk_free(&device->vk.alloc, setup->mrt_resources); vk_free(&device->vk.alloc, setup->mrt_resources);
} }
static bool
pvr_rendering_info_needs_load(const struct pvr_dynamic_render_info *dr_info)
{
for (unsigned i = 0; i < dr_info->hw_render.color_init_count; i++) {
const uint32_t index = dr_info->hw_render.color_init[i].index;
if (index == VK_ATTACHMENT_UNUSED)
continue;
const VkAttachmentLoadOp op = dr_info->hw_render.color_init[i].op;
if (op == VK_ATTACHMENT_LOAD_OP_LOAD || op == VK_ATTACHMENT_LOAD_OP_CLEAR)
return true;
}
return false;
}
static VkResult pvr_mrt_load_op_init(struct pvr_device *device,
const VkAllocationCallbacks *alloc,
const struct pvr_render_pass_info *rp_info,
struct pvr_load_op *load_op,
uint32_t view_idx)
{
const struct pvr_dynamic_render_info *dr_info = rp_info->dr_info;
VkResult result;
load_op->clears_loads_state.depth_clear_to_reg = PVR_NO_DEPTH_CLEAR_TO_REG;
assert(dr_info->hw_render.color_init_count <=
PVR_LOAD_OP_CLEARS_LOADS_MAX_RTS);
for (unsigned i = 0; i < dr_info->hw_render.color_init_count; i++) {
const struct pvr_renderpass_colorinit *color_init =
&dr_info->hw_render.color_init[i];
const struct pvr_image *image;
assert(color_init->index < rp_info->attachment_count);
load_op->clears_loads_state.dest_vk_format[i] =
rp_info->attachments[color_init->index]->vk.view_format;
image = pvr_image_view_get_image(rp_info->attachments[color_init->index]);
if (image->vk.samples > VK_SAMPLE_COUNT_1_BIT)
load_op->clears_loads_state.unresolved_msaa_mask |= BITFIELD_BIT(i);
switch (color_init->op) {
case VK_ATTACHMENT_LOAD_OP_CLEAR:
load_op->clears_loads_state.rt_clear_mask |= BITFIELD_BIT(i);
break;
case VK_ATTACHMENT_LOAD_OP_LOAD:
load_op->clears_loads_state.rt_load_mask |= BITFIELD_BIT(i);
break;
case VK_ATTACHMENT_LOAD_OP_DONT_CARE:
case VK_ATTACHMENT_LOAD_OP_NONE:
break;
default:
UNREACHABLE("unsupported loadOp");
}
}
load_op->clears_loads_state.mrt_setup = &dr_info->hw_render.init_setup;
result = pvr_load_op_shader_generate(device, alloc, load_op);
if (result != VK_SUCCESS) {
vk_free2(&device->vk.alloc, alloc, load_op);
return result;
}
load_op->view_indices[0] = view_idx;
load_op->view_count = 1;
load_op->is_hw_object = true;
load_op->hw_render = &dr_info->hw_render;
return VK_SUCCESS;
}
static void pvr_load_op_fini(struct pvr_load_op *load_op)
{
pvr_bo_suballoc_free(load_op->pds_tex_state_prog.pvr_bo);
pvr_bo_suballoc_free(load_op->pds_frag_prog.pvr_bo);
pvr_bo_suballoc_free(load_op->usc_frag_prog_bo);
}
static void pvr_load_op_destroy(struct pvr_device *device,
const VkAllocationCallbacks *allocator,
struct pvr_load_op *load_op)
{
pvr_load_op_fini(load_op);
vk_free2(&device->vk.alloc, allocator, load_op);
}
void
pvr_mrt_load_op_state_cleanup(const struct pvr_device *device,
const VkAllocationCallbacks *alloc,
struct pvr_load_op_state *state)
{
if (!state)
return;
while (state->load_op_count--) {
const uint32_t load_op_idx = state->load_op_count;
struct pvr_load_op *load_op = &state->load_ops[load_op_idx];
pvr_load_op_fini(load_op);
}
vk_free2(&device->vk.alloc, alloc, state);
}
static VkResult
pvr_mrt_load_op_state_create(struct pvr_device *device,
const VkAllocationCallbacks *alloc,
const struct pvr_render_pass_info *rp_info,
struct pvr_load_op_state **state)
{
const struct pvr_dynamic_render_info *dr_info = rp_info->dr_info;
const uint32_t view_count = util_bitcount(dr_info->hw_render.view_mask);
struct pvr_load_op_state *load_op_state;
struct pvr_load_op *load_ops;
VkResult result;
VK_MULTIALLOC(ma);
vk_multialloc_add(&ma, &load_op_state, __typeof__(*load_op_state), 1);
vk_multialloc_add(&ma, &load_ops, __typeof__(*load_ops), view_count);
if (!vk_multialloc_zalloc(&ma, alloc, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE))
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
load_op_state->load_ops = load_ops;
u_foreach_bit (view_idx, dr_info->hw_render.view_mask) {
struct pvr_load_op *const load_op =
&load_op_state->load_ops[load_op_state->load_op_count];
result = pvr_mrt_load_op_init(device, alloc, rp_info, load_op, view_idx);
if (result != VK_SUCCESS)
goto err_load_op_state_cleanup;
load_op_state->load_op_count++;
}
*state = load_op_state;
return VK_SUCCESS;
err_load_op_state_cleanup:
pvr_mrt_load_op_state_cleanup(device, alloc, load_op_state);
return result;
}
/* TODO: Can we gaurantee that if we have at least one render target there will
* be a render target allocated as a REG?
*/
static inline bool pvr_needs_output_register_writes(
const struct usc_mrt_setup *setup)
{
for (uint32_t i = 0; i < setup->num_render_targets; i++) {
struct usc_mrt_resource *mrt_resource =
&setup->mrt_resources[i];
if (mrt_resource->type == USC_MRT_RESOURCE_TYPE_OUTPUT_REG)
return true;
}
return false;
}
static inline VkResult pvr_mrt_add_missing_output_register_write(
struct usc_mrt_setup *setup,
const VkAllocationCallbacks *alloc)
{
const uint32_t last = setup->num_render_targets;
struct usc_mrt_resource *mrt_resources;
if (pvr_needs_output_register_writes(setup))
return VK_SUCCESS;
setup->num_render_targets++;
mrt_resources = vk_realloc(alloc,
setup->mrt_resources,
setup->num_render_targets *
sizeof(*mrt_resources),
8U,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!mrt_resources)
return VK_ERROR_OUT_OF_HOST_MEMORY;
setup->mrt_resources = mrt_resources;
mrt_resources[last].type = USC_MRT_RESOURCE_TYPE_OUTPUT_REG;
mrt_resources[last].reg.output_reg = 0U;
mrt_resources[last].reg.offset = 0U;
mrt_resources[last].intermediate_size = 4U;
mrt_resources[last].mrt_desc.intermediate_size = 4U;
mrt_resources[last].mrt_desc.priority = 0U;
mrt_resources[last].mrt_desc.valid_mask[0U] = ~0;
mrt_resources[last].mrt_desc.valid_mask[1U] = ~0;
mrt_resources[last].mrt_desc.valid_mask[2U] = ~0;
mrt_resources[last].mrt_desc.valid_mask[3U] = ~0;
return VK_SUCCESS;
}
VkResult pvr_mrt_load_ops_setup(struct pvr_cmd_buffer *cmd_buffer,
const VkAllocationCallbacks *alloc,
struct pvr_load_op_state **load_op_state)
{
const struct pvr_cmd_buffer_state *state = &cmd_buffer->state;
const struct pvr_dynamic_render_info *dr_info =
state->render_pass_info.dr_info;
struct pvr_device *device = cmd_buffer->device;
VkResult result = VK_SUCCESS;
if (dr_info->mrt_setup->num_tile_buffers) {
result = pvr_device_tile_buffer_ensure_cap(
device,
dr_info->mrt_setup->num_tile_buffers);
if (result != VK_SUCCESS)
return result;
}
if (!pvr_rendering_info_needs_load(dr_info))
return VK_SUCCESS;
result =
pvr_mrt_add_missing_output_register_write(dr_info->mrt_setup,
alloc);
if (result != VK_SUCCESS)
return result;
result = pvr_mrt_load_op_state_create(device,
alloc,
&state->render_pass_info,
load_op_state);
return result;
}
VkResult pvr_pds_unitex_state_program_create_and_upload( VkResult pvr_pds_unitex_state_program_create_and_upload(
struct pvr_device *device, struct pvr_device *device,
const VkAllocationCallbacks *allocator, const VkAllocationCallbacks *allocator,
@ -413,3 +658,4 @@ err_free_usc_frag_prog_bo:
return result; return result;
} }

View file

@ -189,4 +189,15 @@ struct pvr_load_op_state {
struct pvr_load_op *load_ops; struct pvr_load_op *load_ops;
}; };
struct pvr_dynamic_render_info;
struct pvr_cmd_buffer;
VkResult pvr_mrt_load_ops_setup(struct pvr_cmd_buffer *cmd_buffer,
const VkAllocationCallbacks *alloc,
struct pvr_load_op_state **state);
void
pvr_mrt_load_op_state_cleanup(const struct pvr_device *device,
const VkAllocationCallbacks *alloc,
struct pvr_load_op_state *state);
#endif #endif

View file

@ -26,10 +26,14 @@ struct pvr_render_pass_attachment {
VkAttachmentStoreOp store_op; VkAttachmentStoreOp store_op;
VkResolveModeFlagBits resolve_mode;
VkAttachmentLoadOp stencil_load_op; VkAttachmentLoadOp stencil_load_op;
VkAttachmentStoreOp stencil_store_op; VkAttachmentStoreOp stencil_store_op;
VkResolveModeFlagBits stencil_resolve_mode;
VkFormat vk_format; VkFormat vk_format;
uint32_t sample_count; uint32_t sample_count;
VkImageLayout initial_layout; VkImageLayout initial_layout;
@ -39,7 +43,11 @@ struct pvr_render_pass_attachment {
/* Can this surface be resolved by the PBE. */ /* Can this surface be resolved by the PBE. */
bool is_pbe_downscalable; bool is_pbe_downscalable;
bool is_depth;
bool is_stencil;
bool need_eot;
uint32_t resolve_target;
uint32_t index; uint32_t index;
}; };

View file

@ -410,7 +410,7 @@ pvr_cmd_buffer_state_get_view_count(const struct pvr_cmd_buffer_state *state)
const struct pvr_sub_cmd_gfx *gfx_sub_cmd = &state->current_sub_cmd->gfx; const struct pvr_sub_cmd_gfx *gfx_sub_cmd = &state->current_sub_cmd->gfx;
const uint32_t hw_render_idx = gfx_sub_cmd->hw_render_idx; const uint32_t hw_render_idx = gfx_sub_cmd->hw_render_idx;
const struct pvr_renderpass_hwsetup_render *hw_render = const struct pvr_renderpass_hwsetup_render *hw_render =
&render_pass_info->pass->hw_setup->renders[hw_render_idx]; pvr_pass_info_get_hw_render(render_pass_info, hw_render_idx);
const uint32_t view_count = util_bitcount(hw_render->view_mask); const uint32_t view_count = util_bitcount(hw_render->view_mask);
assert(state->current_sub_cmd->type == PVR_SUB_CMD_TYPE_GRAPHICS); assert(state->current_sub_cmd->type == PVR_SUB_CMD_TYPE_GRAPHICS);

View file

@ -37,6 +37,11 @@ struct pvr_query_pool {
struct pvr_query_info { struct pvr_query_info {
enum pvr_query_type type; enum pvr_query_type type;
struct {
bool is_dynamic_render : 1;
bool is_suspend : 1;
};
union { union {
struct { struct {
uint32_t num_query_indices; uint32_t num_query_indices;

View file

@ -412,6 +412,9 @@ VkResult pvr_add_query_program(struct pvr_cmd_buffer *cmd_buffer,
if (result != VK_SUCCESS) if (result != VK_SUCCESS)
return result; return result;
cmd_buffer->state.current_sub_cmd->is_dynamic_render = query_info->is_dynamic_render;
cmd_buffer->state.current_sub_cmd->is_suspend = query_info->is_suspend;
switch (query_info->type) { switch (query_info->type) {
case PVR_QUERY_TYPE_AVAILABILITY_WRITE: case PVR_QUERY_TYPE_AVAILABILITY_WRITE:
/* Adds a compute shader (fenced on the last 3D) that writes a non-zero /* Adds a compute shader (fenced on the last 3D) that writes a non-zero