1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2022 Imagination Technologies Ltd. 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 5bf215546Sopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 6bf215546Sopenharmony_ci * in the Software without restriction, including without limitation the rights 7bf215546Sopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8bf215546Sopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 9bf215546Sopenharmony_ci * 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 THE 18bf215546Sopenharmony_ci * 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 FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include <stdbool.h> 25bf215546Sopenharmony_ci#include <stddef.h> 26bf215546Sopenharmony_ci#include <stdint.h> 27bf215546Sopenharmony_ci#include <string.h> 28bf215546Sopenharmony_ci#include <vulkan/vulkan_core.h> 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "compiler/shader_enums.h" 31bf215546Sopenharmony_ci#include "hwdef/rogue_hw_utils.h" 32bf215546Sopenharmony_ci#include "pvr_device_info.h" 33bf215546Sopenharmony_ci#include "pvr_hardcode.h" 34bf215546Sopenharmony_ci#include "pvr_private.h" 35bf215546Sopenharmony_ci#include "rogue/rogue.h" 36bf215546Sopenharmony_ci#include "usc/hardcoded_apps/pvr_simple_compute.h" 37bf215546Sopenharmony_ci#include "util/macros.h" 38bf215546Sopenharmony_ci#include "util/u_process.h" 39bf215546Sopenharmony_ci 40bf215546Sopenharmony_ci/** 41bf215546Sopenharmony_ci * \file pvr_hardcode.c 42bf215546Sopenharmony_ci * 43bf215546Sopenharmony_ci * \brief Contains hard coding functions. 44bf215546Sopenharmony_ci * This should eventually be deleted as the compiler becomes more capable. 45bf215546Sopenharmony_ci */ 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci#define PVR_AXE_1_16M_BVNC PVR_BVNC_PACK(33, 15, 11, 3) 48bf215546Sopenharmony_ci#define PVR_GX6250_BVNC PVR_BVNC_PACK(4, 40, 2, 51) 49bf215546Sopenharmony_ci 50bf215546Sopenharmony_cienum pvr_hard_code_shader_type { 51bf215546Sopenharmony_ci PVR_HARD_CODE_SHADER_TYPE_COMPUTE, 52bf215546Sopenharmony_ci PVR_HARD_CODE_SHADER_TYPE_GRAPHICS, 53bf215546Sopenharmony_ci}; 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci/* Table indicating which demo and for which device the compiler is capable of 56bf215546Sopenharmony_ci * generating valid shaders. 57bf215546Sopenharmony_ci */ 58bf215546Sopenharmony_cistatic struct { 59bf215546Sopenharmony_ci const char *const name; 60bf215546Sopenharmony_ci uint64_t bvncs[3]; 61bf215546Sopenharmony_ci} compatiblity_table[] = { 62bf215546Sopenharmony_ci { 63bf215546Sopenharmony_ci .name = "triangle", 64bf215546Sopenharmony_ci .bvncs = { PVR_GX6250_BVNC, }, 65bf215546Sopenharmony_ci }, 66bf215546Sopenharmony_ci}; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_cistatic const struct pvr_hard_coding_data { 69bf215546Sopenharmony_ci const char *const name; 70bf215546Sopenharmony_ci uint64_t bvnc; 71bf215546Sopenharmony_ci enum pvr_hard_code_shader_type type; 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci union { 74bf215546Sopenharmony_ci struct { 75bf215546Sopenharmony_ci const uint8_t *const shader; 76bf215546Sopenharmony_ci size_t shader_size; 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci /* Note that the bo field will be unused. */ 79bf215546Sopenharmony_ci const struct pvr_compute_pipeline_shader_state shader_info; 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci const struct pvr_hard_code_compute_build_info build_info; 82bf215546Sopenharmony_ci } compute; 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_ci struct { 85bf215546Sopenharmony_ci /* Mask of MESA_SHADER_* (gl_shader_stage). */ 86bf215546Sopenharmony_ci uint32_t flags; 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci struct rogue_shader_binary *const *const vert_shaders; 89bf215546Sopenharmony_ci struct rogue_shader_binary *const *const frag_shaders; 90bf215546Sopenharmony_ci 91bf215546Sopenharmony_ci const struct pvr_vertex_shader_state *const *const vert_shader_states; 92bf215546Sopenharmony_ci const struct pvr_fragment_shader_state *const *const frag_shader_states; 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci const struct pvr_hard_code_graphics_build_info *const 95bf215546Sopenharmony_ci *const build_infos; 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci uint32_t shader_count; 98bf215546Sopenharmony_ci } graphics; 99bf215546Sopenharmony_ci }; 100bf215546Sopenharmony_ci 101bf215546Sopenharmony_ci} hard_coding_table[] = { 102bf215546Sopenharmony_ci { 103bf215546Sopenharmony_ci .name = "simple-compute", 104bf215546Sopenharmony_ci .bvnc = PVR_GX6250_BVNC, 105bf215546Sopenharmony_ci .type = PVR_HARD_CODE_SHADER_TYPE_COMPUTE, 106bf215546Sopenharmony_ci 107bf215546Sopenharmony_ci .compute = { 108bf215546Sopenharmony_ci .shader = pvr_simple_compute_shader, 109bf215546Sopenharmony_ci .shader_size = sizeof(pvr_simple_compute_shader), 110bf215546Sopenharmony_ci 111bf215546Sopenharmony_ci .shader_info = { 112bf215546Sopenharmony_ci .uses_atomic_ops = false, 113bf215546Sopenharmony_ci .uses_barrier = false, 114bf215546Sopenharmony_ci .uses_num_workgroups = false, 115bf215546Sopenharmony_ci 116bf215546Sopenharmony_ci .const_shared_reg_count = 4, 117bf215546Sopenharmony_ci .input_register_count = 8, 118bf215546Sopenharmony_ci .work_size = 1 * 1 * 1, 119bf215546Sopenharmony_ci .coefficient_register_count = 4, 120bf215546Sopenharmony_ci }, 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci .build_info = { 123bf215546Sopenharmony_ci .ubo_data = { 0 }, 124bf215546Sopenharmony_ci .compile_time_consts_data = { 125bf215546Sopenharmony_ci .static_consts = { 0 }, 126bf215546Sopenharmony_ci }, 127bf215546Sopenharmony_ci 128bf215546Sopenharmony_ci .local_invocation_regs = { 0, 1 }, 129bf215546Sopenharmony_ci .work_group_regs = { 0, 1, 2 }, 130bf215546Sopenharmony_ci .barrier_reg = ROGUE_REG_UNUSED, 131bf215546Sopenharmony_ci .usc_temps = 0, 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci .explicit_conts_usage = { 134bf215546Sopenharmony_ci .start_offset = 0, 135bf215546Sopenharmony_ci }, 136bf215546Sopenharmony_ci }, 137bf215546Sopenharmony_ci } 138bf215546Sopenharmony_ci }, 139bf215546Sopenharmony_ci}; 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_cistatic inline uint64_t 142bf215546Sopenharmony_cipvr_device_get_bvnc(const struct pvr_device_info *const dev_info) 143bf215546Sopenharmony_ci{ 144bf215546Sopenharmony_ci const struct pvr_device_ident *const ident = &dev_info->ident; 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci return PVR_BVNC_PACK(ident->b, ident->v, ident->n, ident->c); 147bf215546Sopenharmony_ci} 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_cibool pvr_hard_code_shader_required(const struct pvr_device_info *const dev_info) 150bf215546Sopenharmony_ci{ 151bf215546Sopenharmony_ci const char *const program = util_get_process_name(); 152bf215546Sopenharmony_ci const uint64_t bvnc = pvr_device_get_bvnc(dev_info); 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(compatiblity_table); i++) { 155bf215546Sopenharmony_ci for (uint32_t j = 0; j < ARRAY_SIZE(compatiblity_table[0].bvncs); j++) { 156bf215546Sopenharmony_ci if (bvnc != compatiblity_table[i].bvncs[j]) 157bf215546Sopenharmony_ci continue; 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci if (strcmp(program, compatiblity_table[i].name) == 0) 160bf215546Sopenharmony_ci return false; 161bf215546Sopenharmony_ci } 162bf215546Sopenharmony_ci } 163bf215546Sopenharmony_ci 164bf215546Sopenharmony_ci return true; 165bf215546Sopenharmony_ci} 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_cistatic const struct pvr_hard_coding_data * 168bf215546Sopenharmony_cipvr_get_hard_coding_data(const struct pvr_device_info *const dev_info) 169bf215546Sopenharmony_ci{ 170bf215546Sopenharmony_ci const char *const program = util_get_process_name(); 171bf215546Sopenharmony_ci const uint64_t bvnc = pvr_device_get_bvnc(dev_info); 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(hard_coding_table); i++) { 174bf215546Sopenharmony_ci if (bvnc != hard_coding_table[i].bvnc) 175bf215546Sopenharmony_ci continue; 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci if (strcmp(program, hard_coding_table[i].name) == 0) 178bf215546Sopenharmony_ci return &hard_coding_table[i]; 179bf215546Sopenharmony_ci } 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci mesa_loge("Could not find hard coding data for %s", program); 182bf215546Sopenharmony_ci 183bf215546Sopenharmony_ci return NULL; 184bf215546Sopenharmony_ci} 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ciVkResult pvr_hard_code_compute_pipeline( 187bf215546Sopenharmony_ci struct pvr_device *const device, 188bf215546Sopenharmony_ci struct pvr_compute_pipeline_shader_state *const shader_state_out, 189bf215546Sopenharmony_ci struct pvr_hard_code_compute_build_info *const build_info_out) 190bf215546Sopenharmony_ci{ 191bf215546Sopenharmony_ci const uint32_t cache_line_size = 192bf215546Sopenharmony_ci rogue_get_slc_cache_line_size(&device->pdevice->dev_info); 193bf215546Sopenharmony_ci const struct pvr_hard_coding_data *const data = 194bf215546Sopenharmony_ci pvr_get_hard_coding_data(&device->pdevice->dev_info); 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci assert(data->type == PVR_HARD_CODE_SHADER_TYPE_COMPUTE); 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci mesa_logd("Hard coding compute pipeline for %s", data->name); 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci *build_info_out = data->compute.build_info; 201bf215546Sopenharmony_ci *shader_state_out = data->compute.shader_info; 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci return pvr_gpu_upload_usc(device, 204bf215546Sopenharmony_ci data->compute.shader, 205bf215546Sopenharmony_ci data->compute.shader_size, 206bf215546Sopenharmony_ci cache_line_size, 207bf215546Sopenharmony_ci &shader_state_out->bo); 208bf215546Sopenharmony_ci} 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ciuint32_t 211bf215546Sopenharmony_cipvr_hard_code_graphics_get_flags(const struct pvr_device_info *const dev_info) 212bf215546Sopenharmony_ci{ 213bf215546Sopenharmony_ci const struct pvr_hard_coding_data *const data = 214bf215546Sopenharmony_ci pvr_get_hard_coding_data(dev_info); 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS); 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci return data->graphics.flags; 219bf215546Sopenharmony_ci} 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_civoid pvr_hard_code_graphics_shader(const struct pvr_device_info *const dev_info, 222bf215546Sopenharmony_ci uint32_t pipeline_n, 223bf215546Sopenharmony_ci gl_shader_stage stage, 224bf215546Sopenharmony_ci struct rogue_shader_binary **const shader_out) 225bf215546Sopenharmony_ci{ 226bf215546Sopenharmony_ci const struct pvr_hard_coding_data *const data = 227bf215546Sopenharmony_ci pvr_get_hard_coding_data(dev_info); 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS); 230bf215546Sopenharmony_ci assert(pipeline_n < data->graphics.shader_count); 231bf215546Sopenharmony_ci assert(data->graphics.flags & BITFIELD_BIT(stage)); 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci mesa_logd("Hard coding %s stage shader for \"%s\" demo.", 234bf215546Sopenharmony_ci _mesa_shader_stage_to_string(stage), 235bf215546Sopenharmony_ci data->name); 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ci switch (stage) { 238bf215546Sopenharmony_ci case MESA_SHADER_VERTEX: 239bf215546Sopenharmony_ci *shader_out = data->graphics.vert_shaders[pipeline_n]; 240bf215546Sopenharmony_ci break; 241bf215546Sopenharmony_ci 242bf215546Sopenharmony_ci case MESA_SHADER_FRAGMENT: 243bf215546Sopenharmony_ci *shader_out = data->graphics.frag_shaders[pipeline_n]; 244bf215546Sopenharmony_ci break; 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_ci default: 247bf215546Sopenharmony_ci unreachable("Unsupported stage."); 248bf215546Sopenharmony_ci } 249bf215546Sopenharmony_ci} 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_civoid pvr_hard_code_graphics_vertex_state( 252bf215546Sopenharmony_ci const struct pvr_device_info *const dev_info, 253bf215546Sopenharmony_ci uint32_t pipeline_n, 254bf215546Sopenharmony_ci struct pvr_vertex_shader_state *const vert_state_out) 255bf215546Sopenharmony_ci{ 256bf215546Sopenharmony_ci const struct pvr_hard_coding_data *const data = 257bf215546Sopenharmony_ci pvr_get_hard_coding_data(dev_info); 258bf215546Sopenharmony_ci 259bf215546Sopenharmony_ci assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS); 260bf215546Sopenharmony_ci assert(pipeline_n < data->graphics.shader_count); 261bf215546Sopenharmony_ci assert(data->graphics.flags & BITFIELD_BIT(MESA_SHADER_VERTEX)); 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci *vert_state_out = *data->graphics.vert_shader_states[0]; 264bf215546Sopenharmony_ci} 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_civoid pvr_hard_code_graphics_fragment_state( 267bf215546Sopenharmony_ci const struct pvr_device_info *const dev_info, 268bf215546Sopenharmony_ci uint32_t pipeline_n, 269bf215546Sopenharmony_ci struct pvr_fragment_shader_state *const frag_state_out) 270bf215546Sopenharmony_ci{ 271bf215546Sopenharmony_ci const struct pvr_hard_coding_data *const data = 272bf215546Sopenharmony_ci pvr_get_hard_coding_data(dev_info); 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS); 275bf215546Sopenharmony_ci assert(pipeline_n < data->graphics.shader_count); 276bf215546Sopenharmony_ci assert(data->graphics.flags & BITFIELD_BIT(MESA_SHADER_FRAGMENT)); 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci *frag_state_out = *data->graphics.frag_shader_states[0]; 279bf215546Sopenharmony_ci} 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_civoid pvr_hard_code_graphics_get_build_info( 282bf215546Sopenharmony_ci const struct pvr_device_info *const dev_info, 283bf215546Sopenharmony_ci uint32_t pipeline_n, 284bf215546Sopenharmony_ci gl_shader_stage stage, 285bf215546Sopenharmony_ci struct rogue_common_build_data *const common_build_data, 286bf215546Sopenharmony_ci struct rogue_build_data *const build_data, 287bf215546Sopenharmony_ci struct pvr_explicit_constant_usage *const explicit_const_usage) 288bf215546Sopenharmony_ci{ 289bf215546Sopenharmony_ci const struct pvr_hard_coding_data *const data = 290bf215546Sopenharmony_ci pvr_get_hard_coding_data(dev_info); 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci assert(data->type == PVR_HARD_CODE_SHADER_TYPE_GRAPHICS); 293bf215546Sopenharmony_ci assert(pipeline_n < data->graphics.shader_count); 294bf215546Sopenharmony_ci assert(data->graphics.flags & BITFIELD_BIT(stage)); 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci switch (stage) { 297bf215546Sopenharmony_ci case MESA_SHADER_VERTEX: 298bf215546Sopenharmony_ci assert( 299bf215546Sopenharmony_ci data->graphics.build_infos[pipeline_n]->vert_common_data.temps == 300bf215546Sopenharmony_ci data->graphics.vert_shader_states[pipeline_n]->stage_state.temps_count); 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci assert(data->graphics.build_infos[pipeline_n]->vert_common_data.coeffs == 303bf215546Sopenharmony_ci data->graphics.vert_shader_states[pipeline_n] 304bf215546Sopenharmony_ci ->stage_state.coefficient_size); 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci build_data->vs = data->graphics.build_infos[pipeline_n]->stage_data.vs; 307bf215546Sopenharmony_ci *common_build_data = 308bf215546Sopenharmony_ci data->graphics.build_infos[pipeline_n]->vert_common_data; 309bf215546Sopenharmony_ci *explicit_const_usage = 310bf215546Sopenharmony_ci data->graphics.build_infos[pipeline_n]->vert_explicit_conts_usage; 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci break; 313bf215546Sopenharmony_ci 314bf215546Sopenharmony_ci case MESA_SHADER_FRAGMENT: 315bf215546Sopenharmony_ci assert( 316bf215546Sopenharmony_ci data->graphics.build_infos[pipeline_n]->frag_common_data.temps == 317bf215546Sopenharmony_ci data->graphics.frag_shader_states[pipeline_n]->stage_state.temps_count); 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci assert(data->graphics.build_infos[pipeline_n]->frag_common_data.coeffs == 320bf215546Sopenharmony_ci data->graphics.frag_shader_states[pipeline_n] 321bf215546Sopenharmony_ci ->stage_state.coefficient_size); 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci build_data->fs = data->graphics.build_infos[pipeline_n]->stage_data.fs; 324bf215546Sopenharmony_ci *common_build_data = 325bf215546Sopenharmony_ci data->graphics.build_infos[pipeline_n]->frag_common_data; 326bf215546Sopenharmony_ci *explicit_const_usage = 327bf215546Sopenharmony_ci data->graphics.build_infos[pipeline_n]->frag_explicit_conts_usage; 328bf215546Sopenharmony_ci 329bf215546Sopenharmony_ci break; 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci default: 332bf215546Sopenharmony_ci unreachable("Unsupported stage."); 333bf215546Sopenharmony_ci } 334bf215546Sopenharmony_ci} 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_civoid pvr_hard_code_get_idfwdf_program( 337bf215546Sopenharmony_ci const struct pvr_device_info *const dev_info, 338bf215546Sopenharmony_ci const struct rogue_shader_binary **const program_out, 339bf215546Sopenharmony_ci uint32_t *usc_shareds_out, 340bf215546Sopenharmony_ci uint32_t *usc_temps_out) 341bf215546Sopenharmony_ci{ 342bf215546Sopenharmony_ci static const struct rogue_shader_binary shader = { 343bf215546Sopenharmony_ci .size = 8U, 344bf215546Sopenharmony_ci .data = { 0, 0, 0, 0, 0, 0, 0, 0 } 345bf215546Sopenharmony_ci }; 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci mesa_loge("No hard coded idfwdf program. Returning empty program."); 348bf215546Sopenharmony_ci *program_out = &shader; 349bf215546Sopenharmony_ci *usc_shareds_out = 12U; 350bf215546Sopenharmony_ci *usc_temps_out = 4U; 351bf215546Sopenharmony_ci} 352