xref: /aosp_15_r20/external/mesa3d/src/imagination/vulkan/pvr_pass.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1*61046927SAndroid Build Coastguard Worker /*
2*61046927SAndroid Build Coastguard Worker  * Copyright © 2022 Imagination Technologies Ltd.
3*61046927SAndroid Build Coastguard Worker  *
4*61046927SAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
5*61046927SAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to deal
6*61046927SAndroid Build Coastguard Worker  * in the Software without restriction, including without limitation the rights
7*61046927SAndroid Build Coastguard Worker  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8*61046927SAndroid Build Coastguard Worker  * copies of the Software, and to permit persons to whom the Software is
9*61046927SAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
10*61046927SAndroid Build Coastguard Worker  *
11*61046927SAndroid Build Coastguard Worker  * The above copyright notice and this permission notice (including the next
12*61046927SAndroid Build Coastguard Worker  * paragraph) shall be included in all copies or substantial portions of the
13*61046927SAndroid Build Coastguard Worker  * Software.
14*61046927SAndroid Build Coastguard Worker  *
15*61046927SAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16*61046927SAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17*61046927SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18*61046927SAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19*61046927SAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20*61046927SAndroid Build Coastguard Worker  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21*61046927SAndroid Build Coastguard Worker  * SOFTWARE.
22*61046927SAndroid Build Coastguard Worker  */
23*61046927SAndroid Build Coastguard Worker 
24*61046927SAndroid Build Coastguard Worker #include <stdbool.h>
25*61046927SAndroid Build Coastguard Worker #include <stdint.h>
26*61046927SAndroid Build Coastguard Worker 
27*61046927SAndroid Build Coastguard Worker #include "hwdef/rogue_hw_utils.h"
28*61046927SAndroid Build Coastguard Worker #include "pvr_bo.h"
29*61046927SAndroid Build Coastguard Worker #include "pvr_device_info.h"
30*61046927SAndroid Build Coastguard Worker #include "pvr_formats.h"
31*61046927SAndroid Build Coastguard Worker #include "pvr_hw_pass.h"
32*61046927SAndroid Build Coastguard Worker #include "pvr_pds.h"
33*61046927SAndroid Build Coastguard Worker #include "pvr_private.h"
34*61046927SAndroid Build Coastguard Worker #include "pvr_types.h"
35*61046927SAndroid Build Coastguard Worker #include "pvr_usc_fragment_shader.h"
36*61046927SAndroid Build Coastguard Worker #include "util/macros.h"
37*61046927SAndroid Build Coastguard Worker #include "rogue/rogue.h"
38*61046927SAndroid Build Coastguard Worker #include "vk_alloc.h"
39*61046927SAndroid Build Coastguard Worker #include "vk_format.h"
40*61046927SAndroid Build Coastguard Worker #include "vk_log.h"
41*61046927SAndroid Build Coastguard Worker #include "vk_render_pass.h"
42*61046927SAndroid Build Coastguard Worker 
43*61046927SAndroid Build Coastguard Worker /*****************************************************************************
44*61046927SAndroid Build Coastguard Worker   PDS pre-baked program generation parameters and variables.
45*61046927SAndroid Build Coastguard Worker *****************************************************************************/
46*61046927SAndroid Build Coastguard Worker /* These would normally be produced by the compiler or other code. We're using
47*61046927SAndroid Build Coastguard Worker  * them for now just to speed up things. All of these should eventually be
48*61046927SAndroid Build Coastguard Worker  * removed.
49*61046927SAndroid Build Coastguard Worker  */
50*61046927SAndroid Build Coastguard Worker 
51*61046927SAndroid Build Coastguard Worker static const struct {
52*61046927SAndroid Build Coastguard Worker    /* Indicates the amount of temporaries for the shader. */
53*61046927SAndroid Build Coastguard Worker    uint32_t temp_count;
54*61046927SAndroid Build Coastguard Worker    enum rogue_msaa_mode msaa_mode;
55*61046927SAndroid Build Coastguard Worker    /* Indicates the presence of PHAS instruction. */
56*61046927SAndroid Build Coastguard Worker    bool has_phase_rate_change;
57*61046927SAndroid Build Coastguard Worker } pvr_pds_fragment_program_params = {
58*61046927SAndroid Build Coastguard Worker    .temp_count = 0,
59*61046927SAndroid Build Coastguard Worker    .msaa_mode = ROGUE_MSAA_MODE_PIXEL,
60*61046927SAndroid Build Coastguard Worker    .has_phase_rate_change = false,
61*61046927SAndroid Build Coastguard Worker };
62*61046927SAndroid Build Coastguard Worker 
pvr_subpass_has_msaa_input_attachment(struct pvr_render_subpass * subpass,const VkRenderPassCreateInfo2 * pCreateInfo)63*61046927SAndroid Build Coastguard Worker static inline bool pvr_subpass_has_msaa_input_attachment(
64*61046927SAndroid Build Coastguard Worker    struct pvr_render_subpass *subpass,
65*61046927SAndroid Build Coastguard Worker    const VkRenderPassCreateInfo2 *pCreateInfo)
66*61046927SAndroid Build Coastguard Worker {
67*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < subpass->input_count; i++) {
68*61046927SAndroid Build Coastguard Worker       const uint32_t attachment = subpass->input_attachments[i];
69*61046927SAndroid Build Coastguard Worker 
70*61046927SAndroid Build Coastguard Worker       if (pCreateInfo->pAttachments[attachment].samples > 1)
71*61046927SAndroid Build Coastguard Worker          return true;
72*61046927SAndroid Build Coastguard Worker    }
73*61046927SAndroid Build Coastguard Worker 
74*61046927SAndroid Build Coastguard Worker    return false;
75*61046927SAndroid Build Coastguard Worker }
76*61046927SAndroid Build Coastguard Worker 
pvr_is_subpass_initops_flush_needed(const struct pvr_render_pass * pass,const struct pvr_renderpass_hwsetup_render * hw_render)77*61046927SAndroid Build Coastguard Worker static bool pvr_is_subpass_initops_flush_needed(
78*61046927SAndroid Build Coastguard Worker    const struct pvr_render_pass *pass,
79*61046927SAndroid Build Coastguard Worker    const struct pvr_renderpass_hwsetup_render *hw_render)
80*61046927SAndroid Build Coastguard Worker {
81*61046927SAndroid Build Coastguard Worker    struct pvr_render_subpass *subpass = &pass->subpasses[0];
82*61046927SAndroid Build Coastguard Worker    uint32_t render_loadop_mask = 0;
83*61046927SAndroid Build Coastguard Worker    uint32_t color_attachment_mask;
84*61046927SAndroid Build Coastguard Worker 
85*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < hw_render->color_init_count; i++) {
86*61046927SAndroid Build Coastguard Worker       if (hw_render->color_init[i].op != VK_ATTACHMENT_LOAD_OP_DONT_CARE)
87*61046927SAndroid Build Coastguard Worker          render_loadop_mask |= (1 << hw_render->color_init[i].index);
88*61046927SAndroid Build Coastguard Worker    }
89*61046927SAndroid Build Coastguard Worker 
90*61046927SAndroid Build Coastguard Worker    /* If there are no load ops then there's nothing to flush. */
91*61046927SAndroid Build Coastguard Worker    if (render_loadop_mask == 0)
92*61046927SAndroid Build Coastguard Worker       return false;
93*61046927SAndroid Build Coastguard Worker 
94*61046927SAndroid Build Coastguard Worker    /* If the first subpass has any input attachments, they need to be
95*61046927SAndroid Build Coastguard Worker     * initialized with the result of the load op. Since the input attachment
96*61046927SAndroid Build Coastguard Worker     * may be read from fragments with an opaque pass type, the load ops must be
97*61046927SAndroid Build Coastguard Worker     * flushed or else they would be obscured and eliminated by HSR.
98*61046927SAndroid Build Coastguard Worker     */
99*61046927SAndroid Build Coastguard Worker    if (subpass->input_count != 0)
100*61046927SAndroid Build Coastguard Worker       return true;
101*61046927SAndroid Build Coastguard Worker 
102*61046927SAndroid Build Coastguard Worker    color_attachment_mask = 0;
103*61046927SAndroid Build Coastguard Worker 
104*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < subpass->color_count; i++) {
105*61046927SAndroid Build Coastguard Worker       const uint32_t color_idx = subpass->color_attachments[i];
106*61046927SAndroid Build Coastguard Worker 
107*61046927SAndroid Build Coastguard Worker       if (color_idx != VK_ATTACHMENT_UNUSED)
108*61046927SAndroid Build Coastguard Worker          color_attachment_mask |= (1 << pass->attachments[color_idx].index);
109*61046927SAndroid Build Coastguard Worker    }
110*61046927SAndroid Build Coastguard Worker 
111*61046927SAndroid Build Coastguard Worker    /* If the first subpass does not write to all attachments which have a load
112*61046927SAndroid Build Coastguard Worker     * op then the load ops need to be flushed to ensure they don't get obscured
113*61046927SAndroid Build Coastguard Worker     * and removed by HSR.
114*61046927SAndroid Build Coastguard Worker     */
115*61046927SAndroid Build Coastguard Worker    return (render_loadop_mask & color_attachment_mask) != render_loadop_mask;
116*61046927SAndroid Build Coastguard Worker }
117*61046927SAndroid Build Coastguard Worker 
118*61046927SAndroid Build Coastguard Worker static void
pvr_init_subpass_isp_userpass(struct pvr_renderpass_hwsetup * hw_setup,struct pvr_render_pass * pass,struct pvr_render_subpass * subpasses)119*61046927SAndroid Build Coastguard Worker pvr_init_subpass_isp_userpass(struct pvr_renderpass_hwsetup *hw_setup,
120*61046927SAndroid Build Coastguard Worker                               struct pvr_render_pass *pass,
121*61046927SAndroid Build Coastguard Worker                               struct pvr_render_subpass *subpasses)
122*61046927SAndroid Build Coastguard Worker {
123*61046927SAndroid Build Coastguard Worker    uint32_t subpass_idx = 0;
124*61046927SAndroid Build Coastguard Worker 
125*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < hw_setup->render_count; i++) {
126*61046927SAndroid Build Coastguard Worker       struct pvr_renderpass_hwsetup_render *hw_render = &hw_setup->renders[i];
127*61046927SAndroid Build Coastguard Worker       const uint32_t initial_isp_userpass =
128*61046927SAndroid Build Coastguard Worker          (uint32_t)pvr_is_subpass_initops_flush_needed(pass, hw_render);
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker       for (uint32_t j = 0; j < hw_render->subpass_count; j++) {
131*61046927SAndroid Build Coastguard Worker          subpasses[subpass_idx].isp_userpass =
132*61046927SAndroid Build Coastguard Worker             (j + initial_isp_userpass) & PVRX(CR_ISP_CTL_UPASS_START_SIZE_MAX);
133*61046927SAndroid Build Coastguard Worker          subpass_idx++;
134*61046927SAndroid Build Coastguard Worker       }
135*61046927SAndroid Build Coastguard Worker    }
136*61046927SAndroid Build Coastguard Worker 
137*61046927SAndroid Build Coastguard Worker    assert(subpass_idx == pass->subpass_count);
138*61046927SAndroid Build Coastguard Worker }
139*61046927SAndroid Build Coastguard Worker 
pvr_has_output_register_writes(const struct pvr_renderpass_hwsetup_render * hw_render)140*61046927SAndroid Build Coastguard Worker static inline bool pvr_has_output_register_writes(
141*61046927SAndroid Build Coastguard Worker    const struct pvr_renderpass_hwsetup_render *hw_render)
142*61046927SAndroid Build Coastguard Worker {
143*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < hw_render->init_setup.num_render_targets; i++) {
144*61046927SAndroid Build Coastguard Worker       struct usc_mrt_resource *mrt_resource =
145*61046927SAndroid Build Coastguard Worker          &hw_render->init_setup.mrt_resources[i];
146*61046927SAndroid Build Coastguard Worker 
147*61046927SAndroid Build Coastguard Worker       if (mrt_resource->type == USC_MRT_RESOURCE_TYPE_OUTPUT_REG)
148*61046927SAndroid Build Coastguard Worker          return true;
149*61046927SAndroid Build Coastguard Worker    }
150*61046927SAndroid Build Coastguard Worker 
151*61046927SAndroid Build Coastguard Worker    return false;
152*61046927SAndroid Build Coastguard Worker }
153*61046927SAndroid Build Coastguard Worker 
pvr_pds_unitex_state_program_create_and_upload(struct pvr_device * device,const VkAllocationCallbacks * allocator,uint32_t texture_kicks,uint32_t uniform_kicks,struct pvr_pds_upload * const pds_upload_out)154*61046927SAndroid Build Coastguard Worker VkResult pvr_pds_unitex_state_program_create_and_upload(
155*61046927SAndroid Build Coastguard Worker    struct pvr_device *device,
156*61046927SAndroid Build Coastguard Worker    const VkAllocationCallbacks *allocator,
157*61046927SAndroid Build Coastguard Worker    uint32_t texture_kicks,
158*61046927SAndroid Build Coastguard Worker    uint32_t uniform_kicks,
159*61046927SAndroid Build Coastguard Worker    struct pvr_pds_upload *const pds_upload_out)
160*61046927SAndroid Build Coastguard Worker {
161*61046927SAndroid Build Coastguard Worker    struct pvr_pds_pixel_shader_sa_program program = {
162*61046927SAndroid Build Coastguard Worker       .num_texture_dma_kicks = texture_kicks,
163*61046927SAndroid Build Coastguard Worker       .num_uniform_dma_kicks = uniform_kicks,
164*61046927SAndroid Build Coastguard Worker    };
165*61046927SAndroid Build Coastguard Worker    uint32_t staging_buffer_size;
166*61046927SAndroid Build Coastguard Worker    uint32_t *staging_buffer;
167*61046927SAndroid Build Coastguard Worker    VkResult result;
168*61046927SAndroid Build Coastguard Worker 
169*61046927SAndroid Build Coastguard Worker    pvr_pds_set_sizes_pixel_shader_uniform_texture_code(&program);
170*61046927SAndroid Build Coastguard Worker 
171*61046927SAndroid Build Coastguard Worker    staging_buffer_size = PVR_DW_TO_BYTES(program.code_size);
172*61046927SAndroid Build Coastguard Worker 
173*61046927SAndroid Build Coastguard Worker    staging_buffer = vk_alloc2(&device->vk.alloc,
174*61046927SAndroid Build Coastguard Worker                               allocator,
175*61046927SAndroid Build Coastguard Worker                               staging_buffer_size,
176*61046927SAndroid Build Coastguard Worker                               8U,
177*61046927SAndroid Build Coastguard Worker                               VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
178*61046927SAndroid Build Coastguard Worker    if (!staging_buffer)
179*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker    pvr_pds_generate_pixel_shader_sa_code_segment(&program, staging_buffer);
182*61046927SAndroid Build Coastguard Worker 
183*61046927SAndroid Build Coastguard Worker    /* FIXME: Figure out the define for alignment of 16. */
184*61046927SAndroid Build Coastguard Worker    result = pvr_gpu_upload_pds(device,
185*61046927SAndroid Build Coastguard Worker                                NULL,
186*61046927SAndroid Build Coastguard Worker                                0U,
187*61046927SAndroid Build Coastguard Worker                                0U,
188*61046927SAndroid Build Coastguard Worker                                staging_buffer,
189*61046927SAndroid Build Coastguard Worker                                program.code_size,
190*61046927SAndroid Build Coastguard Worker                                16U,
191*61046927SAndroid Build Coastguard Worker                                16U,
192*61046927SAndroid Build Coastguard Worker                                pds_upload_out);
193*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS) {
194*61046927SAndroid Build Coastguard Worker       vk_free2(&device->vk.alloc, allocator, staging_buffer);
195*61046927SAndroid Build Coastguard Worker       return result;
196*61046927SAndroid Build Coastguard Worker    }
197*61046927SAndroid Build Coastguard Worker 
198*61046927SAndroid Build Coastguard Worker    vk_free2(&device->vk.alloc, allocator, staging_buffer);
199*61046927SAndroid Build Coastguard Worker 
200*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
201*61046927SAndroid Build Coastguard Worker }
202*61046927SAndroid Build Coastguard Worker 
203*61046927SAndroid Build Coastguard Worker /* TODO: pvr_create_subpass_load_op() and pvr_create_render_load_op() are quite
204*61046927SAndroid Build Coastguard Worker  * similar. See if we can dedup them?
205*61046927SAndroid Build Coastguard Worker  */
206*61046927SAndroid Build Coastguard Worker static VkResult
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)207*61046927SAndroid Build Coastguard Worker pvr_create_subpass_load_op(struct pvr_device *device,
208*61046927SAndroid Build Coastguard Worker                            const VkAllocationCallbacks *allocator,
209*61046927SAndroid Build Coastguard Worker                            const struct pvr_render_pass *pass,
210*61046927SAndroid Build Coastguard Worker                            struct pvr_renderpass_hwsetup_render *hw_render,
211*61046927SAndroid Build Coastguard Worker                            uint32_t hw_subpass_idx,
212*61046927SAndroid Build Coastguard Worker                            struct pvr_load_op **const load_op_out)
213*61046927SAndroid Build Coastguard Worker {
214*61046927SAndroid Build Coastguard Worker    const struct pvr_renderpass_hwsetup_subpass *hw_subpass =
215*61046927SAndroid Build Coastguard Worker       &hw_render->subpasses[hw_subpass_idx];
216*61046927SAndroid Build Coastguard Worker    const struct pvr_render_subpass *subpass =
217*61046927SAndroid Build Coastguard Worker       &pass->subpasses[hw_subpass->index];
218*61046927SAndroid Build Coastguard Worker 
219*61046927SAndroid Build Coastguard Worker    struct pvr_load_op *load_op = vk_zalloc2(&device->vk.alloc,
220*61046927SAndroid Build Coastguard Worker                                             allocator,
221*61046927SAndroid Build Coastguard Worker                                             sizeof(*load_op),
222*61046927SAndroid Build Coastguard Worker                                             8,
223*61046927SAndroid Build Coastguard Worker                                             VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
224*61046927SAndroid Build Coastguard Worker    if (!load_op)
225*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
226*61046927SAndroid Build Coastguard Worker 
227*61046927SAndroid Build Coastguard Worker    load_op->clears_loads_state.depth_clear_to_reg = PVR_NO_DEPTH_CLEAR_TO_REG;
228*61046927SAndroid Build Coastguard Worker 
229*61046927SAndroid Build Coastguard Worker    if (hw_subpass->z_replicate != -1) {
230*61046927SAndroid Build Coastguard Worker       const int32_t z_replicate = hw_subpass->z_replicate;
231*61046927SAndroid Build Coastguard Worker 
232*61046927SAndroid Build Coastguard Worker       switch (hw_subpass->depth_initop) {
233*61046927SAndroid Build Coastguard Worker       case VK_ATTACHMENT_LOAD_OP_LOAD:
234*61046927SAndroid Build Coastguard Worker          assert(z_replicate < PVR_LOAD_OP_CLEARS_LOADS_MAX_RTS);
235*61046927SAndroid Build Coastguard Worker          load_op->clears_loads_state.rt_load_mask = BITFIELD_BIT(z_replicate);
236*61046927SAndroid Build Coastguard Worker          load_op->clears_loads_state.dest_vk_format[z_replicate] =
237*61046927SAndroid Build Coastguard Worker             VK_FORMAT_D32_SFLOAT;
238*61046927SAndroid Build Coastguard Worker          break;
239*61046927SAndroid Build Coastguard Worker 
240*61046927SAndroid Build Coastguard Worker       case VK_ATTACHMENT_LOAD_OP_CLEAR:
241*61046927SAndroid Build Coastguard Worker          load_op->clears_loads_state.depth_clear_to_reg = z_replicate;
242*61046927SAndroid Build Coastguard Worker          break;
243*61046927SAndroid Build Coastguard Worker 
244*61046927SAndroid Build Coastguard Worker       default:
245*61046927SAndroid Build Coastguard Worker          break;
246*61046927SAndroid Build Coastguard Worker       }
247*61046927SAndroid Build Coastguard Worker    }
248*61046927SAndroid Build Coastguard Worker 
249*61046927SAndroid Build Coastguard Worker    assert(subpass->color_count <= PVR_LOAD_OP_CLEARS_LOADS_MAX_RTS);
250*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < subpass->color_count; i++) {
251*61046927SAndroid Build Coastguard Worker       const uint32_t attachment_idx = subpass->color_attachments[i];
252*61046927SAndroid Build Coastguard Worker 
253*61046927SAndroid Build Coastguard Worker       assert(attachment_idx < pass->attachment_count);
254*61046927SAndroid Build Coastguard Worker       load_op->clears_loads_state.dest_vk_format[i] =
255*61046927SAndroid Build Coastguard Worker          pass->attachments[attachment_idx].vk_format;
256*61046927SAndroid Build Coastguard Worker 
257*61046927SAndroid Build Coastguard Worker       if (pass->attachments[attachment_idx].sample_count > 1)
258*61046927SAndroid Build Coastguard Worker          load_op->clears_loads_state.unresolved_msaa_mask |= BITFIELD_BIT(i);
259*61046927SAndroid Build Coastguard Worker 
260*61046927SAndroid Build Coastguard Worker       if (hw_subpass->color_initops[i] == VK_ATTACHMENT_LOAD_OP_LOAD)
261*61046927SAndroid Build Coastguard Worker          load_op->clears_loads_state.rt_load_mask |= BITFIELD_BIT(i);
262*61046927SAndroid Build Coastguard Worker       else if (hw_subpass->color_initops[i] == VK_ATTACHMENT_LOAD_OP_CLEAR)
263*61046927SAndroid Build Coastguard Worker          load_op->clears_loads_state.rt_clear_mask |= BITFIELD_BIT(i);
264*61046927SAndroid Build Coastguard Worker    }
265*61046927SAndroid Build Coastguard Worker 
266*61046927SAndroid Build Coastguard Worker    load_op->is_hw_object = false;
267*61046927SAndroid Build Coastguard Worker    load_op->subpass = subpass;
268*61046927SAndroid Build Coastguard Worker 
269*61046927SAndroid Build Coastguard Worker    *load_op_out = load_op;
270*61046927SAndroid Build Coastguard Worker 
271*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
272*61046927SAndroid Build Coastguard Worker }
273*61046927SAndroid Build Coastguard Worker 
274*61046927SAndroid Build Coastguard Worker static VkResult
pvr_create_render_load_op(struct pvr_device * device,const VkAllocationCallbacks * allocator,const struct pvr_render_pass * pass,const struct pvr_renderpass_hwsetup_render * hw_render,struct pvr_load_op ** const load_op_out)275*61046927SAndroid Build Coastguard Worker pvr_create_render_load_op(struct pvr_device *device,
276*61046927SAndroid Build Coastguard Worker                           const VkAllocationCallbacks *allocator,
277*61046927SAndroid Build Coastguard Worker                           const struct pvr_render_pass *pass,
278*61046927SAndroid Build Coastguard Worker                           const struct pvr_renderpass_hwsetup_render *hw_render,
279*61046927SAndroid Build Coastguard Worker                           struct pvr_load_op **const load_op_out)
280*61046927SAndroid Build Coastguard Worker {
281*61046927SAndroid Build Coastguard Worker    struct pvr_load_op *load_op = vk_zalloc2(&device->vk.alloc,
282*61046927SAndroid Build Coastguard Worker                                             allocator,
283*61046927SAndroid Build Coastguard Worker                                             sizeof(*load_op),
284*61046927SAndroid Build Coastguard Worker                                             8,
285*61046927SAndroid Build Coastguard Worker                                             VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
286*61046927SAndroid Build Coastguard Worker    if (!load_op)
287*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
288*61046927SAndroid Build Coastguard Worker 
289*61046927SAndroid Build Coastguard Worker    load_op->clears_loads_state.depth_clear_to_reg = PVR_NO_DEPTH_CLEAR_TO_REG;
290*61046927SAndroid Build Coastguard Worker 
291*61046927SAndroid Build Coastguard Worker    assert(hw_render->color_init_count <= PVR_LOAD_OP_CLEARS_LOADS_MAX_RTS);
292*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < hw_render->color_init_count; i++) {
293*61046927SAndroid Build Coastguard Worker       struct pvr_renderpass_colorinit *color_init = &hw_render->color_init[i];
294*61046927SAndroid Build Coastguard Worker 
295*61046927SAndroid Build Coastguard Worker       assert(color_init->index < pass->attachment_count);
296*61046927SAndroid Build Coastguard Worker       load_op->clears_loads_state.dest_vk_format[i] =
297*61046927SAndroid Build Coastguard Worker          pass->attachments[color_init->index].vk_format;
298*61046927SAndroid Build Coastguard Worker 
299*61046927SAndroid Build Coastguard Worker       if (pass->attachments[color_init->index].sample_count > 1)
300*61046927SAndroid Build Coastguard Worker          load_op->clears_loads_state.unresolved_msaa_mask |= BITFIELD_BIT(i);
301*61046927SAndroid Build Coastguard Worker 
302*61046927SAndroid Build Coastguard Worker       if (color_init->op == VK_ATTACHMENT_LOAD_OP_LOAD)
303*61046927SAndroid Build Coastguard Worker          load_op->clears_loads_state.rt_load_mask |= BITFIELD_BIT(i);
304*61046927SAndroid Build Coastguard Worker       else if (color_init->op == VK_ATTACHMENT_LOAD_OP_CLEAR)
305*61046927SAndroid Build Coastguard Worker          load_op->clears_loads_state.rt_clear_mask |= BITFIELD_BIT(i);
306*61046927SAndroid Build Coastguard Worker    }
307*61046927SAndroid Build Coastguard Worker 
308*61046927SAndroid Build Coastguard Worker    load_op->is_hw_object = true;
309*61046927SAndroid Build Coastguard Worker    load_op->hw_render = hw_render;
310*61046927SAndroid Build Coastguard Worker 
311*61046927SAndroid Build Coastguard Worker    *load_op_out = load_op;
312*61046927SAndroid Build Coastguard Worker 
313*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
314*61046927SAndroid Build Coastguard Worker }
315*61046927SAndroid Build Coastguard Worker 
316*61046927SAndroid Build Coastguard Worker 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)317*61046927SAndroid Build Coastguard Worker pvr_generate_load_op_shader(struct pvr_device *device,
318*61046927SAndroid Build Coastguard Worker                             const VkAllocationCallbacks *allocator,
319*61046927SAndroid Build Coastguard Worker                             struct pvr_renderpass_hwsetup_render *hw_render,
320*61046927SAndroid Build Coastguard Worker                             struct pvr_load_op *load_op)
321*61046927SAndroid Build Coastguard Worker {
322*61046927SAndroid Build Coastguard Worker    const struct pvr_device_info *dev_info = &device->pdevice->dev_info;
323*61046927SAndroid Build Coastguard Worker    const uint32_t cache_line_size = rogue_get_slc_cache_line_size(dev_info);
324*61046927SAndroid Build Coastguard Worker 
325*61046927SAndroid Build Coastguard Worker    VkResult result = pvr_gpu_upload_usc(device,
326*61046927SAndroid Build Coastguard Worker                                         pvr_usc_fragment_shader,
327*61046927SAndroid Build Coastguard Worker                                         sizeof(pvr_usc_fragment_shader),
328*61046927SAndroid Build Coastguard Worker                                         cache_line_size,
329*61046927SAndroid Build Coastguard Worker                                         &load_op->usc_frag_prog_bo);
330*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
331*61046927SAndroid Build Coastguard Worker       return result;
332*61046927SAndroid Build Coastguard Worker 
333*61046927SAndroid Build Coastguard Worker    result = pvr_pds_fragment_program_create_and_upload(
334*61046927SAndroid Build Coastguard Worker       device,
335*61046927SAndroid Build Coastguard Worker       allocator,
336*61046927SAndroid Build Coastguard Worker       load_op->usc_frag_prog_bo,
337*61046927SAndroid Build Coastguard Worker       pvr_pds_fragment_program_params.temp_count,
338*61046927SAndroid Build Coastguard Worker       pvr_pds_fragment_program_params.msaa_mode,
339*61046927SAndroid Build Coastguard Worker       pvr_pds_fragment_program_params.has_phase_rate_change,
340*61046927SAndroid Build Coastguard Worker       &load_op->pds_frag_prog);
341*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
342*61046927SAndroid Build Coastguard Worker       goto err_free_usc_frag_prog_bo;
343*61046927SAndroid Build Coastguard Worker 
344*61046927SAndroid Build Coastguard Worker    result = pvr_pds_unitex_state_program_create_and_upload(
345*61046927SAndroid Build Coastguard Worker       device,
346*61046927SAndroid Build Coastguard Worker       allocator,
347*61046927SAndroid Build Coastguard Worker       1U,
348*61046927SAndroid Build Coastguard Worker       0U,
349*61046927SAndroid Build Coastguard Worker       &load_op->pds_tex_state_prog);
350*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
351*61046927SAndroid Build Coastguard Worker       goto err_free_pds_frag_prog;
352*61046927SAndroid Build Coastguard Worker 
353*61046927SAndroid Build Coastguard Worker    /* FIXME: These should be based on the USC and PDS programs, but are hard
354*61046927SAndroid Build Coastguard Worker     * coded for now.
355*61046927SAndroid Build Coastguard Worker     */
356*61046927SAndroid Build Coastguard Worker    load_op->const_shareds_count = 1;
357*61046927SAndroid Build Coastguard Worker    load_op->shareds_dest_offset = 0;
358*61046927SAndroid Build Coastguard Worker    load_op->shareds_count = 1;
359*61046927SAndroid Build Coastguard Worker    load_op->temps_count = 1;
360*61046927SAndroid Build Coastguard Worker 
361*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
362*61046927SAndroid Build Coastguard Worker 
363*61046927SAndroid Build Coastguard Worker err_free_pds_frag_prog:
364*61046927SAndroid Build Coastguard Worker    pvr_bo_suballoc_free(load_op->pds_frag_prog.pvr_bo);
365*61046927SAndroid Build Coastguard Worker 
366*61046927SAndroid Build Coastguard Worker err_free_usc_frag_prog_bo:
367*61046927SAndroid Build Coastguard Worker    pvr_bo_suballoc_free(load_op->usc_frag_prog_bo);
368*61046927SAndroid Build Coastguard Worker 
369*61046927SAndroid Build Coastguard Worker    return result;
370*61046927SAndroid Build Coastguard Worker }
371*61046927SAndroid Build Coastguard Worker 
pvr_load_op_destroy(struct pvr_device * device,const VkAllocationCallbacks * allocator,struct pvr_load_op * load_op)372*61046927SAndroid Build Coastguard Worker static void pvr_load_op_destroy(struct pvr_device *device,
373*61046927SAndroid Build Coastguard Worker                                 const VkAllocationCallbacks *allocator,
374*61046927SAndroid Build Coastguard Worker                                 struct pvr_load_op *load_op)
375*61046927SAndroid Build Coastguard Worker {
376*61046927SAndroid Build Coastguard Worker    pvr_bo_suballoc_free(load_op->pds_tex_state_prog.pvr_bo);
377*61046927SAndroid Build Coastguard Worker    pvr_bo_suballoc_free(load_op->pds_frag_prog.pvr_bo);
378*61046927SAndroid Build Coastguard Worker    pvr_bo_suballoc_free(load_op->usc_frag_prog_bo);
379*61046927SAndroid Build Coastguard Worker    vk_free2(&device->vk.alloc, allocator, load_op);
380*61046927SAndroid Build Coastguard Worker }
381*61046927SAndroid Build Coastguard Worker 
382*61046927SAndroid Build Coastguard Worker #define PVR_SPM_LOAD_IN_BUFFERS_COUNT(dev_info)              \
383*61046927SAndroid Build Coastguard Worker    ({                                                        \
384*61046927SAndroid Build Coastguard Worker       int __ret = PVR_MAX_TILE_BUFFER_COUNT;                 \
385*61046927SAndroid Build Coastguard Worker       if (PVR_HAS_FEATURE(dev_info, eight_output_registers)) \
386*61046927SAndroid Build Coastguard Worker          __ret -= 4U;                                        \
387*61046927SAndroid Build Coastguard Worker       __ret;                                                 \
388*61046927SAndroid Build Coastguard Worker    })
389*61046927SAndroid Build Coastguard Worker 
390*61046927SAndroid Build Coastguard Worker 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)391*61046927SAndroid Build Coastguard Worker pvr_is_load_op_needed(const struct pvr_render_pass *pass,
392*61046927SAndroid Build Coastguard Worker                       struct pvr_renderpass_hwsetup_render *hw_render,
393*61046927SAndroid Build Coastguard Worker                       const uint32_t subpass_idx)
394*61046927SAndroid Build Coastguard Worker {
395*61046927SAndroid Build Coastguard Worker    struct pvr_renderpass_hwsetup_subpass *hw_subpass =
396*61046927SAndroid Build Coastguard Worker       &hw_render->subpasses[subpass_idx];
397*61046927SAndroid Build Coastguard Worker    const struct pvr_render_subpass *subpass =
398*61046927SAndroid Build Coastguard Worker       &pass->subpasses[hw_subpass->index];
399*61046927SAndroid Build Coastguard Worker 
400*61046927SAndroid Build Coastguard Worker    if (hw_subpass->z_replicate != -1 &&
401*61046927SAndroid Build Coastguard Worker        (hw_subpass->depth_initop == VK_ATTACHMENT_LOAD_OP_LOAD ||
402*61046927SAndroid Build Coastguard Worker         hw_subpass->depth_initop == VK_ATTACHMENT_LOAD_OP_CLEAR)) {
403*61046927SAndroid Build Coastguard Worker       return true;
404*61046927SAndroid Build Coastguard Worker    }
405*61046927SAndroid Build Coastguard Worker 
406*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < subpass->color_count; i++) {
407*61046927SAndroid Build Coastguard Worker       if (subpass->color_attachments[i] == VK_ATTACHMENT_UNUSED)
408*61046927SAndroid Build Coastguard Worker          continue;
409*61046927SAndroid Build Coastguard Worker 
410*61046927SAndroid Build Coastguard Worker       if (hw_subpass->color_initops[i] == VK_ATTACHMENT_LOAD_OP_LOAD ||
411*61046927SAndroid Build Coastguard Worker           hw_subpass->color_initops[i] == VK_ATTACHMENT_LOAD_OP_CLEAR) {
412*61046927SAndroid Build Coastguard Worker          return true;
413*61046927SAndroid Build Coastguard Worker       }
414*61046927SAndroid Build Coastguard Worker    }
415*61046927SAndroid Build Coastguard Worker 
416*61046927SAndroid Build Coastguard Worker    return false;
417*61046927SAndroid Build Coastguard Worker }
418*61046927SAndroid Build Coastguard Worker 
pvr_CreateRenderPass2(VkDevice _device,const VkRenderPassCreateInfo2 * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkRenderPass * pRenderPass)419*61046927SAndroid Build Coastguard Worker VkResult pvr_CreateRenderPass2(VkDevice _device,
420*61046927SAndroid Build Coastguard Worker                                const VkRenderPassCreateInfo2 *pCreateInfo,
421*61046927SAndroid Build Coastguard Worker                                const VkAllocationCallbacks *pAllocator,
422*61046927SAndroid Build Coastguard Worker                                VkRenderPass *pRenderPass)
423*61046927SAndroid Build Coastguard Worker {
424*61046927SAndroid Build Coastguard Worker    struct pvr_render_pass_attachment *attachments;
425*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_device, device, _device);
426*61046927SAndroid Build Coastguard Worker    struct pvr_render_subpass *subpasses;
427*61046927SAndroid Build Coastguard Worker    const VkAllocationCallbacks *alloc;
428*61046927SAndroid Build Coastguard Worker    size_t subpass_attachment_count;
429*61046927SAndroid Build Coastguard Worker    uint32_t *subpass_attachments;
430*61046927SAndroid Build Coastguard Worker    struct pvr_render_pass *pass;
431*61046927SAndroid Build Coastguard Worker    uint32_t *dep_list;
432*61046927SAndroid Build Coastguard Worker    bool *flush_on_dep;
433*61046927SAndroid Build Coastguard Worker    VkResult result;
434*61046927SAndroid Build Coastguard Worker 
435*61046927SAndroid Build Coastguard Worker    alloc = pAllocator ? pAllocator : &device->vk.alloc;
436*61046927SAndroid Build Coastguard Worker 
437*61046927SAndroid Build Coastguard Worker    VK_MULTIALLOC(ma);
438*61046927SAndroid Build Coastguard Worker    vk_multialloc_add(&ma, &pass, __typeof__(*pass), 1);
439*61046927SAndroid Build Coastguard Worker    vk_multialloc_add(&ma,
440*61046927SAndroid Build Coastguard Worker                      &attachments,
441*61046927SAndroid Build Coastguard Worker                      __typeof__(*attachments),
442*61046927SAndroid Build Coastguard Worker                      pCreateInfo->attachmentCount);
443*61046927SAndroid Build Coastguard Worker    vk_multialloc_add(&ma,
444*61046927SAndroid Build Coastguard Worker                      &subpasses,
445*61046927SAndroid Build Coastguard Worker                      __typeof__(*subpasses),
446*61046927SAndroid Build Coastguard Worker                      pCreateInfo->subpassCount);
447*61046927SAndroid Build Coastguard Worker 
448*61046927SAndroid Build Coastguard Worker    subpass_attachment_count = 0;
449*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
450*61046927SAndroid Build Coastguard Worker       const VkSubpassDescription2 *desc = &pCreateInfo->pSubpasses[i];
451*61046927SAndroid Build Coastguard Worker       subpass_attachment_count +=
452*61046927SAndroid Build Coastguard Worker          desc->inputAttachmentCount + desc->colorAttachmentCount +
453*61046927SAndroid Build Coastguard Worker          (desc->pResolveAttachments ? desc->colorAttachmentCount : 0);
454*61046927SAndroid Build Coastguard Worker    }
455*61046927SAndroid Build Coastguard Worker 
456*61046927SAndroid Build Coastguard Worker    vk_multialloc_add(&ma,
457*61046927SAndroid Build Coastguard Worker                      &subpass_attachments,
458*61046927SAndroid Build Coastguard Worker                      __typeof__(*subpass_attachments),
459*61046927SAndroid Build Coastguard Worker                      subpass_attachment_count);
460*61046927SAndroid Build Coastguard Worker    vk_multialloc_add(&ma,
461*61046927SAndroid Build Coastguard Worker                      &dep_list,
462*61046927SAndroid Build Coastguard Worker                      __typeof__(*dep_list),
463*61046927SAndroid Build Coastguard Worker                      pCreateInfo->dependencyCount);
464*61046927SAndroid Build Coastguard Worker    vk_multialloc_add(&ma,
465*61046927SAndroid Build Coastguard Worker                      &flush_on_dep,
466*61046927SAndroid Build Coastguard Worker                      __typeof__(*flush_on_dep),
467*61046927SAndroid Build Coastguard Worker                      pCreateInfo->dependencyCount);
468*61046927SAndroid Build Coastguard Worker 
469*61046927SAndroid Build Coastguard Worker    if (!vk_multialloc_zalloc(&ma, alloc, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT))
470*61046927SAndroid Build Coastguard Worker       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
471*61046927SAndroid Build Coastguard Worker 
472*61046927SAndroid Build Coastguard Worker    vk_object_base_init(&device->vk, &pass->base, VK_OBJECT_TYPE_RENDER_PASS);
473*61046927SAndroid Build Coastguard Worker    pass->attachment_count = pCreateInfo->attachmentCount;
474*61046927SAndroid Build Coastguard Worker    pass->attachments = attachments;
475*61046927SAndroid Build Coastguard Worker    pass->subpass_count = pCreateInfo->subpassCount;
476*61046927SAndroid Build Coastguard Worker    pass->subpasses = subpasses;
477*61046927SAndroid Build Coastguard Worker    pass->max_sample_count = 1;
478*61046927SAndroid Build Coastguard Worker 
479*61046927SAndroid Build Coastguard Worker    /* Copy attachment descriptions. */
480*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pass->attachment_count; i++) {
481*61046927SAndroid Build Coastguard Worker       const VkAttachmentDescription2 *desc = &pCreateInfo->pAttachments[i];
482*61046927SAndroid Build Coastguard Worker       struct pvr_render_pass_attachment *attachment = &pass->attachments[i];
483*61046927SAndroid Build Coastguard Worker 
484*61046927SAndroid Build Coastguard Worker       pvr_assert(!(desc->flags & ~VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT));
485*61046927SAndroid Build Coastguard Worker 
486*61046927SAndroid Build Coastguard Worker       attachment->load_op = desc->loadOp;
487*61046927SAndroid Build Coastguard Worker       attachment->store_op = desc->storeOp;
488*61046927SAndroid Build Coastguard Worker 
489*61046927SAndroid Build Coastguard Worker       attachment->aspects = vk_format_aspects(desc->format);
490*61046927SAndroid Build Coastguard Worker       if (attachment->aspects & VK_IMAGE_ASPECT_STENCIL_BIT) {
491*61046927SAndroid Build Coastguard Worker          attachment->stencil_load_op = desc->stencilLoadOp;
492*61046927SAndroid Build Coastguard Worker          attachment->stencil_store_op = desc->stencilStoreOp;
493*61046927SAndroid Build Coastguard Worker       }
494*61046927SAndroid Build Coastguard Worker 
495*61046927SAndroid Build Coastguard Worker       attachment->vk_format = desc->format;
496*61046927SAndroid Build Coastguard Worker       attachment->sample_count = desc->samples;
497*61046927SAndroid Build Coastguard Worker       attachment->initial_layout = desc->initialLayout;
498*61046927SAndroid Build Coastguard Worker       attachment->is_pbe_downscalable =
499*61046927SAndroid Build Coastguard Worker          pvr_format_is_pbe_downscalable(attachment->vk_format);
500*61046927SAndroid Build Coastguard Worker       attachment->index = i;
501*61046927SAndroid Build Coastguard Worker 
502*61046927SAndroid Build Coastguard Worker       if (attachment->sample_count > pass->max_sample_count)
503*61046927SAndroid Build Coastguard Worker          pass->max_sample_count = attachment->sample_count;
504*61046927SAndroid Build Coastguard Worker    }
505*61046927SAndroid Build Coastguard Worker 
506*61046927SAndroid Build Coastguard Worker    /* Count how many dependencies each subpass has. */
507*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) {
508*61046927SAndroid Build Coastguard Worker       const VkSubpassDependency2 *dep = &pCreateInfo->pDependencies[i];
509*61046927SAndroid Build Coastguard Worker 
510*61046927SAndroid Build Coastguard Worker       if (dep->srcSubpass != VK_SUBPASS_EXTERNAL &&
511*61046927SAndroid Build Coastguard Worker           dep->dstSubpass != VK_SUBPASS_EXTERNAL &&
512*61046927SAndroid Build Coastguard Worker           dep->srcSubpass != dep->dstSubpass) {
513*61046927SAndroid Build Coastguard Worker          pass->subpasses[dep->dstSubpass].dep_count++;
514*61046927SAndroid Build Coastguard Worker       }
515*61046927SAndroid Build Coastguard Worker    }
516*61046927SAndroid Build Coastguard Worker 
517*61046927SAndroid Build Coastguard Worker    /* Assign reference pointers to lists, and fill in the attachments list, we
518*61046927SAndroid Build Coastguard Worker     * need to re-walk the dependencies array later to fill the per-subpass
519*61046927SAndroid Build Coastguard Worker     * dependencies lists in.
520*61046927SAndroid Build Coastguard Worker     */
521*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pass->subpass_count; i++) {
522*61046927SAndroid Build Coastguard Worker       const VkSubpassDescription2 *desc = &pCreateInfo->pSubpasses[i];
523*61046927SAndroid Build Coastguard Worker       struct pvr_render_subpass *subpass = &pass->subpasses[i];
524*61046927SAndroid Build Coastguard Worker 
525*61046927SAndroid Build Coastguard Worker       subpass->pipeline_bind_point = desc->pipelineBindPoint;
526*61046927SAndroid Build Coastguard Worker 
527*61046927SAndroid Build Coastguard Worker       /* From the Vulkan spec. 1.3.265
528*61046927SAndroid Build Coastguard Worker        * VUID-VkSubpassDescription2-multisampledRenderToSingleSampled-06872:
529*61046927SAndroid Build Coastguard Worker        *
530*61046927SAndroid Build Coastguard Worker        *   "If none of the VK_AMD_mixed_attachment_samples extension, the
531*61046927SAndroid Build Coastguard Worker        *   VK_NV_framebuffer_mixed_samples extension, or the
532*61046927SAndroid Build Coastguard Worker        *   multisampledRenderToSingleSampled feature are enabled, all
533*61046927SAndroid Build Coastguard Worker        *   attachments in pDepthStencilAttachment or pColorAttachments that are
534*61046927SAndroid Build Coastguard Worker        *   not VK_ATTACHMENT_UNUSED must have the same sample count"
535*61046927SAndroid Build Coastguard Worker        *
536*61046927SAndroid Build Coastguard Worker        */
537*61046927SAndroid Build Coastguard Worker       subpass->sample_count = VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM;
538*61046927SAndroid Build Coastguard Worker 
539*61046927SAndroid Build Coastguard Worker       if (desc->pDepthStencilAttachment) {
540*61046927SAndroid Build Coastguard Worker          uint32_t index = desc->pDepthStencilAttachment->attachment;
541*61046927SAndroid Build Coastguard Worker 
542*61046927SAndroid Build Coastguard Worker          if (index != VK_ATTACHMENT_UNUSED)
543*61046927SAndroid Build Coastguard Worker             subpass->sample_count = pass->attachments[index].sample_count;
544*61046927SAndroid Build Coastguard Worker 
545*61046927SAndroid Build Coastguard Worker          subpass->depth_stencil_attachment = index;
546*61046927SAndroid Build Coastguard Worker       } else {
547*61046927SAndroid Build Coastguard Worker          subpass->depth_stencil_attachment = VK_ATTACHMENT_UNUSED;
548*61046927SAndroid Build Coastguard Worker       }
549*61046927SAndroid Build Coastguard Worker 
550*61046927SAndroid Build Coastguard Worker       subpass->color_count = desc->colorAttachmentCount;
551*61046927SAndroid Build Coastguard Worker       if (subpass->color_count > 0) {
552*61046927SAndroid Build Coastguard Worker          subpass->color_attachments = subpass_attachments;
553*61046927SAndroid Build Coastguard Worker          subpass_attachments += subpass->color_count;
554*61046927SAndroid Build Coastguard Worker 
555*61046927SAndroid Build Coastguard Worker          for (uint32_t j = 0; j < subpass->color_count; j++) {
556*61046927SAndroid Build Coastguard Worker             subpass->color_attachments[j] =
557*61046927SAndroid Build Coastguard Worker                desc->pColorAttachments[j].attachment;
558*61046927SAndroid Build Coastguard Worker 
559*61046927SAndroid Build Coastguard Worker             if (subpass->color_attachments[j] == VK_ATTACHMENT_UNUSED)
560*61046927SAndroid Build Coastguard Worker                continue;
561*61046927SAndroid Build Coastguard Worker 
562*61046927SAndroid Build Coastguard Worker             if (subpass->sample_count == VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM) {
563*61046927SAndroid Build Coastguard Worker                uint32_t index;
564*61046927SAndroid Build Coastguard Worker                index = subpass->color_attachments[j];
565*61046927SAndroid Build Coastguard Worker                subpass->sample_count = pass->attachments[index].sample_count;
566*61046927SAndroid Build Coastguard Worker             }
567*61046927SAndroid Build Coastguard Worker          }
568*61046927SAndroid Build Coastguard Worker       }
569*61046927SAndroid Build Coastguard Worker 
570*61046927SAndroid Build Coastguard Worker       if (subpass->sample_count == VK_SAMPLE_COUNT_FLAG_BITS_MAX_ENUM)
571*61046927SAndroid Build Coastguard Worker          subpass->sample_count = VK_SAMPLE_COUNT_1_BIT;
572*61046927SAndroid Build Coastguard Worker 
573*61046927SAndroid Build Coastguard Worker       if (desc->pResolveAttachments) {
574*61046927SAndroid Build Coastguard Worker          subpass->resolve_attachments = subpass_attachments;
575*61046927SAndroid Build Coastguard Worker          subpass_attachments += subpass->color_count;
576*61046927SAndroid Build Coastguard Worker 
577*61046927SAndroid Build Coastguard Worker          for (uint32_t j = 0; j < subpass->color_count; j++) {
578*61046927SAndroid Build Coastguard Worker             subpass->resolve_attachments[j] =
579*61046927SAndroid Build Coastguard Worker                desc->pResolveAttachments[j].attachment;
580*61046927SAndroid Build Coastguard Worker          }
581*61046927SAndroid Build Coastguard Worker       }
582*61046927SAndroid Build Coastguard Worker 
583*61046927SAndroid Build Coastguard Worker       subpass->input_count = desc->inputAttachmentCount;
584*61046927SAndroid Build Coastguard Worker       if (subpass->input_count > 0) {
585*61046927SAndroid Build Coastguard Worker          subpass->input_attachments = subpass_attachments;
586*61046927SAndroid Build Coastguard Worker          subpass_attachments += subpass->input_count;
587*61046927SAndroid Build Coastguard Worker 
588*61046927SAndroid Build Coastguard Worker          for (uint32_t j = 0; j < subpass->input_count; j++) {
589*61046927SAndroid Build Coastguard Worker             subpass->input_attachments[j] =
590*61046927SAndroid Build Coastguard Worker                desc->pInputAttachments[j].attachment;
591*61046927SAndroid Build Coastguard Worker          }
592*61046927SAndroid Build Coastguard Worker       }
593*61046927SAndroid Build Coastguard Worker 
594*61046927SAndroid Build Coastguard Worker       /* Give the dependencies a slice of the subpass_attachments array. */
595*61046927SAndroid Build Coastguard Worker       subpass->dep_list = dep_list;
596*61046927SAndroid Build Coastguard Worker       dep_list += subpass->dep_count;
597*61046927SAndroid Build Coastguard Worker       subpass->flush_on_dep = flush_on_dep;
598*61046927SAndroid Build Coastguard Worker       flush_on_dep += subpass->dep_count;
599*61046927SAndroid Build Coastguard Worker 
600*61046927SAndroid Build Coastguard Worker       /* Reset the dependencies count so we can start from 0 and index into
601*61046927SAndroid Build Coastguard Worker        * the dependencies array.
602*61046927SAndroid Build Coastguard Worker        */
603*61046927SAndroid Build Coastguard Worker       subpass->dep_count = 0;
604*61046927SAndroid Build Coastguard Worker       subpass->index = i;
605*61046927SAndroid Build Coastguard Worker    }
606*61046927SAndroid Build Coastguard Worker 
607*61046927SAndroid Build Coastguard Worker    /* Compute dependencies and populate dep_list and flush_on_dep. */
608*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pCreateInfo->dependencyCount; i++) {
609*61046927SAndroid Build Coastguard Worker       const VkSubpassDependency2 *dep = &pCreateInfo->pDependencies[i];
610*61046927SAndroid Build Coastguard Worker 
611*61046927SAndroid Build Coastguard Worker       if (dep->srcSubpass != VK_SUBPASS_EXTERNAL &&
612*61046927SAndroid Build Coastguard Worker           dep->dstSubpass != VK_SUBPASS_EXTERNAL &&
613*61046927SAndroid Build Coastguard Worker           dep->srcSubpass != dep->dstSubpass) {
614*61046927SAndroid Build Coastguard Worker          struct pvr_render_subpass *subpass = &pass->subpasses[dep->dstSubpass];
615*61046927SAndroid Build Coastguard Worker          bool is_dep_fb_local =
616*61046927SAndroid Build Coastguard Worker             vk_subpass_dependency_is_fb_local(dep,
617*61046927SAndroid Build Coastguard Worker                                               dep->srcStageMask,
618*61046927SAndroid Build Coastguard Worker                                               dep->dstStageMask);
619*61046927SAndroid Build Coastguard Worker 
620*61046927SAndroid Build Coastguard Worker          subpass->dep_list[subpass->dep_count] = dep->srcSubpass;
621*61046927SAndroid Build Coastguard Worker          if (pvr_subpass_has_msaa_input_attachment(subpass, pCreateInfo) ||
622*61046927SAndroid Build Coastguard Worker              !is_dep_fb_local) {
623*61046927SAndroid Build Coastguard Worker             subpass->flush_on_dep[subpass->dep_count] = true;
624*61046927SAndroid Build Coastguard Worker          }
625*61046927SAndroid Build Coastguard Worker 
626*61046927SAndroid Build Coastguard Worker          subpass->dep_count++;
627*61046927SAndroid Build Coastguard Worker       }
628*61046927SAndroid Build Coastguard Worker    }
629*61046927SAndroid Build Coastguard Worker 
630*61046927SAndroid Build Coastguard Worker    pass->max_tilebuffer_count =
631*61046927SAndroid Build Coastguard Worker       PVR_SPM_LOAD_IN_BUFFERS_COUNT(&device->pdevice->dev_info);
632*61046927SAndroid Build Coastguard Worker 
633*61046927SAndroid Build Coastguard Worker    result =
634*61046927SAndroid Build Coastguard Worker       pvr_create_renderpass_hwsetup(device, alloc, pass, false, &pass->hw_setup);
635*61046927SAndroid Build Coastguard Worker    if (result != VK_SUCCESS)
636*61046927SAndroid Build Coastguard Worker       goto err_free_pass;
637*61046927SAndroid Build Coastguard Worker 
638*61046927SAndroid Build Coastguard Worker    pvr_init_subpass_isp_userpass(pass->hw_setup, pass, pass->subpasses);
639*61046927SAndroid Build Coastguard Worker 
640*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pass->hw_setup->render_count; i++) {
641*61046927SAndroid Build Coastguard Worker       struct pvr_renderpass_hwsetup_render *hw_render =
642*61046927SAndroid Build Coastguard Worker          &pass->hw_setup->renders[i];
643*61046927SAndroid Build Coastguard Worker       struct pvr_load_op *load_op = NULL;
644*61046927SAndroid Build Coastguard Worker 
645*61046927SAndroid Build Coastguard Worker       if (hw_render->tile_buffers_count) {
646*61046927SAndroid Build Coastguard Worker          result = pvr_device_tile_buffer_ensure_cap(
647*61046927SAndroid Build Coastguard Worker             device,
648*61046927SAndroid Build Coastguard Worker             hw_render->tile_buffers_count,
649*61046927SAndroid Build Coastguard Worker             hw_render->eot_setup.tile_buffer_size);
650*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS)
651*61046927SAndroid Build Coastguard Worker             goto err_free_pass;
652*61046927SAndroid Build Coastguard Worker       }
653*61046927SAndroid Build Coastguard Worker 
654*61046927SAndroid Build Coastguard Worker       assert(!hw_render->load_op);
655*61046927SAndroid Build Coastguard Worker 
656*61046927SAndroid Build Coastguard Worker       if (hw_render->color_init_count != 0U) {
657*61046927SAndroid Build Coastguard Worker          if (!pvr_has_output_register_writes(hw_render)) {
658*61046927SAndroid Build Coastguard Worker             const uint32_t last = hw_render->init_setup.num_render_targets;
659*61046927SAndroid Build Coastguard Worker             struct usc_mrt_resource *mrt_resources;
660*61046927SAndroid Build Coastguard Worker 
661*61046927SAndroid Build Coastguard Worker             hw_render->init_setup.num_render_targets++;
662*61046927SAndroid Build Coastguard Worker 
663*61046927SAndroid Build Coastguard Worker             mrt_resources =
664*61046927SAndroid Build Coastguard Worker                vk_realloc(alloc,
665*61046927SAndroid Build Coastguard Worker                           hw_render->init_setup.mrt_resources,
666*61046927SAndroid Build Coastguard Worker                           hw_render->init_setup.num_render_targets *
667*61046927SAndroid Build Coastguard Worker                              sizeof(*mrt_resources),
668*61046927SAndroid Build Coastguard Worker                           8U,
669*61046927SAndroid Build Coastguard Worker                           VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
670*61046927SAndroid Build Coastguard Worker             if (!mrt_resources) {
671*61046927SAndroid Build Coastguard Worker                result = vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
672*61046927SAndroid Build Coastguard Worker                goto err_load_op_destroy;
673*61046927SAndroid Build Coastguard Worker             }
674*61046927SAndroid Build Coastguard Worker 
675*61046927SAndroid Build Coastguard Worker             hw_render->init_setup.mrt_resources = mrt_resources;
676*61046927SAndroid Build Coastguard Worker 
677*61046927SAndroid Build Coastguard Worker             mrt_resources[last].type = USC_MRT_RESOURCE_TYPE_OUTPUT_REG;
678*61046927SAndroid Build Coastguard Worker             mrt_resources[last].reg.output_reg = 0U;
679*61046927SAndroid Build Coastguard Worker             mrt_resources[last].reg.offset = 0U;
680*61046927SAndroid Build Coastguard Worker             mrt_resources[last].intermediate_size = 4U;
681*61046927SAndroid Build Coastguard Worker             mrt_resources[last].mrt_desc.intermediate_size = 4U;
682*61046927SAndroid Build Coastguard Worker             mrt_resources[last].mrt_desc.priority = 0U;
683*61046927SAndroid Build Coastguard Worker             mrt_resources[last].mrt_desc.valid_mask[0U] = ~0;
684*61046927SAndroid Build Coastguard Worker             mrt_resources[last].mrt_desc.valid_mask[1U] = ~0;
685*61046927SAndroid Build Coastguard Worker             mrt_resources[last].mrt_desc.valid_mask[2U] = ~0;
686*61046927SAndroid Build Coastguard Worker             mrt_resources[last].mrt_desc.valid_mask[3U] = ~0;
687*61046927SAndroid Build Coastguard Worker          }
688*61046927SAndroid Build Coastguard Worker 
689*61046927SAndroid Build Coastguard Worker          result = pvr_create_render_load_op(device,
690*61046927SAndroid Build Coastguard Worker                                             pAllocator,
691*61046927SAndroid Build Coastguard Worker                                             pass,
692*61046927SAndroid Build Coastguard Worker                                             hw_render,
693*61046927SAndroid Build Coastguard Worker                                             &load_op);
694*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS)
695*61046927SAndroid Build Coastguard Worker             goto err_load_op_destroy;
696*61046927SAndroid Build Coastguard Worker 
697*61046927SAndroid Build Coastguard Worker          result =
698*61046927SAndroid Build Coastguard Worker             pvr_generate_load_op_shader(device, pAllocator, hw_render, load_op);
699*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS) {
700*61046927SAndroid Build Coastguard Worker             vk_free2(&device->vk.alloc, pAllocator, load_op);
701*61046927SAndroid Build Coastguard Worker             goto err_load_op_destroy;
702*61046927SAndroid Build Coastguard Worker          }
703*61046927SAndroid Build Coastguard Worker 
704*61046927SAndroid Build Coastguard Worker          hw_render->load_op = load_op;
705*61046927SAndroid Build Coastguard Worker       }
706*61046927SAndroid Build Coastguard Worker 
707*61046927SAndroid Build Coastguard Worker       for (uint32_t j = 0; j < hw_render->subpass_count; j++) {
708*61046927SAndroid Build Coastguard Worker          if (!pvr_is_load_op_needed(pass, hw_render, j))
709*61046927SAndroid Build Coastguard Worker             continue;
710*61046927SAndroid Build Coastguard Worker 
711*61046927SAndroid Build Coastguard Worker          result = pvr_create_subpass_load_op(device,
712*61046927SAndroid Build Coastguard Worker                                              pAllocator,
713*61046927SAndroid Build Coastguard Worker                                              pass,
714*61046927SAndroid Build Coastguard Worker                                              hw_render,
715*61046927SAndroid Build Coastguard Worker                                              j,
716*61046927SAndroid Build Coastguard Worker                                              &load_op);
717*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS) {
718*61046927SAndroid Build Coastguard Worker             vk_free2(&device->vk.alloc, pAllocator, load_op);
719*61046927SAndroid Build Coastguard Worker             goto err_load_op_destroy;
720*61046927SAndroid Build Coastguard Worker          }
721*61046927SAndroid Build Coastguard Worker 
722*61046927SAndroid Build Coastguard Worker          result =
723*61046927SAndroid Build Coastguard Worker             pvr_generate_load_op_shader(device, pAllocator, hw_render, load_op);
724*61046927SAndroid Build Coastguard Worker          if (result != VK_SUCCESS)
725*61046927SAndroid Build Coastguard Worker             goto err_load_op_destroy;
726*61046927SAndroid Build Coastguard Worker 
727*61046927SAndroid Build Coastguard Worker          hw_render->subpasses[j].load_op = load_op;
728*61046927SAndroid Build Coastguard Worker       }
729*61046927SAndroid Build Coastguard Worker    }
730*61046927SAndroid Build Coastguard Worker 
731*61046927SAndroid Build Coastguard Worker    *pRenderPass = pvr_render_pass_to_handle(pass);
732*61046927SAndroid Build Coastguard Worker 
733*61046927SAndroid Build Coastguard Worker    return VK_SUCCESS;
734*61046927SAndroid Build Coastguard Worker 
735*61046927SAndroid Build Coastguard Worker err_load_op_destroy:
736*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pass->hw_setup->render_count; i++) {
737*61046927SAndroid Build Coastguard Worker       struct pvr_renderpass_hwsetup_render *hw_render =
738*61046927SAndroid Build Coastguard Worker          &pass->hw_setup->renders[i];
739*61046927SAndroid Build Coastguard Worker 
740*61046927SAndroid Build Coastguard Worker       for (uint32_t j = 0; j < hw_render->subpass_count; j++) {
741*61046927SAndroid Build Coastguard Worker          if (hw_render->subpasses[j].load_op) {
742*61046927SAndroid Build Coastguard Worker             pvr_load_op_destroy(device,
743*61046927SAndroid Build Coastguard Worker                                 pAllocator,
744*61046927SAndroid Build Coastguard Worker                                 hw_render->subpasses[j].load_op);
745*61046927SAndroid Build Coastguard Worker          }
746*61046927SAndroid Build Coastguard Worker       }
747*61046927SAndroid Build Coastguard Worker 
748*61046927SAndroid Build Coastguard Worker       if (hw_render->load_op)
749*61046927SAndroid Build Coastguard Worker          pvr_load_op_destroy(device, pAllocator, hw_render->load_op);
750*61046927SAndroid Build Coastguard Worker    }
751*61046927SAndroid Build Coastguard Worker 
752*61046927SAndroid Build Coastguard Worker    pvr_destroy_renderpass_hwsetup(alloc, pass->hw_setup);
753*61046927SAndroid Build Coastguard Worker 
754*61046927SAndroid Build Coastguard Worker err_free_pass:
755*61046927SAndroid Build Coastguard Worker    vk_object_base_finish(&pass->base);
756*61046927SAndroid Build Coastguard Worker    vk_free2(&device->vk.alloc, pAllocator, pass);
757*61046927SAndroid Build Coastguard Worker 
758*61046927SAndroid Build Coastguard Worker    return result;
759*61046927SAndroid Build Coastguard Worker }
760*61046927SAndroid Build Coastguard Worker 
pvr_DestroyRenderPass(VkDevice _device,VkRenderPass _pass,const VkAllocationCallbacks * pAllocator)761*61046927SAndroid Build Coastguard Worker void pvr_DestroyRenderPass(VkDevice _device,
762*61046927SAndroid Build Coastguard Worker                            VkRenderPass _pass,
763*61046927SAndroid Build Coastguard Worker                            const VkAllocationCallbacks *pAllocator)
764*61046927SAndroid Build Coastguard Worker {
765*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_device, device, _device);
766*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_render_pass, pass, _pass);
767*61046927SAndroid Build Coastguard Worker 
768*61046927SAndroid Build Coastguard Worker    if (!pass)
769*61046927SAndroid Build Coastguard Worker       return;
770*61046927SAndroid Build Coastguard Worker 
771*61046927SAndroid Build Coastguard Worker    for (uint32_t i = 0; i < pass->hw_setup->render_count; i++) {
772*61046927SAndroid Build Coastguard Worker       struct pvr_renderpass_hwsetup_render *hw_render =
773*61046927SAndroid Build Coastguard Worker          &pass->hw_setup->renders[i];
774*61046927SAndroid Build Coastguard Worker 
775*61046927SAndroid Build Coastguard Worker       for (uint32_t j = 0; j < hw_render->subpass_count; j++) {
776*61046927SAndroid Build Coastguard Worker          if (hw_render->subpasses[j].load_op) {
777*61046927SAndroid Build Coastguard Worker             pvr_load_op_destroy(device,
778*61046927SAndroid Build Coastguard Worker                                 pAllocator,
779*61046927SAndroid Build Coastguard Worker                                 hw_render->subpasses[j].load_op);
780*61046927SAndroid Build Coastguard Worker          }
781*61046927SAndroid Build Coastguard Worker       }
782*61046927SAndroid Build Coastguard Worker 
783*61046927SAndroid Build Coastguard Worker       if (hw_render->load_op)
784*61046927SAndroid Build Coastguard Worker          pvr_load_op_destroy(device, pAllocator, hw_render->load_op);
785*61046927SAndroid Build Coastguard Worker    }
786*61046927SAndroid Build Coastguard Worker 
787*61046927SAndroid Build Coastguard Worker    pvr_destroy_renderpass_hwsetup(pAllocator ? pAllocator : &device->vk.alloc,
788*61046927SAndroid Build Coastguard Worker                                   pass->hw_setup);
789*61046927SAndroid Build Coastguard Worker    vk_object_base_finish(&pass->base);
790*61046927SAndroid Build Coastguard Worker    vk_free2(&device->vk.alloc, pAllocator, pass);
791*61046927SAndroid Build Coastguard Worker }
792*61046927SAndroid Build Coastguard Worker 
pvr_GetRenderAreaGranularity(VkDevice _device,VkRenderPass renderPass,VkExtent2D * pGranularity)793*61046927SAndroid Build Coastguard Worker void pvr_GetRenderAreaGranularity(VkDevice _device,
794*61046927SAndroid Build Coastguard Worker                                   VkRenderPass renderPass,
795*61046927SAndroid Build Coastguard Worker                                   VkExtent2D *pGranularity)
796*61046927SAndroid Build Coastguard Worker {
797*61046927SAndroid Build Coastguard Worker    PVR_FROM_HANDLE(pvr_device, device, _device);
798*61046927SAndroid Build Coastguard Worker    const struct pvr_device_info *dev_info = &device->pdevice->dev_info;
799*61046927SAndroid Build Coastguard Worker 
800*61046927SAndroid Build Coastguard Worker    /* Granularity does not depend on any settings in the render pass, so return
801*61046927SAndroid Build Coastguard Worker     * the tile granularity.
802*61046927SAndroid Build Coastguard Worker     *
803*61046927SAndroid Build Coastguard Worker     * The default value is based on the minimum value found in all existing
804*61046927SAndroid Build Coastguard Worker     * cores.
805*61046927SAndroid Build Coastguard Worker     */
806*61046927SAndroid Build Coastguard Worker    pGranularity->width = PVR_GET_FEATURE_VALUE(dev_info, tile_size_x, 16);
807*61046927SAndroid Build Coastguard Worker    pGranularity->height = PVR_GET_FEATURE_VALUE(dev_info, tile_size_y, 16);
808*61046927SAndroid Build Coastguard Worker }
809