Path: blob/21.2-virgl/src/compiler/spirv/vtn_amd.c
4545 views
/*1* Copyright © 2018 Valve Corporation2* Copyright © 2017 Red Hat3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* the rights to use, copy, modify, merge, publish, distribute, sublicense,8* and/or sell copies of the Software, and to permit persons to whom the9* Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the next12* paragraph) shall be included in all copies or substantial portions of the13* Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING20* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS21* IN THE SOFTWARE.22*23*/2425#include "vtn_private.h"26#include "GLSL.ext.AMD.h"2728bool29vtn_handle_amd_gcn_shader_instruction(struct vtn_builder *b, SpvOp ext_opcode,30const uint32_t *w, unsigned count)31{32nir_ssa_def *def;33switch ((enum GcnShaderAMD)ext_opcode) {34case CubeFaceIndexAMD:35def = nir_cube_face_index_amd(&b->nb, vtn_get_nir_ssa(b, w[5]));36break;37case CubeFaceCoordAMD:38def = nir_cube_face_coord_amd(&b->nb, vtn_get_nir_ssa(b, w[5]));39break;40case TimeAMD: {41def = nir_pack_64_2x32(&b->nb, nir_shader_clock(&b->nb, NIR_SCOPE_SUBGROUP));42break;43}44default:45unreachable("Invalid opcode");46}4748vtn_push_nir_ssa(b, w[2], def);4950return true;51}5253bool54vtn_handle_amd_shader_ballot_instruction(struct vtn_builder *b, SpvOp ext_opcode,55const uint32_t *w, unsigned count)56{57unsigned num_args;58nir_intrinsic_op op;59switch ((enum ShaderBallotAMD)ext_opcode) {60case SwizzleInvocationsAMD:61num_args = 1;62op = nir_intrinsic_quad_swizzle_amd;63break;64case SwizzleInvocationsMaskedAMD:65num_args = 1;66op = nir_intrinsic_masked_swizzle_amd;67break;68case WriteInvocationAMD:69num_args = 3;70op = nir_intrinsic_write_invocation_amd;71break;72case MbcntAMD:73num_args = 1;74op = nir_intrinsic_mbcnt_amd;75break;76default:77unreachable("Invalid opcode");78}7980const struct glsl_type *dest_type = vtn_get_type(b, w[1])->type;81nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->nb.shader, op);82nir_ssa_dest_init_for_type(&intrin->instr, &intrin->dest, dest_type, NULL);83if (nir_intrinsic_infos[op].src_components[0] == 0)84intrin->num_components = intrin->dest.ssa.num_components;8586for (unsigned i = 0; i < num_args; i++)87intrin->src[i] = nir_src_for_ssa(vtn_get_nir_ssa(b, w[i + 5]));8889if (intrin->intrinsic == nir_intrinsic_quad_swizzle_amd) {90struct vtn_value *val = vtn_value(b, w[6], vtn_value_type_constant);91unsigned mask = val->constant->values[0].u32 |92val->constant->values[1].u32 << 2 |93val->constant->values[2].u32 << 4 |94val->constant->values[3].u32 << 6;95nir_intrinsic_set_swizzle_mask(intrin, mask);9697} else if (intrin->intrinsic == nir_intrinsic_masked_swizzle_amd) {98struct vtn_value *val = vtn_value(b, w[6], vtn_value_type_constant);99unsigned mask = val->constant->values[0].u32 |100val->constant->values[1].u32 << 5 |101val->constant->values[2].u32 << 10;102nir_intrinsic_set_swizzle_mask(intrin, mask);103} else if (intrin->intrinsic == nir_intrinsic_mbcnt_amd) {104/* The v_mbcnt instruction has an additional source that is added to the result.105* This is exposed by the NIR intrinsic but not by SPIR-V, so we add zero here.106*/107intrin->src[1] = nir_src_for_ssa(nir_imm_int(&b->nb, 0));108}109110nir_builder_instr_insert(&b->nb, &intrin->instr);111vtn_push_nir_ssa(b, w[2], &intrin->dest.ssa);112113return true;114}115116bool117vtn_handle_amd_shader_trinary_minmax_instruction(struct vtn_builder *b, SpvOp ext_opcode,118const uint32_t *w, unsigned count)119{120struct nir_builder *nb = &b->nb;121122unsigned num_inputs = count - 5;123assert(num_inputs == 3);124nir_ssa_def *src[3] = { NULL, };125for (unsigned i = 0; i < num_inputs; i++)126src[i] = vtn_get_nir_ssa(b, w[i + 5]);127128/* place constants at src[1-2] for easier constant-folding */129for (unsigned i = 1; i <= 2; i++) {130if (nir_src_as_const_value(nir_src_for_ssa(src[0]))) {131nir_ssa_def* tmp = src[i];132src[i] = src[0];133src[0] = tmp;134}135}136nir_ssa_def *def;137switch ((enum ShaderTrinaryMinMaxAMD)ext_opcode) {138case FMin3AMD:139def = nir_fmin(nb, src[0], nir_fmin(nb, src[1], src[2]));140break;141case UMin3AMD:142def = nir_umin(nb, src[0], nir_umin(nb, src[1], src[2]));143break;144case SMin3AMD:145def = nir_imin(nb, src[0], nir_imin(nb, src[1], src[2]));146break;147case FMax3AMD:148def = nir_fmax(nb, src[0], nir_fmax(nb, src[1], src[2]));149break;150case UMax3AMD:151def = nir_umax(nb, src[0], nir_umax(nb, src[1], src[2]));152break;153case SMax3AMD:154def = nir_imax(nb, src[0], nir_imax(nb, src[1], src[2]));155break;156case FMid3AMD:157def = nir_fmin(nb, nir_fmax(nb, src[0], nir_fmin(nb, src[1], src[2])),158nir_fmax(nb, src[1], src[2]));159break;160case UMid3AMD:161def = nir_umin(nb, nir_umax(nb, src[0], nir_umin(nb, src[1], src[2])),162nir_umax(nb, src[1], src[2]));163break;164case SMid3AMD:165def = nir_imin(nb, nir_imax(nb, src[0], nir_imin(nb, src[1], src[2])),166nir_imax(nb, src[1], src[2]));167break;168default:169unreachable("unknown opcode\n");170break;171}172173vtn_push_nir_ssa(b, w[2], def);174175return true;176}177178bool179vtn_handle_amd_shader_explicit_vertex_parameter_instruction(struct vtn_builder *b, SpvOp ext_opcode,180const uint32_t *w, unsigned count)181{182nir_intrinsic_op op;183switch ((enum ShaderExplicitVertexParameterAMD)ext_opcode) {184case InterpolateAtVertexAMD:185op = nir_intrinsic_interp_deref_at_vertex;186break;187default:188unreachable("unknown opcode");189}190191nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->nb.shader, op);192193struct vtn_pointer *ptr =194vtn_value(b, w[5], vtn_value_type_pointer)->pointer;195nir_deref_instr *deref = vtn_pointer_to_deref(b, ptr);196197/* If the value we are interpolating has an index into a vector then198* interpolate the vector and index the result of that instead. This is199* necessary because the index will get generated as a series of nir_bcsel200* instructions so it would no longer be an input variable.201*/202const bool vec_array_deref = deref->deref_type == nir_deref_type_array &&203glsl_type_is_vector(nir_deref_instr_parent(deref)->type);204205nir_deref_instr *vec_deref = NULL;206if (vec_array_deref) {207vec_deref = deref;208deref = nir_deref_instr_parent(deref);209}210intrin->src[0] = nir_src_for_ssa(&deref->dest.ssa);211intrin->src[1] = nir_src_for_ssa(vtn_get_nir_ssa(b, w[6]));212213intrin->num_components = glsl_get_vector_elements(deref->type);214nir_ssa_dest_init(&intrin->instr, &intrin->dest,215glsl_get_vector_elements(deref->type),216glsl_get_bit_size(deref->type), NULL);217218nir_builder_instr_insert(&b->nb, &intrin->instr);219220nir_ssa_def *def;221if (vec_array_deref) {222assert(vec_deref);223def = nir_vector_extract(&b->nb, &intrin->dest.ssa,224vec_deref->arr.index.ssa);225} else {226def = &intrin->dest.ssa;227}228vtn_push_nir_ssa(b, w[2], def);229230return true;231}232233234