diff --git a/src/imagination/csbgen/rogue_cr.xml b/src/imagination/csbgen/rogue_cr.xml
index 3477a77f6d7..8eb345f12ce 100644
--- a/src/imagination/csbgen/rogue_cr.xml
+++ b/src/imagination/csbgen/rogue_cr.xml
@@ -583,7 +583,9 @@ SOFTWARE.
-
+
+
+
diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c
index ab88b2ed448..98f10af0c02 100644
--- a/src/imagination/vulkan/pvr_device.c
+++ b/src/imagination/vulkan/pvr_device.c
@@ -2621,11 +2621,13 @@ VkResult pvr_CreateFramebuffer(VkDevice _device,
const VkAllocationCallbacks *pAllocator,
VkFramebuffer *pFramebuffer)
{
+ PVR_FROM_HANDLE(pvr_render_pass, pass, pCreateInfo->renderPass);
PVR_FROM_HANDLE(pvr_device, device, _device);
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);
@@ -2677,10 +2679,24 @@ VkResult pvr_CreateFramebuffer(VkDevice _device,
goto err_free_ppp_state_bo;
}
+ scratch_buffer_size =
+ pvr_spm_scratch_buffer_calc_required_size(pass,
+ framebuffer->width,
+ framebuffer->height);
+
+ result = pvr_spm_scratch_buffer_get_buffer(device,
+ scratch_buffer_size,
+ &framebuffer->scratch_buffer);
+ if (result != VK_SUCCESS)
+ goto err_finish_render_targets;
+
*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_free(device, framebuffer->ppp_state_bo);
@@ -2695,12 +2711,13 @@ void pvr_DestroyFramebuffer(VkDevice _device,
VkFramebuffer _fb,
const VkAllocationCallbacks *pAllocator)
{
- PVR_FROM_HANDLE(pvr_device, device, _device);
PVR_FROM_HANDLE(pvr_framebuffer, framebuffer, _fb);
+ PVR_FROM_HANDLE(pvr_device, device, _device);
if (!framebuffer)
return;
+ pvr_spm_scratch_buffer_release(device, framebuffer->scratch_buffer);
pvr_render_targets_fini(framebuffer->render_targets,
framebuffer->render_targets_count);
pvr_bo_free(device, framebuffer->ppp_state_bo);
diff --git a/src/imagination/vulkan/pvr_private.h b/src/imagination/vulkan/pvr_private.h
index 592b92906a2..e8fd902b2e0 100644
--- a/src/imagination/vulkan/pvr_private.h
+++ b/src/imagination/vulkan/pvr_private.h
@@ -1294,6 +1294,8 @@ struct pvr_framebuffer {
uint32_t render_targets_count;
struct pvr_render_target *render_targets;
+
+ struct pvr_spm_scratch_buffer *scratch_buffer;
};
struct pvr_render_pass_attachment {
diff --git a/src/imagination/vulkan/pvr_spm.c b/src/imagination/vulkan/pvr_spm.c
index 2bc6aeab14f..3fd26d94ccd 100644
--- a/src/imagination/vulkan/pvr_spm.c
+++ b/src/imagination/vulkan/pvr_spm.c
@@ -69,6 +69,38 @@ 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 dwords_per_pixel;
+ uint64_t buffer_size;
+
+ /* If we're allocating an SPM scratch buffer we'll have a minimum of 1 output
+ * reg and/or tile_buffer.
+ */
+ 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];
+
+ 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;
+
+ buffer_size = ALIGN_POT((uint64_t)framebuffer_width,
+ PVRX(CR_PBE_WORD0_MRT0_LINESTRIDE_ALIGNMENT));
+ buffer_size *= (uint64_t)framebuffer_height * dwords_per_pixel * 4;
+
+ return buffer_size;
+}
+
static VkResult
pvr_spm_scratch_buffer_alloc(struct pvr_device *device,
uint64_t size,
diff --git a/src/imagination/vulkan/pvr_spm.h b/src/imagination/vulkan/pvr_spm.h
index fe0854f33e3..a3475d9c3f6 100644
--- a/src/imagination/vulkan/pvr_spm.h
+++ b/src/imagination/vulkan/pvr_spm.h
@@ -45,6 +45,7 @@
#include "util/simple_mtx.h"
struct pvr_device;
+struct pvr_render_pass;
struct pvr_spm_scratch_buffer;
struct pvr_spm_scratch_buffer_store {
@@ -63,6 +64,10 @@ void pvr_spm_finish_scratch_buffer_store(struct pvr_device *device);
* VK_ATTACHMENT_STORE_OP_NONE, not currently supported) or lazily allocated
* 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);
VkResult pvr_spm_scratch_buffer_get_buffer(
struct pvr_device *device,
uint64_t size,