1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2021 Collabora Ltd. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Derived from tu_pipeline.c which is: 5bf215546Sopenharmony_ci * Copyright © 2016 Red Hat. 6bf215546Sopenharmony_ci * Copyright © 2016 Bas Nieuwenhuizen 7bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation 8bf215546Sopenharmony_ci * 9bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 10bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 11bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 12bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 14bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 15bf215546Sopenharmony_ci * 16bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 17bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 18bf215546Sopenharmony_ci * Software. 19bf215546Sopenharmony_ci * 20bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 23bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 27bf215546Sopenharmony_ci */ 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "panvk_cs.h" 30bf215546Sopenharmony_ci#include "panvk_private.h" 31bf215546Sopenharmony_ci 32bf215546Sopenharmony_ci#include "pan_bo.h" 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "nir/nir.h" 35bf215546Sopenharmony_ci#include "nir/nir_builder.h" 36bf215546Sopenharmony_ci#include "spirv/nir_spirv.h" 37bf215546Sopenharmony_ci#include "util/debug.h" 38bf215546Sopenharmony_ci#include "util/mesa-sha1.h" 39bf215546Sopenharmony_ci#include "util/u_atomic.h" 40bf215546Sopenharmony_ci#include "vk_format.h" 41bf215546Sopenharmony_ci#include "vk_util.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_ci#include "panfrost/util/pan_lower_framebuffer.h" 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_cistruct panvk_pipeline_builder 47bf215546Sopenharmony_ci{ 48bf215546Sopenharmony_ci struct panvk_device *device; 49bf215546Sopenharmony_ci struct panvk_pipeline_cache *cache; 50bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc; 51bf215546Sopenharmony_ci struct { 52bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *gfx; 53bf215546Sopenharmony_ci const VkComputePipelineCreateInfo *compute; 54bf215546Sopenharmony_ci } create_info; 55bf215546Sopenharmony_ci const struct panvk_pipeline_layout *layout; 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci struct panvk_shader *shaders[MESA_SHADER_STAGES]; 58bf215546Sopenharmony_ci struct { 59bf215546Sopenharmony_ci uint32_t shader_offset; 60bf215546Sopenharmony_ci uint32_t rsd_offset; 61bf215546Sopenharmony_ci } stages[MESA_SHADER_STAGES]; 62bf215546Sopenharmony_ci uint32_t blend_shader_offsets[MAX_RTS]; 63bf215546Sopenharmony_ci uint32_t shader_total_size; 64bf215546Sopenharmony_ci uint32_t static_state_size; 65bf215546Sopenharmony_ci uint32_t vpd_offset; 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci bool rasterizer_discard; 68bf215546Sopenharmony_ci /* these states are affectd by rasterizer_discard */ 69bf215546Sopenharmony_ci VkSampleCountFlagBits samples; 70bf215546Sopenharmony_ci bool use_depth_stencil_attachment; 71bf215546Sopenharmony_ci uint8_t active_color_attachments; 72bf215546Sopenharmony_ci enum pipe_format color_attachment_formats[MAX_RTS]; 73bf215546Sopenharmony_ci}; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_cistatic VkResult 76bf215546Sopenharmony_cipanvk_pipeline_builder_create_pipeline(struct panvk_pipeline_builder *builder, 77bf215546Sopenharmony_ci struct panvk_pipeline **out_pipeline) 78bf215546Sopenharmony_ci{ 79bf215546Sopenharmony_ci struct panvk_device *dev = builder->device; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci struct panvk_pipeline *pipeline = 82bf215546Sopenharmony_ci vk_object_zalloc(&dev->vk, builder->alloc, 83bf215546Sopenharmony_ci sizeof(*pipeline), VK_OBJECT_TYPE_PIPELINE); 84bf215546Sopenharmony_ci if (!pipeline) 85bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci pipeline->layout = builder->layout; 88bf215546Sopenharmony_ci *out_pipeline = pipeline; 89bf215546Sopenharmony_ci return VK_SUCCESS; 90bf215546Sopenharmony_ci} 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_cistatic void 93bf215546Sopenharmony_cipanvk_pipeline_builder_finish(struct panvk_pipeline_builder *builder) 94bf215546Sopenharmony_ci{ 95bf215546Sopenharmony_ci for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) { 96bf215546Sopenharmony_ci if (!builder->shaders[i]) 97bf215546Sopenharmony_ci continue; 98bf215546Sopenharmony_ci panvk_shader_destroy(builder->device, builder->shaders[i], builder->alloc); 99bf215546Sopenharmony_ci } 100bf215546Sopenharmony_ci} 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_cistatic bool 103bf215546Sopenharmony_cipanvk_pipeline_static_state(struct panvk_pipeline *pipeline, uint32_t id) 104bf215546Sopenharmony_ci{ 105bf215546Sopenharmony_ci return !(pipeline->dynamic_state_mask & (1 << id)); 106bf215546Sopenharmony_ci} 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_cistatic VkResult 109bf215546Sopenharmony_cipanvk_pipeline_builder_compile_shaders(struct panvk_pipeline_builder *builder, 110bf215546Sopenharmony_ci struct panvk_pipeline *pipeline) 111bf215546Sopenharmony_ci{ 112bf215546Sopenharmony_ci const VkPipelineShaderStageCreateInfo *stage_infos[MESA_SHADER_STAGES] = { 113bf215546Sopenharmony_ci NULL 114bf215546Sopenharmony_ci }; 115bf215546Sopenharmony_ci const VkPipelineShaderStageCreateInfo *stages = 116bf215546Sopenharmony_ci builder->create_info.gfx ? 117bf215546Sopenharmony_ci builder->create_info.gfx->pStages : 118bf215546Sopenharmony_ci &builder->create_info.compute->stage; 119bf215546Sopenharmony_ci unsigned stage_count = 120bf215546Sopenharmony_ci builder->create_info.gfx ? builder->create_info.gfx->stageCount : 1; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci for (uint32_t i = 0; i < stage_count; i++) { 123bf215546Sopenharmony_ci gl_shader_stage stage = vk_to_mesa_shader_stage(stages[i].stage); 124bf215546Sopenharmony_ci stage_infos[stage] = &stages[i]; 125bf215546Sopenharmony_ci } 126bf215546Sopenharmony_ci 127bf215546Sopenharmony_ci /* compile shaders in reverse order */ 128bf215546Sopenharmony_ci for (gl_shader_stage stage = MESA_SHADER_STAGES - 1; 129bf215546Sopenharmony_ci stage > MESA_SHADER_NONE; stage--) { 130bf215546Sopenharmony_ci const VkPipelineShaderStageCreateInfo *stage_info = stage_infos[stage]; 131bf215546Sopenharmony_ci if (!stage_info) 132bf215546Sopenharmony_ci continue; 133bf215546Sopenharmony_ci 134bf215546Sopenharmony_ci struct panvk_shader *shader; 135bf215546Sopenharmony_ci 136bf215546Sopenharmony_ci shader = panvk_per_arch(shader_create)(builder->device, stage, stage_info, 137bf215546Sopenharmony_ci builder->layout, 138bf215546Sopenharmony_ci PANVK_SYSVAL_UBO_INDEX, 139bf215546Sopenharmony_ci &pipeline->blend.state, 140bf215546Sopenharmony_ci panvk_pipeline_static_state(pipeline, 141bf215546Sopenharmony_ci VK_DYNAMIC_STATE_BLEND_CONSTANTS), 142bf215546Sopenharmony_ci builder->alloc); 143bf215546Sopenharmony_ci if (!shader) 144bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_HOST_MEMORY; 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci builder->shaders[stage] = shader; 147bf215546Sopenharmony_ci builder->shader_total_size = ALIGN_POT(builder->shader_total_size, 128); 148bf215546Sopenharmony_ci builder->stages[stage].shader_offset = builder->shader_total_size; 149bf215546Sopenharmony_ci builder->shader_total_size += 150bf215546Sopenharmony_ci util_dynarray_num_elements(&shader->binary, uint8_t); 151bf215546Sopenharmony_ci } 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_ci return VK_SUCCESS; 154bf215546Sopenharmony_ci} 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_cistatic VkResult 157bf215546Sopenharmony_cipanvk_pipeline_builder_upload_shaders(struct panvk_pipeline_builder *builder, 158bf215546Sopenharmony_ci struct panvk_pipeline *pipeline) 159bf215546Sopenharmony_ci{ 160bf215546Sopenharmony_ci /* In some cases, the optimized shader is empty. Don't bother allocating 161bf215546Sopenharmony_ci * anything in this case. 162bf215546Sopenharmony_ci */ 163bf215546Sopenharmony_ci if (builder->shader_total_size == 0) 164bf215546Sopenharmony_ci return VK_SUCCESS; 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci struct panfrost_bo *bin_bo = 167bf215546Sopenharmony_ci panfrost_bo_create(&builder->device->physical_device->pdev, 168bf215546Sopenharmony_ci builder->shader_total_size, PAN_BO_EXECUTE, 169bf215546Sopenharmony_ci "Shader"); 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_ci pipeline->binary_bo = bin_bo; 172bf215546Sopenharmony_ci panfrost_bo_mmap(bin_bo); 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) { 175bf215546Sopenharmony_ci const struct panvk_shader *shader = builder->shaders[i]; 176bf215546Sopenharmony_ci if (!shader) 177bf215546Sopenharmony_ci continue; 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci memcpy(pipeline->binary_bo->ptr.cpu + builder->stages[i].shader_offset, 180bf215546Sopenharmony_ci util_dynarray_element(&shader->binary, uint8_t, 0), 181bf215546Sopenharmony_ci util_dynarray_num_elements(&shader->binary, uint8_t)); 182bf215546Sopenharmony_ci } 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci return VK_SUCCESS; 185bf215546Sopenharmony_ci} 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_cistatic bool 188bf215546Sopenharmony_cipanvk_pipeline_static_sysval(struct panvk_pipeline *pipeline, 189bf215546Sopenharmony_ci unsigned id) 190bf215546Sopenharmony_ci{ 191bf215546Sopenharmony_ci switch (id) { 192bf215546Sopenharmony_ci case PAN_SYSVAL_VIEWPORT_SCALE: 193bf215546Sopenharmony_ci case PAN_SYSVAL_VIEWPORT_OFFSET: 194bf215546Sopenharmony_ci return panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT); 195bf215546Sopenharmony_ci default: 196bf215546Sopenharmony_ci return false; 197bf215546Sopenharmony_ci } 198bf215546Sopenharmony_ci} 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_cistatic void 201bf215546Sopenharmony_cipanvk_pipeline_builder_alloc_static_state_bo(struct panvk_pipeline_builder *builder, 202bf215546Sopenharmony_ci struct panvk_pipeline *pipeline) 203bf215546Sopenharmony_ci{ 204bf215546Sopenharmony_ci struct panfrost_device *pdev = 205bf215546Sopenharmony_ci &builder->device->physical_device->pdev; 206bf215546Sopenharmony_ci unsigned bo_size = 0; 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_ci for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) { 209bf215546Sopenharmony_ci const struct panvk_shader *shader = builder->shaders[i]; 210bf215546Sopenharmony_ci if (!shader && i != MESA_SHADER_FRAGMENT) 211bf215546Sopenharmony_ci continue; 212bf215546Sopenharmony_ci 213bf215546Sopenharmony_ci if (pipeline->fs.dynamic_rsd && i == MESA_SHADER_FRAGMENT) 214bf215546Sopenharmony_ci continue; 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci bo_size = ALIGN_POT(bo_size, pan_alignment(RENDERER_STATE)); 217bf215546Sopenharmony_ci builder->stages[i].rsd_offset = bo_size; 218bf215546Sopenharmony_ci bo_size += pan_size(RENDERER_STATE); 219bf215546Sopenharmony_ci if (i == MESA_SHADER_FRAGMENT) 220bf215546Sopenharmony_ci bo_size += pan_size(BLEND) * MAX2(pipeline->blend.state.rt_count, 1); 221bf215546Sopenharmony_ci } 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci if (builder->create_info.gfx && 224bf215546Sopenharmony_ci panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT) && 225bf215546Sopenharmony_ci panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_SCISSOR)) { 226bf215546Sopenharmony_ci bo_size = ALIGN_POT(bo_size, pan_alignment(VIEWPORT)); 227bf215546Sopenharmony_ci builder->vpd_offset = bo_size; 228bf215546Sopenharmony_ci bo_size += pan_size(VIEWPORT); 229bf215546Sopenharmony_ci } 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci if (bo_size) { 232bf215546Sopenharmony_ci pipeline->state_bo = 233bf215546Sopenharmony_ci panfrost_bo_create(pdev, bo_size, 0, "Pipeline descriptors"); 234bf215546Sopenharmony_ci panfrost_bo_mmap(pipeline->state_bo); 235bf215546Sopenharmony_ci } 236bf215546Sopenharmony_ci} 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_cistatic void 239bf215546Sopenharmony_cipanvk_pipeline_builder_init_sysvals(struct panvk_pipeline_builder *builder, 240bf215546Sopenharmony_ci struct panvk_pipeline *pipeline, 241bf215546Sopenharmony_ci gl_shader_stage stage) 242bf215546Sopenharmony_ci{ 243bf215546Sopenharmony_ci const struct panvk_shader *shader = builder->shaders[stage]; 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci pipeline->sysvals[stage].ids = shader->info.sysvals; 246bf215546Sopenharmony_ci pipeline->sysvals[stage].ubo_idx = shader->sysval_ubo; 247bf215546Sopenharmony_ci} 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_cistatic void 250bf215546Sopenharmony_cipanvk_pipeline_builder_init_shaders(struct panvk_pipeline_builder *builder, 251bf215546Sopenharmony_ci struct panvk_pipeline *pipeline) 252bf215546Sopenharmony_ci{ 253bf215546Sopenharmony_ci for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) { 254bf215546Sopenharmony_ci const struct panvk_shader *shader = builder->shaders[i]; 255bf215546Sopenharmony_ci if (!shader) 256bf215546Sopenharmony_ci continue; 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci pipeline->tls_size = MAX2(pipeline->tls_size, shader->info.tls_size); 259bf215546Sopenharmony_ci pipeline->wls_size = MAX2(pipeline->wls_size, shader->info.wls_size); 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci if (shader->has_img_access) 262bf215546Sopenharmony_ci pipeline->img_access_mask |= BITFIELD_BIT(i); 263bf215546Sopenharmony_ci 264bf215546Sopenharmony_ci if (i == MESA_SHADER_VERTEX && shader->info.vs.writes_point_size) { 265bf215546Sopenharmony_ci VkPrimitiveTopology topology = 266bf215546Sopenharmony_ci builder->create_info.gfx->pInputAssemblyState->topology; 267bf215546Sopenharmony_ci bool points = (topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST); 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci /* Even if the vertex shader writes point size, we only consider the 270bf215546Sopenharmony_ci * pipeline to write point size when we're actually drawing points. 271bf215546Sopenharmony_ci * Otherwise the point size write would conflict with wide lines. 272bf215546Sopenharmony_ci */ 273bf215546Sopenharmony_ci pipeline->ia.writes_point_size = points; 274bf215546Sopenharmony_ci } 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci mali_ptr shader_ptr = 0; 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci /* Handle empty shaders gracefully */ 279bf215546Sopenharmony_ci if (util_dynarray_num_elements(&builder->shaders[i]->binary, uint8_t)) { 280bf215546Sopenharmony_ci shader_ptr = pipeline->binary_bo->ptr.gpu + 281bf215546Sopenharmony_ci builder->stages[i].shader_offset; 282bf215546Sopenharmony_ci } 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci if (i != MESA_SHADER_FRAGMENT) { 285bf215546Sopenharmony_ci void *rsd = pipeline->state_bo->ptr.cpu + builder->stages[i].rsd_offset; 286bf215546Sopenharmony_ci mali_ptr gpu_rsd = pipeline->state_bo->ptr.gpu + builder->stages[i].rsd_offset; 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci panvk_per_arch(emit_non_fs_rsd)(builder->device, &shader->info, shader_ptr, rsd); 289bf215546Sopenharmony_ci pipeline->rsds[i] = gpu_rsd; 290bf215546Sopenharmony_ci } 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci panvk_pipeline_builder_init_sysvals(builder, pipeline, i); 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci if (i == MESA_SHADER_COMPUTE) 295bf215546Sopenharmony_ci pipeline->cs.local_size = shader->local_size; 296bf215546Sopenharmony_ci } 297bf215546Sopenharmony_ci 298bf215546Sopenharmony_ci if (builder->create_info.gfx && !pipeline->fs.dynamic_rsd) { 299bf215546Sopenharmony_ci void *rsd = pipeline->state_bo->ptr.cpu + builder->stages[MESA_SHADER_FRAGMENT].rsd_offset; 300bf215546Sopenharmony_ci mali_ptr gpu_rsd = pipeline->state_bo->ptr.gpu + builder->stages[MESA_SHADER_FRAGMENT].rsd_offset; 301bf215546Sopenharmony_ci void *bd = rsd + pan_size(RENDERER_STATE); 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci panvk_per_arch(emit_base_fs_rsd)(builder->device, pipeline, rsd); 304bf215546Sopenharmony_ci for (unsigned rt = 0; rt < pipeline->blend.state.rt_count; rt++) { 305bf215546Sopenharmony_ci panvk_per_arch(emit_blend)(builder->device, pipeline, rt, bd); 306bf215546Sopenharmony_ci bd += pan_size(BLEND); 307bf215546Sopenharmony_ci } 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci pipeline->rsds[MESA_SHADER_FRAGMENT] = gpu_rsd; 310bf215546Sopenharmony_ci } else if (builder->create_info.gfx) { 311bf215546Sopenharmony_ci panvk_per_arch(emit_base_fs_rsd)(builder->device, pipeline, &pipeline->fs.rsd_template); 312bf215546Sopenharmony_ci for (unsigned rt = 0; rt < MAX2(pipeline->blend.state.rt_count, 1); rt++) { 313bf215546Sopenharmony_ci panvk_per_arch(emit_blend)(builder->device, pipeline, rt, 314bf215546Sopenharmony_ci &pipeline->blend.bd_template[rt]); 315bf215546Sopenharmony_ci } 316bf215546Sopenharmony_ci } 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_ci pipeline->num_ubos = PANVK_NUM_BUILTIN_UBOS + 319bf215546Sopenharmony_ci builder->layout->num_ubos + 320bf215546Sopenharmony_ci builder->layout->num_dyn_ubos; 321bf215546Sopenharmony_ci} 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_cistatic void 325bf215546Sopenharmony_cipanvk_pipeline_builder_parse_viewport(struct panvk_pipeline_builder *builder, 326bf215546Sopenharmony_ci struct panvk_pipeline *pipeline) 327bf215546Sopenharmony_ci{ 328bf215546Sopenharmony_ci /* The spec says: 329bf215546Sopenharmony_ci * 330bf215546Sopenharmony_ci * pViewportState is a pointer to an instance of the 331bf215546Sopenharmony_ci * VkPipelineViewportStateCreateInfo structure, and is ignored if the 332bf215546Sopenharmony_ci * pipeline has rasterization disabled. 333bf215546Sopenharmony_ci */ 334bf215546Sopenharmony_ci if (!builder->rasterizer_discard && 335bf215546Sopenharmony_ci panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT) && 336bf215546Sopenharmony_ci panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_SCISSOR)) { 337bf215546Sopenharmony_ci void *vpd = pipeline->state_bo->ptr.cpu + builder->vpd_offset; 338bf215546Sopenharmony_ci panvk_per_arch(emit_viewport)(builder->create_info.gfx->pViewportState->pViewports, 339bf215546Sopenharmony_ci builder->create_info.gfx->pViewportState->pScissors, 340bf215546Sopenharmony_ci vpd); 341bf215546Sopenharmony_ci pipeline->vpd = pipeline->state_bo->ptr.gpu + 342bf215546Sopenharmony_ci builder->vpd_offset; 343bf215546Sopenharmony_ci } 344bf215546Sopenharmony_ci if (panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT)) 345bf215546Sopenharmony_ci pipeline->viewport = builder->create_info.gfx->pViewportState->pViewports[0]; 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci if (panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_SCISSOR)) 348bf215546Sopenharmony_ci pipeline->scissor = builder->create_info.gfx->pViewportState->pScissors[0]; 349bf215546Sopenharmony_ci} 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_cistatic void 352bf215546Sopenharmony_cipanvk_pipeline_builder_parse_dynamic(struct panvk_pipeline_builder *builder, 353bf215546Sopenharmony_ci struct panvk_pipeline *pipeline) 354bf215546Sopenharmony_ci{ 355bf215546Sopenharmony_ci const VkPipelineDynamicStateCreateInfo *dynamic_info = 356bf215546Sopenharmony_ci builder->create_info.gfx->pDynamicState; 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci if (!dynamic_info) 359bf215546Sopenharmony_ci return; 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci for (uint32_t i = 0; i < dynamic_info->dynamicStateCount; i++) { 362bf215546Sopenharmony_ci VkDynamicState state = dynamic_info->pDynamicStates[i]; 363bf215546Sopenharmony_ci switch (state) { 364bf215546Sopenharmony_ci case VK_DYNAMIC_STATE_VIEWPORT ... VK_DYNAMIC_STATE_STENCIL_REFERENCE: 365bf215546Sopenharmony_ci pipeline->dynamic_state_mask |= 1 << state; 366bf215546Sopenharmony_ci break; 367bf215546Sopenharmony_ci default: 368bf215546Sopenharmony_ci unreachable("unsupported dynamic state"); 369bf215546Sopenharmony_ci } 370bf215546Sopenharmony_ci } 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci} 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_cistatic enum mali_draw_mode 375bf215546Sopenharmony_citranslate_prim_topology(VkPrimitiveTopology in) 376bf215546Sopenharmony_ci{ 377bf215546Sopenharmony_ci switch (in) { 378bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: 379bf215546Sopenharmony_ci return MALI_DRAW_MODE_POINTS; 380bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: 381bf215546Sopenharmony_ci return MALI_DRAW_MODE_LINES; 382bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: 383bf215546Sopenharmony_ci return MALI_DRAW_MODE_LINE_STRIP; 384bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: 385bf215546Sopenharmony_ci return MALI_DRAW_MODE_TRIANGLES; 386bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: 387bf215546Sopenharmony_ci return MALI_DRAW_MODE_TRIANGLE_STRIP; 388bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: 389bf215546Sopenharmony_ci return MALI_DRAW_MODE_TRIANGLE_FAN; 390bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: 391bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: 392bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: 393bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: 394bf215546Sopenharmony_ci case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: 395bf215546Sopenharmony_ci default: 396bf215546Sopenharmony_ci unreachable("Invalid primitive type"); 397bf215546Sopenharmony_ci } 398bf215546Sopenharmony_ci} 399bf215546Sopenharmony_ci 400bf215546Sopenharmony_cistatic void 401bf215546Sopenharmony_cipanvk_pipeline_builder_parse_input_assembly(struct panvk_pipeline_builder *builder, 402bf215546Sopenharmony_ci struct panvk_pipeline *pipeline) 403bf215546Sopenharmony_ci{ 404bf215546Sopenharmony_ci pipeline->ia.primitive_restart = 405bf215546Sopenharmony_ci builder->create_info.gfx->pInputAssemblyState->primitiveRestartEnable; 406bf215546Sopenharmony_ci pipeline->ia.topology = 407bf215546Sopenharmony_ci translate_prim_topology(builder->create_info.gfx->pInputAssemblyState->topology); 408bf215546Sopenharmony_ci} 409bf215546Sopenharmony_ci 410bf215546Sopenharmony_cistatic enum pipe_logicop 411bf215546Sopenharmony_citranslate_logicop(VkLogicOp in) 412bf215546Sopenharmony_ci{ 413bf215546Sopenharmony_ci switch (in) { 414bf215546Sopenharmony_ci case VK_LOGIC_OP_CLEAR: return PIPE_LOGICOP_CLEAR; 415bf215546Sopenharmony_ci case VK_LOGIC_OP_AND: return PIPE_LOGICOP_AND; 416bf215546Sopenharmony_ci case VK_LOGIC_OP_AND_REVERSE: return PIPE_LOGICOP_AND_REVERSE; 417bf215546Sopenharmony_ci case VK_LOGIC_OP_COPY: return PIPE_LOGICOP_COPY; 418bf215546Sopenharmony_ci case VK_LOGIC_OP_AND_INVERTED: return PIPE_LOGICOP_AND_INVERTED; 419bf215546Sopenharmony_ci case VK_LOGIC_OP_NO_OP: return PIPE_LOGICOP_NOOP; 420bf215546Sopenharmony_ci case VK_LOGIC_OP_XOR: return PIPE_LOGICOP_XOR; 421bf215546Sopenharmony_ci case VK_LOGIC_OP_OR: return PIPE_LOGICOP_OR; 422bf215546Sopenharmony_ci case VK_LOGIC_OP_NOR: return PIPE_LOGICOP_NOR; 423bf215546Sopenharmony_ci case VK_LOGIC_OP_EQUIVALENT: return PIPE_LOGICOP_EQUIV; 424bf215546Sopenharmony_ci case VK_LOGIC_OP_INVERT: return PIPE_LOGICOP_INVERT; 425bf215546Sopenharmony_ci case VK_LOGIC_OP_OR_REVERSE: return PIPE_LOGICOP_OR_REVERSE; 426bf215546Sopenharmony_ci case VK_LOGIC_OP_COPY_INVERTED: return PIPE_LOGICOP_COPY_INVERTED; 427bf215546Sopenharmony_ci case VK_LOGIC_OP_OR_INVERTED: return PIPE_LOGICOP_OR_INVERTED; 428bf215546Sopenharmony_ci case VK_LOGIC_OP_NAND: return PIPE_LOGICOP_NAND; 429bf215546Sopenharmony_ci case VK_LOGIC_OP_SET: return PIPE_LOGICOP_SET; 430bf215546Sopenharmony_ci default: unreachable("Invalid logicop"); 431bf215546Sopenharmony_ci } 432bf215546Sopenharmony_ci} 433bf215546Sopenharmony_ci 434bf215546Sopenharmony_cistatic enum blend_func 435bf215546Sopenharmony_citranslate_blend_op(VkBlendOp in) 436bf215546Sopenharmony_ci{ 437bf215546Sopenharmony_ci switch (in) { 438bf215546Sopenharmony_ci case VK_BLEND_OP_ADD: return BLEND_FUNC_ADD; 439bf215546Sopenharmony_ci case VK_BLEND_OP_SUBTRACT: return BLEND_FUNC_SUBTRACT; 440bf215546Sopenharmony_ci case VK_BLEND_OP_REVERSE_SUBTRACT: return BLEND_FUNC_REVERSE_SUBTRACT; 441bf215546Sopenharmony_ci case VK_BLEND_OP_MIN: return BLEND_FUNC_MIN; 442bf215546Sopenharmony_ci case VK_BLEND_OP_MAX: return BLEND_FUNC_MAX; 443bf215546Sopenharmony_ci default: unreachable("Invalid blend op"); 444bf215546Sopenharmony_ci } 445bf215546Sopenharmony_ci} 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_cistatic enum blend_factor 448bf215546Sopenharmony_citranslate_blend_factor(VkBlendFactor in, bool dest_has_alpha) 449bf215546Sopenharmony_ci{ 450bf215546Sopenharmony_ci switch (in) { 451bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ZERO: 452bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE: 453bf215546Sopenharmony_ci return BLEND_FACTOR_ZERO; 454bf215546Sopenharmony_ci case VK_BLEND_FACTOR_SRC_COLOR: 455bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: 456bf215546Sopenharmony_ci return BLEND_FACTOR_SRC_COLOR; 457bf215546Sopenharmony_ci case VK_BLEND_FACTOR_DST_COLOR: 458bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR: 459bf215546Sopenharmony_ci return BLEND_FACTOR_DST_COLOR; 460bf215546Sopenharmony_ci case VK_BLEND_FACTOR_SRC_ALPHA: 461bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: 462bf215546Sopenharmony_ci return BLEND_FACTOR_SRC_ALPHA; 463bf215546Sopenharmony_ci case VK_BLEND_FACTOR_DST_ALPHA: 464bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: 465bf215546Sopenharmony_ci return dest_has_alpha ? BLEND_FACTOR_DST_ALPHA : BLEND_FACTOR_ZERO; 466bf215546Sopenharmony_ci case VK_BLEND_FACTOR_CONSTANT_COLOR: 467bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: 468bf215546Sopenharmony_ci return BLEND_FACTOR_CONSTANT_COLOR; 469bf215546Sopenharmony_ci case VK_BLEND_FACTOR_CONSTANT_ALPHA: 470bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: 471bf215546Sopenharmony_ci return BLEND_FACTOR_CONSTANT_ALPHA; 472bf215546Sopenharmony_ci case VK_BLEND_FACTOR_SRC1_COLOR: 473bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR: 474bf215546Sopenharmony_ci return BLEND_FACTOR_SRC1_COLOR; 475bf215546Sopenharmony_ci case VK_BLEND_FACTOR_SRC1_ALPHA: 476bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: 477bf215546Sopenharmony_ci return BLEND_FACTOR_SRC1_ALPHA; 478bf215546Sopenharmony_ci case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE: 479bf215546Sopenharmony_ci return BLEND_FACTOR_SRC_ALPHA_SATURATE; 480bf215546Sopenharmony_ci default: unreachable("Invalid blend factor"); 481bf215546Sopenharmony_ci } 482bf215546Sopenharmony_ci} 483bf215546Sopenharmony_ci 484bf215546Sopenharmony_cistatic bool 485bf215546Sopenharmony_ciinverted_blend_factor(VkBlendFactor in, bool dest_has_alpha) 486bf215546Sopenharmony_ci{ 487bf215546Sopenharmony_ci switch (in) { 488bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE: 489bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: 490bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR: 491bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: 492bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: 493bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: 494bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR: 495bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: 496bf215546Sopenharmony_ci return true; 497bf215546Sopenharmony_ci case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: 498bf215546Sopenharmony_ci return dest_has_alpha ? true : false; 499bf215546Sopenharmony_ci case VK_BLEND_FACTOR_DST_ALPHA: 500bf215546Sopenharmony_ci return !dest_has_alpha ? true : false; 501bf215546Sopenharmony_ci default: 502bf215546Sopenharmony_ci return false; 503bf215546Sopenharmony_ci } 504bf215546Sopenharmony_ci} 505bf215546Sopenharmony_ci 506bf215546Sopenharmony_cibool 507bf215546Sopenharmony_cipanvk_per_arch(blend_needs_lowering)(const struct panfrost_device *dev, 508bf215546Sopenharmony_ci const struct pan_blend_state *state, 509bf215546Sopenharmony_ci unsigned rt) 510bf215546Sopenharmony_ci{ 511bf215546Sopenharmony_ci /* LogicOp requires a blend shader */ 512bf215546Sopenharmony_ci if (state->logicop_enable) 513bf215546Sopenharmony_ci return true; 514bf215546Sopenharmony_ci 515bf215546Sopenharmony_ci /* Not all formats can be blended by fixed-function hardware */ 516bf215546Sopenharmony_ci if (!panfrost_blendable_formats_v7[state->rts[rt].format].internal) 517bf215546Sopenharmony_ci return true; 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_ci unsigned constant_mask = pan_blend_constant_mask(state->rts[rt].equation); 520bf215546Sopenharmony_ci 521bf215546Sopenharmony_ci /* v6 doesn't support blend constants in FF blend equations. 522bf215546Sopenharmony_ci * v7 only uses the constant from RT 0 (TODO: what if it's the same 523bf215546Sopenharmony_ci * constant? or a constant is shared?) 524bf215546Sopenharmony_ci */ 525bf215546Sopenharmony_ci if (constant_mask && (PAN_ARCH == 6 || (PAN_ARCH == 7 && rt > 0))) 526bf215546Sopenharmony_ci return true; 527bf215546Sopenharmony_ci 528bf215546Sopenharmony_ci if (!pan_blend_is_homogenous_constant(constant_mask, state->constants)) 529bf215546Sopenharmony_ci return true; 530bf215546Sopenharmony_ci 531bf215546Sopenharmony_ci bool supports_2src = pan_blend_supports_2src(dev->arch); 532bf215546Sopenharmony_ci return !pan_blend_can_fixed_function(state->rts[rt].equation, supports_2src); 533bf215546Sopenharmony_ci} 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_cistatic void 536bf215546Sopenharmony_cipanvk_pipeline_builder_parse_color_blend(struct panvk_pipeline_builder *builder, 537bf215546Sopenharmony_ci struct panvk_pipeline *pipeline) 538bf215546Sopenharmony_ci{ 539bf215546Sopenharmony_ci struct panfrost_device *pdev = &builder->device->physical_device->pdev; 540bf215546Sopenharmony_ci pipeline->blend.state.logicop_enable = 541bf215546Sopenharmony_ci builder->create_info.gfx->pColorBlendState->logicOpEnable; 542bf215546Sopenharmony_ci pipeline->blend.state.logicop_func = 543bf215546Sopenharmony_ci translate_logicop(builder->create_info.gfx->pColorBlendState->logicOp); 544bf215546Sopenharmony_ci pipeline->blend.state.rt_count = util_last_bit(builder->active_color_attachments); 545bf215546Sopenharmony_ci memcpy(pipeline->blend.state.constants, 546bf215546Sopenharmony_ci builder->create_info.gfx->pColorBlendState->blendConstants, 547bf215546Sopenharmony_ci sizeof(pipeline->blend.state.constants)); 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci for (unsigned i = 0; i < pipeline->blend.state.rt_count; i++) { 550bf215546Sopenharmony_ci const VkPipelineColorBlendAttachmentState *in = 551bf215546Sopenharmony_ci &builder->create_info.gfx->pColorBlendState->pAttachments[i]; 552bf215546Sopenharmony_ci struct pan_blend_rt_state *out = &pipeline->blend.state.rts[i]; 553bf215546Sopenharmony_ci 554bf215546Sopenharmony_ci out->format = builder->color_attachment_formats[i]; 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci bool dest_has_alpha = util_format_has_alpha(out->format); 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci out->nr_samples = builder->create_info.gfx->pMultisampleState->rasterizationSamples; 559bf215546Sopenharmony_ci out->equation.blend_enable = in->blendEnable; 560bf215546Sopenharmony_ci out->equation.color_mask = in->colorWriteMask; 561bf215546Sopenharmony_ci out->equation.rgb_func = translate_blend_op(in->colorBlendOp); 562bf215546Sopenharmony_ci out->equation.rgb_src_factor = translate_blend_factor(in->srcColorBlendFactor, dest_has_alpha); 563bf215546Sopenharmony_ci out->equation.rgb_invert_src_factor = inverted_blend_factor(in->srcColorBlendFactor, dest_has_alpha); 564bf215546Sopenharmony_ci out->equation.rgb_dst_factor = translate_blend_factor(in->dstColorBlendFactor, dest_has_alpha); 565bf215546Sopenharmony_ci out->equation.rgb_invert_dst_factor = inverted_blend_factor(in->dstColorBlendFactor, dest_has_alpha); 566bf215546Sopenharmony_ci out->equation.alpha_func = translate_blend_op(in->alphaBlendOp); 567bf215546Sopenharmony_ci out->equation.alpha_src_factor = translate_blend_factor(in->srcAlphaBlendFactor, dest_has_alpha); 568bf215546Sopenharmony_ci out->equation.alpha_invert_src_factor = inverted_blend_factor(in->srcAlphaBlendFactor, dest_has_alpha); 569bf215546Sopenharmony_ci out->equation.alpha_dst_factor = translate_blend_factor(in->dstAlphaBlendFactor, dest_has_alpha); 570bf215546Sopenharmony_ci out->equation.alpha_invert_dst_factor = inverted_blend_factor(in->dstAlphaBlendFactor, dest_has_alpha); 571bf215546Sopenharmony_ci 572bf215546Sopenharmony_ci pipeline->blend.reads_dest |= pan_blend_reads_dest(out->equation); 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_ci unsigned constant_mask = 575bf215546Sopenharmony_ci panvk_per_arch(blend_needs_lowering)(pdev, &pipeline->blend.state, i) ? 576bf215546Sopenharmony_ci 0 : pan_blend_constant_mask(out->equation); 577bf215546Sopenharmony_ci pipeline->blend.constant[i].index = ffs(constant_mask) - 1; 578bf215546Sopenharmony_ci if (constant_mask) { 579bf215546Sopenharmony_ci /* On Bifrost, the blend constant is expressed with a UNORM of the 580bf215546Sopenharmony_ci * size of the target format. The value is then shifted such that 581bf215546Sopenharmony_ci * used bits are in the MSB. Here we calculate the factor at pipeline 582bf215546Sopenharmony_ci * creation time so we only have to do a 583bf215546Sopenharmony_ci * hw_constant = float_constant * factor; 584bf215546Sopenharmony_ci * at descriptor emission time. 585bf215546Sopenharmony_ci */ 586bf215546Sopenharmony_ci const struct util_format_description *format_desc = 587bf215546Sopenharmony_ci util_format_description(out->format); 588bf215546Sopenharmony_ci unsigned chan_size = 0; 589bf215546Sopenharmony_ci for (unsigned c = 0; c < format_desc->nr_channels; c++) 590bf215546Sopenharmony_ci chan_size = MAX2(format_desc->channel[c].size, chan_size); 591bf215546Sopenharmony_ci pipeline->blend.constant[i].bifrost_factor = 592bf215546Sopenharmony_ci ((1 << chan_size) - 1) << (16 - chan_size); 593bf215546Sopenharmony_ci } 594bf215546Sopenharmony_ci } 595bf215546Sopenharmony_ci} 596bf215546Sopenharmony_ci 597bf215546Sopenharmony_cistatic void 598bf215546Sopenharmony_cipanvk_pipeline_builder_parse_multisample(struct panvk_pipeline_builder *builder, 599bf215546Sopenharmony_ci struct panvk_pipeline *pipeline) 600bf215546Sopenharmony_ci{ 601bf215546Sopenharmony_ci unsigned nr_samples = 602bf215546Sopenharmony_ci MAX2(builder->create_info.gfx->pMultisampleState->rasterizationSamples, 1); 603bf215546Sopenharmony_ci 604bf215546Sopenharmony_ci pipeline->ms.rast_samples = 605bf215546Sopenharmony_ci builder->create_info.gfx->pMultisampleState->rasterizationSamples; 606bf215546Sopenharmony_ci pipeline->ms.sample_mask = 607bf215546Sopenharmony_ci builder->create_info.gfx->pMultisampleState->pSampleMask ? 608bf215546Sopenharmony_ci builder->create_info.gfx->pMultisampleState->pSampleMask[0] : UINT16_MAX; 609bf215546Sopenharmony_ci pipeline->ms.min_samples = 610bf215546Sopenharmony_ci MAX2(builder->create_info.gfx->pMultisampleState->minSampleShading * nr_samples, 1); 611bf215546Sopenharmony_ci} 612bf215546Sopenharmony_ci 613bf215546Sopenharmony_cistatic enum mali_stencil_op 614bf215546Sopenharmony_citranslate_stencil_op(VkStencilOp in) 615bf215546Sopenharmony_ci{ 616bf215546Sopenharmony_ci switch (in) { 617bf215546Sopenharmony_ci case VK_STENCIL_OP_KEEP: return MALI_STENCIL_OP_KEEP; 618bf215546Sopenharmony_ci case VK_STENCIL_OP_ZERO: return MALI_STENCIL_OP_ZERO; 619bf215546Sopenharmony_ci case VK_STENCIL_OP_REPLACE: return MALI_STENCIL_OP_REPLACE; 620bf215546Sopenharmony_ci case VK_STENCIL_OP_INCREMENT_AND_CLAMP: return MALI_STENCIL_OP_INCR_SAT; 621bf215546Sopenharmony_ci case VK_STENCIL_OP_DECREMENT_AND_CLAMP: return MALI_STENCIL_OP_DECR_SAT; 622bf215546Sopenharmony_ci case VK_STENCIL_OP_INCREMENT_AND_WRAP: return MALI_STENCIL_OP_INCR_WRAP; 623bf215546Sopenharmony_ci case VK_STENCIL_OP_DECREMENT_AND_WRAP: return MALI_STENCIL_OP_DECR_WRAP; 624bf215546Sopenharmony_ci case VK_STENCIL_OP_INVERT: return MALI_STENCIL_OP_INVERT; 625bf215546Sopenharmony_ci default: unreachable("Invalid stencil op"); 626bf215546Sopenharmony_ci } 627bf215546Sopenharmony_ci} 628bf215546Sopenharmony_ci 629bf215546Sopenharmony_cistatic void 630bf215546Sopenharmony_cipanvk_pipeline_builder_parse_zs(struct panvk_pipeline_builder *builder, 631bf215546Sopenharmony_ci struct panvk_pipeline *pipeline) 632bf215546Sopenharmony_ci{ 633bf215546Sopenharmony_ci if (!builder->use_depth_stencil_attachment) 634bf215546Sopenharmony_ci return; 635bf215546Sopenharmony_ci 636bf215546Sopenharmony_ci pipeline->zs.z_test = builder->create_info.gfx->pDepthStencilState->depthTestEnable; 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_ci /* The Vulkan spec says: 639bf215546Sopenharmony_ci * 640bf215546Sopenharmony_ci * depthWriteEnable controls whether depth writes are enabled when 641bf215546Sopenharmony_ci * depthTestEnable is VK_TRUE. Depth writes are always disabled when 642bf215546Sopenharmony_ci * depthTestEnable is VK_FALSE. 643bf215546Sopenharmony_ci * 644bf215546Sopenharmony_ci * The hardware does not make this distinction, though, so we AND in the 645bf215546Sopenharmony_ci * condition ourselves. 646bf215546Sopenharmony_ci */ 647bf215546Sopenharmony_ci pipeline->zs.z_write = pipeline->zs.z_test && 648bf215546Sopenharmony_ci builder->create_info.gfx->pDepthStencilState->depthWriteEnable; 649bf215546Sopenharmony_ci 650bf215546Sopenharmony_ci pipeline->zs.z_compare_func = 651bf215546Sopenharmony_ci panvk_per_arch(translate_compare_func)(builder->create_info.gfx->pDepthStencilState->depthCompareOp); 652bf215546Sopenharmony_ci pipeline->zs.s_test = builder->create_info.gfx->pDepthStencilState->stencilTestEnable; 653bf215546Sopenharmony_ci pipeline->zs.s_front.fail_op = 654bf215546Sopenharmony_ci translate_stencil_op(builder->create_info.gfx->pDepthStencilState->front.failOp); 655bf215546Sopenharmony_ci pipeline->zs.s_front.pass_op = 656bf215546Sopenharmony_ci translate_stencil_op(builder->create_info.gfx->pDepthStencilState->front.passOp); 657bf215546Sopenharmony_ci pipeline->zs.s_front.z_fail_op = 658bf215546Sopenharmony_ci translate_stencil_op(builder->create_info.gfx->pDepthStencilState->front.depthFailOp); 659bf215546Sopenharmony_ci pipeline->zs.s_front.compare_func = 660bf215546Sopenharmony_ci panvk_per_arch(translate_compare_func)(builder->create_info.gfx->pDepthStencilState->front.compareOp); 661bf215546Sopenharmony_ci pipeline->zs.s_front.compare_mask = 662bf215546Sopenharmony_ci builder->create_info.gfx->pDepthStencilState->front.compareMask; 663bf215546Sopenharmony_ci pipeline->zs.s_front.write_mask = 664bf215546Sopenharmony_ci builder->create_info.gfx->pDepthStencilState->front.writeMask; 665bf215546Sopenharmony_ci pipeline->zs.s_front.ref = 666bf215546Sopenharmony_ci builder->create_info.gfx->pDepthStencilState->front.reference; 667bf215546Sopenharmony_ci pipeline->zs.s_back.fail_op = 668bf215546Sopenharmony_ci translate_stencil_op(builder->create_info.gfx->pDepthStencilState->back.failOp); 669bf215546Sopenharmony_ci pipeline->zs.s_back.pass_op = 670bf215546Sopenharmony_ci translate_stencil_op(builder->create_info.gfx->pDepthStencilState->back.passOp); 671bf215546Sopenharmony_ci pipeline->zs.s_back.z_fail_op = 672bf215546Sopenharmony_ci translate_stencil_op(builder->create_info.gfx->pDepthStencilState->back.depthFailOp); 673bf215546Sopenharmony_ci pipeline->zs.s_back.compare_func = 674bf215546Sopenharmony_ci panvk_per_arch(translate_compare_func)(builder->create_info.gfx->pDepthStencilState->back.compareOp); 675bf215546Sopenharmony_ci pipeline->zs.s_back.compare_mask = 676bf215546Sopenharmony_ci builder->create_info.gfx->pDepthStencilState->back.compareMask; 677bf215546Sopenharmony_ci pipeline->zs.s_back.write_mask = 678bf215546Sopenharmony_ci builder->create_info.gfx->pDepthStencilState->back.writeMask; 679bf215546Sopenharmony_ci pipeline->zs.s_back.ref = 680bf215546Sopenharmony_ci builder->create_info.gfx->pDepthStencilState->back.reference; 681bf215546Sopenharmony_ci} 682bf215546Sopenharmony_ci 683bf215546Sopenharmony_cistatic void 684bf215546Sopenharmony_cipanvk_pipeline_builder_parse_rast(struct panvk_pipeline_builder *builder, 685bf215546Sopenharmony_ci struct panvk_pipeline *pipeline) 686bf215546Sopenharmony_ci{ 687bf215546Sopenharmony_ci pipeline->rast.clamp_depth = builder->create_info.gfx->pRasterizationState->depthClampEnable; 688bf215546Sopenharmony_ci pipeline->rast.depth_bias.enable = builder->create_info.gfx->pRasterizationState->depthBiasEnable; 689bf215546Sopenharmony_ci pipeline->rast.depth_bias.constant_factor = 690bf215546Sopenharmony_ci builder->create_info.gfx->pRasterizationState->depthBiasConstantFactor; 691bf215546Sopenharmony_ci pipeline->rast.depth_bias.clamp = builder->create_info.gfx->pRasterizationState->depthBiasClamp; 692bf215546Sopenharmony_ci pipeline->rast.depth_bias.slope_factor = builder->create_info.gfx->pRasterizationState->depthBiasSlopeFactor; 693bf215546Sopenharmony_ci pipeline->rast.front_ccw = builder->create_info.gfx->pRasterizationState->frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE; 694bf215546Sopenharmony_ci pipeline->rast.cull_front_face = builder->create_info.gfx->pRasterizationState->cullMode & VK_CULL_MODE_FRONT_BIT; 695bf215546Sopenharmony_ci pipeline->rast.cull_back_face = builder->create_info.gfx->pRasterizationState->cullMode & VK_CULL_MODE_BACK_BIT; 696bf215546Sopenharmony_ci pipeline->rast.line_width = builder->create_info.gfx->pRasterizationState->lineWidth; 697bf215546Sopenharmony_ci pipeline->rast.enable = !builder->create_info.gfx->pRasterizationState->rasterizerDiscardEnable; 698bf215546Sopenharmony_ci} 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_cistatic bool 701bf215546Sopenharmony_cipanvk_fs_required(struct panvk_pipeline *pipeline) 702bf215546Sopenharmony_ci{ 703bf215546Sopenharmony_ci const struct pan_shader_info *info = &pipeline->fs.info; 704bf215546Sopenharmony_ci 705bf215546Sopenharmony_ci /* If we generally have side effects */ 706bf215546Sopenharmony_ci if (info->fs.sidefx) 707bf215546Sopenharmony_ci return true; 708bf215546Sopenharmony_ci 709bf215546Sopenharmony_ci /* If colour is written we need to execute */ 710bf215546Sopenharmony_ci const struct pan_blend_state *blend = &pipeline->blend.state; 711bf215546Sopenharmony_ci for (unsigned i = 0; i < blend->rt_count; ++i) { 712bf215546Sopenharmony_ci if (blend->rts[i].equation.color_mask) 713bf215546Sopenharmony_ci return true; 714bf215546Sopenharmony_ci } 715bf215546Sopenharmony_ci 716bf215546Sopenharmony_ci /* If depth is written and not implied we need to execute. 717bf215546Sopenharmony_ci * TODO: Predicate on Z/S writes being enabled */ 718bf215546Sopenharmony_ci return (info->fs.writes_depth || info->fs.writes_stencil); 719bf215546Sopenharmony_ci} 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_ci#define PANVK_DYNAMIC_FS_RSD_MASK \ 722bf215546Sopenharmony_ci ((1 << VK_DYNAMIC_STATE_DEPTH_BIAS) | \ 723bf215546Sopenharmony_ci (1 << VK_DYNAMIC_STATE_BLEND_CONSTANTS) | \ 724bf215546Sopenharmony_ci (1 << VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK) | \ 725bf215546Sopenharmony_ci (1 << VK_DYNAMIC_STATE_STENCIL_WRITE_MASK) | \ 726bf215546Sopenharmony_ci (1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE)) 727bf215546Sopenharmony_ci 728bf215546Sopenharmony_cistatic void 729bf215546Sopenharmony_cipanvk_pipeline_builder_init_fs_state(struct panvk_pipeline_builder *builder, 730bf215546Sopenharmony_ci struct panvk_pipeline *pipeline) 731bf215546Sopenharmony_ci{ 732bf215546Sopenharmony_ci if (!builder->shaders[MESA_SHADER_FRAGMENT]) 733bf215546Sopenharmony_ci return; 734bf215546Sopenharmony_ci 735bf215546Sopenharmony_ci pipeline->fs.dynamic_rsd = 736bf215546Sopenharmony_ci pipeline->dynamic_state_mask & PANVK_DYNAMIC_FS_RSD_MASK; 737bf215546Sopenharmony_ci pipeline->fs.address = pipeline->binary_bo->ptr.gpu + 738bf215546Sopenharmony_ci builder->stages[MESA_SHADER_FRAGMENT].shader_offset; 739bf215546Sopenharmony_ci pipeline->fs.info = builder->shaders[MESA_SHADER_FRAGMENT]->info; 740bf215546Sopenharmony_ci pipeline->fs.rt_mask = builder->active_color_attachments; 741bf215546Sopenharmony_ci pipeline->fs.required = panvk_fs_required(pipeline); 742bf215546Sopenharmony_ci} 743bf215546Sopenharmony_ci 744bf215546Sopenharmony_cistatic void 745bf215546Sopenharmony_cipanvk_pipeline_update_varying_slot(struct panvk_varyings_info *varyings, 746bf215546Sopenharmony_ci gl_shader_stage stage, 747bf215546Sopenharmony_ci const struct pan_shader_varying *varying, 748bf215546Sopenharmony_ci bool input) 749bf215546Sopenharmony_ci{ 750bf215546Sopenharmony_ci gl_varying_slot loc = varying->location; 751bf215546Sopenharmony_ci enum panvk_varying_buf_id buf_id = panvk_varying_buf_id(loc); 752bf215546Sopenharmony_ci 753bf215546Sopenharmony_ci varyings->stage[stage].loc[varyings->stage[stage].count++] = loc; 754bf215546Sopenharmony_ci 755bf215546Sopenharmony_ci assert(loc < ARRAY_SIZE(varyings->varying)); 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_ci enum pipe_format new_fmt = varying->format; 758bf215546Sopenharmony_ci enum pipe_format old_fmt = varyings->varying[loc].format; 759bf215546Sopenharmony_ci 760bf215546Sopenharmony_ci BITSET_SET(varyings->active, loc); 761bf215546Sopenharmony_ci 762bf215546Sopenharmony_ci /* We expect inputs to either be set by a previous stage or be built 763bf215546Sopenharmony_ci * in, skip the entry if that's not the case, we'll emit a const 764bf215546Sopenharmony_ci * varying returning zero for those entries. 765bf215546Sopenharmony_ci */ 766bf215546Sopenharmony_ci if (input && old_fmt == PIPE_FORMAT_NONE) 767bf215546Sopenharmony_ci return; 768bf215546Sopenharmony_ci 769bf215546Sopenharmony_ci unsigned new_size = util_format_get_blocksize(new_fmt); 770bf215546Sopenharmony_ci unsigned old_size = util_format_get_blocksize(old_fmt); 771bf215546Sopenharmony_ci 772bf215546Sopenharmony_ci if (old_size < new_size) 773bf215546Sopenharmony_ci varyings->varying[loc].format = new_fmt; 774bf215546Sopenharmony_ci 775bf215546Sopenharmony_ci varyings->buf_mask |= 1 << buf_id; 776bf215546Sopenharmony_ci} 777bf215546Sopenharmony_ci 778bf215546Sopenharmony_cistatic void 779bf215546Sopenharmony_cipanvk_pipeline_builder_collect_varyings(struct panvk_pipeline_builder *builder, 780bf215546Sopenharmony_ci struct panvk_pipeline *pipeline) 781bf215546Sopenharmony_ci{ 782bf215546Sopenharmony_ci for (uint32_t s = 0; s < MESA_SHADER_STAGES; s++) { 783bf215546Sopenharmony_ci if (!builder->shaders[s]) 784bf215546Sopenharmony_ci continue; 785bf215546Sopenharmony_ci 786bf215546Sopenharmony_ci const struct pan_shader_info *info = &builder->shaders[s]->info; 787bf215546Sopenharmony_ci 788bf215546Sopenharmony_ci for (unsigned i = 0; i < info->varyings.input_count; i++) { 789bf215546Sopenharmony_ci panvk_pipeline_update_varying_slot(&pipeline->varyings, s, 790bf215546Sopenharmony_ci &info->varyings.input[i], 791bf215546Sopenharmony_ci true); 792bf215546Sopenharmony_ci } 793bf215546Sopenharmony_ci 794bf215546Sopenharmony_ci for (unsigned i = 0; i < info->varyings.output_count; i++) { 795bf215546Sopenharmony_ci panvk_pipeline_update_varying_slot(&pipeline->varyings, s, 796bf215546Sopenharmony_ci &info->varyings.output[i], 797bf215546Sopenharmony_ci false); 798bf215546Sopenharmony_ci } 799bf215546Sopenharmony_ci } 800bf215546Sopenharmony_ci 801bf215546Sopenharmony_ci /* TODO: Xfb */ 802bf215546Sopenharmony_ci gl_varying_slot loc; 803bf215546Sopenharmony_ci BITSET_FOREACH_SET(loc, pipeline->varyings.active, VARYING_SLOT_MAX) { 804bf215546Sopenharmony_ci if (pipeline->varyings.varying[loc].format == PIPE_FORMAT_NONE) 805bf215546Sopenharmony_ci continue; 806bf215546Sopenharmony_ci 807bf215546Sopenharmony_ci enum panvk_varying_buf_id buf_id = panvk_varying_buf_id(loc); 808bf215546Sopenharmony_ci unsigned buf_idx = panvk_varying_buf_index(&pipeline->varyings, buf_id); 809bf215546Sopenharmony_ci unsigned varying_sz = panvk_varying_size(&pipeline->varyings, loc); 810bf215546Sopenharmony_ci 811bf215546Sopenharmony_ci pipeline->varyings.varying[loc].buf = buf_idx; 812bf215546Sopenharmony_ci pipeline->varyings.varying[loc].offset = 813bf215546Sopenharmony_ci pipeline->varyings.buf[buf_idx].stride; 814bf215546Sopenharmony_ci pipeline->varyings.buf[buf_idx].stride += varying_sz; 815bf215546Sopenharmony_ci } 816bf215546Sopenharmony_ci} 817bf215546Sopenharmony_ci 818bf215546Sopenharmony_cistatic void 819bf215546Sopenharmony_cipanvk_pipeline_builder_parse_vertex_input(struct panvk_pipeline_builder *builder, 820bf215546Sopenharmony_ci struct panvk_pipeline *pipeline) 821bf215546Sopenharmony_ci{ 822bf215546Sopenharmony_ci struct panvk_attribs_info *attribs = &pipeline->attribs; 823bf215546Sopenharmony_ci const VkPipelineVertexInputStateCreateInfo *info = 824bf215546Sopenharmony_ci builder->create_info.gfx->pVertexInputState; 825bf215546Sopenharmony_ci 826bf215546Sopenharmony_ci const VkPipelineVertexInputDivisorStateCreateInfoEXT *div_info = 827bf215546Sopenharmony_ci vk_find_struct_const(info->pNext, 828bf215546Sopenharmony_ci PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT); 829bf215546Sopenharmony_ci 830bf215546Sopenharmony_ci for (unsigned i = 0; i < info->vertexBindingDescriptionCount; i++) { 831bf215546Sopenharmony_ci const VkVertexInputBindingDescription *desc = 832bf215546Sopenharmony_ci &info->pVertexBindingDescriptions[i]; 833bf215546Sopenharmony_ci attribs->buf_count = MAX2(desc->binding + 1, attribs->buf_count); 834bf215546Sopenharmony_ci attribs->buf[desc->binding].stride = desc->stride; 835bf215546Sopenharmony_ci attribs->buf[desc->binding].per_instance = 836bf215546Sopenharmony_ci desc->inputRate == VK_VERTEX_INPUT_RATE_INSTANCE; 837bf215546Sopenharmony_ci attribs->buf[desc->binding].instance_divisor = 1; 838bf215546Sopenharmony_ci attribs->buf[desc->binding].special = false; 839bf215546Sopenharmony_ci } 840bf215546Sopenharmony_ci 841bf215546Sopenharmony_ci if (div_info) { 842bf215546Sopenharmony_ci for (unsigned i = 0; i < div_info->vertexBindingDivisorCount; i++) { 843bf215546Sopenharmony_ci const VkVertexInputBindingDivisorDescriptionEXT *div = 844bf215546Sopenharmony_ci &div_info->pVertexBindingDivisors[i]; 845bf215546Sopenharmony_ci attribs->buf[div->binding].instance_divisor = div->divisor; 846bf215546Sopenharmony_ci } 847bf215546Sopenharmony_ci } 848bf215546Sopenharmony_ci 849bf215546Sopenharmony_ci const struct pan_shader_info *vs = 850bf215546Sopenharmony_ci &builder->shaders[MESA_SHADER_VERTEX]->info; 851bf215546Sopenharmony_ci 852bf215546Sopenharmony_ci for (unsigned i = 0; i < info->vertexAttributeDescriptionCount; i++) { 853bf215546Sopenharmony_ci const VkVertexInputAttributeDescription *desc = 854bf215546Sopenharmony_ci &info->pVertexAttributeDescriptions[i]; 855bf215546Sopenharmony_ci 856bf215546Sopenharmony_ci unsigned attrib = desc->location + VERT_ATTRIB_GENERIC0; 857bf215546Sopenharmony_ci unsigned slot = util_bitcount64(vs->attributes_read & 858bf215546Sopenharmony_ci BITFIELD64_MASK(attrib)); 859bf215546Sopenharmony_ci 860bf215546Sopenharmony_ci attribs->attrib[slot].buf = desc->binding; 861bf215546Sopenharmony_ci attribs->attrib[slot].format = 862bf215546Sopenharmony_ci vk_format_to_pipe_format(desc->format); 863bf215546Sopenharmony_ci attribs->attrib[slot].offset = desc->offset; 864bf215546Sopenharmony_ci } 865bf215546Sopenharmony_ci 866bf215546Sopenharmony_ci if (vs->attribute_count >= PAN_VERTEX_ID) { 867bf215546Sopenharmony_ci attribs->buf[attribs->buf_count].special = true; 868bf215546Sopenharmony_ci attribs->buf[attribs->buf_count].special_id = PAN_VERTEX_ID; 869bf215546Sopenharmony_ci attribs->attrib[PAN_VERTEX_ID].buf = attribs->buf_count++; 870bf215546Sopenharmony_ci attribs->attrib[PAN_VERTEX_ID].format = PIPE_FORMAT_R32_UINT; 871bf215546Sopenharmony_ci } 872bf215546Sopenharmony_ci 873bf215546Sopenharmony_ci if (vs->attribute_count >= PAN_INSTANCE_ID) { 874bf215546Sopenharmony_ci attribs->buf[attribs->buf_count].special = true; 875bf215546Sopenharmony_ci attribs->buf[attribs->buf_count].special_id = PAN_INSTANCE_ID; 876bf215546Sopenharmony_ci attribs->attrib[PAN_INSTANCE_ID].buf = attribs->buf_count++; 877bf215546Sopenharmony_ci attribs->attrib[PAN_INSTANCE_ID].format = PIPE_FORMAT_R32_UINT; 878bf215546Sopenharmony_ci } 879bf215546Sopenharmony_ci 880bf215546Sopenharmony_ci attribs->attrib_count = MAX2(attribs->attrib_count, vs->attribute_count); 881bf215546Sopenharmony_ci} 882bf215546Sopenharmony_ci 883bf215546Sopenharmony_cistatic VkResult 884bf215546Sopenharmony_cipanvk_pipeline_builder_build(struct panvk_pipeline_builder *builder, 885bf215546Sopenharmony_ci struct panvk_pipeline **pipeline) 886bf215546Sopenharmony_ci{ 887bf215546Sopenharmony_ci VkResult result = panvk_pipeline_builder_create_pipeline(builder, pipeline); 888bf215546Sopenharmony_ci if (result != VK_SUCCESS) 889bf215546Sopenharmony_ci return result; 890bf215546Sopenharmony_ci 891bf215546Sopenharmony_ci /* TODO: make those functions return a result and handle errors */ 892bf215546Sopenharmony_ci if (builder->create_info.gfx) { 893bf215546Sopenharmony_ci panvk_pipeline_builder_parse_dynamic(builder, *pipeline); 894bf215546Sopenharmony_ci panvk_pipeline_builder_parse_color_blend(builder, *pipeline); 895bf215546Sopenharmony_ci panvk_pipeline_builder_compile_shaders(builder, *pipeline); 896bf215546Sopenharmony_ci panvk_pipeline_builder_collect_varyings(builder, *pipeline); 897bf215546Sopenharmony_ci panvk_pipeline_builder_parse_input_assembly(builder, *pipeline); 898bf215546Sopenharmony_ci panvk_pipeline_builder_parse_multisample(builder, *pipeline); 899bf215546Sopenharmony_ci panvk_pipeline_builder_parse_zs(builder, *pipeline); 900bf215546Sopenharmony_ci panvk_pipeline_builder_parse_rast(builder, *pipeline); 901bf215546Sopenharmony_ci panvk_pipeline_builder_parse_vertex_input(builder, *pipeline); 902bf215546Sopenharmony_ci panvk_pipeline_builder_upload_shaders(builder, *pipeline); 903bf215546Sopenharmony_ci panvk_pipeline_builder_init_fs_state(builder, *pipeline); 904bf215546Sopenharmony_ci panvk_pipeline_builder_alloc_static_state_bo(builder, *pipeline); 905bf215546Sopenharmony_ci panvk_pipeline_builder_init_shaders(builder, *pipeline); 906bf215546Sopenharmony_ci panvk_pipeline_builder_parse_viewport(builder, *pipeline); 907bf215546Sopenharmony_ci } else { 908bf215546Sopenharmony_ci panvk_pipeline_builder_compile_shaders(builder, *pipeline); 909bf215546Sopenharmony_ci panvk_pipeline_builder_upload_shaders(builder, *pipeline); 910bf215546Sopenharmony_ci panvk_pipeline_builder_alloc_static_state_bo(builder, *pipeline); 911bf215546Sopenharmony_ci panvk_pipeline_builder_init_shaders(builder, *pipeline); 912bf215546Sopenharmony_ci } 913bf215546Sopenharmony_ci 914bf215546Sopenharmony_ci return VK_SUCCESS; 915bf215546Sopenharmony_ci} 916bf215546Sopenharmony_ci 917bf215546Sopenharmony_cistatic void 918bf215546Sopenharmony_cipanvk_pipeline_builder_init_graphics(struct panvk_pipeline_builder *builder, 919bf215546Sopenharmony_ci struct panvk_device *dev, 920bf215546Sopenharmony_ci struct panvk_pipeline_cache *cache, 921bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *create_info, 922bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc) 923bf215546Sopenharmony_ci{ 924bf215546Sopenharmony_ci VK_FROM_HANDLE(panvk_pipeline_layout, layout, create_info->layout); 925bf215546Sopenharmony_ci assert(layout); 926bf215546Sopenharmony_ci *builder = (struct panvk_pipeline_builder) { 927bf215546Sopenharmony_ci .device = dev, 928bf215546Sopenharmony_ci .cache = cache, 929bf215546Sopenharmony_ci .layout = layout, 930bf215546Sopenharmony_ci .create_info.gfx = create_info, 931bf215546Sopenharmony_ci .alloc = alloc, 932bf215546Sopenharmony_ci }; 933bf215546Sopenharmony_ci 934bf215546Sopenharmony_ci builder->rasterizer_discard = 935bf215546Sopenharmony_ci create_info->pRasterizationState->rasterizerDiscardEnable; 936bf215546Sopenharmony_ci 937bf215546Sopenharmony_ci if (builder->rasterizer_discard) { 938bf215546Sopenharmony_ci builder->samples = VK_SAMPLE_COUNT_1_BIT; 939bf215546Sopenharmony_ci } else { 940bf215546Sopenharmony_ci builder->samples = create_info->pMultisampleState->rasterizationSamples; 941bf215546Sopenharmony_ci 942bf215546Sopenharmony_ci const struct panvk_render_pass *pass = panvk_render_pass_from_handle(create_info->renderPass); 943bf215546Sopenharmony_ci const struct panvk_subpass *subpass = &pass->subpasses[create_info->subpass]; 944bf215546Sopenharmony_ci 945bf215546Sopenharmony_ci builder->use_depth_stencil_attachment = 946bf215546Sopenharmony_ci subpass->zs_attachment.idx != VK_ATTACHMENT_UNUSED; 947bf215546Sopenharmony_ci 948bf215546Sopenharmony_ci assert(subpass->color_count <= create_info->pColorBlendState->attachmentCount); 949bf215546Sopenharmony_ci builder->active_color_attachments = 0; 950bf215546Sopenharmony_ci for (uint32_t i = 0; i < subpass->color_count; i++) { 951bf215546Sopenharmony_ci uint32_t idx = subpass->color_attachments[i].idx; 952bf215546Sopenharmony_ci if (idx == VK_ATTACHMENT_UNUSED) 953bf215546Sopenharmony_ci continue; 954bf215546Sopenharmony_ci 955bf215546Sopenharmony_ci builder->active_color_attachments |= 1 << i; 956bf215546Sopenharmony_ci builder->color_attachment_formats[i] = pass->attachments[idx].format; 957bf215546Sopenharmony_ci } 958bf215546Sopenharmony_ci } 959bf215546Sopenharmony_ci} 960bf215546Sopenharmony_ci 961bf215546Sopenharmony_ciVkResult 962bf215546Sopenharmony_cipanvk_per_arch(CreateGraphicsPipelines)(VkDevice device, 963bf215546Sopenharmony_ci VkPipelineCache pipelineCache, 964bf215546Sopenharmony_ci uint32_t count, 965bf215546Sopenharmony_ci const VkGraphicsPipelineCreateInfo *pCreateInfos, 966bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 967bf215546Sopenharmony_ci VkPipeline *pPipelines) 968bf215546Sopenharmony_ci{ 969bf215546Sopenharmony_ci VK_FROM_HANDLE(panvk_device, dev, device); 970bf215546Sopenharmony_ci VK_FROM_HANDLE(panvk_pipeline_cache, cache, pipelineCache); 971bf215546Sopenharmony_ci 972bf215546Sopenharmony_ci for (uint32_t i = 0; i < count; i++) { 973bf215546Sopenharmony_ci struct panvk_pipeline_builder builder; 974bf215546Sopenharmony_ci panvk_pipeline_builder_init_graphics(&builder, dev, cache, 975bf215546Sopenharmony_ci &pCreateInfos[i], pAllocator); 976bf215546Sopenharmony_ci 977bf215546Sopenharmony_ci struct panvk_pipeline *pipeline; 978bf215546Sopenharmony_ci VkResult result = panvk_pipeline_builder_build(&builder, &pipeline); 979bf215546Sopenharmony_ci panvk_pipeline_builder_finish(&builder); 980bf215546Sopenharmony_ci 981bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 982bf215546Sopenharmony_ci for (uint32_t j = 0; j < i; j++) { 983bf215546Sopenharmony_ci panvk_DestroyPipeline(device, pPipelines[j], pAllocator); 984bf215546Sopenharmony_ci pPipelines[j] = VK_NULL_HANDLE; 985bf215546Sopenharmony_ci } 986bf215546Sopenharmony_ci 987bf215546Sopenharmony_ci return result; 988bf215546Sopenharmony_ci } 989bf215546Sopenharmony_ci 990bf215546Sopenharmony_ci pPipelines[i] = panvk_pipeline_to_handle(pipeline); 991bf215546Sopenharmony_ci } 992bf215546Sopenharmony_ci 993bf215546Sopenharmony_ci return VK_SUCCESS; 994bf215546Sopenharmony_ci} 995bf215546Sopenharmony_ci 996bf215546Sopenharmony_cistatic void 997bf215546Sopenharmony_cipanvk_pipeline_builder_init_compute(struct panvk_pipeline_builder *builder, 998bf215546Sopenharmony_ci struct panvk_device *dev, 999bf215546Sopenharmony_ci struct panvk_pipeline_cache *cache, 1000bf215546Sopenharmony_ci const VkComputePipelineCreateInfo *create_info, 1001bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc) 1002bf215546Sopenharmony_ci{ 1003bf215546Sopenharmony_ci VK_FROM_HANDLE(panvk_pipeline_layout, layout, create_info->layout); 1004bf215546Sopenharmony_ci assert(layout); 1005bf215546Sopenharmony_ci *builder = (struct panvk_pipeline_builder) { 1006bf215546Sopenharmony_ci .device = dev, 1007bf215546Sopenharmony_ci .cache = cache, 1008bf215546Sopenharmony_ci .layout = layout, 1009bf215546Sopenharmony_ci .create_info.compute = create_info, 1010bf215546Sopenharmony_ci .alloc = alloc, 1011bf215546Sopenharmony_ci }; 1012bf215546Sopenharmony_ci} 1013bf215546Sopenharmony_ci 1014bf215546Sopenharmony_ciVkResult 1015bf215546Sopenharmony_cipanvk_per_arch(CreateComputePipelines)(VkDevice device, 1016bf215546Sopenharmony_ci VkPipelineCache pipelineCache, 1017bf215546Sopenharmony_ci uint32_t count, 1018bf215546Sopenharmony_ci const VkComputePipelineCreateInfo *pCreateInfos, 1019bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 1020bf215546Sopenharmony_ci VkPipeline *pPipelines) 1021bf215546Sopenharmony_ci{ 1022bf215546Sopenharmony_ci VK_FROM_HANDLE(panvk_device, dev, device); 1023bf215546Sopenharmony_ci VK_FROM_HANDLE(panvk_pipeline_cache, cache, pipelineCache); 1024bf215546Sopenharmony_ci 1025bf215546Sopenharmony_ci for (uint32_t i = 0; i < count; i++) { 1026bf215546Sopenharmony_ci struct panvk_pipeline_builder builder; 1027bf215546Sopenharmony_ci panvk_pipeline_builder_init_compute(&builder, dev, cache, 1028bf215546Sopenharmony_ci &pCreateInfos[i], pAllocator); 1029bf215546Sopenharmony_ci 1030bf215546Sopenharmony_ci struct panvk_pipeline *pipeline; 1031bf215546Sopenharmony_ci VkResult result = panvk_pipeline_builder_build(&builder, &pipeline); 1032bf215546Sopenharmony_ci panvk_pipeline_builder_finish(&builder); 1033bf215546Sopenharmony_ci 1034bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 1035bf215546Sopenharmony_ci for (uint32_t j = 0; j < i; j++) { 1036bf215546Sopenharmony_ci panvk_DestroyPipeline(device, pPipelines[j], pAllocator); 1037bf215546Sopenharmony_ci pPipelines[j] = VK_NULL_HANDLE; 1038bf215546Sopenharmony_ci } 1039bf215546Sopenharmony_ci 1040bf215546Sopenharmony_ci return result; 1041bf215546Sopenharmony_ci } 1042bf215546Sopenharmony_ci 1043bf215546Sopenharmony_ci pPipelines[i] = panvk_pipeline_to_handle(pipeline); 1044bf215546Sopenharmony_ci } 1045bf215546Sopenharmony_ci 1046bf215546Sopenharmony_ci return VK_SUCCESS; 1047bf215546Sopenharmony_ci} 1048