radeonsi: remove TGSI

Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
This commit is contained in:
Marek Olšák 2020-01-03 23:15:27 -05:00
parent e5167a9276
commit 420fe1e7f9
16 changed files with 598 additions and 5346 deletions

View file

@ -35,10 +35,9 @@ C_SOURCES := \
si_shader.c \
si_shader.h \
si_shader_internal.h \
si_shader_llvm.c \
si_shader_llvm_build.c \
si_shader_nir.c \
si_shader_tgsi_alu.c \
si_shader_tgsi_mem.c \
si_shader_tgsi_setup.c \
si_shaderlib_tgsi.c \
si_state.c \
si_state_binning.c \

View file

@ -50,10 +50,9 @@ files_libradeonsi = files(
'si_shader.c',
'si_shader.h',
'si_shader_internal.h',
'si_shader_llvm.c',
'si_shader_llvm_build.c',
'si_shader_nir.c',
'si_shader_tgsi_alu.c',
'si_shader_tgsi_mem.c',
'si_shader_tgsi_setup.c',
'si_shaderlib_tgsi.c',
'si_state.c',
'si_state.h',

View file

@ -24,7 +24,6 @@
*/
#include "nir/tgsi_to_nir.h"
#include "tgsi/tgsi_parse.h"
#include "util/u_async_debug.h"
#include "util/u_memory.h"
#include "util/u_upload_mgr.h"
@ -124,13 +123,8 @@ static void si_create_compute_state_async(void *job, int thread_index)
if (!compiler->passes)
si_init_compiler(sscreen, compiler);
if (program->ir_type == PIPE_SHADER_IR_TGSI) {
tgsi_scan_shader(sel->tokens, &sel->info);
} else {
assert(program->ir_type == PIPE_SHADER_IR_NIR);
si_nir_scan_shader(sel->nir, &sel->info);
}
assert(program->ir_type == PIPE_SHADER_IR_NIR);
si_nir_scan_shader(sel->nir, &sel->info);
/* Store the declared LDS size into tgsi_shader_info for the shader
* cache to include it.
@ -167,9 +161,6 @@ static void si_create_compute_state_async(void *job, int thread_index)
if (!si_shader_create(sscreen, compiler, &program->shader, debug)) {
program->shader.compilation_failed = true;
if (program->ir_type == PIPE_SHADER_IR_TGSI)
FREE(sel->tokens);
return;
}
@ -209,8 +200,6 @@ static void si_create_compute_state_async(void *job, int thread_index)
simple_mtx_unlock(&sscreen->shader_cache_mutex);
}
FREE(sel->tokens);
sel->tokens = NULL;
ralloc_free(sel->nir);
sel->nir = NULL;
}
@ -234,16 +223,9 @@ static void *si_create_compute_state(
program->input_size = cso->req_input_mem;
if (cso->ir_type != PIPE_SHADER_IR_NATIVE) {
if (sscreen->options.enable_nir &&
cso->ir_type == PIPE_SHADER_IR_TGSI) {
if (cso->ir_type == PIPE_SHADER_IR_TGSI) {
program->ir_type = PIPE_SHADER_IR_NIR;
sel->nir = tgsi_to_nir(cso->prog, ctx->screen);
} else if (cso->ir_type == PIPE_SHADER_IR_TGSI) {
sel->tokens = tgsi_dup_tokens(cso->prog);
if (!sel->tokens) {
FREE(program);
return NULL;
}
} else {
assert(cso->ir_type == PIPE_SHADER_IR_NIR);
sel->nir = (struct nir_shader *) cso->prog;
@ -719,8 +701,8 @@ static bool si_upload_compute_input(struct si_context *sctx,
return true;
}
static void si_setup_tgsi_user_data(struct si_context *sctx,
const struct pipe_grid_info *info)
static void si_setup_nir_user_data(struct si_context *sctx,
const struct pipe_grid_info *info)
{
struct si_compute *program = sctx->cs_shader_state.program;
struct si_shader_selector *sel = &program->sel;
@ -944,7 +926,7 @@ static void si_launch_grid(
}
if (program->ir_type != PIPE_SHADER_IR_NATIVE)
si_setup_tgsi_user_data(sctx, info);
si_setup_nir_user_data(sctx, info);
si_emit_dispatch_packets(sctx, info);
@ -977,7 +959,6 @@ void si_destroy_compute(struct si_compute *program)
FREE(program->global_buffers);
si_shader_destroy(&program->shader);
FREE(program->sel.tokens);
ralloc_free(program->sel.nir);
FREE(program);
}

View file

@ -1,5 +1,4 @@
OPT_BOOL(clear_db_cache_before_clear, false, "Clear DB cache before fast depth clear")
OPT_BOOL(enable_nir, true, "Enable NIR")
OPT_BOOL(aux_debug, false, "Generate ddebug_dumps for the auxiliary context")
OPT_BOOL(sync_compile, false, "Always compile synchronously (will cause stalls)")
OPT_BOOL(dump_shader_binary, false, "Dump shader binary as part of ddebug_dumps")

View file

@ -159,6 +159,9 @@ static int si_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_IMAGE_LOAD_FORMATTED:
case PIPE_CAP_PREFER_COMPUTE_FOR_MULTIMEDIA:
case PIPE_CAP_TGSI_DIV:
case PIPE_CAP_PACKED_UNIFORMS:
case PIPE_CAP_SHADER_SAMPLES_IDENTICAL:
case PIPE_CAP_GL_SPIRV:
return 1;
case PIPE_CAP_QUERY_SO_OVERFLOW:
@ -195,7 +198,7 @@ static int si_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:
if (!sscreen->info.has_indirect_compute_dispatch)
return 420;
return sscreen->options.enable_nir ? 460 : 450;
return 460;
case PIPE_CAP_MAX_TEXTURE_UPLOAD_MEMORY_BUDGET:
/* Optimal number for good TexSubImage performance on Polaris10. */
@ -214,15 +217,6 @@ static int si_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
return sscreen->info.has_sparse_vm_mappings ?
RADEON_SPARSE_PAGE_SIZE : 0;
case PIPE_CAP_PACKED_UNIFORMS:
case PIPE_CAP_SHADER_SAMPLES_IDENTICAL:
case PIPE_CAP_GL_SPIRV:
return sscreen->options.enable_nir;
case PIPE_CAP_PREFER_IMM_ARRAYS_AS_CONSTBUF:
if (sscreen->options.enable_nir)
return 0;
return 1;
/* Unsupported features. */
case PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY:
@ -246,6 +240,7 @@ static int si_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_CONSERVATIVE_RASTER_POST_DEPTH_COVERAGE:
case PIPE_CAP_MAX_CONSERVATIVE_RASTER_SUBPIXEL_PRECISION_BIAS:
case PIPE_CAP_PROGRAMMABLE_SAMPLE_LOCATIONS:
case PIPE_CAP_PREFER_IMM_ARRAYS_AS_CONSTBUF:
return 0;
case PIPE_CAP_FENCE_SIGNAL:
@ -395,14 +390,14 @@ static int si_get_shader_param(struct pipe_screen* pscreen,
int ir = 1 << PIPE_SHADER_IR_NATIVE;
if (sscreen->info.has_indirect_compute_dispatch)
ir |= 1 << PIPE_SHADER_IR_TGSI;
ir |= 1 << PIPE_SHADER_IR_NIR;
return ir;
}
case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: {
uint64_t max_const_buffer_size;
pscreen->get_compute_param(pscreen, PIPE_SHADER_IR_TGSI,
pscreen->get_compute_param(pscreen, PIPE_SHADER_IR_NIR,
PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE,
&max_const_buffer_size);
return MIN2(max_const_buffer_size, INT_MAX);
@ -444,13 +439,9 @@ static int si_get_shader_param(struct pipe_screen* pscreen,
case PIPE_SHADER_CAP_MAX_SHADER_IMAGES:
return SI_NUM_IMAGES;
case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:
if (sscreen->options.enable_nir)
return 0;
return 32;
return 0;
case PIPE_SHADER_CAP_PREFERRED_IR:
if (sscreen->options.enable_nir)
return PIPE_SHADER_IR_NIR;
return PIPE_SHADER_IR_TGSI;
return PIPE_SHADER_IR_NIR;
case PIPE_SHADER_CAP_LOWER_IF_THRESHOLD:
return 4;

View file

@ -660,7 +660,7 @@ static struct pipe_context *si_create_context(struct pipe_screen *screen,
}
uint64_t max_threads_per_block;
screen->get_compute_param(screen, PIPE_SHADER_IR_TGSI,
screen->get_compute_param(screen, PIPE_SHADER_IR_NIR,
PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK,
&max_threads_per_block);
@ -910,10 +910,6 @@ static void si_disk_cache_create(struct si_screen *sscreen)
/* These flags affect shader compilation. */
#define ALL_FLAGS (DBG(SI_SCHED) | DBG(GISEL))
uint64_t shader_debug_flags = sscreen->debug_flags & ALL_FLAGS;
/* Reserve left-most bit for tgsi/nir selector */
assert(!(shader_debug_flags & (1u << 31)));
shader_debug_flags |= (uint32_t)
((sscreen->options.enable_nir & 0x1) << 31);
/* Add the high bits of 32-bit addresses, which affects
* how 32-bit addresses are expanded to 64 bits.

File diff suppressed because it is too large Load diff

View file

@ -326,7 +326,6 @@ struct si_shader_selector {
struct si_shader *gs_copy_shader;
struct tgsi_token *tokens;
struct nir_shader *nir;
void *nir_binary;
unsigned nir_size;
@ -730,10 +729,10 @@ si_generate_gs_copy_shader(struct si_screen *sscreen,
struct ac_llvm_compiler *compiler,
struct si_shader_selector *gs_selector,
struct pipe_debug_callback *debug);
int si_compile_tgsi_shader(struct si_screen *sscreen,
struct ac_llvm_compiler *compiler,
struct si_shader *shader,
struct pipe_debug_callback *debug);
int si_compile_shader(struct si_screen *sscreen,
struct ac_llvm_compiler *compiler,
struct si_shader *shader,
struct pipe_debug_callback *debug);
bool si_shader_create(struct si_screen *sscreen, struct ac_llvm_compiler *compiler,
struct si_shader *shader,
struct pipe_debug_callback *debug);

View file

@ -26,10 +26,6 @@
#define SI_SHADER_PRIVATE_H
#include "si_shader.h"
#include "gallivm/lp_bld_flow.h"
#include "gallivm/lp_bld_init.h"
#include "gallivm/lp_bld_tgsi.h"
#include "tgsi/tgsi_parse.h"
#include "ac_shader_abi.h"
#include <llvm-c/Core.h>
@ -37,12 +33,7 @@
struct pipe_debug_callback;
#define RADEON_LLVM_MAX_INPUT_SLOTS 32
#define RADEON_LLVM_MAX_INPUTS 32 * 4
#define RADEON_LLVM_MAX_OUTPUTS 32 * 4
#define RADEON_LLVM_MAX_SYSTEM_VALUES 11
#define RADEON_LLVM_MAX_ADDRS 16
struct si_shader_output_values {
LLVMValueRef values[4];
@ -52,8 +43,6 @@ struct si_shader_output_values {
};
struct si_shader_context {
struct lp_build_tgsi_context bld_base;
struct gallivm_state gallivm;
struct ac_llvm_context ac;
struct si_shader *shader;
struct si_screen *screen;
@ -69,42 +58,11 @@ struct si_shader_context {
struct ac_shader_args args;
struct ac_shader_abi abi;
/** This function is responsible for initilizing the inputs array and will be
* called once for each input declared in the TGSI shader.
*/
void (*load_input)(struct si_shader_context *,
unsigned input_index,
const struct tgsi_full_declaration *decl,
LLVMValueRef out[4]);
/** This array contains the input values for the shader. Typically these
* values will be in the form of a target intrinsic that will inform the
* backend how to load the actual inputs to the shader.
*/
struct tgsi_full_declaration input_decls[RADEON_LLVM_MAX_INPUT_SLOTS];
LLVMValueRef inputs[RADEON_LLVM_MAX_INPUTS];
LLVMValueRef outputs[RADEON_LLVM_MAX_OUTPUTS][TGSI_NUM_CHANNELS];
LLVMValueRef addrs[RADEON_LLVM_MAX_ADDRS][TGSI_NUM_CHANNELS];
/** This pointer is used to contain the temporary values.
* The amount of temporary used in tgsi can't be bound to a max value and
* thus we must allocate this array at runtime.
*/
LLVMValueRef *temps;
unsigned temps_count;
LLVMValueRef system_values[RADEON_LLVM_MAX_SYSTEM_VALUES];
LLVMValueRef *imms;
unsigned imms_num;
LLVMBasicBlockRef merged_wrap_if_entry_block;
int merged_wrap_if_label;
struct tgsi_array_info *temp_arrays;
LLVMValueRef *temp_array_allocas;
LLVMValueRef undef_alloca;
LLVMValueRef main_fn;
LLVMTypeRef return_type;
@ -233,12 +191,6 @@ struct si_shader_context {
LLVMValueRef i1true;
};
static inline struct si_shader_context *
si_shader_context(struct lp_build_tgsi_context *bld_base)
{
return (struct si_shader_context*)bld_base;
}
static inline struct si_shader_context *
si_shader_context_from_abi(struct ac_shader_abi *abi)
{
@ -255,12 +207,6 @@ unsigned si_llvm_compile(LLVMModuleRef M, struct si_shader_binary *binary,
struct pipe_debug_callback *debug,
bool less_optimized, unsigned wave_size);
LLVMTypeRef tgsi2llvmtype(struct lp_build_tgsi_context *bld_base,
enum tgsi_opcode_type type);
LLVMValueRef bitcast(struct lp_build_tgsi_context *bld_base,
enum tgsi_opcode_type type, LLVMValueRef value);
LLVMValueRef si_llvm_bound_index(struct si_shader_context *ctx,
LLVMValueRef index,
unsigned num);
@ -271,8 +217,7 @@ void si_llvm_context_init(struct si_shader_context *ctx,
unsigned wave_size,
unsigned ballot_mask_bits);
void si_llvm_context_set_ir(struct si_shader_context *ctx,
struct si_shader *shader,
struct nir_shader *nir);
struct si_shader *shader);
void si_llvm_create_func(struct si_shader_context *ctx,
const char *name,
@ -282,18 +227,6 @@ void si_llvm_dispose(struct si_shader_context *ctx);
void si_llvm_optimize_module(struct si_shader_context *ctx);
LLVMValueRef si_llvm_emit_fetch_64bit(struct lp_build_tgsi_context *bld_base,
LLVMTypeRef type,
LLVMValueRef ptr,
LLVMValueRef ptr2);
LLVMValueRef si_llvm_emit_fetch(struct lp_build_tgsi_context *bld_base,
const struct tgsi_full_src_register *reg,
enum tgsi_opcode_type type,
unsigned swizzle);
void si_llvm_emit_kill(struct ac_shader_abi *abi, LLVMValueRef visible);
LLVMValueRef si_nir_load_input_tes(struct ac_shader_abi *abi,
LLVMTypeRef type,
LLVMValueRef vertex_index,
@ -306,34 +239,10 @@ LLVMValueRef si_nir_load_input_tes(struct ac_shader_abi *abi,
bool is_patch,
bool is_compact,
bool load_input);
LLVMValueRef si_llvm_load_input_gs(struct ac_shader_abi *abi,
unsigned input_index,
unsigned vtx_offset_param,
LLVMTypeRef type,
unsigned swizzle);
LLVMValueRef si_nir_lookup_interp_param(struct ac_shader_abi *abi,
enum glsl_interp_mode interp,
unsigned location);
void si_llvm_emit_store(struct lp_build_tgsi_context *bld_base,
const struct tgsi_full_instruction *inst,
const struct tgsi_opcode_info *info,
unsigned index,
LLVMValueRef dst[4]);
LLVMValueRef si_get_indirect_index(struct si_shader_context *ctx,
const struct tgsi_ind_register *ind,
unsigned addr_mul, int rel_index);
LLVMValueRef si_get_bounded_indirect_index(struct si_shader_context *ctx,
const struct tgsi_ind_register *ind,
int rel_index, unsigned num);
LLVMValueRef si_get_sample_id(struct si_shader_context *ctx);
void si_shader_context_init_alu(struct si_shader_context *ctx);
void si_shader_context_init_mem(struct si_shader_context *ctx);
LLVMValueRef si_load_sampler_desc(struct si_shader_context *ctx,
LLVMValueRef list, LLVMValueRef index,
enum ac_descriptor_type type);
@ -342,14 +251,7 @@ LLVMValueRef si_load_image_desc(struct si_shader_context *ctx,
enum ac_descriptor_type desc_type,
bool uses_store, bool bindless);
LLVMValueRef si_nir_emit_fbfetch(struct ac_shader_abi *abi);
void si_load_system_value(struct si_shader_context *ctx,
unsigned index,
const struct tgsi_full_declaration *decl);
void si_declare_compute_memory(struct si_shader_context *ctx);
void si_tgsi_declare_compute_memory(struct si_shader_context *ctx,
const struct tgsi_full_declaration *decl);
LLVMValueRef si_get_primitive_id(struct si_shader_context *ctx,
unsigned swizzle);
void si_llvm_export_vs(struct si_shader_context *ctx,
@ -365,10 +267,6 @@ void si_llvm_load_input_vs(
struct si_shader_context *ctx,
unsigned input_index,
LLVMValueRef out[4]);
void si_llvm_load_input_fs(
struct si_shader_context *ctx,
unsigned input_index,
LLVMValueRef out[4]);
bool si_nir_build_llvm(struct si_shader_context *ctx, struct nir_shader *nir);

View file

@ -0,0 +1,239 @@
/*
* Copyright 2016 Advanced Micro Devices, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "si_shader_internal.h"
#include "si_pipe.h"
#include "ac_llvm_util.h"
#include "util/u_memory.h"
struct si_llvm_diagnostics {
struct pipe_debug_callback *debug;
unsigned retval;
};
static void si_diagnostic_handler(LLVMDiagnosticInfoRef di, void *context)
{
struct si_llvm_diagnostics *diag = (struct si_llvm_diagnostics *)context;
LLVMDiagnosticSeverity severity = LLVMGetDiagInfoSeverity(di);
const char *severity_str = NULL;
switch (severity) {
case LLVMDSError:
severity_str = "error";
break;
case LLVMDSWarning:
severity_str = "warning";
break;
case LLVMDSRemark:
case LLVMDSNote:
default:
return;
}
char *description = LLVMGetDiagInfoDescription(di);
pipe_debug_message(diag->debug, SHADER_INFO,
"LLVM diagnostic (%s): %s", severity_str, description);
if (severity == LLVMDSError) {
diag->retval = 1;
fprintf(stderr,"LLVM triggered Diagnostic Handler: %s\n", description);
}
LLVMDisposeMessage(description);
}
/**
* Compile an LLVM module to machine code.
*
* @returns 0 for success, 1 for failure
*/
unsigned si_llvm_compile(LLVMModuleRef M, struct si_shader_binary *binary,
struct ac_llvm_compiler *compiler,
struct pipe_debug_callback *debug,
bool less_optimized, unsigned wave_size)
{
struct ac_compiler_passes *passes = compiler->passes;
if (wave_size == 32)
passes = compiler->passes_wave32;
else if (less_optimized && compiler->low_opt_passes)
passes = compiler->low_opt_passes;
struct si_llvm_diagnostics diag;
LLVMContextRef llvm_ctx;
diag.debug = debug;
diag.retval = 0;
/* Setup Diagnostic Handler*/
llvm_ctx = LLVMGetModuleContext(M);
LLVMContextSetDiagnosticHandler(llvm_ctx, si_diagnostic_handler, &diag);
/* Compile IR. */
if (!ac_compile_module_to_elf(passes, M, (char **)&binary->elf_buffer,
&binary->elf_size))
diag.retval = 1;
if (diag.retval != 0)
pipe_debug_message(debug, SHADER_INFO, "LLVM compile failed");
return diag.retval;
}
void si_shader_binary_clean(struct si_shader_binary *binary)
{
free((void *)binary->elf_buffer);
binary->elf_buffer = NULL;
free(binary->llvm_ir_string);
binary->llvm_ir_string = NULL;
}
void si_llvm_context_init(struct si_shader_context *ctx,
struct si_screen *sscreen,
struct ac_llvm_compiler *compiler,
unsigned wave_size,
unsigned ballot_mask_bits)
{
/* Initialize the gallivm object:
* We are only using the module, context, and builder fields of this struct.
* This should be enough for us to be able to pass our gallivm struct to the
* helper functions in the gallivm module.
*/
memset(ctx, 0, sizeof(*ctx));
ctx->screen = sscreen;
ctx->compiler = compiler;
ac_llvm_context_init(&ctx->ac, compiler, sscreen->info.chip_class,
sscreen->info.family,
AC_FLOAT_MODE_NO_SIGNED_ZEROS_FP_MATH,
wave_size, ballot_mask_bits);
ctx->voidt = LLVMVoidTypeInContext(ctx->ac.context);
ctx->i1 = LLVMInt1TypeInContext(ctx->ac.context);
ctx->i8 = LLVMInt8TypeInContext(ctx->ac.context);
ctx->i32 = LLVMInt32TypeInContext(ctx->ac.context);
ctx->i64 = LLVMInt64TypeInContext(ctx->ac.context);
ctx->i128 = LLVMIntTypeInContext(ctx->ac.context, 128);
ctx->f32 = LLVMFloatTypeInContext(ctx->ac.context);
ctx->v2i32 = LLVMVectorType(ctx->i32, 2);
ctx->v4i32 = LLVMVectorType(ctx->i32, 4);
ctx->v4f32 = LLVMVectorType(ctx->f32, 4);
ctx->v8i32 = LLVMVectorType(ctx->i32, 8);
ctx->i32_0 = LLVMConstInt(ctx->i32, 0, 0);
ctx->i32_1 = LLVMConstInt(ctx->i32, 1, 0);
ctx->i1false = LLVMConstInt(ctx->i1, 0, 0);
ctx->i1true = LLVMConstInt(ctx->i1, 1, 0);
}
/* Set the context to a certain TGSI shader. Can be called repeatedly
* to change the shader. */
void si_llvm_context_set_ir(struct si_shader_context *ctx,
struct si_shader *shader)
{
struct si_shader_selector *sel = shader->selector;
const struct tgsi_shader_info *info = &sel->info;
ctx->shader = shader;
ctx->type = sel->type;
ctx->num_const_buffers = util_last_bit(info->const_buffers_declared);
ctx->num_shader_buffers = util_last_bit(info->shader_buffers_declared);
ctx->num_samplers = util_last_bit(info->samplers_declared);
ctx->num_images = util_last_bit(info->images_declared);
}
void si_llvm_create_func(struct si_shader_context *ctx,
const char *name,
LLVMTypeRef *return_types, unsigned num_return_elems)
{
LLVMTypeRef ret_type;
enum ac_llvm_calling_convention call_conv;
enum pipe_shader_type real_shader_type;
if (num_return_elems)
ret_type = LLVMStructTypeInContext(ctx->ac.context,
return_types,
num_return_elems, true);
else
ret_type = ctx->voidt;
real_shader_type = ctx->type;
/* LS is merged into HS (TCS), and ES is merged into GS. */
if (ctx->screen->info.chip_class >= GFX9) {
if (ctx->shader->key.as_ls)
real_shader_type = PIPE_SHADER_TESS_CTRL;
else if (ctx->shader->key.as_es || ctx->shader->key.as_ngg)
real_shader_type = PIPE_SHADER_GEOMETRY;
}
switch (real_shader_type) {
case PIPE_SHADER_VERTEX:
case PIPE_SHADER_TESS_EVAL:
call_conv = AC_LLVM_AMDGPU_VS;
break;
case PIPE_SHADER_TESS_CTRL:
call_conv = AC_LLVM_AMDGPU_HS;
break;
case PIPE_SHADER_GEOMETRY:
call_conv = AC_LLVM_AMDGPU_GS;
break;
case PIPE_SHADER_FRAGMENT:
call_conv = AC_LLVM_AMDGPU_PS;
break;
case PIPE_SHADER_COMPUTE:
call_conv = AC_LLVM_AMDGPU_CS;
break;
default:
unreachable("Unhandle shader type");
}
/* Setup the function */
ctx->return_type = ret_type;
ctx->main_fn = ac_build_main(&ctx->args, &ctx->ac, call_conv, name,
ret_type, ctx->ac.module);
}
void si_llvm_optimize_module(struct si_shader_context *ctx)
{
/* Dump LLVM IR before any optimization passes */
if (ctx->screen->debug_flags & DBG(PREOPT_IR) &&
si_can_dump_shader(ctx->screen, ctx->type))
LLVMDumpModule(ctx->ac.module);
/* Run the pass */
LLVMRunPassManager(ctx->compiler->passmgr, ctx->ac.module);
LLVMDisposeBuilder(ctx->ac.builder);
}
void si_llvm_dispose(struct si_shader_context *ctx)
{
LLVMDisposeModule(ctx->ac.module);
LLVMContextDispose(ctx->ac.context);
ac_llvm_context_dispose(&ctx->ac);
}

View file

@ -0,0 +1,219 @@
/*
* Copyright 2017 Advanced Micro Devices, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <llvm/Config/llvm-config.h>
#include "si_shader_internal.h"
#include "si_pipe.h"
#include "sid.h"
#include "ac_llvm_util.h"
/**
* Return a value that is equal to the given i32 \p index if it lies in [0,num)
* or an undefined value in the same interval otherwise.
*/
LLVMValueRef si_llvm_bound_index(struct si_shader_context *ctx,
LLVMValueRef index,
unsigned num)
{
LLVMBuilderRef builder = ctx->ac.builder;
LLVMValueRef c_max = LLVMConstInt(ctx->i32, num - 1, 0);
LLVMValueRef cc;
if (util_is_power_of_two_or_zero(num)) {
index = LLVMBuildAnd(builder, index, c_max, "");
} else {
/* In theory, this MAX pattern should result in code that is
* as good as the bit-wise AND above.
*
* In practice, LLVM generates worse code (at the time of
* writing), because its value tracking is not strong enough.
*/
cc = LLVMBuildICmp(builder, LLVMIntULE, index, c_max, "");
index = LLVMBuildSelect(builder, cc, index, c_max, "");
}
return index;
}
/**
* Given a 256-bit resource descriptor, force the DCC enable bit to off.
*
* At least on Tonga, executing image stores on images with DCC enabled and
* non-trivial can eventually lead to lockups. This can occur when an
* application binds an image as read-only but then uses a shader that writes
* to it. The OpenGL spec allows almost arbitrarily bad behavior (including
* program termination) in this case, but it doesn't cost much to be a bit
* nicer: disabling DCC in the shader still leads to undefined results but
* avoids the lockup.
*/
static LLVMValueRef force_dcc_off(struct si_shader_context *ctx,
LLVMValueRef rsrc)
{
if (ctx->screen->info.chip_class <= GFX7) {
return rsrc;
} else {
LLVMValueRef i32_6 = LLVMConstInt(ctx->i32, 6, 0);
LLVMValueRef i32_C = LLVMConstInt(ctx->i32, C_008F28_COMPRESSION_EN, 0);
LLVMValueRef tmp;
tmp = LLVMBuildExtractElement(ctx->ac.builder, rsrc, i32_6, "");
tmp = LLVMBuildAnd(ctx->ac.builder, tmp, i32_C, "");
return LLVMBuildInsertElement(ctx->ac.builder, rsrc, tmp, i32_6, "");
}
}
/* AC_DESC_FMASK is handled exactly like AC_DESC_IMAGE. The caller should
* adjust "index" to point to FMASK. */
LLVMValueRef si_load_image_desc(struct si_shader_context *ctx,
LLVMValueRef list, LLVMValueRef index,
enum ac_descriptor_type desc_type,
bool uses_store, bool bindless)
{
LLVMBuilderRef builder = ctx->ac.builder;
LLVMValueRef rsrc;
if (desc_type == AC_DESC_BUFFER) {
index = ac_build_imad(&ctx->ac, index, LLVMConstInt(ctx->i32, 2, 0),
ctx->i32_1);
list = LLVMBuildPointerCast(builder, list,
ac_array_in_const32_addr_space(ctx->v4i32), "");
} else {
assert(desc_type == AC_DESC_IMAGE ||
desc_type == AC_DESC_FMASK);
}
if (bindless)
rsrc = ac_build_load_to_sgpr_uint_wraparound(&ctx->ac, list, index);
else
rsrc = ac_build_load_to_sgpr(&ctx->ac, list, index);
if (desc_type == AC_DESC_IMAGE && uses_store)
rsrc = force_dcc_off(ctx, rsrc);
return rsrc;
}
/**
* Load an image view, fmask view. or sampler state descriptor.
*/
LLVMValueRef si_load_sampler_desc(struct si_shader_context *ctx,
LLVMValueRef list, LLVMValueRef index,
enum ac_descriptor_type type)
{
LLVMBuilderRef builder = ctx->ac.builder;
switch (type) {
case AC_DESC_IMAGE:
/* The image is at [0:7]. */
index = LLVMBuildMul(builder, index, LLVMConstInt(ctx->i32, 2, 0), "");
break;
case AC_DESC_BUFFER:
/* The buffer is in [4:7]. */
index = ac_build_imad(&ctx->ac, index, LLVMConstInt(ctx->i32, 4, 0),
ctx->i32_1);
list = LLVMBuildPointerCast(builder, list,
ac_array_in_const32_addr_space(ctx->v4i32), "");
break;
case AC_DESC_FMASK:
/* The FMASK is at [8:15]. */
index = ac_build_imad(&ctx->ac, index, LLVMConstInt(ctx->i32, 2, 0),
ctx->i32_1);
break;
case AC_DESC_SAMPLER:
/* The sampler state is at [12:15]. */
index = ac_build_imad(&ctx->ac, index, LLVMConstInt(ctx->i32, 4, 0),
LLVMConstInt(ctx->i32, 3, 0));
list = LLVMBuildPointerCast(builder, list,
ac_array_in_const32_addr_space(ctx->v4i32), "");
break;
case AC_DESC_PLANE_0:
case AC_DESC_PLANE_1:
case AC_DESC_PLANE_2:
/* Only used for the multiplane image support for Vulkan. Should
* never be reached in radeonsi.
*/
unreachable("Plane descriptor requested in radeonsi.");
}
return ac_build_load_to_sgpr(&ctx->ac, list, index);
}
LLVMValueRef si_nir_emit_fbfetch(struct ac_shader_abi *abi)
{
struct si_shader_context *ctx = si_shader_context_from_abi(abi);
struct ac_image_args args = {};
LLVMValueRef ptr, image, fmask;
/* Ignore src0, because KHR_blend_func_extended disallows multiple render
* targets.
*/
/* Load the image descriptor. */
STATIC_ASSERT(SI_PS_IMAGE_COLORBUF0 % 2 == 0);
ptr = ac_get_arg(&ctx->ac, ctx->rw_buffers);
ptr = LLVMBuildPointerCast(ctx->ac.builder, ptr,
ac_array_in_const32_addr_space(ctx->v8i32), "");
image = ac_build_load_to_sgpr(&ctx->ac, ptr,
LLVMConstInt(ctx->i32, SI_PS_IMAGE_COLORBUF0 / 2, 0));
unsigned chan = 0;
args.coords[chan++] = si_unpack_param(ctx, ctx->pos_fixed_pt, 0, 16);
if (!ctx->shader->key.mono.u.ps.fbfetch_is_1D)
args.coords[chan++] = si_unpack_param(ctx, ctx->pos_fixed_pt, 16, 16);
/* Get the current render target layer index. */
if (ctx->shader->key.mono.u.ps.fbfetch_layered)
args.coords[chan++] = si_unpack_param(ctx, ctx->args.ancillary, 16, 11);
if (ctx->shader->key.mono.u.ps.fbfetch_msaa)
args.coords[chan++] = si_get_sample_id(ctx);
if (ctx->shader->key.mono.u.ps.fbfetch_msaa &&
!(ctx->screen->debug_flags & DBG(NO_FMASK))) {
fmask = ac_build_load_to_sgpr(&ctx->ac, ptr,
LLVMConstInt(ctx->i32, SI_PS_IMAGE_COLORBUF0_FMASK / 2, 0));
ac_apply_fmask_to_sample(&ctx->ac, fmask, args.coords,
ctx->shader->key.mono.u.ps.fbfetch_layered);
}
args.opcode = ac_image_load;
args.resource = image;
args.dmask = 0xf;
args.attributes = AC_FUNC_ATTR_READNONE;
if (ctx->shader->key.mono.u.ps.fbfetch_msaa)
args.dim = ctx->shader->key.mono.u.ps.fbfetch_layered ?
ac_image_2darraymsaa : ac_image_2dmsaa;
else if (ctx->shader->key.mono.u.ps.fbfetch_is_1D)
args.dim = ctx->shader->key.mono.u.ps.fbfetch_layered ?
ac_image_1darray : ac_image_1d;
else
args.dim = ctx->shader->key.mono.u.ps.fbfetch_layered ?
ac_image_2darray : ac_image_2d;
return ac_build_image_opcode(&ctx->ac, &args);
}

View file

@ -1,834 +0,0 @@
/*
* Copyright 2016 Advanced Micro Devices, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "si_shader_internal.h"
#include "si_pipe.h"
#include "ac_llvm_util.h"
void si_llvm_emit_kill(struct ac_shader_abi *abi, LLVMValueRef visible)
{
struct si_shader_context *ctx = si_shader_context_from_abi(abi);
LLVMBuilderRef builder = ctx->ac.builder;
if (ctx->shader->selector->force_correct_derivs_after_kill) {
/* Kill immediately while maintaining WQM. */
ac_build_kill_if_false(&ctx->ac,
ac_build_wqm_vote(&ctx->ac, visible));
LLVMValueRef mask = LLVMBuildLoad(builder, ctx->postponed_kill, "");
mask = LLVMBuildAnd(builder, mask, visible, "");
LLVMBuildStore(builder, mask, ctx->postponed_kill);
return;
}
ac_build_kill_if_false(&ctx->ac, visible);
}
static void kil_emit(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMValueRef visible;
if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_KILL_IF) {
const struct tgsi_full_instruction *inst = emit_data->inst;
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMBuilderRef builder = ctx->ac.builder;
unsigned i;
LLVMValueRef conds[TGSI_NUM_CHANNELS];
for (i = 0; i < TGSI_NUM_CHANNELS; i++) {
LLVMValueRef value = lp_build_emit_fetch(bld_base, inst, 0, i);
/* UGE because NaN shouldn't get killed */
conds[i] = LLVMBuildFCmp(builder, LLVMRealUGE, value,
ctx->ac.f32_0, "");
}
/* And the conditions together */
for (i = TGSI_NUM_CHANNELS - 1; i > 0; i--) {
conds[i - 1] = LLVMBuildAnd(builder, conds[i], conds[i - 1], "");
}
visible = conds[0];
} else {
assert(emit_data->inst->Instruction.Opcode == TGSI_OPCODE_KILL);
visible = ctx->i1false;
}
si_llvm_emit_kill(&ctx->abi, visible);
}
static void emit_icmp(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
unsigned pred;
struct si_shader_context *ctx = si_shader_context(bld_base);
switch (emit_data->inst->Instruction.Opcode) {
case TGSI_OPCODE_USEQ:
case TGSI_OPCODE_U64SEQ: pred = LLVMIntEQ; break;
case TGSI_OPCODE_USNE:
case TGSI_OPCODE_U64SNE: pred = LLVMIntNE; break;
case TGSI_OPCODE_USGE:
case TGSI_OPCODE_U64SGE: pred = LLVMIntUGE; break;
case TGSI_OPCODE_USLT:
case TGSI_OPCODE_U64SLT: pred = LLVMIntULT; break;
case TGSI_OPCODE_ISGE:
case TGSI_OPCODE_I64SGE: pred = LLVMIntSGE; break;
case TGSI_OPCODE_ISLT:
case TGSI_OPCODE_I64SLT: pred = LLVMIntSLT; break;
default:
assert(!"unknown instruction");
pred = 0;
break;
}
LLVMValueRef v = LLVMBuildICmp(ctx->ac.builder, pred,
emit_data->args[0], emit_data->args[1],"");
v = LLVMBuildSExtOrBitCast(ctx->ac.builder, v, ctx->i32, "");
emit_data->output[emit_data->chan] = v;
}
static void emit_ucmp(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMValueRef arg0 = ac_to_integer(&ctx->ac, emit_data->args[0]);
LLVMValueRef v = LLVMBuildICmp(ctx->ac.builder, LLVMIntNE, arg0,
ctx->i32_0, "");
emit_data->output[emit_data->chan] =
LLVMBuildSelect(ctx->ac.builder, v, emit_data->args[1], emit_data->args[2], "");
}
static void emit_cmp(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMValueRef cond, *args = emit_data->args;
cond = LLVMBuildFCmp(ctx->ac.builder, LLVMRealOLT, args[0],
ctx->ac.f32_0, "");
emit_data->output[emit_data->chan] =
LLVMBuildSelect(ctx->ac.builder, cond, args[1], args[2], "");
}
static void emit_set_cond(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMRealPredicate pred;
LLVMValueRef cond;
/* Use ordered for everything but NE (which is usual for
* float comparisons)
*/
switch (emit_data->inst->Instruction.Opcode) {
case TGSI_OPCODE_SGE: pred = LLVMRealOGE; break;
case TGSI_OPCODE_SEQ: pred = LLVMRealOEQ; break;
case TGSI_OPCODE_SLE: pred = LLVMRealOLE; break;
case TGSI_OPCODE_SLT: pred = LLVMRealOLT; break;
case TGSI_OPCODE_SNE: pred = LLVMRealUNE; break;
case TGSI_OPCODE_SGT: pred = LLVMRealOGT; break;
default: assert(!"unknown instruction"); pred = 0; break;
}
cond = LLVMBuildFCmp(ctx->ac.builder,
pred, emit_data->args[0], emit_data->args[1], "");
emit_data->output[emit_data->chan] = LLVMBuildSelect(ctx->ac.builder,
cond, ctx->ac.f32_1, ctx->ac.f32_0, "");
}
static void emit_fcmp(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMRealPredicate pred;
/* Use ordered for everything but NE (which is usual for
* float comparisons)
*/
switch (emit_data->inst->Instruction.Opcode) {
case TGSI_OPCODE_FSEQ: pred = LLVMRealOEQ; break;
case TGSI_OPCODE_FSGE: pred = LLVMRealOGE; break;
case TGSI_OPCODE_FSLT: pred = LLVMRealOLT; break;
case TGSI_OPCODE_FSNE: pred = LLVMRealUNE; break;
default: assert(!"unknown instruction"); pred = 0; break;
}
LLVMValueRef v = LLVMBuildFCmp(ctx->ac.builder, pred,
emit_data->args[0], emit_data->args[1],"");
v = LLVMBuildSExtOrBitCast(ctx->ac.builder, v, ctx->i32, "");
emit_data->output[emit_data->chan] = v;
}
static void emit_dcmp(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMRealPredicate pred;
/* Use ordered for everything but NE (which is usual for
* float comparisons)
*/
switch (emit_data->inst->Instruction.Opcode) {
case TGSI_OPCODE_DSEQ: pred = LLVMRealOEQ; break;
case TGSI_OPCODE_DSGE: pred = LLVMRealOGE; break;
case TGSI_OPCODE_DSLT: pred = LLVMRealOLT; break;
case TGSI_OPCODE_DSNE: pred = LLVMRealUNE; break;
default: assert(!"unknown instruction"); pred = 0; break;
}
LLVMValueRef v = LLVMBuildFCmp(ctx->ac.builder, pred,
emit_data->args[0], emit_data->args[1],"");
v = LLVMBuildSExtOrBitCast(ctx->ac.builder, v, ctx->i32, "");
emit_data->output[emit_data->chan] = v;
}
static void emit_not(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMValueRef v = ac_to_integer(&ctx->ac, emit_data->args[0]);
emit_data->output[emit_data->chan] = LLVMBuildNot(ctx->ac.builder, v, "");
}
static void emit_arl(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMValueRef floor_index =
ac_build_intrinsic(&ctx->ac, "llvm.floor.f32", ctx->f32,
&emit_data->args[0], 1, AC_FUNC_ATTR_READNONE);
emit_data->output[emit_data->chan] = LLVMBuildFPToSI(ctx->ac.builder,
floor_index, ctx->i32, "");
}
static void emit_and(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildAnd(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
static void emit_or(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildOr(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
static void emit_uadd(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildAdd(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
static void emit_udiv(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildUDiv(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
static void emit_idiv(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildSDiv(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
static void emit_mod(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildSRem(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
static void emit_umod(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildURem(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
static void emit_shl(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildShl(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
static void emit_ushr(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildLShr(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
static void emit_ishr(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildAShr(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
static void emit_xor(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildXor(ctx->ac.builder,
emit_data->args[0], emit_data->args[1], "");
}
static void emit_ssg(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMValueRef val;
if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_I64SSG) {
val = ac_build_isign(&ctx->ac, emit_data->args[0], 64);
} else if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_ISSG) {
val = ac_build_isign(&ctx->ac, emit_data->args[0], 32);
} else if (emit_data->inst->Instruction.Opcode == TGSI_OPCODE_DSSG) {
val = ac_build_fsign(&ctx->ac, emit_data->args[0], 64);
} else {
val = ac_build_fsign(&ctx->ac, emit_data->args[0], 32);
}
emit_data->output[emit_data->chan] = val;
}
static void emit_ineg(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildNeg(ctx->ac.builder,
emit_data->args[0], "");
}
static void emit_dneg(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildFNeg(ctx->ac.builder,
emit_data->args[0], "");
}
static void emit_frac(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
unsigned bitsize;
if (emit_data->info->opcode == TGSI_OPCODE_FRC)
bitsize = 32;
else if (emit_data->info->opcode == TGSI_OPCODE_DFRAC)
bitsize = 64;
else {
assert(0);
return;
}
emit_data->output[emit_data->chan] =
ac_build_fract(&ctx->ac, emit_data->args[0], bitsize);
}
static void emit_f2i(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildFPToSI(ctx->ac.builder,
emit_data->args[0], ctx->i32, "");
}
static void emit_f2u(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildFPToUI(ctx->ac.builder,
emit_data->args[0], ctx->i32, "");
}
static void emit_i2f(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildSIToFP(ctx->ac.builder,
emit_data->args[0], ctx->f32, "");
}
static void emit_u2f(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = LLVMBuildUIToFP(ctx->ac.builder,
emit_data->args[0], ctx->f32, "");
}
static void
build_tgsi_intrinsic_nomem(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] =
ac_build_intrinsic(&ctx->ac, action->intr_name,
emit_data->dst_type, emit_data->args,
emit_data->arg_count, AC_FUNC_ATTR_READNONE);
}
static void emit_bfi(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMBuilderRef builder = ctx->ac.builder;
LLVMValueRef bfi_args[3];
LLVMValueRef bfi_sm5;
LLVMValueRef cond;
// Calculate the bitmask: (((1 << src3) - 1) << src2
bfi_args[0] = LLVMBuildShl(builder,
LLVMBuildSub(builder,
LLVMBuildShl(builder,
ctx->i32_1,
emit_data->args[3], ""),
ctx->i32_1, ""),
emit_data->args[2], "");
bfi_args[1] = LLVMBuildShl(builder, emit_data->args[1],
emit_data->args[2], "");
bfi_args[2] = emit_data->args[0];
/* Calculate:
* (arg0 & arg1) | (~arg0 & arg2) = arg2 ^ (arg0 & (arg1 ^ arg2)
* Use the right-hand side, which the LLVM backend can convert to V_BFI.
*/
bfi_sm5 =
LLVMBuildXor(builder, bfi_args[2],
LLVMBuildAnd(builder, bfi_args[0],
LLVMBuildXor(builder, bfi_args[1], bfi_args[2],
""), ""), "");
/* Since shifts of >= 32 bits are undefined in LLVM IR, the backend
* uses the convenient V_BFI lowering for the above, which follows SM5
* and disagrees with GLSL semantics when bits (src3) is 32.
*/
cond = LLVMBuildICmp(builder, LLVMIntUGE, emit_data->args[3],
LLVMConstInt(ctx->i32, 32, 0), "");
emit_data->output[emit_data->chan] =
LLVMBuildSelect(builder, cond, emit_data->args[1], bfi_sm5, "");
}
static void emit_bfe(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
/* FIXME: LLVM 7 returns incorrect result when count is 0.
* https://bugs.freedesktop.org/show_bug.cgi?id=107276
*/
LLVMValueRef zero = ctx->i32_0;
LLVMValueRef bfe_sm5 =
ac_build_bfe(&ctx->ac, emit_data->args[0],
emit_data->args[1], emit_data->args[2],
emit_data->info->opcode == TGSI_OPCODE_IBFE);
/* Correct for GLSL semantics. */
LLVMValueRef cond = LLVMBuildICmp(ctx->ac.builder, LLVMIntUGE, emit_data->args[2],
LLVMConstInt(ctx->i32, 32, 0), "");
LLVMValueRef cond2 = LLVMBuildICmp(ctx->ac.builder, LLVMIntEQ, emit_data->args[2],
zero, "");
bfe_sm5 = LLVMBuildSelect(ctx->ac.builder, cond, emit_data->args[0], bfe_sm5, "");
emit_data->output[emit_data->chan] =
LLVMBuildSelect(ctx->ac.builder, cond2, zero, bfe_sm5, "");
}
/* this is ffs in C */
static void emit_lsb(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] = ac_find_lsb(&ctx->ac, emit_data->dst_type, emit_data->args[0]);
}
/* Find the last bit set. */
static void emit_umsb(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] =
ac_build_umsb(&ctx->ac, emit_data->args[0], emit_data->dst_type);
}
/* Find the last bit opposite of the sign bit. */
static void emit_imsb(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] =
ac_build_imsb(&ctx->ac, emit_data->args[0],
emit_data->dst_type);
}
static void emit_iabs(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] =
ac_build_imax(&ctx->ac, emit_data->args[0],
LLVMBuildNeg(ctx->ac.builder, emit_data->args[0], ""));
}
static void emit_minmax_int(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMIntPredicate op;
switch (emit_data->info->opcode) {
default:
assert(0);
case TGSI_OPCODE_IMAX:
case TGSI_OPCODE_I64MAX:
op = LLVMIntSGT;
break;
case TGSI_OPCODE_IMIN:
case TGSI_OPCODE_I64MIN:
op = LLVMIntSLT;
break;
case TGSI_OPCODE_UMAX:
case TGSI_OPCODE_U64MAX:
op = LLVMIntUGT;
break;
case TGSI_OPCODE_UMIN:
case TGSI_OPCODE_U64MIN:
op = LLVMIntULT;
break;
}
emit_data->output[emit_data->chan] =
LLVMBuildSelect(ctx->ac.builder,
LLVMBuildICmp(ctx->ac.builder, op, emit_data->args[0],
emit_data->args[1], ""),
emit_data->args[0],
emit_data->args[1], "");
}
static void emit_pk2h(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMValueRef v[] = {
lp_build_emit_fetch(bld_base, emit_data->inst, 0, TGSI_CHAN_X),
lp_build_emit_fetch(bld_base, emit_data->inst, 0, TGSI_CHAN_Y),
};
/* From the GLSL 4.50 spec:
* "The rounding mode cannot be set and is undefined."
*
* v_cvt_pkrtz_f16 rounds to zero, but it's fastest.
*/
emit_data->output[emit_data->chan] =
LLVMBuildBitCast(ctx->ac.builder, ac_build_cvt_pkrtz_f16(&ctx->ac, v),
ctx->i32, "");
}
static void emit_up2h(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMTypeRef i16;
LLVMValueRef const16, input, val;
unsigned i;
i16 = LLVMInt16TypeInContext(ctx->ac.context);
const16 = LLVMConstInt(ctx->i32, 16, 0);
input = lp_build_emit_fetch(bld_base, emit_data->inst, 0, TGSI_CHAN_X);
for (i = 0; i < 2; i++) {
val = i == 1 ? LLVMBuildLShr(ctx->ac.builder, input, const16, "") : input;
val = LLVMBuildTrunc(ctx->ac.builder, val, i16, "");
val = ac_to_float(&ctx->ac, val);
emit_data->output[i] = LLVMBuildFPExt(ctx->ac.builder, val, ctx->f32, "");
}
}
static void emit_fdiv(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
emit_data->output[emit_data->chan] =
ac_build_fdiv(&ctx->ac, emit_data->args[0], emit_data->args[1]);
}
/* 1/sqrt is translated to rsq for f32 if fp32 denormals are not enabled in
* the target machine. f64 needs global unsafe math flags to get rsq. */
static void emit_rsq(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMValueRef sqrt =
ac_build_intrinsic(&ctx->ac, "llvm.sqrt.f32", ctx->f32,
&emit_data->args[0], 1, AC_FUNC_ATTR_READNONE);
emit_data->output[emit_data->chan] =
ac_build_fdiv(&ctx->ac, ctx->ac.f32_1, sqrt);
}
static void dfracexp_emit(const struct lp_build_tgsi_action *action,
struct lp_build_tgsi_context *bld_base,
struct lp_build_emit_data *emit_data)
{
struct si_shader_context *ctx = si_shader_context(bld_base);
LLVMValueRef in = lp_build_emit_fetch(bld_base, emit_data->inst, 0, TGSI_CHAN_X);
emit_data->output[emit_data->chan] =
ac_build_intrinsic(&ctx->ac, "llvm.amdgcn.frexp.mant.f64",
ctx->ac.f64, &in, 1, 0);
emit_data->output1[emit_data->chan] =
ac_build_intrinsic(&ctx->ac, "llvm.amdgcn.frexp.exp.i32.f64",
ctx->ac.i32, &in, 1, 0);
}
void si_shader_context_init_alu(struct si_shader_context *ctx)
{
struct lp_build_tgsi_context *bld_base = &ctx->bld_base;
lp_set_default_actions(bld_base);
bld_base->op_actions[TGSI_OPCODE_AND].emit = emit_and;
bld_base->op_actions[TGSI_OPCODE_ARL].emit = emit_arl;
bld_base->op_actions[TGSI_OPCODE_BFI].emit = emit_bfi;
bld_base->op_actions[TGSI_OPCODE_BREV].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_BREV].intr_name = "llvm.bitreverse.i32";
bld_base->op_actions[TGSI_OPCODE_CEIL].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_CEIL].intr_name = "llvm.ceil.f32";
bld_base->op_actions[TGSI_OPCODE_CMP].emit = emit_cmp;
bld_base->op_actions[TGSI_OPCODE_COS].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_COS].intr_name = "llvm.cos.f32";
bld_base->op_actions[TGSI_OPCODE_DABS].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_DABS].intr_name = "llvm.fabs.f64";
bld_base->op_actions[TGSI_OPCODE_DCEIL].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_DCEIL].intr_name = "llvm.ceil.f64";
bld_base->op_actions[TGSI_OPCODE_DFLR].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_DFLR].intr_name = "llvm.floor.f64";
bld_base->op_actions[TGSI_OPCODE_DFMA].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_DFMA].intr_name = "llvm.fma.f64";
bld_base->op_actions[TGSI_OPCODE_DFRAC].emit = emit_frac;
bld_base->op_actions[TGSI_OPCODE_DIV].emit = emit_fdiv;
bld_base->op_actions[TGSI_OPCODE_DNEG].emit = emit_dneg;
bld_base->op_actions[TGSI_OPCODE_DROUND].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_DROUND].intr_name = "llvm.rint.f64";
bld_base->op_actions[TGSI_OPCODE_DSEQ].emit = emit_dcmp;
bld_base->op_actions[TGSI_OPCODE_DSGE].emit = emit_dcmp;
bld_base->op_actions[TGSI_OPCODE_DSLT].emit = emit_dcmp;
bld_base->op_actions[TGSI_OPCODE_DSNE].emit = emit_dcmp;
bld_base->op_actions[TGSI_OPCODE_DSSG].emit = emit_ssg;
bld_base->op_actions[TGSI_OPCODE_DRSQ].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_DRSQ].intr_name = "llvm.amdgcn.rsq.f64";
bld_base->op_actions[TGSI_OPCODE_DSQRT].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_DSQRT].intr_name = "llvm.sqrt.f64";
bld_base->op_actions[TGSI_OPCODE_DTRUNC].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_DTRUNC].intr_name = "llvm.trunc.f64";
bld_base->op_actions[TGSI_OPCODE_DFRACEXP].emit = dfracexp_emit;
bld_base->op_actions[TGSI_OPCODE_DLDEXP].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_DLDEXP].intr_name = "llvm.amdgcn.ldexp.f64";
bld_base->op_actions[TGSI_OPCODE_EX2].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_EX2].intr_name = "llvm.exp2.f32";
bld_base->op_actions[TGSI_OPCODE_FLR].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_FLR].intr_name = "llvm.floor.f32";
/* FMA is better on GFX10, because it has FMA units instead of MUL-ADD units. */
if (ctx->screen->info.chip_class >= GFX10) {
bld_base->op_actions[TGSI_OPCODE_FMA].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_FMA].intr_name = "llvm.fma.f32";
} else {
bld_base->op_actions[TGSI_OPCODE_FMA].emit =
bld_base->op_actions[TGSI_OPCODE_MAD].emit;
}
bld_base->op_actions[TGSI_OPCODE_FRC].emit = emit_frac;
bld_base->op_actions[TGSI_OPCODE_F2I].emit = emit_f2i;
bld_base->op_actions[TGSI_OPCODE_F2U].emit = emit_f2u;
bld_base->op_actions[TGSI_OPCODE_FSEQ].emit = emit_fcmp;
bld_base->op_actions[TGSI_OPCODE_FSGE].emit = emit_fcmp;
bld_base->op_actions[TGSI_OPCODE_FSLT].emit = emit_fcmp;
bld_base->op_actions[TGSI_OPCODE_FSNE].emit = emit_fcmp;
bld_base->op_actions[TGSI_OPCODE_IABS].emit = emit_iabs;
bld_base->op_actions[TGSI_OPCODE_IBFE].emit = emit_bfe;
bld_base->op_actions[TGSI_OPCODE_IDIV].emit = emit_idiv;
bld_base->op_actions[TGSI_OPCODE_IMAX].emit = emit_minmax_int;
bld_base->op_actions[TGSI_OPCODE_IMIN].emit = emit_minmax_int;
bld_base->op_actions[TGSI_OPCODE_IMSB].emit = emit_imsb;
bld_base->op_actions[TGSI_OPCODE_INEG].emit = emit_ineg;
bld_base->op_actions[TGSI_OPCODE_ISHR].emit = emit_ishr;
bld_base->op_actions[TGSI_OPCODE_ISGE].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_ISLT].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_ISSG].emit = emit_ssg;
bld_base->op_actions[TGSI_OPCODE_I2F].emit = emit_i2f;
bld_base->op_actions[TGSI_OPCODE_KILL_IF].emit = kil_emit;
bld_base->op_actions[TGSI_OPCODE_KILL].emit = kil_emit;
bld_base->op_actions[TGSI_OPCODE_LDEXP].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_LDEXP].intr_name = "llvm.amdgcn.ldexp.f32";
bld_base->op_actions[TGSI_OPCODE_LSB].emit = emit_lsb;
bld_base->op_actions[TGSI_OPCODE_LG2].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_LG2].intr_name = "llvm.log2.f32";
bld_base->op_actions[TGSI_OPCODE_MAX].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_MAX].intr_name = "llvm.maxnum.f32";
bld_base->op_actions[TGSI_OPCODE_MIN].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_MIN].intr_name = "llvm.minnum.f32";
bld_base->op_actions[TGSI_OPCODE_MOD].emit = emit_mod;
bld_base->op_actions[TGSI_OPCODE_UMSB].emit = emit_umsb;
bld_base->op_actions[TGSI_OPCODE_NOT].emit = emit_not;
bld_base->op_actions[TGSI_OPCODE_OR].emit = emit_or;
bld_base->op_actions[TGSI_OPCODE_PK2H].emit = emit_pk2h;
bld_base->op_actions[TGSI_OPCODE_POPC].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_POPC].intr_name = "llvm.ctpop.i32";
bld_base->op_actions[TGSI_OPCODE_POW].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_POW].intr_name = "llvm.pow.f32";
bld_base->op_actions[TGSI_OPCODE_ROUND].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_ROUND].intr_name = "llvm.rint.f32";
bld_base->op_actions[TGSI_OPCODE_RSQ].emit = emit_rsq;
bld_base->op_actions[TGSI_OPCODE_SGE].emit = emit_set_cond;
bld_base->op_actions[TGSI_OPCODE_SEQ].emit = emit_set_cond;
bld_base->op_actions[TGSI_OPCODE_SHL].emit = emit_shl;
bld_base->op_actions[TGSI_OPCODE_SLE].emit = emit_set_cond;
bld_base->op_actions[TGSI_OPCODE_SLT].emit = emit_set_cond;
bld_base->op_actions[TGSI_OPCODE_SNE].emit = emit_set_cond;
bld_base->op_actions[TGSI_OPCODE_SGT].emit = emit_set_cond;
bld_base->op_actions[TGSI_OPCODE_SIN].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_SIN].intr_name = "llvm.sin.f32";
bld_base->op_actions[TGSI_OPCODE_SQRT].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_SQRT].intr_name = "llvm.sqrt.f32";
bld_base->op_actions[TGSI_OPCODE_SSG].emit = emit_ssg;
bld_base->op_actions[TGSI_OPCODE_TRUNC].emit = build_tgsi_intrinsic_nomem;
bld_base->op_actions[TGSI_OPCODE_TRUNC].intr_name = "llvm.trunc.f32";
bld_base->op_actions[TGSI_OPCODE_UADD].emit = emit_uadd;
bld_base->op_actions[TGSI_OPCODE_UBFE].emit = emit_bfe;
bld_base->op_actions[TGSI_OPCODE_UDIV].emit = emit_udiv;
bld_base->op_actions[TGSI_OPCODE_UMAX].emit = emit_minmax_int;
bld_base->op_actions[TGSI_OPCODE_UMIN].emit = emit_minmax_int;
bld_base->op_actions[TGSI_OPCODE_UMOD].emit = emit_umod;
bld_base->op_actions[TGSI_OPCODE_USEQ].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_USGE].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_USHR].emit = emit_ushr;
bld_base->op_actions[TGSI_OPCODE_USLT].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_USNE].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_U2F].emit = emit_u2f;
bld_base->op_actions[TGSI_OPCODE_XOR].emit = emit_xor;
bld_base->op_actions[TGSI_OPCODE_UCMP].emit = emit_ucmp;
bld_base->op_actions[TGSI_OPCODE_UP2H].emit = emit_up2h;
bld_base->op_actions[TGSI_OPCODE_I64MAX].emit = emit_minmax_int;
bld_base->op_actions[TGSI_OPCODE_I64MIN].emit = emit_minmax_int;
bld_base->op_actions[TGSI_OPCODE_U64MAX].emit = emit_minmax_int;
bld_base->op_actions[TGSI_OPCODE_U64MIN].emit = emit_minmax_int;
bld_base->op_actions[TGSI_OPCODE_I64ABS].emit = emit_iabs;
bld_base->op_actions[TGSI_OPCODE_I64SSG].emit = emit_ssg;
bld_base->op_actions[TGSI_OPCODE_I64NEG].emit = emit_ineg;
bld_base->op_actions[TGSI_OPCODE_U64SEQ].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_U64SNE].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_U64SGE].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_U64SLT].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_I64SGE].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_I64SLT].emit = emit_icmp;
bld_base->op_actions[TGSI_OPCODE_U64ADD].emit = emit_uadd;
bld_base->op_actions[TGSI_OPCODE_U64SHL].emit = emit_shl;
bld_base->op_actions[TGSI_OPCODE_U64SHR].emit = emit_ushr;
bld_base->op_actions[TGSI_OPCODE_I64SHR].emit = emit_ishr;
bld_base->op_actions[TGSI_OPCODE_U64MOD].emit = emit_umod;
bld_base->op_actions[TGSI_OPCODE_I64MOD].emit = emit_mod;
bld_base->op_actions[TGSI_OPCODE_U64DIV].emit = emit_udiv;
bld_base->op_actions[TGSI_OPCODE_I64DIV].emit = emit_idiv;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -27,7 +27,6 @@
#include "compiler/nir/nir_serialize.h"
#include "nir/tgsi_to_nir.h"
#include "tgsi/tgsi_parse.h"
#include "util/hash_table.h"
#include "util/crc32.h"
#include "util/u_async_debug.h"
@ -51,11 +50,7 @@ void si_get_ir_cache_key(struct si_shader_selector *sel, bool ngg, bool es,
unsigned ir_size;
void *ir_binary;
if (sel->tokens) {
ir_binary = sel->tokens;
ir_size = tgsi_num_tokens(sel->tokens) *
sizeof(struct tgsi_token);
} else if (sel->nir_binary) {
if (sel->nir_binary) {
ir_binary = sel->nir_binary;
ir_size = sel->nir_size;
} else {
@ -2153,7 +2148,7 @@ static bool si_check_missing_main_part(struct si_screen *sscreen,
main_part->key.as_ngg = key->as_ngg;
main_part->is_monolithic = false;
if (si_compile_tgsi_shader(sscreen, compiler_state->compiler,
if (si_compile_shader(sscreen, compiler_state->compiler,
main_part, &compiler_state->debug) != 0) {
FREE(main_part);
return false;
@ -2516,7 +2511,7 @@ static void si_init_shader_selector_async(void *job, int thread_index)
sel->type == PIPE_SHADER_GEOMETRY))
shader->key.as_ngg = 1;
if (sel->tokens || sel->nir) {
if (sel->nir) {
si_get_ir_cache_key(sel, shader->key.as_ngg,
shader->key.as_es, ir_sha1_cache_key);
}
@ -2531,7 +2526,7 @@ static void si_init_shader_selector_async(void *job, int thread_index)
simple_mtx_unlock(&sscreen->shader_cache_mutex);
/* Compile the shader if it hasn't been loaded from the cache. */
if (si_compile_tgsi_shader(sscreen, compiler, shader,
if (si_compile_shader(sscreen, compiler, shader,
debug) != 0) {
FREE(shader);
fprintf(stderr, "radeonsi: can't compile a main shader part\n");
@ -2695,44 +2690,17 @@ static void *si_create_shader_selector(struct pipe_context *ctx,
sel->so = state->stream_output;
if (state->type == PIPE_SHADER_IR_TGSI &&
!sscreen->options.enable_nir) {
sel->tokens = tgsi_dup_tokens(state->tokens);
if (!sel->tokens) {
FREE(sel);
return NULL;
}
tgsi_scan_shader(state->tokens, &sel->info);
tgsi_scan_tess_ctrl(state->tokens, &sel->info, &sel->tcs_info);
/* Fixup for TGSI: Set which opcode uses which (i,j) pair. */
if (sel->info.uses_persp_opcode_interp_centroid)
sel->info.uses_persp_centroid = true;
if (sel->info.uses_linear_opcode_interp_centroid)
sel->info.uses_linear_centroid = true;
if (sel->info.uses_persp_opcode_interp_offset ||
sel->info.uses_persp_opcode_interp_sample)
sel->info.uses_persp_center = true;
if (sel->info.uses_linear_opcode_interp_offset ||
sel->info.uses_linear_opcode_interp_sample)
sel->info.uses_linear_center = true;
if (state->type == PIPE_SHADER_IR_TGSI) {
sel->nir = tgsi_to_nir(state->tokens, ctx->screen);
} else {
if (state->type == PIPE_SHADER_IR_TGSI) {
sel->nir = tgsi_to_nir(state->tokens, ctx->screen);
} else {
assert(state->type == PIPE_SHADER_IR_NIR);
sel->nir = state->ir.nir;
}
si_nir_scan_shader(sel->nir, &sel->info);
si_nir_scan_tess_ctrl(sel->nir, &sel->tcs_info);
si_nir_adjust_driver_locations(sel->nir);
assert(state->type == PIPE_SHADER_IR_NIR);
sel->nir = state->ir.nir;
}
si_nir_scan_shader(sel->nir, &sel->info);
si_nir_scan_tess_ctrl(sel->nir, &sel->tcs_info);
si_nir_adjust_driver_locations(sel->nir);
sel->type = sel->info.processor;
p_atomic_inc(&sscreen->num_shaders_created);
si_get_active_slot_masks(&sel->info,
@ -3304,7 +3272,6 @@ void si_destroy_shader_selector(struct si_context *sctx,
util_queue_fence_destroy(&sel->ready);
simple_mtx_destroy(&sel->mutex);
free(sel->tokens);
ralloc_free(sel->nir);
free(sel->nir_binary);
free(sel);

View file

@ -552,12 +552,6 @@ TODO: document the other workarounds.
<application name="Rocket League" executable="RocketLeague">
<option name="radeonsi_zerovram" value="true" />
</application>
<application name="Civilization 6" executable="Civ6">
<option name="radeonsi_enable_nir" value="true"/>
</application>
<application name="Civilization 6" executable="Civ6Sub">
<option name="radeonsi_enable_nir" value="true"/>
</application>
<application name="DiRT Rally" executable="DirtRally">
<option name="radeonsi_prim_restart_tri_strips_only" value="true"/>
</application>