2022-02-25 10:28:39 +00:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2022 Imagination Technologies Ltd.
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
* in the Software without restriction, including without limitation the rights
|
|
|
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
* copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
* furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
|
* Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
|
* SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include <stdint.h>
|
|
|
|
|
|
|
|
|
|
#include "hwdef/rogue_hw_utils.h"
|
|
|
|
|
#include "pvr_bo.h"
|
|
|
|
|
#include "pvr_device_info.h"
|
|
|
|
|
#include "pvr_formats.h"
|
|
|
|
|
#include "pvr_hw_pass.h"
|
|
|
|
|
#include "pvr_pds.h"
|
|
|
|
|
#include "pvr_private.h"
|
2023-02-14 13:04:39 +00:00
|
|
|
#include "pvr_types.h"
|
2024-04-05 19:43:33 +01:00
|
|
|
#include "usc/programs/pvr_usc_fragment_shader.h"
|
2023-01-27 18:25:57 +00:00
|
|
|
#include "util/macros.h"
|
2022-02-25 10:28:39 +00:00
|
|
|
#include "rogue/rogue.h"
|
|
|
|
|
#include "vk_alloc.h"
|
|
|
|
|
#include "vk_format.h"
|
|
|
|
|
#include "vk_log.h"
|
pvr: Don't merge subpasses on framebuffer-global dependancy
When we have a framebuffer-local dependency we cannot merge
subpasses.
dEQP tests fixed:
dEQP-VK.renderpass.suballocation.attachment_allocation
.input_output.{15,23,35,61,80,93}
dEQP-VK.renderpass.suballocation.attachment_allocation
.roll.{13,31,42,47,55,59,61,98}
Signed-off-by: Karmjit Mahil <Karmjit.Mahil@imgtec.com>
Reviewed-by: Frank Binns <frank.binns@imgtec.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25612>
2023-10-09 10:25:35 +01:00
|
|
|
#include "vk_render_pass.h"
|
2022-02-25 10:28:39 +00:00
|
|
|
|
|
|
|
|
/*****************************************************************************
|
|
|
|
|
PDS pre-baked program generation parameters and variables.
|
|
|
|
|
*****************************************************************************/
|
|
|
|
|
/* These would normally be produced by the compiler or other code. We're using
|
|
|
|
|
* them for now just to speed up things. All of these should eventually be
|
|
|
|
|
* removed.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static const struct {
|
|
|
|
|
/* Indicates the amount of temporaries for the shader. */
|
|
|
|
|
uint32_t temp_count;
|
2024-04-03 21:44:10 +01:00
|
|
|
enum pvr_msaa_mode msaa_mode;
|
2022-02-25 10:28:39 +00:00
|
|
|
/* Indicates the presence of PHAS instruction. */
|
|
|
|
|
bool has_phase_rate_change;
|
|
|
|
|
} pvr_pds_fragment_program_params = {
|
|
|
|
|
.temp_count = 0,
|
2024-04-03 21:44:10 +01:00
|
|
|
.msaa_mode = PVR_MSAA_MODE_PIXEL,
|
2022-02-25 10:28:39 +00:00
|
|
|
.has_phase_rate_change = false,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
static inline bool pvr_subpass_has_msaa_input_attachment(
|
|
|
|
|
struct pvr_render_subpass *subpass,
|
2022-07-01 13:05:45 +01:00
|
|
|
const VkRenderPassCreateInfo2 *pCreateInfo)
|
2022-02-25 10:28:39 +00:00
|
|
|
{
|
|
|
|
|
for (uint32_t i = 0; i < subpass->input_count; i++) {
|
|
|
|
|
const uint32_t attachment = subpass->input_attachments[i];
|
|
|
|
|
|
|
|
|
|
if (pCreateInfo->pAttachments[attachment].samples > 1)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool pvr_is_subpass_initops_flush_needed(
|
|
|
|
|
const struct pvr_render_pass *pass,
|
|
|
|
|
const struct pvr_renderpass_hwsetup_render *hw_render)
|
|
|
|
|
{
|
|
|
|
|
struct pvr_render_subpass *subpass = &pass->subpasses[0];
|
|
|
|
|
uint32_t render_loadop_mask = 0;
|
|
|
|
|
uint32_t color_attachment_mask;
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < hw_render->color_init_count; i++) {
|
2022-08-02 13:52:03 +01:00
|
|
|
if (hw_render->color_init[i].op != VK_ATTACHMENT_LOAD_OP_DONT_CARE)
|
2022-08-02 13:27:35 +01:00
|
|
|
render_loadop_mask |= (1 << hw_render->color_init[i].index);
|
2022-02-25 10:28:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If there are no load ops then there's nothing to flush. */
|
|
|
|
|
if (render_loadop_mask == 0)
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
/* If the first subpass has any input attachments, they need to be
|
|
|
|
|
* initialized with the result of the load op. Since the input attachment
|
|
|
|
|
* may be read from fragments with an opaque pass type, the load ops must be
|
|
|
|
|
* flushed or else they would be obscured and eliminated by HSR.
|
|
|
|
|
*/
|
|
|
|
|
if (subpass->input_count != 0)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
color_attachment_mask = 0;
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < subpass->color_count; i++) {
|
2022-09-25 19:20:22 +01:00
|
|
|
const uint32_t color_idx = subpass->color_attachments[i];
|
2022-02-25 10:28:39 +00:00
|
|
|
|
2022-09-25 19:20:22 +01:00
|
|
|
if (color_idx != VK_ATTACHMENT_UNUSED)
|
2022-02-25 10:28:39 +00:00
|
|
|
color_attachment_mask |= (1 << pass->attachments[color_idx].index);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If the first subpass does not write to all attachments which have a load
|
|
|
|
|
* op then the load ops need to be flushed to ensure they don't get obscured
|
|
|
|
|
* and removed by HSR.
|
|
|
|
|
*/
|
|
|
|
|
return (render_loadop_mask & color_attachment_mask) != render_loadop_mask;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2022-08-23 11:35:25 +01:00
|
|
|
pvr_init_subpass_isp_userpass(struct pvr_renderpass_hwsetup *hw_setup,
|
|
|
|
|
struct pvr_render_pass *pass,
|
|
|
|
|
struct pvr_render_subpass *subpasses)
|
2022-02-25 10:28:39 +00:00
|
|
|
{
|
|
|
|
|
uint32_t subpass_idx = 0;
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < hw_setup->render_count; i++) {
|
|
|
|
|
struct pvr_renderpass_hwsetup_render *hw_render = &hw_setup->renders[i];
|
2022-08-23 11:35:25 +01:00
|
|
|
const uint32_t initial_isp_userpass =
|
2022-02-25 10:28:39 +00:00
|
|
|
(uint32_t)pvr_is_subpass_initops_flush_needed(pass, hw_render);
|
|
|
|
|
|
|
|
|
|
for (uint32_t j = 0; j < hw_render->subpass_count; j++) {
|
2022-09-01 13:13:12 +01:00
|
|
|
subpasses[subpass_idx].isp_userpass =
|
|
|
|
|
(j + initial_isp_userpass) & PVRX(CR_ISP_CTL_UPASS_START_SIZE_MAX);
|
2022-02-25 10:28:39 +00:00
|
|
|
subpass_idx++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert(subpass_idx == pass->subpass_count);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static inline bool pvr_has_output_register_writes(
|
|
|
|
|
const struct pvr_renderpass_hwsetup_render *hw_render)
|
|
|
|
|
{
|
2022-08-02 13:27:35 +01:00
|
|
|
for (uint32_t i = 0; i < hw_render->init_setup.num_render_targets; i++) {
|
2022-02-25 10:28:39 +00:00
|
|
|
struct usc_mrt_resource *mrt_resource =
|
|
|
|
|
&hw_render->init_setup.mrt_resources[i];
|
|
|
|
|
|
2022-08-02 13:27:35 +01:00
|
|
|
if (mrt_resource->type == USC_MRT_RESOURCE_TYPE_OUTPUT_REG)
|
2022-02-25 10:28:39 +00:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-04-04 12:17:47 +01:00
|
|
|
VkResult pvr_pds_unitex_state_program_create_and_upload(
|
2022-02-25 10:28:39 +00:00
|
|
|
struct pvr_device *device,
|
|
|
|
|
const VkAllocationCallbacks *allocator,
|
2022-04-04 12:17:47 +01:00
|
|
|
uint32_t texture_kicks,
|
|
|
|
|
uint32_t uniform_kicks,
|
2022-02-25 10:28:39 +00:00
|
|
|
struct pvr_pds_upload *const pds_upload_out)
|
|
|
|
|
{
|
|
|
|
|
struct pvr_pds_pixel_shader_sa_program program = {
|
2022-04-04 12:17:47 +01:00
|
|
|
.num_texture_dma_kicks = texture_kicks,
|
|
|
|
|
.num_uniform_dma_kicks = uniform_kicks,
|
2022-02-25 10:28:39 +00:00
|
|
|
};
|
|
|
|
|
uint32_t staging_buffer_size;
|
|
|
|
|
uint32_t *staging_buffer;
|
|
|
|
|
VkResult result;
|
|
|
|
|
|
|
|
|
|
pvr_pds_set_sizes_pixel_shader_uniform_texture_code(&program);
|
|
|
|
|
|
2023-02-14 13:04:39 +00:00
|
|
|
staging_buffer_size = PVR_DW_TO_BYTES(program.code_size);
|
2022-02-25 10:28:39 +00:00
|
|
|
|
|
|
|
|
staging_buffer = vk_alloc2(&device->vk.alloc,
|
|
|
|
|
allocator,
|
|
|
|
|
staging_buffer_size,
|
2022-04-04 12:17:47 +01:00
|
|
|
8U,
|
2022-02-25 10:28:39 +00:00
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
|
|
|
|
|
if (!staging_buffer)
|
|
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
|
|
pvr_pds_generate_pixel_shader_sa_code_segment(&program, staging_buffer);
|
|
|
|
|
|
|
|
|
|
/* FIXME: Figure out the define for alignment of 16. */
|
|
|
|
|
result = pvr_gpu_upload_pds(device,
|
|
|
|
|
NULL,
|
2022-04-04 12:17:47 +01:00
|
|
|
0U,
|
|
|
|
|
0U,
|
|
|
|
|
staging_buffer,
|
2022-02-25 10:28:39 +00:00
|
|
|
program.code_size,
|
2022-04-04 12:17:47 +01:00
|
|
|
16U,
|
|
|
|
|
16U,
|
2022-02-25 10:28:39 +00:00
|
|
|
pds_upload_out);
|
|
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
|
vk_free2(&device->vk.alloc, allocator, staging_buffer);
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vk_free2(&device->vk.alloc, allocator, staging_buffer);
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-27 18:25:57 +00:00
|
|
|
/* TODO: pvr_create_subpass_load_op() and pvr_create_render_load_op() are quite
|
|
|
|
|
* similar. See if we can dedup them?
|
|
|
|
|
*/
|
2022-02-25 10:28:39 +00:00
|
|
|
static VkResult
|
2022-08-30 15:50:15 +01:00
|
|
|
pvr_create_subpass_load_op(struct pvr_device *device,
|
|
|
|
|
const VkAllocationCallbacks *allocator,
|
|
|
|
|
const struct pvr_render_pass *pass,
|
|
|
|
|
struct pvr_renderpass_hwsetup_render *hw_render,
|
|
|
|
|
uint32_t hw_subpass_idx,
|
|
|
|
|
struct pvr_load_op **const load_op_out)
|
2022-02-25 10:28:39 +00:00
|
|
|
{
|
2022-08-30 15:50:15 +01:00
|
|
|
const struct pvr_renderpass_hwsetup_subpass *hw_subpass =
|
|
|
|
|
&hw_render->subpasses[hw_subpass_idx];
|
|
|
|
|
const struct pvr_render_subpass *subpass =
|
|
|
|
|
&pass->subpasses[hw_subpass->index];
|
|
|
|
|
|
|
|
|
|
struct pvr_load_op *load_op = vk_zalloc2(&device->vk.alloc,
|
|
|
|
|
allocator,
|
|
|
|
|
sizeof(*load_op),
|
|
|
|
|
8,
|
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
|
|
|
|
|
if (!load_op)
|
|
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
2023-01-27 18:25:57 +00:00
|
|
|
load_op->clears_loads_state.depth_clear_to_reg = PVR_NO_DEPTH_CLEAR_TO_REG;
|
|
|
|
|
|
|
|
|
|
if (hw_subpass->z_replicate != -1) {
|
|
|
|
|
const int32_t z_replicate = hw_subpass->z_replicate;
|
|
|
|
|
|
|
|
|
|
switch (hw_subpass->depth_initop) {
|
|
|
|
|
case VK_ATTACHMENT_LOAD_OP_LOAD:
|
|
|
|
|
assert(z_replicate < PVR_LOAD_OP_CLEARS_LOADS_MAX_RTS);
|
|
|
|
|
load_op->clears_loads_state.rt_load_mask = BITFIELD_BIT(z_replicate);
|
|
|
|
|
load_op->clears_loads_state.dest_vk_format[z_replicate] =
|
|
|
|
|
VK_FORMAT_D32_SFLOAT;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case VK_ATTACHMENT_LOAD_OP_CLEAR:
|
|
|
|
|
load_op->clears_loads_state.depth_clear_to_reg = z_replicate;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2022-08-30 15:50:15 +01:00
|
|
|
}
|
|
|
|
|
|
2023-01-27 18:25:57 +00:00
|
|
|
assert(subpass->color_count <= PVR_LOAD_OP_CLEARS_LOADS_MAX_RTS);
|
2022-08-30 15:50:15 +01:00
|
|
|
for (uint32_t i = 0; i < subpass->color_count; i++) {
|
2023-01-27 18:25:57 +00:00
|
|
|
const uint32_t attachment_idx = subpass->color_attachments[i];
|
2022-08-30 15:50:15 +01:00
|
|
|
|
2023-01-27 18:25:57 +00:00
|
|
|
assert(attachment_idx < pass->attachment_count);
|
|
|
|
|
load_op->clears_loads_state.dest_vk_format[i] =
|
|
|
|
|
pass->attachments[attachment_idx].vk_format;
|
|
|
|
|
|
|
|
|
|
if (pass->attachments[attachment_idx].sample_count > 1)
|
2023-09-26 22:48:08 +01:00
|
|
|
load_op->clears_loads_state.unresolved_msaa_mask |= BITFIELD_BIT(i);
|
2023-01-27 18:25:57 +00:00
|
|
|
|
|
|
|
|
if (hw_subpass->color_initops[i] == VK_ATTACHMENT_LOAD_OP_LOAD)
|
|
|
|
|
load_op->clears_loads_state.rt_load_mask |= BITFIELD_BIT(i);
|
|
|
|
|
else if (hw_subpass->color_initops[i] == VK_ATTACHMENT_LOAD_OP_CLEAR)
|
|
|
|
|
load_op->clears_loads_state.rt_clear_mask |= BITFIELD_BIT(i);
|
2022-08-30 15:50:15 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
load_op->is_hw_object = false;
|
|
|
|
|
load_op->subpass = subpass;
|
|
|
|
|
|
|
|
|
|
*load_op_out = load_op;
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
2022-02-25 10:28:39 +00:00
|
|
|
|
2022-08-30 15:50:15 +01:00
|
|
|
static VkResult
|
|
|
|
|
pvr_create_render_load_op(struct pvr_device *device,
|
|
|
|
|
const VkAllocationCallbacks *allocator,
|
2023-01-27 18:25:57 +00:00
|
|
|
const struct pvr_render_pass *pass,
|
|
|
|
|
const struct pvr_renderpass_hwsetup_render *hw_render,
|
2022-08-30 15:50:15 +01:00
|
|
|
struct pvr_load_op **const load_op_out)
|
|
|
|
|
{
|
|
|
|
|
struct pvr_load_op *load_op = vk_zalloc2(&device->vk.alloc,
|
|
|
|
|
allocator,
|
|
|
|
|
sizeof(*load_op),
|
|
|
|
|
8,
|
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
|
2022-02-25 10:28:39 +00:00
|
|
|
if (!load_op)
|
|
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
2023-01-27 18:25:57 +00:00
|
|
|
load_op->clears_loads_state.depth_clear_to_reg = PVR_NO_DEPTH_CLEAR_TO_REG;
|
|
|
|
|
|
|
|
|
|
assert(hw_render->color_init_count <= PVR_LOAD_OP_CLEARS_LOADS_MAX_RTS);
|
2022-02-25 10:28:39 +00:00
|
|
|
for (uint32_t i = 0; i < hw_render->color_init_count; i++) {
|
|
|
|
|
struct pvr_renderpass_colorinit *color_init = &hw_render->color_init[i];
|
|
|
|
|
|
2023-01-27 18:25:57 +00:00
|
|
|
assert(color_init->index < pass->attachment_count);
|
|
|
|
|
load_op->clears_loads_state.dest_vk_format[i] =
|
|
|
|
|
pass->attachments[color_init->index].vk_format;
|
|
|
|
|
|
|
|
|
|
if (pass->attachments[color_init->index].sample_count > 1)
|
2023-09-26 22:48:08 +01:00
|
|
|
load_op->clears_loads_state.unresolved_msaa_mask |= BITFIELD_BIT(i);
|
2023-01-27 18:25:57 +00:00
|
|
|
|
|
|
|
|
if (color_init->op == VK_ATTACHMENT_LOAD_OP_LOAD)
|
|
|
|
|
load_op->clears_loads_state.rt_load_mask |= BITFIELD_BIT(i);
|
|
|
|
|
else if (color_init->op == VK_ATTACHMENT_LOAD_OP_CLEAR)
|
|
|
|
|
load_op->clears_loads_state.rt_clear_mask |= BITFIELD_BIT(i);
|
2022-02-25 10:28:39 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-30 15:50:15 +01:00
|
|
|
load_op->is_hw_object = true;
|
|
|
|
|
load_op->hw_render = hw_render;
|
|
|
|
|
|
|
|
|
|
*load_op_out = load_op;
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static VkResult
|
|
|
|
|
pvr_generate_load_op_shader(struct pvr_device *device,
|
|
|
|
|
const VkAllocationCallbacks *allocator,
|
|
|
|
|
struct pvr_renderpass_hwsetup_render *hw_render,
|
|
|
|
|
struct pvr_load_op *load_op)
|
|
|
|
|
{
|
|
|
|
|
const struct pvr_device_info *dev_info = &device->pdevice->dev_info;
|
|
|
|
|
const uint32_t cache_line_size = rogue_get_slc_cache_line_size(dev_info);
|
|
|
|
|
|
|
|
|
|
VkResult result = pvr_gpu_upload_usc(device,
|
|
|
|
|
pvr_usc_fragment_shader,
|
|
|
|
|
sizeof(pvr_usc_fragment_shader),
|
|
|
|
|
cache_line_size,
|
|
|
|
|
&load_op->usc_frag_prog_bo);
|
2022-02-25 10:28:39 +00:00
|
|
|
if (result != VK_SUCCESS)
|
2022-08-30 15:50:15 +01:00
|
|
|
return result;
|
2022-02-25 10:28:39 +00:00
|
|
|
|
|
|
|
|
result = pvr_pds_fragment_program_create_and_upload(
|
|
|
|
|
device,
|
|
|
|
|
allocator,
|
|
|
|
|
load_op->usc_frag_prog_bo,
|
|
|
|
|
pvr_pds_fragment_program_params.temp_count,
|
|
|
|
|
pvr_pds_fragment_program_params.msaa_mode,
|
|
|
|
|
pvr_pds_fragment_program_params.has_phase_rate_change,
|
|
|
|
|
&load_op->pds_frag_prog);
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
|
goto err_free_usc_frag_prog_bo;
|
|
|
|
|
|
2022-04-04 12:17:47 +01:00
|
|
|
result = pvr_pds_unitex_state_program_create_and_upload(
|
2022-02-25 10:28:39 +00:00
|
|
|
device,
|
|
|
|
|
allocator,
|
2022-04-04 12:17:47 +01:00
|
|
|
1U,
|
|
|
|
|
0U,
|
2022-02-25 10:28:39 +00:00
|
|
|
&load_op->pds_tex_state_prog);
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
|
goto err_free_pds_frag_prog;
|
|
|
|
|
|
|
|
|
|
/* FIXME: These should be based on the USC and PDS programs, but are hard
|
|
|
|
|
* coded for now.
|
|
|
|
|
*/
|
|
|
|
|
load_op->const_shareds_count = 1;
|
|
|
|
|
load_op->shareds_dest_offset = 0;
|
|
|
|
|
load_op->shareds_count = 1;
|
|
|
|
|
load_op->temps_count = 1;
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
|
|
err_free_pds_frag_prog:
|
2023-05-10 08:29:35 +01:00
|
|
|
pvr_bo_suballoc_free(load_op->pds_frag_prog.pvr_bo);
|
2022-02-25 10:28:39 +00:00
|
|
|
|
|
|
|
|
err_free_usc_frag_prog_bo:
|
2023-05-10 08:29:35 +01:00
|
|
|
pvr_bo_suballoc_free(load_op->usc_frag_prog_bo);
|
2022-02-25 10:28:39 +00:00
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void pvr_load_op_destroy(struct pvr_device *device,
|
|
|
|
|
const VkAllocationCallbacks *allocator,
|
|
|
|
|
struct pvr_load_op *load_op)
|
|
|
|
|
{
|
2023-05-10 08:29:35 +01:00
|
|
|
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);
|
2022-02-25 10:28:39 +00:00
|
|
|
vk_free2(&device->vk.alloc, allocator, load_op);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define PVR_SPM_LOAD_IN_BUFFERS_COUNT(dev_info) \
|
|
|
|
|
({ \
|
2022-11-17 17:17:42 +00:00
|
|
|
int __ret = PVR_MAX_TILE_BUFFER_COUNT; \
|
2022-02-25 10:28:39 +00:00
|
|
|
if (PVR_HAS_FEATURE(dev_info, eight_output_registers)) \
|
2022-11-17 17:17:42 +00:00
|
|
|
__ret -= 4U; \
|
2022-02-25 10:28:39 +00:00
|
|
|
__ret; \
|
|
|
|
|
})
|
|
|
|
|
|
2022-08-30 15:50:15 +01:00
|
|
|
static bool
|
|
|
|
|
pvr_is_load_op_needed(const struct pvr_render_pass *pass,
|
|
|
|
|
struct pvr_renderpass_hwsetup_render *hw_render,
|
|
|
|
|
const uint32_t subpass_idx)
|
|
|
|
|
{
|
|
|
|
|
struct pvr_renderpass_hwsetup_subpass *hw_subpass =
|
|
|
|
|
&hw_render->subpasses[subpass_idx];
|
|
|
|
|
const struct pvr_render_subpass *subpass =
|
|
|
|
|
&pass->subpasses[hw_subpass->index];
|
|
|
|
|
|
|
|
|
|
if (hw_subpass->z_replicate != -1 &&
|
|
|
|
|
(hw_subpass->depth_initop == VK_ATTACHMENT_LOAD_OP_LOAD ||
|
|
|
|
|
hw_subpass->depth_initop == VK_ATTACHMENT_LOAD_OP_CLEAR)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < subpass->color_count; i++) {
|
2022-09-25 19:20:22 +01:00
|
|
|
if (subpass->color_attachments[i] == VK_ATTACHMENT_UNUSED)
|
2022-08-30 15:50:15 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (hw_subpass->color_initops[i] == VK_ATTACHMENT_LOAD_OP_LOAD ||
|
|
|
|
|
hw_subpass->color_initops[i] == VK_ATTACHMENT_LOAD_OP_CLEAR) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-25 10:28:39 +00:00
|
|
|
VkResult pvr_CreateRenderPass2(VkDevice _device,
|
2022-07-01 13:05:45 +01:00
|
|
|
const VkRenderPassCreateInfo2 *pCreateInfo,
|
2022-02-25 10:28:39 +00:00
|
|
|
const VkAllocationCallbacks *pAllocator,
|
|
|
|
|
VkRenderPass *pRenderPass)
|
|
|
|
|
{
|
|
|
|
|
struct pvr_render_pass_attachment *attachments;
|
|
|
|
|
PVR_FROM_HANDLE(pvr_device, device, _device);
|
|
|
|
|
struct pvr_render_subpass *subpasses;
|
2022-08-03 17:53:32 +01:00
|
|
|
const VkAllocationCallbacks *alloc;
|
2022-02-25 10:28:39 +00:00
|
|
|
size_t subpass_attachment_count;
|
|
|
|
|
uint32_t *subpass_attachments;
|
|
|
|
|
struct pvr_render_pass *pass;
|
|
|
|
|
uint32_t *dep_list;
|
|
|
|
|
bool *flush_on_dep;
|
|
|
|
|
VkResult result;
|
|
|
|
|
|
2022-08-03 17:53:32 +01:00
|
|
|
alloc = pAllocator ? pAllocator : &device->vk.alloc;
|
|
|
|
|
|
2022-02-25 10:28:39 +00:00
|
|
|
VK_MULTIALLOC(ma);
|
|
|
|
|
vk_multialloc_add(&ma, &pass, __typeof__(*pass), 1);
|
|
|
|
|
vk_multialloc_add(&ma,
|
|
|
|
|
&attachments,
|
|
|
|
|
__typeof__(*attachments),
|
|
|
|
|
pCreateInfo->attachmentCount);
|
|
|
|
|
vk_multialloc_add(&ma,
|
|
|
|
|
&subpasses,
|
|
|
|
|
__typeof__(*subpasses),
|
|
|
|
|
pCreateInfo->subpassCount);
|
|
|
|
|
|
|
|
|
|
subpass_attachment_count = 0;
|
|
|
|
|
for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
|
2023-01-31 19:24:30 +00:00
|
|
|
const VkSubpassDescription2 *desc = &pCreateInfo->pSubpasses[i];
|
2022-02-25 10:28:39 +00:00
|
|
|
subpass_attachment_count +=
|
2023-01-31 19:24:30 +00:00
|
|
|
desc->inputAttachmentCount + desc->colorAttachmentCount +
|
|
|
|
|
(desc->pResolveAttachments ? desc->colorAttachmentCount : 0);
|
2022-02-25 10:28:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vk_multialloc_add(&ma,
|
|
|
|
|
&subpass_attachments,
|
|
|
|
|
__typeof__(*subpass_attachments),
|
|
|
|
|
subpass_attachment_count);
|
|
|
|
|
vk_multialloc_add(&ma,
|
|
|
|
|
&dep_list,
|
|
|
|
|
__typeof__(*dep_list),
|
|
|
|
|
pCreateInfo->dependencyCount);
|
|
|
|
|
vk_multialloc_add(&ma,
|
|
|
|
|
&flush_on_dep,
|
|
|
|
|
__typeof__(*flush_on_dep),
|
|
|
|
|
pCreateInfo->dependencyCount);
|
|
|
|
|
|
2022-08-03 17:53:32 +01:00
|
|
|
if (!vk_multialloc_zalloc(&ma, alloc, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
|
2022-02-25 10:28:39 +00:00
|
|
|
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
|
|
|
|
|
vk_object_base_init(&device->vk, &pass->base, VK_OBJECT_TYPE_RENDER_PASS);
|
|
|
|
|
pass->attachment_count = pCreateInfo->attachmentCount;
|
|
|
|
|
pass->attachments = attachments;
|
|
|
|
|
pass->subpass_count = pCreateInfo->subpassCount;
|
|
|
|
|
pass->subpasses = subpasses;
|
|
|
|
|
pass->max_sample_count = 1;
|
|
|
|
|
|
|
|
|
|
/* Copy attachment descriptions. */
|
|
|
|
|
for (uint32_t i = 0; i < pass->attachment_count; i++) {
|
|
|
|
|
const VkAttachmentDescription2 *desc = &pCreateInfo->pAttachments[i];
|
|
|
|
|
struct pvr_render_pass_attachment *attachment = &pass->attachments[i];
|
|
|
|
|
|
|
|
|
|
pvr_assert(!(desc->flags & ~VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT));
|
|
|
|
|
|
|
|
|
|
attachment->load_op = desc->loadOp;
|
|
|
|
|
attachment->store_op = desc->storeOp;
|
|
|
|
|
|
2022-10-28 17:13:43 +01:00
|
|
|
attachment->aspects = vk_format_aspects(desc->format);
|
|
|
|
|
if (attachment->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
|
2022-02-25 10:28:39 +00:00
|
|
|
attachment->stencil_load_op = desc->stencilLoadOp;
|
|
|
|
|
attachment->stencil_store_op = desc->stencilStoreOp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
attachment->vk_format = desc->format;
|
|
|
|
|
attachment->sample_count = desc->samples;
|
|
|
|
|
attachment->initial_layout = desc->initialLayout;
|
|
|
|
|
attachment->is_pbe_downscalable =
|
|
|
|
|
pvr_format_is_pbe_downscalable(attachment->vk_format);
|
|
|
|
|
attachment->index = i;
|
|
|
|
|
|
|
|
|
|
if (attachment->sample_count > pass->max_sample_count)
|
|
|
|
|
pass->max_sample_count = attachment->sample_count;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Count how many dependencies each subpass has. */
|
|
|
|
|
for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) {
|
|
|
|
|
const VkSubpassDependency2 *dep = &pCreateInfo->pDependencies[i];
|
|
|
|
|
|
|
|
|
|
if (dep->srcSubpass != VK_SUBPASS_EXTERNAL &&
|
|
|
|
|
dep->dstSubpass != VK_SUBPASS_EXTERNAL &&
|
|
|
|
|
dep->srcSubpass != dep->dstSubpass) {
|
|
|
|
|
pass->subpasses[dep->dstSubpass].dep_count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Assign reference pointers to lists, and fill in the attachments list, we
|
|
|
|
|
* need to re-walk the dependencies array later to fill the per-subpass
|
|
|
|
|
* dependencies lists in.
|
|
|
|
|
*/
|
|
|
|
|
for (uint32_t i = 0; i < pass->subpass_count; i++) {
|
|
|
|
|
const VkSubpassDescription2 *desc = &pCreateInfo->pSubpasses[i];
|
|
|
|
|
struct pvr_render_subpass *subpass = &pass->subpasses[i];
|
|
|
|
|
|
|
|
|
|
subpass->pipeline_bind_point = desc->pipelineBindPoint;
|
|
|
|
|
|
2023-09-24 13:54:49 +01:00
|
|
|
/* From the Vulkan spec. 1.3.265
|
|
|
|
|
* VUID-VkSubpassDescription2-multisampledRenderToSingleSampled-06872:
|
|
|
|
|
*
|
|
|
|
|
* "If none of the VK_AMD_mixed_attachment_samples extension, the
|
|
|
|
|
* VK_NV_framebuffer_mixed_samples extension, or the
|
|
|
|
|
* multisampledRenderToSingleSampled feature are enabled, all
|
|
|
|
|
* attachments in pDepthStencilAttachment or pColorAttachments that are
|
|
|
|
|
* not VK_ATTACHMENT_UNUSED must have the same sample count"
|
|
|
|
|
*
|
|
|
|
|
*/
|
2023-09-24 14:14:15 +01:00
|
|
|
subpass->sample_count = VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM;
|
|
|
|
|
|
|
|
|
|
if (desc->pDepthStencilAttachment) {
|
|
|
|
|
uint32_t index = desc->pDepthStencilAttachment->attachment;
|
|
|
|
|
|
|
|
|
|
if (index != VK_ATTACHMENT_UNUSED)
|
|
|
|
|
subpass->sample_count = pass->attachments[index].sample_count;
|
|
|
|
|
|
|
|
|
|
subpass->depth_stencil_attachment = index;
|
|
|
|
|
} else {
|
|
|
|
|
subpass->depth_stencil_attachment = VK_ATTACHMENT_UNUSED;
|
|
|
|
|
}
|
2023-09-24 13:54:49 +01:00
|
|
|
|
2022-02-25 10:28:39 +00:00
|
|
|
subpass->color_count = desc->colorAttachmentCount;
|
|
|
|
|
if (subpass->color_count > 0) {
|
|
|
|
|
subpass->color_attachments = subpass_attachments;
|
|
|
|
|
subpass_attachments += subpass->color_count;
|
|
|
|
|
|
|
|
|
|
for (uint32_t j = 0; j < subpass->color_count; j++) {
|
|
|
|
|
subpass->color_attachments[j] =
|
|
|
|
|
desc->pColorAttachments[j].attachment;
|
|
|
|
|
|
|
|
|
|
if (subpass->color_attachments[j] == VK_ATTACHMENT_UNUSED)
|
|
|
|
|
continue;
|
|
|
|
|
|
2023-09-24 14:14:15 +01:00
|
|
|
if (subpass->sample_count == VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM) {
|
|
|
|
|
uint32_t index;
|
|
|
|
|
index = subpass->color_attachments[j];
|
|
|
|
|
subpass->sample_count = pass->attachments[index].sample_count;
|
|
|
|
|
}
|
2022-02-25 10:28:39 +00:00
|
|
|
}
|
2023-09-24 13:54:49 +01:00
|
|
|
}
|
2022-02-25 10:28:39 +00:00
|
|
|
|
2023-09-24 14:14:15 +01:00
|
|
|
if (subpass->sample_count == VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM)
|
|
|
|
|
subpass->sample_count = VK_SAMPLE_COUNT_1_BIT;
|
2022-02-25 10:28:39 +00:00
|
|
|
|
|
|
|
|
if (desc->pResolveAttachments) {
|
|
|
|
|
subpass->resolve_attachments = subpass_attachments;
|
|
|
|
|
subpass_attachments += subpass->color_count;
|
|
|
|
|
|
|
|
|
|
for (uint32_t j = 0; j < subpass->color_count; j++) {
|
|
|
|
|
subpass->resolve_attachments[j] =
|
|
|
|
|
desc->pResolveAttachments[j].attachment;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
subpass->input_count = desc->inputAttachmentCount;
|
|
|
|
|
if (subpass->input_count > 0) {
|
|
|
|
|
subpass->input_attachments = subpass_attachments;
|
|
|
|
|
subpass_attachments += subpass->input_count;
|
|
|
|
|
|
|
|
|
|
for (uint32_t j = 0; j < subpass->input_count; j++) {
|
|
|
|
|
subpass->input_attachments[j] =
|
|
|
|
|
desc->pInputAttachments[j].attachment;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Give the dependencies a slice of the subpass_attachments array. */
|
|
|
|
|
subpass->dep_list = dep_list;
|
|
|
|
|
dep_list += subpass->dep_count;
|
|
|
|
|
subpass->flush_on_dep = flush_on_dep;
|
|
|
|
|
flush_on_dep += subpass->dep_count;
|
|
|
|
|
|
|
|
|
|
/* Reset the dependencies count so we can start from 0 and index into
|
|
|
|
|
* the dependencies array.
|
|
|
|
|
*/
|
|
|
|
|
subpass->dep_count = 0;
|
|
|
|
|
subpass->index = i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Compute dependencies and populate dep_list and flush_on_dep. */
|
|
|
|
|
for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) {
|
|
|
|
|
const VkSubpassDependency2 *dep = &pCreateInfo->pDependencies[i];
|
|
|
|
|
|
|
|
|
|
if (dep->srcSubpass != VK_SUBPASS_EXTERNAL &&
|
|
|
|
|
dep->dstSubpass != VK_SUBPASS_EXTERNAL &&
|
|
|
|
|
dep->srcSubpass != dep->dstSubpass) {
|
|
|
|
|
struct pvr_render_subpass *subpass = &pass->subpasses[dep->dstSubpass];
|
pvr: Don't merge subpasses on framebuffer-global dependancy
When we have a framebuffer-local dependency we cannot merge
subpasses.
dEQP tests fixed:
dEQP-VK.renderpass.suballocation.attachment_allocation
.input_output.{15,23,35,61,80,93}
dEQP-VK.renderpass.suballocation.attachment_allocation
.roll.{13,31,42,47,55,59,61,98}
Signed-off-by: Karmjit Mahil <Karmjit.Mahil@imgtec.com>
Reviewed-by: Frank Binns <frank.binns@imgtec.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25612>
2023-10-09 10:25:35 +01:00
|
|
|
bool is_dep_fb_local =
|
|
|
|
|
vk_subpass_dependency_is_fb_local(dep,
|
|
|
|
|
dep->srcStageMask,
|
|
|
|
|
dep->dstStageMask);
|
2022-02-25 10:28:39 +00:00
|
|
|
|
|
|
|
|
subpass->dep_list[subpass->dep_count] = dep->srcSubpass;
|
pvr: Don't merge subpasses on framebuffer-global dependancy
When we have a framebuffer-local dependency we cannot merge
subpasses.
dEQP tests fixed:
dEQP-VK.renderpass.suballocation.attachment_allocation
.input_output.{15,23,35,61,80,93}
dEQP-VK.renderpass.suballocation.attachment_allocation
.roll.{13,31,42,47,55,59,61,98}
Signed-off-by: Karmjit Mahil <Karmjit.Mahil@imgtec.com>
Reviewed-by: Frank Binns <frank.binns@imgtec.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25612>
2023-10-09 10:25:35 +01:00
|
|
|
if (pvr_subpass_has_msaa_input_attachment(subpass, pCreateInfo) ||
|
|
|
|
|
!is_dep_fb_local) {
|
2022-02-25 10:28:39 +00:00
|
|
|
subpass->flush_on_dep[subpass->dep_count] = true;
|
pvr: Don't merge subpasses on framebuffer-global dependancy
When we have a framebuffer-local dependency we cannot merge
subpasses.
dEQP tests fixed:
dEQP-VK.renderpass.suballocation.attachment_allocation
.input_output.{15,23,35,61,80,93}
dEQP-VK.renderpass.suballocation.attachment_allocation
.roll.{13,31,42,47,55,59,61,98}
Signed-off-by: Karmjit Mahil <Karmjit.Mahil@imgtec.com>
Reviewed-by: Frank Binns <frank.binns@imgtec.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25612>
2023-10-09 10:25:35 +01:00
|
|
|
}
|
2022-02-25 10:28:39 +00:00
|
|
|
|
|
|
|
|
subpass->dep_count++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pass->max_tilebuffer_count =
|
|
|
|
|
PVR_SPM_LOAD_IN_BUFFERS_COUNT(&device->pdevice->dev_info);
|
|
|
|
|
|
2022-07-05 12:26:37 +01:00
|
|
|
result =
|
2022-08-03 17:53:32 +01:00
|
|
|
pvr_create_renderpass_hwsetup(device, alloc, pass, false, &pass->hw_setup);
|
2022-07-05 12:26:37 +01:00
|
|
|
if (result != VK_SUCCESS)
|
2022-02-25 10:28:39 +00:00
|
|
|
goto err_free_pass;
|
|
|
|
|
|
2022-08-23 11:35:25 +01:00
|
|
|
pvr_init_subpass_isp_userpass(pass->hw_setup, pass, pass->subpasses);
|
2022-02-25 10:28:39 +00:00
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < pass->hw_setup->render_count; i++) {
|
|
|
|
|
struct pvr_renderpass_hwsetup_render *hw_render =
|
|
|
|
|
&pass->hw_setup->renders[i];
|
|
|
|
|
struct pvr_load_op *load_op = NULL;
|
|
|
|
|
|
2022-11-17 17:17:42 +00:00
|
|
|
if (hw_render->tile_buffers_count) {
|
|
|
|
|
result = pvr_device_tile_buffer_ensure_cap(
|
|
|
|
|
device,
|
|
|
|
|
hw_render->tile_buffers_count,
|
|
|
|
|
hw_render->eot_setup.tile_buffer_size);
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
|
goto err_free_pass;
|
|
|
|
|
}
|
2022-02-25 10:28:39 +00:00
|
|
|
|
2022-08-30 15:50:15 +01:00
|
|
|
assert(!hw_render->load_op);
|
|
|
|
|
|
|
|
|
|
if (hw_render->color_init_count != 0U) {
|
|
|
|
|
if (!pvr_has_output_register_writes(hw_render)) {
|
|
|
|
|
const uint32_t last = hw_render->init_setup.num_render_targets;
|
|
|
|
|
struct usc_mrt_resource *mrt_resources;
|
|
|
|
|
|
|
|
|
|
hw_render->init_setup.num_render_targets++;
|
|
|
|
|
|
|
|
|
|
mrt_resources =
|
|
|
|
|
vk_realloc(alloc,
|
|
|
|
|
hw_render->init_setup.mrt_resources,
|
|
|
|
|
hw_render->init_setup.num_render_targets *
|
|
|
|
|
sizeof(*mrt_resources),
|
|
|
|
|
8U,
|
|
|
|
|
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
|
|
|
if (!mrt_resources) {
|
|
|
|
|
result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
|
|
|
|
goto err_load_op_destroy;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hw_render->init_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;
|
|
|
|
|
}
|
2022-02-25 10:28:39 +00:00
|
|
|
|
2023-01-27 18:25:57 +00:00
|
|
|
result = pvr_create_render_load_op(device,
|
|
|
|
|
pAllocator,
|
|
|
|
|
pass,
|
|
|
|
|
hw_render,
|
|
|
|
|
&load_op);
|
2023-05-05 13:45:07 +01:00
|
|
|
if (result != VK_SUCCESS)
|
2022-08-03 17:53:32 +01:00
|
|
|
goto err_load_op_destroy;
|
|
|
|
|
|
2022-08-30 15:50:15 +01:00
|
|
|
result =
|
|
|
|
|
pvr_generate_load_op_shader(device, pAllocator, hw_render, load_op);
|
2023-05-05 13:45:07 +01:00
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
|
vk_free2(&device->vk.alloc, pAllocator, load_op);
|
2022-08-30 15:50:15 +01:00
|
|
|
goto err_load_op_destroy;
|
2023-05-05 13:45:07 +01:00
|
|
|
}
|
2022-08-30 15:50:15 +01:00
|
|
|
|
|
|
|
|
hw_render->load_op = load_op;
|
2022-08-03 17:53:32 +01:00
|
|
|
}
|
2022-02-25 10:28:39 +00:00
|
|
|
|
2022-08-30 15:50:15 +01:00
|
|
|
for (uint32_t j = 0; j < hw_render->subpass_count; j++) {
|
|
|
|
|
if (!pvr_is_load_op_needed(pass, hw_render, j))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
result = pvr_create_subpass_load_op(device,
|
|
|
|
|
pAllocator,
|
|
|
|
|
pass,
|
|
|
|
|
hw_render,
|
|
|
|
|
j,
|
|
|
|
|
&load_op);
|
|
|
|
|
if (result != VK_SUCCESS) {
|
|
|
|
|
vk_free2(&device->vk.alloc, pAllocator, load_op);
|
|
|
|
|
goto err_load_op_destroy;
|
|
|
|
|
}
|
2022-02-25 10:28:39 +00:00
|
|
|
|
2022-08-30 15:50:15 +01:00
|
|
|
result =
|
|
|
|
|
pvr_generate_load_op_shader(device, pAllocator, hw_render, load_op);
|
|
|
|
|
if (result != VK_SUCCESS)
|
|
|
|
|
goto err_load_op_destroy;
|
|
|
|
|
|
|
|
|
|
hw_render->subpasses[j].load_op = load_op;
|
|
|
|
|
}
|
2022-02-25 10:28:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*pRenderPass = pvr_render_pass_to_handle(pass);
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
|
|
err_load_op_destroy:
|
|
|
|
|
for (uint32_t i = 0; i < pass->hw_setup->render_count; i++) {
|
|
|
|
|
struct pvr_renderpass_hwsetup_render *hw_render =
|
|
|
|
|
&pass->hw_setup->renders[i];
|
|
|
|
|
|
2022-08-30 15:50:15 +01:00
|
|
|
for (uint32_t j = 0; j < hw_render->subpass_count; j++) {
|
|
|
|
|
if (hw_render->subpasses[j].load_op) {
|
|
|
|
|
pvr_load_op_destroy(device,
|
|
|
|
|
pAllocator,
|
|
|
|
|
hw_render->subpasses[j].load_op);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-05 12:26:37 +01:00
|
|
|
if (hw_render->load_op)
|
|
|
|
|
pvr_load_op_destroy(device, pAllocator, hw_render->load_op);
|
2022-02-25 10:28:39 +00:00
|
|
|
}
|
|
|
|
|
|
2022-08-03 17:53:32 +01:00
|
|
|
pvr_destroy_renderpass_hwsetup(alloc, pass->hw_setup);
|
2022-02-25 10:28:39 +00:00
|
|
|
|
|
|
|
|
err_free_pass:
|
|
|
|
|
vk_object_base_finish(&pass->base);
|
|
|
|
|
vk_free2(&device->vk.alloc, pAllocator, pass);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pvr_DestroyRenderPass(VkDevice _device,
|
|
|
|
|
VkRenderPass _pass,
|
|
|
|
|
const VkAllocationCallbacks *pAllocator)
|
|
|
|
|
{
|
|
|
|
|
PVR_FROM_HANDLE(pvr_device, device, _device);
|
|
|
|
|
PVR_FROM_HANDLE(pvr_render_pass, pass, _pass);
|
|
|
|
|
|
|
|
|
|
if (!pass)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < pass->hw_setup->render_count; i++) {
|
|
|
|
|
struct pvr_renderpass_hwsetup_render *hw_render =
|
|
|
|
|
&pass->hw_setup->renders[i];
|
|
|
|
|
|
2022-08-30 15:50:15 +01:00
|
|
|
for (uint32_t j = 0; j < hw_render->subpass_count; j++) {
|
|
|
|
|
if (hw_render->subpasses[j].load_op) {
|
|
|
|
|
pvr_load_op_destroy(device,
|
|
|
|
|
pAllocator,
|
|
|
|
|
hw_render->subpasses[j].load_op);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (hw_render->load_op)
|
|
|
|
|
pvr_load_op_destroy(device, pAllocator, hw_render->load_op);
|
2022-02-25 10:28:39 +00:00
|
|
|
}
|
|
|
|
|
|
2022-07-05 12:26:37 +01:00
|
|
|
pvr_destroy_renderpass_hwsetup(pAllocator ? pAllocator : &device->vk.alloc,
|
|
|
|
|
pass->hw_setup);
|
2022-02-25 10:28:39 +00:00
|
|
|
vk_object_base_finish(&pass->base);
|
|
|
|
|
vk_free2(&device->vk.alloc, pAllocator, pass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void pvr_GetRenderAreaGranularity(VkDevice _device,
|
|
|
|
|
VkRenderPass renderPass,
|
|
|
|
|
VkExtent2D *pGranularity)
|
|
|
|
|
{
|
|
|
|
|
PVR_FROM_HANDLE(pvr_device, device, _device);
|
|
|
|
|
const struct pvr_device_info *dev_info = &device->pdevice->dev_info;
|
|
|
|
|
|
|
|
|
|
/* Granularity does not depend on any settings in the render pass, so return
|
|
|
|
|
* the tile granularity.
|
|
|
|
|
*
|
|
|
|
|
* The default value is based on the minimum value found in all existing
|
|
|
|
|
* cores.
|
|
|
|
|
*/
|
|
|
|
|
pGranularity->width = PVR_GET_FEATURE_VALUE(dev_info, tile_size_x, 16);
|
|
|
|
|
pGranularity->height = PVR_GET_FEATURE_VALUE(dev_info, tile_size_y, 16);
|
|
|
|
|
}
|