1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2020 Raspberry Pi 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 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * 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 NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "v3dv_private.h" 25bf215546Sopenharmony_ci#include "v3dv_meta_common.h" 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "compiler/nir/nir_builder.h" 28bf215546Sopenharmony_ci#include "util/u_pack_color.h" 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_cistatic void 31bf215546Sopenharmony_ciget_hw_clear_color(struct v3dv_device *device, 32bf215546Sopenharmony_ci const VkClearColorValue *color, 33bf215546Sopenharmony_ci VkFormat fb_format, 34bf215546Sopenharmony_ci VkFormat image_format, 35bf215546Sopenharmony_ci uint32_t internal_type, 36bf215546Sopenharmony_ci uint32_t internal_bpp, 37bf215546Sopenharmony_ci uint32_t *hw_color) 38bf215546Sopenharmony_ci{ 39bf215546Sopenharmony_ci const uint32_t internal_size = 4 << internal_bpp; 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci /* If the image format doesn't match the framebuffer format, then we are 42bf215546Sopenharmony_ci * trying to clear an unsupported tlb format using a compatible 43bf215546Sopenharmony_ci * format for the framebuffer. In this case, we want to make sure that 44bf215546Sopenharmony_ci * we pack the clear value according to the original format semantics, 45bf215546Sopenharmony_ci * not the compatible format. 46bf215546Sopenharmony_ci */ 47bf215546Sopenharmony_ci if (fb_format == image_format) { 48bf215546Sopenharmony_ci v3dv_X(device, get_hw_clear_color)(color, internal_type, internal_size, 49bf215546Sopenharmony_ci hw_color); 50bf215546Sopenharmony_ci } else { 51bf215546Sopenharmony_ci union util_color uc; 52bf215546Sopenharmony_ci enum pipe_format pipe_image_format = 53bf215546Sopenharmony_ci vk_format_to_pipe_format(image_format); 54bf215546Sopenharmony_ci util_pack_color(color->float32, pipe_image_format, &uc); 55bf215546Sopenharmony_ci memcpy(hw_color, uc.ui, internal_size); 56bf215546Sopenharmony_ci } 57bf215546Sopenharmony_ci} 58bf215546Sopenharmony_ci 59bf215546Sopenharmony_ci/* Returns true if the implementation is able to handle the case, false 60bf215546Sopenharmony_ci * otherwise. 61bf215546Sopenharmony_ci*/ 62bf215546Sopenharmony_cistatic bool 63bf215546Sopenharmony_ciclear_image_tlb(struct v3dv_cmd_buffer *cmd_buffer, 64bf215546Sopenharmony_ci struct v3dv_image *image, 65bf215546Sopenharmony_ci const VkClearValue *clear_value, 66bf215546Sopenharmony_ci const VkImageSubresourceRange *range) 67bf215546Sopenharmony_ci{ 68bf215546Sopenharmony_ci const VkOffset3D origin = { 0, 0, 0 }; 69bf215546Sopenharmony_ci VkFormat fb_format; 70bf215546Sopenharmony_ci if (!v3dv_meta_can_use_tlb(image, &origin, &fb_format)) 71bf215546Sopenharmony_ci return false; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci uint32_t internal_type, internal_bpp; 74bf215546Sopenharmony_ci v3dv_X(cmd_buffer->device, get_internal_type_bpp_for_image_aspects) 75bf215546Sopenharmony_ci (fb_format, range->aspectMask, 76bf215546Sopenharmony_ci &internal_type, &internal_bpp); 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci union v3dv_clear_value hw_clear_value = { 0 }; 79bf215546Sopenharmony_ci if (range->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) { 80bf215546Sopenharmony_ci get_hw_clear_color(cmd_buffer->device, &clear_value->color, fb_format, 81bf215546Sopenharmony_ci image->vk.format, internal_type, internal_bpp, 82bf215546Sopenharmony_ci &hw_clear_value.color[0]); 83bf215546Sopenharmony_ci } else { 84bf215546Sopenharmony_ci assert((range->aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) || 85bf215546Sopenharmony_ci (range->aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)); 86bf215546Sopenharmony_ci hw_clear_value.z = clear_value->depthStencil.depth; 87bf215546Sopenharmony_ci hw_clear_value.s = clear_value->depthStencil.stencil; 88bf215546Sopenharmony_ci } 89bf215546Sopenharmony_ci 90bf215546Sopenharmony_ci uint32_t level_count = vk_image_subresource_level_count(&image->vk, range); 91bf215546Sopenharmony_ci uint32_t min_level = range->baseMipLevel; 92bf215546Sopenharmony_ci uint32_t max_level = range->baseMipLevel + level_count; 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci /* For 3D images baseArrayLayer and layerCount must be 0 and 1 respectively. 95bf215546Sopenharmony_ci * Instead, we need to consider the full depth dimension of the image, which 96bf215546Sopenharmony_ci * goes from 0 up to the level's depth extent. 97bf215546Sopenharmony_ci */ 98bf215546Sopenharmony_ci uint32_t min_layer; 99bf215546Sopenharmony_ci uint32_t max_layer; 100bf215546Sopenharmony_ci if (image->vk.image_type != VK_IMAGE_TYPE_3D) { 101bf215546Sopenharmony_ci min_layer = range->baseArrayLayer; 102bf215546Sopenharmony_ci max_layer = range->baseArrayLayer + 103bf215546Sopenharmony_ci vk_image_subresource_layer_count(&image->vk, range); 104bf215546Sopenharmony_ci } else { 105bf215546Sopenharmony_ci min_layer = 0; 106bf215546Sopenharmony_ci max_layer = 0; 107bf215546Sopenharmony_ci } 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci for (uint32_t level = min_level; level < max_level; level++) { 110bf215546Sopenharmony_ci if (image->vk.image_type == VK_IMAGE_TYPE_3D) 111bf215546Sopenharmony_ci max_layer = u_minify(image->vk.extent.depth, level); 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci uint32_t width = u_minify(image->vk.extent.width, level); 114bf215546Sopenharmony_ci uint32_t height = u_minify(image->vk.extent.height, level); 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci struct v3dv_job *job = 117bf215546Sopenharmony_ci v3dv_cmd_buffer_start_job(cmd_buffer, -1, V3DV_JOB_TYPE_GPU_CL); 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci if (!job) 120bf215546Sopenharmony_ci return true; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci v3dv_job_start_frame(job, width, height, max_layer, false, 123bf215546Sopenharmony_ci 1, internal_bpp, 124bf215546Sopenharmony_ci image->vk.samples > VK_SAMPLE_COUNT_1_BIT); 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_ci struct v3dv_meta_framebuffer framebuffer; 127bf215546Sopenharmony_ci v3dv_X(job->device, meta_framebuffer_init)(&framebuffer, fb_format, 128bf215546Sopenharmony_ci internal_type, 129bf215546Sopenharmony_ci &job->frame_tiling); 130bf215546Sopenharmony_ci 131bf215546Sopenharmony_ci v3dv_X(job->device, job_emit_binning_flush)(job); 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci /* If this triggers it is an application bug: the spec requires 134bf215546Sopenharmony_ci * that any aspects to clear are present in the image. 135bf215546Sopenharmony_ci */ 136bf215546Sopenharmony_ci assert(range->aspectMask & image->vk.aspects); 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci v3dv_X(job->device, meta_emit_clear_image_rcl) 139bf215546Sopenharmony_ci (job, image, &framebuffer, &hw_clear_value, 140bf215546Sopenharmony_ci range->aspectMask, min_layer, max_layer, level); 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci v3dv_cmd_buffer_finish_job(cmd_buffer); 143bf215546Sopenharmony_ci } 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci return true; 146bf215546Sopenharmony_ci} 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 149bf215546Sopenharmony_civ3dv_CmdClearColorImage(VkCommandBuffer commandBuffer, 150bf215546Sopenharmony_ci VkImage _image, 151bf215546Sopenharmony_ci VkImageLayout imageLayout, 152bf215546Sopenharmony_ci const VkClearColorValue *pColor, 153bf215546Sopenharmony_ci uint32_t rangeCount, 154bf215546Sopenharmony_ci const VkImageSubresourceRange *pRanges) 155bf215546Sopenharmony_ci{ 156bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer); 157bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_image, image, _image); 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci const VkClearValue clear_value = { 160bf215546Sopenharmony_ci .color = *pColor, 161bf215546Sopenharmony_ci }; 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci cmd_buffer->state.is_transfer = true; 164bf215546Sopenharmony_ci 165bf215546Sopenharmony_ci for (uint32_t i = 0; i < rangeCount; i++) { 166bf215546Sopenharmony_ci if (clear_image_tlb(cmd_buffer, image, &clear_value, &pRanges[i])) 167bf215546Sopenharmony_ci continue; 168bf215546Sopenharmony_ci unreachable("Unsupported color clear."); 169bf215546Sopenharmony_ci } 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci cmd_buffer->state.is_transfer = false; 172bf215546Sopenharmony_ci} 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 175bf215546Sopenharmony_civ3dv_CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, 176bf215546Sopenharmony_ci VkImage _image, 177bf215546Sopenharmony_ci VkImageLayout imageLayout, 178bf215546Sopenharmony_ci const VkClearDepthStencilValue *pDepthStencil, 179bf215546Sopenharmony_ci uint32_t rangeCount, 180bf215546Sopenharmony_ci const VkImageSubresourceRange *pRanges) 181bf215546Sopenharmony_ci{ 182bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer); 183bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_image, image, _image); 184bf215546Sopenharmony_ci 185bf215546Sopenharmony_ci const VkClearValue clear_value = { 186bf215546Sopenharmony_ci .depthStencil = *pDepthStencil, 187bf215546Sopenharmony_ci }; 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci cmd_buffer->state.is_transfer = true; 190bf215546Sopenharmony_ci 191bf215546Sopenharmony_ci for (uint32_t i = 0; i < rangeCount; i++) { 192bf215546Sopenharmony_ci if (clear_image_tlb(cmd_buffer, image, &clear_value, &pRanges[i])) 193bf215546Sopenharmony_ci continue; 194bf215546Sopenharmony_ci unreachable("Unsupported depth/stencil clear."); 195bf215546Sopenharmony_ci } 196bf215546Sopenharmony_ci 197bf215546Sopenharmony_ci cmd_buffer->state.is_transfer = false; 198bf215546Sopenharmony_ci} 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_cistatic void 201bf215546Sopenharmony_cidestroy_color_clear_pipeline(VkDevice _device, 202bf215546Sopenharmony_ci uint64_t pipeline, 203bf215546Sopenharmony_ci VkAllocationCallbacks *alloc) 204bf215546Sopenharmony_ci{ 205bf215546Sopenharmony_ci struct v3dv_meta_color_clear_pipeline *p = 206bf215546Sopenharmony_ci (struct v3dv_meta_color_clear_pipeline *) (uintptr_t) pipeline; 207bf215546Sopenharmony_ci v3dv_DestroyPipeline(_device, p->pipeline, alloc); 208bf215546Sopenharmony_ci if (p->cached) 209bf215546Sopenharmony_ci v3dv_DestroyRenderPass(_device, p->pass, alloc); 210bf215546Sopenharmony_ci vk_free(alloc, p); 211bf215546Sopenharmony_ci} 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_cistatic void 214bf215546Sopenharmony_cidestroy_depth_clear_pipeline(VkDevice _device, 215bf215546Sopenharmony_ci struct v3dv_meta_depth_clear_pipeline *p, 216bf215546Sopenharmony_ci VkAllocationCallbacks *alloc) 217bf215546Sopenharmony_ci{ 218bf215546Sopenharmony_ci v3dv_DestroyPipeline(_device, p->pipeline, alloc); 219bf215546Sopenharmony_ci vk_free(alloc, p); 220bf215546Sopenharmony_ci} 221bf215546Sopenharmony_ci 222bf215546Sopenharmony_cistatic VkResult 223bf215546Sopenharmony_cicreate_color_clear_pipeline_layout(struct v3dv_device *device, 224bf215546Sopenharmony_ci VkPipelineLayout *pipeline_layout) 225bf215546Sopenharmony_ci{ 226bf215546Sopenharmony_ci /* FIXME: this is abusing a bit the API, since not all of our clear 227bf215546Sopenharmony_ci * pipelines have a geometry shader. We could create 2 different pipeline 228bf215546Sopenharmony_ci * layouts, but this works for us for now. 229bf215546Sopenharmony_ci */ 230bf215546Sopenharmony_ci VkPushConstantRange ranges[2] = { 231bf215546Sopenharmony_ci { VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16 }, 232bf215546Sopenharmony_ci { VK_SHADER_STAGE_GEOMETRY_BIT, 16, 4 }, 233bf215546Sopenharmony_ci }; 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_ci VkPipelineLayoutCreateInfo info = { 236bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 237bf215546Sopenharmony_ci .setLayoutCount = 0, 238bf215546Sopenharmony_ci .pushConstantRangeCount = 2, 239bf215546Sopenharmony_ci .pPushConstantRanges = ranges, 240bf215546Sopenharmony_ci }; 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci return v3dv_CreatePipelineLayout(v3dv_device_to_handle(device), 243bf215546Sopenharmony_ci &info, &device->vk.alloc, pipeline_layout); 244bf215546Sopenharmony_ci} 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_cistatic VkResult 247bf215546Sopenharmony_cicreate_depth_clear_pipeline_layout(struct v3dv_device *device, 248bf215546Sopenharmony_ci VkPipelineLayout *pipeline_layout) 249bf215546Sopenharmony_ci{ 250bf215546Sopenharmony_ci /* FIXME: this is abusing a bit the API, since not all of our clear 251bf215546Sopenharmony_ci * pipelines have a geometry shader. We could create 2 different pipeline 252bf215546Sopenharmony_ci * layouts, but this works for us for now. 253bf215546Sopenharmony_ci */ 254bf215546Sopenharmony_ci VkPushConstantRange ranges[2] = { 255bf215546Sopenharmony_ci { VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4 }, 256bf215546Sopenharmony_ci { VK_SHADER_STAGE_GEOMETRY_BIT, 4, 4 }, 257bf215546Sopenharmony_ci }; 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci VkPipelineLayoutCreateInfo info = { 260bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, 261bf215546Sopenharmony_ci .setLayoutCount = 0, 262bf215546Sopenharmony_ci .pushConstantRangeCount = 2, 263bf215546Sopenharmony_ci .pPushConstantRanges = ranges 264bf215546Sopenharmony_ci }; 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci return v3dv_CreatePipelineLayout(v3dv_device_to_handle(device), 267bf215546Sopenharmony_ci &info, &device->vk.alloc, pipeline_layout); 268bf215546Sopenharmony_ci} 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_civoid 271bf215546Sopenharmony_civ3dv_meta_clear_init(struct v3dv_device *device) 272bf215546Sopenharmony_ci{ 273bf215546Sopenharmony_ci device->meta.color_clear.cache = 274bf215546Sopenharmony_ci _mesa_hash_table_create(NULL, u64_hash, u64_compare); 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci create_color_clear_pipeline_layout(device, 277bf215546Sopenharmony_ci &device->meta.color_clear.p_layout); 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci device->meta.depth_clear.cache = 280bf215546Sopenharmony_ci _mesa_hash_table_create(NULL, u64_hash, u64_compare); 281bf215546Sopenharmony_ci 282bf215546Sopenharmony_ci create_depth_clear_pipeline_layout(device, 283bf215546Sopenharmony_ci &device->meta.depth_clear.p_layout); 284bf215546Sopenharmony_ci} 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_civoid 287bf215546Sopenharmony_civ3dv_meta_clear_finish(struct v3dv_device *device) 288bf215546Sopenharmony_ci{ 289bf215546Sopenharmony_ci VkDevice _device = v3dv_device_to_handle(device); 290bf215546Sopenharmony_ci 291bf215546Sopenharmony_ci hash_table_foreach(device->meta.color_clear.cache, entry) { 292bf215546Sopenharmony_ci struct v3dv_meta_color_clear_pipeline *item = entry->data; 293bf215546Sopenharmony_ci destroy_color_clear_pipeline(_device, (uintptr_t)item, &device->vk.alloc); 294bf215546Sopenharmony_ci } 295bf215546Sopenharmony_ci _mesa_hash_table_destroy(device->meta.color_clear.cache, NULL); 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci if (device->meta.color_clear.p_layout) { 298bf215546Sopenharmony_ci v3dv_DestroyPipelineLayout(_device, device->meta.color_clear.p_layout, 299bf215546Sopenharmony_ci &device->vk.alloc); 300bf215546Sopenharmony_ci } 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci hash_table_foreach(device->meta.depth_clear.cache, entry) { 303bf215546Sopenharmony_ci struct v3dv_meta_depth_clear_pipeline *item = entry->data; 304bf215546Sopenharmony_ci destroy_depth_clear_pipeline(_device, item, &device->vk.alloc); 305bf215546Sopenharmony_ci } 306bf215546Sopenharmony_ci _mesa_hash_table_destroy(device->meta.depth_clear.cache, NULL); 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci if (device->meta.depth_clear.p_layout) { 309bf215546Sopenharmony_ci v3dv_DestroyPipelineLayout(_device, device->meta.depth_clear.p_layout, 310bf215546Sopenharmony_ci &device->vk.alloc); 311bf215546Sopenharmony_ci } 312bf215546Sopenharmony_ci} 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_cistatic nir_shader * 315bf215546Sopenharmony_ciget_clear_rect_vs() 316bf215546Sopenharmony_ci{ 317bf215546Sopenharmony_ci const nir_shader_compiler_options *options = v3dv_pipeline_get_nir_options(); 318bf215546Sopenharmony_ci nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_VERTEX, options, 319bf215546Sopenharmony_ci "meta clear vs"); 320bf215546Sopenharmony_ci 321bf215546Sopenharmony_ci const struct glsl_type *vec4 = glsl_vec4_type(); 322bf215546Sopenharmony_ci nir_variable *vs_out_pos = 323bf215546Sopenharmony_ci nir_variable_create(b.shader, nir_var_shader_out, vec4, "gl_Position"); 324bf215546Sopenharmony_ci vs_out_pos->data.location = VARYING_SLOT_POS; 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci nir_ssa_def *pos = nir_gen_rect_vertices(&b, NULL, NULL); 327bf215546Sopenharmony_ci nir_store_var(&b, vs_out_pos, pos, 0xf); 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci return b.shader; 330bf215546Sopenharmony_ci} 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_cistatic nir_shader * 333bf215546Sopenharmony_ciget_clear_rect_gs(uint32_t push_constant_layer_base) 334bf215546Sopenharmony_ci{ 335bf215546Sopenharmony_ci /* FIXME: this creates a geometry shader that takes the index of a single 336bf215546Sopenharmony_ci * layer to clear from push constants, so we need to emit a draw call for 337bf215546Sopenharmony_ci * each layer that we want to clear. We could actually do better and have it 338bf215546Sopenharmony_ci * take a range of layers and then emit one triangle per layer to clear, 339bf215546Sopenharmony_ci * however, if we were to do this we would need to be careful not to exceed 340bf215546Sopenharmony_ci * the maximum number of output vertices allowed in a geometry shader. 341bf215546Sopenharmony_ci */ 342bf215546Sopenharmony_ci const nir_shader_compiler_options *options = v3dv_pipeline_get_nir_options(); 343bf215546Sopenharmony_ci nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_GEOMETRY, options, 344bf215546Sopenharmony_ci "meta clear gs"); 345bf215546Sopenharmony_ci nir_shader *nir = b.shader; 346bf215546Sopenharmony_ci nir->info.inputs_read = 1ull << VARYING_SLOT_POS; 347bf215546Sopenharmony_ci nir->info.outputs_written = (1ull << VARYING_SLOT_POS) | 348bf215546Sopenharmony_ci (1ull << VARYING_SLOT_LAYER); 349bf215546Sopenharmony_ci nir->info.gs.input_primitive = SHADER_PRIM_TRIANGLES; 350bf215546Sopenharmony_ci nir->info.gs.output_primitive = SHADER_PRIM_TRIANGLE_STRIP; 351bf215546Sopenharmony_ci nir->info.gs.vertices_in = 3; 352bf215546Sopenharmony_ci nir->info.gs.vertices_out = 3; 353bf215546Sopenharmony_ci nir->info.gs.invocations = 1; 354bf215546Sopenharmony_ci nir->info.gs.active_stream_mask = 0x1; 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci /* in vec4 gl_Position[3] */ 357bf215546Sopenharmony_ci nir_variable *gs_in_pos = 358bf215546Sopenharmony_ci nir_variable_create(b.shader, nir_var_shader_in, 359bf215546Sopenharmony_ci glsl_array_type(glsl_vec4_type(), 3, 0), 360bf215546Sopenharmony_ci "in_gl_Position"); 361bf215546Sopenharmony_ci gs_in_pos->data.location = VARYING_SLOT_POS; 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci /* out vec4 gl_Position */ 364bf215546Sopenharmony_ci nir_variable *gs_out_pos = 365bf215546Sopenharmony_ci nir_variable_create(b.shader, nir_var_shader_out, glsl_vec4_type(), 366bf215546Sopenharmony_ci "out_gl_Position"); 367bf215546Sopenharmony_ci gs_out_pos->data.location = VARYING_SLOT_POS; 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci /* out float gl_Layer */ 370bf215546Sopenharmony_ci nir_variable *gs_out_layer = 371bf215546Sopenharmony_ci nir_variable_create(b.shader, nir_var_shader_out, glsl_float_type(), 372bf215546Sopenharmony_ci "out_gl_Layer"); 373bf215546Sopenharmony_ci gs_out_layer->data.location = VARYING_SLOT_LAYER; 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci /* Emit output triangle */ 376bf215546Sopenharmony_ci for (uint32_t i = 0; i < 3; i++) { 377bf215546Sopenharmony_ci /* gl_Position from shader input */ 378bf215546Sopenharmony_ci nir_deref_instr *in_pos_i = 379bf215546Sopenharmony_ci nir_build_deref_array_imm(&b, nir_build_deref_var(&b, gs_in_pos), i); 380bf215546Sopenharmony_ci nir_copy_deref(&b, nir_build_deref_var(&b, gs_out_pos), in_pos_i); 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci /* gl_Layer from push constants */ 383bf215546Sopenharmony_ci nir_ssa_def *layer = 384bf215546Sopenharmony_ci nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), 385bf215546Sopenharmony_ci .base = push_constant_layer_base, .range = 4); 386bf215546Sopenharmony_ci nir_store_var(&b, gs_out_layer, layer, 0x1); 387bf215546Sopenharmony_ci 388bf215546Sopenharmony_ci nir_emit_vertex(&b, 0); 389bf215546Sopenharmony_ci } 390bf215546Sopenharmony_ci 391bf215546Sopenharmony_ci nir_end_primitive(&b, 0); 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci return nir; 394bf215546Sopenharmony_ci} 395bf215546Sopenharmony_ci 396bf215546Sopenharmony_cistatic nir_shader * 397bf215546Sopenharmony_ciget_color_clear_rect_fs(uint32_t rt_idx, VkFormat format) 398bf215546Sopenharmony_ci{ 399bf215546Sopenharmony_ci const nir_shader_compiler_options *options = v3dv_pipeline_get_nir_options(); 400bf215546Sopenharmony_ci nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, options, 401bf215546Sopenharmony_ci "meta clear fs"); 402bf215546Sopenharmony_ci 403bf215546Sopenharmony_ci enum pipe_format pformat = vk_format_to_pipe_format(format); 404bf215546Sopenharmony_ci const struct glsl_type *fs_out_type = 405bf215546Sopenharmony_ci util_format_is_float(pformat) ? glsl_vec4_type() : glsl_uvec4_type(); 406bf215546Sopenharmony_ci 407bf215546Sopenharmony_ci nir_variable *fs_out_color = 408bf215546Sopenharmony_ci nir_variable_create(b.shader, nir_var_shader_out, fs_out_type, "out_color"); 409bf215546Sopenharmony_ci fs_out_color->data.location = FRAG_RESULT_DATA0 + rt_idx; 410bf215546Sopenharmony_ci 411bf215546Sopenharmony_ci nir_ssa_def *color_load = nir_load_push_constant(&b, 4, 32, nir_imm_int(&b, 0), .base = 0, .range = 16); 412bf215546Sopenharmony_ci nir_store_var(&b, fs_out_color, color_load, 0xf); 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci return b.shader; 415bf215546Sopenharmony_ci} 416bf215546Sopenharmony_ci 417bf215546Sopenharmony_cistatic nir_shader * 418bf215546Sopenharmony_ciget_depth_clear_rect_fs() 419bf215546Sopenharmony_ci{ 420bf215546Sopenharmony_ci const nir_shader_compiler_options *options = v3dv_pipeline_get_nir_options(); 421bf215546Sopenharmony_ci nir_builder b = nir_builder_init_simple_shader(MESA_SHADER_FRAGMENT, options, 422bf215546Sopenharmony_ci "meta depth clear fs"); 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci nir_variable *fs_out_depth = 425bf215546Sopenharmony_ci nir_variable_create(b.shader, nir_var_shader_out, glsl_float_type(), 426bf215546Sopenharmony_ci "out_depth"); 427bf215546Sopenharmony_ci fs_out_depth->data.location = FRAG_RESULT_DEPTH; 428bf215546Sopenharmony_ci 429bf215546Sopenharmony_ci nir_ssa_def *depth_load = 430bf215546Sopenharmony_ci nir_load_push_constant(&b, 1, 32, nir_imm_int(&b, 0), .base = 0, .range = 4); 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_ci nir_store_var(&b, fs_out_depth, depth_load, 0x1); 433bf215546Sopenharmony_ci 434bf215546Sopenharmony_ci return b.shader; 435bf215546Sopenharmony_ci} 436bf215546Sopenharmony_ci 437bf215546Sopenharmony_cistatic VkResult 438bf215546Sopenharmony_cicreate_pipeline(struct v3dv_device *device, 439bf215546Sopenharmony_ci struct v3dv_render_pass *pass, 440bf215546Sopenharmony_ci uint32_t subpass_idx, 441bf215546Sopenharmony_ci uint32_t samples, 442bf215546Sopenharmony_ci struct nir_shader *vs_nir, 443bf215546Sopenharmony_ci struct nir_shader *gs_nir, 444bf215546Sopenharmony_ci struct nir_shader *fs_nir, 445bf215546Sopenharmony_ci const VkPipelineVertexInputStateCreateInfo *vi_state, 446bf215546Sopenharmony_ci const VkPipelineDepthStencilStateCreateInfo *ds_state, 447bf215546Sopenharmony_ci const VkPipelineColorBlendStateCreateInfo *cb_state, 448bf215546Sopenharmony_ci const VkPipelineLayout layout, 449bf215546Sopenharmony_ci VkPipeline *pipeline) 450bf215546Sopenharmony_ci{ 451bf215546Sopenharmony_ci VkPipelineShaderStageCreateInfo stages[3] = { 0 }; 452bf215546Sopenharmony_ci struct vk_shader_module vs_m = vk_shader_module_from_nir(vs_nir); 453bf215546Sopenharmony_ci struct vk_shader_module gs_m; 454bf215546Sopenharmony_ci struct vk_shader_module fs_m; 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci uint32_t stage_count = 0; 457bf215546Sopenharmony_ci stages[stage_count].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 458bf215546Sopenharmony_ci stages[stage_count].stage = VK_SHADER_STAGE_VERTEX_BIT; 459bf215546Sopenharmony_ci stages[stage_count].module = vk_shader_module_to_handle(&vs_m); 460bf215546Sopenharmony_ci stages[stage_count].pName = "main"; 461bf215546Sopenharmony_ci stage_count++; 462bf215546Sopenharmony_ci 463bf215546Sopenharmony_ci if (gs_nir) { 464bf215546Sopenharmony_ci gs_m = vk_shader_module_from_nir(gs_nir); 465bf215546Sopenharmony_ci stages[stage_count].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 466bf215546Sopenharmony_ci stages[stage_count].stage = VK_SHADER_STAGE_GEOMETRY_BIT; 467bf215546Sopenharmony_ci stages[stage_count].module = vk_shader_module_to_handle(&gs_m); 468bf215546Sopenharmony_ci stages[stage_count].pName = "main"; 469bf215546Sopenharmony_ci stage_count++; 470bf215546Sopenharmony_ci } 471bf215546Sopenharmony_ci 472bf215546Sopenharmony_ci if (fs_nir) { 473bf215546Sopenharmony_ci fs_m = vk_shader_module_from_nir(fs_nir); 474bf215546Sopenharmony_ci stages[stage_count].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; 475bf215546Sopenharmony_ci stages[stage_count].stage = VK_SHADER_STAGE_FRAGMENT_BIT; 476bf215546Sopenharmony_ci stages[stage_count].module = vk_shader_module_to_handle(&fs_m); 477bf215546Sopenharmony_ci stages[stage_count].pName = "main"; 478bf215546Sopenharmony_ci stage_count++; 479bf215546Sopenharmony_ci } 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci VkGraphicsPipelineCreateInfo info = { 482bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_ci .stageCount = stage_count, 485bf215546Sopenharmony_ci .pStages = stages, 486bf215546Sopenharmony_ci 487bf215546Sopenharmony_ci .pVertexInputState = vi_state, 488bf215546Sopenharmony_ci 489bf215546Sopenharmony_ci .pInputAssemblyState = &(VkPipelineInputAssemblyStateCreateInfo) { 490bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, 491bf215546Sopenharmony_ci .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 492bf215546Sopenharmony_ci .primitiveRestartEnable = false, 493bf215546Sopenharmony_ci }, 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_ci .pViewportState = &(VkPipelineViewportStateCreateInfo) { 496bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, 497bf215546Sopenharmony_ci .viewportCount = 1, 498bf215546Sopenharmony_ci .scissorCount = 1, 499bf215546Sopenharmony_ci }, 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_ci .pRasterizationState = &(VkPipelineRasterizationStateCreateInfo) { 502bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 503bf215546Sopenharmony_ci .rasterizerDiscardEnable = false, 504bf215546Sopenharmony_ci .polygonMode = VK_POLYGON_MODE_FILL, 505bf215546Sopenharmony_ci .cullMode = VK_CULL_MODE_NONE, 506bf215546Sopenharmony_ci .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, 507bf215546Sopenharmony_ci .depthBiasEnable = false, 508bf215546Sopenharmony_ci }, 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_ci .pMultisampleState = &(VkPipelineMultisampleStateCreateInfo) { 511bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 512bf215546Sopenharmony_ci .rasterizationSamples = samples, 513bf215546Sopenharmony_ci .sampleShadingEnable = false, 514bf215546Sopenharmony_ci .pSampleMask = NULL, 515bf215546Sopenharmony_ci .alphaToCoverageEnable = false, 516bf215546Sopenharmony_ci .alphaToOneEnable = false, 517bf215546Sopenharmony_ci }, 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci .pDepthStencilState = ds_state, 520bf215546Sopenharmony_ci 521bf215546Sopenharmony_ci .pColorBlendState = cb_state, 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci /* The meta clear pipeline declares all state as dynamic. 524bf215546Sopenharmony_ci * As a consequence, vkCmdBindPipeline writes no dynamic state 525bf215546Sopenharmony_ci * to the cmd buffer. Therefore, at the end of the meta clear, 526bf215546Sopenharmony_ci * we need only restore dynamic state that was vkCmdSet. 527bf215546Sopenharmony_ci */ 528bf215546Sopenharmony_ci .pDynamicState = &(VkPipelineDynamicStateCreateInfo) { 529bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, 530bf215546Sopenharmony_ci .dynamicStateCount = 6, 531bf215546Sopenharmony_ci .pDynamicStates = (VkDynamicState[]) { 532bf215546Sopenharmony_ci VK_DYNAMIC_STATE_VIEWPORT, 533bf215546Sopenharmony_ci VK_DYNAMIC_STATE_SCISSOR, 534bf215546Sopenharmony_ci VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, 535bf215546Sopenharmony_ci VK_DYNAMIC_STATE_STENCIL_WRITE_MASK, 536bf215546Sopenharmony_ci VK_DYNAMIC_STATE_STENCIL_REFERENCE, 537bf215546Sopenharmony_ci VK_DYNAMIC_STATE_BLEND_CONSTANTS, 538bf215546Sopenharmony_ci VK_DYNAMIC_STATE_DEPTH_BIAS, 539bf215546Sopenharmony_ci VK_DYNAMIC_STATE_LINE_WIDTH, 540bf215546Sopenharmony_ci }, 541bf215546Sopenharmony_ci }, 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci .flags = 0, 544bf215546Sopenharmony_ci .layout = layout, 545bf215546Sopenharmony_ci .renderPass = v3dv_render_pass_to_handle(pass), 546bf215546Sopenharmony_ci .subpass = subpass_idx, 547bf215546Sopenharmony_ci }; 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci VkResult result = 550bf215546Sopenharmony_ci v3dv_CreateGraphicsPipelines(v3dv_device_to_handle(device), 551bf215546Sopenharmony_ci VK_NULL_HANDLE, 552bf215546Sopenharmony_ci 1, &info, 553bf215546Sopenharmony_ci &device->vk.alloc, 554bf215546Sopenharmony_ci pipeline); 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci ralloc_free(vs_nir); 557bf215546Sopenharmony_ci ralloc_free(gs_nir); 558bf215546Sopenharmony_ci ralloc_free(fs_nir); 559bf215546Sopenharmony_ci 560bf215546Sopenharmony_ci return result; 561bf215546Sopenharmony_ci} 562bf215546Sopenharmony_ci 563bf215546Sopenharmony_cistatic VkResult 564bf215546Sopenharmony_cicreate_color_clear_pipeline(struct v3dv_device *device, 565bf215546Sopenharmony_ci struct v3dv_render_pass *pass, 566bf215546Sopenharmony_ci uint32_t subpass_idx, 567bf215546Sopenharmony_ci uint32_t rt_idx, 568bf215546Sopenharmony_ci VkFormat format, 569bf215546Sopenharmony_ci uint32_t samples, 570bf215546Sopenharmony_ci uint32_t components, 571bf215546Sopenharmony_ci bool is_layered, 572bf215546Sopenharmony_ci VkPipelineLayout pipeline_layout, 573bf215546Sopenharmony_ci VkPipeline *pipeline) 574bf215546Sopenharmony_ci{ 575bf215546Sopenharmony_ci nir_shader *vs_nir = get_clear_rect_vs(); 576bf215546Sopenharmony_ci nir_shader *fs_nir = get_color_clear_rect_fs(rt_idx, format); 577bf215546Sopenharmony_ci nir_shader *gs_nir = is_layered ? get_clear_rect_gs(16) : NULL; 578bf215546Sopenharmony_ci 579bf215546Sopenharmony_ci const VkPipelineVertexInputStateCreateInfo vi_state = { 580bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 581bf215546Sopenharmony_ci .vertexBindingDescriptionCount = 0, 582bf215546Sopenharmony_ci .vertexAttributeDescriptionCount = 0, 583bf215546Sopenharmony_ci }; 584bf215546Sopenharmony_ci 585bf215546Sopenharmony_ci const VkPipelineDepthStencilStateCreateInfo ds_state = { 586bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, 587bf215546Sopenharmony_ci .depthTestEnable = false, 588bf215546Sopenharmony_ci .depthWriteEnable = false, 589bf215546Sopenharmony_ci .depthBoundsTestEnable = false, 590bf215546Sopenharmony_ci .stencilTestEnable = false, 591bf215546Sopenharmony_ci }; 592bf215546Sopenharmony_ci 593bf215546Sopenharmony_ci assert(subpass_idx < pass->subpass_count); 594bf215546Sopenharmony_ci const uint32_t color_count = pass->subpasses[subpass_idx].color_count; 595bf215546Sopenharmony_ci assert(rt_idx < color_count); 596bf215546Sopenharmony_ci 597bf215546Sopenharmony_ci VkPipelineColorBlendAttachmentState blend_att_state[V3D_MAX_DRAW_BUFFERS]; 598bf215546Sopenharmony_ci for (uint32_t i = 0; i < color_count; i++) { 599bf215546Sopenharmony_ci blend_att_state[i] = (VkPipelineColorBlendAttachmentState) { 600bf215546Sopenharmony_ci .blendEnable = false, 601bf215546Sopenharmony_ci .colorWriteMask = i == rt_idx ? components : 0, 602bf215546Sopenharmony_ci }; 603bf215546Sopenharmony_ci } 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_ci const VkPipelineColorBlendStateCreateInfo cb_state = { 606bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 607bf215546Sopenharmony_ci .logicOpEnable = false, 608bf215546Sopenharmony_ci .attachmentCount = color_count, 609bf215546Sopenharmony_ci .pAttachments = blend_att_state 610bf215546Sopenharmony_ci }; 611bf215546Sopenharmony_ci 612bf215546Sopenharmony_ci return create_pipeline(device, 613bf215546Sopenharmony_ci pass, subpass_idx, 614bf215546Sopenharmony_ci samples, 615bf215546Sopenharmony_ci vs_nir, gs_nir, fs_nir, 616bf215546Sopenharmony_ci &vi_state, 617bf215546Sopenharmony_ci &ds_state, 618bf215546Sopenharmony_ci &cb_state, 619bf215546Sopenharmony_ci pipeline_layout, 620bf215546Sopenharmony_ci pipeline); 621bf215546Sopenharmony_ci} 622bf215546Sopenharmony_ci 623bf215546Sopenharmony_cistatic VkResult 624bf215546Sopenharmony_cicreate_depth_clear_pipeline(struct v3dv_device *device, 625bf215546Sopenharmony_ci VkImageAspectFlags aspects, 626bf215546Sopenharmony_ci struct v3dv_render_pass *pass, 627bf215546Sopenharmony_ci uint32_t subpass_idx, 628bf215546Sopenharmony_ci uint32_t samples, 629bf215546Sopenharmony_ci bool is_layered, 630bf215546Sopenharmony_ci VkPipelineLayout pipeline_layout, 631bf215546Sopenharmony_ci VkPipeline *pipeline) 632bf215546Sopenharmony_ci{ 633bf215546Sopenharmony_ci const bool has_depth = aspects & VK_IMAGE_ASPECT_DEPTH_BIT; 634bf215546Sopenharmony_ci const bool has_stencil = aspects & VK_IMAGE_ASPECT_STENCIL_BIT; 635bf215546Sopenharmony_ci assert(has_depth || has_stencil); 636bf215546Sopenharmony_ci 637bf215546Sopenharmony_ci nir_shader *vs_nir = get_clear_rect_vs(); 638bf215546Sopenharmony_ci nir_shader *fs_nir = has_depth ? get_depth_clear_rect_fs() : NULL; 639bf215546Sopenharmony_ci nir_shader *gs_nir = is_layered ? get_clear_rect_gs(4) : NULL; 640bf215546Sopenharmony_ci 641bf215546Sopenharmony_ci const VkPipelineVertexInputStateCreateInfo vi_state = { 642bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, 643bf215546Sopenharmony_ci .vertexBindingDescriptionCount = 0, 644bf215546Sopenharmony_ci .vertexAttributeDescriptionCount = 0, 645bf215546Sopenharmony_ci }; 646bf215546Sopenharmony_ci 647bf215546Sopenharmony_ci const VkPipelineDepthStencilStateCreateInfo ds_state = { 648bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, 649bf215546Sopenharmony_ci .depthTestEnable = has_depth, 650bf215546Sopenharmony_ci .depthWriteEnable = has_depth, 651bf215546Sopenharmony_ci .depthCompareOp = VK_COMPARE_OP_ALWAYS, 652bf215546Sopenharmony_ci .depthBoundsTestEnable = false, 653bf215546Sopenharmony_ci .stencilTestEnable = has_stencil, 654bf215546Sopenharmony_ci .front = { 655bf215546Sopenharmony_ci .passOp = VK_STENCIL_OP_REPLACE, 656bf215546Sopenharmony_ci .compareOp = VK_COMPARE_OP_ALWAYS, 657bf215546Sopenharmony_ci /* compareMask, writeMask and reference are dynamic state */ 658bf215546Sopenharmony_ci }, 659bf215546Sopenharmony_ci .back = { 0 }, 660bf215546Sopenharmony_ci }; 661bf215546Sopenharmony_ci 662bf215546Sopenharmony_ci assert(subpass_idx < pass->subpass_count); 663bf215546Sopenharmony_ci VkPipelineColorBlendAttachmentState blend_att_state[V3D_MAX_DRAW_BUFFERS] = { 0 }; 664bf215546Sopenharmony_ci const VkPipelineColorBlendStateCreateInfo cb_state = { 665bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 666bf215546Sopenharmony_ci .logicOpEnable = false, 667bf215546Sopenharmony_ci .attachmentCount = pass->subpasses[subpass_idx].color_count, 668bf215546Sopenharmony_ci .pAttachments = blend_att_state, 669bf215546Sopenharmony_ci }; 670bf215546Sopenharmony_ci 671bf215546Sopenharmony_ci return create_pipeline(device, 672bf215546Sopenharmony_ci pass, subpass_idx, 673bf215546Sopenharmony_ci samples, 674bf215546Sopenharmony_ci vs_nir, gs_nir, fs_nir, 675bf215546Sopenharmony_ci &vi_state, 676bf215546Sopenharmony_ci &ds_state, 677bf215546Sopenharmony_ci &cb_state, 678bf215546Sopenharmony_ci pipeline_layout, 679bf215546Sopenharmony_ci pipeline); 680bf215546Sopenharmony_ci} 681bf215546Sopenharmony_ci 682bf215546Sopenharmony_cistatic VkResult 683bf215546Sopenharmony_cicreate_color_clear_render_pass(struct v3dv_device *device, 684bf215546Sopenharmony_ci uint32_t rt_idx, 685bf215546Sopenharmony_ci VkFormat format, 686bf215546Sopenharmony_ci uint32_t samples, 687bf215546Sopenharmony_ci VkRenderPass *pass) 688bf215546Sopenharmony_ci{ 689bf215546Sopenharmony_ci VkAttachmentDescription2 att = { 690bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, 691bf215546Sopenharmony_ci .format = format, 692bf215546Sopenharmony_ci .samples = samples, 693bf215546Sopenharmony_ci .loadOp = VK_ATTACHMENT_LOAD_OP_LOAD, 694bf215546Sopenharmony_ci .storeOp = VK_ATTACHMENT_STORE_OP_STORE, 695bf215546Sopenharmony_ci .initialLayout = VK_IMAGE_LAYOUT_GENERAL, 696bf215546Sopenharmony_ci .finalLayout = VK_IMAGE_LAYOUT_GENERAL, 697bf215546Sopenharmony_ci }; 698bf215546Sopenharmony_ci 699bf215546Sopenharmony_ci VkAttachmentReference2 att_ref = { 700bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, 701bf215546Sopenharmony_ci .attachment = rt_idx, 702bf215546Sopenharmony_ci .layout = VK_IMAGE_LAYOUT_GENERAL, 703bf215546Sopenharmony_ci }; 704bf215546Sopenharmony_ci 705bf215546Sopenharmony_ci VkSubpassDescription2 subpass = { 706bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, 707bf215546Sopenharmony_ci .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS, 708bf215546Sopenharmony_ci .inputAttachmentCount = 0, 709bf215546Sopenharmony_ci .colorAttachmentCount = 1, 710bf215546Sopenharmony_ci .pColorAttachments = &att_ref, 711bf215546Sopenharmony_ci .pResolveAttachments = NULL, 712bf215546Sopenharmony_ci .pDepthStencilAttachment = NULL, 713bf215546Sopenharmony_ci .preserveAttachmentCount = 0, 714bf215546Sopenharmony_ci .pPreserveAttachments = NULL, 715bf215546Sopenharmony_ci }; 716bf215546Sopenharmony_ci 717bf215546Sopenharmony_ci VkRenderPassCreateInfo2 info = { 718bf215546Sopenharmony_ci .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, 719bf215546Sopenharmony_ci .attachmentCount = 1, 720bf215546Sopenharmony_ci .pAttachments = &att, 721bf215546Sopenharmony_ci .subpassCount = 1, 722bf215546Sopenharmony_ci .pSubpasses = &subpass, 723bf215546Sopenharmony_ci .dependencyCount = 0, 724bf215546Sopenharmony_ci .pDependencies = NULL, 725bf215546Sopenharmony_ci }; 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci return v3dv_CreateRenderPass2(v3dv_device_to_handle(device), 728bf215546Sopenharmony_ci &info, &device->vk.alloc, pass); 729bf215546Sopenharmony_ci} 730bf215546Sopenharmony_ci 731bf215546Sopenharmony_cistatic inline uint64_t 732bf215546Sopenharmony_ciget_color_clear_pipeline_cache_key(uint32_t rt_idx, 733bf215546Sopenharmony_ci VkFormat format, 734bf215546Sopenharmony_ci uint32_t samples, 735bf215546Sopenharmony_ci uint32_t components, 736bf215546Sopenharmony_ci bool is_layered) 737bf215546Sopenharmony_ci{ 738bf215546Sopenharmony_ci assert(rt_idx < V3D_MAX_DRAW_BUFFERS); 739bf215546Sopenharmony_ci 740bf215546Sopenharmony_ci uint64_t key = 0; 741bf215546Sopenharmony_ci uint32_t bit_offset = 0; 742bf215546Sopenharmony_ci 743bf215546Sopenharmony_ci key |= rt_idx; 744bf215546Sopenharmony_ci bit_offset += 2; 745bf215546Sopenharmony_ci 746bf215546Sopenharmony_ci key |= ((uint64_t) format) << bit_offset; 747bf215546Sopenharmony_ci bit_offset += 32; 748bf215546Sopenharmony_ci 749bf215546Sopenharmony_ci key |= ((uint64_t) samples) << bit_offset; 750bf215546Sopenharmony_ci bit_offset += 4; 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_ci key |= ((uint64_t) components) << bit_offset; 753bf215546Sopenharmony_ci bit_offset += 4; 754bf215546Sopenharmony_ci 755bf215546Sopenharmony_ci key |= (is_layered ? 1ull : 0ull) << bit_offset; 756bf215546Sopenharmony_ci bit_offset += 1; 757bf215546Sopenharmony_ci 758bf215546Sopenharmony_ci assert(bit_offset <= 64); 759bf215546Sopenharmony_ci return key; 760bf215546Sopenharmony_ci} 761bf215546Sopenharmony_ci 762bf215546Sopenharmony_cistatic inline uint64_t 763bf215546Sopenharmony_ciget_depth_clear_pipeline_cache_key(VkImageAspectFlags aspects, 764bf215546Sopenharmony_ci VkFormat format, 765bf215546Sopenharmony_ci uint32_t samples, 766bf215546Sopenharmony_ci bool is_layered) 767bf215546Sopenharmony_ci{ 768bf215546Sopenharmony_ci uint64_t key = 0; 769bf215546Sopenharmony_ci uint32_t bit_offset = 0; 770bf215546Sopenharmony_ci 771bf215546Sopenharmony_ci key |= format; 772bf215546Sopenharmony_ci bit_offset += 32; 773bf215546Sopenharmony_ci 774bf215546Sopenharmony_ci key |= ((uint64_t) samples) << bit_offset; 775bf215546Sopenharmony_ci bit_offset += 4; 776bf215546Sopenharmony_ci 777bf215546Sopenharmony_ci const bool has_depth = (aspects & VK_IMAGE_ASPECT_DEPTH_BIT) ? 1 : 0; 778bf215546Sopenharmony_ci key |= ((uint64_t) has_depth) << bit_offset; 779bf215546Sopenharmony_ci bit_offset++; 780bf215546Sopenharmony_ci 781bf215546Sopenharmony_ci const bool has_stencil = (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) ? 1 : 0; 782bf215546Sopenharmony_ci key |= ((uint64_t) has_stencil) << bit_offset; 783bf215546Sopenharmony_ci bit_offset++;; 784bf215546Sopenharmony_ci 785bf215546Sopenharmony_ci key |= (is_layered ? 1ull : 0ull) << bit_offset; 786bf215546Sopenharmony_ci bit_offset += 1; 787bf215546Sopenharmony_ci 788bf215546Sopenharmony_ci assert(bit_offset <= 64); 789bf215546Sopenharmony_ci return key; 790bf215546Sopenharmony_ci} 791bf215546Sopenharmony_ci 792bf215546Sopenharmony_cistatic VkResult 793bf215546Sopenharmony_ciget_color_clear_pipeline(struct v3dv_device *device, 794bf215546Sopenharmony_ci struct v3dv_render_pass *pass, 795bf215546Sopenharmony_ci uint32_t subpass_idx, 796bf215546Sopenharmony_ci uint32_t rt_idx, 797bf215546Sopenharmony_ci uint32_t attachment_idx, 798bf215546Sopenharmony_ci VkFormat format, 799bf215546Sopenharmony_ci uint32_t samples, 800bf215546Sopenharmony_ci uint32_t components, 801bf215546Sopenharmony_ci bool is_layered, 802bf215546Sopenharmony_ci struct v3dv_meta_color_clear_pipeline **pipeline) 803bf215546Sopenharmony_ci{ 804bf215546Sopenharmony_ci assert(vk_format_is_color(format)); 805bf215546Sopenharmony_ci 806bf215546Sopenharmony_ci VkResult result = VK_SUCCESS; 807bf215546Sopenharmony_ci 808bf215546Sopenharmony_ci /* If pass != NULL it means that we are emitting the clear as a draw call 809bf215546Sopenharmony_ci * in the current pass bound by the application. In that case, we can't 810bf215546Sopenharmony_ci * cache the pipeline, since it will be referencing that pass and the 811bf215546Sopenharmony_ci * application could be destroying it at any point. Hopefully, the perf 812bf215546Sopenharmony_ci * impact is not too big since we still have the device pipeline cache 813bf215546Sopenharmony_ci * around and we won't end up re-compiling the clear shader. 814bf215546Sopenharmony_ci * 815bf215546Sopenharmony_ci * FIXME: alternatively, we could refcount (or maybe clone) the render pass 816bf215546Sopenharmony_ci * provided by the application and include it in the pipeline key setup 817bf215546Sopenharmony_ci * to make caching safe in this scenario, however, based on tests with 818bf215546Sopenharmony_ci * vkQuake3, the fact that we are not caching here doesn't seem to have 819bf215546Sopenharmony_ci * any significant impact in performance, so it might not be worth it. 820bf215546Sopenharmony_ci */ 821bf215546Sopenharmony_ci const bool can_cache_pipeline = (pass == NULL); 822bf215546Sopenharmony_ci 823bf215546Sopenharmony_ci uint64_t key; 824bf215546Sopenharmony_ci if (can_cache_pipeline) { 825bf215546Sopenharmony_ci key = get_color_clear_pipeline_cache_key(rt_idx, format, samples, 826bf215546Sopenharmony_ci components, is_layered); 827bf215546Sopenharmony_ci mtx_lock(&device->meta.mtx); 828bf215546Sopenharmony_ci struct hash_entry *entry = 829bf215546Sopenharmony_ci _mesa_hash_table_search(device->meta.color_clear.cache, &key); 830bf215546Sopenharmony_ci if (entry) { 831bf215546Sopenharmony_ci mtx_unlock(&device->meta.mtx); 832bf215546Sopenharmony_ci *pipeline = entry->data; 833bf215546Sopenharmony_ci return VK_SUCCESS; 834bf215546Sopenharmony_ci } 835bf215546Sopenharmony_ci } 836bf215546Sopenharmony_ci 837bf215546Sopenharmony_ci *pipeline = vk_zalloc2(&device->vk.alloc, NULL, sizeof(**pipeline), 8, 838bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 839bf215546Sopenharmony_ci 840bf215546Sopenharmony_ci if (*pipeline == NULL) { 841bf215546Sopenharmony_ci result = VK_ERROR_OUT_OF_HOST_MEMORY; 842bf215546Sopenharmony_ci goto fail; 843bf215546Sopenharmony_ci } 844bf215546Sopenharmony_ci 845bf215546Sopenharmony_ci if (!pass) { 846bf215546Sopenharmony_ci result = create_color_clear_render_pass(device, 847bf215546Sopenharmony_ci rt_idx, 848bf215546Sopenharmony_ci format, 849bf215546Sopenharmony_ci samples, 850bf215546Sopenharmony_ci &(*pipeline)->pass); 851bf215546Sopenharmony_ci if (result != VK_SUCCESS) 852bf215546Sopenharmony_ci goto fail; 853bf215546Sopenharmony_ci 854bf215546Sopenharmony_ci pass = v3dv_render_pass_from_handle((*pipeline)->pass); 855bf215546Sopenharmony_ci } else { 856bf215546Sopenharmony_ci (*pipeline)->pass = v3dv_render_pass_to_handle(pass); 857bf215546Sopenharmony_ci } 858bf215546Sopenharmony_ci 859bf215546Sopenharmony_ci result = create_color_clear_pipeline(device, 860bf215546Sopenharmony_ci pass, 861bf215546Sopenharmony_ci subpass_idx, 862bf215546Sopenharmony_ci rt_idx, 863bf215546Sopenharmony_ci format, 864bf215546Sopenharmony_ci samples, 865bf215546Sopenharmony_ci components, 866bf215546Sopenharmony_ci is_layered, 867bf215546Sopenharmony_ci device->meta.color_clear.p_layout, 868bf215546Sopenharmony_ci &(*pipeline)->pipeline); 869bf215546Sopenharmony_ci if (result != VK_SUCCESS) 870bf215546Sopenharmony_ci goto fail; 871bf215546Sopenharmony_ci 872bf215546Sopenharmony_ci if (can_cache_pipeline) { 873bf215546Sopenharmony_ci (*pipeline)->key = key; 874bf215546Sopenharmony_ci (*pipeline)->cached = true; 875bf215546Sopenharmony_ci _mesa_hash_table_insert(device->meta.color_clear.cache, 876bf215546Sopenharmony_ci &(*pipeline)->key, *pipeline); 877bf215546Sopenharmony_ci 878bf215546Sopenharmony_ci mtx_unlock(&device->meta.mtx); 879bf215546Sopenharmony_ci } 880bf215546Sopenharmony_ci 881bf215546Sopenharmony_ci return VK_SUCCESS; 882bf215546Sopenharmony_ci 883bf215546Sopenharmony_cifail: 884bf215546Sopenharmony_ci if (can_cache_pipeline) 885bf215546Sopenharmony_ci mtx_unlock(&device->meta.mtx); 886bf215546Sopenharmony_ci 887bf215546Sopenharmony_ci VkDevice _device = v3dv_device_to_handle(device); 888bf215546Sopenharmony_ci if (*pipeline) { 889bf215546Sopenharmony_ci if ((*pipeline)->cached) 890bf215546Sopenharmony_ci v3dv_DestroyRenderPass(_device, (*pipeline)->pass, &device->vk.alloc); 891bf215546Sopenharmony_ci if ((*pipeline)->pipeline) 892bf215546Sopenharmony_ci v3dv_DestroyPipeline(_device, (*pipeline)->pipeline, &device->vk.alloc); 893bf215546Sopenharmony_ci vk_free(&device->vk.alloc, *pipeline); 894bf215546Sopenharmony_ci *pipeline = NULL; 895bf215546Sopenharmony_ci } 896bf215546Sopenharmony_ci 897bf215546Sopenharmony_ci return result; 898bf215546Sopenharmony_ci} 899bf215546Sopenharmony_ci 900bf215546Sopenharmony_cistatic VkResult 901bf215546Sopenharmony_ciget_depth_clear_pipeline(struct v3dv_device *device, 902bf215546Sopenharmony_ci VkImageAspectFlags aspects, 903bf215546Sopenharmony_ci struct v3dv_render_pass *pass, 904bf215546Sopenharmony_ci uint32_t subpass_idx, 905bf215546Sopenharmony_ci uint32_t attachment_idx, 906bf215546Sopenharmony_ci bool is_layered, 907bf215546Sopenharmony_ci struct v3dv_meta_depth_clear_pipeline **pipeline) 908bf215546Sopenharmony_ci{ 909bf215546Sopenharmony_ci assert(subpass_idx < pass->subpass_count); 910bf215546Sopenharmony_ci assert(attachment_idx != VK_ATTACHMENT_UNUSED); 911bf215546Sopenharmony_ci assert(attachment_idx < pass->attachment_count); 912bf215546Sopenharmony_ci 913bf215546Sopenharmony_ci VkResult result = VK_SUCCESS; 914bf215546Sopenharmony_ci 915bf215546Sopenharmony_ci const uint32_t samples = pass->attachments[attachment_idx].desc.samples; 916bf215546Sopenharmony_ci const VkFormat format = pass->attachments[attachment_idx].desc.format; 917bf215546Sopenharmony_ci assert(vk_format_is_depth_or_stencil(format)); 918bf215546Sopenharmony_ci 919bf215546Sopenharmony_ci const uint64_t key = 920bf215546Sopenharmony_ci get_depth_clear_pipeline_cache_key(aspects, format, samples, is_layered); 921bf215546Sopenharmony_ci mtx_lock(&device->meta.mtx); 922bf215546Sopenharmony_ci struct hash_entry *entry = 923bf215546Sopenharmony_ci _mesa_hash_table_search(device->meta.depth_clear.cache, &key); 924bf215546Sopenharmony_ci if (entry) { 925bf215546Sopenharmony_ci mtx_unlock(&device->meta.mtx); 926bf215546Sopenharmony_ci *pipeline = entry->data; 927bf215546Sopenharmony_ci return VK_SUCCESS; 928bf215546Sopenharmony_ci } 929bf215546Sopenharmony_ci 930bf215546Sopenharmony_ci *pipeline = vk_zalloc2(&device->vk.alloc, NULL, sizeof(**pipeline), 8, 931bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 932bf215546Sopenharmony_ci 933bf215546Sopenharmony_ci if (*pipeline == NULL) { 934bf215546Sopenharmony_ci result = VK_ERROR_OUT_OF_HOST_MEMORY; 935bf215546Sopenharmony_ci goto fail; 936bf215546Sopenharmony_ci } 937bf215546Sopenharmony_ci 938bf215546Sopenharmony_ci result = create_depth_clear_pipeline(device, 939bf215546Sopenharmony_ci aspects, 940bf215546Sopenharmony_ci pass, 941bf215546Sopenharmony_ci subpass_idx, 942bf215546Sopenharmony_ci samples, 943bf215546Sopenharmony_ci is_layered, 944bf215546Sopenharmony_ci device->meta.depth_clear.p_layout, 945bf215546Sopenharmony_ci &(*pipeline)->pipeline); 946bf215546Sopenharmony_ci if (result != VK_SUCCESS) 947bf215546Sopenharmony_ci goto fail; 948bf215546Sopenharmony_ci 949bf215546Sopenharmony_ci (*pipeline)->key = key; 950bf215546Sopenharmony_ci _mesa_hash_table_insert(device->meta.depth_clear.cache, 951bf215546Sopenharmony_ci &(*pipeline)->key, *pipeline); 952bf215546Sopenharmony_ci 953bf215546Sopenharmony_ci mtx_unlock(&device->meta.mtx); 954bf215546Sopenharmony_ci return VK_SUCCESS; 955bf215546Sopenharmony_ci 956bf215546Sopenharmony_cifail: 957bf215546Sopenharmony_ci mtx_unlock(&device->meta.mtx); 958bf215546Sopenharmony_ci 959bf215546Sopenharmony_ci VkDevice _device = v3dv_device_to_handle(device); 960bf215546Sopenharmony_ci if (*pipeline) { 961bf215546Sopenharmony_ci if ((*pipeline)->pipeline) 962bf215546Sopenharmony_ci v3dv_DestroyPipeline(_device, (*pipeline)->pipeline, &device->vk.alloc); 963bf215546Sopenharmony_ci vk_free(&device->vk.alloc, *pipeline); 964bf215546Sopenharmony_ci *pipeline = NULL; 965bf215546Sopenharmony_ci } 966bf215546Sopenharmony_ci 967bf215546Sopenharmony_ci return result; 968bf215546Sopenharmony_ci} 969bf215546Sopenharmony_ci 970bf215546Sopenharmony_ci/* Emits a scissored quad in the clear color */ 971bf215546Sopenharmony_cistatic void 972bf215546Sopenharmony_ciemit_subpass_color_clear_rects(struct v3dv_cmd_buffer *cmd_buffer, 973bf215546Sopenharmony_ci struct v3dv_render_pass *pass, 974bf215546Sopenharmony_ci struct v3dv_subpass *subpass, 975bf215546Sopenharmony_ci uint32_t rt_idx, 976bf215546Sopenharmony_ci const VkClearColorValue *clear_color, 977bf215546Sopenharmony_ci bool is_layered, 978bf215546Sopenharmony_ci bool all_rects_same_layers, 979bf215546Sopenharmony_ci uint32_t rect_count, 980bf215546Sopenharmony_ci const VkClearRect *rects) 981bf215546Sopenharmony_ci{ 982bf215546Sopenharmony_ci /* Skip if attachment is unused in the current subpass */ 983bf215546Sopenharmony_ci assert(rt_idx < subpass->color_count); 984bf215546Sopenharmony_ci const uint32_t attachment_idx = subpass->color_attachments[rt_idx].attachment; 985bf215546Sopenharmony_ci if (attachment_idx == VK_ATTACHMENT_UNUSED) 986bf215546Sopenharmony_ci return; 987bf215546Sopenharmony_ci 988bf215546Sopenharmony_ci /* Obtain a pipeline for this clear */ 989bf215546Sopenharmony_ci assert(attachment_idx < cmd_buffer->state.pass->attachment_count); 990bf215546Sopenharmony_ci const VkFormat format = 991bf215546Sopenharmony_ci cmd_buffer->state.pass->attachments[attachment_idx].desc.format; 992bf215546Sopenharmony_ci const VkFormat samples = 993bf215546Sopenharmony_ci cmd_buffer->state.pass->attachments[attachment_idx].desc.samples; 994bf215546Sopenharmony_ci const uint32_t components = VK_COLOR_COMPONENT_R_BIT | 995bf215546Sopenharmony_ci VK_COLOR_COMPONENT_G_BIT | 996bf215546Sopenharmony_ci VK_COLOR_COMPONENT_B_BIT | 997bf215546Sopenharmony_ci VK_COLOR_COMPONENT_A_BIT; 998bf215546Sopenharmony_ci struct v3dv_meta_color_clear_pipeline *pipeline = NULL; 999bf215546Sopenharmony_ci VkResult result = get_color_clear_pipeline(cmd_buffer->device, 1000bf215546Sopenharmony_ci pass, 1001bf215546Sopenharmony_ci cmd_buffer->state.subpass_idx, 1002bf215546Sopenharmony_ci rt_idx, 1003bf215546Sopenharmony_ci attachment_idx, 1004bf215546Sopenharmony_ci format, 1005bf215546Sopenharmony_ci samples, 1006bf215546Sopenharmony_ci components, 1007bf215546Sopenharmony_ci is_layered, 1008bf215546Sopenharmony_ci &pipeline); 1009bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 1010bf215546Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) 1011bf215546Sopenharmony_ci v3dv_flag_oom(cmd_buffer, NULL); 1012bf215546Sopenharmony_ci return; 1013bf215546Sopenharmony_ci } 1014bf215546Sopenharmony_ci assert(pipeline && pipeline->pipeline); 1015bf215546Sopenharmony_ci 1016bf215546Sopenharmony_ci /* Emit clear rects */ 1017bf215546Sopenharmony_ci v3dv_cmd_buffer_meta_state_push(cmd_buffer, false); 1018bf215546Sopenharmony_ci 1019bf215546Sopenharmony_ci VkCommandBuffer cmd_buffer_handle = v3dv_cmd_buffer_to_handle(cmd_buffer); 1020bf215546Sopenharmony_ci v3dv_CmdPushConstants(cmd_buffer_handle, 1021bf215546Sopenharmony_ci cmd_buffer->device->meta.depth_clear.p_layout, 1022bf215546Sopenharmony_ci VK_SHADER_STAGE_FRAGMENT_BIT, 0, 16, 1023bf215546Sopenharmony_ci clear_color->float32); 1024bf215546Sopenharmony_ci 1025bf215546Sopenharmony_ci v3dv_CmdBindPipeline(cmd_buffer_handle, 1026bf215546Sopenharmony_ci VK_PIPELINE_BIND_POINT_GRAPHICS, 1027bf215546Sopenharmony_ci pipeline->pipeline); 1028bf215546Sopenharmony_ci 1029bf215546Sopenharmony_ci uint32_t dynamic_states = V3DV_CMD_DIRTY_VIEWPORT | V3DV_CMD_DIRTY_SCISSOR; 1030bf215546Sopenharmony_ci 1031bf215546Sopenharmony_ci for (uint32_t i = 0; i < rect_count; i++) { 1032bf215546Sopenharmony_ci const VkViewport viewport = { 1033bf215546Sopenharmony_ci .x = rects[i].rect.offset.x, 1034bf215546Sopenharmony_ci .y = rects[i].rect.offset.y, 1035bf215546Sopenharmony_ci .width = rects[i].rect.extent.width, 1036bf215546Sopenharmony_ci .height = rects[i].rect.extent.height, 1037bf215546Sopenharmony_ci .minDepth = 0.0f, 1038bf215546Sopenharmony_ci .maxDepth = 1.0f 1039bf215546Sopenharmony_ci }; 1040bf215546Sopenharmony_ci v3dv_CmdSetViewport(cmd_buffer_handle, 0, 1, &viewport); 1041bf215546Sopenharmony_ci v3dv_CmdSetScissor(cmd_buffer_handle, 0, 1, &rects[i].rect); 1042bf215546Sopenharmony_ci 1043bf215546Sopenharmony_ci if (is_layered) { 1044bf215546Sopenharmony_ci for (uint32_t layer_offset = 0; layer_offset < rects[i].layerCount; 1045bf215546Sopenharmony_ci layer_offset++) { 1046bf215546Sopenharmony_ci uint32_t layer = rects[i].baseArrayLayer + layer_offset; 1047bf215546Sopenharmony_ci v3dv_CmdPushConstants(cmd_buffer_handle, 1048bf215546Sopenharmony_ci cmd_buffer->device->meta.depth_clear.p_layout, 1049bf215546Sopenharmony_ci VK_SHADER_STAGE_GEOMETRY_BIT, 16, 4, &layer); 1050bf215546Sopenharmony_ci v3dv_CmdDraw(cmd_buffer_handle, 4, 1, 0, 0); 1051bf215546Sopenharmony_ci } 1052bf215546Sopenharmony_ci } else { 1053bf215546Sopenharmony_ci assert(rects[i].baseArrayLayer == 0 && rects[i].layerCount == 1); 1054bf215546Sopenharmony_ci v3dv_CmdDraw(cmd_buffer_handle, 4, 1, 0, 0); 1055bf215546Sopenharmony_ci } 1056bf215546Sopenharmony_ci } 1057bf215546Sopenharmony_ci 1058bf215546Sopenharmony_ci /* Subpass pipelines can't be cached because they include a reference to the 1059bf215546Sopenharmony_ci * render pass currently bound by the application, which means that we need 1060bf215546Sopenharmony_ci * to destroy them manually here. 1061bf215546Sopenharmony_ci */ 1062bf215546Sopenharmony_ci assert(!pipeline->cached); 1063bf215546Sopenharmony_ci v3dv_cmd_buffer_add_private_obj( 1064bf215546Sopenharmony_ci cmd_buffer, (uintptr_t)pipeline, 1065bf215546Sopenharmony_ci (v3dv_cmd_buffer_private_obj_destroy_cb) destroy_color_clear_pipeline); 1066bf215546Sopenharmony_ci 1067bf215546Sopenharmony_ci v3dv_cmd_buffer_meta_state_pop(cmd_buffer, dynamic_states, false); 1068bf215546Sopenharmony_ci} 1069bf215546Sopenharmony_ci 1070bf215546Sopenharmony_ci/* Emits a scissored quad, clearing the depth aspect by writing to gl_FragDepth 1071bf215546Sopenharmony_ci * and the stencil aspect by using stencil testing. 1072bf215546Sopenharmony_ci */ 1073bf215546Sopenharmony_cistatic void 1074bf215546Sopenharmony_ciemit_subpass_ds_clear_rects(struct v3dv_cmd_buffer *cmd_buffer, 1075bf215546Sopenharmony_ci struct v3dv_render_pass *pass, 1076bf215546Sopenharmony_ci struct v3dv_subpass *subpass, 1077bf215546Sopenharmony_ci VkImageAspectFlags aspects, 1078bf215546Sopenharmony_ci const VkClearDepthStencilValue *clear_ds, 1079bf215546Sopenharmony_ci bool is_layered, 1080bf215546Sopenharmony_ci bool all_rects_same_layers, 1081bf215546Sopenharmony_ci uint32_t rect_count, 1082bf215546Sopenharmony_ci const VkClearRect *rects) 1083bf215546Sopenharmony_ci{ 1084bf215546Sopenharmony_ci /* Skip if attachment is unused in the current subpass */ 1085bf215546Sopenharmony_ci const uint32_t attachment_idx = subpass->ds_attachment.attachment; 1086bf215546Sopenharmony_ci if (attachment_idx == VK_ATTACHMENT_UNUSED) 1087bf215546Sopenharmony_ci return; 1088bf215546Sopenharmony_ci 1089bf215546Sopenharmony_ci /* Obtain a pipeline for this clear */ 1090bf215546Sopenharmony_ci assert(attachment_idx < cmd_buffer->state.pass->attachment_count); 1091bf215546Sopenharmony_ci struct v3dv_meta_depth_clear_pipeline *pipeline = NULL; 1092bf215546Sopenharmony_ci VkResult result = get_depth_clear_pipeline(cmd_buffer->device, 1093bf215546Sopenharmony_ci aspects, 1094bf215546Sopenharmony_ci pass, 1095bf215546Sopenharmony_ci cmd_buffer->state.subpass_idx, 1096bf215546Sopenharmony_ci attachment_idx, 1097bf215546Sopenharmony_ci is_layered, 1098bf215546Sopenharmony_ci &pipeline); 1099bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 1100bf215546Sopenharmony_ci if (result == VK_ERROR_OUT_OF_HOST_MEMORY) 1101bf215546Sopenharmony_ci v3dv_flag_oom(cmd_buffer, NULL); 1102bf215546Sopenharmony_ci return; 1103bf215546Sopenharmony_ci } 1104bf215546Sopenharmony_ci assert(pipeline && pipeline->pipeline); 1105bf215546Sopenharmony_ci 1106bf215546Sopenharmony_ci /* Emit clear rects */ 1107bf215546Sopenharmony_ci v3dv_cmd_buffer_meta_state_push(cmd_buffer, false); 1108bf215546Sopenharmony_ci 1109bf215546Sopenharmony_ci VkCommandBuffer cmd_buffer_handle = v3dv_cmd_buffer_to_handle(cmd_buffer); 1110bf215546Sopenharmony_ci v3dv_CmdPushConstants(cmd_buffer_handle, 1111bf215546Sopenharmony_ci cmd_buffer->device->meta.depth_clear.p_layout, 1112bf215546Sopenharmony_ci VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4, 1113bf215546Sopenharmony_ci &clear_ds->depth); 1114bf215546Sopenharmony_ci 1115bf215546Sopenharmony_ci v3dv_CmdBindPipeline(cmd_buffer_handle, 1116bf215546Sopenharmony_ci VK_PIPELINE_BIND_POINT_GRAPHICS, 1117bf215546Sopenharmony_ci pipeline->pipeline); 1118bf215546Sopenharmony_ci 1119bf215546Sopenharmony_ci uint32_t dynamic_states = V3DV_CMD_DIRTY_VIEWPORT | V3DV_CMD_DIRTY_SCISSOR; 1120bf215546Sopenharmony_ci if (aspects & VK_IMAGE_ASPECT_STENCIL_BIT) { 1121bf215546Sopenharmony_ci v3dv_CmdSetStencilReference(cmd_buffer_handle, 1122bf215546Sopenharmony_ci VK_STENCIL_FACE_FRONT_AND_BACK, 1123bf215546Sopenharmony_ci clear_ds->stencil); 1124bf215546Sopenharmony_ci v3dv_CmdSetStencilWriteMask(cmd_buffer_handle, 1125bf215546Sopenharmony_ci VK_STENCIL_FACE_FRONT_AND_BACK, 0xff); 1126bf215546Sopenharmony_ci v3dv_CmdSetStencilCompareMask(cmd_buffer_handle, 1127bf215546Sopenharmony_ci VK_STENCIL_FACE_FRONT_AND_BACK, 0xff); 1128bf215546Sopenharmony_ci dynamic_states |= VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK | 1129bf215546Sopenharmony_ci VK_DYNAMIC_STATE_STENCIL_WRITE_MASK | 1130bf215546Sopenharmony_ci VK_DYNAMIC_STATE_STENCIL_REFERENCE; 1131bf215546Sopenharmony_ci } 1132bf215546Sopenharmony_ci 1133bf215546Sopenharmony_ci for (uint32_t i = 0; i < rect_count; i++) { 1134bf215546Sopenharmony_ci const VkViewport viewport = { 1135bf215546Sopenharmony_ci .x = rects[i].rect.offset.x, 1136bf215546Sopenharmony_ci .y = rects[i].rect.offset.y, 1137bf215546Sopenharmony_ci .width = rects[i].rect.extent.width, 1138bf215546Sopenharmony_ci .height = rects[i].rect.extent.height, 1139bf215546Sopenharmony_ci .minDepth = 0.0f, 1140bf215546Sopenharmony_ci .maxDepth = 1.0f 1141bf215546Sopenharmony_ci }; 1142bf215546Sopenharmony_ci v3dv_CmdSetViewport(cmd_buffer_handle, 0, 1, &viewport); 1143bf215546Sopenharmony_ci v3dv_CmdSetScissor(cmd_buffer_handle, 0, 1, &rects[i].rect); 1144bf215546Sopenharmony_ci if (is_layered) { 1145bf215546Sopenharmony_ci for (uint32_t layer_offset = 0; layer_offset < rects[i].layerCount; 1146bf215546Sopenharmony_ci layer_offset++) { 1147bf215546Sopenharmony_ci uint32_t layer = rects[i].baseArrayLayer + layer_offset; 1148bf215546Sopenharmony_ci v3dv_CmdPushConstants(cmd_buffer_handle, 1149bf215546Sopenharmony_ci cmd_buffer->device->meta.depth_clear.p_layout, 1150bf215546Sopenharmony_ci VK_SHADER_STAGE_GEOMETRY_BIT, 4, 4, &layer); 1151bf215546Sopenharmony_ci v3dv_CmdDraw(cmd_buffer_handle, 4, 1, 0, 0); 1152bf215546Sopenharmony_ci } 1153bf215546Sopenharmony_ci } else { 1154bf215546Sopenharmony_ci assert(rects[i].baseArrayLayer == 0 && rects[i].layerCount == 1); 1155bf215546Sopenharmony_ci v3dv_CmdDraw(cmd_buffer_handle, 4, 1, 0, 0); 1156bf215546Sopenharmony_ci } 1157bf215546Sopenharmony_ci } 1158bf215546Sopenharmony_ci 1159bf215546Sopenharmony_ci v3dv_cmd_buffer_meta_state_pop(cmd_buffer, dynamic_states, false); 1160bf215546Sopenharmony_ci} 1161bf215546Sopenharmony_ci 1162bf215546Sopenharmony_cistatic void 1163bf215546Sopenharmony_cigather_layering_info(uint32_t rect_count, const VkClearRect *rects, 1164bf215546Sopenharmony_ci bool *is_layered, bool *all_rects_same_layers) 1165bf215546Sopenharmony_ci{ 1166bf215546Sopenharmony_ci *all_rects_same_layers = true; 1167bf215546Sopenharmony_ci 1168bf215546Sopenharmony_ci uint32_t min_layer = rects[0].baseArrayLayer; 1169bf215546Sopenharmony_ci uint32_t max_layer = rects[0].baseArrayLayer + rects[0].layerCount - 1; 1170bf215546Sopenharmony_ci for (uint32_t i = 1; i < rect_count; i++) { 1171bf215546Sopenharmony_ci if (rects[i].baseArrayLayer != rects[i - 1].baseArrayLayer || 1172bf215546Sopenharmony_ci rects[i].layerCount != rects[i - 1].layerCount) { 1173bf215546Sopenharmony_ci *all_rects_same_layers = false; 1174bf215546Sopenharmony_ci min_layer = MIN2(min_layer, rects[i].baseArrayLayer); 1175bf215546Sopenharmony_ci max_layer = MAX2(max_layer, rects[i].baseArrayLayer + 1176bf215546Sopenharmony_ci rects[i].layerCount - 1); 1177bf215546Sopenharmony_ci } 1178bf215546Sopenharmony_ci } 1179bf215546Sopenharmony_ci 1180bf215546Sopenharmony_ci *is_layered = !(min_layer == 0 && max_layer == 0); 1181bf215546Sopenharmony_ci} 1182bf215546Sopenharmony_ci 1183bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1184bf215546Sopenharmony_civ3dv_CmdClearAttachments(VkCommandBuffer commandBuffer, 1185bf215546Sopenharmony_ci uint32_t attachmentCount, 1186bf215546Sopenharmony_ci const VkClearAttachment *pAttachments, 1187bf215546Sopenharmony_ci uint32_t rectCount, 1188bf215546Sopenharmony_ci const VkClearRect *pRects) 1189bf215546Sopenharmony_ci{ 1190bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer); 1191bf215546Sopenharmony_ci 1192bf215546Sopenharmony_ci /* We can only clear attachments in the current subpass */ 1193bf215546Sopenharmony_ci assert(attachmentCount <= 5); /* 4 color + D/S */ 1194bf215546Sopenharmony_ci 1195bf215546Sopenharmony_ci struct v3dv_render_pass *pass = cmd_buffer->state.pass; 1196bf215546Sopenharmony_ci 1197bf215546Sopenharmony_ci assert(cmd_buffer->state.subpass_idx < pass->subpass_count); 1198bf215546Sopenharmony_ci struct v3dv_subpass *subpass = 1199bf215546Sopenharmony_ci &cmd_buffer->state.pass->subpasses[cmd_buffer->state.subpass_idx]; 1200bf215546Sopenharmony_ci 1201bf215546Sopenharmony_ci /* Emit a clear rect inside the current job for this subpass. For layered 1202bf215546Sopenharmony_ci * framebuffers, we use a geometry shader to redirect clears to the 1203bf215546Sopenharmony_ci * appropriate layers. 1204bf215546Sopenharmony_ci */ 1205bf215546Sopenharmony_ci bool is_layered, all_rects_same_layers; 1206bf215546Sopenharmony_ci gather_layering_info(rectCount, pRects, &is_layered, &all_rects_same_layers); 1207bf215546Sopenharmony_ci for (uint32_t i = 0; i < attachmentCount; i++) { 1208bf215546Sopenharmony_ci if (pAttachments[i].aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) { 1209bf215546Sopenharmony_ci emit_subpass_color_clear_rects(cmd_buffer, pass, subpass, 1210bf215546Sopenharmony_ci pAttachments[i].colorAttachment, 1211bf215546Sopenharmony_ci &pAttachments[i].clearValue.color, 1212bf215546Sopenharmony_ci is_layered, all_rects_same_layers, 1213bf215546Sopenharmony_ci rectCount, pRects); 1214bf215546Sopenharmony_ci } else { 1215bf215546Sopenharmony_ci emit_subpass_ds_clear_rects(cmd_buffer, pass, subpass, 1216bf215546Sopenharmony_ci pAttachments[i].aspectMask, 1217bf215546Sopenharmony_ci &pAttachments[i].clearValue.depthStencil, 1218bf215546Sopenharmony_ci is_layered, all_rects_same_layers, 1219bf215546Sopenharmony_ci rectCount, pRects); 1220bf215546Sopenharmony_ci } 1221bf215546Sopenharmony_ci } 1222bf215546Sopenharmony_ci} 1223