diff --git a/src/imagination/vulkan/meson.build b/src/imagination/vulkan/meson.build index 656524ba477..55fb5bf6b17 100644 --- a/src/imagination/vulkan/meson.build +++ b/src/imagination/vulkan/meson.build @@ -35,6 +35,7 @@ pvr_files = files( 'pvr_device.c', 'pvr_dump_bo.c', 'pvr_dump_csb.c', + 'pvr_framebuffer.c', 'pvr_free_list.c', 'pvr_formats.c', 'pvr_hw_pass.c', diff --git a/src/imagination/vulkan/pvr_cmd_buffer.c b/src/imagination/vulkan/pvr_cmd_buffer.c index e58738eb1d0..2ec6c800d9e 100644 --- a/src/imagination/vulkan/pvr_cmd_buffer.c +++ b/src/imagination/vulkan/pvr_cmd_buffer.c @@ -45,6 +45,7 @@ #include "pvr_device_info.h" #include "pvr_entrypoints.h" #include "pvr_formats.h" +#include "pvr_framebuffer.h" #include "pvr_hw_pass.h" #include "pvr_image.h" #include "pvr_job_common.h" diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c index 4e822da3a65..dac37bcfc12 100644 --- a/src/imagination/vulkan/pvr_device.c +++ b/src/imagination/vulkan/pvr_device.c @@ -1868,73 +1868,8 @@ VkResult pvr_gpu_upload_pds(struct pvr_device *device, return VK_SUCCESS; } -static VkResult -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); - uint32_t ppp_state[3]; - VkResult result; - - pvr_csb_pack (&ppp_state[0], TA_STATE_HEADER, header) { - header.pres_terminate = true; - } - - pvr_csb_pack (&ppp_state[1], TA_STATE_TERMINATE0, term0) { - term0.clip_right = - DIV_ROUND_UP( - rstate->width, - ROGUE_TA_STATE_TERMINATE0_CLIP_RIGHT_BLOCK_SIZE_IN_PIXELS) - - 1; - term0.clip_bottom = - DIV_ROUND_UP( - rstate->height, - ROGUE_TA_STATE_TERMINATE0_CLIP_BOTTOM_BLOCK_SIZE_IN_PIXELS) - - 1; - } - - pvr_csb_pack (&ppp_state[2], TA_STATE_TERMINATE1, term1) { - term1.render_target = 0; - term1.clip_left = 0; - } - - result = pvr_gpu_upload(device, - device->heaps.general_heap, - ppp_state, - sizeof(ppp_state), - cache_line_size, - &rstate->ppp_state_bo); - if (result != VK_SUCCESS) - return result; - - /* Calculate the size of PPP state in dwords. */ - rstate->ppp_state_size = sizeof(ppp_state) / sizeof(uint32_t); - - return VK_SUCCESS; -} - -static bool pvr_render_targets_init(struct pvr_render_target *render_targets, - uint32_t render_targets_count) -{ - uint32_t i; - - for (i = 0; i < render_targets_count; i++) { - if (pthread_mutex_init(&render_targets[i].mutex, NULL)) - goto err_mutex_destroy; - } - - return true; - -err_mutex_destroy: - while (i--) - pthread_mutex_destroy(&render_targets[i].mutex); - - return false; -} - -static void pvr_render_targets_fini(struct pvr_render_target *render_targets, - uint32_t render_targets_count) +void pvr_render_targets_fini(struct pvr_render_target *render_targets, + uint32_t render_targets_count) { for (uint32_t i = 0; i < render_targets_count; i++) { pvr_render_targets_datasets_destroy(&render_targets[i]); @@ -1942,19 +1877,6 @@ static void pvr_render_targets_fini(struct pvr_render_target *render_targets, } } -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) { @@ -1975,206 +1897,6 @@ void pvr_render_state_cleanup(struct pvr_device *device, vk_free(&device->vk.alloc, rstate->render_targets); } -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) -{ - 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; - uint32_t render_targets_count; - VkResult result; - - render_targets_count = - PVR_RENDER_TARGETS_PER_FRAMEBUFFER(&device->pdevice->dev_info); - - VK_MULTIALLOC(ma); - vk_multialloc_add(&ma, - &render_targets, - __typeof__(*render_targets), - render_targets_count); - vk_multialloc_add(&ma, - &spm_eot_state_per_render, - __typeof__(*spm_eot_state_per_render), - render_count); - vk_multialloc_add(&ma, - &spm_bgobj_state_per_render, - __typeof__(*spm_bgobj_state_per_render), - render_count); - - if (!vk_multialloc_zalloc2(&ma, - &device->vk.alloc, - pAllocator, - VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)) { - return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); - } - - 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_render_targets; - } - - assert(rstate->scratch_buffer_size); - result = pvr_spm_scratch_buffer_get_buffer(device, - rstate->scratch_buffer_size, - &rstate->scratch_buffer); - if (result != VK_SUCCESS) - goto err_finish_render_targets; - - 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], - 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], - rstate, - &renders[i]); - if (result != VK_SUCCESS) - goto err_finish_bgobj_state; - - continue; - -err_finish_bgobj_state: - pvr_spm_finish_eot_state(device, &spm_eot_state_per_render[i]); - - for (uint32_t j = 0; j < i; j++) - pvr_spm_finish_bgobj_state(device, &spm_bgobj_state_per_render[j]); - -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_free_ppp_state_bo; - } - - 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_free_framebuffer: - vk_object_base_finish(&framebuffer->base); - vk_free2(&device->vk.alloc, pAllocator, framebuffer); - - return result; -} - -void pvr_DestroyFramebuffer(VkDevice _device, - VkFramebuffer _fb, - const VkAllocationCallbacks *pAllocator) -{ - VK_FROM_HANDLE(pvr_framebuffer, framebuffer, _fb); - VK_FROM_HANDLE(pvr_device, device, _device); - - if (!framebuffer) - return; - - pvr_render_state_cleanup(device, framebuffer->rstate); - /* the render state is freed with the framebuffer */ - - vk_object_base_finish(&framebuffer->base); - vk_free2(&device->vk.alloc, pAllocator, framebuffer); -} - void pvr_GetBufferMemoryRequirements2( VkDevice _device, const VkBufferMemoryRequirementsInfo2 *pInfo, diff --git a/src/imagination/vulkan/pvr_device.h b/src/imagination/vulkan/pvr_device.h index 2edc4e52de3..89e783bde99 100644 --- a/src/imagination/vulkan/pvr_device.h +++ b/src/imagination/vulkan/pvr_device.h @@ -38,6 +38,7 @@ struct pvr_border_color_table; struct pvr_device_static_clear_state; struct pvr_instance; struct pvr_queue; +struct pvr_render_target; struct pvr_compute_query_shader { struct pvr_suballoc_bo *usc_bo; @@ -228,4 +229,7 @@ void pvr_rstate_entry_add(struct pvr_device *device, void pvr_rstate_entry_remove(struct pvr_device *device, const struct pvr_render_state *rstate); +void pvr_render_targets_fini(struct pvr_render_target *render_targets, + uint32_t render_targets_count); + #endif /* PVR_DEVICE_H */ diff --git a/src/imagination/vulkan/pvr_framebuffer.c b/src/imagination/vulkan/pvr_framebuffer.c new file mode 100644 index 00000000000..1e6c5e14a44 --- /dev/null +++ b/src/imagination/vulkan/pvr_framebuffer.c @@ -0,0 +1,306 @@ +/* + * Copyright © 2022 Imagination Technologies Ltd. + * + * based in part on anv driver which is: + * Copyright © 2015 Intel Corporation + * + * based in part on v3dv driver which is: + * Copyright © 2019 Raspberry Pi + * + * SPDX-License-Identifier: MIT + */ + +#include "pvr_framebuffer.h" + +#include "vk_util.h" + +#include "hwdef/pvr_hw_utils.h" + +#include "pvr_cmd_buffer.h" +#include "pvr_csb.h" +#include "pvr_device.h" +#include "pvr_entrypoints.h" +#include "pvr_hw_pass.h" +#include "pvr_image.h" +#include "pvr_pass.h" +#include "pvr_physical_device.h" +#include "pvr_rt_dataset.h" +#include "pvr_spm.h" + +static VkResult +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); + uint32_t ppp_state[3]; + VkResult result; + + pvr_csb_pack (&ppp_state[0], TA_STATE_HEADER, header) { + header.pres_terminate = true; + } + + pvr_csb_pack (&ppp_state[1], TA_STATE_TERMINATE0, term0) { + term0.clip_right = + DIV_ROUND_UP( + rstate->width, + ROGUE_TA_STATE_TERMINATE0_CLIP_RIGHT_BLOCK_SIZE_IN_PIXELS) - + 1; + term0.clip_bottom = + DIV_ROUND_UP( + rstate->height, + ROGUE_TA_STATE_TERMINATE0_CLIP_BOTTOM_BLOCK_SIZE_IN_PIXELS) - + 1; + } + + pvr_csb_pack (&ppp_state[2], TA_STATE_TERMINATE1, term1) { + term1.render_target = 0; + term1.clip_left = 0; + } + + result = pvr_gpu_upload(device, + device->heaps.general_heap, + ppp_state, + sizeof(ppp_state), + cache_line_size, + &rstate->ppp_state_bo); + if (result != VK_SUCCESS) + return result; + + /* Calculate the size of PPP state in dwords. */ + rstate->ppp_state_size = sizeof(ppp_state) / sizeof(uint32_t); + + return VK_SUCCESS; +} + +static bool pvr_render_targets_init(struct pvr_render_target *render_targets, + uint32_t render_targets_count) +{ + uint32_t i; + + for (i = 0; i < render_targets_count; i++) { + if (pthread_mutex_init(&render_targets[i].mutex, NULL)) + goto err_mutex_destroy; + } + + return true; + +err_mutex_destroy: + while (i--) + pthread_mutex_destroy(&render_targets[i].mutex); + + return false; +} + +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) +{ + 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; + uint32_t render_targets_count; + VkResult result; + + render_targets_count = + PVR_RENDER_TARGETS_PER_FRAMEBUFFER(&device->pdevice->dev_info); + + VK_MULTIALLOC(ma); + vk_multialloc_add(&ma, + &render_targets, + __typeof__(*render_targets), + render_targets_count); + vk_multialloc_add(&ma, + &spm_eot_state_per_render, + __typeof__(*spm_eot_state_per_render), + render_count); + vk_multialloc_add(&ma, + &spm_bgobj_state_per_render, + __typeof__(*spm_bgobj_state_per_render), + render_count); + + if (!vk_multialloc_zalloc2(&ma, + &device->vk.alloc, + pAllocator, + VK_SYSTEM_ALLOCATION_SCOPE_OBJECT)) { + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + } + + 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_render_targets; + } + + assert(rstate->scratch_buffer_size); + result = pvr_spm_scratch_buffer_get_buffer(device, + rstate->scratch_buffer_size, + &rstate->scratch_buffer); + if (result != VK_SUCCESS) + goto err_finish_render_targets; + + 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], + 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], + rstate, + &renders[i]); + if (result != VK_SUCCESS) + goto err_finish_bgobj_state; + + continue; + +err_finish_bgobj_state: + pvr_spm_finish_eot_state(device, &spm_eot_state_per_render[i]); + + for (uint32_t j = 0; j < i; j++) + pvr_spm_finish_bgobj_state(device, &spm_bgobj_state_per_render[j]); + +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_free_ppp_state_bo; + } + + 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; +} + +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); +} + +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_free_framebuffer: + vk_object_base_finish(&framebuffer->base); + vk_free2(&device->vk.alloc, pAllocator, framebuffer); + + return result; +} + +void pvr_DestroyFramebuffer(VkDevice _device, + VkFramebuffer _fb, + const VkAllocationCallbacks *pAllocator) +{ + VK_FROM_HANDLE(pvr_framebuffer, framebuffer, _fb); + VK_FROM_HANDLE(pvr_device, device, _device); + + if (!framebuffer) + return; + + pvr_render_state_cleanup(device, framebuffer->rstate); + /* the render state is freed with the framebuffer */ + + 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 032de41ef37..2c8efd56f35 100644 --- a/src/imagination/vulkan/pvr_framebuffer.h +++ b/src/imagination/vulkan/pvr_framebuffer.h @@ -21,6 +21,7 @@ #include "vk_object.h" #include "pvr_limits.h" +#include "pvr_macros.h" struct pvr_render_target { struct pvr_rt_dataset *rt_dataset[PVR_MAX_MULTIVIEW];