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 <stdio.h> 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci#include "compiler/shader_enums.h" 30bf215546Sopenharmony_ci#include "compiler/spirv/nir_spirv.h" 31bf215546Sopenharmony_ci#include "nir/nir.h" 32bf215546Sopenharmony_ci#include "rogue.h" 33bf215546Sopenharmony_ci#include "rogue_build_data.h" 34bf215546Sopenharmony_ci#include "rogue_compiler.h" 35bf215546Sopenharmony_ci#include "rogue_constreg.h" 36bf215546Sopenharmony_ci#include "rogue_encode.h" 37bf215546Sopenharmony_ci#include "rogue_nir.h" 38bf215546Sopenharmony_ci#include "rogue_nir_helpers.h" 39bf215546Sopenharmony_ci#include "rogue_operand.h" 40bf215546Sopenharmony_ci#include "rogue_regalloc.h" 41bf215546Sopenharmony_ci#include "rogue_shader.h" 42bf215546Sopenharmony_ci#include "rogue_validate.h" 43bf215546Sopenharmony_ci#include "util/macros.h" 44bf215546Sopenharmony_ci#include "util/memstream.h" 45bf215546Sopenharmony_ci#include "util/ralloc.h" 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_ci/** 48bf215546Sopenharmony_ci * \file rogue.c 49bf215546Sopenharmony_ci * 50bf215546Sopenharmony_ci * \brief Contains the top-level Rogue compiler interface for Vulkan driver and 51bf215546Sopenharmony_ci * the offline compiler. 52bf215546Sopenharmony_ci */ 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci/** 55bf215546Sopenharmony_ci * \brief Converts a SPIR-V shader to NIR. 56bf215546Sopenharmony_ci * 57bf215546Sopenharmony_ci * \param[in] ctx Shared multi-stage build context. 58bf215546Sopenharmony_ci * \param[in] stage Shader stage. 59bf215546Sopenharmony_ci * \param[in] spirv_size SPIR-V data length in DWORDs. 60bf215546Sopenharmony_ci * \param[in] spirv_data SPIR-V data. 61bf215546Sopenharmony_ci * \param[in] num_spec Number of SPIR-V specializations. 62bf215546Sopenharmony_ci * \param[in] spec SPIR-V specializations. 63bf215546Sopenharmony_ci * \return A nir_shader* if successful, or NULL if unsuccessful. 64bf215546Sopenharmony_ci */ 65bf215546Sopenharmony_cinir_shader *rogue_spirv_to_nir(struct rogue_build_ctx *ctx, 66bf215546Sopenharmony_ci gl_shader_stage stage, 67bf215546Sopenharmony_ci const char *entry, 68bf215546Sopenharmony_ci size_t spirv_size, 69bf215546Sopenharmony_ci const uint32_t *spirv_data, 70bf215546Sopenharmony_ci unsigned num_spec, 71bf215546Sopenharmony_ci struct nir_spirv_specialization *spec) 72bf215546Sopenharmony_ci{ 73bf215546Sopenharmony_ci nir_shader *nir; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci nir = spirv_to_nir(spirv_data, 76bf215546Sopenharmony_ci spirv_size, 77bf215546Sopenharmony_ci spec, 78bf215546Sopenharmony_ci num_spec, 79bf215546Sopenharmony_ci stage, 80bf215546Sopenharmony_ci entry, 81bf215546Sopenharmony_ci rogue_get_spirv_options(ctx->compiler), 82bf215546Sopenharmony_ci rogue_get_compiler_options(ctx->compiler)); 83bf215546Sopenharmony_ci if (!nir) 84bf215546Sopenharmony_ci return NULL; 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci ralloc_steal(ctx, nir); 87bf215546Sopenharmony_ci 88bf215546Sopenharmony_ci /* Apply passes. */ 89bf215546Sopenharmony_ci if (!rogue_nir_passes(ctx, nir, stage)) { 90bf215546Sopenharmony_ci ralloc_free(nir); 91bf215546Sopenharmony_ci return NULL; 92bf215546Sopenharmony_ci } 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci /* Collect I/O data to pass back to the driver. */ 95bf215546Sopenharmony_ci if (!rogue_collect_io_data(ctx, nir)) { 96bf215546Sopenharmony_ci ralloc_free(nir); 97bf215546Sopenharmony_ci return NULL; 98bf215546Sopenharmony_ci } 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci return nir; 101bf215546Sopenharmony_ci} 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci/** 104bf215546Sopenharmony_ci * \brief Converts a Rogue shader to binary. 105bf215546Sopenharmony_ci * 106bf215546Sopenharmony_ci * \param[in] ctx Shared multi-stage build context. 107bf215546Sopenharmony_ci * \param[in] shader Rogue shader. 108bf215546Sopenharmony_ci * \return A rogue_shader_binary* if successful, or NULL if unsuccessful. 109bf215546Sopenharmony_ci */ 110bf215546Sopenharmony_cistruct rogue_shader_binary *rogue_to_binary(struct rogue_build_ctx *ctx, 111bf215546Sopenharmony_ci const struct rogue_shader *shader) 112bf215546Sopenharmony_ci{ 113bf215546Sopenharmony_ci struct rogue_shader_binary *binary; 114bf215546Sopenharmony_ci struct u_memstream mem; 115bf215546Sopenharmony_ci size_t buf_size; 116bf215546Sopenharmony_ci char *buf; 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci if (!rogue_validate_shader(shader)) 119bf215546Sopenharmony_ci return NULL; 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci if (!u_memstream_open(&mem, &buf, &buf_size)) 122bf215546Sopenharmony_ci return NULL; 123bf215546Sopenharmony_ci 124bf215546Sopenharmony_ci if (!rogue_encode_shader(shader, u_memstream_get(&mem))) { 125bf215546Sopenharmony_ci u_memstream_close(&mem); 126bf215546Sopenharmony_ci free(buf); 127bf215546Sopenharmony_ci return NULL; 128bf215546Sopenharmony_ci } 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci u_memstream_close(&mem); 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci binary = rzalloc_size(ctx, sizeof(*binary) + buf_size); 133bf215546Sopenharmony_ci if (!binary) { 134bf215546Sopenharmony_ci free(buf); 135bf215546Sopenharmony_ci return NULL; 136bf215546Sopenharmony_ci } 137bf215546Sopenharmony_ci 138bf215546Sopenharmony_ci binary->size = buf_size; 139bf215546Sopenharmony_ci memcpy(binary->data, buf, buf_size); 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci free(buf); 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci return binary; 144bf215546Sopenharmony_ci} 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_cistatic bool 147bf215546Sopenharmony_cisetup_alu_dest(struct rogue_instr *instr, size_t dest_index, nir_alu_instr *alu) 148bf215546Sopenharmony_ci{ 149bf215546Sopenharmony_ci assert(dest_index == 0); 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci /* Dest validation. */ 152bf215546Sopenharmony_ci assert(nir_dest_num_components(alu->dest.dest) == 1 || 153bf215546Sopenharmony_ci nir_dest_num_components(alu->dest.dest) == 4); 154bf215546Sopenharmony_ci assert(nir_dest_bit_size(alu->dest.dest) == 32); 155bf215546Sopenharmony_ci 156bf215546Sopenharmony_ci size_t nir_dest_reg = nir_alu_dest_regindex(alu); 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci if (nir_dest_num_components(alu->dest.dest) == 1) { 159bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, dest_index, nir_dest_reg)); 160bf215546Sopenharmony_ci } else { 161bf215546Sopenharmony_ci size_t comp = nir_alu_dest_comp(alu); 162bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg_vec(instr, 163bf215546Sopenharmony_ci dest_index, 164bf215546Sopenharmony_ci comp, 165bf215546Sopenharmony_ci nir_dest_reg)); 166bf215546Sopenharmony_ci } 167bf215546Sopenharmony_ci 168bf215546Sopenharmony_ci return true; 169bf215546Sopenharmony_ci} 170bf215546Sopenharmony_ci 171bf215546Sopenharmony_cistatic bool trans_constreg_operand(struct rogue_instr *instr, 172bf215546Sopenharmony_ci size_t operand_index, 173bf215546Sopenharmony_ci uint32_t const_value) 174bf215546Sopenharmony_ci{ 175bf215546Sopenharmony_ci size_t const_reg = rogue_constreg_lookup(const_value); 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci /* Only values that can be sourced from const regs should be left from the 178bf215546Sopenharmony_ci * rogue_nir_constreg pass. 179bf215546Sopenharmony_ci */ 180bf215546Sopenharmony_ci assert(const_reg != ROGUE_NO_CONST_REG); 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_reg(instr, 183bf215546Sopenharmony_ci operand_index, 184bf215546Sopenharmony_ci ROGUE_OPERAND_TYPE_REG_CONST, 185bf215546Sopenharmony_ci const_reg)); 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci return true; 188bf215546Sopenharmony_ci} 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_cistatic bool trans_nir_alu_fmax(struct rogue_shader *shader, nir_alu_instr *alu) 191bf215546Sopenharmony_ci{ 192bf215546Sopenharmony_ci /* Src validation. */ 193bf215546Sopenharmony_ci assert(nir_src_num_components(alu->src[0].src) == 1); 194bf215546Sopenharmony_ci assert(nir_src_bit_size(alu->src[0].src) == 32); 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci assert(nir_src_num_components(alu->src[1].src) == 1); 197bf215546Sopenharmony_ci assert(nir_src_bit_size(alu->src[1].src) == 32); 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MAX); 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci CHECK(setup_alu_dest(instr, 0, alu)); 202bf215546Sopenharmony_ci 203bf215546Sopenharmony_ci for (size_t u = 0; u < nir_op_infos[nir_op_fmax].num_inputs; ++u) { 204bf215546Sopenharmony_ci /* Handle values that can be pulled from const regs. */ 205bf215546Sopenharmony_ci if (nir_alu_src_is_const(alu, u)) { 206bf215546Sopenharmony_ci CHECK(trans_constreg_operand(instr, u + 1, nir_alu_src_const(alu, u))); 207bf215546Sopenharmony_ci continue; 208bf215546Sopenharmony_ci } 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci size_t nir_src_reg = nir_alu_src_regindex(alu, u); 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, u + 1, nir_src_reg)); 213bf215546Sopenharmony_ci } 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci return true; 216bf215546Sopenharmony_ci} 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_cistatic bool trans_nir_alu_fmin(struct rogue_shader *shader, nir_alu_instr *alu) 219bf215546Sopenharmony_ci{ 220bf215546Sopenharmony_ci /* Src validation. */ 221bf215546Sopenharmony_ci assert(nir_src_num_components(alu->src[0].src) == 1); 222bf215546Sopenharmony_ci assert(nir_src_bit_size(alu->src[0].src) == 32); 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci assert(nir_src_num_components(alu->src[1].src) == 1); 225bf215546Sopenharmony_ci assert(nir_src_bit_size(alu->src[1].src) == 32); 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MIN); 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci CHECK(setup_alu_dest(instr, 0, alu)); 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_ci for (size_t u = 0; u < nir_op_infos[nir_op_fmin].num_inputs; ++u) { 232bf215546Sopenharmony_ci /* Handle values that can be pulled from const regs. */ 233bf215546Sopenharmony_ci if (nir_alu_src_is_const(alu, u)) { 234bf215546Sopenharmony_ci CHECK(trans_constreg_operand(instr, u + 1, nir_alu_src_const(alu, u))); 235bf215546Sopenharmony_ci continue; 236bf215546Sopenharmony_ci } 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci size_t nir_src_reg = nir_alu_src_regindex(alu, u); 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, u + 1, nir_src_reg)); 241bf215546Sopenharmony_ci } 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci return true; 244bf215546Sopenharmony_ci} 245bf215546Sopenharmony_ci 246bf215546Sopenharmony_cistatic bool trans_nir_alu_mov_imm(struct rogue_shader *shader, 247bf215546Sopenharmony_ci nir_alu_instr *alu) 248bf215546Sopenharmony_ci{ 249bf215546Sopenharmony_ci /* Src validation. */ 250bf215546Sopenharmony_ci assert(nir_src_num_components(alu->src[0].src) == 1); 251bf215546Sopenharmony_ci assert(nir_src_bit_size(alu->src[0].src) == 32); 252bf215546Sopenharmony_ci 253bf215546Sopenharmony_ci uint32_t value = nir_alu_src_const(alu, 0); 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MOV_IMM); 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci CHECK(setup_alu_dest(instr, 0, alu)); 258bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_imm(instr, 1, value)); 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci return true; 261bf215546Sopenharmony_ci} 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_cistatic bool trans_nir_alu_mov(struct rogue_shader *shader, nir_alu_instr *alu) 264bf215546Sopenharmony_ci{ 265bf215546Sopenharmony_ci /* Constant value that isn't in constregs. */ 266bf215546Sopenharmony_ci if (nir_alu_src_is_const(alu, 0) && 267bf215546Sopenharmony_ci nir_dest_num_components(alu->dest.dest) == 1) 268bf215546Sopenharmony_ci return trans_nir_alu_mov_imm(shader, alu); 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci /* Src validation. */ 271bf215546Sopenharmony_ci assert(nir_src_num_components(alu->src[0].src) == 1); 272bf215546Sopenharmony_ci assert(nir_src_bit_size(alu->src[0].src) == 32); 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MOV); 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci CHECK(setup_alu_dest(instr, 0, alu)); 277bf215546Sopenharmony_ci 278bf215546Sopenharmony_ci /* Handle values that can be pulled from const regs. */ 279bf215546Sopenharmony_ci if (nir_alu_src_is_const(alu, 0)) { 280bf215546Sopenharmony_ci return trans_constreg_operand(instr, 1, nir_alu_src_const(alu, 0)); 281bf215546Sopenharmony_ci } 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci size_t nir_src_reg = nir_alu_src_regindex(alu, 0); 284bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, 1, nir_src_reg)); 285bf215546Sopenharmony_ci 286bf215546Sopenharmony_ci return true; 287bf215546Sopenharmony_ci} 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_cistatic bool trans_nir_alu_pack_unorm_4x8(struct rogue_shader *shader, 290bf215546Sopenharmony_ci nir_alu_instr *alu) 291bf215546Sopenharmony_ci{ 292bf215546Sopenharmony_ci /* Src/dest validation. */ 293bf215546Sopenharmony_ci assert(nir_dest_num_components(alu->dest.dest) == 1); 294bf215546Sopenharmony_ci assert(nir_dest_bit_size(alu->dest.dest) == 32); 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci assert(nir_src_num_components(alu->src[0].src) == 4); 297bf215546Sopenharmony_ci assert(nir_src_bit_size(alu->src[0].src) == 32); 298bf215546Sopenharmony_ci 299bf215546Sopenharmony_ci size_t nir_src_reg = nir_alu_src_regindex(alu, 0); 300bf215546Sopenharmony_ci size_t nir_dest_reg = nir_alu_dest_regindex(alu); 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_PACK_U8888); 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, 0, nir_dest_reg)); 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci /* Ensure all 4 components are being sourced in order. */ 307bf215546Sopenharmony_ci for (size_t u = 0; u < nir_src_num_components(alu->src[0].src); ++u) 308bf215546Sopenharmony_ci assert(alu->src->swizzle[u] == u); 309bf215546Sopenharmony_ci 310bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg_vec(instr, 311bf215546Sopenharmony_ci 1, 312bf215546Sopenharmony_ci ROGUE_COMPONENT_ALL, 313bf215546Sopenharmony_ci nir_src_reg)); 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci return true; 316bf215546Sopenharmony_ci} 317bf215546Sopenharmony_ci 318bf215546Sopenharmony_cistatic bool trans_nir_alu_fmul(struct rogue_shader *shader, nir_alu_instr *alu) 319bf215546Sopenharmony_ci{ 320bf215546Sopenharmony_ci /* Src validation. */ 321bf215546Sopenharmony_ci assert(nir_src_num_components(alu->src[0].src) == 1); 322bf215546Sopenharmony_ci assert(nir_src_bit_size(alu->src[0].src) == 32); 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ci assert(nir_src_num_components(alu->src[1].src) == 1); 325bf215546Sopenharmony_ci assert(nir_src_bit_size(alu->src[1].src) == 32); 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci size_t nir_in_reg_a = nir_alu_src_regindex(alu, 0); 328bf215546Sopenharmony_ci size_t nir_in_reg_b = nir_alu_src_regindex(alu, 1); 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MUL); 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci CHECK(setup_alu_dest(instr, 0, alu)); 333bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, 1, nir_in_reg_a)); 334bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, 2, nir_in_reg_b)); 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci return true; 337bf215546Sopenharmony_ci} 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_cistatic bool trans_nir_alu_ffma(struct rogue_shader *shader, nir_alu_instr *alu) 340bf215546Sopenharmony_ci{ 341bf215546Sopenharmony_ci /* Src validation. */ 342bf215546Sopenharmony_ci assert(nir_src_num_components(alu->src[0].src) == 1); 343bf215546Sopenharmony_ci assert(nir_src_bit_size(alu->src[0].src) == 32); 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci assert(nir_src_num_components(alu->src[1].src) == 1); 346bf215546Sopenharmony_ci assert(nir_src_bit_size(alu->src[1].src) == 32); 347bf215546Sopenharmony_ci 348bf215546Sopenharmony_ci assert(nir_src_num_components(alu->src[2].src) == 1); 349bf215546Sopenharmony_ci assert(nir_src_bit_size(alu->src[2].src) == 32); 350bf215546Sopenharmony_ci 351bf215546Sopenharmony_ci size_t nir_in_reg_a = nir_alu_src_regindex(alu, 0); 352bf215546Sopenharmony_ci size_t nir_in_reg_b = nir_alu_src_regindex(alu, 1); 353bf215546Sopenharmony_ci size_t nir_in_reg_c = nir_alu_src_regindex(alu, 2); 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_FMA); 356bf215546Sopenharmony_ci 357bf215546Sopenharmony_ci CHECK(setup_alu_dest(instr, 0, alu)); 358bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, 1, nir_in_reg_a)); 359bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, 2, nir_in_reg_b)); 360bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, 3, nir_in_reg_c)); 361bf215546Sopenharmony_ci 362bf215546Sopenharmony_ci return true; 363bf215546Sopenharmony_ci} 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_cistatic bool trans_nir_alu(struct rogue_shader *shader, nir_alu_instr *alu) 366bf215546Sopenharmony_ci{ 367bf215546Sopenharmony_ci switch (alu->op) { 368bf215546Sopenharmony_ci case nir_op_fmax: 369bf215546Sopenharmony_ci return trans_nir_alu_fmax(shader, alu); 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci case nir_op_fmin: 372bf215546Sopenharmony_ci return trans_nir_alu_fmin(shader, alu); 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci case nir_op_pack_unorm_4x8: 375bf215546Sopenharmony_ci return trans_nir_alu_pack_unorm_4x8(shader, alu); 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci case nir_op_mov: 378bf215546Sopenharmony_ci return trans_nir_alu_mov(shader, alu); 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci case nir_op_fmul: 381bf215546Sopenharmony_ci return trans_nir_alu_fmul(shader, alu); 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci case nir_op_ffma: 384bf215546Sopenharmony_ci return trans_nir_alu_ffma(shader, alu); 385bf215546Sopenharmony_ci 386bf215546Sopenharmony_ci default: 387bf215546Sopenharmony_ci break; 388bf215546Sopenharmony_ci } 389bf215546Sopenharmony_ci 390bf215546Sopenharmony_ci unreachable("Unimplemented NIR ALU instruction."); 391bf215546Sopenharmony_ci} 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_cistatic bool trans_nir_intrinsic_load_input_fs(struct rogue_shader *shader, 394bf215546Sopenharmony_ci nir_intrinsic_instr *intr) 395bf215546Sopenharmony_ci{ 396bf215546Sopenharmony_ci struct rogue_fs_build_data *fs_data = &shader->ctx->stage_data.fs; 397bf215546Sopenharmony_ci 398bf215546Sopenharmony_ci /* Src/dest validation. */ 399bf215546Sopenharmony_ci assert(nir_dest_num_components(intr->dest) == 1); 400bf215546Sopenharmony_ci assert(nir_dest_bit_size(intr->dest) == 32); 401bf215546Sopenharmony_ci 402bf215546Sopenharmony_ci assert(nir_src_num_components(intr->src[0]) == 1); 403bf215546Sopenharmony_ci assert(nir_src_bit_size(intr->src[0]) == 32); 404bf215546Sopenharmony_ci assert(nir_intr_src_is_const(intr, 0)); 405bf215546Sopenharmony_ci 406bf215546Sopenharmony_ci /* Intrinsic index validation. */ 407bf215546Sopenharmony_ci assert(nir_intrinsic_dest_type(intr) == nir_type_float32); 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_ci struct nir_io_semantics io_semantics = nir_intrinsic_io_semantics(intr); 410bf215546Sopenharmony_ci size_t component = nir_intrinsic_component(intr); 411bf215546Sopenharmony_ci size_t coeff_index = rogue_coeff_index_fs(&fs_data->iterator_args, 412bf215546Sopenharmony_ci io_semantics.location, 413bf215546Sopenharmony_ci component); 414bf215546Sopenharmony_ci size_t wcoeff_index = rogue_coeff_index_fs(&fs_data->iterator_args, ~0, 0); 415bf215546Sopenharmony_ci size_t drc_num = rogue_acquire_drc(shader); 416bf215546Sopenharmony_ci uint64_t source_count = nir_dest_num_components(intr->dest); 417bf215546Sopenharmony_ci 418bf215546Sopenharmony_ci size_t nir_dest_reg = nir_intr_dest_regindex(intr); 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_ci /* pixiter.w instruction. */ 421bf215546Sopenharmony_ci struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_PIX_ITER_W); 422bf215546Sopenharmony_ci 423bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, 0, nir_dest_reg)); 424bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_drc(instr, 1, drc_num)); 425bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_reg(instr, 426bf215546Sopenharmony_ci 2, 427bf215546Sopenharmony_ci ROGUE_OPERAND_TYPE_REG_COEFF, 428bf215546Sopenharmony_ci coeff_index)); 429bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_reg(instr, 430bf215546Sopenharmony_ci 3, 431bf215546Sopenharmony_ci ROGUE_OPERAND_TYPE_REG_COEFF, 432bf215546Sopenharmony_ci wcoeff_index)); 433bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_imm(instr, 4, source_count)); 434bf215546Sopenharmony_ci 435bf215546Sopenharmony_ci /* wdf instruction must follow the pixiter.w. */ 436bf215546Sopenharmony_ci instr = rogue_shader_insert(shader, ROGUE_OP_WDF); 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_drc(instr, 0, drc_num)); 439bf215546Sopenharmony_ci rogue_release_drc(shader, drc_num); 440bf215546Sopenharmony_ci 441bf215546Sopenharmony_ci return true; 442bf215546Sopenharmony_ci} 443bf215546Sopenharmony_ci 444bf215546Sopenharmony_cistatic bool trans_nir_intrinsic_load_input_vs(struct rogue_shader *shader, 445bf215546Sopenharmony_ci nir_intrinsic_instr *intr) 446bf215546Sopenharmony_ci{ 447bf215546Sopenharmony_ci /* Src/dest validation. */ 448bf215546Sopenharmony_ci assert(nir_dest_num_components(intr->dest) == 1); 449bf215546Sopenharmony_ci assert(nir_dest_bit_size(intr->dest) == 32); 450bf215546Sopenharmony_ci 451bf215546Sopenharmony_ci assert(nir_src_num_components(intr->src[0]) == 1); 452bf215546Sopenharmony_ci assert(nir_src_bit_size(intr->src[0]) == 32); 453bf215546Sopenharmony_ci assert(nir_intr_src_is_const(intr, 0)); 454bf215546Sopenharmony_ci 455bf215546Sopenharmony_ci /* Intrinsic index validation. */ 456bf215546Sopenharmony_ci assert(nir_intrinsic_dest_type(intr) == nir_type_float32); 457bf215546Sopenharmony_ci 458bf215546Sopenharmony_ci size_t component = nir_intrinsic_component(intr); 459bf215546Sopenharmony_ci struct nir_io_semantics io_semantics = nir_intrinsic_io_semantics(intr); 460bf215546Sopenharmony_ci size_t vi_reg_index = ((io_semantics.location - VERT_ATTRIB_GENERIC0) * 3) + 461bf215546Sopenharmony_ci component; /* TODO: get these properly with the 462bf215546Sopenharmony_ci * intrinsic index (ssa argument) 463bf215546Sopenharmony_ci */ 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci size_t nir_dest_reg = nir_intr_dest_regindex(intr); 466bf215546Sopenharmony_ci 467bf215546Sopenharmony_ci struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MOV); 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, 0, nir_dest_reg)); 470bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_reg(instr, 471bf215546Sopenharmony_ci 1, 472bf215546Sopenharmony_ci ROGUE_OPERAND_TYPE_REG_VERTEX_IN, 473bf215546Sopenharmony_ci vi_reg_index)); 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci return true; 476bf215546Sopenharmony_ci} 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_cistatic bool trans_nir_intrinsic_load_input(struct rogue_shader *shader, 479bf215546Sopenharmony_ci nir_intrinsic_instr *intr) 480bf215546Sopenharmony_ci{ 481bf215546Sopenharmony_ci switch (shader->stage) { 482bf215546Sopenharmony_ci case MESA_SHADER_FRAGMENT: 483bf215546Sopenharmony_ci return trans_nir_intrinsic_load_input_fs(shader, intr); 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_ci case MESA_SHADER_VERTEX: 486bf215546Sopenharmony_ci return trans_nir_intrinsic_load_input_vs(shader, intr); 487bf215546Sopenharmony_ci 488bf215546Sopenharmony_ci default: 489bf215546Sopenharmony_ci break; 490bf215546Sopenharmony_ci } 491bf215546Sopenharmony_ci 492bf215546Sopenharmony_ci unreachable("Unimplemented NIR load_input variant."); 493bf215546Sopenharmony_ci} 494bf215546Sopenharmony_ci 495bf215546Sopenharmony_cistatic bool trans_nir_intrinsic_store_output_fs(struct rogue_shader *shader, 496bf215546Sopenharmony_ci nir_intrinsic_instr *intr) 497bf215546Sopenharmony_ci{ 498bf215546Sopenharmony_ci /* Src/dest validation. */ 499bf215546Sopenharmony_ci assert(nir_src_num_components(intr->src[0]) == 1); 500bf215546Sopenharmony_ci assert(nir_src_bit_size(intr->src[0]) == 32); 501bf215546Sopenharmony_ci assert(!nir_intr_src_is_const(intr, 0)); 502bf215546Sopenharmony_ci 503bf215546Sopenharmony_ci assert(nir_src_num_components(intr->src[1]) == 1); 504bf215546Sopenharmony_ci assert(nir_src_bit_size(intr->src[1]) == 32); 505bf215546Sopenharmony_ci assert(nir_intr_src_is_const(intr, 1)); 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci /* Intrinsic index validation. */ 508bf215546Sopenharmony_ci assert(nir_intrinsic_src_type(intr) == nir_type_uint32); 509bf215546Sopenharmony_ci 510bf215546Sopenharmony_ci /* Fetch the output offset. */ 511bf215546Sopenharmony_ci /* TODO: Is this really the right value to use for pixel out reg. num? */ 512bf215546Sopenharmony_ci size_t offset = nir_intr_src_const(intr, 1); 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci /* Fetch the components. */ 515bf215546Sopenharmony_ci size_t src_reg = nir_intr_src_regindex(intr, 0); 516bf215546Sopenharmony_ci 517bf215546Sopenharmony_ci /* mov.olchk instruction. */ 518bf215546Sopenharmony_ci struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MOV); 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_reg(instr, 521bf215546Sopenharmony_ci 0, 522bf215546Sopenharmony_ci ROGUE_OPERAND_TYPE_REG_PIXEL_OUT, 523bf215546Sopenharmony_ci offset)); 524bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, 1, src_reg)); 525bf215546Sopenharmony_ci CHECK(rogue_instr_set_flag(instr, ROGUE_INSTR_FLAG_OLCHK)); 526bf215546Sopenharmony_ci 527bf215546Sopenharmony_ci return true; 528bf215546Sopenharmony_ci} 529bf215546Sopenharmony_ci 530bf215546Sopenharmony_cistatic bool trans_nir_intrinsic_store_output_vs(struct rogue_shader *shader, 531bf215546Sopenharmony_ci nir_intrinsic_instr *intr) 532bf215546Sopenharmony_ci{ 533bf215546Sopenharmony_ci struct rogue_vs_build_data *vs_data = &shader->ctx->stage_data.vs; 534bf215546Sopenharmony_ci 535bf215546Sopenharmony_ci /* Src/dest validation. */ 536bf215546Sopenharmony_ci assert(nir_src_num_components(intr->src[0]) == 1); 537bf215546Sopenharmony_ci assert(nir_src_bit_size(intr->src[0]) == 32); 538bf215546Sopenharmony_ci assert(!nir_intr_src_is_const(intr, 0)); 539bf215546Sopenharmony_ci 540bf215546Sopenharmony_ci assert(nir_src_num_components(intr->src[1]) == 1); 541bf215546Sopenharmony_ci assert(nir_src_bit_size(intr->src[1]) == 32); 542bf215546Sopenharmony_ci assert(nir_intr_src_is_const(intr, 1)); 543bf215546Sopenharmony_ci 544bf215546Sopenharmony_ci /* Intrinsic index validation. */ 545bf215546Sopenharmony_ci assert(nir_intrinsic_src_type(intr) == nir_type_float32); 546bf215546Sopenharmony_ci assert(util_bitcount(nir_intrinsic_write_mask(intr)) == 1); 547bf215546Sopenharmony_ci 548bf215546Sopenharmony_ci struct nir_io_semantics io_semantics = nir_intrinsic_io_semantics(intr); 549bf215546Sopenharmony_ci size_t component = nir_intrinsic_component(intr); 550bf215546Sopenharmony_ci size_t vo_index = rogue_output_index_vs(&vs_data->outputs, 551bf215546Sopenharmony_ci io_semantics.location, 552bf215546Sopenharmony_ci component); 553bf215546Sopenharmony_ci 554bf215546Sopenharmony_ci size_t src_reg = nir_intr_src_regindex(intr, 0); 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_VTXOUT); 557bf215546Sopenharmony_ci 558bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_imm(instr, 0, vo_index)); 559bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, 1, src_reg)); 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci return true; 562bf215546Sopenharmony_ci} 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_cistatic bool trans_nir_intrinsic_store_output(struct rogue_shader *shader, 565bf215546Sopenharmony_ci nir_intrinsic_instr *intr) 566bf215546Sopenharmony_ci{ 567bf215546Sopenharmony_ci switch (shader->stage) { 568bf215546Sopenharmony_ci case MESA_SHADER_FRAGMENT: 569bf215546Sopenharmony_ci return trans_nir_intrinsic_store_output_fs(shader, intr); 570bf215546Sopenharmony_ci 571bf215546Sopenharmony_ci case MESA_SHADER_VERTEX: 572bf215546Sopenharmony_ci return trans_nir_intrinsic_store_output_vs(shader, intr); 573bf215546Sopenharmony_ci 574bf215546Sopenharmony_ci default: 575bf215546Sopenharmony_ci break; 576bf215546Sopenharmony_ci } 577bf215546Sopenharmony_ci 578bf215546Sopenharmony_ci unreachable("Unimplemented NIR store_output variant."); 579bf215546Sopenharmony_ci} 580bf215546Sopenharmony_ci 581bf215546Sopenharmony_cistatic bool trans_nir_intrinsic_load_ubo(struct rogue_shader *shader, 582bf215546Sopenharmony_ci nir_intrinsic_instr *intr) 583bf215546Sopenharmony_ci{ 584bf215546Sopenharmony_ci struct rogue_ubo_data *ubo_data = 585bf215546Sopenharmony_ci &shader->ctx->common_data[shader->stage].ubo_data; 586bf215546Sopenharmony_ci 587bf215546Sopenharmony_ci /* Src/dest validation. */ 588bf215546Sopenharmony_ci assert(nir_dest_num_components(intr->dest) == 1); 589bf215546Sopenharmony_ci assert(nir_dest_bit_size(intr->dest) == 32); 590bf215546Sopenharmony_ci 591bf215546Sopenharmony_ci assert(nir_src_num_components(intr->src[0]) == 2); 592bf215546Sopenharmony_ci assert(nir_src_bit_size(intr->src[0]) == 32); 593bf215546Sopenharmony_ci assert(nir_intr_src_is_const(intr, 0)); 594bf215546Sopenharmony_ci 595bf215546Sopenharmony_ci assert(nir_src_num_components(intr->src[1]) == 1); 596bf215546Sopenharmony_ci assert(nir_src_bit_size(intr->src[1]) == 32); 597bf215546Sopenharmony_ci assert(nir_intr_src_is_const(intr, 1)); 598bf215546Sopenharmony_ci 599bf215546Sopenharmony_ci /* Intrinsic index validation. */ 600bf215546Sopenharmony_ci assert((nir_intrinsic_range_base(intr) % ROGUE_REG_SIZE_BYTES) == 0); 601bf215546Sopenharmony_ci assert(nir_intrinsic_range(intr) == ROGUE_REG_SIZE_BYTES); 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_ci size_t nir_dest_reg = nir_intr_dest_regindex(intr); 604bf215546Sopenharmony_ci 605bf215546Sopenharmony_ci size_t desc_set = nir_intr_src_comp_const(intr, 0, 0); 606bf215546Sopenharmony_ci size_t binding = nir_intr_src_comp_const(intr, 0, 1); 607bf215546Sopenharmony_ci size_t offset = nir_intrinsic_range_base(intr); 608bf215546Sopenharmony_ci 609bf215546Sopenharmony_ci size_t sh_num = rogue_ubo_reg(ubo_data, desc_set, binding, offset); 610bf215546Sopenharmony_ci 611bf215546Sopenharmony_ci struct rogue_instr *instr = rogue_shader_insert(shader, ROGUE_OP_MOV); 612bf215546Sopenharmony_ci 613bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_vreg(instr, 0, nir_dest_reg)); 614bf215546Sopenharmony_ci CHECK(rogue_instr_set_operand_reg(instr, 615bf215546Sopenharmony_ci 1, 616bf215546Sopenharmony_ci ROGUE_OPERAND_TYPE_REG_SHARED, 617bf215546Sopenharmony_ci sh_num)); 618bf215546Sopenharmony_ci return true; 619bf215546Sopenharmony_ci} 620bf215546Sopenharmony_ci 621bf215546Sopenharmony_cistatic bool trans_nir_intrinsic(struct rogue_shader *shader, 622bf215546Sopenharmony_ci nir_intrinsic_instr *intr) 623bf215546Sopenharmony_ci{ 624bf215546Sopenharmony_ci switch (intr->intrinsic) { 625bf215546Sopenharmony_ci case nir_intrinsic_load_input: 626bf215546Sopenharmony_ci return trans_nir_intrinsic_load_input(shader, intr); 627bf215546Sopenharmony_ci 628bf215546Sopenharmony_ci case nir_intrinsic_store_output: 629bf215546Sopenharmony_ci return trans_nir_intrinsic_store_output(shader, intr); 630bf215546Sopenharmony_ci 631bf215546Sopenharmony_ci case nir_intrinsic_load_ubo: 632bf215546Sopenharmony_ci return trans_nir_intrinsic_load_ubo(shader, intr); 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_ci default: 635bf215546Sopenharmony_ci break; 636bf215546Sopenharmony_ci } 637bf215546Sopenharmony_ci 638bf215546Sopenharmony_ci unreachable("Unimplemented NIR intrinsic instruction."); 639bf215546Sopenharmony_ci} 640bf215546Sopenharmony_ci 641bf215546Sopenharmony_cistatic bool trans_nir_load_const(struct rogue_shader *shader, 642bf215546Sopenharmony_ci nir_load_const_instr *load_const) 643bf215546Sopenharmony_ci{ 644bf215546Sopenharmony_ci /* Src/dest validation. */ 645bf215546Sopenharmony_ci assert(load_const->def.bit_size == 32); 646bf215546Sopenharmony_ci 647bf215546Sopenharmony_ci /* Ensure that two-component load_consts are used only by load_ubos. */ 648bf215546Sopenharmony_ci if (load_const->def.num_components == 2) { 649bf215546Sopenharmony_ci nir_foreach_use (use_src, &load_const->def) { 650bf215546Sopenharmony_ci nir_instr *instr = use_src->parent_instr; 651bf215546Sopenharmony_ci assert(instr->type == nir_instr_type_intrinsic); 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci ASSERTED nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); 654bf215546Sopenharmony_ci assert(intr->intrinsic == nir_intrinsic_load_ubo); 655bf215546Sopenharmony_ci } 656bf215546Sopenharmony_ci } else { 657bf215546Sopenharmony_ci assert(load_const->def.num_components == 1); 658bf215546Sopenharmony_ci } 659bf215546Sopenharmony_ci 660bf215546Sopenharmony_ci /* TODO: This is currently done in MOV_IMM, but instead now would be the 661bf215546Sopenharmony_ci * time to lookup the constant value, see if it lives in const regs, or if 662bf215546Sopenharmony_ci * it needs to generate a MOV_IMM (or be constant calc-ed). 663bf215546Sopenharmony_ci */ 664bf215546Sopenharmony_ci return true; 665bf215546Sopenharmony_ci} 666bf215546Sopenharmony_ci 667bf215546Sopenharmony_cistatic bool trans_nir_jump_return(struct rogue_shader *shader, 668bf215546Sopenharmony_ci nir_jump_instr *jump) 669bf215546Sopenharmony_ci{ 670bf215546Sopenharmony_ci enum rogue_opcode return_op; 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_ci switch (shader->stage) { 673bf215546Sopenharmony_ci case MESA_SHADER_FRAGMENT: 674bf215546Sopenharmony_ci return_op = ROGUE_OP_END_FRAG; 675bf215546Sopenharmony_ci break; 676bf215546Sopenharmony_ci 677bf215546Sopenharmony_ci case MESA_SHADER_VERTEX: 678bf215546Sopenharmony_ci return_op = ROGUE_OP_END_VERT; 679bf215546Sopenharmony_ci break; 680bf215546Sopenharmony_ci 681bf215546Sopenharmony_ci default: 682bf215546Sopenharmony_ci unreachable("Unimplemented NIR return instruction type."); 683bf215546Sopenharmony_ci } 684bf215546Sopenharmony_ci 685bf215546Sopenharmony_ci rogue_shader_insert(shader, return_op); 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_ci return true; 688bf215546Sopenharmony_ci} 689bf215546Sopenharmony_ci 690bf215546Sopenharmony_cistatic bool trans_nir_jump(struct rogue_shader *shader, nir_jump_instr *jump) 691bf215546Sopenharmony_ci{ 692bf215546Sopenharmony_ci switch (jump->type) { 693bf215546Sopenharmony_ci case nir_jump_return: 694bf215546Sopenharmony_ci return trans_nir_jump_return(shader, jump); 695bf215546Sopenharmony_ci 696bf215546Sopenharmony_ci default: 697bf215546Sopenharmony_ci break; 698bf215546Sopenharmony_ci } 699bf215546Sopenharmony_ci 700bf215546Sopenharmony_ci unreachable("Unimplemented NIR jump instruction type."); 701bf215546Sopenharmony_ci} 702bf215546Sopenharmony_ci 703bf215546Sopenharmony_ci/** 704bf215546Sopenharmony_ci * \brief Converts a NIR shader to Rogue. 705bf215546Sopenharmony_ci * 706bf215546Sopenharmony_ci * \param[in] ctx Shared multi-stage build context. 707bf215546Sopenharmony_ci * \param[in] nir NIR shader. 708bf215546Sopenharmony_ci * \return A rogue_shader* if successful, or NULL if unsuccessful. 709bf215546Sopenharmony_ci */ 710bf215546Sopenharmony_cistruct rogue_shader *rogue_nir_to_rogue(struct rogue_build_ctx *ctx, 711bf215546Sopenharmony_ci const nir_shader *nir) 712bf215546Sopenharmony_ci{ 713bf215546Sopenharmony_ci gl_shader_stage stage = nir->info.stage; 714bf215546Sopenharmony_ci struct rogue_shader *shader = rogue_shader_create(ctx, stage); 715bf215546Sopenharmony_ci if (!shader) 716bf215546Sopenharmony_ci return NULL; 717bf215546Sopenharmony_ci 718bf215546Sopenharmony_ci /* Make sure we only have a single function. */ 719bf215546Sopenharmony_ci assert(exec_list_length(&nir->functions) == 1); 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_ci /* Translate shader entrypoint. */ 722bf215546Sopenharmony_ci nir_function_impl *entry = nir_shader_get_entrypoint((nir_shader *)nir); 723bf215546Sopenharmony_ci nir_foreach_block (block, entry) { 724bf215546Sopenharmony_ci nir_foreach_instr (instr, block) { 725bf215546Sopenharmony_ci switch (instr->type) { 726bf215546Sopenharmony_ci case nir_instr_type_alu: 727bf215546Sopenharmony_ci /* TODO: Cleanup on failure. */ 728bf215546Sopenharmony_ci CHECKF(trans_nir_alu(shader, nir_instr_as_alu(instr)), 729bf215546Sopenharmony_ci "Failed to translate NIR ALU instruction."); 730bf215546Sopenharmony_ci break; 731bf215546Sopenharmony_ci 732bf215546Sopenharmony_ci case nir_instr_type_intrinsic: 733bf215546Sopenharmony_ci CHECKF(trans_nir_intrinsic(shader, nir_instr_as_intrinsic(instr)), 734bf215546Sopenharmony_ci "Failed to translate NIR intrinsic instruction."); 735bf215546Sopenharmony_ci break; 736bf215546Sopenharmony_ci 737bf215546Sopenharmony_ci case nir_instr_type_load_const: 738bf215546Sopenharmony_ci CHECKF(trans_nir_load_const(shader, nir_instr_as_load_const(instr)), 739bf215546Sopenharmony_ci "Failed to translate NIR load_const instruction."); 740bf215546Sopenharmony_ci break; 741bf215546Sopenharmony_ci 742bf215546Sopenharmony_ci case nir_instr_type_jump: 743bf215546Sopenharmony_ci CHECKF(trans_nir_jump(shader, nir_instr_as_jump(instr)), 744bf215546Sopenharmony_ci "Failed to translate NIR jump instruction."); 745bf215546Sopenharmony_ci break; 746bf215546Sopenharmony_ci 747bf215546Sopenharmony_ci default: 748bf215546Sopenharmony_ci unreachable("Unimplemented NIR instruction type."); 749bf215546Sopenharmony_ci } 750bf215546Sopenharmony_ci } 751bf215546Sopenharmony_ci } 752bf215546Sopenharmony_ci 753bf215546Sopenharmony_ci /* Perform register allocation. */ 754bf215546Sopenharmony_ci /* TODO: handle failure. */ 755bf215546Sopenharmony_ci if (!rogue_ra_alloc(&shader->instr_list, 756bf215546Sopenharmony_ci shader->ra, 757bf215546Sopenharmony_ci &ctx->common_data[stage].temps, 758bf215546Sopenharmony_ci &ctx->common_data[stage].internals)) 759bf215546Sopenharmony_ci return NULL; 760bf215546Sopenharmony_ci 761bf215546Sopenharmony_ci return shader; 762bf215546Sopenharmony_ci} 763bf215546Sopenharmony_ci 764bf215546Sopenharmony_ci/** 765bf215546Sopenharmony_ci * \brief Creates and sets up a shared multi-stage build context. 766bf215546Sopenharmony_ci * 767bf215546Sopenharmony_ci * \param[in] compiler The compiler context. 768bf215546Sopenharmony_ci * \return A pointer to the new build context, or NULL on failure. 769bf215546Sopenharmony_ci */ 770bf215546Sopenharmony_cistruct rogue_build_ctx * 771bf215546Sopenharmony_cirogue_create_build_context(struct rogue_compiler *compiler) 772bf215546Sopenharmony_ci{ 773bf215546Sopenharmony_ci struct rogue_build_ctx *ctx; 774bf215546Sopenharmony_ci 775bf215546Sopenharmony_ci ctx = rzalloc_size(compiler, sizeof(*ctx)); 776bf215546Sopenharmony_ci if (!ctx) 777bf215546Sopenharmony_ci return NULL; 778bf215546Sopenharmony_ci 779bf215546Sopenharmony_ci ctx->compiler = compiler; 780bf215546Sopenharmony_ci 781bf215546Sopenharmony_ci /* nir/rogue/binary shaders need to be default-zeroed; 782bf215546Sopenharmony_ci * this is taken care of by rzalloc_size. 783bf215546Sopenharmony_ci */ 784bf215546Sopenharmony_ci 785bf215546Sopenharmony_ci /* Setup non-zero defaults. */ 786bf215546Sopenharmony_ci ctx->stage_data.fs.msaa_mode = ROGUE_MSAA_MODE_PIXEL; 787bf215546Sopenharmony_ci 788bf215546Sopenharmony_ci return ctx; 789bf215546Sopenharmony_ci} 790