Module: Mesa Branch: main Commit: ca04882117f3d1a8924f6052ee3b5f15d04df885 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=ca04882117f3d1a8924f6052ee3b5f15d04df885
Author: Karmjit Mahil <[email protected]> Date: Mon Jan 9 16:04:16 2023 +0000 pvr: Setup SPM EOT state On entering SPM we need to store the tile data for the current render into the scratch buffer so we need to setup an EOT program to do so. Signed-off-by: Karmjit Mahil <[email protected]> Reviewed-by: Frank Binns <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21386> --- src/imagination/vulkan/pvr_cmd_buffer.c | 4 + src/imagination/vulkan/pvr_device.c | 26 ++ src/imagination/vulkan/pvr_hw_pass.c | 2 +- src/imagination/vulkan/pvr_hw_pass.h | 2 + src/imagination/vulkan/pvr_private.h | 3 + src/imagination/vulkan/pvr_spm.c | 428 ++++++++++++++++++++++++++++++++ src/imagination/vulkan/pvr_spm.h | 31 +++ 7 files changed, 495 insertions(+), 1 deletion(-) diff --git a/src/imagination/vulkan/pvr_cmd_buffer.c b/src/imagination/vulkan/pvr_cmd_buffer.c index 95f251d92c0..3ff0a3d5c66 100644 --- a/src/imagination/vulkan/pvr_cmd_buffer.c +++ b/src/imagination/vulkan/pvr_cmd_buffer.c @@ -1370,6 +1370,10 @@ static VkResult pvr_sub_cmd_gfx_job_init(const struct pvr_device_info *dev_info, * case SPM is hit so set the flag unconditionally. */ job->requires_spm_scratch_buffer = true; + /* FIXME: We should be using the SPM PBE reg words and the SPM EOT PDS data + * section instead of the regular, but for now we don't have an actual + * SPM EOT USC shader so that would cause problems. + */ return VK_SUCCESS; } diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c index 80f3186d876..180e955ecbe 100644 --- a/src/imagination/vulkan/pvr_device.c +++ b/src/imagination/vulkan/pvr_device.c @@ -2642,6 +2642,7 @@ VkResult pvr_CreateFramebuffer(VkDevice _device, { PVR_FROM_HANDLE(pvr_render_pass, pass, pCreateInfo->renderPass); PVR_FROM_HANDLE(pvr_device, device, _device); + struct pvr_spm_eot_state *spm_eot_state_per_render; struct pvr_render_target *render_targets; struct pvr_framebuffer *framebuffer; struct pvr_image_view **attachments; @@ -2664,6 +2665,10 @@ VkResult pvr_CreateFramebuffer(VkDevice _device, &render_targets, __typeof__(*render_targets), render_targets_count); + vk_multialloc_add(&ma, + &spm_eot_state_per_render, + __typeof__(*spm_eot_state_per_render), + pass->hw_setup->render_count); if (!vk_multialloc_zalloc2(&ma, &device->vk.alloc, @@ -2709,6 +2714,22 @@ VkResult pvr_CreateFramebuffer(VkDevice _device, if (result != VK_SUCCESS) goto err_finish_render_targets; + for (uint32_t i = 0; i < pass->hw_setup->render_count; i++) { + result = pvr_spm_init_eot_state(device, + &spm_eot_state_per_render[i], + framebuffer, + &pass->hw_setup->renders[i]); + if (result != VK_SUCCESS) { + for (uint32_t j = 0; j < i; j++) + pvr_spm_finish_eot_state(device, &spm_eot_state_per_render[j]); + + goto err_finish_render_targets; + } + } + + framebuffer->spm_eot_state_per_render = spm_eot_state_per_render; + framebuffer->spm_eot_state_count = pass->hw_setup->render_count; + *pFramebuffer = pvr_framebuffer_to_handle(framebuffer); return VK_SUCCESS; @@ -2736,6 +2757,11 @@ void pvr_DestroyFramebuffer(VkDevice _device, if (!framebuffer) return; + for (uint32_t i = 0; i < framebuffer->spm_eot_state_count; i++) { + pvr_spm_finish_eot_state(device, + &framebuffer->spm_eot_state_per_render[i]); + } + pvr_spm_scratch_buffer_release(device, framebuffer->scratch_buffer); pvr_render_targets_fini(framebuffer->render_targets, framebuffer->render_targets_count); diff --git a/src/imagination/vulkan/pvr_hw_pass.c b/src/imagination/vulkan/pvr_hw_pass.c index ba0ca947887..ee6dc661574 100644 --- a/src/imagination/vulkan/pvr_hw_pass.c +++ b/src/imagination/vulkan/pvr_hw_pass.c @@ -342,7 +342,7 @@ pvr_get_tile_buffer_size_per_core(const struct pvr_device *device) /** * Gets the amount of memory to allocate for a tile buffer on the current BVNC. */ -static uint32_t pvr_get_tile_buffer_size(const struct pvr_device *device) +uint32_t pvr_get_tile_buffer_size(const struct pvr_device *device) { /* On a multicore system duplicate the buffer for each core. */ return pvr_get_tile_buffer_size_per_core(device) * diff --git a/src/imagination/vulkan/pvr_hw_pass.h b/src/imagination/vulkan/pvr_hw_pass.h index 090444fba96..ca8d47d865e 100644 --- a/src/imagination/vulkan/pvr_hw_pass.h +++ b/src/imagination/vulkan/pvr_hw_pass.h @@ -293,4 +293,6 @@ VkResult pvr_create_renderpass_hwsetup( void pvr_destroy_renderpass_hwsetup(const VkAllocationCallbacks *alloc, struct pvr_renderpass_hwsetup *hw_setup); +uint32_t pvr_get_tile_buffer_size(const struct pvr_device *device); + #endif /* PVR_HW_PASS_H */ diff --git a/src/imagination/vulkan/pvr_private.h b/src/imagination/vulkan/pvr_private.h index aac5380422c..8dfbbae644e 100644 --- a/src/imagination/vulkan/pvr_private.h +++ b/src/imagination/vulkan/pvr_private.h @@ -991,6 +991,9 @@ struct pvr_framebuffer { struct pvr_render_target *render_targets; struct pvr_spm_scratch_buffer *scratch_buffer; + + uint32_t spm_eot_state_count; + struct pvr_spm_eot_state *spm_eot_state_per_render; }; struct pvr_render_pass_attachment { diff --git a/src/imagination/vulkan/pvr_spm.c b/src/imagination/vulkan/pvr_spm.c index a0d096ebb29..b394baf7231 100644 --- a/src/imagination/vulkan/pvr_spm.c +++ b/src/imagination/vulkan/pvr_spm.c @@ -29,12 +29,19 @@ #include "c11/threads.h" #include "hwdef/rogue_hw_utils.h" #include "pvr_bo.h" +#include "pvr_csb.h" +#include "pvr_csb_enum_helpers.h" #include "pvr_device_info.h" +#include "pvr_hw_pass.h" +#include "pvr_job_common.h" #include "pvr_pds.h" #include "pvr_private.h" #include "pvr_shader_factory.h" #include "pvr_spm.h" #include "pvr_static_shaders.h" +#include "pvr_types.h" +#include "util/bitscan.h" +#include "util/macros.h" #include "util/simple_mtx.h" #include "util/u_atomic.h" #include "vk_alloc.h" @@ -393,3 +400,424 @@ void pvr_device_finish_spm_load_state(struct pvr_device *device) pvr_bo_free(device, device->spm_load_state.pds_programs); pvr_bo_free(device, device->spm_load_state.usc_programs); } + +static inline enum PVRX(PBESTATE_PACKMODE) + pvr_spm_get_pbe_packmode(uint32_t dword_count) +{ + switch (dword_count) { + case 1: + return PVRX(PBESTATE_PACKMODE_U32); + case 2: + return PVRX(PBESTATE_PACKMODE_U32U32); + case 3: + return PVRX(PBESTATE_PACKMODE_U32U32U32); + case 4: + return PVRX(PBESTATE_PACKMODE_U32U32U32U32); + default: + unreachable("Unsupported dword_count"); + } +} + +/** + * \brief Sets up PBE registers and state values per a single render output. + * + * On a PR we want to store tile data to the scratch buffer so we need to + * setup the Pixel Back End (PBE) to write the data to the scratch buffer. This + * function sets up the PBE state and register values required to do so, for a + * single resource whether it be a tile buffer or the output register set. + * + * \return Size of the data saved into the scratch buffer in bytes. + */ +static uint64_t pvr_spm_setup_pbe_state( + const struct pvr_device_info *dev_info, + const VkExtent2D *framebuffer_size, + uint32_t dword_count, + enum pvr_pbe_source_start_pos source_start, + uint32_t sample_count, + pvr_dev_addr_t scratch_buffer_addr, + uint32_t pbe_state_words_out[static const ROGUE_NUM_PBESTATE_STATE_WORDS], + uint64_t pbe_reg_words_out[static const ROGUE_NUM_PBESTATE_REG_WORDS]) +{ + const uint32_t stride = + ALIGN_POT(framebuffer_size->width, + PVRX(PBESTATE_REG_WORD0_LINESTRIDE_UNIT_SIZE)); + + const struct pvr_pbe_surf_params surface_params = { + .swizzle = { + [0] = PIPE_SWIZZLE_X, + [1] = PIPE_SWIZZLE_Y, + [2] = PIPE_SWIZZLE_Z, + [3] = PIPE_SWIZZLE_W, + }, + .pbe_packmode = pvr_spm_get_pbe_packmode(dword_count), + .source_format = PVRX(PBESTATE_SOURCE_FORMAT_8_PER_CHANNEL), + .addr = scratch_buffer_addr, + .mem_layout = PVR_MEMLAYOUT_LINEAR, + .stride = stride, + }; + const struct pvr_pbe_render_params render_params = { + .max_x_clip = framebuffer_size->width - 1, + .max_y_clip = framebuffer_size->height - 1, + .source_start = source_start, + }; + + pvr_pbe_pack_state(dev_info, + &surface_params, + &render_params, + pbe_state_words_out, + pbe_reg_words_out); + + return (uint64_t)stride * framebuffer_size->height * sample_count * + dword_count * sizeof(uint32_t); +} + +static inline void pvr_set_pbe_all_valid_mask(struct usc_mrt_desc *desc) +{ + for (uint32_t i = 0; i < ARRAY_SIZE(desc->valid_mask); i++) + desc->valid_mask[i] = ~0; +} + +#define PVR_DEV_ADDR_ADVANCE(_addr, _offset) \ + _addr = PVR_DEV_ADDR_OFFSET(_addr, _offset) + +/** + * \brief Sets up PBE registers, PBE state values and MRT data per a single + * render output requiring 8 dwords to be written. + * + * On a PR we want to store tile data to the scratch buffer so we need to + * setup the Pixel Back End (PBE) to write the data to the scratch buffer, as + * well as setup the Multiple Render Target (MRT) info so the compiler knows + * what data needs to be stored (output regs or tile buffers) and generate the + * appropriate EOT shader. + * + * This function is only available for devices with the eight_output_registers + * feature thus requiring 8 dwords to be stored. + * + * \return Size of the data saved into the scratch buffer in bytes. + */ +static uint64_t pvr_spm_setup_pbe_eight_dword_write( + const struct pvr_device_info *dev_info, + const VkExtent2D *framebuffer_size, + uint32_t sample_count, + enum usc_mrt_resource_type source_type, + uint32_t tile_buffer_idx, + pvr_dev_addr_t scratch_buffer_addr, + uint32_t pbe_state_word_0_out[static const ROGUE_NUM_PBESTATE_STATE_WORDS], + uint32_t pbe_state_word_1_out[static const ROGUE_NUM_PBESTATE_STATE_WORDS], + uint64_t pbe_reg_word_0_out[static const ROGUE_NUM_PBESTATE_REG_WORDS], + uint64_t pbe_reg_word_1_out[static const ROGUE_NUM_PBESTATE_REG_WORDS], + struct usc_mrt_resource mrt_resources[static const 2], + uint32_t *render_target_used_out) +{ + const uint32_t max_pbe_write_size_dw = 4; + uint32_t render_target_used = 0; + uint64_t mem_stored; + + assert(PVR_HAS_FEATURE(dev_info, eight_output_registers)); + assert(source_type != USC_MRT_RESOURCE_TYPE_INVALID); + + /* To store 8 dwords we need to split this into two + * ROGUE_PBESTATE_PACKMODE_U32U32U32U32 stores with the second one using + * PVR_PBE_STARTPOS_BIT128 as the source offset to store the last 4 dwords. + */ + + mem_stored = pvr_spm_setup_pbe_state(dev_info, + framebuffer_size, + max_pbe_write_size_dw, + PVR_PBE_STARTPOS_BIT0, + sample_count, + scratch_buffer_addr, + pbe_state_word_0_out, + pbe_reg_word_0_out); + + PVR_DEV_ADDR_ADVANCE(scratch_buffer_addr, mem_stored); + + mrt_resources[render_target_used] = (struct usc_mrt_resource){ + .mrt_desc = { + .intermediate_size = max_pbe_write_size_dw * sizeof(uint32_t), + }, + .type = source_type, + .intermediate_size = max_pbe_write_size_dw * sizeof(uint32_t), + }; + + if (source_type == USC_MRT_RESOURCE_TYPE_MEMORY) + mrt_resources[render_target_used].mem.tile_buffer = tile_buffer_idx; + + pvr_set_pbe_all_valid_mask(&mrt_resources[render_target_used].mrt_desc); + + render_target_used++; + + mem_stored += pvr_spm_setup_pbe_state(dev_info, + framebuffer_size, + max_pbe_write_size_dw, + PVR_PBE_STARTPOS_BIT128, + sample_count, + scratch_buffer_addr, + pbe_state_word_1_out, + pbe_reg_word_1_out); + + PVR_DEV_ADDR_ADVANCE(scratch_buffer_addr, mem_stored); + + mrt_resources[render_target_used] = (struct usc_mrt_resource){ + .mrt_desc = { + .intermediate_size = max_pbe_write_size_dw * sizeof(uint32_t), + }, + .type = source_type, + .intermediate_size = max_pbe_write_size_dw * sizeof(uint32_t), + }; + + if (source_type == USC_MRT_RESOURCE_TYPE_OUTPUT_REG) { + /* Start from o4. */ + mrt_resources[render_target_used].reg.output_reg = max_pbe_write_size_dw; + } else { + mrt_resources[render_target_used].mem.tile_buffer = tile_buffer_idx; + mrt_resources[render_target_used].mem.offset_dw = max_pbe_write_size_dw; + } + + pvr_set_pbe_all_valid_mask(&mrt_resources[render_target_used].mrt_desc); + + render_target_used++; + *render_target_used_out = render_target_used; + + return mem_stored; +} + +/** + * \brief Create and upload the EOT PDS program. + * + * Essentially DOUTU the USC EOT shader. + */ +/* TODO: See if we can dedup this with + * pvr_sub_cmd_gfx_per_job_fragment_programs_create_and_upload(). + */ +static VkResult pvr_pds_pixel_event_program_create_and_upload( + struct pvr_device *device, + const struct pvr_bo *usc_eot_program, + uint32_t usc_temp_count, + struct pvr_pds_upload *const pds_upload_out) +{ + const struct pvr_device_info *dev_info = &device->pdevice->dev_info; + struct pvr_pds_event_program program = { 0 }; + uint32_t *staging_buffer; + VkResult result; + + pvr_pds_setup_doutu(&program.task_control, + usc_eot_program->vma->dev_addr.addr, + usc_temp_count, + PVRX(PDSINST_DOUTU_SAMPLE_RATE_INSTANCE), + false); + + staging_buffer = + vk_alloc(&device->vk.alloc, + device->pixel_event_data_size_in_dwords * sizeof(uint32_t), + 8, + VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); + if (!staging_buffer) + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + + pvr_pds_generate_pixel_event_data_segment(&program, + staging_buffer, + dev_info); + + result = pvr_gpu_upload_pds(device, + staging_buffer, + device->pixel_event_data_size_in_dwords, + 4, + NULL, + 0, + 0, + 4, + pds_upload_out); + vk_free(&device->vk.alloc, staging_buffer); + return result; +} + +/** + * \brief Sets up the End of Tile (EOT) program for SPM. + * + * This sets up an EOT program to store the render pass'es on-chip and + * off-chip tile data to the SPM scratch buffer on the EOT event. + */ +VkResult +pvr_spm_init_eot_state(struct pvr_device *device, + struct pvr_spm_eot_state *spm_eot_state, + const struct pvr_framebuffer *framebuffer, + const struct pvr_renderpass_hwsetup_render *hw_render) +{ + const struct pvr_device_info *dev_info = &device->pdevice->dev_info; + struct pvr_pds_upload pds_eot_program; + uint64_t mem_stored; + VkResult result; + + const VkExtent2D framebuffer_size = { + .width = framebuffer->width, + .height = framebuffer->height, + }; + pvr_dev_addr_t next_scratch_buffer_addr = + framebuffer->scratch_buffer->bo->vma->dev_addr; + + /* TODO: These are only setup but not used for now. They will be used by the + * compiler once it's hooked up to generate the eot shader. + */ + struct usc_mrt_resource mrt_resources[PVR_MAX_COLOR_ATTACHMENTS]; + struct usc_mrt_setup mrt_setup = { + .num_output_regs = hw_render->output_regs_count, + .tile_buffer_size = pvr_get_tile_buffer_size(device), + .mrt_resources = mrt_resources, + }; + + /* FIXME: Remove this hard coding. */ + uint32_t empty_eot_program[8] = { 0 }; + uint32_t usc_temp_count = 0; + + /* TODO: See if instead of having a separate path for devices with 8 output + * regs we can instead do this in a loop and dedup some stuff. + */ + assert(util_is_power_of_two_or_zero(hw_render->output_regs_count) && + hw_render->output_regs_count <= 8); + if (hw_render->output_regs_count == 8) { + uint32_t render_targets_used; + + /* Store on-chip tile data (i.e. output regs). */ + + mem_stored = pvr_spm_setup_pbe_eight_dword_write( + dev_info, + &framebuffer_size, + hw_render->sample_count, + USC_MRT_RESOURCE_TYPE_OUTPUT_REG, + 0, + next_scratch_buffer_addr, + spm_eot_state->pbe_cs_words[mrt_setup.num_render_targets], + spm_eot_state->pbe_cs_words[mrt_setup.num_render_targets + 1], + spm_eot_state->pbe_reg_words[mrt_setup.num_render_targets], + spm_eot_state->pbe_reg_words[mrt_setup.num_render_targets + 1], + &mrt_resources[mrt_setup.num_render_targets], + &render_targets_used); + + PVR_DEV_ADDR_ADVANCE(next_scratch_buffer_addr, mem_stored); + mrt_setup.num_render_targets += render_targets_used; + + /* Store off-chip tile data (i.e. tile buffers). */ + + for (uint32_t i = 0; i < hw_render->tile_buffers_count; i++) { + /* `+ 1` since we have 2 emits per tile buffer. */ + assert(mrt_setup.num_render_targets + 1 < PVR_MAX_COLOR_ATTACHMENTS); + + mem_stored = pvr_spm_setup_pbe_eight_dword_write( + dev_info, + &framebuffer_size, + hw_render->sample_count, + USC_MRT_RESOURCE_TYPE_MEMORY, + i, + next_scratch_buffer_addr, + spm_eot_state->pbe_cs_words[mrt_setup.num_render_targets], + spm_eot_state->pbe_cs_words[mrt_setup.num_render_targets + 1], + spm_eot_state->pbe_reg_words[mrt_setup.num_render_targets], + spm_eot_state->pbe_reg_words[mrt_setup.num_render_targets + 1], + &mrt_resources[mrt_setup.num_render_targets], + &render_targets_used); + + PVR_DEV_ADDR_ADVANCE(next_scratch_buffer_addr, mem_stored); + mrt_setup.num_render_targets += render_targets_used; + } + } else { + /* Store on-chip tile data (i.e. output regs). */ + + mem_stored = pvr_spm_setup_pbe_state( + dev_info, + &framebuffer_size, + hw_render->output_regs_count, + PVR_PBE_STARTPOS_BIT0, + hw_render->sample_count, + next_scratch_buffer_addr, + spm_eot_state->pbe_cs_words[mrt_setup.num_render_targets], + spm_eot_state->pbe_reg_words[mrt_setup.num_render_targets]); + + PVR_DEV_ADDR_ADVANCE(next_scratch_buffer_addr, mem_stored); + + mrt_resources[mrt_setup.num_render_targets] = (struct usc_mrt_resource){ + .mrt_desc = { + .intermediate_size = hw_render->output_regs_count * sizeof(uint32_t), + }, + .type = USC_MRT_RESOURCE_TYPE_OUTPUT_REG, + .intermediate_size = hw_render->output_regs_count * sizeof(uint32_t), + }; + + pvr_set_pbe_all_valid_mask( + &mrt_resources[mrt_setup.num_render_targets].mrt_desc); + + mrt_setup.num_render_targets++; + + /* Store off-chip tile data (i.e. tile buffers). */ + + for (uint32_t i = 0; i < hw_render->tile_buffers_count; i++) { + assert(mrt_setup.num_render_targets < PVR_MAX_COLOR_ATTACHMENTS); + + mem_stored = pvr_spm_setup_pbe_state( + dev_info, + &framebuffer_size, + hw_render->output_regs_count, + PVR_PBE_STARTPOS_BIT0, + hw_render->sample_count, + next_scratch_buffer_addr, + spm_eot_state->pbe_cs_words[mrt_setup.num_render_targets], + spm_eot_state->pbe_reg_words[mrt_setup.num_render_targets]); + + PVR_DEV_ADDR_ADVANCE(next_scratch_buffer_addr, mem_stored); + + mrt_resources[mrt_setup.num_render_targets] = (struct usc_mrt_resource){ + .mrt_desc = { + .intermediate_size = + hw_render->output_regs_count * sizeof(uint32_t), + }, + .type = USC_MRT_RESOURCE_TYPE_MEMORY, + .intermediate_size = hw_render->output_regs_count * sizeof(uint32_t), + .mem = { .tile_buffer = i, }, + }; + + pvr_set_pbe_all_valid_mask( + &mrt_resources[mrt_setup.num_render_targets].mrt_desc); + + mrt_setup.num_render_targets++; + } + } + + /* TODO: The PBE state words likely only get used by the compiler to be + * embedded into the shader so we should probably remove it from + * spm_eot_state. + */ + /* FIXME: Compile the EOT shader based on the mrt_setup configured above. */ + + /* TODO: Create a #define in the compiler code to replace the 16. */ + result = pvr_gpu_upload_usc(device, + empty_eot_program, + sizeof(empty_eot_program), + 16, + &spm_eot_state->usc_eot_program); + if (result != VK_SUCCESS) + return result; + + result = pvr_pds_pixel_event_program_create_and_upload( + device, + spm_eot_state->usc_eot_program, + usc_temp_count, + &pds_eot_program); + if (result != VK_SUCCESS) { + pvr_bo_free(device, spm_eot_state->usc_eot_program); + return result; + } + + spm_eot_state->pixel_event_program_data_upload = pds_eot_program.pvr_bo; + spm_eot_state->pixel_event_program_data_offset = pds_eot_program.data_offset; + + return VK_SUCCESS; +} + +#undef PVR_DEV_ADDR_ADVANCE + +void pvr_spm_finish_eot_state(struct pvr_device *device, + struct pvr_spm_eot_state *spm_eot_state) +{ + pvr_bo_free(device, spm_eot_state->pixel_event_program_data_upload); + pvr_bo_free(device, spm_eot_state->usc_eot_program); +} diff --git a/src/imagination/vulkan/pvr_spm.h b/src/imagination/vulkan/pvr_spm.h index 71c48e8f113..22cd67d61e7 100644 --- a/src/imagination/vulkan/pvr_spm.h +++ b/src/imagination/vulkan/pvr_spm.h @@ -42,10 +42,15 @@ #include <stdint.h> #include <vulkan/vulkan_core.h> +#include "hwdef/rogue_hw_defs.h" +#include "pvr_limits.h" #include "util/simple_mtx.h" +struct pvr_bo; struct pvr_device; +struct pvr_framebuffer; struct pvr_render_pass; +struct pvr_renderpass_hwsetup_render; struct pvr_spm_scratch_buffer; struct pvr_spm_scratch_buffer_store { @@ -53,6 +58,24 @@ struct pvr_spm_scratch_buffer_store { struct pvr_spm_scratch_buffer *head_ref; }; +struct pvr_spm_eot_state { + uint32_t pbe_cs_words[PVR_MAX_COLOR_ATTACHMENTS] + [ROGUE_NUM_PBESTATE_STATE_WORDS]; + uint64_t pbe_reg_words[PVR_MAX_COLOR_ATTACHMENTS] + [ROGUE_NUM_PBESTATE_REG_WORDS]; + + struct pvr_bo *usc_eot_program; + + /* TODO: Make this struct pvr_pds_upload? It would pull in pvr_private.h + * though which causes a cycle since that includes pvr_spm.h . + */ + /* This is only the data section upload. The code was uploaded at device + * creation. + */ + uint64_t pixel_event_program_data_offset; + struct pvr_bo *pixel_event_program_data_upload; +}; + void pvr_spm_init_scratch_buffer_store(struct pvr_device *device); void pvr_spm_finish_scratch_buffer_store(struct pvr_device *device); @@ -79,4 +102,12 @@ void pvr_spm_scratch_buffer_release(struct pvr_device *device, VkResult pvr_device_init_spm_load_state(struct pvr_device *device); void pvr_device_finish_spm_load_state(struct pvr_device *device); +VkResult +pvr_spm_init_eot_state(struct pvr_device *device, + struct pvr_spm_eot_state *spm_eot_state, + const struct pvr_framebuffer *framebuffer, + const struct pvr_renderpass_hwsetup_render *hw_render); +void pvr_spm_finish_eot_state(struct pvr_device *device, + struct pvr_spm_eot_state *spm_eot_state); + #endif /* PVR_SPM_H */
