1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2018 Collabora Ltd. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * on the rights to use, copy, modify, merge, publish, distribute, sub 8bf215546Sopenharmony_ci * license, and/or sell copies of the Software, and to permit persons to whom 9bf215546Sopenharmony_ci * the Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 19bf215546Sopenharmony_ci * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 20bf215546Sopenharmony_ci * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 21bf215546Sopenharmony_ci * USE OR OTHER DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "zink_context.h" 25bf215546Sopenharmony_ci#include "zink_framebuffer.h" 26bf215546Sopenharmony_ci#include "zink_kopper.h" 27bf215546Sopenharmony_ci#include "zink_query.h" 28bf215546Sopenharmony_ci#include "zink_render_pass.h" 29bf215546Sopenharmony_ci#include "zink_resource.h" 30bf215546Sopenharmony_ci#include "zink_screen.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "util/u_memory.h" 33bf215546Sopenharmony_ci#include "util/u_string.h" 34bf215546Sopenharmony_ci#include "util/u_blitter.h" 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_cistatic VkAttachmentLoadOp 37bf215546Sopenharmony_ciget_rt_loadop(const struct zink_rt_attrib *rt, bool clear) 38bf215546Sopenharmony_ci{ 39bf215546Sopenharmony_ci return clear ? VK_ATTACHMENT_LOAD_OP_CLEAR : 40bf215546Sopenharmony_ci /* TODO: need replicate EXT */ 41bf215546Sopenharmony_ci //rt->resolve || rt->invalid ? 42bf215546Sopenharmony_ci rt->invalid ? 43bf215546Sopenharmony_ci VK_ATTACHMENT_LOAD_OP_DONT_CARE : 44bf215546Sopenharmony_ci VK_ATTACHMENT_LOAD_OP_LOAD; 45bf215546Sopenharmony_ci} 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_cistatic VkImageLayout 48bf215546Sopenharmony_ciget_color_rt_layout(const struct zink_rt_attrib *rt) 49bf215546Sopenharmony_ci{ 50bf215546Sopenharmony_ci return rt->fbfetch ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; 51bf215546Sopenharmony_ci} 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_cistatic VkImageLayout 54bf215546Sopenharmony_ciget_zs_rt_layout(const struct zink_rt_attrib *rt) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci bool has_clear = rt->clear_color || rt->clear_stencil; 57bf215546Sopenharmony_ci if (rt->mixed_zs) 58bf215546Sopenharmony_ci return VK_IMAGE_LAYOUT_GENERAL; 59bf215546Sopenharmony_ci return rt->needs_write || has_clear ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; 60bf215546Sopenharmony_ci} 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_cistatic VkRenderPass 63bf215546Sopenharmony_cicreate_render_pass2(struct zink_screen *screen, struct zink_render_pass_state *state, struct zink_render_pass_pipeline_state *pstate) 64bf215546Sopenharmony_ci{ 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci VkAttachmentReference2 color_refs[PIPE_MAX_COLOR_BUFS], color_resolves[PIPE_MAX_COLOR_BUFS], zs_ref, zs_resolve; 67bf215546Sopenharmony_ci VkAttachmentReference2 input_attachments[PIPE_MAX_COLOR_BUFS]; 68bf215546Sopenharmony_ci VkAttachmentDescription2 attachments[2 * (PIPE_MAX_COLOR_BUFS + 1)]; 69bf215546Sopenharmony_ci VkPipelineStageFlags dep_pipeline = 0; 70bf215546Sopenharmony_ci VkAccessFlags dep_access = 0; 71bf215546Sopenharmony_ci unsigned input_count = 0; 72bf215546Sopenharmony_ci const unsigned cresolve_offset = state->num_cbufs + state->have_zsbuf; 73bf215546Sopenharmony_ci const unsigned zsresolve_offset = cresolve_offset + state->num_cresolves; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci pstate->num_attachments = state->num_cbufs; 76bf215546Sopenharmony_ci pstate->num_cresolves = state->num_cresolves; 77bf215546Sopenharmony_ci pstate->num_zsresolves = state->num_zsresolves; 78bf215546Sopenharmony_ci pstate->fbfetch = 0; 79bf215546Sopenharmony_ci for (int i = 0; i < state->num_cbufs; i++) { 80bf215546Sopenharmony_ci struct zink_rt_attrib *rt = state->rts + i; 81bf215546Sopenharmony_ci attachments[i].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2; 82bf215546Sopenharmony_ci attachments[i].pNext = NULL; 83bf215546Sopenharmony_ci attachments[i].flags = 0; 84bf215546Sopenharmony_ci pstate->attachments[i].format = attachments[i].format = rt->format; 85bf215546Sopenharmony_ci pstate->attachments[i].samples = attachments[i].samples = rt->samples; 86bf215546Sopenharmony_ci attachments[i].loadOp = get_rt_loadop(rt, rt->clear_color); 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci /* TODO: need replicate EXT */ 89bf215546Sopenharmony_ci //attachments[i].storeOp = rt->resolve ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE; 90bf215546Sopenharmony_ci attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; 91bf215546Sopenharmony_ci attachments[i].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 92bf215546Sopenharmony_ci attachments[i].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; 93bf215546Sopenharmony_ci /* if layout changes are ever handled here, need VkAttachmentSampleLocationsEXT */ 94bf215546Sopenharmony_ci VkImageLayout layout = get_color_rt_layout(rt); 95bf215546Sopenharmony_ci attachments[i].initialLayout = layout; 96bf215546Sopenharmony_ci attachments[i].finalLayout = layout; 97bf215546Sopenharmony_ci color_refs[i].sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; 98bf215546Sopenharmony_ci color_refs[i].pNext = NULL; 99bf215546Sopenharmony_ci color_refs[i].attachment = i; 100bf215546Sopenharmony_ci color_refs[i].layout = layout; 101bf215546Sopenharmony_ci color_refs[i].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; 102bf215546Sopenharmony_ci dep_pipeline |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 103bf215546Sopenharmony_ci if (rt->fbfetch) { 104bf215546Sopenharmony_ci memcpy(&input_attachments[input_count++], &color_refs[i], sizeof(VkAttachmentReference2)); 105bf215546Sopenharmony_ci dep_pipeline |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; 106bf215546Sopenharmony_ci dep_access |= VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; 107bf215546Sopenharmony_ci pstate->fbfetch = 1; 108bf215546Sopenharmony_ci } 109bf215546Sopenharmony_ci dep_access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 110bf215546Sopenharmony_ci if (attachments[i].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD) 111bf215546Sopenharmony_ci dep_access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci if (rt->resolve) { 114bf215546Sopenharmony_ci memcpy(&attachments[cresolve_offset + i], &attachments[i], sizeof(VkAttachmentDescription2)); 115bf215546Sopenharmony_ci attachments[cresolve_offset + i].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 116bf215546Sopenharmony_ci attachments[cresolve_offset + i].storeOp = VK_ATTACHMENT_STORE_OP_STORE; 117bf215546Sopenharmony_ci attachments[cresolve_offset + i].samples = 1; 118bf215546Sopenharmony_ci memcpy(&color_resolves[i], &color_refs[i], sizeof(VkAttachmentReference2)); 119bf215546Sopenharmony_ci color_resolves[i].attachment = cresolve_offset + i; 120bf215546Sopenharmony_ci if (attachments[cresolve_offset + i].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD) 121bf215546Sopenharmony_ci dep_access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; 122bf215546Sopenharmony_ci } 123bf215546Sopenharmony_ci } 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci int num_attachments = state->num_cbufs; 126bf215546Sopenharmony_ci if (state->have_zsbuf) { 127bf215546Sopenharmony_ci struct zink_rt_attrib *rt = state->rts + state->num_cbufs; 128bf215546Sopenharmony_ci VkImageLayout layout = get_zs_rt_layout(rt); 129bf215546Sopenharmony_ci attachments[num_attachments].sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2; 130bf215546Sopenharmony_ci attachments[num_attachments].pNext = NULL; 131bf215546Sopenharmony_ci attachments[num_attachments].flags = 0; 132bf215546Sopenharmony_ci pstate->attachments[num_attachments].format = attachments[num_attachments].format = rt->format; 133bf215546Sopenharmony_ci pstate->attachments[num_attachments].samples = attachments[num_attachments].samples = rt->samples; 134bf215546Sopenharmony_ci attachments[num_attachments].loadOp = rt->clear_color ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD; 135bf215546Sopenharmony_ci attachments[num_attachments].stencilLoadOp = rt->clear_stencil ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD; 136bf215546Sopenharmony_ci /* TODO: need replicate EXT */ 137bf215546Sopenharmony_ci //attachments[num_attachments].storeOp = rt->resolve ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE; 138bf215546Sopenharmony_ci //attachments[num_attachments].stencilStoreOp = rt->resolve ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE; 139bf215546Sopenharmony_ci attachments[num_attachments].storeOp = VK_ATTACHMENT_STORE_OP_STORE; 140bf215546Sopenharmony_ci attachments[num_attachments].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; 141bf215546Sopenharmony_ci /* if layout changes are ever handled here, need VkAttachmentSampleLocationsEXT */ 142bf215546Sopenharmony_ci attachments[num_attachments].initialLayout = layout; 143bf215546Sopenharmony_ci attachments[num_attachments].finalLayout = layout; 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci dep_pipeline |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; 146bf215546Sopenharmony_ci if (layout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) 147bf215546Sopenharmony_ci dep_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; 148bf215546Sopenharmony_ci if (attachments[num_attachments].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD || 149bf215546Sopenharmony_ci attachments[num_attachments].stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD) 150bf215546Sopenharmony_ci dep_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci zs_ref.sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2; 153bf215546Sopenharmony_ci zs_ref.pNext = NULL; 154bf215546Sopenharmony_ci zs_ref.attachment = num_attachments++; 155bf215546Sopenharmony_ci zs_ref.layout = layout; 156bf215546Sopenharmony_ci if (rt->resolve) { 157bf215546Sopenharmony_ci memcpy(&attachments[zsresolve_offset], &attachments[num_attachments], sizeof(VkAttachmentDescription2)); 158bf215546Sopenharmony_ci attachments[zsresolve_offset].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 159bf215546Sopenharmony_ci attachments[zsresolve_offset].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; 160bf215546Sopenharmony_ci attachments[zsresolve_offset].storeOp = VK_ATTACHMENT_STORE_OP_STORE; 161bf215546Sopenharmony_ci attachments[zsresolve_offset].stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; 162bf215546Sopenharmony_ci attachments[zsresolve_offset].samples = 1; 163bf215546Sopenharmony_ci memcpy(&zs_resolve, &zs_ref, sizeof(VkAttachmentReference2)); 164bf215546Sopenharmony_ci zs_ref.attachment = zsresolve_offset; 165bf215546Sopenharmony_ci if (attachments[zsresolve_offset].loadOp == VK_ATTACHMENT_LOAD_OP_LOAD || 166bf215546Sopenharmony_ci attachments[zsresolve_offset].stencilLoadOp == VK_ATTACHMENT_LOAD_OP_LOAD) 167bf215546Sopenharmony_ci dep_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; 168bf215546Sopenharmony_ci } 169bf215546Sopenharmony_ci pstate->num_attachments++; 170bf215546Sopenharmony_ci } 171bf215546Sopenharmony_ci pstate->color_read = (dep_access & VK_ACCESS_COLOR_ATTACHMENT_READ_BIT) > 0; 172bf215546Sopenharmony_ci pstate->depth_read = (dep_access & VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT) > 0; 173bf215546Sopenharmony_ci pstate->depth_write = (dep_access & VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT) > 0; 174bf215546Sopenharmony_ci 175bf215546Sopenharmony_ci if (!screen->info.have_KHR_synchronization2) 176bf215546Sopenharmony_ci dep_pipeline = MAX2(dep_pipeline, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_ci VkDependencyFlags flag = screen->info.have_KHR_synchronization2 ? VK_DEPENDENCY_BY_REGION_BIT : 0; 179bf215546Sopenharmony_ci VkSubpassDependency2 deps[] = { 180bf215546Sopenharmony_ci {VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, NULL, VK_SUBPASS_EXTERNAL, 0, dep_pipeline, dep_pipeline, 0, dep_access, flag, 0}, 181bf215546Sopenharmony_ci {VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, NULL, 0, VK_SUBPASS_EXTERNAL, dep_pipeline, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, dep_access, 0, flag, 0} 182bf215546Sopenharmony_ci }; 183bf215546Sopenharmony_ci VkPipelineStageFlags input_dep = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; 184bf215546Sopenharmony_ci //if (zs_fbfetch) input_dep |= VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; 185bf215546Sopenharmony_ci VkAccessFlags input_access = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT; 186bf215546Sopenharmony_ci //if (zs_fbfetch) input_access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; 187bf215546Sopenharmony_ci VkSubpassDependency2 fbfetch_deps[] = { 188bf215546Sopenharmony_ci {VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, NULL, VK_SUBPASS_EXTERNAL, 0, dep_pipeline, dep_pipeline, 0, dep_access, flag, 0}, 189bf215546Sopenharmony_ci {VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, NULL, 0, 0, dep_pipeline, input_dep, dep_access, input_access, flag, 0}, 190bf215546Sopenharmony_ci {VK_STRUCTURE_TYPE_SUBPASS_DEPENDENCY_2, NULL, 0, VK_SUBPASS_EXTERNAL, dep_pipeline, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, dep_access, 0, flag, 0} 191bf215546Sopenharmony_ci }; 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci VkSubpassDescription2 subpass = {0}; 194bf215546Sopenharmony_ci VkSubpassDescriptionDepthStencilResolve zsresolve; 195bf215546Sopenharmony_ci subpass.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2; 196bf215546Sopenharmony_ci subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; 197bf215546Sopenharmony_ci subpass.colorAttachmentCount = state->num_cbufs; 198bf215546Sopenharmony_ci subpass.pColorAttachments = color_refs; 199bf215546Sopenharmony_ci subpass.pDepthStencilAttachment = state->have_zsbuf ? &zs_ref : NULL; 200bf215546Sopenharmony_ci subpass.inputAttachmentCount = input_count; 201bf215546Sopenharmony_ci subpass.pInputAttachments = input_attachments; 202bf215546Sopenharmony_ci if (state->num_cresolves) 203bf215546Sopenharmony_ci subpass.pResolveAttachments = color_resolves; 204bf215546Sopenharmony_ci if (state->num_zsresolves) { 205bf215546Sopenharmony_ci subpass.pNext = &zsresolve; 206bf215546Sopenharmony_ci zsresolve.sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE; 207bf215546Sopenharmony_ci zsresolve.pNext = NULL; 208bf215546Sopenharmony_ci zsresolve.depthResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT; 209bf215546Sopenharmony_ci zsresolve.stencilResolveMode = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT; 210bf215546Sopenharmony_ci zsresolve.pDepthStencilResolveAttachment = &zs_resolve; 211bf215546Sopenharmony_ci } else 212bf215546Sopenharmony_ci subpass.pNext = NULL; 213bf215546Sopenharmony_ci 214bf215546Sopenharmony_ci VkRenderPassCreateInfo2 rpci = {0}; 215bf215546Sopenharmony_ci rpci.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2; 216bf215546Sopenharmony_ci rpci.attachmentCount = num_attachments + state->num_cresolves + state->num_zsresolves; 217bf215546Sopenharmony_ci rpci.pAttachments = attachments; 218bf215546Sopenharmony_ci rpci.subpassCount = 1; 219bf215546Sopenharmony_ci rpci.pSubpasses = &subpass; 220bf215546Sopenharmony_ci rpci.dependencyCount = input_count ? 3 : 2; 221bf215546Sopenharmony_ci rpci.pDependencies = input_count ? fbfetch_deps : deps; 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci VkRenderPass render_pass; 224bf215546Sopenharmony_ci VkResult result = VKSCR(CreateRenderPass2)(screen->dev, &rpci, NULL, &render_pass); 225bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 226bf215546Sopenharmony_ci mesa_loge("ZINK: vkCreateRenderPass2 failed (%s)", vk_Result_to_str(result)); 227bf215546Sopenharmony_ci return VK_NULL_HANDLE; 228bf215546Sopenharmony_ci } 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci return render_pass; 231bf215546Sopenharmony_ci} 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_cistruct zink_render_pass * 234bf215546Sopenharmony_cizink_create_render_pass(struct zink_screen *screen, 235bf215546Sopenharmony_ci struct zink_render_pass_state *state, 236bf215546Sopenharmony_ci struct zink_render_pass_pipeline_state *pstate) 237bf215546Sopenharmony_ci{ 238bf215546Sopenharmony_ci struct zink_render_pass *rp = CALLOC_STRUCT(zink_render_pass); 239bf215546Sopenharmony_ci if (!rp) 240bf215546Sopenharmony_ci goto fail; 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci rp->render_pass = create_render_pass2(screen, state, pstate); 243bf215546Sopenharmony_ci if (!rp->render_pass) 244bf215546Sopenharmony_ci goto fail; 245bf215546Sopenharmony_ci memcpy(&rp->state, state, sizeof(struct zink_render_pass_state)); 246bf215546Sopenharmony_ci return rp; 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_cifail: 249bf215546Sopenharmony_ci if (rp) 250bf215546Sopenharmony_ci zink_destroy_render_pass(screen, rp); 251bf215546Sopenharmony_ci return NULL; 252bf215546Sopenharmony_ci} 253bf215546Sopenharmony_ci 254bf215546Sopenharmony_civoid 255bf215546Sopenharmony_cizink_destroy_render_pass(struct zink_screen *screen, 256bf215546Sopenharmony_ci struct zink_render_pass *rp) 257bf215546Sopenharmony_ci{ 258bf215546Sopenharmony_ci VKSCR(DestroyRenderPass)(screen->dev, rp->render_pass, NULL); 259bf215546Sopenharmony_ci FREE(rp); 260bf215546Sopenharmony_ci} 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ciVkImageLayout 263bf215546Sopenharmony_cizink_render_pass_attachment_get_barrier_info(const struct zink_rt_attrib *rt, bool color, 264bf215546Sopenharmony_ci VkPipelineStageFlags *pipeline, VkAccessFlags *access) 265bf215546Sopenharmony_ci{ 266bf215546Sopenharmony_ci *access = 0; 267bf215546Sopenharmony_ci if (color) { 268bf215546Sopenharmony_ci *pipeline = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; 269bf215546Sopenharmony_ci *access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; 270bf215546Sopenharmony_ci if (!rt->clear_color && !rt->invalid) 271bf215546Sopenharmony_ci *access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; 272bf215546Sopenharmony_ci return get_color_rt_layout(rt); 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci 275bf215546Sopenharmony_ci *pipeline = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; 276bf215546Sopenharmony_ci if (rt->mixed_zs) { 277bf215546Sopenharmony_ci *access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; 278bf215546Sopenharmony_ci } else { 279bf215546Sopenharmony_ci if (!rt->clear_color && !rt->clear_stencil) 280bf215546Sopenharmony_ci *access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; 281bf215546Sopenharmony_ci if (rt->clear_color || rt->clear_stencil || rt->needs_write) 282bf215546Sopenharmony_ci *access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; 283bf215546Sopenharmony_ci } 284bf215546Sopenharmony_ci return get_zs_rt_layout(rt); 285bf215546Sopenharmony_ci} 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_cistatic size_t 289bf215546Sopenharmony_cirp_state_size(const struct zink_render_pass_pipeline_state *pstate) 290bf215546Sopenharmony_ci{ 291bf215546Sopenharmony_ci return offsetof(struct zink_render_pass_pipeline_state, attachments) + 292bf215546Sopenharmony_ci sizeof(pstate->attachments[0]) * pstate->num_attachments; 293bf215546Sopenharmony_ci} 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_cistatic uint32_t 296bf215546Sopenharmony_cihash_rp_state(const void *key) 297bf215546Sopenharmony_ci{ 298bf215546Sopenharmony_ci const struct zink_render_pass_pipeline_state *s = key; 299bf215546Sopenharmony_ci return _mesa_hash_data(key, rp_state_size(s)); 300bf215546Sopenharmony_ci} 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_cistatic bool 303bf215546Sopenharmony_ciequals_rp_state(const void *a, const void *b) 304bf215546Sopenharmony_ci{ 305bf215546Sopenharmony_ci return !memcmp(a, b, rp_state_size(a)); 306bf215546Sopenharmony_ci} 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_cistatic uint32_t 309bf215546Sopenharmony_cihash_render_pass_state(const void *key) 310bf215546Sopenharmony_ci{ 311bf215546Sopenharmony_ci struct zink_render_pass_state* s = (struct zink_render_pass_state*)key; 312bf215546Sopenharmony_ci return _mesa_hash_data(key, offsetof(struct zink_render_pass_state, rts) + sizeof(s->rts[0]) * s->num_rts); 313bf215546Sopenharmony_ci} 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_cistatic bool 316bf215546Sopenharmony_ciequals_render_pass_state(const void *a, const void *b) 317bf215546Sopenharmony_ci{ 318bf215546Sopenharmony_ci const struct zink_render_pass_state *s_a = a, *s_b = b; 319bf215546Sopenharmony_ci if (s_a->num_rts != s_b->num_rts) 320bf215546Sopenharmony_ci return false; 321bf215546Sopenharmony_ci return memcmp(a, b, offsetof(struct zink_render_pass_state, rts) + sizeof(s_a->rts[0]) * s_a->num_rts) == 0; 322bf215546Sopenharmony_ci} 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_civoid 325bf215546Sopenharmony_cizink_init_zs_attachment(struct zink_context *ctx, struct zink_rt_attrib *rt) 326bf215546Sopenharmony_ci{ 327bf215546Sopenharmony_ci const struct pipe_framebuffer_state *fb = &ctx->fb_state; 328bf215546Sopenharmony_ci struct zink_resource *zsbuf = zink_resource(fb->zsbuf->texture); 329bf215546Sopenharmony_ci struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[PIPE_MAX_COLOR_BUFS]; 330bf215546Sopenharmony_ci struct zink_surface *transient = zink_transient_surface(fb->zsbuf); 331bf215546Sopenharmony_ci rt->format = zsbuf->format; 332bf215546Sopenharmony_ci rt->samples = MAX3(transient ? transient->base.nr_samples : 0, fb->zsbuf->texture->nr_samples, 1); 333bf215546Sopenharmony_ci rt->clear_color = zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS) && 334bf215546Sopenharmony_ci !zink_fb_clear_first_needs_explicit(fb_clear) && 335bf215546Sopenharmony_ci (zink_fb_clear_element(fb_clear, 0)->zs.bits & PIPE_CLEAR_DEPTH); 336bf215546Sopenharmony_ci rt->clear_stencil = zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS) && 337bf215546Sopenharmony_ci !zink_fb_clear_first_needs_explicit(fb_clear) && 338bf215546Sopenharmony_ci (zink_fb_clear_element(fb_clear, 0)->zs.bits & PIPE_CLEAR_STENCIL); 339bf215546Sopenharmony_ci const uint64_t outputs_written = ctx->gfx_stages[PIPE_SHADER_FRAGMENT] ? 340bf215546Sopenharmony_ci ctx->gfx_stages[PIPE_SHADER_FRAGMENT]->nir->info.outputs_written : 0; 341bf215546Sopenharmony_ci bool needs_write_z = (ctx->dsa_state && ctx->dsa_state->hw_state.depth_write) || 342bf215546Sopenharmony_ci outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH); 343bf215546Sopenharmony_ci needs_write_z |= transient || rt->clear_color || 344bf215546Sopenharmony_ci (zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS) && (zink_fb_clear_element(fb_clear, 0)->zs.bits & PIPE_CLEAR_DEPTH)); 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci bool needs_write_s = rt->clear_stencil || (outputs_written & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) || 347bf215546Sopenharmony_ci (zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS) && (zink_fb_clear_element(fb_clear, 0)->zs.bits & PIPE_CLEAR_STENCIL)); 348bf215546Sopenharmony_ci if (!needs_write_z && (!ctx->dsa_state || !ctx->dsa_state->base.depth_enabled)) 349bf215546Sopenharmony_ci /* depth sample, stencil write */ 350bf215546Sopenharmony_ci rt->mixed_zs = needs_write_s && zsbuf->bind_count[0]; 351bf215546Sopenharmony_ci else 352bf215546Sopenharmony_ci /* depth write + sample */ 353bf215546Sopenharmony_ci rt->mixed_zs = needs_write_z && zsbuf->bind_count[0]; 354bf215546Sopenharmony_ci rt->needs_write = needs_write_z | needs_write_s; 355bf215546Sopenharmony_ci} 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_civoid 358bf215546Sopenharmony_cizink_init_color_attachment(struct zink_context *ctx, unsigned i, struct zink_rt_attrib *rt) 359bf215546Sopenharmony_ci{ 360bf215546Sopenharmony_ci const struct pipe_framebuffer_state *fb = &ctx->fb_state; 361bf215546Sopenharmony_ci struct pipe_surface *psurf = fb->cbufs[i]; 362bf215546Sopenharmony_ci if (psurf && !zink_use_dummy_attachments(ctx)) { 363bf215546Sopenharmony_ci struct zink_surface *surf = zink_csurface(psurf); 364bf215546Sopenharmony_ci struct zink_surface *transient = zink_transient_surface(psurf); 365bf215546Sopenharmony_ci rt->format = surf->info.format[0]; 366bf215546Sopenharmony_ci rt->samples = MAX3(transient ? transient->base.nr_samples : 0, psurf->texture->nr_samples, 1); 367bf215546Sopenharmony_ci rt->clear_color = zink_fb_clear_enabled(ctx, i) && !zink_fb_clear_first_needs_explicit(&ctx->fb_clears[i]); 368bf215546Sopenharmony_ci rt->invalid = !zink_resource(psurf->texture)->valid || (ctx->new_swapchain && (psurf->texture->bind & PIPE_BIND_DISPLAY_TARGET)); 369bf215546Sopenharmony_ci rt->fbfetch = (ctx->fbfetch_outputs & BITFIELD_BIT(i)) > 0; 370bf215546Sopenharmony_ci } else { 371bf215546Sopenharmony_ci memset(rt, 0, sizeof(struct zink_rt_attrib)); 372bf215546Sopenharmony_ci rt->format = VK_FORMAT_R8G8B8A8_UNORM; 373bf215546Sopenharmony_ci rt->samples = fb->samples; 374bf215546Sopenharmony_ci } 375bf215546Sopenharmony_ci} 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_cistatic struct zink_render_pass * 378bf215546Sopenharmony_ciget_render_pass(struct zink_context *ctx) 379bf215546Sopenharmony_ci{ 380bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(ctx->base.screen); 381bf215546Sopenharmony_ci const struct pipe_framebuffer_state *fb = &ctx->fb_state; 382bf215546Sopenharmony_ci struct zink_render_pass_state state = {0}; 383bf215546Sopenharmony_ci uint32_t clears = 0; 384bf215546Sopenharmony_ci state.samples = fb->samples > 0; 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_ci for (int i = 0; i < fb->nr_cbufs; i++) { 387bf215546Sopenharmony_ci zink_init_color_attachment(ctx, i, &state.rts[i]); 388bf215546Sopenharmony_ci struct pipe_surface *surf = fb->cbufs[i]; 389bf215546Sopenharmony_ci if (surf && !zink_use_dummy_attachments(ctx)) { 390bf215546Sopenharmony_ci clears |= !!state.rts[i].clear_color ? PIPE_CLEAR_COLOR0 << i : 0; 391bf215546Sopenharmony_ci struct zink_surface *transient = zink_transient_surface(surf); 392bf215546Sopenharmony_ci if (transient) { 393bf215546Sopenharmony_ci state.num_cresolves++; 394bf215546Sopenharmony_ci state.rts[i].resolve = true; 395bf215546Sopenharmony_ci if (!state.rts[i].clear_color) 396bf215546Sopenharmony_ci state.msaa_expand_mask |= BITFIELD_BIT(i); 397bf215546Sopenharmony_ci } else { 398bf215546Sopenharmony_ci state.rts[i].resolve = false; 399bf215546Sopenharmony_ci } 400bf215546Sopenharmony_ci } 401bf215546Sopenharmony_ci state.num_rts++; 402bf215546Sopenharmony_ci } 403bf215546Sopenharmony_ci state.num_cbufs = fb->nr_cbufs; 404bf215546Sopenharmony_ci assert(!state.num_cresolves || state.num_cbufs == state.num_cresolves); 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci if (fb->zsbuf) { 407bf215546Sopenharmony_ci zink_init_zs_attachment(ctx, &state.rts[fb->nr_cbufs]); 408bf215546Sopenharmony_ci struct zink_surface *transient = zink_transient_surface(fb->zsbuf); 409bf215546Sopenharmony_ci if (transient) { 410bf215546Sopenharmony_ci state.num_zsresolves = 1; 411bf215546Sopenharmony_ci state.rts[fb->nr_cbufs].resolve = true; 412bf215546Sopenharmony_ci } 413bf215546Sopenharmony_ci if (state.rts[fb->nr_cbufs].clear_color) 414bf215546Sopenharmony_ci clears |= PIPE_CLEAR_DEPTH; 415bf215546Sopenharmony_ci if (state.rts[fb->nr_cbufs].clear_stencil) 416bf215546Sopenharmony_ci clears |= PIPE_CLEAR_STENCIL; 417bf215546Sopenharmony_ci state.num_rts++; 418bf215546Sopenharmony_ci } 419bf215546Sopenharmony_ci state.have_zsbuf = fb->zsbuf != NULL; 420bf215546Sopenharmony_ci if (zink_use_dummy_attachments(ctx)) 421bf215546Sopenharmony_ci assert(clears == (ctx->rp_clears_enabled & PIPE_CLEAR_DEPTHSTENCIL)); 422bf215546Sopenharmony_ci else 423bf215546Sopenharmony_ci assert(clears == ctx->rp_clears_enabled); 424bf215546Sopenharmony_ci state.clears = clears; 425bf215546Sopenharmony_ci uint32_t hash = hash_render_pass_state(&state); 426bf215546Sopenharmony_ci struct hash_entry *entry = _mesa_hash_table_search_pre_hashed(ctx->render_pass_cache, hash, 427bf215546Sopenharmony_ci &state); 428bf215546Sopenharmony_ci struct zink_render_pass *rp; 429bf215546Sopenharmony_ci if (entry) { 430bf215546Sopenharmony_ci rp = entry->data; 431bf215546Sopenharmony_ci assert(rp->state.clears == clears); 432bf215546Sopenharmony_ci } else { 433bf215546Sopenharmony_ci struct zink_render_pass_pipeline_state pstate; 434bf215546Sopenharmony_ci pstate.samples = state.samples; 435bf215546Sopenharmony_ci rp = zink_create_render_pass(screen, &state, &pstate); 436bf215546Sopenharmony_ci if (!_mesa_hash_table_insert_pre_hashed(ctx->render_pass_cache, hash, &rp->state, rp)) 437bf215546Sopenharmony_ci return NULL; 438bf215546Sopenharmony_ci bool found = false; 439bf215546Sopenharmony_ci struct set_entry *entry = _mesa_set_search_or_add(&ctx->render_pass_state_cache, &pstate, &found); 440bf215546Sopenharmony_ci struct zink_render_pass_pipeline_state *ppstate; 441bf215546Sopenharmony_ci if (!found) { 442bf215546Sopenharmony_ci entry->key = ralloc(ctx, struct zink_render_pass_pipeline_state); 443bf215546Sopenharmony_ci ppstate = (void*)entry->key; 444bf215546Sopenharmony_ci memcpy(ppstate, &pstate, rp_state_size(&pstate)); 445bf215546Sopenharmony_ci ppstate->id = ctx->render_pass_state_cache.entries; 446bf215546Sopenharmony_ci } 447bf215546Sopenharmony_ci ppstate = (void*)entry->key; 448bf215546Sopenharmony_ci rp->pipeline_state = ppstate->id; 449bf215546Sopenharmony_ci } 450bf215546Sopenharmony_ci return rp; 451bf215546Sopenharmony_ci} 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci/* check whether the active rp needs to be split to replace it with rp2 */ 454bf215546Sopenharmony_cistatic bool 455bf215546Sopenharmony_cirp_must_change(const struct zink_render_pass *rp, const struct zink_render_pass *rp2, bool in_rp) 456bf215546Sopenharmony_ci{ 457bf215546Sopenharmony_ci if (rp == rp2) 458bf215546Sopenharmony_ci return false; 459bf215546Sopenharmony_ci unsigned num_cbufs = rp->state.num_cbufs; 460bf215546Sopenharmony_ci if (rp->pipeline_state != rp2->pipeline_state) { 461bf215546Sopenharmony_ci /* if any core attrib bits are different, must split */ 462bf215546Sopenharmony_ci if (rp->state.val != rp2->state.val) 463bf215546Sopenharmony_ci return true; 464bf215546Sopenharmony_ci for (unsigned i = 0; i < num_cbufs; i++) { 465bf215546Sopenharmony_ci const struct zink_rt_attrib *rt = &rp->state.rts[i]; 466bf215546Sopenharmony_ci const struct zink_rt_attrib *rt2 = &rp2->state.rts[i]; 467bf215546Sopenharmony_ci /* if layout changed, must split */ 468bf215546Sopenharmony_ci if (get_color_rt_layout(rt) != get_color_rt_layout(rt2)) 469bf215546Sopenharmony_ci return true; 470bf215546Sopenharmony_ci } 471bf215546Sopenharmony_ci } 472bf215546Sopenharmony_ci if (rp->state.have_zsbuf) { 473bf215546Sopenharmony_ci const struct zink_rt_attrib *rt = &rp->state.rts[num_cbufs]; 474bf215546Sopenharmony_ci const struct zink_rt_attrib *rt2 = &rp2->state.rts[num_cbufs]; 475bf215546Sopenharmony_ci /* if zs layout has gone from read-only to read-write, split renderpass */ 476bf215546Sopenharmony_ci if (get_zs_rt_layout(rt) == VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL && 477bf215546Sopenharmony_ci get_zs_rt_layout(rt2) == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) 478bf215546Sopenharmony_ci return true; 479bf215546Sopenharmony_ci } 480bf215546Sopenharmony_ci /* any other change doesn't require splitting a renderpass */ 481bf215546Sopenharmony_ci return !in_rp; 482bf215546Sopenharmony_ci} 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_cistatic void 485bf215546Sopenharmony_cisetup_framebuffer(struct zink_context *ctx) 486bf215546Sopenharmony_ci{ 487bf215546Sopenharmony_ci struct zink_screen *screen = zink_screen(ctx->base.screen); 488bf215546Sopenharmony_ci struct zink_render_pass *rp = ctx->gfx_pipeline_state.render_pass; 489bf215546Sopenharmony_ci 490bf215546Sopenharmony_ci zink_update_vk_sample_locations(ctx); 491bf215546Sopenharmony_ci 492bf215546Sopenharmony_ci if (ctx->rp_changed || ctx->rp_layout_changed || ctx->rp_loadop_changed) { 493bf215546Sopenharmony_ci /* 0. ensure no stale pointers are set */ 494bf215546Sopenharmony_ci ctx->gfx_pipeline_state.next_render_pass = NULL; 495bf215546Sopenharmony_ci /* 1. calc new rp */ 496bf215546Sopenharmony_ci rp = get_render_pass(ctx); 497bf215546Sopenharmony_ci /* 2. evaluate whether to use new rp */ 498bf215546Sopenharmony_ci if (ctx->gfx_pipeline_state.render_pass) { 499bf215546Sopenharmony_ci /* 2a. if previous rp exists, check whether new rp MUST be used */ 500bf215546Sopenharmony_ci bool must_change = rp_must_change(ctx->gfx_pipeline_state.render_pass, rp, ctx->batch.in_rp); 501bf215546Sopenharmony_ci ctx->fb_changed |= must_change; 502bf215546Sopenharmony_ci if (!must_change) 503bf215546Sopenharmony_ci /* 2b. if non-essential attribs have changed, store for later use and continue on */ 504bf215546Sopenharmony_ci ctx->gfx_pipeline_state.next_render_pass = rp; 505bf215546Sopenharmony_ci } else { 506bf215546Sopenharmony_ci /* 2c. no previous rp in use, use this one */ 507bf215546Sopenharmony_ci ctx->fb_changed = true; 508bf215546Sopenharmony_ci } 509bf215546Sopenharmony_ci } else if (ctx->gfx_pipeline_state.next_render_pass) { 510bf215546Sopenharmony_ci /* previous rp was calculated but deferred: use it */ 511bf215546Sopenharmony_ci assert(!ctx->batch.in_rp); 512bf215546Sopenharmony_ci rp = ctx->gfx_pipeline_state.next_render_pass; 513bf215546Sopenharmony_ci ctx->gfx_pipeline_state.next_render_pass = NULL; 514bf215546Sopenharmony_ci ctx->fb_changed = true; 515bf215546Sopenharmony_ci } 516bf215546Sopenharmony_ci if (rp->pipeline_state != ctx->gfx_pipeline_state.rp_state) { 517bf215546Sopenharmony_ci ctx->gfx_pipeline_state.rp_state = rp->pipeline_state; 518bf215546Sopenharmony_ci ctx->gfx_pipeline_state.dirty = true; 519bf215546Sopenharmony_ci } 520bf215546Sopenharmony_ci 521bf215546Sopenharmony_ci ctx->rp_loadop_changed = false; 522bf215546Sopenharmony_ci ctx->rp_layout_changed = false; 523bf215546Sopenharmony_ci ctx->rp_changed = false; 524bf215546Sopenharmony_ci zink_render_update_swapchain(ctx); 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci if (!ctx->fb_changed) 527bf215546Sopenharmony_ci return; 528bf215546Sopenharmony_ci 529bf215546Sopenharmony_ci zink_update_framebuffer_state(ctx); 530bf215546Sopenharmony_ci zink_init_framebuffer(screen, ctx->framebuffer, rp); 531bf215546Sopenharmony_ci ctx->fb_changed = false; 532bf215546Sopenharmony_ci ctx->gfx_pipeline_state.render_pass = rp; 533bf215546Sopenharmony_ci zink_batch_no_rp(ctx); 534bf215546Sopenharmony_ci} 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_cistatic bool 537bf215546Sopenharmony_ciprep_fb_attachments(struct zink_context *ctx, VkImageView *att) 538bf215546Sopenharmony_ci{ 539bf215546Sopenharmony_ci const unsigned cresolve_offset = ctx->fb_state.nr_cbufs + !!ctx->fb_state.zsbuf; 540bf215546Sopenharmony_ci unsigned num_resolves = 0; 541bf215546Sopenharmony_ci for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) { 542bf215546Sopenharmony_ci struct zink_surface *surf = zink_csurface(ctx->fb_state.cbufs[i]); 543bf215546Sopenharmony_ci struct zink_surface *transient = zink_transient_surface(ctx->fb_state.cbufs[i]); 544bf215546Sopenharmony_ci if (transient) { 545bf215546Sopenharmony_ci att[i] = zink_prep_fb_attachment(ctx, transient, i); 546bf215546Sopenharmony_ci att[i + cresolve_offset] = zink_prep_fb_attachment(ctx, surf, i); 547bf215546Sopenharmony_ci num_resolves++; 548bf215546Sopenharmony_ci } else { 549bf215546Sopenharmony_ci att[i] = zink_prep_fb_attachment(ctx, surf, i); 550bf215546Sopenharmony_ci if (!att[i]) 551bf215546Sopenharmony_ci /* dead swapchain */ 552bf215546Sopenharmony_ci return false; 553bf215546Sopenharmony_ci } 554bf215546Sopenharmony_ci } 555bf215546Sopenharmony_ci if (ctx->fb_state.zsbuf) { 556bf215546Sopenharmony_ci struct zink_surface *surf = zink_csurface(ctx->fb_state.zsbuf); 557bf215546Sopenharmony_ci struct zink_surface *transient = zink_transient_surface(ctx->fb_state.zsbuf); 558bf215546Sopenharmony_ci if (transient) { 559bf215546Sopenharmony_ci att[ctx->fb_state.nr_cbufs] = zink_prep_fb_attachment(ctx, transient, ctx->fb_state.nr_cbufs); 560bf215546Sopenharmony_ci att[cresolve_offset + num_resolves] = zink_prep_fb_attachment(ctx, surf, ctx->fb_state.nr_cbufs); 561bf215546Sopenharmony_ci } else { 562bf215546Sopenharmony_ci att[ctx->fb_state.nr_cbufs] = zink_prep_fb_attachment(ctx, surf, ctx->fb_state.nr_cbufs); 563bf215546Sopenharmony_ci } 564bf215546Sopenharmony_ci } 565bf215546Sopenharmony_ci return true; 566bf215546Sopenharmony_ci} 567bf215546Sopenharmony_ci 568bf215546Sopenharmony_cistatic unsigned 569bf215546Sopenharmony_cibegin_render_pass(struct zink_context *ctx) 570bf215546Sopenharmony_ci{ 571bf215546Sopenharmony_ci struct zink_batch *batch = &ctx->batch; 572bf215546Sopenharmony_ci struct pipe_framebuffer_state *fb_state = &ctx->fb_state; 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_ci VkRenderPassBeginInfo rpbi = {0}; 575bf215546Sopenharmony_ci rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; 576bf215546Sopenharmony_ci rpbi.renderPass = ctx->gfx_pipeline_state.render_pass->render_pass; 577bf215546Sopenharmony_ci rpbi.renderArea.offset.x = 0; 578bf215546Sopenharmony_ci rpbi.renderArea.offset.y = 0; 579bf215546Sopenharmony_ci rpbi.renderArea.extent.width = fb_state->width; 580bf215546Sopenharmony_ci rpbi.renderArea.extent.height = fb_state->height; 581bf215546Sopenharmony_ci 582bf215546Sopenharmony_ci VkClearValue clears[PIPE_MAX_COLOR_BUFS + 1] = {0}; 583bf215546Sopenharmony_ci unsigned clear_buffers = 0; 584bf215546Sopenharmony_ci uint32_t clear_validate = 0; 585bf215546Sopenharmony_ci for (int i = 0; i < fb_state->nr_cbufs; i++) { 586bf215546Sopenharmony_ci /* these are no-ops */ 587bf215546Sopenharmony_ci if (!fb_state->cbufs[i] || !zink_fb_clear_enabled(ctx, i) || zink_use_dummy_attachments(ctx)) 588bf215546Sopenharmony_ci continue; 589bf215546Sopenharmony_ci /* these need actual clear calls inside the rp */ 590bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(&ctx->fb_clears[i], 0); 591bf215546Sopenharmony_ci if (zink_fb_clear_needs_explicit(&ctx->fb_clears[i])) { 592bf215546Sopenharmony_ci clear_buffers |= (PIPE_CLEAR_COLOR0 << i); 593bf215546Sopenharmony_ci if (zink_fb_clear_count(&ctx->fb_clears[i]) < 2 || 594bf215546Sopenharmony_ci zink_fb_clear_element_needs_explicit(clear)) 595bf215546Sopenharmony_ci continue; 596bf215546Sopenharmony_ci } 597bf215546Sopenharmony_ci /* we now know there's one clear that can be done here */ 598bf215546Sopenharmony_ci memcpy(&clears[i].color, &clear->color, sizeof(float) * 4); 599bf215546Sopenharmony_ci rpbi.clearValueCount = i + 1; 600bf215546Sopenharmony_ci clear_validate |= PIPE_CLEAR_COLOR0 << i; 601bf215546Sopenharmony_ci assert(ctx->framebuffer->rp->state.clears); 602bf215546Sopenharmony_ci } 603bf215546Sopenharmony_ci if (fb_state->zsbuf && zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS)) { 604bf215546Sopenharmony_ci struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[PIPE_MAX_COLOR_BUFS]; 605bf215546Sopenharmony_ci struct zink_framebuffer_clear_data *clear = zink_fb_clear_element(fb_clear, 0); 606bf215546Sopenharmony_ci if (!zink_fb_clear_element_needs_explicit(clear)) { 607bf215546Sopenharmony_ci clears[fb_state->nr_cbufs].depthStencil.depth = clear->zs.depth; 608bf215546Sopenharmony_ci clears[fb_state->nr_cbufs].depthStencil.stencil = clear->zs.stencil; 609bf215546Sopenharmony_ci rpbi.clearValueCount = fb_state->nr_cbufs + 1; 610bf215546Sopenharmony_ci clear_validate |= clear->zs.bits; 611bf215546Sopenharmony_ci assert(ctx->framebuffer->rp->state.clears); 612bf215546Sopenharmony_ci } 613bf215546Sopenharmony_ci if (zink_fb_clear_needs_explicit(fb_clear)) { 614bf215546Sopenharmony_ci for (int j = !zink_fb_clear_element_needs_explicit(clear); 615bf215546Sopenharmony_ci (clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL && j < zink_fb_clear_count(fb_clear); 616bf215546Sopenharmony_ci j++) 617bf215546Sopenharmony_ci clear_buffers |= zink_fb_clear_element(fb_clear, j)->zs.bits; 618bf215546Sopenharmony_ci } 619bf215546Sopenharmony_ci } 620bf215546Sopenharmony_ci assert(clear_validate == ctx->framebuffer->rp->state.clears); 621bf215546Sopenharmony_ci rpbi.pClearValues = &clears[0]; 622bf215546Sopenharmony_ci rpbi.framebuffer = ctx->framebuffer->fb; 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ci assert(ctx->gfx_pipeline_state.render_pass && ctx->framebuffer); 625bf215546Sopenharmony_ci 626bf215546Sopenharmony_ci VkRenderPassAttachmentBeginInfo infos; 627bf215546Sopenharmony_ci VkImageView att[2 * (PIPE_MAX_COLOR_BUFS + 1)]; 628bf215546Sopenharmony_ci infos.sType = VK_STRUCTURE_TYPE_RENDER_PASS_ATTACHMENT_BEGIN_INFO; 629bf215546Sopenharmony_ci infos.pNext = NULL; 630bf215546Sopenharmony_ci infos.attachmentCount = ctx->framebuffer->state.num_attachments; 631bf215546Sopenharmony_ci infos.pAttachments = att; 632bf215546Sopenharmony_ci if (!prep_fb_attachments(ctx, att)) 633bf215546Sopenharmony_ci return 0; 634bf215546Sopenharmony_ci /* this can be set if fbfetch is activated */ 635bf215546Sopenharmony_ci ctx->rp_changed = false; 636bf215546Sopenharmony_ci#ifndef NDEBUG 637bf215546Sopenharmony_ci const unsigned cresolve_offset = ctx->fb_state.nr_cbufs + !!ctx->fb_state.zsbuf; 638bf215546Sopenharmony_ci for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) { 639bf215546Sopenharmony_ci if (ctx->fb_state.cbufs[i]) { 640bf215546Sopenharmony_ci struct zink_surface *surf = zink_csurface(ctx->fb_state.cbufs[i]); 641bf215546Sopenharmony_ci if (zink_use_dummy_attachments(ctx)) { 642bf215546Sopenharmony_ci surf = zink_csurface(ctx->dummy_surface[util_logbase2_ceil(ctx->fb_state.samples)]); 643bf215546Sopenharmony_ci assert(zink_resource(surf->base.texture)->obj->vkusage == ctx->framebuffer->state.infos[i].usage); 644bf215546Sopenharmony_ci } else { 645bf215546Sopenharmony_ci struct zink_surface *transient = zink_transient_surface(ctx->fb_state.cbufs[i]); 646bf215546Sopenharmony_ci if (surf->base.format == ctx->fb_state.cbufs[i]->format) { 647bf215546Sopenharmony_ci if (transient) { 648bf215546Sopenharmony_ci assert(zink_resource(transient->base.texture)->obj->vkusage == ctx->framebuffer->state.infos[i].usage); 649bf215546Sopenharmony_ci assert(zink_resource(surf->base.texture)->obj->vkusage == ctx->framebuffer->state.infos[cresolve_offset].usage); 650bf215546Sopenharmony_ci } else { 651bf215546Sopenharmony_ci assert(zink_resource(surf->base.texture)->obj->vkusage == ctx->framebuffer->state.infos[i].usage); 652bf215546Sopenharmony_ci } 653bf215546Sopenharmony_ci } 654bf215546Sopenharmony_ci } 655bf215546Sopenharmony_ci } 656bf215546Sopenharmony_ci } 657bf215546Sopenharmony_ci if (ctx->fb_state.zsbuf) { 658bf215546Sopenharmony_ci struct zink_surface *surf = zink_csurface(ctx->fb_state.zsbuf); 659bf215546Sopenharmony_ci struct zink_surface *transient = zink_transient_surface(ctx->fb_state.zsbuf); 660bf215546Sopenharmony_ci if (transient) { 661bf215546Sopenharmony_ci assert(zink_resource(transient->base.texture)->obj->vkusage == ctx->framebuffer->state.infos[ctx->fb_state.nr_cbufs].usage); 662bf215546Sopenharmony_ci assert(zink_resource(surf->base.texture)->obj->vkusage == ctx->framebuffer->state.infos[cresolve_offset].usage); 663bf215546Sopenharmony_ci } else { 664bf215546Sopenharmony_ci assert(zink_resource(surf->base.texture)->obj->vkusage == ctx->framebuffer->state.infos[ctx->fb_state.nr_cbufs].usage); 665bf215546Sopenharmony_ci } 666bf215546Sopenharmony_ci } 667bf215546Sopenharmony_ci#endif 668bf215546Sopenharmony_ci rpbi.pNext = &infos; 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_ci VKCTX(CmdBeginRenderPass)(batch->state->cmdbuf, &rpbi, VK_SUBPASS_CONTENTS_INLINE); 671bf215546Sopenharmony_ci batch->in_rp = true; 672bf215546Sopenharmony_ci ctx->new_swapchain = false; 673bf215546Sopenharmony_ci return clear_buffers; 674bf215546Sopenharmony_ci} 675bf215546Sopenharmony_ci 676bf215546Sopenharmony_ciunsigned 677bf215546Sopenharmony_cizink_begin_render_pass(struct zink_context *ctx) 678bf215546Sopenharmony_ci{ 679bf215546Sopenharmony_ci setup_framebuffer(ctx); 680bf215546Sopenharmony_ci if (ctx->batch.in_rp) 681bf215546Sopenharmony_ci return 0; 682bf215546Sopenharmony_ci /* TODO: need replicate EXT */ 683bf215546Sopenharmony_ci if (ctx->framebuffer->rp->state.msaa_expand_mask) { 684bf215546Sopenharmony_ci uint32_t rp_state = ctx->gfx_pipeline_state.rp_state; 685bf215546Sopenharmony_ci struct zink_render_pass *rp = ctx->gfx_pipeline_state.render_pass; 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_ci u_foreach_bit(i, ctx->framebuffer->rp->state.msaa_expand_mask) { 688bf215546Sopenharmony_ci struct zink_ctx_surface *csurf = (struct zink_ctx_surface*)ctx->fb_state.cbufs[i]; 689bf215546Sopenharmony_ci if (csurf->transient_init) 690bf215546Sopenharmony_ci continue; 691bf215546Sopenharmony_ci struct pipe_surface *dst_view = (struct pipe_surface*)csurf->transient; 692bf215546Sopenharmony_ci assert(dst_view); 693bf215546Sopenharmony_ci struct pipe_sampler_view src_templ, *src_view; 694bf215546Sopenharmony_ci struct pipe_resource *src = ctx->fb_state.cbufs[i]->texture; 695bf215546Sopenharmony_ci struct pipe_box dstbox; 696bf215546Sopenharmony_ci 697bf215546Sopenharmony_ci u_box_3d(0, 0, 0, ctx->fb_state.width, ctx->fb_state.height, 698bf215546Sopenharmony_ci 1 + dst_view->u.tex.last_layer - dst_view->u.tex.first_layer, &dstbox); 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_ci util_blitter_default_src_texture(ctx->blitter, &src_templ, src, ctx->fb_state.cbufs[i]->u.tex.level); 701bf215546Sopenharmony_ci src_view = ctx->base.create_sampler_view(&ctx->base, src, &src_templ); 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_ci zink_blit_begin(ctx, ZINK_BLIT_SAVE_FB | ZINK_BLIT_SAVE_FS | ZINK_BLIT_SAVE_TEXTURES); 704bf215546Sopenharmony_ci util_blitter_blit_generic(ctx->blitter, dst_view, &dstbox, 705bf215546Sopenharmony_ci src_view, &dstbox, ctx->fb_state.width, ctx->fb_state.height, 706bf215546Sopenharmony_ci PIPE_MASK_RGBAZS, PIPE_TEX_FILTER_NEAREST, NULL, 707bf215546Sopenharmony_ci false, false, 0); 708bf215546Sopenharmony_ci 709bf215546Sopenharmony_ci pipe_sampler_view_reference(&src_view, NULL); 710bf215546Sopenharmony_ci csurf->transient_init = true; 711bf215546Sopenharmony_ci } 712bf215546Sopenharmony_ci ctx->rp_layout_changed = ctx->rp_loadop_changed = false; 713bf215546Sopenharmony_ci ctx->fb_changed = ctx->rp_changed = false; 714bf215546Sopenharmony_ci ctx->gfx_pipeline_state.rp_state = rp_state; 715bf215546Sopenharmony_ci ctx->gfx_pipeline_state.render_pass = rp; 716bf215546Sopenharmony_ci } 717bf215546Sopenharmony_ci assert(ctx->gfx_pipeline_state.render_pass); 718bf215546Sopenharmony_ci return begin_render_pass(ctx); 719bf215546Sopenharmony_ci} 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_civoid 722bf215546Sopenharmony_cizink_end_render_pass(struct zink_context *ctx) 723bf215546Sopenharmony_ci{ 724bf215546Sopenharmony_ci if (ctx->batch.in_rp) { 725bf215546Sopenharmony_ci VKCTX(CmdEndRenderPass)(ctx->batch.state->cmdbuf); 726bf215546Sopenharmony_ci for (unsigned i = 0; i < ctx->fb_state.nr_cbufs; i++) { 727bf215546Sopenharmony_ci struct zink_ctx_surface *csurf = (struct zink_ctx_surface*)ctx->fb_state.cbufs[i]; 728bf215546Sopenharmony_ci if (csurf) 729bf215546Sopenharmony_ci csurf->transient_init = true; 730bf215546Sopenharmony_ci } 731bf215546Sopenharmony_ci } 732bf215546Sopenharmony_ci ctx->batch.in_rp = false; 733bf215546Sopenharmony_ci} 734bf215546Sopenharmony_ci 735bf215546Sopenharmony_cibool 736bf215546Sopenharmony_cizink_init_render_pass(struct zink_context *ctx) 737bf215546Sopenharmony_ci{ 738bf215546Sopenharmony_ci _mesa_set_init(&ctx->render_pass_state_cache, ctx, hash_rp_state, equals_rp_state); 739bf215546Sopenharmony_ci ctx->render_pass_cache = _mesa_hash_table_create(NULL, 740bf215546Sopenharmony_ci hash_render_pass_state, 741bf215546Sopenharmony_ci equals_render_pass_state); 742bf215546Sopenharmony_ci return !!ctx->render_pass_cache; 743bf215546Sopenharmony_ci} 744bf215546Sopenharmony_ci 745bf215546Sopenharmony_civoid 746bf215546Sopenharmony_cizink_render_update_swapchain(struct zink_context *ctx) 747bf215546Sopenharmony_ci{ 748bf215546Sopenharmony_ci bool has_swapchain = false; 749bf215546Sopenharmony_ci for (unsigned i = 0; i < ctx->fb_state.nr_cbufs; i++) { 750bf215546Sopenharmony_ci if (!ctx->fb_state.cbufs[i]) 751bf215546Sopenharmony_ci continue; 752bf215546Sopenharmony_ci struct zink_resource *res = zink_resource(ctx->fb_state.cbufs[i]->texture); 753bf215546Sopenharmony_ci if (zink_is_swapchain(res)) { 754bf215546Sopenharmony_ci has_swapchain = true; 755bf215546Sopenharmony_ci if (zink_kopper_acquire(ctx, res, UINT64_MAX)) 756bf215546Sopenharmony_ci zink_surface_swapchain_update(ctx, zink_csurface(ctx->fb_state.cbufs[i])); 757bf215546Sopenharmony_ci } 758bf215546Sopenharmony_ci } 759bf215546Sopenharmony_ci if (has_swapchain && (ctx->swapchain_size.width || ctx->swapchain_size.height)) { 760bf215546Sopenharmony_ci unsigned old_w = ctx->fb_state.width; 761bf215546Sopenharmony_ci unsigned old_h = ctx->fb_state.height; 762bf215546Sopenharmony_ci ctx->fb_state.width = ctx->swapchain_size.width; 763bf215546Sopenharmony_ci ctx->fb_state.height = ctx->swapchain_size.height; 764bf215546Sopenharmony_ci zink_kopper_fixup_depth_buffer(ctx); 765bf215546Sopenharmony_ci if (ctx->fb_state.width != old_w || ctx->fb_state.height != old_h) 766bf215546Sopenharmony_ci ctx->scissor_changed = true; 767bf215546Sopenharmony_ci zink_update_framebuffer_state(ctx); 768bf215546Sopenharmony_ci ctx->swapchain_size.width = ctx->swapchain_size.height = 0; 769bf215546Sopenharmony_ci } 770bf215546Sopenharmony_ci} 771