diff --git a/src/imagination/vulkan/pvr_cmd_buffer.c b/src/imagination/vulkan/pvr_cmd_buffer.c index 8a9aacf38cb..73efa79b62e 100644 --- a/src/imagination/vulkan/pvr_cmd_buffer.c +++ b/src/imagination/vulkan/pvr_cmd_buffer.c @@ -369,8 +369,8 @@ static VkResult pvr_cmd_buffer_emit_ppp_state(const struct pvr_cmd_buffer *const cmd_buffer, struct pvr_csb *const csb) { - const struct pvr_framebuffer *const framebuffer = - cmd_buffer->state.render_pass_info.framebuffer; + const struct pvr_render_state *const rstate = + cmd_buffer->state.render_pass_info.rstate; assert(csb->stream_type == PVR_CMD_STREAM_TYPE_GRAPHICS || csb->stream_type == PVR_CMD_STREAM_TYPE_GRAPHICS_DEFERRED); @@ -378,12 +378,12 @@ pvr_cmd_buffer_emit_ppp_state(const struct pvr_cmd_buffer *const cmd_buffer, pvr_csb_set_relocation_mark(csb); pvr_csb_emit (csb, VDMCTRL_PPP_STATE0, state0) { - state0.addrmsb = framebuffer->ppp_state_bo->dev_addr; - state0.word_count = framebuffer->ppp_state_size; + state0.addrmsb = rstate->ppp_state_bo->dev_addr; + state0.word_count = rstate->ppp_state_size; } pvr_csb_emit (csb, VDMCTRL_PPP_STATE1, state1) { - state1.addrlsb = framebuffer->ppp_state_bo->dev_addr; + state1.addrlsb = rstate->ppp_state_bo->dev_addr; } pvr_csb_clear_relocation_mark(csb); @@ -1060,7 +1060,7 @@ static inline uint32_t pvr_stride_from_pitch(uint32_t pitch, VkFormat vk_format) static void pvr_setup_pbe_state( const struct pvr_device_info *dev_info, - const struct pvr_framebuffer *framebuffer, + const struct pvr_render_state *rstate, uint32_t mrt_index, const struct usc_mrt_resource *mrt_resource, const struct pvr_image_view *const iview, @@ -1170,10 +1170,10 @@ static void pvr_setup_pbe_state( render_params.min_x_clip = MAX2(0, render_area->offset.x); render_params.min_y_clip = MAX2(0, render_area->offset.y); render_params.max_x_clip = MIN2( - framebuffer->width - 1, + rstate->width - 1, PVR_DEC_IF_NOT_ZERO(render_area->offset.x + render_area->extent.width)); render_params.max_y_clip = MIN2( - framebuffer->height - 1, + rstate->height - 1, PVR_DEC_IF_NOT_ZERO(render_area->offset.y + render_area->extent.height)); #undef PVR_DEC_IF_NOT_ZERO @@ -1190,12 +1190,9 @@ static void pvr_setup_pbe_state( } static struct pvr_render_target * -pvr_get_render_target(const struct pvr_render_pass *pass, - const struct pvr_framebuffer *framebuffer, - uint32_t idx) +pvr_get_render_target(const struct pvr_renderpass_hwsetup_render *hw_render, + const struct pvr_render_state *rstate) { - const struct pvr_renderpass_hwsetup_render *hw_render = - &pass->hw_setup->renders[idx]; uint32_t rt_idx = 0; switch (hw_render->sample_count) { @@ -1211,16 +1208,13 @@ pvr_get_render_target(const struct pvr_render_pass *pass, break; } - return &framebuffer->render_targets[rt_idx]; + return &rstate->render_targets[rt_idx]; } static uint32_t -pvr_pass_get_pixel_output_width(const struct pvr_render_pass *pass, - uint32_t idx, - const struct pvr_device_info *dev_info) +pvr_get_pixel_output_width(const struct pvr_renderpass_hwsetup_render *hw_render, + const struct pvr_device_info *dev_info) { - const struct pvr_renderpass_hwsetup_render *hw_render = - &pass->hw_setup->renders[idx]; /* Default value based on the maximum value found in all existing cores. The * maximum is used as this is being treated as a lower bound, making it a * "safer" choice than the minimum value found in all existing cores. @@ -1484,8 +1478,8 @@ pvr_setup_emit_state(const struct pvr_device_info *dev_info, resource_type <= USC_MRT_RESOURCE_TYPE_MEMORY; resource_type++) { for (uint32_t i = 0; i < hw_render->eot_surface_count; i++) { - const struct pvr_framebuffer *framebuffer = - render_pass_info->framebuffer; + const struct pvr_render_state *rstate = + render_pass_info->rstate; const struct pvr_renderpass_hwsetup_eot_surface *surface = &hw_render->eot_surfaces[i]; const struct pvr_image_view *iview = @@ -1522,7 +1516,7 @@ pvr_setup_emit_state(const struct pvr_device_info *dev_info, : ~0; pvr_setup_pbe_state(dev_info, - framebuffer, + rstate, emit_state->emit_count, mrt_resource, iview, @@ -1551,6 +1545,13 @@ pvr_is_render_area_tile_aligned(const struct pvr_cmd_buffer *cmd_buffer, render_area->extent.width == iview->vk.extent.width; } +static inline struct pvr_renderpass_hwsetup_render * +pvr_pass_info_get_hw_render(const struct pvr_render_pass_info *render_pass_info, + uint32_t idx) +{ + return &render_pass_info->pass->hw_setup->renders[idx]; +} + 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) @@ -1565,13 +1566,13 @@ static VkResult pvr_sub_cmd_gfx_job_init(const struct pvr_device_info *dev_info, struct pvr_render_pass_info *render_pass_info = &cmd_buffer->state.render_pass_info; const struct pvr_renderpass_hwsetup_render *hw_render = - &render_pass_info->pass->hw_setup->renders[sub_cmd->hw_render_idx]; + pvr_pass_info_get_hw_render(render_pass_info, sub_cmd->hw_render_idx); struct pvr_render_job *job = &sub_cmd->job; - struct pvr_framebuffer *framebuffer = render_pass_info->framebuffer; + struct pvr_render_state *rstate = render_pass_info->rstate; struct pvr_spm_bgobj_state *spm_bgobj_state = - &framebuffer->spm_bgobj_state_per_render[sub_cmd->hw_render_idx]; + &rstate->spm_bgobj_state_per_render[sub_cmd->hw_render_idx]; struct pvr_spm_eot_state *spm_eot_state = - &framebuffer->spm_eot_state_per_render[sub_cmd->hw_render_idx]; + &rstate->spm_eot_state_per_render[sub_cmd->hw_render_idx]; struct pvr_render_target *render_target; VkResult result; @@ -1622,9 +1623,7 @@ static VkResult pvr_sub_cmd_gfx_job_init(const struct pvr_device_info *dev_info, &emit_state); unsigned pixel_output_width = - pvr_pass_get_pixel_output_width(render_pass_info->pass, - sub_cmd->hw_render_idx, - dev_info); + pvr_get_pixel_output_width(hw_render, dev_info); result = pvr_sub_cmd_gfx_per_job_fragment_programs_create_and_upload( cmd_buffer, @@ -1703,9 +1702,7 @@ static VkResult pvr_sub_cmd_gfx_job_init(const struct pvr_device_info *dev_info, spm_eot_state->pixel_event_program_data_offset; } - render_target = pvr_get_render_target(render_pass_info->pass, - framebuffer, - sub_cmd->hw_render_idx); + render_target = pvr_get_render_target(hw_render, render_pass_info->rstate); job->view_state.rt_datasets = &render_target->rt_dataset[0]; job->ctrl_stream_addr = pvr_csb_get_start_address(&sub_cmd->control_stream); @@ -1721,9 +1718,7 @@ static VkResult pvr_sub_cmd_gfx_job_init(const struct pvr_device_info *dev_info, job->scissor_table_addr = PVR_DEV_ADDR_INVALID; job->pixel_output_width = - pvr_pass_get_pixel_output_width(render_pass_info->pass, - sub_cmd->hw_render_idx, - dev_info); + pvr_get_pixel_output_width(hw_render, dev_info); /* Setup depth/stencil job information. */ if (hw_render->ds_attach_idx != VK_ATTACHMENT_UNUSED) { @@ -2603,9 +2598,8 @@ static inline uint32_t pvr_render_pass_info_get_view_mask(const struct pvr_render_pass_info *rp_info) { const uint32_t hw_render_idx = rp_info->current_hw_subpass; - const struct pvr_render_pass *pass = rp_info->pass; const struct pvr_renderpass_hwsetup_render *hw_render = - &pass->hw_setup->renders[hw_render_idx]; + pvr_pass_info_get_hw_render(rp_info, hw_render_idx); return hw_render->view_mask; } @@ -2660,7 +2654,7 @@ VkResult pvr_cmd_buffer_start_sub_cmd(struct pvr_cmd_buffer *cmd_buffer, isp_max_tiles_in_flight, 1); sub_cmd->gfx.hw_render_idx = state->render_pass_info.current_hw_subpass; - sub_cmd->gfx.framebuffer = state->render_pass_info.framebuffer; + sub_cmd->gfx.rstate = state->render_pass_info.rstate; sub_cmd->gfx.empty_cmd = true; sub_cmd->gfx.view_mask = pvr_render_pass_info_get_view_mask(&state->render_pass_info); @@ -3092,13 +3086,13 @@ static VkResult pvr_cmd_buffer_attachments_setup( static inline VkResult pvr_render_targets_datasets_create( struct pvr_device *device, - struct pvr_framebuffer *framebuffer, + struct pvr_render_state *rstate, const struct pvr_renderpass_hwsetup_render *hw_render, struct pvr_render_target *render_target) { const struct pvr_device_info *const dev_info = &device->pdevice->dev_info; const uint32_t layers = - PVR_HAS_FEATURE(dev_info, gs_rta_support) ? framebuffer->layers : 1; + PVR_HAS_FEATURE(dev_info, gs_rta_support) ? rstate->layers : 1; pthread_mutex_lock(&render_target->mutex); @@ -3110,8 +3104,8 @@ static inline VkResult pvr_render_targets_datasets_create( continue; result = pvr_render_target_dataset_create(device, - framebuffer->width, - framebuffer->height, + rstate->width, + rstate->height, hw_render->sample_count, layers, &rt_dataset); @@ -3130,21 +3124,33 @@ static inline VkResult pvr_render_targets_datasets_create( return VK_SUCCESS; } -static VkResult pvr_render_targets_init(struct pvr_device *device, - struct pvr_render_pass *pass, - struct pvr_framebuffer *framebuffer) +static VkResult +pvr_render_targets_init(struct pvr_device *device, + struct pvr_render_state *rstate, + const struct pvr_renderpass_hwsetup_render *hw_render) +{ + struct pvr_render_target *render_target = + pvr_get_render_target(hw_render, rstate); + + return pvr_render_targets_datasets_create(device, + rstate, + hw_render, + render_target); +} + +static VkResult +pvr_render_targets_init_for_render(struct pvr_device *device, + struct pvr_render_pass *pass, + struct pvr_framebuffer *framebuffer) { for (uint32_t i = 0; i < pass->hw_setup->render_count; i++) { - struct pvr_render_target *render_target = - pvr_get_render_target(pass, framebuffer, i); const struct pvr_renderpass_hwsetup_render *hw_render = &pass->hw_setup->renders[i]; VkResult result; - result = pvr_render_targets_datasets_create(device, - framebuffer, - hw_render, - render_target); + result = pvr_render_targets_init(device, + framebuffer->rstate, + hw_render); if (result != VK_SUCCESS) return result; } @@ -3163,7 +3169,7 @@ pvr_get_hw_subpass(const struct pvr_render_pass *pass, const uint32_t subpass) static void pvr_perform_start_of_render_attachment_clear( struct pvr_cmd_buffer *cmd_buffer, - const struct pvr_framebuffer *framebuffer, + uint32_t layers, uint32_t index, bool is_depth_stencil, uint32_t *index_list_clear_mask) @@ -3173,9 +3179,11 @@ static void pvr_perform_start_of_render_attachment_clear( VK_IMAGE_ASPECT_COLOR_BIT; struct pvr_render_pass_info *info = &cmd_buffer->state.render_pass_info; const struct pvr_render_pass *pass = info->pass; - const struct pvr_renderpass_hwsetup *hw_setup = pass->hw_setup; + const struct pvr_renderpass_hwsetup *hw_setup = pass ? pass->hw_setup : NULL; + const uint32_t hw_render_idx = hw_setup ? + hw_setup->subpass_map[info->subpass_idx].render : 0; const struct pvr_renderpass_hwsetup_render *hw_render = - &hw_setup->renders[hw_setup->subpass_map[info->subpass_idx].render]; + pvr_pass_info_get_hw_render(info, hw_render_idx); VkImageAspectFlags image_aspect; struct pvr_image_view *iview; uint32_t view_idx; @@ -3217,8 +3225,7 @@ static void pvr_perform_start_of_render_attachment_clear( /* If this is single-layer fullscreen, we already do the clears in * pvr_sub_cmd_gfx_job_init(). */ - if (pvr_is_render_area_tile_aligned(cmd_buffer, iview) && - framebuffer->layers == 1) { + if (pvr_is_render_area_tile_aligned(cmd_buffer, iview) && layers == 1) { return; } @@ -3244,7 +3251,13 @@ static void pvr_perform_start_of_render_attachment_clear( VkClearRect rect = { .rect = info->render_area, .baseArrayLayer = 0, - .layerCount = info->framebuffer->layers, + /* TODO: + * + * Verify where layers should come from, info->framebuffer + * vs layers (function argument). Aren't they the same? + * If they are, drop the argument altogether. + */ + .layerCount = info->rstate->layers, }; assert(view_idx < info->clear_value_count); @@ -3259,11 +3272,9 @@ static void pvr_perform_start_of_render_clears(struct pvr_cmd_buffer *cmd_buffer) { struct pvr_render_pass_info *info = &cmd_buffer->state.render_pass_info; - const struct pvr_framebuffer *framebuffer = info->framebuffer; - const struct pvr_render_pass *pass = info->pass; - const struct pvr_renderpass_hwsetup *hw_setup = pass->hw_setup; + const struct pvr_renderpass_hwsetup *hw_setup = info->pass->hw_setup; const struct pvr_renderpass_hwsetup_render *hw_render = - &hw_setup->renders[hw_setup->subpass_map[info->subpass_idx].render]; + pvr_pass_info_get_hw_render(info, hw_setup->subpass_map[info->subpass_idx].render); /* Mask of attachment clears using index lists instead of background object * to clear. @@ -3272,7 +3283,7 @@ pvr_perform_start_of_render_clears(struct pvr_cmd_buffer *cmd_buffer) for (uint32_t i = 0; i < hw_render->color_init_count; i++) { pvr_perform_start_of_render_attachment_clear(cmd_buffer, - framebuffer, + info->rstate->layers, i, false, &index_list_clear_mask); @@ -3294,7 +3305,7 @@ pvr_perform_start_of_render_clears(struct pvr_cmd_buffer *cmd_buffer) uint32_t ds_index_list = 0; pvr_perform_start_of_render_attachment_clear(cmd_buffer, - framebuffer, + info->rstate->layers, 0, true, &ds_index_list); @@ -3304,9 +3315,8 @@ pvr_perform_start_of_render_clears(struct pvr_cmd_buffer *cmd_buffer) static void pvr_stash_depth_format(struct pvr_cmd_buffer_state *state, struct pvr_sub_cmd_gfx *const sub_cmd) { - const struct pvr_render_pass *pass = state->render_pass_info.pass; const struct pvr_renderpass_hwsetup_render *hw_render = - &pass->hw_setup->renders[sub_cmd->hw_render_idx]; + pvr_pass_info_get_hw_render(&state->render_pass_info, sub_cmd->hw_render_idx); if (hw_render->ds_attach_idx != VK_ATTACHMENT_UNUSED) { struct pvr_image_view **iviews = state->render_pass_info.attachments; @@ -3563,6 +3573,7 @@ void pvr_CmdBeginRenderPass2(VkCommandBuffer commandBuffer, * look at cmd_buffer_begin_subpass() for example. */ state->render_pass_info.pass = pass; state->render_pass_info.framebuffer = framebuffer; + state->render_pass_info.rstate = framebuffer->rstate; state->render_pass_info.subpass_idx = 0; state->render_pass_info.render_area = pRenderPassBeginInfo->renderArea; state->render_pass_info.current_hw_subpass = 0; @@ -3578,7 +3589,7 @@ void pvr_CmdBeginRenderPass2(VkCommandBuffer commandBuffer, if (result != VK_SUCCESS) return; - result = pvr_render_targets_init(cmd_buffer->device, pass, framebuffer); + result = pvr_render_targets_init_for_render(cmd_buffer->device, pass, framebuffer); if (result != VK_SUCCESS) { pvr_cmd_buffer_set_error_unwarned(cmd_buffer, result); return; @@ -7295,7 +7306,7 @@ pvr_resolve_unemitted_resolve_attachments(struct pvr_cmd_buffer *cmd_buffer, { struct pvr_cmd_buffer_state *state = &cmd_buffer->state; const struct pvr_renderpass_hwsetup_render *hw_render = - &state->render_pass_info.pass->hw_setup->renders[info->current_hw_subpass]; + pvr_pass_info_get_hw_render(&state->render_pass_info, info->current_hw_subpass); for (uint32_t i = 0U; i < hw_render->eot_surface_count; i++) { const struct pvr_renderpass_hwsetup_eot_surface *surface = @@ -8054,7 +8065,7 @@ static bool pvr_is_stencil_store_load_needed( return false; hw_render_idx = state->current_sub_cmd->gfx.hw_render_idx; - hw_render = &pass->hw_setup->renders[hw_render_idx]; + hw_render = pvr_pass_info_get_hw_render(&state->render_pass_info, hw_render_idx); if (hw_render->ds_attach_idx == VK_ATTACHMENT_UNUSED) return false; diff --git a/src/imagination/vulkan/pvr_cmd_buffer.h b/src/imagination/vulkan/pvr_cmd_buffer.h index af13ac436d0..e9c345e93ac 100644 --- a/src/imagination/vulkan/pvr_cmd_buffer.h +++ b/src/imagination/vulkan/pvr_cmd_buffer.h @@ -119,7 +119,7 @@ struct pvr_transfer_cmd { }; struct pvr_sub_cmd_gfx { - const struct pvr_framebuffer *framebuffer; + const struct pvr_render_state *rstate; struct pvr_render_job job; @@ -272,6 +272,9 @@ struct pvr_render_pass_info { const struct pvr_render_pass *pass; struct pvr_framebuffer *framebuffer; + struct pvr_render_state *rstate; + + uint32_t attachment_count; struct pvr_image_view **attachments; uint32_t subpass_idx; @@ -536,7 +539,7 @@ pvr_cmd_buffer_set_error_unwarned(struct pvr_cmd_buffer *cmd_buffer, static inline bool pvr_sub_cmd_gfx_requires_split_submit( const struct pvr_sub_cmd_gfx *const sub_cmd) { - return sub_cmd->job.run_frag && sub_cmd->framebuffer->layers > 1; + return sub_cmd->job.run_frag && sub_cmd->rstate->layers > 1; } #define PVR_CHECK_COMMAND_BUFFER_BUILDING_STATE(cmd_buffer) \ diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c index 7ff6fb72e8b..0a12ae48fcd 100644 --- a/src/imagination/vulkan/pvr_device.c +++ b/src/imagination/vulkan/pvr_device.c @@ -1827,8 +1827,8 @@ VkResult pvr_gpu_upload_pds(struct pvr_device *device, } static VkResult -pvr_framebuffer_create_ppp_state(struct pvr_device *device, - struct pvr_framebuffer *framebuffer) +pvr_render_state_create_ppp_state(struct pvr_device *device, + struct pvr_render_state *rstate) { const uint32_t cache_line_size = pvr_get_slc_cache_line_size(&device->pdevice->dev_info); @@ -1842,12 +1842,12 @@ pvr_framebuffer_create_ppp_state(struct pvr_device *device, pvr_csb_pack (&ppp_state[1], TA_STATE_TERMINATE0, term0) { term0.clip_right = DIV_ROUND_UP( - framebuffer->width, + rstate->width, ROGUE_TA_STATE_TERMINATE0_CLIP_RIGHT_BLOCK_SIZE_IN_PIXELS) - 1; term0.clip_bottom = DIV_ROUND_UP( - framebuffer->height, + rstate->height, ROGUE_TA_STATE_TERMINATE0_CLIP_BOTTOM_BLOCK_SIZE_IN_PIXELS) - 1; } @@ -1862,12 +1862,12 @@ pvr_framebuffer_create_ppp_state(struct pvr_device *device, ppp_state, sizeof(ppp_state), cache_line_size, - &framebuffer->ppp_state_bo); + &rstate->ppp_state_bo); if (result != VK_SUCCESS) return result; /* Calculate the size of PPP state in dwords. */ - framebuffer->ppp_state_size = sizeof(ppp_state) / sizeof(uint32_t); + rstate->ppp_state_size = sizeof(ppp_state) / sizeof(uint32_t); return VK_SUCCESS; } @@ -1900,37 +1900,56 @@ static void pvr_render_targets_fini(struct pvr_render_target *render_targets, } } -VkResult pvr_CreateFramebuffer(VkDevice _device, - const VkFramebufferCreateInfo *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VkFramebuffer *pFramebuffer) +static inline uint64_t +pvr_render_pass_get_scratch_buffer_size(struct pvr_device *device, + const struct pvr_render_pass *pass, + const struct pvr_render_state *rstate) +{ + return pvr_spm_scratch_buffer_calc_required_size( + pass->hw_setup->renders, + pass->hw_setup->render_count, + pass->max_sample_count, + rstate->width, + rstate->height); +} + +void pvr_render_state_cleanup(struct pvr_device *device, + const struct pvr_render_state *rstate) +{ + if (!rstate) + return; + + for (uint32_t i = 0; i < rstate->render_count; i++) { + pvr_spm_finish_bgobj_state(device, + &rstate->spm_bgobj_state_per_render[i]); + + pvr_spm_finish_eot_state(device, + &rstate->spm_eot_state_per_render[i]); + } + + pvr_spm_scratch_buffer_release(device, rstate->scratch_buffer); + pvr_render_targets_fini(rstate->render_targets, + rstate->render_targets_count); + pvr_bo_suballoc_free(rstate->ppp_state_bo); +} + +VkResult pvr_render_state_setup( + struct pvr_device *device, + const VkAllocationCallbacks *pAllocator, + struct pvr_render_state *rstate, + uint32_t render_count, + const struct pvr_renderpass_hwsetup_render *renders) { - VK_FROM_HANDLE(pvr_render_pass, pass, pCreateInfo->renderPass); - VK_FROM_HANDLE(pvr_device, device, _device); - const VkFramebufferAttachmentsCreateInfoKHR *pImageless; struct pvr_spm_bgobj_state *spm_bgobj_state_per_render; 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; uint32_t render_targets_count; - uint64_t scratch_buffer_size; VkResult result; - assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO); - - pImageless = vk_find_struct_const(pCreateInfo->pNext, - FRAMEBUFFER_ATTACHMENTS_CREATE_INFO); - render_targets_count = PVR_RENDER_TARGETS_PER_FRAMEBUFFER(&device->pdevice->dev_info); VK_MULTIALLOC(ma); - vk_multialloc_add(&ma, &framebuffer, __typeof__(*framebuffer), 1); - vk_multialloc_add(&ma, - &attachments, - __typeof__(*attachments), - pCreateInfo->attachmentCount); vk_multialloc_add(&ma, &render_targets, __typeof__(*render_targets), @@ -1938,75 +1957,50 @@ VkResult pvr_CreateFramebuffer(VkDevice _device, vk_multialloc_add(&ma, &spm_eot_state_per_render, __typeof__(*spm_eot_state_per_render), - pass->hw_setup->render_count); + render_count); vk_multialloc_add(&ma, &spm_bgobj_state_per_render, __typeof__(*spm_bgobj_state_per_render), - pass->hw_setup->render_count); + render_count); if (!vk_multialloc_zalloc2(&ma, &device->vk.alloc, pAllocator, - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)) + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)) { return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); - - vk_object_base_init(&device->vk, - &framebuffer->base, - VK_OBJECT_TYPE_FRAMEBUFFER); - - framebuffer->width = pCreateInfo->width; - framebuffer->height = pCreateInfo->height; - framebuffer->layers = pCreateInfo->layers; - - framebuffer->attachments = attachments; - if (!pImageless) - framebuffer->attachment_count = pCreateInfo->attachmentCount; - else - framebuffer->attachment_count = pImageless->attachmentImageInfoCount; - for (uint32_t i = 0; i < framebuffer->attachment_count; i++) { - if (!pImageless) { - framebuffer->attachments[i] = - pvr_image_view_from_handle(pCreateInfo->pAttachments[i]); - } else { - assert(i < pImageless->attachmentImageInfoCount); - } } - result = pvr_framebuffer_create_ppp_state(device, framebuffer); - if (result != VK_SUCCESS) - goto err_free_framebuffer; - - framebuffer->render_targets = render_targets; - framebuffer->render_targets_count = render_targets_count; - if (!pvr_render_targets_init(framebuffer->render_targets, + rstate->render_targets = render_targets; + rstate->render_targets_count = render_targets_count; + if (!pvr_render_targets_init(rstate->render_targets, render_targets_count)) { result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); - goto err_free_ppp_state_bo; + goto err_free_render_targets; } - scratch_buffer_size = - pvr_spm_scratch_buffer_calc_required_size(pass, - framebuffer->width, - framebuffer->height); - + assert(rstate->scratch_buffer_size); result = pvr_spm_scratch_buffer_get_buffer(device, - scratch_buffer_size, - &framebuffer->scratch_buffer); + rstate->scratch_buffer_size, + &rstate->scratch_buffer); if (result != VK_SUCCESS) goto err_finish_render_targets; - for (uint32_t i = 0; i < pass->hw_setup->render_count; i++) { + result = pvr_render_state_create_ppp_state(device, rstate); + if (result != VK_SUCCESS) + goto err_release_scratch_buffer; + + for (uint32_t i = 0; i < render_count; i++) { result = pvr_spm_init_eot_state(device, &spm_eot_state_per_render[i], - framebuffer, - &pass->hw_setup->renders[i]); + rstate, + &renders[i]); if (result != VK_SUCCESS) goto err_finish_eot_state; result = pvr_spm_init_bgobj_state(device, &spm_bgobj_state_per_render[i], - framebuffer, - &pass->hw_setup->renders[i]); + rstate, + &renders[i]); if (result != VK_SUCCESS) goto err_finish_bgobj_state; @@ -2022,23 +2016,102 @@ err_finish_eot_state: 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; + goto err_free_ppp_state_bo; } - framebuffer->render_count = pass->hw_setup->render_count; - framebuffer->spm_eot_state_per_render = spm_eot_state_per_render; - framebuffer->spm_bgobj_state_per_render = spm_bgobj_state_per_render; + rstate->render_count = render_count; + rstate->spm_eot_state_per_render = spm_eot_state_per_render; + rstate->spm_bgobj_state_per_render = spm_bgobj_state_per_render; + + return VK_SUCCESS; + +err_free_ppp_state_bo: + pvr_bo_suballoc_free(rstate->ppp_state_bo); + +err_release_scratch_buffer: + pvr_spm_scratch_buffer_release(device, rstate->scratch_buffer); + +err_finish_render_targets: + pvr_render_targets_fini(rstate->render_targets, render_targets_count); + +err_free_render_targets: + vk_free2(&device->vk.alloc, pAllocator, rstate->render_targets); + + return result; +} + +VkResult pvr_CreateFramebuffer(VkDevice _device, + const VkFramebufferCreateInfo *pCreateInfo, + const VkAllocationCallbacks *pAllocator, + VkFramebuffer *pFramebuffer) +{ + VK_FROM_HANDLE(pvr_render_pass, pass, pCreateInfo->renderPass); + VK_FROM_HANDLE(pvr_device, device, _device); + const VkFramebufferAttachmentsCreateInfoKHR *pImageless; + struct pvr_framebuffer *framebuffer; + struct pvr_image_view **attachments; + struct pvr_render_state *rstate; + VkResult result; + + assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO); + + pImageless = vk_find_struct_const(pCreateInfo->pNext, + FRAMEBUFFER_ATTACHMENTS_CREATE_INFO); + + VK_MULTIALLOC(ma); + vk_multialloc_add(&ma, &framebuffer, __typeof__(*framebuffer), 1); + vk_multialloc_add(&ma, &rstate, __typeof__(*rstate), 1); + vk_multialloc_add(&ma, + &attachments, + __typeof__(*attachments), + pCreateInfo->attachmentCount); + + if (!vk_multialloc_zalloc2(&ma, + &device->vk.alloc, + pAllocator, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)) + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + + vk_object_base_init(&device->vk, + &framebuffer->base, + VK_OBJECT_TYPE_FRAMEBUFFER); + + framebuffer->attachments = attachments; + if (!pImageless) + framebuffer->attachment_count = pCreateInfo->attachmentCount; + else + framebuffer->attachment_count = pImageless->attachmentImageInfoCount; + for (uint32_t i = 0; i < framebuffer->attachment_count; i++) { + if (!pImageless) { + framebuffer->attachments[i] = + pvr_image_view_from_handle(pCreateInfo->pAttachments[i]); + } else { + assert(i < pImageless->attachmentImageInfoCount); + } + } + + rstate->width = pCreateInfo->width; + rstate->height = pCreateInfo->height; + rstate->layers = pCreateInfo->layers; + rstate->scratch_buffer_size = + pvr_render_pass_get_scratch_buffer_size(device, + pass, + rstate); + + result = pvr_render_state_setup(device, + pAllocator, + rstate, + pass->hw_setup->render_count, + pass->hw_setup->renders); + if (result != VK_SUCCESS) + goto err_free_framebuffer; + + framebuffer->rstate = rstate; *pFramebuffer = pvr_framebuffer_to_handle(framebuffer); return VK_SUCCESS; -err_finish_render_targets: - pvr_render_targets_fini(framebuffer->render_targets, render_targets_count); - -err_free_ppp_state_bo: - pvr_bo_suballoc_free(framebuffer->ppp_state_bo); - err_free_framebuffer: vk_object_base_finish(&framebuffer->base); vk_free2(&device->vk.alloc, pAllocator, framebuffer); @@ -2056,18 +2129,8 @@ void pvr_DestroyFramebuffer(VkDevice _device, if (!framebuffer) return; - for (uint32_t i = 0; i < framebuffer->render_count; i++) { - pvr_spm_finish_bgobj_state(device, - &framebuffer->spm_bgobj_state_per_render[i]); + pvr_render_state_cleanup(device, framebuffer->rstate); - 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); - pvr_bo_suballoc_free(framebuffer->ppp_state_bo); vk_object_base_finish(&framebuffer->base); vk_free2(&device->vk.alloc, pAllocator, framebuffer); } diff --git a/src/imagination/vulkan/pvr_framebuffer.h b/src/imagination/vulkan/pvr_framebuffer.h index 38acd69c4aa..0f911819fc2 100644 --- a/src/imagination/vulkan/pvr_framebuffer.h +++ b/src/imagination/vulkan/pvr_framebuffer.h @@ -22,17 +22,42 @@ struct pvr_render_target { uint32_t valid_mask; }; -struct pvr_framebuffer { - struct vk_object_base base; - - /* Saved information from pCreateInfo. */ +struct pvr_render_state { uint32_t width; uint32_t height; uint32_t layers; + uint32_t width_alignment; + uint32_t height_alignment; + + /* 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; + + uint64_t scratch_buffer_size; + 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; +}; + +struct pvr_framebuffer { + struct vk_object_base base; + uint32_t attachment_count; 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. */ @@ -46,8 +71,23 @@ struct pvr_framebuffer { 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; +#endif }; +struct pvr_device; +struct pvr_renderpass_hwsetup_render; + +VkResult pvr_render_state_setup(struct pvr_device *device, + const VkAllocationCallbacks *pAllocator, + struct pvr_render_state *rstate, + uint32_t render_count, + const struct pvr_renderpass_hwsetup_render *renders); + +void pvr_render_state_cleanup(struct pvr_device *device, + const struct pvr_render_state *rstate); + VK_DEFINE_NONDISP_HANDLE_CASTS(pvr_framebuffer, base, VkFramebuffer, diff --git a/src/imagination/vulkan/pvr_spm.c b/src/imagination/vulkan/pvr_spm.c index 87af46c7f76..f018e51ea53 100644 --- a/src/imagination/vulkan/pvr_spm.c +++ b/src/imagination/vulkan/pvr_spm.c @@ -86,10 +86,12 @@ void pvr_spm_finish_scratch_buffer_store(struct pvr_device *device) } } -uint64_t -pvr_spm_scratch_buffer_calc_required_size(const struct pvr_render_pass *pass, - uint32_t framebuffer_width, - uint32_t framebuffer_height) +uint64_t pvr_spm_scratch_buffer_calc_required_size( + const struct pvr_renderpass_hwsetup_render *renders, + uint32_t render_count, + uint32_t sample_count, + uint32_t framebuffer_width, + uint32_t framebuffer_height) { uint64_t dwords_per_pixel; uint64_t buffer_size; @@ -100,16 +102,15 @@ pvr_spm_scratch_buffer_calc_required_size(const struct pvr_render_pass *pass, uint32_t nr_tile_buffers = 1; uint32_t nr_output_regs = 1; - for (uint32_t i = 0; i < pass->hw_setup->render_count; i++) { - const struct pvr_renderpass_hwsetup_render *hw_render = - &pass->hw_setup->renders[i]; + for (uint32_t i = 0; i < render_count; i++) { + const struct pvr_renderpass_hwsetup_render *hw_render = &renders[i]; nr_tile_buffers = MAX2(nr_tile_buffers, hw_render->tile_buffers_count); nr_output_regs = MAX2(nr_output_regs, hw_render->output_regs_count); } dwords_per_pixel = - (uint64_t)pass->max_sample_count * nr_output_regs * nr_tile_buffers; + (uint64_t)sample_count * nr_output_regs * nr_tile_buffers; buffer_size = ALIGN_POT((uint64_t)framebuffer_width, ROGUE_CR_PBE_WORD0_MRT0_LINESTRIDE_ALIGNMENT); @@ -641,12 +642,12 @@ static VkResult pvr_pds_pixel_event_program_create_and_upload( 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_render_state *rstate, const struct pvr_renderpass_hwsetup_render *hw_render) { const VkExtent2D framebuffer_size = { - .width = framebuffer->width, - .height = framebuffer->height, + .width = rstate->width, + .height = rstate->height, }; uint32_t pbe_state_words[PVR_MAX_COLOR_ATTACHMENTS] [ROGUE_NUM_PBESTATE_STATE_WORDS]; @@ -659,7 +660,7 @@ pvr_spm_init_eot_state(struct pvr_device *device, VkResult result; pvr_dev_addr_t next_scratch_buffer_addr = - framebuffer->scratch_buffer->bo->vma->dev_addr; + rstate->scratch_buffer->bo->vma->dev_addr; uint64_t mem_stored; /* TODO: See if instead of having a separate path for devices with 8 output @@ -942,15 +943,15 @@ static VkResult pvr_pds_bgnd_program_create_and_upload( VkResult pvr_spm_init_bgobj_state(struct pvr_device *device, struct pvr_spm_bgobj_state *spm_bgobj_state, - const struct pvr_framebuffer *framebuffer, + const struct pvr_render_state *rstate, const struct pvr_renderpass_hwsetup_render *hw_render) { const VkExtent2D framebuffer_size = { - .width = framebuffer->width, - .height = framebuffer->height, + .width = rstate->width, + .height = rstate->height, }; pvr_dev_addr_t next_scratch_buffer_addr = - framebuffer->scratch_buffer->bo->vma->dev_addr; + rstate->scratch_buffer->bo->vma->dev_addr; struct pvr_spm_per_load_program_state *load_program_state; struct pvr_pds_upload pds_texture_data_upload; struct pvr_sampler_descriptor *descriptor; diff --git a/src/imagination/vulkan/pvr_spm.h b/src/imagination/vulkan/pvr_spm.h index 67cd9335a31..75e50f79554 100644 --- a/src/imagination/vulkan/pvr_spm.h +++ b/src/imagination/vulkan/pvr_spm.h @@ -51,6 +51,7 @@ struct pvr_device; struct pvr_framebuffer; struct pvr_render_pass; struct pvr_renderpass_hwsetup_render; +struct pvr_render_state; struct pvr_spm_scratch_buffer; struct pvr_spm_scratch_buffer_store { @@ -93,9 +94,12 @@ void pvr_spm_finish_scratch_buffer_store(struct pvr_device *device); * attachments with no backing. */ uint64_t -pvr_spm_scratch_buffer_calc_required_size(const struct pvr_render_pass *pass, - uint32_t framebuffer_width, - uint32_t framebuffer_height); +pvr_spm_scratch_buffer_calc_required_size( + const struct pvr_renderpass_hwsetup_render *renders, + uint32_t render_count, + uint32_t sample_count, + uint32_t framebuffer_width, + uint32_t framebuffer_height); VkResult pvr_spm_scratch_buffer_get_buffer( struct pvr_device *device, uint64_t size, @@ -110,7 +114,7 @@ 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_render_state *rstate, const struct pvr_renderpass_hwsetup_render *hw_render); void pvr_spm_finish_eot_state(struct pvr_device *device, @@ -119,7 +123,7 @@ void pvr_spm_finish_eot_state(struct pvr_device *device, VkResult pvr_spm_init_bgobj_state(struct pvr_device *device, struct pvr_spm_bgobj_state *spm_bgobj_state, - const struct pvr_framebuffer *framebuffer, + const struct pvr_render_state *rstate, const struct pvr_renderpass_hwsetup_render *hw_render); void pvr_spm_finish_bgobj_state(struct pvr_device *device,