17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2021 Collabora Ltd. 37ec681f3Smrg * 47ec681f3Smrg * Derived from tu_pipeline.c which is: 57ec681f3Smrg * Copyright © 2016 Red Hat. 67ec681f3Smrg * Copyright © 2016 Bas Nieuwenhuizen 77ec681f3Smrg * Copyright © 2015 Intel Corporation 87ec681f3Smrg * 97ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 107ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 117ec681f3Smrg * to deal in the Software without restriction, including without limitation 127ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 137ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 147ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 157ec681f3Smrg * 167ec681f3Smrg * The above copyright notice and this permission notice (including the next 177ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 187ec681f3Smrg * Software. 197ec681f3Smrg * 207ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 217ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 227ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 237ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 247ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 257ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 267ec681f3Smrg * DEALINGS IN THE SOFTWARE. 277ec681f3Smrg */ 287ec681f3Smrg 297ec681f3Smrg#include "panvk_cs.h" 307ec681f3Smrg#include "panvk_private.h" 317ec681f3Smrg 327ec681f3Smrg#include "pan_bo.h" 337ec681f3Smrg 347ec681f3Smrg#include "nir/nir.h" 357ec681f3Smrg#include "nir/nir_builder.h" 367ec681f3Smrg#include "spirv/nir_spirv.h" 377ec681f3Smrg#include "util/debug.h" 387ec681f3Smrg#include "util/mesa-sha1.h" 397ec681f3Smrg#include "util/u_atomic.h" 407ec681f3Smrg#include "vk_format.h" 417ec681f3Smrg#include "vk_util.h" 427ec681f3Smrg 437ec681f3Smrg#include "panfrost/util/pan_lower_framebuffer.h" 447ec681f3Smrg 457ec681f3Smrg#include "panfrost-quirks.h" 467ec681f3Smrg 477ec681f3Smrgstruct panvk_pipeline_builder 487ec681f3Smrg{ 497ec681f3Smrg struct panvk_device *device; 507ec681f3Smrg struct panvk_pipeline_cache *cache; 517ec681f3Smrg const VkAllocationCallbacks *alloc; 527ec681f3Smrg const VkGraphicsPipelineCreateInfo *create_info; 537ec681f3Smrg const struct panvk_pipeline_layout *layout; 547ec681f3Smrg 557ec681f3Smrg struct panvk_shader *shaders[MESA_SHADER_STAGES]; 567ec681f3Smrg struct { 577ec681f3Smrg uint32_t shader_offset; 587ec681f3Smrg uint32_t rsd_offset; 597ec681f3Smrg uint32_t sysvals_offset; 607ec681f3Smrg } stages[MESA_SHADER_STAGES]; 617ec681f3Smrg uint32_t blend_shader_offsets[MAX_RTS]; 627ec681f3Smrg uint32_t shader_total_size; 637ec681f3Smrg uint32_t static_state_size; 647ec681f3Smrg uint32_t vpd_offset; 657ec681f3Smrg 667ec681f3Smrg bool rasterizer_discard; 677ec681f3Smrg /* these states are affectd by rasterizer_discard */ 687ec681f3Smrg VkSampleCountFlagBits samples; 697ec681f3Smrg bool use_depth_stencil_attachment; 707ec681f3Smrg uint8_t active_color_attachments; 717ec681f3Smrg enum pipe_format color_attachment_formats[MAX_RTS]; 727ec681f3Smrg}; 737ec681f3Smrg 747ec681f3Smrgstatic VkResult 757ec681f3Smrgpanvk_pipeline_builder_create_pipeline(struct panvk_pipeline_builder *builder, 767ec681f3Smrg struct panvk_pipeline **out_pipeline) 777ec681f3Smrg{ 787ec681f3Smrg struct panvk_device *dev = builder->device; 797ec681f3Smrg 807ec681f3Smrg struct panvk_pipeline *pipeline = 817ec681f3Smrg vk_object_zalloc(&dev->vk, builder->alloc, 827ec681f3Smrg sizeof(*pipeline), VK_OBJECT_TYPE_PIPELINE); 837ec681f3Smrg if (!pipeline) 847ec681f3Smrg return VK_ERROR_OUT_OF_HOST_MEMORY; 857ec681f3Smrg 867ec681f3Smrg pipeline->layout = builder->layout; 877ec681f3Smrg *out_pipeline = pipeline; 887ec681f3Smrg return VK_SUCCESS; 897ec681f3Smrg} 907ec681f3Smrg 917ec681f3Smrgstatic void 927ec681f3Smrgpanvk_pipeline_builder_finish(struct panvk_pipeline_builder *builder) 937ec681f3Smrg{ 947ec681f3Smrg for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) { 957ec681f3Smrg if (!builder->shaders[i]) 967ec681f3Smrg continue; 977ec681f3Smrg panvk_shader_destroy(builder->device, builder->shaders[i], builder->alloc); 987ec681f3Smrg } 997ec681f3Smrg} 1007ec681f3Smrg 1017ec681f3Smrgstatic bool 1027ec681f3Smrgpanvk_pipeline_static_state(struct panvk_pipeline *pipeline, uint32_t id) 1037ec681f3Smrg{ 1047ec681f3Smrg return !(pipeline->dynamic_state_mask & (1 << id)); 1057ec681f3Smrg} 1067ec681f3Smrg 1077ec681f3Smrgstatic VkResult 1087ec681f3Smrgpanvk_pipeline_builder_compile_shaders(struct panvk_pipeline_builder *builder, 1097ec681f3Smrg struct panvk_pipeline *pipeline) 1107ec681f3Smrg{ 1117ec681f3Smrg const VkPipelineShaderStageCreateInfo *stage_infos[MESA_SHADER_STAGES] = { 1127ec681f3Smrg NULL 1137ec681f3Smrg }; 1147ec681f3Smrg for (uint32_t i = 0; i < builder->create_info->stageCount; i++) { 1157ec681f3Smrg gl_shader_stage stage = vk_to_mesa_shader_stage(builder->create_info->pStages[i].stage); 1167ec681f3Smrg stage_infos[stage] = &builder->create_info->pStages[i]; 1177ec681f3Smrg } 1187ec681f3Smrg 1197ec681f3Smrg /* compile shaders in reverse order */ 1207ec681f3Smrg unsigned sysval_ubo = builder->layout->num_ubos; 1217ec681f3Smrg 1227ec681f3Smrg for (gl_shader_stage stage = MESA_SHADER_STAGES - 1; 1237ec681f3Smrg stage > MESA_SHADER_NONE; stage--) { 1247ec681f3Smrg const VkPipelineShaderStageCreateInfo *stage_info = stage_infos[stage]; 1257ec681f3Smrg if (!stage_info) 1267ec681f3Smrg continue; 1277ec681f3Smrg 1287ec681f3Smrg struct panvk_shader *shader; 1297ec681f3Smrg 1307ec681f3Smrg shader = panvk_per_arch(shader_create)(builder->device, stage, stage_info, 1317ec681f3Smrg builder->layout, sysval_ubo, 1327ec681f3Smrg &pipeline->blend.state, 1337ec681f3Smrg panvk_pipeline_static_state(pipeline, 1347ec681f3Smrg VK_DYNAMIC_STATE_BLEND_CONSTANTS), 1357ec681f3Smrg builder->alloc); 1367ec681f3Smrg if (!shader) 1377ec681f3Smrg return VK_ERROR_OUT_OF_HOST_MEMORY; 1387ec681f3Smrg 1397ec681f3Smrg if (shader->info.sysvals.sysval_count) 1407ec681f3Smrg sysval_ubo++; 1417ec681f3Smrg 1427ec681f3Smrg builder->shaders[stage] = shader; 1437ec681f3Smrg builder->shader_total_size = ALIGN_POT(builder->shader_total_size, 128); 1447ec681f3Smrg builder->stages[stage].shader_offset = builder->shader_total_size; 1457ec681f3Smrg builder->shader_total_size += 1467ec681f3Smrg util_dynarray_num_elements(&shader->binary, uint8_t); 1477ec681f3Smrg } 1487ec681f3Smrg 1497ec681f3Smrg return VK_SUCCESS; 1507ec681f3Smrg} 1517ec681f3Smrg 1527ec681f3Smrgstatic VkResult 1537ec681f3Smrgpanvk_pipeline_builder_upload_shaders(struct panvk_pipeline_builder *builder, 1547ec681f3Smrg struct panvk_pipeline *pipeline) 1557ec681f3Smrg{ 1567ec681f3Smrg struct panfrost_bo *bin_bo = 1577ec681f3Smrg panfrost_bo_create(&builder->device->physical_device->pdev, 1587ec681f3Smrg builder->shader_total_size, PAN_BO_EXECUTE, 1597ec681f3Smrg "Shader"); 1607ec681f3Smrg 1617ec681f3Smrg pipeline->binary_bo = bin_bo; 1627ec681f3Smrg panfrost_bo_mmap(bin_bo); 1637ec681f3Smrg 1647ec681f3Smrg for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) { 1657ec681f3Smrg const struct panvk_shader *shader = builder->shaders[i]; 1667ec681f3Smrg if (!shader) 1677ec681f3Smrg continue; 1687ec681f3Smrg 1697ec681f3Smrg memcpy(pipeline->binary_bo->ptr.cpu + builder->stages[i].shader_offset, 1707ec681f3Smrg util_dynarray_element(&shader->binary, uint8_t, 0), 1717ec681f3Smrg util_dynarray_num_elements(&shader->binary, uint8_t)); 1727ec681f3Smrg } 1737ec681f3Smrg 1747ec681f3Smrg return VK_SUCCESS; 1757ec681f3Smrg} 1767ec681f3Smrg 1777ec681f3Smrgstatic bool 1787ec681f3Smrgpanvk_pipeline_static_sysval(struct panvk_pipeline *pipeline, 1797ec681f3Smrg unsigned id) 1807ec681f3Smrg{ 1817ec681f3Smrg switch (id) { 1827ec681f3Smrg case PAN_SYSVAL_VIEWPORT_SCALE: 1837ec681f3Smrg case PAN_SYSVAL_VIEWPORT_OFFSET: 1847ec681f3Smrg return panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT); 1857ec681f3Smrg default: 1867ec681f3Smrg return false; 1877ec681f3Smrg } 1887ec681f3Smrg} 1897ec681f3Smrg 1907ec681f3Smrgstatic void 1917ec681f3Smrgpanvk_pipeline_builder_alloc_static_state_bo(struct panvk_pipeline_builder *builder, 1927ec681f3Smrg struct panvk_pipeline *pipeline) 1937ec681f3Smrg{ 1947ec681f3Smrg struct panfrost_device *pdev = 1957ec681f3Smrg &builder->device->physical_device->pdev; 1967ec681f3Smrg unsigned bo_size = 0; 1977ec681f3Smrg 1987ec681f3Smrg for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) { 1997ec681f3Smrg const struct panvk_shader *shader = builder->shaders[i]; 2007ec681f3Smrg if (!shader) 2017ec681f3Smrg continue; 2027ec681f3Smrg 2037ec681f3Smrg if (pipeline->fs.dynamic_rsd && i == MESA_SHADER_FRAGMENT) 2047ec681f3Smrg continue; 2057ec681f3Smrg 2067ec681f3Smrg bo_size = ALIGN_POT(bo_size, pan_alignment(RENDERER_STATE)); 2077ec681f3Smrg builder->stages[i].rsd_offset = bo_size; 2087ec681f3Smrg bo_size += pan_size(RENDERER_STATE); 2097ec681f3Smrg if (i == MESA_SHADER_FRAGMENT) 2107ec681f3Smrg bo_size += pan_size(BLEND) * MAX2(pipeline->blend.state.rt_count, 1); 2117ec681f3Smrg } 2127ec681f3Smrg 2137ec681f3Smrg if (panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT) && 2147ec681f3Smrg panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_SCISSOR)) { 2157ec681f3Smrg bo_size = ALIGN_POT(bo_size, pan_alignment(VIEWPORT)); 2167ec681f3Smrg builder->vpd_offset = bo_size; 2177ec681f3Smrg bo_size += pan_size(VIEWPORT); 2187ec681f3Smrg } 2197ec681f3Smrg 2207ec681f3Smrg for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) { 2217ec681f3Smrg const struct panvk_shader *shader = builder->shaders[i]; 2227ec681f3Smrg if (!shader || !shader->info.sysvals.sysval_count) 2237ec681f3Smrg continue; 2247ec681f3Smrg 2257ec681f3Smrg bool static_sysvals = true; 2267ec681f3Smrg for (unsigned s = 0; s < shader->info.sysvals.sysval_count; s++) { 2277ec681f3Smrg unsigned id = shader->info.sysvals.sysvals[i]; 2287ec681f3Smrg static_sysvals &= panvk_pipeline_static_sysval(pipeline, id); 2297ec681f3Smrg switch (PAN_SYSVAL_TYPE(id)) { 2307ec681f3Smrg case PAN_SYSVAL_VIEWPORT_SCALE: 2317ec681f3Smrg case PAN_SYSVAL_VIEWPORT_OFFSET: 2327ec681f3Smrg pipeline->sysvals[i].dirty_mask |= PANVK_DYNAMIC_VIEWPORT; 2337ec681f3Smrg break; 2347ec681f3Smrg default: 2357ec681f3Smrg break; 2367ec681f3Smrg } 2377ec681f3Smrg } 2387ec681f3Smrg 2397ec681f3Smrg if (!static_sysvals) { 2407ec681f3Smrg builder->stages[i].sysvals_offset = ~0; 2417ec681f3Smrg continue; 2427ec681f3Smrg } 2437ec681f3Smrg 2447ec681f3Smrg bo_size = ALIGN_POT(bo_size, 16); 2457ec681f3Smrg builder->stages[i].sysvals_offset = bo_size; 2467ec681f3Smrg bo_size += shader->info.sysvals.sysval_count * 16; 2477ec681f3Smrg } 2487ec681f3Smrg 2497ec681f3Smrg if (bo_size) { 2507ec681f3Smrg pipeline->state_bo = 2517ec681f3Smrg panfrost_bo_create(pdev, bo_size, 0, "Pipeline descriptors"); 2527ec681f3Smrg panfrost_bo_mmap(pipeline->state_bo); 2537ec681f3Smrg } 2547ec681f3Smrg} 2557ec681f3Smrg 2567ec681f3Smrgstatic void 2577ec681f3Smrgpanvk_pipeline_builder_upload_sysval(struct panvk_pipeline_builder *builder, 2587ec681f3Smrg struct panvk_pipeline *pipeline, 2597ec681f3Smrg unsigned id, union panvk_sysval_data *data) 2607ec681f3Smrg{ 2617ec681f3Smrg switch (PAN_SYSVAL_TYPE(id)) { 2627ec681f3Smrg case PAN_SYSVAL_VIEWPORT_SCALE: 2637ec681f3Smrg panvk_sysval_upload_viewport_scale(builder->create_info->pViewportState->pViewports, 2647ec681f3Smrg data); 2657ec681f3Smrg break; 2667ec681f3Smrg case PAN_SYSVAL_VIEWPORT_OFFSET: 2677ec681f3Smrg panvk_sysval_upload_viewport_offset(builder->create_info->pViewportState->pViewports, 2687ec681f3Smrg data); 2697ec681f3Smrg break; 2707ec681f3Smrg default: 2717ec681f3Smrg unreachable("Invalid static sysval"); 2727ec681f3Smrg } 2737ec681f3Smrg} 2747ec681f3Smrg 2757ec681f3Smrgstatic void 2767ec681f3Smrgpanvk_pipeline_builder_init_sysvals(struct panvk_pipeline_builder *builder, 2777ec681f3Smrg struct panvk_pipeline *pipeline, 2787ec681f3Smrg gl_shader_stage stage) 2797ec681f3Smrg{ 2807ec681f3Smrg const struct panvk_shader *shader = builder->shaders[stage]; 2817ec681f3Smrg 2827ec681f3Smrg pipeline->sysvals[stage].ids = shader->info.sysvals; 2837ec681f3Smrg pipeline->sysvals[stage].ubo_idx = shader->sysval_ubo; 2847ec681f3Smrg 2857ec681f3Smrg if (!shader->info.sysvals.sysval_count || 2867ec681f3Smrg builder->stages[stage].sysvals_offset == ~0) 2877ec681f3Smrg return; 2887ec681f3Smrg 2897ec681f3Smrg union panvk_sysval_data *static_data = 2907ec681f3Smrg pipeline->state_bo->ptr.cpu + builder->stages[stage].sysvals_offset; 2917ec681f3Smrg 2927ec681f3Smrg pipeline->sysvals[stage].ubo = 2937ec681f3Smrg pipeline->state_bo->ptr.gpu + builder->stages[stage].sysvals_offset; 2947ec681f3Smrg 2957ec681f3Smrg for (unsigned i = 0; i < shader->info.sysvals.sysval_count; i++) { 2967ec681f3Smrg unsigned id = shader->info.sysvals.sysvals[i]; 2977ec681f3Smrg 2987ec681f3Smrg panvk_pipeline_builder_upload_sysval(builder, 2997ec681f3Smrg pipeline, 3007ec681f3Smrg id, &static_data[i]); 3017ec681f3Smrg } 3027ec681f3Smrg} 3037ec681f3Smrg 3047ec681f3Smrgstatic void 3057ec681f3Smrgpanvk_pipeline_builder_init_shaders(struct panvk_pipeline_builder *builder, 3067ec681f3Smrg struct panvk_pipeline *pipeline) 3077ec681f3Smrg{ 3087ec681f3Smrg for (uint32_t i = 0; i < MESA_SHADER_STAGES; i++) { 3097ec681f3Smrg const struct panvk_shader *shader = builder->shaders[i]; 3107ec681f3Smrg if (!shader) 3117ec681f3Smrg continue; 3127ec681f3Smrg 3137ec681f3Smrg pipeline->tls_size = MAX2(pipeline->tls_size, shader->info.tls_size); 3147ec681f3Smrg pipeline->wls_size = MAX2(pipeline->wls_size, shader->info.wls_size); 3157ec681f3Smrg 3167ec681f3Smrg if (i == MESA_SHADER_VERTEX && shader->info.vs.writes_point_size) 3177ec681f3Smrg pipeline->ia.writes_point_size = true; 3187ec681f3Smrg 3197ec681f3Smrg mali_ptr shader_ptr = pipeline->binary_bo->ptr.gpu + 3207ec681f3Smrg builder->stages[i].shader_offset; 3217ec681f3Smrg 3227ec681f3Smrg void *rsd = pipeline->state_bo->ptr.cpu + builder->stages[i].rsd_offset; 3237ec681f3Smrg mali_ptr gpu_rsd = pipeline->state_bo->ptr.gpu + builder->stages[i].rsd_offset; 3247ec681f3Smrg 3257ec681f3Smrg if (i != MESA_SHADER_FRAGMENT) { 3267ec681f3Smrg panvk_per_arch(emit_non_fs_rsd)(builder->device, &shader->info, shader_ptr, rsd); 3277ec681f3Smrg } else if (!pipeline->fs.dynamic_rsd) { 3287ec681f3Smrg void *bd = rsd + pan_size(RENDERER_STATE); 3297ec681f3Smrg 3307ec681f3Smrg panvk_per_arch(emit_base_fs_rsd)(builder->device, pipeline, rsd); 3317ec681f3Smrg for (unsigned rt = 0; rt < MAX2(pipeline->blend.state.rt_count, 1); rt++) { 3327ec681f3Smrg panvk_per_arch(emit_blend)(builder->device, pipeline, rt, bd); 3337ec681f3Smrg bd += pan_size(BLEND); 3347ec681f3Smrg } 3357ec681f3Smrg } else { 3367ec681f3Smrg gpu_rsd = 0; 3377ec681f3Smrg panvk_per_arch(emit_base_fs_rsd)(builder->device, pipeline, &pipeline->fs.rsd_template); 3387ec681f3Smrg for (unsigned rt = 0; rt < MAX2(pipeline->blend.state.rt_count, 1); rt++) { 3397ec681f3Smrg panvk_per_arch(emit_blend)(builder->device, pipeline, rt, 3407ec681f3Smrg &pipeline->blend.bd_template[rt]); 3417ec681f3Smrg } 3427ec681f3Smrg } 3437ec681f3Smrg 3447ec681f3Smrg pipeline->rsds[i] = gpu_rsd; 3457ec681f3Smrg panvk_pipeline_builder_init_sysvals(builder, pipeline, i); 3467ec681f3Smrg } 3477ec681f3Smrg 3487ec681f3Smrg pipeline->num_ubos = builder->layout->num_ubos; 3497ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(pipeline->sysvals); i++) { 3507ec681f3Smrg if (pipeline->sysvals[i].ids.sysval_count) 3517ec681f3Smrg pipeline->num_ubos = MAX2(pipeline->num_ubos, pipeline->sysvals[i].ubo_idx + 1); 3527ec681f3Smrg } 3537ec681f3Smrg 3547ec681f3Smrg pipeline->num_sysvals = 0; 3557ec681f3Smrg for (unsigned i = 0; i < ARRAY_SIZE(pipeline->sysvals); i++) 3567ec681f3Smrg pipeline->num_sysvals += pipeline->sysvals[i].ids.sysval_count; 3577ec681f3Smrg} 3587ec681f3Smrg 3597ec681f3Smrg 3607ec681f3Smrgstatic void 3617ec681f3Smrgpanvk_pipeline_builder_parse_viewport(struct panvk_pipeline_builder *builder, 3627ec681f3Smrg struct panvk_pipeline *pipeline) 3637ec681f3Smrg{ 3647ec681f3Smrg /* The spec says: 3657ec681f3Smrg * 3667ec681f3Smrg * pViewportState is a pointer to an instance of the 3677ec681f3Smrg * VkPipelineViewportStateCreateInfo structure, and is ignored if the 3687ec681f3Smrg * pipeline has rasterization disabled. 3697ec681f3Smrg */ 3707ec681f3Smrg if (!builder->rasterizer_discard && 3717ec681f3Smrg panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT) && 3727ec681f3Smrg panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_SCISSOR)) { 3737ec681f3Smrg void *vpd = pipeline->state_bo->ptr.cpu + builder->vpd_offset; 3747ec681f3Smrg panvk_per_arch(emit_viewport)(builder->create_info->pViewportState->pViewports, 3757ec681f3Smrg builder->create_info->pViewportState->pScissors, 3767ec681f3Smrg vpd); 3777ec681f3Smrg pipeline->vpd = pipeline->state_bo->ptr.gpu + 3787ec681f3Smrg builder->vpd_offset; 3797ec681f3Smrg } 3807ec681f3Smrg if (panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT)) 3817ec681f3Smrg pipeline->viewport = builder->create_info->pViewportState->pViewports[0]; 3827ec681f3Smrg 3837ec681f3Smrg if (panvk_pipeline_static_state(pipeline, VK_DYNAMIC_STATE_SCISSOR)) 3847ec681f3Smrg pipeline->scissor = builder->create_info->pViewportState->pScissors[0]; 3857ec681f3Smrg} 3867ec681f3Smrg 3877ec681f3Smrgstatic void 3887ec681f3Smrgpanvk_pipeline_builder_parse_dynamic(struct panvk_pipeline_builder *builder, 3897ec681f3Smrg struct panvk_pipeline *pipeline) 3907ec681f3Smrg{ 3917ec681f3Smrg const VkPipelineDynamicStateCreateInfo *dynamic_info = 3927ec681f3Smrg builder->create_info->pDynamicState; 3937ec681f3Smrg 3947ec681f3Smrg if (!dynamic_info) 3957ec681f3Smrg return; 3967ec681f3Smrg 3977ec681f3Smrg for (uint32_t i = 0; i < dynamic_info->dynamicStateCount; i++) { 3987ec681f3Smrg VkDynamicState state = dynamic_info->pDynamicStates[i]; 3997ec681f3Smrg switch (state) { 4007ec681f3Smrg case VK_DYNAMIC_STATE_VIEWPORT ... VK_DYNAMIC_STATE_STENCIL_REFERENCE: 4017ec681f3Smrg pipeline->dynamic_state_mask |= 1 << state; 4027ec681f3Smrg break; 4037ec681f3Smrg default: 4047ec681f3Smrg unreachable("unsupported dynamic state"); 4057ec681f3Smrg } 4067ec681f3Smrg } 4077ec681f3Smrg 4087ec681f3Smrg} 4097ec681f3Smrg 4107ec681f3Smrgstatic enum mali_draw_mode 4117ec681f3Smrgtranslate_prim_topology(VkPrimitiveTopology in) 4127ec681f3Smrg{ 4137ec681f3Smrg switch (in) { 4147ec681f3Smrg case VK_PRIMITIVE_TOPOLOGY_POINT_LIST: 4157ec681f3Smrg return MALI_DRAW_MODE_POINTS; 4167ec681f3Smrg case VK_PRIMITIVE_TOPOLOGY_LINE_LIST: 4177ec681f3Smrg return MALI_DRAW_MODE_LINES; 4187ec681f3Smrg case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP: 4197ec681f3Smrg return MALI_DRAW_MODE_LINE_STRIP; 4207ec681f3Smrg case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST: 4217ec681f3Smrg return MALI_DRAW_MODE_TRIANGLES; 4227ec681f3Smrg case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP: 4237ec681f3Smrg return MALI_DRAW_MODE_TRIANGLE_STRIP; 4247ec681f3Smrg case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN: 4257ec681f3Smrg return MALI_DRAW_MODE_TRIANGLE_FAN; 4267ec681f3Smrg case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY: 4277ec681f3Smrg case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY: 4287ec681f3Smrg case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY: 4297ec681f3Smrg case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY: 4307ec681f3Smrg case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST: 4317ec681f3Smrg default: 4327ec681f3Smrg unreachable("Invalid primitive type"); 4337ec681f3Smrg } 4347ec681f3Smrg} 4357ec681f3Smrg 4367ec681f3Smrgstatic void 4377ec681f3Smrgpanvk_pipeline_builder_parse_input_assembly(struct panvk_pipeline_builder *builder, 4387ec681f3Smrg struct panvk_pipeline *pipeline) 4397ec681f3Smrg{ 4407ec681f3Smrg pipeline->ia.primitive_restart = 4417ec681f3Smrg builder->create_info->pInputAssemblyState->primitiveRestartEnable; 4427ec681f3Smrg pipeline->ia.topology = 4437ec681f3Smrg translate_prim_topology(builder->create_info->pInputAssemblyState->topology); 4447ec681f3Smrg} 4457ec681f3Smrg 4467ec681f3Smrgstatic enum pipe_logicop 4477ec681f3Smrgtranslate_logicop(VkLogicOp in) 4487ec681f3Smrg{ 4497ec681f3Smrg switch (in) { 4507ec681f3Smrg case VK_LOGIC_OP_CLEAR: return PIPE_LOGICOP_CLEAR; 4517ec681f3Smrg case VK_LOGIC_OP_AND: return PIPE_LOGICOP_AND; 4527ec681f3Smrg case VK_LOGIC_OP_AND_REVERSE: return PIPE_LOGICOP_AND_REVERSE; 4537ec681f3Smrg case VK_LOGIC_OP_COPY: return PIPE_LOGICOP_COPY; 4547ec681f3Smrg case VK_LOGIC_OP_AND_INVERTED: return PIPE_LOGICOP_AND_INVERTED; 4557ec681f3Smrg case VK_LOGIC_OP_NO_OP: return PIPE_LOGICOP_NOOP; 4567ec681f3Smrg case VK_LOGIC_OP_XOR: return PIPE_LOGICOP_XOR; 4577ec681f3Smrg case VK_LOGIC_OP_OR: return PIPE_LOGICOP_OR; 4587ec681f3Smrg case VK_LOGIC_OP_NOR: return PIPE_LOGICOP_NOR; 4597ec681f3Smrg case VK_LOGIC_OP_EQUIVALENT: return PIPE_LOGICOP_EQUIV; 4607ec681f3Smrg case VK_LOGIC_OP_INVERT: return PIPE_LOGICOP_INVERT; 4617ec681f3Smrg case VK_LOGIC_OP_OR_REVERSE: return PIPE_LOGICOP_OR_REVERSE; 4627ec681f3Smrg case VK_LOGIC_OP_COPY_INVERTED: return PIPE_LOGICOP_COPY_INVERTED; 4637ec681f3Smrg case VK_LOGIC_OP_OR_INVERTED: return PIPE_LOGICOP_OR_INVERTED; 4647ec681f3Smrg case VK_LOGIC_OP_NAND: return PIPE_LOGICOP_NAND; 4657ec681f3Smrg case VK_LOGIC_OP_SET: return PIPE_LOGICOP_SET; 4667ec681f3Smrg default: unreachable("Invalid logicop"); 4677ec681f3Smrg } 4687ec681f3Smrg} 4697ec681f3Smrg 4707ec681f3Smrgstatic enum blend_func 4717ec681f3Smrgtranslate_blend_op(VkBlendOp in) 4727ec681f3Smrg{ 4737ec681f3Smrg switch (in) { 4747ec681f3Smrg case VK_BLEND_OP_ADD: return BLEND_FUNC_ADD; 4757ec681f3Smrg case VK_BLEND_OP_SUBTRACT: return BLEND_FUNC_SUBTRACT; 4767ec681f3Smrg case VK_BLEND_OP_REVERSE_SUBTRACT: return BLEND_FUNC_REVERSE_SUBTRACT; 4777ec681f3Smrg case VK_BLEND_OP_MIN: return BLEND_FUNC_MIN; 4787ec681f3Smrg case VK_BLEND_OP_MAX: return BLEND_FUNC_MAX; 4797ec681f3Smrg default: unreachable("Invalid blend op"); 4807ec681f3Smrg } 4817ec681f3Smrg} 4827ec681f3Smrg 4837ec681f3Smrgstatic enum blend_factor 4847ec681f3Smrgtranslate_blend_factor(VkBlendFactor in, bool dest_has_alpha) 4857ec681f3Smrg{ 4867ec681f3Smrg switch (in) { 4877ec681f3Smrg case VK_BLEND_FACTOR_ZERO: 4887ec681f3Smrg case VK_BLEND_FACTOR_ONE: 4897ec681f3Smrg return BLEND_FACTOR_ZERO; 4907ec681f3Smrg case VK_BLEND_FACTOR_SRC_COLOR: 4917ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: 4927ec681f3Smrg return BLEND_FACTOR_SRC_COLOR; 4937ec681f3Smrg case VK_BLEND_FACTOR_DST_COLOR: 4947ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR: 4957ec681f3Smrg return BLEND_FACTOR_DST_COLOR; 4967ec681f3Smrg case VK_BLEND_FACTOR_SRC_ALPHA: 4977ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: 4987ec681f3Smrg return BLEND_FACTOR_SRC_ALPHA; 4997ec681f3Smrg case VK_BLEND_FACTOR_DST_ALPHA: 5007ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: 5017ec681f3Smrg return dest_has_alpha ? BLEND_FACTOR_DST_ALPHA : BLEND_FACTOR_ZERO; 5027ec681f3Smrg case VK_BLEND_FACTOR_CONSTANT_COLOR: 5037ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: 5047ec681f3Smrg return BLEND_FACTOR_CONSTANT_COLOR; 5057ec681f3Smrg case VK_BLEND_FACTOR_CONSTANT_ALPHA: 5067ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: 5077ec681f3Smrg return BLEND_FACTOR_CONSTANT_ALPHA; 5087ec681f3Smrg case VK_BLEND_FACTOR_SRC1_COLOR: 5097ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR: 5107ec681f3Smrg return BLEND_FACTOR_SRC1_COLOR; 5117ec681f3Smrg case VK_BLEND_FACTOR_SRC1_ALPHA: 5127ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: 5137ec681f3Smrg return BLEND_FACTOR_SRC1_ALPHA; 5147ec681f3Smrg case VK_BLEND_FACTOR_SRC_ALPHA_SATURATE: 5157ec681f3Smrg return BLEND_FACTOR_SRC_ALPHA_SATURATE; 5167ec681f3Smrg default: unreachable("Invalid blend factor"); 5177ec681f3Smrg } 5187ec681f3Smrg} 5197ec681f3Smrg 5207ec681f3Smrgstatic bool 5217ec681f3Smrginverted_blend_factor(VkBlendFactor in, bool dest_has_alpha) 5227ec681f3Smrg{ 5237ec681f3Smrg switch (in) { 5247ec681f3Smrg case VK_BLEND_FACTOR_ONE: 5257ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR: 5267ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR: 5277ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA: 5287ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR: 5297ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA: 5307ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR: 5317ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA: 5327ec681f3Smrg return true; 5337ec681f3Smrg case VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA: 5347ec681f3Smrg return dest_has_alpha ? true : false; 5357ec681f3Smrg case VK_BLEND_FACTOR_DST_ALPHA: 5367ec681f3Smrg return !dest_has_alpha ? true : false; 5377ec681f3Smrg default: 5387ec681f3Smrg return false; 5397ec681f3Smrg } 5407ec681f3Smrg} 5417ec681f3Smrg 5427ec681f3Smrgbool 5437ec681f3Smrgpanvk_per_arch(blend_needs_lowering)(const struct panfrost_device *dev, 5447ec681f3Smrg const struct pan_blend_state *state, 5457ec681f3Smrg unsigned rt) 5467ec681f3Smrg{ 5477ec681f3Smrg /* LogicOp requires a blend shader */ 5487ec681f3Smrg if (state->logicop_enable) 5497ec681f3Smrg return true; 5507ec681f3Smrg 5517ec681f3Smrg /* Not all formats can be blended by fixed-function hardware */ 5527ec681f3Smrg if (!panfrost_blendable_formats_v7[state->rts[rt].format].internal) 5537ec681f3Smrg return true; 5547ec681f3Smrg 5557ec681f3Smrg unsigned constant_mask = pan_blend_constant_mask(state->rts[rt].equation); 5567ec681f3Smrg 5577ec681f3Smrg /* v6 doesn't support blend constants in FF blend equations. 5587ec681f3Smrg * v7 only uses the constant from RT 0 (TODO: what if it's the same 5597ec681f3Smrg * constant? or a constant is shared?) 5607ec681f3Smrg */ 5617ec681f3Smrg if (constant_mask && (PAN_ARCH == 6 || (PAN_ARCH == 7 && rt > 0))) 5627ec681f3Smrg return true; 5637ec681f3Smrg 5647ec681f3Smrg if (!pan_blend_is_homogenous_constant(constant_mask, state->constants)) 5657ec681f3Smrg return true; 5667ec681f3Smrg 5677ec681f3Smrg bool supports_2src = pan_blend_supports_2src(dev->arch); 5687ec681f3Smrg return !pan_blend_can_fixed_function(state->rts[rt].equation, supports_2src); 5697ec681f3Smrg} 5707ec681f3Smrg 5717ec681f3Smrgstatic void 5727ec681f3Smrgpanvk_pipeline_builder_parse_color_blend(struct panvk_pipeline_builder *builder, 5737ec681f3Smrg struct panvk_pipeline *pipeline) 5747ec681f3Smrg{ 5757ec681f3Smrg struct panfrost_device *pdev = &builder->device->physical_device->pdev; 5767ec681f3Smrg pipeline->blend.state.logicop_enable = 5777ec681f3Smrg builder->create_info->pColorBlendState->logicOpEnable; 5787ec681f3Smrg pipeline->blend.state.logicop_func = 5797ec681f3Smrg translate_logicop(builder->create_info->pColorBlendState->logicOp); 5807ec681f3Smrg pipeline->blend.state.rt_count = util_last_bit(builder->active_color_attachments); 5817ec681f3Smrg memcpy(pipeline->blend.state.constants, 5827ec681f3Smrg builder->create_info->pColorBlendState->blendConstants, 5837ec681f3Smrg sizeof(pipeline->blend.state.constants)); 5847ec681f3Smrg 5857ec681f3Smrg for (unsigned i = 0; i < pipeline->blend.state.rt_count; i++) { 5867ec681f3Smrg const VkPipelineColorBlendAttachmentState *in = 5877ec681f3Smrg &builder->create_info->pColorBlendState->pAttachments[i]; 5887ec681f3Smrg struct pan_blend_rt_state *out = &pipeline->blend.state.rts[i]; 5897ec681f3Smrg 5907ec681f3Smrg out->format = builder->color_attachment_formats[i]; 5917ec681f3Smrg 5927ec681f3Smrg bool dest_has_alpha = util_format_has_alpha(out->format); 5937ec681f3Smrg 5947ec681f3Smrg out->nr_samples = builder->create_info->pMultisampleState->rasterizationSamples; 5957ec681f3Smrg out->equation.blend_enable = in->blendEnable; 5967ec681f3Smrg out->equation.color_mask = in->colorWriteMask; 5977ec681f3Smrg out->equation.rgb_func = translate_blend_op(in->colorBlendOp); 5987ec681f3Smrg out->equation.rgb_src_factor = translate_blend_factor(in->srcColorBlendFactor, dest_has_alpha); 5997ec681f3Smrg out->equation.rgb_invert_src_factor = inverted_blend_factor(in->srcColorBlendFactor, dest_has_alpha); 6007ec681f3Smrg out->equation.rgb_dst_factor = translate_blend_factor(in->dstColorBlendFactor, dest_has_alpha); 6017ec681f3Smrg out->equation.rgb_invert_dst_factor = inverted_blend_factor(in->dstColorBlendFactor, dest_has_alpha); 6027ec681f3Smrg out->equation.alpha_func = translate_blend_op(in->alphaBlendOp); 6037ec681f3Smrg out->equation.alpha_src_factor = translate_blend_factor(in->srcAlphaBlendFactor, dest_has_alpha); 6047ec681f3Smrg out->equation.alpha_invert_src_factor = inverted_blend_factor(in->srcAlphaBlendFactor, dest_has_alpha); 6057ec681f3Smrg out->equation.alpha_dst_factor = translate_blend_factor(in->dstAlphaBlendFactor, dest_has_alpha); 6067ec681f3Smrg out->equation.alpha_invert_dst_factor = inverted_blend_factor(in->dstAlphaBlendFactor, dest_has_alpha); 6077ec681f3Smrg 6087ec681f3Smrg pipeline->blend.reads_dest |= pan_blend_reads_dest(out->equation); 6097ec681f3Smrg 6107ec681f3Smrg unsigned constant_mask = 6117ec681f3Smrg panvk_per_arch(blend_needs_lowering)(pdev, &pipeline->blend.state, i) ? 6127ec681f3Smrg 0 : pan_blend_constant_mask(out->equation); 6137ec681f3Smrg pipeline->blend.constant[i].index = ffs(constant_mask) - 1; 6147ec681f3Smrg if (constant_mask && PAN_ARCH >= 6) { 6157ec681f3Smrg /* On Bifrost, the blend constant is expressed with a UNORM of the 6167ec681f3Smrg * size of the target format. The value is then shifted such that 6177ec681f3Smrg * used bits are in the MSB. Here we calculate the factor at pipeline 6187ec681f3Smrg * creation time so we only have to do a 6197ec681f3Smrg * hw_constant = float_constant * factor; 6207ec681f3Smrg * at descriptor emission time. 6217ec681f3Smrg */ 6227ec681f3Smrg const struct util_format_description *format_desc = 6237ec681f3Smrg util_format_description(out->format); 6247ec681f3Smrg unsigned chan_size = 0; 6257ec681f3Smrg for (unsigned c = 0; c < format_desc->nr_channels; c++) 6267ec681f3Smrg chan_size = MAX2(format_desc->channel[c].size, chan_size); 6277ec681f3Smrg pipeline->blend.constant[i].bifrost_factor = 6287ec681f3Smrg ((1 << chan_size) - 1) << (16 - chan_size); 6297ec681f3Smrg } 6307ec681f3Smrg } 6317ec681f3Smrg} 6327ec681f3Smrg 6337ec681f3Smrgstatic void 6347ec681f3Smrgpanvk_pipeline_builder_parse_multisample(struct panvk_pipeline_builder *builder, 6357ec681f3Smrg struct panvk_pipeline *pipeline) 6367ec681f3Smrg{ 6377ec681f3Smrg unsigned nr_samples = 6387ec681f3Smrg MAX2(builder->create_info->pMultisampleState->rasterizationSamples, 1); 6397ec681f3Smrg 6407ec681f3Smrg pipeline->ms.rast_samples = 6417ec681f3Smrg builder->create_info->pMultisampleState->rasterizationSamples; 6427ec681f3Smrg pipeline->ms.sample_mask = 6437ec681f3Smrg builder->create_info->pMultisampleState->pSampleMask ? 6447ec681f3Smrg builder->create_info->pMultisampleState->pSampleMask[0] : UINT16_MAX; 6457ec681f3Smrg pipeline->ms.min_samples = 6467ec681f3Smrg MAX2(builder->create_info->pMultisampleState->minSampleShading * nr_samples, 1); 6477ec681f3Smrg} 6487ec681f3Smrg 6497ec681f3Smrgstatic enum mali_stencil_op 6507ec681f3Smrgtranslate_stencil_op(VkStencilOp in) 6517ec681f3Smrg{ 6527ec681f3Smrg switch (in) { 6537ec681f3Smrg case VK_STENCIL_OP_KEEP: return MALI_STENCIL_OP_KEEP; 6547ec681f3Smrg case VK_STENCIL_OP_ZERO: return MALI_STENCIL_OP_ZERO; 6557ec681f3Smrg case VK_STENCIL_OP_REPLACE: return MALI_STENCIL_OP_REPLACE; 6567ec681f3Smrg case VK_STENCIL_OP_INCREMENT_AND_CLAMP: return MALI_STENCIL_OP_INCR_SAT; 6577ec681f3Smrg case VK_STENCIL_OP_DECREMENT_AND_CLAMP: return MALI_STENCIL_OP_DECR_SAT; 6587ec681f3Smrg case VK_STENCIL_OP_INCREMENT_AND_WRAP: return MALI_STENCIL_OP_INCR_WRAP; 6597ec681f3Smrg case VK_STENCIL_OP_DECREMENT_AND_WRAP: return MALI_STENCIL_OP_DECR_WRAP; 6607ec681f3Smrg case VK_STENCIL_OP_INVERT: return MALI_STENCIL_OP_INVERT; 6617ec681f3Smrg default: unreachable("Invalid stencil op"); 6627ec681f3Smrg } 6637ec681f3Smrg} 6647ec681f3Smrg 6657ec681f3Smrgstatic void 6667ec681f3Smrgpanvk_pipeline_builder_parse_zs(struct panvk_pipeline_builder *builder, 6677ec681f3Smrg struct panvk_pipeline *pipeline) 6687ec681f3Smrg{ 6697ec681f3Smrg pipeline->zs.z_test = builder->create_info->pDepthStencilState->depthTestEnable; 6707ec681f3Smrg pipeline->zs.z_write = builder->create_info->pDepthStencilState->depthWriteEnable; 6717ec681f3Smrg pipeline->zs.z_compare_func = 6727ec681f3Smrg panvk_per_arch(translate_compare_func)(builder->create_info->pDepthStencilState->depthCompareOp); 6737ec681f3Smrg pipeline->zs.s_test = builder->create_info->pDepthStencilState->stencilTestEnable; 6747ec681f3Smrg pipeline->zs.s_front.fail_op = 6757ec681f3Smrg translate_stencil_op(builder->create_info->pDepthStencilState->front.failOp); 6767ec681f3Smrg pipeline->zs.s_front.pass_op = 6777ec681f3Smrg translate_stencil_op(builder->create_info->pDepthStencilState->front.passOp); 6787ec681f3Smrg pipeline->zs.s_front.z_fail_op = 6797ec681f3Smrg translate_stencil_op(builder->create_info->pDepthStencilState->front.depthFailOp); 6807ec681f3Smrg pipeline->zs.s_front.compare_func = 6817ec681f3Smrg panvk_per_arch(translate_compare_func)(builder->create_info->pDepthStencilState->front.compareOp); 6827ec681f3Smrg pipeline->zs.s_front.compare_mask = 6837ec681f3Smrg builder->create_info->pDepthStencilState->front.compareMask; 6847ec681f3Smrg pipeline->zs.s_front.write_mask = 6857ec681f3Smrg builder->create_info->pDepthStencilState->front.writeMask; 6867ec681f3Smrg pipeline->zs.s_front.ref = 6877ec681f3Smrg builder->create_info->pDepthStencilState->front.reference; 6887ec681f3Smrg pipeline->zs.s_back.fail_op = 6897ec681f3Smrg translate_stencil_op(builder->create_info->pDepthStencilState->back.failOp); 6907ec681f3Smrg pipeline->zs.s_back.pass_op = 6917ec681f3Smrg translate_stencil_op(builder->create_info->pDepthStencilState->back.passOp); 6927ec681f3Smrg pipeline->zs.s_back.z_fail_op = 6937ec681f3Smrg translate_stencil_op(builder->create_info->pDepthStencilState->back.depthFailOp); 6947ec681f3Smrg pipeline->zs.s_back.compare_func = 6957ec681f3Smrg panvk_per_arch(translate_compare_func)(builder->create_info->pDepthStencilState->back.compareOp); 6967ec681f3Smrg pipeline->zs.s_back.compare_mask = 6977ec681f3Smrg builder->create_info->pDepthStencilState->back.compareMask; 6987ec681f3Smrg pipeline->zs.s_back.write_mask = 6997ec681f3Smrg builder->create_info->pDepthStencilState->back.writeMask; 7007ec681f3Smrg pipeline->zs.s_back.ref = 7017ec681f3Smrg builder->create_info->pDepthStencilState->back.reference; 7027ec681f3Smrg} 7037ec681f3Smrg 7047ec681f3Smrgstatic void 7057ec681f3Smrgpanvk_pipeline_builder_parse_rast(struct panvk_pipeline_builder *builder, 7067ec681f3Smrg struct panvk_pipeline *pipeline) 7077ec681f3Smrg{ 7087ec681f3Smrg pipeline->rast.clamp_depth = builder->create_info->pRasterizationState->depthClampEnable; 7097ec681f3Smrg pipeline->rast.depth_bias.enable = builder->create_info->pRasterizationState->depthBiasEnable; 7107ec681f3Smrg pipeline->rast.depth_bias.constant_factor = 7117ec681f3Smrg builder->create_info->pRasterizationState->depthBiasConstantFactor; 7127ec681f3Smrg pipeline->rast.depth_bias.clamp = builder->create_info->pRasterizationState->depthBiasClamp; 7137ec681f3Smrg pipeline->rast.depth_bias.slope_factor = builder->create_info->pRasterizationState->depthBiasSlopeFactor; 7147ec681f3Smrg pipeline->rast.front_ccw = builder->create_info->pRasterizationState->frontFace == VK_FRONT_FACE_COUNTER_CLOCKWISE; 7157ec681f3Smrg pipeline->rast.cull_front_face = builder->create_info->pRasterizationState->cullMode & VK_CULL_MODE_FRONT_BIT; 7167ec681f3Smrg pipeline->rast.cull_back_face = builder->create_info->pRasterizationState->cullMode & VK_CULL_MODE_BACK_BIT; 7177ec681f3Smrg} 7187ec681f3Smrg 7197ec681f3Smrgstatic bool 7207ec681f3Smrgpanvk_fs_required(struct panvk_pipeline *pipeline) 7217ec681f3Smrg{ 7227ec681f3Smrg const struct pan_shader_info *info = &pipeline->fs.info; 7237ec681f3Smrg 7247ec681f3Smrg /* If we generally have side effects */ 7257ec681f3Smrg if (info->fs.sidefx) 7267ec681f3Smrg return true; 7277ec681f3Smrg 7287ec681f3Smrg /* If colour is written we need to execute */ 7297ec681f3Smrg const struct pan_blend_state *blend = &pipeline->blend.state; 7307ec681f3Smrg for (unsigned i = 0; i < blend->rt_count; ++i) { 7317ec681f3Smrg if (blend->rts[i].equation.color_mask) 7327ec681f3Smrg return true; 7337ec681f3Smrg } 7347ec681f3Smrg 7357ec681f3Smrg /* If depth is written and not implied we need to execute. 7367ec681f3Smrg * TODO: Predicate on Z/S writes being enabled */ 7377ec681f3Smrg return (info->fs.writes_depth || info->fs.writes_stencil); 7387ec681f3Smrg} 7397ec681f3Smrg 7407ec681f3Smrg#define PANVK_DYNAMIC_FS_RSD_MASK \ 7417ec681f3Smrg ((1 << VK_DYNAMIC_STATE_DEPTH_BIAS) | \ 7427ec681f3Smrg (1 << VK_DYNAMIC_STATE_BLEND_CONSTANTS) | \ 7437ec681f3Smrg (1 << VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK) | \ 7447ec681f3Smrg (1 << VK_DYNAMIC_STATE_STENCIL_WRITE_MASK) | \ 7457ec681f3Smrg (1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE)) 7467ec681f3Smrg 7477ec681f3Smrgstatic void 7487ec681f3Smrgpanvk_pipeline_builder_init_fs_state(struct panvk_pipeline_builder *builder, 7497ec681f3Smrg struct panvk_pipeline *pipeline) 7507ec681f3Smrg{ 7517ec681f3Smrg if (!builder->shaders[MESA_SHADER_FRAGMENT]) 7527ec681f3Smrg return; 7537ec681f3Smrg 7547ec681f3Smrg pipeline->fs.dynamic_rsd = 7557ec681f3Smrg pipeline->dynamic_state_mask & PANVK_DYNAMIC_FS_RSD_MASK; 7567ec681f3Smrg pipeline->fs.address = pipeline->binary_bo->ptr.gpu + 7577ec681f3Smrg builder->stages[MESA_SHADER_FRAGMENT].shader_offset; 7587ec681f3Smrg pipeline->fs.info = builder->shaders[MESA_SHADER_FRAGMENT]->info; 7597ec681f3Smrg pipeline->fs.rt_mask = builder->active_color_attachments; 7607ec681f3Smrg pipeline->fs.required = panvk_fs_required(pipeline); 7617ec681f3Smrg} 7627ec681f3Smrg 7637ec681f3Smrgstatic void 7647ec681f3Smrgpanvk_pipeline_update_varying_slot(struct panvk_varyings_info *varyings, 7657ec681f3Smrg gl_shader_stage stage, 7667ec681f3Smrg const struct pan_shader_varying *varying, 7677ec681f3Smrg bool input) 7687ec681f3Smrg{ 7697ec681f3Smrg bool fs = stage == MESA_SHADER_FRAGMENT; 7707ec681f3Smrg gl_varying_slot loc = varying->location; 7717ec681f3Smrg enum panvk_varying_buf_id buf_id = 7727ec681f3Smrg panvk_varying_buf_id(fs, loc); 7737ec681f3Smrg 7747ec681f3Smrg varyings->stage[stage].loc[varyings->stage[stage].count++] = loc; 7757ec681f3Smrg 7767ec681f3Smrg if (panvk_varying_is_builtin(stage, loc)) { 7777ec681f3Smrg varyings->buf_mask |= 1 << buf_id; 7787ec681f3Smrg return; 7797ec681f3Smrg } 7807ec681f3Smrg 7817ec681f3Smrg assert(loc < ARRAY_SIZE(varyings->varying)); 7827ec681f3Smrg 7837ec681f3Smrg enum pipe_format new_fmt = varying->format; 7847ec681f3Smrg enum pipe_format old_fmt = varyings->varying[loc].format; 7857ec681f3Smrg 7867ec681f3Smrg BITSET_SET(varyings->active, loc); 7877ec681f3Smrg 7887ec681f3Smrg /* We expect inputs to either be set by a previous stage or be built 7897ec681f3Smrg * in, skip the entry if that's not the case, we'll emit a const 7907ec681f3Smrg * varying returning zero for those entries. 7917ec681f3Smrg */ 7927ec681f3Smrg if (input && old_fmt == PIPE_FORMAT_NONE) 7937ec681f3Smrg return; 7947ec681f3Smrg 7957ec681f3Smrg unsigned new_size = util_format_get_blocksize(new_fmt); 7967ec681f3Smrg unsigned old_size = util_format_get_blocksize(old_fmt); 7977ec681f3Smrg 7987ec681f3Smrg if (old_size < new_size) 7997ec681f3Smrg varyings->varying[loc].format = new_fmt; 8007ec681f3Smrg 8017ec681f3Smrg varyings->buf_mask |= 1 << buf_id; 8027ec681f3Smrg} 8037ec681f3Smrg 8047ec681f3Smrgstatic void 8057ec681f3Smrgpanvk_pipeline_builder_collect_varyings(struct panvk_pipeline_builder *builder, 8067ec681f3Smrg struct panvk_pipeline *pipeline) 8077ec681f3Smrg{ 8087ec681f3Smrg for (uint32_t s = 0; s < MESA_SHADER_STAGES; s++) { 8097ec681f3Smrg if (!builder->shaders[s]) 8107ec681f3Smrg continue; 8117ec681f3Smrg 8127ec681f3Smrg const struct pan_shader_info *info = &builder->shaders[s]->info; 8137ec681f3Smrg 8147ec681f3Smrg for (unsigned i = 0; i < info->varyings.input_count; i++) { 8157ec681f3Smrg panvk_pipeline_update_varying_slot(&pipeline->varyings, s, 8167ec681f3Smrg &info->varyings.input[i], 8177ec681f3Smrg true); 8187ec681f3Smrg } 8197ec681f3Smrg 8207ec681f3Smrg for (unsigned i = 0; i < info->varyings.output_count; i++) { 8217ec681f3Smrg panvk_pipeline_update_varying_slot(&pipeline->varyings, s, 8227ec681f3Smrg &info->varyings.output[i], 8237ec681f3Smrg false); 8247ec681f3Smrg } 8257ec681f3Smrg } 8267ec681f3Smrg 8277ec681f3Smrg /* TODO: Xfb */ 8287ec681f3Smrg gl_varying_slot loc; 8297ec681f3Smrg BITSET_FOREACH_SET(loc, pipeline->varyings.active, VARYING_SLOT_MAX) { 8307ec681f3Smrg if (pipeline->varyings.varying[loc].format == PIPE_FORMAT_NONE) 8317ec681f3Smrg continue; 8327ec681f3Smrg 8337ec681f3Smrg enum panvk_varying_buf_id buf_id = 8347ec681f3Smrg panvk_varying_buf_id(false, loc); 8357ec681f3Smrg unsigned buf_idx = panvk_varying_buf_index(&pipeline->varyings, buf_id); 8367ec681f3Smrg unsigned varying_sz = panvk_varying_size(&pipeline->varyings, loc); 8377ec681f3Smrg 8387ec681f3Smrg pipeline->varyings.varying[loc].buf = buf_idx; 8397ec681f3Smrg pipeline->varyings.varying[loc].offset = 8407ec681f3Smrg pipeline->varyings.buf[buf_idx].stride; 8417ec681f3Smrg pipeline->varyings.buf[buf_idx].stride += varying_sz; 8427ec681f3Smrg } 8437ec681f3Smrg} 8447ec681f3Smrg 8457ec681f3Smrgstatic void 8467ec681f3Smrgpanvk_pipeline_builder_parse_vertex_input(struct panvk_pipeline_builder *builder, 8477ec681f3Smrg struct panvk_pipeline *pipeline) 8487ec681f3Smrg{ 8497ec681f3Smrg struct panvk_attribs_info *attribs = &pipeline->attribs; 8507ec681f3Smrg const VkPipelineVertexInputStateCreateInfo *info = 8517ec681f3Smrg builder->create_info->pVertexInputState; 8527ec681f3Smrg 8537ec681f3Smrg for (unsigned i = 0; i < info->vertexBindingDescriptionCount; i++) { 8547ec681f3Smrg const VkVertexInputBindingDescription *desc = 8557ec681f3Smrg &info->pVertexBindingDescriptions[i]; 8567ec681f3Smrg attribs->buf_count = MAX2(desc->binding + 1, attribs->buf_count); 8577ec681f3Smrg attribs->buf[desc->binding].stride = desc->stride; 8587ec681f3Smrg attribs->buf[desc->binding].special = false; 8597ec681f3Smrg } 8607ec681f3Smrg 8617ec681f3Smrg for (unsigned i = 0; i < info->vertexAttributeDescriptionCount; i++) { 8627ec681f3Smrg const VkVertexInputAttributeDescription *desc = 8637ec681f3Smrg &info->pVertexAttributeDescriptions[i]; 8647ec681f3Smrg attribs->attrib[desc->location].buf = desc->binding; 8657ec681f3Smrg attribs->attrib[desc->location].format = 8667ec681f3Smrg vk_format_to_pipe_format(desc->format); 8677ec681f3Smrg attribs->attrib[desc->location].offset = desc->offset; 8687ec681f3Smrg } 8697ec681f3Smrg 8707ec681f3Smrg const struct pan_shader_info *vs = 8717ec681f3Smrg &builder->shaders[MESA_SHADER_VERTEX]->info; 8727ec681f3Smrg 8737ec681f3Smrg if (vs->attribute_count >= PAN_VERTEX_ID) { 8747ec681f3Smrg attribs->buf[attribs->buf_count].special = true; 8757ec681f3Smrg attribs->buf[attribs->buf_count].special_id = PAN_VERTEX_ID; 8767ec681f3Smrg attribs->attrib[PAN_VERTEX_ID].buf = attribs->buf_count++; 8777ec681f3Smrg attribs->attrib[PAN_VERTEX_ID].format = PIPE_FORMAT_R32_UINT; 8787ec681f3Smrg } 8797ec681f3Smrg 8807ec681f3Smrg if (vs->attribute_count >= PAN_INSTANCE_ID) { 8817ec681f3Smrg attribs->buf[attribs->buf_count].special = true; 8827ec681f3Smrg attribs->buf[attribs->buf_count].special_id = PAN_INSTANCE_ID; 8837ec681f3Smrg attribs->attrib[PAN_INSTANCE_ID].buf = attribs->buf_count++; 8847ec681f3Smrg attribs->attrib[PAN_INSTANCE_ID].format = PIPE_FORMAT_R32_UINT; 8857ec681f3Smrg } 8867ec681f3Smrg 8877ec681f3Smrg attribs->attrib_count = MAX2(attribs->attrib_count, vs->attribute_count); 8887ec681f3Smrg} 8897ec681f3Smrg 8907ec681f3Smrgstatic VkResult 8917ec681f3Smrgpanvk_pipeline_builder_build(struct panvk_pipeline_builder *builder, 8927ec681f3Smrg struct panvk_pipeline **pipeline) 8937ec681f3Smrg{ 8947ec681f3Smrg VkResult result = panvk_pipeline_builder_create_pipeline(builder, pipeline); 8957ec681f3Smrg if (result != VK_SUCCESS) 8967ec681f3Smrg return result; 8977ec681f3Smrg 8987ec681f3Smrg /* TODO: make those functions return a result and handle errors */ 8997ec681f3Smrg panvk_pipeline_builder_parse_dynamic(builder, *pipeline); 9007ec681f3Smrg panvk_pipeline_builder_parse_color_blend(builder, *pipeline); 9017ec681f3Smrg panvk_pipeline_builder_compile_shaders(builder, *pipeline); 9027ec681f3Smrg panvk_pipeline_builder_collect_varyings(builder, *pipeline); 9037ec681f3Smrg panvk_pipeline_builder_parse_input_assembly(builder, *pipeline); 9047ec681f3Smrg panvk_pipeline_builder_parse_multisample(builder, *pipeline); 9057ec681f3Smrg panvk_pipeline_builder_parse_zs(builder, *pipeline); 9067ec681f3Smrg panvk_pipeline_builder_parse_rast(builder, *pipeline); 9077ec681f3Smrg panvk_pipeline_builder_parse_vertex_input(builder, *pipeline); 9087ec681f3Smrg 9097ec681f3Smrg 9107ec681f3Smrg panvk_pipeline_builder_upload_shaders(builder, *pipeline); 9117ec681f3Smrg panvk_pipeline_builder_init_fs_state(builder, *pipeline); 9127ec681f3Smrg panvk_pipeline_builder_alloc_static_state_bo(builder, *pipeline); 9137ec681f3Smrg panvk_pipeline_builder_init_shaders(builder, *pipeline); 9147ec681f3Smrg panvk_pipeline_builder_parse_viewport(builder, *pipeline); 9157ec681f3Smrg 9167ec681f3Smrg return VK_SUCCESS; 9177ec681f3Smrg} 9187ec681f3Smrg 9197ec681f3Smrgstatic void 9207ec681f3Smrgpanvk_pipeline_builder_init_graphics(struct panvk_pipeline_builder *builder, 9217ec681f3Smrg struct panvk_device *dev, 9227ec681f3Smrg struct panvk_pipeline_cache *cache, 9237ec681f3Smrg const VkGraphicsPipelineCreateInfo *create_info, 9247ec681f3Smrg const VkAllocationCallbacks *alloc) 9257ec681f3Smrg{ 9267ec681f3Smrg VK_FROM_HANDLE(panvk_pipeline_layout, layout, create_info->layout); 9277ec681f3Smrg assert(layout); 9287ec681f3Smrg *builder = (struct panvk_pipeline_builder) { 9297ec681f3Smrg .device = dev, 9307ec681f3Smrg .cache = cache, 9317ec681f3Smrg .layout = layout, 9327ec681f3Smrg .create_info = create_info, 9337ec681f3Smrg .alloc = alloc, 9347ec681f3Smrg }; 9357ec681f3Smrg 9367ec681f3Smrg builder->rasterizer_discard = 9377ec681f3Smrg create_info->pRasterizationState->rasterizerDiscardEnable; 9387ec681f3Smrg 9397ec681f3Smrg if (builder->rasterizer_discard) { 9407ec681f3Smrg builder->samples = VK_SAMPLE_COUNT_1_BIT; 9417ec681f3Smrg } else { 9427ec681f3Smrg builder->samples = create_info->pMultisampleState->rasterizationSamples; 9437ec681f3Smrg 9447ec681f3Smrg const struct panvk_render_pass *pass = panvk_render_pass_from_handle(create_info->renderPass); 9457ec681f3Smrg const struct panvk_subpass *subpass = &pass->subpasses[create_info->subpass]; 9467ec681f3Smrg 9477ec681f3Smrg builder->use_depth_stencil_attachment = 9487ec681f3Smrg subpass->zs_attachment.idx != VK_ATTACHMENT_UNUSED; 9497ec681f3Smrg 9507ec681f3Smrg assert(subpass->color_count <= create_info->pColorBlendState->attachmentCount); 9517ec681f3Smrg builder->active_color_attachments = 0; 9527ec681f3Smrg for (uint32_t i = 0; i < subpass->color_count; i++) { 9537ec681f3Smrg uint32_t idx = subpass->color_attachments[i].idx; 9547ec681f3Smrg if (idx == VK_ATTACHMENT_UNUSED) 9557ec681f3Smrg continue; 9567ec681f3Smrg 9577ec681f3Smrg builder->active_color_attachments |= 1 << i; 9587ec681f3Smrg builder->color_attachment_formats[i] = pass->attachments[idx].format; 9597ec681f3Smrg } 9607ec681f3Smrg } 9617ec681f3Smrg} 9627ec681f3Smrg 9637ec681f3SmrgVkResult 9647ec681f3Smrgpanvk_per_arch(CreateGraphicsPipelines)(VkDevice device, 9657ec681f3Smrg VkPipelineCache pipelineCache, 9667ec681f3Smrg uint32_t count, 9677ec681f3Smrg const VkGraphicsPipelineCreateInfo *pCreateInfos, 9687ec681f3Smrg const VkAllocationCallbacks *pAllocator, 9697ec681f3Smrg VkPipeline *pPipelines) 9707ec681f3Smrg{ 9717ec681f3Smrg VK_FROM_HANDLE(panvk_device, dev, device); 9727ec681f3Smrg VK_FROM_HANDLE(panvk_pipeline_cache, cache, pipelineCache); 9737ec681f3Smrg 9747ec681f3Smrg for (uint32_t i = 0; i < count; i++) { 9757ec681f3Smrg struct panvk_pipeline_builder builder; 9767ec681f3Smrg panvk_pipeline_builder_init_graphics(&builder, dev, cache, 9777ec681f3Smrg &pCreateInfos[i], pAllocator); 9787ec681f3Smrg 9797ec681f3Smrg struct panvk_pipeline *pipeline; 9807ec681f3Smrg VkResult result = panvk_pipeline_builder_build(&builder, &pipeline); 9817ec681f3Smrg panvk_pipeline_builder_finish(&builder); 9827ec681f3Smrg 9837ec681f3Smrg if (result != VK_SUCCESS) { 9847ec681f3Smrg for (uint32_t j = 0; j < i; j++) { 9857ec681f3Smrg panvk_DestroyPipeline(device, pPipelines[j], pAllocator); 9867ec681f3Smrg pPipelines[j] = VK_NULL_HANDLE; 9877ec681f3Smrg } 9887ec681f3Smrg 9897ec681f3Smrg return result; 9907ec681f3Smrg } 9917ec681f3Smrg 9927ec681f3Smrg pPipelines[i] = panvk_pipeline_to_handle(pipeline); 9937ec681f3Smrg } 9947ec681f3Smrg 9957ec681f3Smrg return VK_SUCCESS; 9967ec681f3Smrg} 997