Path: blob/21.2-virgl/src/panfrost/lib/pan_shader.h
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, ARISING FROM,19* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE20* SOFTWARE.21*22*/2324#ifndef __PAN_SHADER_H__25#define __PAN_SHADER_H__2627#include "compiler/nir/nir.h"28#include "panfrost/util/pan_ir.h"2930#include "pan_device.h"31#include "midgard_pack.h"3233struct panfrost_device;3435const nir_shader_compiler_options *36pan_shader_get_compiler_options(const struct panfrost_device *dev);3738void39pan_shader_compile(const struct panfrost_device *dev,40nir_shader *nir,41const struct panfrost_compile_inputs *inputs,42struct util_dynarray *binary,43struct pan_shader_info *info);4445static inline void46pan_shader_prepare_midgard_rsd(const struct pan_shader_info *info,47struct MALI_RENDERER_STATE *rsd)48{49assert((info->push.count & 3) == 0);5051rsd->properties.midgard.uniform_count = info->push.count / 4;52rsd->properties.midgard.shader_has_side_effects = info->writes_global;53rsd->properties.midgard.fp_mode = MALI_FP_MODE_GL_INF_NAN_ALLOWED;5455/* For fragment shaders, work register count, early-z, reads at draw-time */5657if (info->stage != MESA_SHADER_FRAGMENT) {58rsd->properties.midgard.work_register_count = info->work_reg_count;59} else {60rsd->properties.midgard.shader_reads_tilebuffer =61info->fs.outputs_read;6263/* However, forcing early-z in the shader overrides draw-time */64rsd->properties.midgard.force_early_z =65info->fs.early_fragment_tests;66}67}6869/* Classify a shader into the following pixel kill categories:70*71* (force early, strong early): no side effects/depth/stencil/coverage writes (force)72* (weak early, weak early): no side effects/depth/stencil/coverage writes73* (weak early, force late): no side effects/depth/stencil writes74* (force late, weak early): side effects but no depth/stencil/coverage writes75* (force late, force early): only run for side effects76* (force late, force late): depth/stencil writes77*78* Note that discard is considered a coverage write. TODO: what about79* alpha-to-coverage?80* */8182#define SET_PIXEL_KILL(kill, update) do { \83rsd->properties.bifrost.pixel_kill_operation = MALI_PIXEL_KILL_## kill; \84rsd->properties.bifrost.zs_update_operation = MALI_PIXEL_KILL_## update; \85} while(0)8687static inline void88pan_shader_classify_pixel_kill_coverage(const struct pan_shader_info *info,89struct MALI_RENDERER_STATE *rsd)90{91bool force_early = info->fs.early_fragment_tests;92bool sidefx = info->writes_global;93bool coverage = info->fs.writes_coverage || info->fs.can_discard;94bool depth = info->fs.writes_depth;95bool stencil = info->fs.writes_stencil;9697rsd->properties.bifrost.shader_modifies_coverage = coverage;9899if (force_early)100SET_PIXEL_KILL(FORCE_EARLY, STRONG_EARLY);101else if (depth || stencil || (sidefx && coverage))102SET_PIXEL_KILL(FORCE_LATE, FORCE_LATE);103else if (sidefx)104SET_PIXEL_KILL(FORCE_LATE, WEAK_EARLY);105else if (coverage)106SET_PIXEL_KILL(WEAK_EARLY, FORCE_LATE);107else108SET_PIXEL_KILL(WEAK_EARLY, WEAK_EARLY);109}110111#undef SET_PIXEL_KILL112113static inline void114pan_shader_prepare_bifrost_rsd(const struct panfrost_device *dev,115const struct pan_shader_info *info,116struct MALI_RENDERER_STATE *rsd)117{118unsigned fau_count = DIV_ROUND_UP(info->push.count, 2);119rsd->preload.uniform_count = fau_count;120121if (dev->arch == 7) {122rsd->properties.bifrost.shader_register_allocation =123(info->work_reg_count <= 32) ?124MALI_SHADER_REGISTER_ALLOCATION_32_PER_THREAD :125MALI_SHADER_REGISTER_ALLOCATION_64_PER_THREAD;126}127128switch (info->stage) {129case MESA_SHADER_VERTEX:130rsd->preload.vertex.vertex_id = true;131rsd->preload.vertex.instance_id = true;132break;133134case MESA_SHADER_FRAGMENT:135pan_shader_classify_pixel_kill_coverage(info, rsd);136137if (dev->arch > 6) {138rsd->properties.bifrost.shader_wait_dependency_6 = info->bifrost.wait_6;139rsd->properties.bifrost.shader_wait_dependency_7 = info->bifrost.wait_7;140}141142rsd->properties.bifrost.allow_forward_pixel_to_be_killed =143!info->fs.sidefx;144145rsd->preload.fragment.fragment_position = info->fs.reads_frag_coord;146rsd->preload.fragment.coverage = true;147rsd->preload.fragment.primitive_flags = info->fs.reads_face;148149/* Contains sample ID and sample mask. Sample position and150* helper invocation are expressed in terms of the above, so151* preload for those too */152rsd->preload.fragment.sample_mask_id =153info->fs.reads_sample_id |154info->fs.reads_sample_pos |155info->fs.reads_sample_mask_in |156info->fs.reads_helper_invocation |157info->fs.sample_shading;158159rsd->message_preload_1 = info->bifrost.messages[0];160rsd->message_preload_2 = info->bifrost.messages[1];161break;162163case MESA_SHADER_COMPUTE:164rsd->preload.compute.local_invocation_xy = true;165rsd->preload.compute.local_invocation_z = true;166rsd->preload.compute.work_group_x = true;167rsd->preload.compute.work_group_y = true;168rsd->preload.compute.work_group_z = true;169rsd->preload.compute.global_invocation_x = true;170rsd->preload.compute.global_invocation_y = true;171rsd->preload.compute.global_invocation_z = true;172break;173174default:175unreachable("TODO");176}177}178179static inline void180pan_shader_prepare_rsd(const struct panfrost_device *dev,181const struct pan_shader_info *shader_info,182mali_ptr shader_ptr,183struct MALI_RENDERER_STATE *rsd)184{185if (!pan_is_bifrost(dev))186shader_ptr |= shader_info->midgard.first_tag;187188rsd->shader.shader = shader_ptr;189rsd->shader.attribute_count = shader_info->attribute_count;190rsd->shader.varying_count = shader_info->varyings.input_count +191shader_info->varyings.output_count;192rsd->shader.texture_count = shader_info->texture_count;193rsd->shader.sampler_count = shader_info->sampler_count;194rsd->properties.shader_contains_barrier = shader_info->contains_barrier;195rsd->properties.uniform_buffer_count = shader_info->ubo_count;196197if (shader_info->stage == MESA_SHADER_FRAGMENT) {198rsd->properties.shader_contains_barrier |=199shader_info->fs.helper_invocations;200rsd->properties.stencil_from_shader =201shader_info->fs.writes_stencil;202rsd->properties.depth_source =203shader_info->fs.writes_depth ?204MALI_DEPTH_SOURCE_SHADER :205MALI_DEPTH_SOURCE_FIXED_FUNCTION;206207/* This also needs to be set if the API forces per-sample208* shading, but that'll just got ORed in */209rsd->multisample_misc.evaluate_per_sample =210shader_info->fs.sample_shading;211}212213if (pan_is_bifrost(dev))214pan_shader_prepare_bifrost_rsd(dev, shader_info, rsd);215else216pan_shader_prepare_midgard_rsd(shader_info, rsd);217}218219#endif220221222