1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright (C) 2021 Collabora Ltd. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21bf215546Sopenharmony_ci * DEALINGS IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "genxml/gen_macros.h" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "util/macros.h" 27bf215546Sopenharmony_ci#include "compiler/shader_enums.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "vk_util.h" 30bf215546Sopenharmony_ci 31bf215546Sopenharmony_ci#include "pan_cs.h" 32bf215546Sopenharmony_ci#include "pan_encoder.h" 33bf215546Sopenharmony_ci#include "pan_pool.h" 34bf215546Sopenharmony_ci#include "pan_shader.h" 35bf215546Sopenharmony_ci#include "pan_earlyzs.h" 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci#include "panvk_cs.h" 38bf215546Sopenharmony_ci#include "panvk_private.h" 39bf215546Sopenharmony_ci#include "panvk_varyings.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#include "vk_sampler.h" 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_cistatic enum mali_mipmap_mode 44bf215546Sopenharmony_cipanvk_translate_sampler_mipmap_mode(VkSamplerMipmapMode mode) 45bf215546Sopenharmony_ci{ 46bf215546Sopenharmony_ci switch (mode) { 47bf215546Sopenharmony_ci case VK_SAMPLER_MIPMAP_MODE_NEAREST: return MALI_MIPMAP_MODE_NEAREST; 48bf215546Sopenharmony_ci case VK_SAMPLER_MIPMAP_MODE_LINEAR: return MALI_MIPMAP_MODE_TRILINEAR; 49bf215546Sopenharmony_ci default: unreachable("Invalid mipmap mode"); 50bf215546Sopenharmony_ci } 51bf215546Sopenharmony_ci} 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_cistatic unsigned 54bf215546Sopenharmony_cipanvk_translate_sampler_address_mode(VkSamplerAddressMode mode) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci switch (mode) { 57bf215546Sopenharmony_ci case VK_SAMPLER_ADDRESS_MODE_REPEAT: return MALI_WRAP_MODE_REPEAT; 58bf215546Sopenharmony_ci case VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT: return MALI_WRAP_MODE_MIRRORED_REPEAT; 59bf215546Sopenharmony_ci case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE: return MALI_WRAP_MODE_CLAMP_TO_EDGE; 60bf215546Sopenharmony_ci case VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER: return MALI_WRAP_MODE_CLAMP_TO_BORDER; 61bf215546Sopenharmony_ci case VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE: return MALI_WRAP_MODE_MIRRORED_CLAMP_TO_EDGE; 62bf215546Sopenharmony_ci default: unreachable("Invalid wrap"); 63bf215546Sopenharmony_ci } 64bf215546Sopenharmony_ci} 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_cistatic mali_pixel_format 67bf215546Sopenharmony_cipanvk_varying_hw_format(const struct panvk_device *dev, 68bf215546Sopenharmony_ci const struct panvk_varyings_info *varyings, 69bf215546Sopenharmony_ci gl_shader_stage stage, unsigned idx) 70bf215546Sopenharmony_ci{ 71bf215546Sopenharmony_ci const struct panfrost_device *pdev = &dev->physical_device->pdev; 72bf215546Sopenharmony_ci gl_varying_slot loc = varyings->stage[stage].loc[idx]; 73bf215546Sopenharmony_ci 74bf215546Sopenharmony_ci switch (loc) { 75bf215546Sopenharmony_ci case VARYING_SLOT_PNTC: 76bf215546Sopenharmony_ci case VARYING_SLOT_PSIZ: 77bf215546Sopenharmony_ci#if PAN_ARCH <= 6 78bf215546Sopenharmony_ci return (MALI_R16F << 12) | panfrost_get_default_swizzle(1); 79bf215546Sopenharmony_ci#else 80bf215546Sopenharmony_ci return (MALI_R16F << 12) | MALI_RGB_COMPONENT_ORDER_R000; 81bf215546Sopenharmony_ci#endif 82bf215546Sopenharmony_ci case VARYING_SLOT_POS: 83bf215546Sopenharmony_ci#if PAN_ARCH <= 6 84bf215546Sopenharmony_ci return (MALI_SNAP_4 << 12) | panfrost_get_default_swizzle(4); 85bf215546Sopenharmony_ci#else 86bf215546Sopenharmony_ci return (MALI_SNAP_4 << 12) | MALI_RGB_COMPONENT_ORDER_RGBA; 87bf215546Sopenharmony_ci#endif 88bf215546Sopenharmony_ci default: 89bf215546Sopenharmony_ci if (varyings->varying[loc].format != PIPE_FORMAT_NONE) 90bf215546Sopenharmony_ci return pdev->formats[varyings->varying[loc].format].hw; 91bf215546Sopenharmony_ci#if PAN_ARCH >= 7 92bf215546Sopenharmony_ci return (MALI_CONSTANT << 12) | MALI_RGB_COMPONENT_ORDER_0000; 93bf215546Sopenharmony_ci#else 94bf215546Sopenharmony_ci return (MALI_CONSTANT << 12) | PAN_V6_SWIZZLE(0, 0, 0, 0); 95bf215546Sopenharmony_ci#endif 96bf215546Sopenharmony_ci } 97bf215546Sopenharmony_ci} 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_cistatic void 100bf215546Sopenharmony_cipanvk_emit_varying(const struct panvk_device *dev, 101bf215546Sopenharmony_ci const struct panvk_varyings_info *varyings, 102bf215546Sopenharmony_ci gl_shader_stage stage, unsigned idx, 103bf215546Sopenharmony_ci void *attrib) 104bf215546Sopenharmony_ci{ 105bf215546Sopenharmony_ci gl_varying_slot loc = varyings->stage[stage].loc[idx]; 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci pan_pack(attrib, ATTRIBUTE, cfg) { 108bf215546Sopenharmony_ci cfg.buffer_index = varyings->varying[loc].buf; 109bf215546Sopenharmony_ci cfg.offset = varyings->varying[loc].offset; 110bf215546Sopenharmony_ci cfg.format = panvk_varying_hw_format(dev, varyings, stage, idx); 111bf215546Sopenharmony_ci } 112bf215546Sopenharmony_ci} 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_civoid 115bf215546Sopenharmony_cipanvk_per_arch(emit_varyings)(const struct panvk_device *dev, 116bf215546Sopenharmony_ci const struct panvk_varyings_info *varyings, 117bf215546Sopenharmony_ci gl_shader_stage stage, 118bf215546Sopenharmony_ci void *descs) 119bf215546Sopenharmony_ci{ 120bf215546Sopenharmony_ci struct mali_attribute_packed *attrib = descs; 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci for (unsigned i = 0; i < varyings->stage[stage].count; i++) 123bf215546Sopenharmony_ci panvk_emit_varying(dev, varyings, stage, i, attrib++); 124bf215546Sopenharmony_ci} 125bf215546Sopenharmony_ci 126bf215546Sopenharmony_cistatic void 127bf215546Sopenharmony_cipanvk_emit_varying_buf(const struct panvk_varyings_info *varyings, 128bf215546Sopenharmony_ci enum panvk_varying_buf_id id, void *buf) 129bf215546Sopenharmony_ci{ 130bf215546Sopenharmony_ci unsigned buf_idx = panvk_varying_buf_index(varyings, id); 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci pan_pack(buf, ATTRIBUTE_BUFFER, cfg) { 133bf215546Sopenharmony_ci unsigned offset = varyings->buf[buf_idx].address & 63; 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci cfg.stride = varyings->buf[buf_idx].stride; 136bf215546Sopenharmony_ci cfg.size = varyings->buf[buf_idx].size + offset; 137bf215546Sopenharmony_ci cfg.pointer = varyings->buf[buf_idx].address & ~63ULL; 138bf215546Sopenharmony_ci } 139bf215546Sopenharmony_ci} 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_civoid 142bf215546Sopenharmony_cipanvk_per_arch(emit_varying_bufs)(const struct panvk_varyings_info *varyings, 143bf215546Sopenharmony_ci void *descs) 144bf215546Sopenharmony_ci{ 145bf215546Sopenharmony_ci struct mali_attribute_buffer_packed *buf = descs; 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci for (unsigned i = 0; i < PANVK_VARY_BUF_MAX; i++) { 148bf215546Sopenharmony_ci if (varyings->buf_mask & (1 << i)) 149bf215546Sopenharmony_ci panvk_emit_varying_buf(varyings, i, buf++); 150bf215546Sopenharmony_ci } 151bf215546Sopenharmony_ci} 152bf215546Sopenharmony_ci 153bf215546Sopenharmony_cistatic void 154bf215546Sopenharmony_cipanvk_emit_attrib_buf(const struct panvk_attribs_info *info, 155bf215546Sopenharmony_ci const struct panvk_draw_info *draw, 156bf215546Sopenharmony_ci const struct panvk_attrib_buf *bufs, 157bf215546Sopenharmony_ci unsigned buf_count, 158bf215546Sopenharmony_ci unsigned idx, void *desc) 159bf215546Sopenharmony_ci{ 160bf215546Sopenharmony_ci const struct panvk_attrib_buf_info *buf_info = &info->buf[idx]; 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci assert(idx < buf_count); 163bf215546Sopenharmony_ci const struct panvk_attrib_buf *buf = &bufs[idx]; 164bf215546Sopenharmony_ci mali_ptr addr = buf->address & ~63ULL; 165bf215546Sopenharmony_ci unsigned size = buf->size + (buf->address & 63); 166bf215546Sopenharmony_ci unsigned divisor = 167bf215546Sopenharmony_ci draw->padded_vertex_count * buf_info->instance_divisor; 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci /* TODO: support instanced arrays */ 170bf215546Sopenharmony_ci if (draw->instance_count <= 1) { 171bf215546Sopenharmony_ci pan_pack(desc, ATTRIBUTE_BUFFER, cfg) { 172bf215546Sopenharmony_ci cfg.type = MALI_ATTRIBUTE_TYPE_1D; 173bf215546Sopenharmony_ci cfg.stride = buf_info->per_instance ? 0 : buf_info->stride; 174bf215546Sopenharmony_ci cfg.pointer = addr; 175bf215546Sopenharmony_ci cfg.size = size; 176bf215546Sopenharmony_ci } 177bf215546Sopenharmony_ci } else if (!buf_info->per_instance) { 178bf215546Sopenharmony_ci pan_pack(desc, ATTRIBUTE_BUFFER, cfg) { 179bf215546Sopenharmony_ci cfg.type = MALI_ATTRIBUTE_TYPE_1D_MODULUS; 180bf215546Sopenharmony_ci cfg.divisor = draw->padded_vertex_count; 181bf215546Sopenharmony_ci cfg.stride = buf_info->stride; 182bf215546Sopenharmony_ci cfg.pointer = addr; 183bf215546Sopenharmony_ci cfg.size = size; 184bf215546Sopenharmony_ci } 185bf215546Sopenharmony_ci } else if (!divisor) { 186bf215546Sopenharmony_ci /* instance_divisor == 0 means all instances share the same value. 187bf215546Sopenharmony_ci * Make it a 1D array with a zero stride. 188bf215546Sopenharmony_ci */ 189bf215546Sopenharmony_ci pan_pack(desc, ATTRIBUTE_BUFFER, cfg) { 190bf215546Sopenharmony_ci cfg.type = MALI_ATTRIBUTE_TYPE_1D; 191bf215546Sopenharmony_ci cfg.stride = 0; 192bf215546Sopenharmony_ci cfg.pointer = addr; 193bf215546Sopenharmony_ci cfg.size = size; 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci } else if (util_is_power_of_two_or_zero(divisor)) { 196bf215546Sopenharmony_ci pan_pack(desc, ATTRIBUTE_BUFFER, cfg) { 197bf215546Sopenharmony_ci cfg.type = MALI_ATTRIBUTE_TYPE_1D_POT_DIVISOR; 198bf215546Sopenharmony_ci cfg.stride = buf_info->stride; 199bf215546Sopenharmony_ci cfg.pointer = addr; 200bf215546Sopenharmony_ci cfg.size = size; 201bf215546Sopenharmony_ci cfg.divisor_r = __builtin_ctz(divisor); 202bf215546Sopenharmony_ci } 203bf215546Sopenharmony_ci } else { 204bf215546Sopenharmony_ci unsigned divisor_r = 0, divisor_e = 0; 205bf215546Sopenharmony_ci unsigned divisor_num = 206bf215546Sopenharmony_ci panfrost_compute_magic_divisor(divisor, &divisor_r, &divisor_e); 207bf215546Sopenharmony_ci pan_pack(desc, ATTRIBUTE_BUFFER, cfg) { 208bf215546Sopenharmony_ci cfg.type = MALI_ATTRIBUTE_TYPE_1D_NPOT_DIVISOR; 209bf215546Sopenharmony_ci cfg.stride = buf_info->stride; 210bf215546Sopenharmony_ci cfg.pointer = addr; 211bf215546Sopenharmony_ci cfg.size = size; 212bf215546Sopenharmony_ci cfg.divisor_r = divisor_r; 213bf215546Sopenharmony_ci cfg.divisor_e = divisor_e; 214bf215546Sopenharmony_ci } 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci desc += pan_size(ATTRIBUTE_BUFFER); 217bf215546Sopenharmony_ci pan_pack(desc, ATTRIBUTE_BUFFER_CONTINUATION_NPOT, cfg) { 218bf215546Sopenharmony_ci cfg.divisor_numerator = divisor_num; 219bf215546Sopenharmony_ci cfg.divisor = buf_info->instance_divisor; 220bf215546Sopenharmony_ci } 221bf215546Sopenharmony_ci } 222bf215546Sopenharmony_ci} 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_civoid 225bf215546Sopenharmony_cipanvk_per_arch(emit_attrib_bufs)(const struct panvk_attribs_info *info, 226bf215546Sopenharmony_ci const struct panvk_attrib_buf *bufs, 227bf215546Sopenharmony_ci unsigned buf_count, 228bf215546Sopenharmony_ci const struct panvk_draw_info *draw, 229bf215546Sopenharmony_ci void *descs) 230bf215546Sopenharmony_ci{ 231bf215546Sopenharmony_ci struct mali_attribute_buffer_packed *buf = descs; 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci for (unsigned i = 0; i < info->buf_count; i++) { 234bf215546Sopenharmony_ci panvk_emit_attrib_buf(info, draw, bufs, buf_count, i, buf); 235bf215546Sopenharmony_ci buf += 2; 236bf215546Sopenharmony_ci } 237bf215546Sopenharmony_ci} 238bf215546Sopenharmony_ci 239bf215546Sopenharmony_civoid 240bf215546Sopenharmony_cipanvk_per_arch(emit_sampler)(const VkSamplerCreateInfo *pCreateInfo, 241bf215546Sopenharmony_ci void *desc) 242bf215546Sopenharmony_ci{ 243bf215546Sopenharmony_ci VkClearColorValue border_color = 244bf215546Sopenharmony_ci vk_sampler_border_color_value(pCreateInfo, NULL); 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci pan_pack(desc, SAMPLER, cfg) { 247bf215546Sopenharmony_ci cfg.magnify_nearest = pCreateInfo->magFilter == VK_FILTER_NEAREST; 248bf215546Sopenharmony_ci cfg.minify_nearest = pCreateInfo->minFilter == VK_FILTER_NEAREST; 249bf215546Sopenharmony_ci cfg.mipmap_mode = panvk_translate_sampler_mipmap_mode(pCreateInfo->mipmapMode); 250bf215546Sopenharmony_ci cfg.normalized_coordinates = !pCreateInfo->unnormalizedCoordinates; 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci cfg.lod_bias = FIXED_16(pCreateInfo->mipLodBias, true); 253bf215546Sopenharmony_ci cfg.minimum_lod = FIXED_16(pCreateInfo->minLod, false); 254bf215546Sopenharmony_ci cfg.maximum_lod = FIXED_16(pCreateInfo->maxLod, false); 255bf215546Sopenharmony_ci cfg.wrap_mode_s = panvk_translate_sampler_address_mode(pCreateInfo->addressModeU); 256bf215546Sopenharmony_ci cfg.wrap_mode_t = panvk_translate_sampler_address_mode(pCreateInfo->addressModeV); 257bf215546Sopenharmony_ci cfg.wrap_mode_r = panvk_translate_sampler_address_mode(pCreateInfo->addressModeW); 258bf215546Sopenharmony_ci cfg.compare_function = panvk_per_arch(translate_sampler_compare_func)(pCreateInfo); 259bf215546Sopenharmony_ci cfg.border_color_r = border_color.uint32[0]; 260bf215546Sopenharmony_ci cfg.border_color_g = border_color.uint32[1]; 261bf215546Sopenharmony_ci cfg.border_color_b = border_color.uint32[2]; 262bf215546Sopenharmony_ci cfg.border_color_a = border_color.uint32[3]; 263bf215546Sopenharmony_ci } 264bf215546Sopenharmony_ci} 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_cistatic void 267bf215546Sopenharmony_cipanvk_emit_attrib(const struct panvk_device *dev, 268bf215546Sopenharmony_ci const struct panvk_draw_info *draw, 269bf215546Sopenharmony_ci const struct panvk_attribs_info *attribs, 270bf215546Sopenharmony_ci const struct panvk_attrib_buf *bufs, 271bf215546Sopenharmony_ci unsigned buf_count, 272bf215546Sopenharmony_ci unsigned idx, void *attrib) 273bf215546Sopenharmony_ci{ 274bf215546Sopenharmony_ci const struct panfrost_device *pdev = &dev->physical_device->pdev; 275bf215546Sopenharmony_ci unsigned buf_idx = attribs->attrib[idx].buf; 276bf215546Sopenharmony_ci const struct panvk_attrib_buf_info *buf_info = &attribs->buf[buf_idx]; 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci pan_pack(attrib, ATTRIBUTE, cfg) { 279bf215546Sopenharmony_ci cfg.buffer_index = buf_idx * 2; 280bf215546Sopenharmony_ci cfg.offset = attribs->attrib[idx].offset + 281bf215546Sopenharmony_ci (bufs[buf_idx].address & 63); 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci if (buf_info->per_instance) 284bf215546Sopenharmony_ci cfg.offset += draw->first_instance * buf_info->stride; 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci cfg.format = pdev->formats[attribs->attrib[idx].format].hw; 287bf215546Sopenharmony_ci } 288bf215546Sopenharmony_ci} 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_civoid 291bf215546Sopenharmony_cipanvk_per_arch(emit_attribs)(const struct panvk_device *dev, 292bf215546Sopenharmony_ci const struct panvk_draw_info *draw, 293bf215546Sopenharmony_ci const struct panvk_attribs_info *attribs, 294bf215546Sopenharmony_ci const struct panvk_attrib_buf *bufs, 295bf215546Sopenharmony_ci unsigned buf_count, 296bf215546Sopenharmony_ci void *descs) 297bf215546Sopenharmony_ci{ 298bf215546Sopenharmony_ci struct mali_attribute_packed *attrib = descs; 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_ci for (unsigned i = 0; i < attribs->attrib_count; i++) 301bf215546Sopenharmony_ci panvk_emit_attrib(dev, draw, attribs, bufs, buf_count, i, attrib++); 302bf215546Sopenharmony_ci} 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_civoid 305bf215546Sopenharmony_cipanvk_per_arch(emit_ubo)(mali_ptr address, size_t size, void *desc) 306bf215546Sopenharmony_ci{ 307bf215546Sopenharmony_ci pan_pack(desc, UNIFORM_BUFFER, cfg) { 308bf215546Sopenharmony_ci cfg.pointer = address; 309bf215546Sopenharmony_ci cfg.entries = DIV_ROUND_UP(size, 16); 310bf215546Sopenharmony_ci } 311bf215546Sopenharmony_ci} 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_civoid 314bf215546Sopenharmony_cipanvk_per_arch(emit_ubos)(const struct panvk_pipeline *pipeline, 315bf215546Sopenharmony_ci const struct panvk_descriptor_state *state, 316bf215546Sopenharmony_ci void *descs) 317bf215546Sopenharmony_ci{ 318bf215546Sopenharmony_ci struct mali_uniform_buffer_packed *ubos = descs; 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci panvk_per_arch(emit_ubo)(state->sysvals_ptr, 321bf215546Sopenharmony_ci sizeof(state->sysvals), 322bf215546Sopenharmony_ci &ubos[PANVK_SYSVAL_UBO_INDEX]); 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci if (pipeline->layout->push_constants.size) { 325bf215546Sopenharmony_ci panvk_per_arch(emit_ubo)(state->push_constants, 326bf215546Sopenharmony_ci ALIGN_POT(pipeline->layout->push_constants.size, 16), 327bf215546Sopenharmony_ci &ubos[PANVK_PUSH_CONST_UBO_INDEX]); 328bf215546Sopenharmony_ci } else { 329bf215546Sopenharmony_ci memset(&ubos[PANVK_PUSH_CONST_UBO_INDEX], 0, sizeof(*ubos)); 330bf215546Sopenharmony_ci } 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci for (unsigned s = 0; s < pipeline->layout->vk.set_count; s++) { 333bf215546Sopenharmony_ci const struct panvk_descriptor_set_layout *set_layout = 334bf215546Sopenharmony_ci vk_to_panvk_descriptor_set_layout(pipeline->layout->vk.set_layouts[s]); 335bf215546Sopenharmony_ci const struct panvk_descriptor_set *set = state->sets[s]; 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci unsigned ubo_start = 338bf215546Sopenharmony_ci panvk_pipeline_layout_ubo_start(pipeline->layout, s, false); 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_ci if (!set) { 341bf215546Sopenharmony_ci unsigned all_ubos = set_layout->num_ubos + set_layout->num_dyn_ubos; 342bf215546Sopenharmony_ci memset(&ubos[ubo_start], 0, all_ubos * sizeof(*ubos)); 343bf215546Sopenharmony_ci } else { 344bf215546Sopenharmony_ci memcpy(&ubos[ubo_start], set->ubos, 345bf215546Sopenharmony_ci set_layout->num_ubos * sizeof(*ubos)); 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci unsigned dyn_ubo_start = 348bf215546Sopenharmony_ci panvk_pipeline_layout_ubo_start(pipeline->layout, s, true); 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci for (unsigned i = 0; i < set_layout->num_dyn_ubos; i++) { 351bf215546Sopenharmony_ci const struct panvk_buffer_desc *bdesc = 352bf215546Sopenharmony_ci &state->dyn.ubos[pipeline->layout->sets[s].dyn_ubo_offset + i]; 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci mali_ptr address = panvk_buffer_gpu_ptr(bdesc->buffer, 355bf215546Sopenharmony_ci bdesc->offset); 356bf215546Sopenharmony_ci size_t size = panvk_buffer_range(bdesc->buffer, 357bf215546Sopenharmony_ci bdesc->offset, bdesc->size); 358bf215546Sopenharmony_ci if (size) { 359bf215546Sopenharmony_ci panvk_per_arch(emit_ubo)(address, size, 360bf215546Sopenharmony_ci &ubos[dyn_ubo_start + i]); 361bf215546Sopenharmony_ci } else { 362bf215546Sopenharmony_ci memset(&ubos[dyn_ubo_start + i], 0, sizeof(*ubos)); 363bf215546Sopenharmony_ci } 364bf215546Sopenharmony_ci } 365bf215546Sopenharmony_ci } 366bf215546Sopenharmony_ci } 367bf215546Sopenharmony_ci} 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_civoid 370bf215546Sopenharmony_cipanvk_per_arch(emit_vertex_job)(const struct panvk_pipeline *pipeline, 371bf215546Sopenharmony_ci const struct panvk_draw_info *draw, 372bf215546Sopenharmony_ci void *job) 373bf215546Sopenharmony_ci{ 374bf215546Sopenharmony_ci void *section = pan_section_ptr(job, COMPUTE_JOB, INVOCATION); 375bf215546Sopenharmony_ci 376bf215546Sopenharmony_ci memcpy(section, &draw->invocation, pan_size(INVOCATION)); 377bf215546Sopenharmony_ci 378bf215546Sopenharmony_ci pan_section_pack(job, COMPUTE_JOB, PARAMETERS, cfg) { 379bf215546Sopenharmony_ci cfg.job_task_split = 5; 380bf215546Sopenharmony_ci } 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci pan_section_pack(job, COMPUTE_JOB, DRAW, cfg) { 383bf215546Sopenharmony_ci cfg.state = pipeline->rsds[MESA_SHADER_VERTEX]; 384bf215546Sopenharmony_ci cfg.attributes = draw->stages[MESA_SHADER_VERTEX].attributes; 385bf215546Sopenharmony_ci cfg.attribute_buffers = draw->stages[MESA_SHADER_VERTEX].attribute_bufs; 386bf215546Sopenharmony_ci cfg.varyings = draw->stages[MESA_SHADER_VERTEX].varyings; 387bf215546Sopenharmony_ci cfg.varying_buffers = draw->varying_bufs; 388bf215546Sopenharmony_ci cfg.thread_storage = draw->tls; 389bf215546Sopenharmony_ci cfg.offset_start = draw->offset_start; 390bf215546Sopenharmony_ci cfg.instance_size = draw->instance_count > 1 ? 391bf215546Sopenharmony_ci draw->padded_vertex_count : 1; 392bf215546Sopenharmony_ci cfg.uniform_buffers = draw->ubos; 393bf215546Sopenharmony_ci cfg.push_uniforms = draw->stages[PIPE_SHADER_VERTEX].push_constants; 394bf215546Sopenharmony_ci cfg.textures = draw->textures; 395bf215546Sopenharmony_ci cfg.samplers = draw->samplers; 396bf215546Sopenharmony_ci } 397bf215546Sopenharmony_ci} 398bf215546Sopenharmony_ci 399bf215546Sopenharmony_civoid 400bf215546Sopenharmony_cipanvk_per_arch(emit_compute_job)(const struct panvk_pipeline *pipeline, 401bf215546Sopenharmony_ci const struct panvk_dispatch_info *dispatch, 402bf215546Sopenharmony_ci void *job) 403bf215546Sopenharmony_ci{ 404bf215546Sopenharmony_ci panfrost_pack_work_groups_compute(pan_section_ptr(job, COMPUTE_JOB, INVOCATION), 405bf215546Sopenharmony_ci dispatch->wg_count.x, 406bf215546Sopenharmony_ci dispatch->wg_count.y, 407bf215546Sopenharmony_ci dispatch->wg_count.z, 408bf215546Sopenharmony_ci pipeline->cs.local_size.x, 409bf215546Sopenharmony_ci pipeline->cs.local_size.y, 410bf215546Sopenharmony_ci pipeline->cs.local_size.z, 411bf215546Sopenharmony_ci false, false); 412bf215546Sopenharmony_ci 413bf215546Sopenharmony_ci pan_section_pack(job, COMPUTE_JOB, PARAMETERS, cfg) { 414bf215546Sopenharmony_ci cfg.job_task_split = 415bf215546Sopenharmony_ci util_logbase2_ceil(pipeline->cs.local_size.x + 1) + 416bf215546Sopenharmony_ci util_logbase2_ceil(pipeline->cs.local_size.y + 1) + 417bf215546Sopenharmony_ci util_logbase2_ceil(pipeline->cs.local_size.z + 1); 418bf215546Sopenharmony_ci } 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_ci pan_section_pack(job, COMPUTE_JOB, DRAW, cfg) { 421bf215546Sopenharmony_ci cfg.state = pipeline->rsds[MESA_SHADER_COMPUTE]; 422bf215546Sopenharmony_ci cfg.attributes = dispatch->attributes; 423bf215546Sopenharmony_ci cfg.attribute_buffers = dispatch->attribute_bufs; 424bf215546Sopenharmony_ci cfg.thread_storage = dispatch->tsd; 425bf215546Sopenharmony_ci cfg.uniform_buffers = dispatch->ubos; 426bf215546Sopenharmony_ci cfg.push_uniforms = dispatch->push_uniforms; 427bf215546Sopenharmony_ci cfg.textures = dispatch->textures; 428bf215546Sopenharmony_ci cfg.samplers = dispatch->samplers; 429bf215546Sopenharmony_ci } 430bf215546Sopenharmony_ci} 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_cistatic void 433bf215546Sopenharmony_cipanvk_emit_tiler_primitive(const struct panvk_pipeline *pipeline, 434bf215546Sopenharmony_ci const struct panvk_draw_info *draw, 435bf215546Sopenharmony_ci void *prim) 436bf215546Sopenharmony_ci{ 437bf215546Sopenharmony_ci pan_pack(prim, PRIMITIVE, cfg) { 438bf215546Sopenharmony_ci cfg.draw_mode = pipeline->ia.topology; 439bf215546Sopenharmony_ci if (pipeline->ia.writes_point_size) 440bf215546Sopenharmony_ci cfg.point_size_array_format = MALI_POINT_SIZE_ARRAY_FORMAT_FP16; 441bf215546Sopenharmony_ci 442bf215546Sopenharmony_ci cfg.first_provoking_vertex = true; 443bf215546Sopenharmony_ci if (pipeline->ia.primitive_restart) 444bf215546Sopenharmony_ci cfg.primitive_restart = MALI_PRIMITIVE_RESTART_IMPLICIT; 445bf215546Sopenharmony_ci cfg.job_task_split = 6; 446bf215546Sopenharmony_ci 447bf215546Sopenharmony_ci if (draw->index_size) { 448bf215546Sopenharmony_ci cfg.index_count = draw->index_count; 449bf215546Sopenharmony_ci cfg.indices = draw->indices; 450bf215546Sopenharmony_ci cfg.base_vertex_offset = draw->vertex_offset - draw->offset_start; 451bf215546Sopenharmony_ci 452bf215546Sopenharmony_ci switch (draw->index_size) { 453bf215546Sopenharmony_ci case 32: cfg.index_type = MALI_INDEX_TYPE_UINT32; break; 454bf215546Sopenharmony_ci case 16: cfg.index_type = MALI_INDEX_TYPE_UINT16; break; 455bf215546Sopenharmony_ci case 8: cfg.index_type = MALI_INDEX_TYPE_UINT8; break; 456bf215546Sopenharmony_ci default: unreachable("Invalid index size"); 457bf215546Sopenharmony_ci } 458bf215546Sopenharmony_ci } else { 459bf215546Sopenharmony_ci cfg.index_count = draw->vertex_count; 460bf215546Sopenharmony_ci cfg.index_type = MALI_INDEX_TYPE_NONE; 461bf215546Sopenharmony_ci } 462bf215546Sopenharmony_ci } 463bf215546Sopenharmony_ci} 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_cistatic void 466bf215546Sopenharmony_cipanvk_emit_tiler_primitive_size(const struct panvk_pipeline *pipeline, 467bf215546Sopenharmony_ci const struct panvk_draw_info *draw, 468bf215546Sopenharmony_ci void *primsz) 469bf215546Sopenharmony_ci{ 470bf215546Sopenharmony_ci pan_pack(primsz, PRIMITIVE_SIZE, cfg) { 471bf215546Sopenharmony_ci if (pipeline->ia.writes_point_size) { 472bf215546Sopenharmony_ci cfg.size_array = draw->psiz; 473bf215546Sopenharmony_ci } else { 474bf215546Sopenharmony_ci cfg.constant = draw->line_width; 475bf215546Sopenharmony_ci } 476bf215546Sopenharmony_ci } 477bf215546Sopenharmony_ci} 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_cistatic void 480bf215546Sopenharmony_cipanvk_emit_tiler_dcd(const struct panvk_pipeline *pipeline, 481bf215546Sopenharmony_ci const struct panvk_draw_info *draw, 482bf215546Sopenharmony_ci void *dcd) 483bf215546Sopenharmony_ci{ 484bf215546Sopenharmony_ci pan_pack(dcd, DRAW, cfg) { 485bf215546Sopenharmony_ci cfg.front_face_ccw = pipeline->rast.front_ccw; 486bf215546Sopenharmony_ci cfg.cull_front_face = pipeline->rast.cull_front_face; 487bf215546Sopenharmony_ci cfg.cull_back_face = pipeline->rast.cull_back_face; 488bf215546Sopenharmony_ci cfg.position = draw->position; 489bf215546Sopenharmony_ci cfg.state = draw->fs_rsd; 490bf215546Sopenharmony_ci cfg.attributes = draw->stages[MESA_SHADER_FRAGMENT].attributes; 491bf215546Sopenharmony_ci cfg.attribute_buffers = draw->stages[MESA_SHADER_FRAGMENT].attribute_bufs; 492bf215546Sopenharmony_ci cfg.viewport = draw->viewport; 493bf215546Sopenharmony_ci cfg.varyings = draw->stages[MESA_SHADER_FRAGMENT].varyings; 494bf215546Sopenharmony_ci cfg.varying_buffers = cfg.varyings ? draw->varying_bufs : 0; 495bf215546Sopenharmony_ci cfg.thread_storage = draw->tls; 496bf215546Sopenharmony_ci 497bf215546Sopenharmony_ci /* For all primitives but lines DRAW.flat_shading_vertex must 498bf215546Sopenharmony_ci * be set to 0 and the provoking vertex is selected with the 499bf215546Sopenharmony_ci * PRIMITIVE.first_provoking_vertex field. 500bf215546Sopenharmony_ci */ 501bf215546Sopenharmony_ci if (pipeline->ia.topology == MALI_DRAW_MODE_LINES || 502bf215546Sopenharmony_ci pipeline->ia.topology == MALI_DRAW_MODE_LINE_STRIP || 503bf215546Sopenharmony_ci pipeline->ia.topology == MALI_DRAW_MODE_LINE_LOOP) { 504bf215546Sopenharmony_ci cfg.flat_shading_vertex = true; 505bf215546Sopenharmony_ci } 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci cfg.offset_start = draw->offset_start; 508bf215546Sopenharmony_ci cfg.instance_size = draw->instance_count > 1 ? 509bf215546Sopenharmony_ci draw->padded_vertex_count : 1; 510bf215546Sopenharmony_ci cfg.uniform_buffers = draw->ubos; 511bf215546Sopenharmony_ci cfg.push_uniforms = draw->stages[PIPE_SHADER_FRAGMENT].push_constants; 512bf215546Sopenharmony_ci cfg.textures = draw->textures; 513bf215546Sopenharmony_ci cfg.samplers = draw->samplers; 514bf215546Sopenharmony_ci 515bf215546Sopenharmony_ci /* TODO: occlusion queries */ 516bf215546Sopenharmony_ci } 517bf215546Sopenharmony_ci} 518bf215546Sopenharmony_ci 519bf215546Sopenharmony_civoid 520bf215546Sopenharmony_cipanvk_per_arch(emit_tiler_job)(const struct panvk_pipeline *pipeline, 521bf215546Sopenharmony_ci const struct panvk_draw_info *draw, 522bf215546Sopenharmony_ci void *job) 523bf215546Sopenharmony_ci{ 524bf215546Sopenharmony_ci void *section; 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci section = pan_section_ptr(job, TILER_JOB, INVOCATION); 527bf215546Sopenharmony_ci memcpy(section, &draw->invocation, pan_size(INVOCATION)); 528bf215546Sopenharmony_ci 529bf215546Sopenharmony_ci section = pan_section_ptr(job, TILER_JOB, PRIMITIVE); 530bf215546Sopenharmony_ci panvk_emit_tiler_primitive(pipeline, draw, section); 531bf215546Sopenharmony_ci 532bf215546Sopenharmony_ci section = pan_section_ptr(job, TILER_JOB, PRIMITIVE_SIZE); 533bf215546Sopenharmony_ci panvk_emit_tiler_primitive_size(pipeline, draw, section); 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci section = pan_section_ptr(job, TILER_JOB, DRAW); 536bf215546Sopenharmony_ci panvk_emit_tiler_dcd(pipeline, draw, section); 537bf215546Sopenharmony_ci 538bf215546Sopenharmony_ci pan_section_pack(job, TILER_JOB, TILER, cfg) { 539bf215546Sopenharmony_ci cfg.address = draw->tiler_ctx->bifrost; 540bf215546Sopenharmony_ci } 541bf215546Sopenharmony_ci pan_section_pack(job, TILER_JOB, PADDING, padding); 542bf215546Sopenharmony_ci} 543bf215546Sopenharmony_ci 544bf215546Sopenharmony_civoid 545bf215546Sopenharmony_cipanvk_per_arch(emit_viewport)(const VkViewport *viewport, 546bf215546Sopenharmony_ci const VkRect2D *scissor, 547bf215546Sopenharmony_ci void *vpd) 548bf215546Sopenharmony_ci{ 549bf215546Sopenharmony_ci /* The spec says "width must be greater than 0.0" */ 550bf215546Sopenharmony_ci assert(viewport->x >= 0); 551bf215546Sopenharmony_ci int minx = (int)viewport->x; 552bf215546Sopenharmony_ci int maxx = (int)(viewport->x + viewport->width); 553bf215546Sopenharmony_ci 554bf215546Sopenharmony_ci /* Viewport height can be negative */ 555bf215546Sopenharmony_ci int miny = MIN2((int)viewport->y, (int)(viewport->y + viewport->height)); 556bf215546Sopenharmony_ci int maxy = MAX2((int)viewport->y, (int)(viewport->y + viewport->height)); 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci assert(scissor->offset.x >= 0 && scissor->offset.y >= 0); 559bf215546Sopenharmony_ci miny = MAX2(scissor->offset.x, minx); 560bf215546Sopenharmony_ci miny = MAX2(scissor->offset.y, miny); 561bf215546Sopenharmony_ci maxx = MIN2(scissor->offset.x + scissor->extent.width, maxx); 562bf215546Sopenharmony_ci maxy = MIN2(scissor->offset.y + scissor->extent.height, maxy); 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci /* Make sure we don't end up with a max < min when width/height is 0 */ 565bf215546Sopenharmony_ci maxx = maxx > minx ? maxx - 1 : maxx; 566bf215546Sopenharmony_ci maxy = maxy > miny ? maxy - 1 : maxy; 567bf215546Sopenharmony_ci 568bf215546Sopenharmony_ci assert(viewport->minDepth >= 0.0f && viewport->minDepth <= 1.0f); 569bf215546Sopenharmony_ci assert(viewport->maxDepth >= 0.0f && viewport->maxDepth <= 1.0f); 570bf215546Sopenharmony_ci 571bf215546Sopenharmony_ci pan_pack(vpd, VIEWPORT, cfg) { 572bf215546Sopenharmony_ci cfg.scissor_minimum_x = minx; 573bf215546Sopenharmony_ci cfg.scissor_minimum_y = miny; 574bf215546Sopenharmony_ci cfg.scissor_maximum_x = maxx; 575bf215546Sopenharmony_ci cfg.scissor_maximum_y = maxy; 576bf215546Sopenharmony_ci cfg.minimum_z = MIN2(viewport->minDepth, viewport->maxDepth); 577bf215546Sopenharmony_ci cfg.maximum_z = MAX2(viewport->minDepth, viewport->maxDepth); 578bf215546Sopenharmony_ci } 579bf215546Sopenharmony_ci} 580bf215546Sopenharmony_ci 581bf215546Sopenharmony_cistatic enum mali_register_file_format 582bf215546Sopenharmony_cibifrost_blend_type_from_nir(nir_alu_type nir_type) 583bf215546Sopenharmony_ci{ 584bf215546Sopenharmony_ci switch(nir_type) { 585bf215546Sopenharmony_ci case 0: /* Render target not in use */ 586bf215546Sopenharmony_ci return 0; 587bf215546Sopenharmony_ci case nir_type_float16: 588bf215546Sopenharmony_ci return MALI_REGISTER_FILE_FORMAT_F16; 589bf215546Sopenharmony_ci case nir_type_float32: 590bf215546Sopenharmony_ci return MALI_REGISTER_FILE_FORMAT_F32; 591bf215546Sopenharmony_ci case nir_type_int32: 592bf215546Sopenharmony_ci return MALI_REGISTER_FILE_FORMAT_I32; 593bf215546Sopenharmony_ci case nir_type_uint32: 594bf215546Sopenharmony_ci return MALI_REGISTER_FILE_FORMAT_U32; 595bf215546Sopenharmony_ci case nir_type_int16: 596bf215546Sopenharmony_ci return MALI_REGISTER_FILE_FORMAT_I16; 597bf215546Sopenharmony_ci case nir_type_uint16: 598bf215546Sopenharmony_ci return MALI_REGISTER_FILE_FORMAT_U16; 599bf215546Sopenharmony_ci default: 600bf215546Sopenharmony_ci unreachable("Unsupported blend shader type for NIR alu type"); 601bf215546Sopenharmony_ci } 602bf215546Sopenharmony_ci} 603bf215546Sopenharmony_ci 604bf215546Sopenharmony_civoid 605bf215546Sopenharmony_cipanvk_per_arch(emit_blend)(const struct panvk_device *dev, 606bf215546Sopenharmony_ci const struct panvk_pipeline *pipeline, 607bf215546Sopenharmony_ci unsigned rt, void *bd) 608bf215546Sopenharmony_ci{ 609bf215546Sopenharmony_ci const struct pan_blend_state *blend = &pipeline->blend.state; 610bf215546Sopenharmony_ci const struct pan_blend_rt_state *rts = &blend->rts[rt]; 611bf215546Sopenharmony_ci bool dithered = false; 612bf215546Sopenharmony_ci 613bf215546Sopenharmony_ci pan_pack(bd, BLEND, cfg) { 614bf215546Sopenharmony_ci if (!blend->rt_count || !rts->equation.color_mask) { 615bf215546Sopenharmony_ci cfg.enable = false; 616bf215546Sopenharmony_ci cfg.internal.mode = MALI_BLEND_MODE_OFF; 617bf215546Sopenharmony_ci continue; 618bf215546Sopenharmony_ci } 619bf215546Sopenharmony_ci 620bf215546Sopenharmony_ci cfg.srgb = util_format_is_srgb(rts->format); 621bf215546Sopenharmony_ci cfg.load_destination = pan_blend_reads_dest(blend->rts[rt].equation); 622bf215546Sopenharmony_ci cfg.round_to_fb_precision = !dithered; 623bf215546Sopenharmony_ci 624bf215546Sopenharmony_ci const struct panfrost_device *pdev = &dev->physical_device->pdev; 625bf215546Sopenharmony_ci const struct util_format_description *format_desc = 626bf215546Sopenharmony_ci util_format_description(rts->format); 627bf215546Sopenharmony_ci unsigned chan_size = 0; 628bf215546Sopenharmony_ci for (unsigned i = 0; i < format_desc->nr_channels; i++) 629bf215546Sopenharmony_ci chan_size = MAX2(format_desc->channel[i].size, chan_size); 630bf215546Sopenharmony_ci 631bf215546Sopenharmony_ci pan_blend_to_fixed_function_equation(blend->rts[rt].equation, 632bf215546Sopenharmony_ci &cfg.equation); 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_ci /* Fixed point constant */ 635bf215546Sopenharmony_ci float fconst = 636bf215546Sopenharmony_ci pan_blend_get_constant(pan_blend_constant_mask(blend->rts[rt].equation), 637bf215546Sopenharmony_ci blend->constants); 638bf215546Sopenharmony_ci u16 constant = fconst * ((1 << chan_size) - 1); 639bf215546Sopenharmony_ci constant <<= 16 - chan_size; 640bf215546Sopenharmony_ci cfg.constant = constant; 641bf215546Sopenharmony_ci 642bf215546Sopenharmony_ci if (pan_blend_is_opaque(blend->rts[rt].equation)) { 643bf215546Sopenharmony_ci cfg.internal.mode = MALI_BLEND_MODE_OPAQUE; 644bf215546Sopenharmony_ci } else { 645bf215546Sopenharmony_ci cfg.internal.mode = MALI_BLEND_MODE_FIXED_FUNCTION; 646bf215546Sopenharmony_ci 647bf215546Sopenharmony_ci cfg.internal.fixed_function.alpha_zero_nop = 648bf215546Sopenharmony_ci pan_blend_alpha_zero_nop(blend->rts[rt].equation); 649bf215546Sopenharmony_ci cfg.internal.fixed_function.alpha_one_store = 650bf215546Sopenharmony_ci pan_blend_alpha_one_store(blend->rts[rt].equation); 651bf215546Sopenharmony_ci } 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci /* If we want the conversion to work properly, 654bf215546Sopenharmony_ci * num_comps must be set to 4 655bf215546Sopenharmony_ci */ 656bf215546Sopenharmony_ci cfg.internal.fixed_function.num_comps = 4; 657bf215546Sopenharmony_ci cfg.internal.fixed_function.conversion.memory_format = 658bf215546Sopenharmony_ci panfrost_format_to_bifrost_blend(pdev, rts->format, dithered); 659bf215546Sopenharmony_ci cfg.internal.fixed_function.conversion.register_format = 660bf215546Sopenharmony_ci bifrost_blend_type_from_nir(pipeline->fs.info.bifrost.blend[rt].type); 661bf215546Sopenharmony_ci cfg.internal.fixed_function.rt = rt; 662bf215546Sopenharmony_ci } 663bf215546Sopenharmony_ci} 664bf215546Sopenharmony_ci 665bf215546Sopenharmony_civoid 666bf215546Sopenharmony_cipanvk_per_arch(emit_blend_constant)(const struct panvk_device *dev, 667bf215546Sopenharmony_ci const struct panvk_pipeline *pipeline, 668bf215546Sopenharmony_ci unsigned rt, const float *constants, 669bf215546Sopenharmony_ci void *bd) 670bf215546Sopenharmony_ci{ 671bf215546Sopenharmony_ci float constant = constants[pipeline->blend.constant[rt].index]; 672bf215546Sopenharmony_ci 673bf215546Sopenharmony_ci pan_pack(bd, BLEND, cfg) { 674bf215546Sopenharmony_ci cfg.enable = false; 675bf215546Sopenharmony_ci cfg.constant = constant * pipeline->blend.constant[rt].bifrost_factor; 676bf215546Sopenharmony_ci } 677bf215546Sopenharmony_ci} 678bf215546Sopenharmony_ci 679bf215546Sopenharmony_civoid 680bf215546Sopenharmony_cipanvk_per_arch(emit_dyn_fs_rsd)(const struct panvk_pipeline *pipeline, 681bf215546Sopenharmony_ci const struct panvk_cmd_state *state, 682bf215546Sopenharmony_ci void *rsd) 683bf215546Sopenharmony_ci{ 684bf215546Sopenharmony_ci pan_pack(rsd, RENDERER_STATE, cfg) { 685bf215546Sopenharmony_ci if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_DEPTH_BIAS)) { 686bf215546Sopenharmony_ci cfg.depth_units = state->rast.depth_bias.constant_factor * 2.0f; 687bf215546Sopenharmony_ci cfg.depth_factor = state->rast.depth_bias.slope_factor; 688bf215546Sopenharmony_ci cfg.depth_bias_clamp = state->rast.depth_bias.clamp; 689bf215546Sopenharmony_ci } 690bf215546Sopenharmony_ci 691bf215546Sopenharmony_ci if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK)) { 692bf215546Sopenharmony_ci cfg.stencil_front.mask = state->zs.s_front.compare_mask; 693bf215546Sopenharmony_ci cfg.stencil_back.mask = state->zs.s_back.compare_mask; 694bf215546Sopenharmony_ci } 695bf215546Sopenharmony_ci 696bf215546Sopenharmony_ci if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_WRITE_MASK)) { 697bf215546Sopenharmony_ci cfg.stencil_mask_misc.stencil_mask_front = state->zs.s_front.write_mask; 698bf215546Sopenharmony_ci cfg.stencil_mask_misc.stencil_mask_back = state->zs.s_back.write_mask; 699bf215546Sopenharmony_ci } 700bf215546Sopenharmony_ci 701bf215546Sopenharmony_ci if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE)) { 702bf215546Sopenharmony_ci cfg.stencil_front.reference_value = state->zs.s_front.ref; 703bf215546Sopenharmony_ci cfg.stencil_back.reference_value = state->zs.s_back.ref; 704bf215546Sopenharmony_ci } 705bf215546Sopenharmony_ci } 706bf215546Sopenharmony_ci} 707bf215546Sopenharmony_ci 708bf215546Sopenharmony_civoid 709bf215546Sopenharmony_cipanvk_per_arch(emit_base_fs_rsd)(const struct panvk_device *dev, 710bf215546Sopenharmony_ci const struct panvk_pipeline *pipeline, 711bf215546Sopenharmony_ci void *rsd) 712bf215546Sopenharmony_ci{ 713bf215546Sopenharmony_ci const struct pan_shader_info *info = &pipeline->fs.info; 714bf215546Sopenharmony_ci 715bf215546Sopenharmony_ci pan_pack(rsd, RENDERER_STATE, cfg) { 716bf215546Sopenharmony_ci if (pipeline->fs.required) { 717bf215546Sopenharmony_ci pan_shader_prepare_rsd(info, pipeline->fs.address, &cfg); 718bf215546Sopenharmony_ci 719bf215546Sopenharmony_ci uint8_t rt_written = pipeline->fs.info.outputs_written >> FRAG_RESULT_DATA0; 720bf215546Sopenharmony_ci uint8_t rt_mask = pipeline->fs.rt_mask; 721bf215546Sopenharmony_ci cfg.properties.allow_forward_pixel_to_kill = 722bf215546Sopenharmony_ci pipeline->fs.info.fs.can_fpk && 723bf215546Sopenharmony_ci !(rt_mask & ~rt_written) && 724bf215546Sopenharmony_ci !pipeline->ms.alpha_to_coverage && 725bf215546Sopenharmony_ci !pipeline->blend.reads_dest; 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci bool writes_zs = pipeline->zs.z_write || pipeline->zs.s_test; 728bf215546Sopenharmony_ci bool zs_always_passes = !pipeline->zs.z_test && !pipeline->zs.s_test; 729bf215546Sopenharmony_ci bool oq = false; /* TODO: Occlusion queries */ 730bf215546Sopenharmony_ci 731bf215546Sopenharmony_ci struct pan_earlyzs_state earlyzs = 732bf215546Sopenharmony_ci pan_earlyzs_get(pan_earlyzs_analyze(info), writes_zs || oq, 733bf215546Sopenharmony_ci pipeline->ms.alpha_to_coverage, zs_always_passes); 734bf215546Sopenharmony_ci 735bf215546Sopenharmony_ci cfg.properties.pixel_kill_operation = earlyzs.kill; 736bf215546Sopenharmony_ci cfg.properties.zs_update_operation = earlyzs.update; 737bf215546Sopenharmony_ci } else { 738bf215546Sopenharmony_ci cfg.properties.depth_source = MALI_DEPTH_SOURCE_FIXED_FUNCTION; 739bf215546Sopenharmony_ci cfg.properties.allow_forward_pixel_to_kill = true; 740bf215546Sopenharmony_ci cfg.properties.allow_forward_pixel_to_be_killed = true; 741bf215546Sopenharmony_ci cfg.properties.zs_update_operation = MALI_PIXEL_KILL_STRONG_EARLY; 742bf215546Sopenharmony_ci } 743bf215546Sopenharmony_ci 744bf215546Sopenharmony_ci bool msaa = pipeline->ms.rast_samples > 1; 745bf215546Sopenharmony_ci cfg.multisample_misc.multisample_enable = msaa; 746bf215546Sopenharmony_ci cfg.multisample_misc.sample_mask = 747bf215546Sopenharmony_ci msaa ? pipeline->ms.sample_mask : UINT16_MAX; 748bf215546Sopenharmony_ci 749bf215546Sopenharmony_ci cfg.multisample_misc.depth_function = 750bf215546Sopenharmony_ci pipeline->zs.z_test ? pipeline->zs.z_compare_func : MALI_FUNC_ALWAYS; 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_ci cfg.multisample_misc.depth_write_mask = pipeline->zs.z_write; 753bf215546Sopenharmony_ci cfg.multisample_misc.fixed_function_near_discard = !pipeline->rast.clamp_depth; 754bf215546Sopenharmony_ci cfg.multisample_misc.fixed_function_far_discard = !pipeline->rast.clamp_depth; 755bf215546Sopenharmony_ci cfg.multisample_misc.shader_depth_range_fixed = true; 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_ci cfg.stencil_mask_misc.stencil_enable = pipeline->zs.s_test; 758bf215546Sopenharmony_ci cfg.stencil_mask_misc.alpha_to_coverage = pipeline->ms.alpha_to_coverage; 759bf215546Sopenharmony_ci cfg.stencil_mask_misc.alpha_test_compare_function = MALI_FUNC_ALWAYS; 760bf215546Sopenharmony_ci cfg.stencil_mask_misc.front_facing_depth_bias = pipeline->rast.depth_bias.enable; 761bf215546Sopenharmony_ci cfg.stencil_mask_misc.back_facing_depth_bias = pipeline->rast.depth_bias.enable; 762bf215546Sopenharmony_ci cfg.stencil_mask_misc.single_sampled_lines = pipeline->ms.rast_samples <= 1; 763bf215546Sopenharmony_ci 764bf215546Sopenharmony_ci if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_DEPTH_BIAS))) { 765bf215546Sopenharmony_ci cfg.depth_units = pipeline->rast.depth_bias.constant_factor * 2.0f; 766bf215546Sopenharmony_ci cfg.depth_factor = pipeline->rast.depth_bias.slope_factor; 767bf215546Sopenharmony_ci cfg.depth_bias_clamp = pipeline->rast.depth_bias.clamp; 768bf215546Sopenharmony_ci } 769bf215546Sopenharmony_ci 770bf215546Sopenharmony_ci if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK))) { 771bf215546Sopenharmony_ci cfg.stencil_front.mask = pipeline->zs.s_front.compare_mask; 772bf215546Sopenharmony_ci cfg.stencil_back.mask = pipeline->zs.s_back.compare_mask; 773bf215546Sopenharmony_ci } 774bf215546Sopenharmony_ci 775bf215546Sopenharmony_ci if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_WRITE_MASK))) { 776bf215546Sopenharmony_ci cfg.stencil_mask_misc.stencil_mask_front = pipeline->zs.s_front.write_mask; 777bf215546Sopenharmony_ci cfg.stencil_mask_misc.stencil_mask_back = pipeline->zs.s_back.write_mask; 778bf215546Sopenharmony_ci } 779bf215546Sopenharmony_ci 780bf215546Sopenharmony_ci if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE))) { 781bf215546Sopenharmony_ci cfg.stencil_front.reference_value = pipeline->zs.s_front.ref; 782bf215546Sopenharmony_ci cfg.stencil_back.reference_value = pipeline->zs.s_back.ref; 783bf215546Sopenharmony_ci } 784bf215546Sopenharmony_ci 785bf215546Sopenharmony_ci cfg.stencil_front.compare_function = pipeline->zs.s_front.compare_func; 786bf215546Sopenharmony_ci cfg.stencil_front.stencil_fail = pipeline->zs.s_front.fail_op; 787bf215546Sopenharmony_ci cfg.stencil_front.depth_fail = pipeline->zs.s_front.z_fail_op; 788bf215546Sopenharmony_ci cfg.stencil_front.depth_pass = pipeline->zs.s_front.pass_op; 789bf215546Sopenharmony_ci cfg.stencil_back.compare_function = pipeline->zs.s_back.compare_func; 790bf215546Sopenharmony_ci cfg.stencil_back.stencil_fail = pipeline->zs.s_back.fail_op; 791bf215546Sopenharmony_ci cfg.stencil_back.depth_fail = pipeline->zs.s_back.z_fail_op; 792bf215546Sopenharmony_ci cfg.stencil_back.depth_pass = pipeline->zs.s_back.pass_op; 793bf215546Sopenharmony_ci } 794bf215546Sopenharmony_ci} 795bf215546Sopenharmony_ci 796bf215546Sopenharmony_civoid 797bf215546Sopenharmony_cipanvk_per_arch(emit_non_fs_rsd)(const struct panvk_device *dev, 798bf215546Sopenharmony_ci const struct pan_shader_info *shader_info, 799bf215546Sopenharmony_ci mali_ptr shader_ptr, 800bf215546Sopenharmony_ci void *rsd) 801bf215546Sopenharmony_ci{ 802bf215546Sopenharmony_ci assert(shader_info->stage != MESA_SHADER_FRAGMENT); 803bf215546Sopenharmony_ci 804bf215546Sopenharmony_ci pan_pack(rsd, RENDERER_STATE, cfg) { 805bf215546Sopenharmony_ci pan_shader_prepare_rsd(shader_info, shader_ptr, &cfg); 806bf215546Sopenharmony_ci } 807bf215546Sopenharmony_ci} 808bf215546Sopenharmony_ci 809bf215546Sopenharmony_civoid 810bf215546Sopenharmony_cipanvk_per_arch(emit_tiler_context)(const struct panvk_device *dev, 811bf215546Sopenharmony_ci unsigned width, unsigned height, 812bf215546Sopenharmony_ci const struct panfrost_ptr *descs) 813bf215546Sopenharmony_ci{ 814bf215546Sopenharmony_ci const struct panfrost_device *pdev = &dev->physical_device->pdev; 815bf215546Sopenharmony_ci 816bf215546Sopenharmony_ci pan_pack(descs->cpu + pan_size(TILER_CONTEXT), TILER_HEAP, cfg) { 817bf215546Sopenharmony_ci cfg.size = pdev->tiler_heap->size; 818bf215546Sopenharmony_ci cfg.base = pdev->tiler_heap->ptr.gpu; 819bf215546Sopenharmony_ci cfg.bottom = pdev->tiler_heap->ptr.gpu; 820bf215546Sopenharmony_ci cfg.top = pdev->tiler_heap->ptr.gpu + pdev->tiler_heap->size; 821bf215546Sopenharmony_ci } 822bf215546Sopenharmony_ci 823bf215546Sopenharmony_ci pan_pack(descs->cpu, TILER_CONTEXT, cfg) { 824bf215546Sopenharmony_ci cfg.hierarchy_mask = 0x28; 825bf215546Sopenharmony_ci cfg.fb_width = width; 826bf215546Sopenharmony_ci cfg.fb_height = height; 827bf215546Sopenharmony_ci cfg.heap = descs->gpu + pan_size(TILER_CONTEXT); 828bf215546Sopenharmony_ci } 829bf215546Sopenharmony_ci} 830