Path: blob/21.2-virgl/src/panfrost/vulkan/panvk_cs.c
4560 views
/*1* Copyright (C) 2021 Collabora Ltd.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER20* DEALINGS IN THE SOFTWARE.21*/2223#include "util/macros.h"24#include "compiler/shader_enums.h"2526#include "panfrost-quirks.h"27#include "pan_cs.h"28#include "pan_encoder.h"29#include "pan_pool.h"3031#include "panvk_cs.h"32#include "panvk_private.h"33#include "panvk_varyings.h"3435static mali_pixel_format36panvk_varying_hw_format(const struct panvk_device *dev,37const struct panvk_varyings_info *varyings,38gl_shader_stage stage, unsigned idx)39{40const struct panfrost_device *pdev = &dev->physical_device->pdev;41gl_varying_slot loc = varyings->stage[stage].loc[idx];42bool fs = stage == MESA_SHADER_FRAGMENT;4344switch (loc) {45case VARYING_SLOT_PNTC:46case VARYING_SLOT_PSIZ:47return (MALI_R16F << 12) |48(pdev->quirks & HAS_SWIZZLES ?49panfrost_get_default_swizzle(1) : 0);50case VARYING_SLOT_POS:51return ((fs ? MALI_RGBA32F : MALI_SNAP_4) << 12) |52(pdev->quirks & HAS_SWIZZLES ?53panfrost_get_default_swizzle(4) : 0);54default:55assert(!panvk_varying_is_builtin(stage, loc));56return pdev->formats[varyings->varying[loc].format].hw;57}58}5960static void61panvk_emit_varying(const struct panvk_device *dev,62const struct panvk_varyings_info *varyings,63gl_shader_stage stage, unsigned idx,64void *attrib)65{66const struct panfrost_device *pdev = &dev->physical_device->pdev;67gl_varying_slot loc = varyings->stage[stage].loc[idx];68bool fs = stage == MESA_SHADER_FRAGMENT;6970pan_pack(attrib, ATTRIBUTE, cfg) {71if (!panvk_varying_is_builtin(stage, loc)) {72cfg.buffer_index = varyings->varying[loc].buf;73cfg.offset = varyings->varying[loc].offset;74} else {75cfg.buffer_index =76panvk_varying_buf_index(varyings,77panvk_varying_buf_id(fs, loc));78}79cfg.offset_enable = !pan_is_bifrost(pdev);80cfg.format = panvk_varying_hw_format(dev, varyings, stage, idx);81}82}8384void85panvk_emit_varyings(const struct panvk_device *dev,86const struct panvk_varyings_info *varyings,87gl_shader_stage stage,88void *descs)89{90struct mali_attribute_packed *attrib = descs;9192for (unsigned i = 0; i < varyings->stage[stage].count; i++)93panvk_emit_varying(dev, varyings, stage, i, attrib++);94}9596static void97panvk_emit_varying_buf(const struct panvk_device *dev,98const struct panvk_varyings_info *varyings,99enum panvk_varying_buf_id id, void *buf)100{101unsigned buf_idx = panvk_varying_buf_index(varyings, id);102enum mali_attribute_special special_id = panvk_varying_special_buf_id(id);103104pan_pack(buf, ATTRIBUTE_BUFFER, cfg) {105if (special_id) {106cfg.type = 0;107cfg.special = special_id;108} else {109unsigned offset = varyings->buf[buf_idx].address & 63;110111cfg.stride = varyings->buf[buf_idx].stride;112cfg.size = varyings->buf[buf_idx].size + offset;113cfg.pointer = varyings->buf[buf_idx].address & ~63ULL;114}115}116}117118void119panvk_emit_varying_bufs(const struct panvk_device *dev,120const struct panvk_varyings_info *varyings,121void *descs)122{123const struct panfrost_device *pdev = &dev->physical_device->pdev;124struct mali_attribute_buffer_packed *buf = descs;125126for (unsigned i = 0; i < PANVK_VARY_BUF_MAX; i++) {127if (varyings->buf_mask & (1 << i))128panvk_emit_varying_buf(dev, varyings, i, buf++);129}130131if (pan_is_bifrost(pdev))132memset(buf, 0, sizeof(*buf));133}134135static void136panvk_emit_attrib_buf(const struct panvk_device *dev,137const struct panvk_attribs_info *info,138const struct panvk_draw_info *draw,139const struct panvk_attrib_buf *bufs,140unsigned buf_count,141unsigned idx, void *desc)142{143ASSERTED const struct panfrost_device *pdev = &dev->physical_device->pdev;144const struct panvk_attrib_buf_info *buf_info = &info->buf[idx];145146if (buf_info->special) {147assert(!pan_is_bifrost(pdev));148switch (buf_info->special_id) {149case PAN_VERTEX_ID:150panfrost_vertex_id(draw->padded_vertex_count, desc,151draw->instance_count > 1);152return;153case PAN_INSTANCE_ID:154panfrost_instance_id(draw->padded_vertex_count, desc,155draw->instance_count > 1);156return;157default:158unreachable("Invalid attribute ID");159}160}161162assert(idx < buf_count);163const struct panvk_attrib_buf *buf = &bufs[idx];164unsigned divisor = buf_info->per_instance ?165draw->padded_vertex_count : 0;166unsigned stride = divisor && draw->instance_count == 1 ?1670 : buf_info->stride;168mali_ptr addr = buf->address & ~63ULL;169unsigned size = buf->size + (buf->address & 63);170171/* TODO: support instanced arrays */172pan_pack(desc, ATTRIBUTE_BUFFER, cfg) {173if (draw->instance_count > 1 && divisor) {174cfg.type = MALI_ATTRIBUTE_TYPE_1D_MODULUS;175cfg.divisor = divisor;176}177178cfg.pointer = addr;179cfg.stride = stride;180cfg.size = size;181}182}183184void185panvk_emit_attrib_bufs(const struct panvk_device *dev,186const struct panvk_attribs_info *info,187const struct panvk_attrib_buf *bufs,188unsigned buf_count,189const struct panvk_draw_info *draw,190void *descs)191{192const struct panfrost_device *pdev = &dev->physical_device->pdev;193struct mali_attribute_buffer_packed *buf = descs;194195for (unsigned i = 0; i < info->buf_count; i++)196panvk_emit_attrib_buf(dev, info, draw, bufs, buf_count, i, buf++);197198/* A NULL entry is needed to stop prefecting on Bifrost */199if (pan_is_bifrost(pdev))200memset(buf, 0, sizeof(*buf));201}202203static void204panvk_emit_attrib(const struct panvk_device *dev,205const struct panvk_attribs_info *attribs,206const struct panvk_attrib_buf *bufs,207unsigned buf_count,208unsigned idx, void *attrib)209{210const struct panfrost_device *pdev = &dev->physical_device->pdev;211212pan_pack(attrib, ATTRIBUTE, cfg) {213cfg.buffer_index = attribs->attrib[idx].buf;214cfg.offset = attribs->attrib[idx].offset +215(bufs[cfg.buffer_index].address & 63);216cfg.format = pdev->formats[attribs->attrib[idx].format].hw;217}218}219220void221panvk_emit_attribs(const struct panvk_device *dev,222const struct panvk_attribs_info *attribs,223const struct panvk_attrib_buf *bufs,224unsigned buf_count,225void *descs)226{227struct mali_attribute_packed *attrib = descs;228229for (unsigned i = 0; i < attribs->attrib_count; i++)230panvk_emit_attrib(dev, attribs, bufs, buf_count, i, attrib++);231}232233void234panvk_emit_ubos(const struct panvk_pipeline *pipeline,235const struct panvk_descriptor_state *state,236void *descs)237{238struct mali_uniform_buffer_packed *ubos = descs;239240for (unsigned i = 0; i < ARRAY_SIZE(state->sets); i++) {241const struct panvk_descriptor_set_layout *set_layout =242pipeline->layout->sets[i].layout;243const struct panvk_descriptor_set *set = state->sets[i].set;244unsigned offset = pipeline->layout->sets[i].ubo_offset;245246if (!set_layout)247continue;248249if (!set) {250unsigned num_ubos = (set_layout->num_dynoffsets != 0) + set_layout->num_ubos;251memset(&ubos[offset], 0, num_ubos * sizeof(*ubos));252} else {253memcpy(&ubos[offset], set->ubos, set_layout->num_ubos * sizeof(*ubos));254if (set_layout->num_dynoffsets) {255pan_pack(&ubos[offset + set_layout->num_ubos], UNIFORM_BUFFER, cfg) {256cfg.pointer = state->sets[i].dynoffsets.gpu;257cfg.entries = DIV_ROUND_UP(set->layout->num_dynoffsets, 16);258}259}260}261}262263for (unsigned i = 0; i < ARRAY_SIZE(pipeline->sysvals); i++) {264if (!pipeline->sysvals[i].ids.sysval_count)265continue;266267pan_pack(&ubos[pipeline->sysvals[i].ubo_idx], UNIFORM_BUFFER, cfg) {268cfg.pointer = pipeline->sysvals[i].ubo ? :269state->sysvals[i];270cfg.entries = pipeline->sysvals[i].ids.sysval_count;271}272}273}274275void276panvk_emit_vertex_job(const struct panvk_device *dev,277const struct panvk_pipeline *pipeline,278const struct panvk_draw_info *draw,279void *job)280{281const struct panfrost_device *pdev = &dev->physical_device->pdev;282void *section = pan_section_ptr(job, COMPUTE_JOB, INVOCATION);283284memcpy(section, &draw->invocation, MALI_INVOCATION_LENGTH);285286pan_section_pack(job, COMPUTE_JOB, PARAMETERS, cfg) {287cfg.job_task_split = 5;288}289290pan_section_pack(job, COMPUTE_JOB, DRAW, cfg) {291cfg.draw_descriptor_is_64b = true;292if (!pan_is_bifrost(pdev))293cfg.texture_descriptor_is_64b = true;294cfg.state = pipeline->rsds[MESA_SHADER_VERTEX];295cfg.attributes = draw->stages[MESA_SHADER_VERTEX].attributes;296cfg.attribute_buffers = draw->attribute_bufs;297cfg.varyings = draw->stages[MESA_SHADER_VERTEX].varyings;298cfg.varying_buffers = draw->varying_bufs;299cfg.thread_storage = draw->tls;300cfg.offset_start = draw->offset_start;301cfg.instance_size = draw->instance_count > 1 ?302draw->padded_vertex_count : 1;303cfg.uniform_buffers = draw->ubos;304cfg.push_uniforms = draw->stages[PIPE_SHADER_VERTEX].push_constants;305cfg.textures = draw->textures;306cfg.samplers = draw->samplers;307}308309pan_section_pack(job, COMPUTE_JOB, DRAW_PADDING, cfg);310}311312void313panvk_emit_tiler_job(const struct panvk_device *dev,314const struct panvk_pipeline *pipeline,315const struct panvk_draw_info *draw,316void *job)317{318const struct panfrost_device *pdev = &dev->physical_device->pdev;319void *section = pan_is_bifrost(pdev) ?320pan_section_ptr(job, BIFROST_TILER_JOB, INVOCATION) :321pan_section_ptr(job, MIDGARD_TILER_JOB, INVOCATION);322323memcpy(section, &draw->invocation, MALI_INVOCATION_LENGTH);324325section = pan_is_bifrost(pdev) ?326pan_section_ptr(job, BIFROST_TILER_JOB, PRIMITIVE) :327pan_section_ptr(job, MIDGARD_TILER_JOB, PRIMITIVE);328329pan_pack(section, PRIMITIVE, cfg) {330cfg.draw_mode = pipeline->ia.topology;331if (pipeline->ia.writes_point_size)332cfg.point_size_array_format = MALI_POINT_SIZE_ARRAY_FORMAT_FP16;333334cfg.first_provoking_vertex = true;335if (pipeline->ia.primitive_restart)336cfg.primitive_restart = MALI_PRIMITIVE_RESTART_IMPLICIT;337cfg.job_task_split = 6;338/* TODO: indexed draws */339cfg.index_count = draw->vertex_count;340}341342section = pan_is_bifrost(pdev) ?343pan_section_ptr(job, BIFROST_TILER_JOB, PRIMITIVE_SIZE) :344pan_section_ptr(job, MIDGARD_TILER_JOB, PRIMITIVE_SIZE);345pan_pack(section, PRIMITIVE_SIZE, cfg) {346if (pipeline->ia.writes_point_size) {347cfg.size_array = draw->psiz;348} else {349cfg.constant = draw->line_width;350}351}352353section = pan_is_bifrost(pdev) ?354pan_section_ptr(job, BIFROST_TILER_JOB, DRAW) :355pan_section_ptr(job, MIDGARD_TILER_JOB, DRAW);356357pan_pack(section, DRAW, cfg) {358cfg.four_components_per_vertex = true;359cfg.draw_descriptor_is_64b = true;360if (!pan_is_bifrost(pdev))361cfg.texture_descriptor_is_64b = true;362cfg.front_face_ccw = pipeline->rast.front_ccw;363cfg.cull_front_face = pipeline->rast.cull_front_face;364cfg.cull_back_face = pipeline->rast.cull_back_face;365cfg.position = draw->position;366cfg.state = draw->fs_rsd;367cfg.attributes = draw->stages[MESA_SHADER_FRAGMENT].attributes;368cfg.attribute_buffers = draw->attribute_bufs;369cfg.viewport = draw->viewport;370cfg.varyings = draw->stages[MESA_SHADER_FRAGMENT].varyings;371cfg.varying_buffers = cfg.varyings ? draw->varying_bufs : 0;372if (pan_is_bifrost(pdev))373cfg.thread_storage = draw->tls;374else375cfg.fbd = draw->fb;376377/* For all primitives but lines DRAW.flat_shading_vertex must378* be set to 0 and the provoking vertex is selected with the379* PRIMITIVE.first_provoking_vertex field.380*/381if (pipeline->ia.topology == MALI_DRAW_MODE_LINES ||382pipeline->ia.topology == MALI_DRAW_MODE_LINE_STRIP ||383pipeline->ia.topology == MALI_DRAW_MODE_LINE_LOOP) {384/* The logic is inverted on bifrost. */385cfg.flat_shading_vertex = pan_is_bifrost(pdev) ?386true : false;387}388389cfg.offset_start = draw->offset_start;390cfg.instance_size = draw->instance_count > 1 ?391draw->padded_vertex_count : 1;392cfg.uniform_buffers = draw->ubos;393cfg.push_uniforms = draw->stages[PIPE_SHADER_FRAGMENT].push_constants;394cfg.textures = draw->textures;395cfg.samplers = draw->samplers;396397/* TODO: occlusion queries */398}399400if (pan_is_bifrost(pdev)) {401pan_section_pack(job, BIFROST_TILER_JOB, TILER, cfg) {402cfg.address = draw->tiler_ctx->bifrost;403}404pan_section_pack(job, BIFROST_TILER_JOB, DRAW_PADDING, padding);405pan_section_pack(job, BIFROST_TILER_JOB, PADDING, padding);406}407}408409void410panvk_emit_fragment_job(const struct panvk_device *dev,411const struct panvk_framebuffer *fb,412mali_ptr fbdesc,413void *job)414{415pan_section_pack(job, FRAGMENT_JOB, HEADER, header) {416header.type = MALI_JOB_TYPE_FRAGMENT;417header.index = 1;418}419420pan_section_pack(job, FRAGMENT_JOB, PAYLOAD, payload) {421payload.bound_min_x = 0;422payload.bound_min_y = 0;423424payload.bound_max_x = (fb->width - 1) >> MALI_TILE_SHIFT;425payload.bound_max_y = (fb->height - 1) >> MALI_TILE_SHIFT;426payload.framebuffer = fbdesc;427}428}429430void431panvk_emit_viewport(const VkViewport *viewport, const VkRect2D *scissor,432void *vpd)433{434/* The spec says "width must be greater than 0.0" */435assert(viewport->x >= 0);436int minx = (int)viewport->x;437int maxx = (int)(viewport->x + viewport->width);438439/* Viewport height can be negative */440int miny = MIN2((int)viewport->y, (int)(viewport->y + viewport->height));441int maxy = MAX2((int)viewport->y, (int)(viewport->y + viewport->height));442443assert(scissor->offset.x >= 0 && scissor->offset.y >= 0);444miny = MAX2(scissor->offset.x, minx);445miny = MAX2(scissor->offset.y, miny);446maxx = MIN2(scissor->offset.x + scissor->extent.width, maxx);447maxy = MIN2(scissor->offset.y + scissor->extent.height, maxy);448449/* Make sure we don't end up with a max < min when width/height is 0 */450maxx = maxx > minx ? maxx - 1 : maxx;451maxy = maxy > miny ? maxy - 1 : maxy;452453assert(viewport->minDepth >= 0.0f && viewport->minDepth <= 1.0f);454assert(viewport->maxDepth >= 0.0f && viewport->maxDepth <= 1.0f);455456pan_pack(vpd, VIEWPORT, cfg) {457cfg.scissor_minimum_x = minx;458cfg.scissor_minimum_y = miny;459cfg.scissor_maximum_x = maxx;460cfg.scissor_maximum_y = maxy;461cfg.minimum_z = MIN2(viewport->minDepth, viewport->maxDepth);462cfg.maximum_z = MAX2(viewport->minDepth, viewport->maxDepth);463}464}465466void467panvk_sysval_upload_viewport_scale(const VkViewport *viewport,468union panvk_sysval_data *data)469{470data->f32[0] = 0.5f * viewport->width;471data->f32[1] = 0.5f * viewport->height;472data->f32[2] = 0.5f * (viewport->maxDepth - viewport->minDepth);473}474475void476panvk_sysval_upload_viewport_offset(const VkViewport *viewport,477union panvk_sysval_data *data)478{479data->f32[0] = (0.5f * viewport->width) + viewport->x;480data->f32[1] = (0.5f * viewport->height) + viewport->y;481data->f32[2] = (0.5f * (viewport->maxDepth - viewport->minDepth)) + viewport->minDepth;482}483484static enum mali_bifrost_register_file_format485bifrost_blend_type_from_nir(nir_alu_type nir_type)486{487switch(nir_type) {488case 0: /* Render target not in use */489return 0;490case nir_type_float16:491return MALI_BIFROST_REGISTER_FILE_FORMAT_F16;492case nir_type_float32:493return MALI_BIFROST_REGISTER_FILE_FORMAT_F32;494case nir_type_int32:495return MALI_BIFROST_REGISTER_FILE_FORMAT_I32;496case nir_type_uint32:497return MALI_BIFROST_REGISTER_FILE_FORMAT_U32;498case nir_type_int16:499return MALI_BIFROST_REGISTER_FILE_FORMAT_I16;500case nir_type_uint16:501return MALI_BIFROST_REGISTER_FILE_FORMAT_U16;502default:503unreachable("Unsupported blend shader type for NIR alu type");504}505}506507static void508panvk_emit_bifrost_blend(const struct panvk_device *dev,509const struct panvk_pipeline *pipeline,510unsigned rt, void *bd)511{512const struct pan_blend_state *blend = &pipeline->blend.state;513const struct panfrost_device *pdev = &dev->physical_device->pdev;514const struct pan_blend_rt_state *rts = &blend->rts[rt];515516pan_pack(bd, BLEND, cfg) {517if (!blend->rt_count || !rts->equation.color_mask) {518cfg.enable = false;519cfg.bifrost.internal.mode = MALI_BIFROST_BLEND_MODE_OFF;520continue;521}522523cfg.srgb = util_format_is_srgb(rts->format);524cfg.load_destination = pan_blend_reads_dest(blend->rts[rt].equation);525cfg.round_to_fb_precision = true;526527const struct util_format_description *format_desc =528util_format_description(rts->format);529unsigned chan_size = 0;530for (unsigned i = 0; i < format_desc->nr_channels; i++)531chan_size = MAX2(format_desc->channel[0].size, chan_size);532533pan_blend_to_fixed_function_equation(blend->rts[rt].equation,534&cfg.bifrost.equation);535536/* Fixed point constant */537float fconst =538pan_blend_get_constant(pan_blend_constant_mask(blend->rts[rt].equation),539blend->constants);540u16 constant = fconst * ((1 << chan_size) - 1);541constant <<= 16 - chan_size;542cfg.bifrost.constant = constant;543544if (pan_blend_is_opaque(blend->rts[rt].equation))545cfg.bifrost.internal.mode = MALI_BIFROST_BLEND_MODE_OPAQUE;546else547cfg.bifrost.internal.mode = MALI_BIFROST_BLEND_MODE_FIXED_FUNCTION;548549/* If we want the conversion to work properly,550* num_comps must be set to 4551*/552cfg.bifrost.internal.fixed_function.num_comps = 4;553cfg.bifrost.internal.fixed_function.conversion.memory_format =554panfrost_format_to_bifrost_blend(pdev, rts->format);555cfg.bifrost.internal.fixed_function.conversion.register_format =556bifrost_blend_type_from_nir(pipeline->fs.info.bifrost.blend[rt].type);557cfg.bifrost.internal.fixed_function.rt = rt;558}559}560561static void562panvk_emit_midgard_blend(const struct panvk_device *dev,563const struct panvk_pipeline *pipeline,564unsigned rt, void *bd)565{566const struct pan_blend_state *blend = &pipeline->blend.state;567const struct pan_blend_rt_state *rts = &blend->rts[rt];568569pan_pack(bd, BLEND, cfg) {570if (!blend->rt_count || !rts->equation.color_mask) {571cfg.enable = false;572continue;573}574575cfg.srgb = util_format_is_srgb(rts->format);576cfg.load_destination = pan_blend_reads_dest(blend->rts[rt].equation);577cfg.round_to_fb_precision = true;578cfg.midgard.blend_shader = false;579pan_blend_to_fixed_function_equation(blend->rts[rt].equation,580&cfg.midgard.equation);581cfg.midgard.constant =582pan_blend_get_constant(pan_blend_constant_mask(blend->rts[rt].equation),583blend->constants);584}585}586587void588panvk_emit_blend(const struct panvk_device *dev,589const struct panvk_pipeline *pipeline,590unsigned rt, void *bd)591{592const struct panfrost_device *pdev = &dev->physical_device->pdev;593594if (pan_is_bifrost(pdev))595panvk_emit_bifrost_blend(dev, pipeline, rt, bd);596else597panvk_emit_midgard_blend(dev, pipeline, rt, bd);598}599600void601panvk_emit_blend_constant(const struct panvk_device *dev,602const struct panvk_pipeline *pipeline,603unsigned rt, const float *constants, void *bd)604{605const struct panfrost_device *pdev = &dev->physical_device->pdev;606float constant = constants[pipeline->blend.constant[rt].index];607608pan_pack(bd, BLEND, cfg) {609cfg.enable = false;610if (pan_is_bifrost(pdev)) {611cfg.bifrost.constant = constant * pipeline->blend.constant[rt].bifrost_factor;612} else {613cfg.midgard.constant = constant;614}615}616}617618void619panvk_emit_dyn_fs_rsd(const struct panvk_device *dev,620const struct panvk_pipeline *pipeline,621const struct panvk_cmd_state *state,622void *rsd)623{624pan_pack(rsd, RENDERER_STATE, cfg) {625if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_DEPTH_BIAS)) {626cfg.depth_units = state->rast.depth_bias.constant_factor * 2.0f;627cfg.depth_factor = state->rast.depth_bias.slope_factor;628cfg.depth_bias_clamp = state->rast.depth_bias.clamp;629}630631if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK)) {632cfg.stencil_front.mask = state->zs.s_front.compare_mask;633cfg.stencil_back.mask = state->zs.s_back.compare_mask;634}635636if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_WRITE_MASK)) {637cfg.stencil_mask_misc.stencil_mask_front = state->zs.s_front.write_mask;638cfg.stencil_mask_misc.stencil_mask_back = state->zs.s_back.write_mask;639}640641if (pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE)) {642cfg.stencil_front.reference_value = state->zs.s_front.ref;643cfg.stencil_back.reference_value = state->zs.s_back.ref;644}645}646}647648void649panvk_emit_base_fs_rsd(const struct panvk_device *dev,650const struct panvk_pipeline *pipeline,651void *rsd)652{653const struct panfrost_device *pdev = &dev->physical_device->pdev;654const struct pan_shader_info *info = &pipeline->fs.info;655656pan_pack(rsd, RENDERER_STATE, cfg) {657if (pipeline->fs.required) {658pan_shader_prepare_rsd(pdev, info, pipeline->fs.address, &cfg);659if (pan_is_bifrost(pdev)) {660cfg.properties.bifrost.allow_forward_pixel_to_kill = info->fs.can_fpk;661} else {662/* If either depth or stencil is enabled, discard matters */663bool zs_enabled =664(pipeline->zs.z_test && pipeline->zs.z_compare_func != MALI_FUNC_ALWAYS) ||665pipeline->zs.s_test;666667cfg.properties.midgard.work_register_count = info->work_reg_count;668cfg.properties.midgard.force_early_z =669info->fs.can_early_z && !pipeline->ms.alpha_to_coverage &&670pipeline->zs.z_compare_func == MALI_FUNC_ALWAYS;671672673/* Workaround a hardware errata where early-z cannot be enabled674* when discarding even when the depth buffer is read-only, by675* lying to the hardware about the discard and setting the676* reads tilebuffer? flag to compensate */677cfg.properties.midgard.shader_reads_tilebuffer =678info->fs.outputs_read ||679(!zs_enabled && info->fs.can_discard);680cfg.properties.midgard.shader_contains_discard =681zs_enabled && info->fs.can_discard;682}683} else {684if (pan_is_bifrost(pdev)) {685cfg.properties.bifrost.shader_modifies_coverage = true;686cfg.properties.bifrost.allow_forward_pixel_to_kill = true;687cfg.properties.bifrost.allow_forward_pixel_to_be_killed = true;688cfg.properties.bifrost.zs_update_operation = MALI_PIXEL_KILL_STRONG_EARLY;689} else {690cfg.shader.shader = 0x1;691cfg.properties.midgard.work_register_count = 1;692cfg.properties.depth_source = MALI_DEPTH_SOURCE_FIXED_FUNCTION;693cfg.properties.midgard.force_early_z = true;694}695}696697bool msaa = pipeline->ms.rast_samples > 1;698cfg.multisample_misc.multisample_enable = msaa;699cfg.multisample_misc.sample_mask =700msaa ? pipeline->ms.sample_mask : UINT16_MAX;701702cfg.multisample_misc.depth_function =703pipeline->zs.z_test ? pipeline->zs.z_compare_func : MALI_FUNC_ALWAYS;704705cfg.multisample_misc.depth_write_mask = pipeline->zs.z_write;706cfg.multisample_misc.fixed_function_near_discard = !pipeline->rast.clamp_depth;707cfg.multisample_misc.fixed_function_far_discard = !pipeline->rast.clamp_depth;708cfg.multisample_misc.shader_depth_range_fixed = true;709710cfg.stencil_mask_misc.stencil_enable = pipeline->zs.s_test;711cfg.stencil_mask_misc.alpha_to_coverage = pipeline->ms.alpha_to_coverage;712cfg.stencil_mask_misc.alpha_test_compare_function = MALI_FUNC_ALWAYS;713cfg.stencil_mask_misc.depth_range_1 = pipeline->rast.depth_bias.enable;714cfg.stencil_mask_misc.depth_range_2 = pipeline->rast.depth_bias.enable;715cfg.stencil_mask_misc.single_sampled_lines = pipeline->ms.rast_samples <= 1;716717if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_DEPTH_BIAS))) {718cfg.depth_units = pipeline->rast.depth_bias.constant_factor * 2.0f;719cfg.depth_factor = pipeline->rast.depth_bias.slope_factor;720cfg.depth_bias_clamp = pipeline->rast.depth_bias.clamp;721}722723if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK))) {724cfg.stencil_front.mask = pipeline->zs.s_front.compare_mask;725cfg.stencil_back.mask = pipeline->zs.s_back.compare_mask;726}727728if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_WRITE_MASK))) {729cfg.stencil_mask_misc.stencil_mask_front = pipeline->zs.s_front.write_mask;730cfg.stencil_mask_misc.stencil_mask_back = pipeline->zs.s_back.write_mask;731}732733if (!(pipeline->dynamic_state_mask & (1 << VK_DYNAMIC_STATE_STENCIL_REFERENCE))) {734cfg.stencil_front.reference_value = pipeline->zs.s_front.ref;735cfg.stencil_back.reference_value = pipeline->zs.s_back.ref;736}737738cfg.stencil_front.compare_function = pipeline->zs.s_front.compare_func;739cfg.stencil_front.stencil_fail = pipeline->zs.s_front.fail_op;740cfg.stencil_front.depth_fail = pipeline->zs.s_front.z_fail_op;741cfg.stencil_front.depth_pass = pipeline->zs.s_front.pass_op;742cfg.stencil_back.compare_function = pipeline->zs.s_back.compare_func;743cfg.stencil_back.stencil_fail = pipeline->zs.s_back.fail_op;744cfg.stencil_back.depth_fail = pipeline->zs.s_back.z_fail_op;745cfg.stencil_back.depth_pass = pipeline->zs.s_back.pass_op;746}747}748749void750panvk_emit_non_fs_rsd(const struct panvk_device *dev,751const struct pan_shader_info *shader_info,752mali_ptr shader_ptr,753void *rsd)754{755const struct panfrost_device *pdev = &dev->physical_device->pdev;756757assert(shader_info->stage != MESA_SHADER_FRAGMENT);758759pan_pack(rsd, RENDERER_STATE, cfg) {760pan_shader_prepare_rsd(pdev, shader_info, shader_ptr, &cfg);761}762}763764void765panvk_emit_bifrost_tiler_context(const struct panvk_device *dev,766unsigned width, unsigned height,767const struct panfrost_ptr *descs)768{769const struct panfrost_device *pdev = &dev->physical_device->pdev;770771pan_pack(descs->cpu + MALI_BIFROST_TILER_LENGTH, BIFROST_TILER_HEAP, cfg) {772cfg.size = pdev->tiler_heap->size;773cfg.base = pdev->tiler_heap->ptr.gpu;774cfg.bottom = pdev->tiler_heap->ptr.gpu;775cfg.top = pdev->tiler_heap->ptr.gpu + pdev->tiler_heap->size;776}777778pan_pack(descs->cpu, BIFROST_TILER, cfg) {779cfg.hierarchy_mask = 0x28;780cfg.fb_width = width;781cfg.fb_height = height;782cfg.heap = descs->gpu + MALI_BIFROST_TILER_LENGTH;783}784}785786unsigned787panvk_emit_fb(const struct panvk_device *dev,788const struct panvk_batch *batch,789const struct panvk_subpass *subpass,790const struct panvk_pipeline *pipeline,791const struct panvk_framebuffer *fb,792const struct panvk_clear_value *clears,793const struct pan_tls_info *tlsinfo,794const struct pan_tiler_context *tilerctx,795void *desc)796{797const struct panfrost_device *pdev = &dev->physical_device->pdev;798struct panvk_image_view *view;799bool crc_valid[8] = { false };800struct pan_fb_info fbinfo = {801.width = fb->width,802.height = fb->height,803.extent.maxx = fb->width - 1,804.extent.maxy = fb->height - 1,805.nr_samples = 1,806};807808for (unsigned cb = 0; cb < subpass->color_count; cb++) {809int idx = subpass->color_attachments[cb].idx;810view = idx != VK_ATTACHMENT_UNUSED ?811fb->attachments[idx].iview : NULL;812if (!view)813continue;814fbinfo.rts[cb].view = &view->pview;815fbinfo.rts[cb].clear = subpass->color_attachments[idx].clear;816fbinfo.rts[cb].crc_valid = &crc_valid[cb];817818memcpy(fbinfo.rts[cb].clear_value, clears[idx].color,819sizeof(fbinfo.rts[cb].clear_value));820fbinfo.nr_samples =821MAX2(fbinfo.nr_samples, view->pview.image->layout.nr_samples);822}823824if (subpass->zs_attachment.idx != VK_ATTACHMENT_UNUSED) {825view = fb->attachments[subpass->zs_attachment.idx].iview;826const struct util_format_description *fdesc =827util_format_description(view->pview.format);828829fbinfo.nr_samples =830MAX2(fbinfo.nr_samples, view->pview.image->layout.nr_samples);831832if (util_format_has_depth(fdesc)) {833fbinfo.zs.clear.z = subpass->zs_attachment.clear;834fbinfo.zs.clear_value.depth = clears[subpass->zs_attachment.idx].depth;835fbinfo.zs.view.zs = &view->pview;836}837838if (util_format_has_depth(fdesc)) {839fbinfo.zs.clear.s = subpass->zs_attachment.clear;840fbinfo.zs.clear_value.stencil = clears[subpass->zs_attachment.idx].depth;841if (!fbinfo.zs.view.zs)842fbinfo.zs.view.s = &view->pview;843}844}845846return pan_emit_fbd(pdev, &fbinfo, tlsinfo, tilerctx, desc);847}848849850