mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 18:18:06 +02:00
radeonsi: remove TGSI
Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
This commit is contained in:
parent
e5167a9276
commit
420fe1e7f9
16 changed files with 598 additions and 5346 deletions
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
239
src/gallium/drivers/radeonsi/si_shader_llvm.c
Normal file
239
src/gallium/drivers/radeonsi/si_shader_llvm.c
Normal 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);
|
||||
}
|
||||
219
src/gallium/drivers/radeonsi/si_shader_llvm_build.c
Normal file
219
src/gallium/drivers/radeonsi/si_shader_llvm_build.c
Normal 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);
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue