mesa/src/microsoft/compiler/dxil_module.h
Jesse Natalie f121d8fe12 microsoft/compiler: Un-lower shared/scratch to derefs
Derefs have index-based access semantics, which means we don't need
custom intrinsics to encode an index instead of a byte offset.

Remove the "masked" store intrinsics and just emit the pair of atomics
directly. This massively reduces duplication between scratch, shared,
and constant, while also moving more things into nir so more optimizations
can be done.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/23173>
2023-06-13 00:43:36 +00:00

583 lines
19 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright © Microsoft Corporation
*
* 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
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
/*
* See the DirectX Shader Compiler for documentation for DXIL details:
* https://github.com/Microsoft/DirectXShaderCompiler/blob/master/docs/DXIL.rst
*/
#ifndef DXIL_MODULE_H
#define DXIL_MODULE_H
#ifdef __cplusplus
extern "C" {
#endif
#include "dxil_buffer.h"
#include "dxil_signature.h"
#include "util/list.h"
#define DXIL_SHADER_MAX_IO_ROWS 80
enum dxil_shader_kind {
DXIL_PIXEL_SHADER = 0,
DXIL_VERTEX_SHADER = 1,
DXIL_GEOMETRY_SHADER = 2,
DXIL_HULL_SHADER = 3,
DXIL_DOMAIN_SHADER = 4,
DXIL_COMPUTE_SHADER = 5,
};
extern int debug_dxil;
enum dxil_debug_flags {
DXIL_DEBUG_VERBOSE = 1 << 0,
DXIL_DEBUG_DUMP_BLOB = 1 << 1,
DXIL_DEBUG_TRACE = 1 << 2,
DXIL_DEBUG_DUMP_MODULE = 1 << 3,
};
enum dxil_bin_opcode {
DXIL_BINOP_ADD = 0,
DXIL_BINOP_SUB = 1,
DXIL_BINOP_MUL = 2,
DXIL_BINOP_UDIV = 3,
DXIL_BINOP_SDIV = 4,
DXIL_BINOP_UREM = 5,
DXIL_BINOP_SREM = 6,
DXIL_BINOP_SHL = 7,
DXIL_BINOP_LSHR = 8,
DXIL_BINOP_ASHR = 9,
DXIL_BINOP_AND = 10,
DXIL_BINOP_OR = 11,
DXIL_BINOP_XOR = 12,
DXIL_BINOP_INSTR_COUNT
};
enum dxil_cast_opcode {
DXIL_CAST_TRUNC = 0,
DXIL_CAST_ZEXT = 1,
DXIL_CAST_SEXT = 2,
DXIL_CAST_FPTOUI = 3,
DXIL_CAST_FPTOSI = 4,
DXIL_CAST_UITOFP = 5,
DXIL_CAST_SITOFP = 6,
DXIL_CAST_FPTRUNC = 7,
DXIL_CAST_FPEXT = 8,
DXIL_CAST_PTRTOINT = 9,
DXIL_CAST_INTTOPTR = 10,
DXIL_CAST_BITCAST = 11,
DXIL_CAST_ADDRSPACECAST = 12,
DXIL_CAST_INSTR_COUNT
};
enum dxil_cmp_pred {
DXIL_FCMP_FALSE = 0,
DXIL_FCMP_OEQ = 1,
DXIL_FCMP_OGT = 2,
DXIL_FCMP_OGE = 3,
DXIL_FCMP_OLT = 4,
DXIL_FCMP_OLE = 5,
DXIL_FCMP_ONE = 6,
DXIL_FCMP_ORD = 7,
DXIL_FCMP_UNO = 8,
DXIL_FCMP_UEQ = 9,
DXIL_FCMP_UGT = 10,
DXIL_FCMP_UGE = 11,
DXIL_FCMP_ULT = 12,
DXIL_FCMP_ULE = 13,
DXIL_FCMP_UNE = 14,
DXIL_FCMP_TRUE = 15,
DXIL_ICMP_EQ = 32,
DXIL_ICMP_NE = 33,
DXIL_ICMP_UGT = 34,
DXIL_ICMP_UGE = 35,
DXIL_ICMP_ULT = 36,
DXIL_ICMP_ULE = 37,
DXIL_ICMP_SGT = 38,
DXIL_ICMP_SGE = 39,
DXIL_ICMP_SLT = 40,
DXIL_ICMP_SLE = 41,
DXIL_CMP_INSTR_COUNT
};
enum dxil_opt_flags {
DXIL_UNSAFE_ALGEBRA = (1 << 0),
DXIL_NO_NANS = (1 << 1),
DXIL_NO_INFS = (1 << 2),
DXIL_NO_SIGNED_ZEROS = (1 << 3),
DXIL_ALLOW_RECIPROCAL = (1 << 4)
};
struct dxil_features {
unsigned doubles : 1,
cs_4x_raw_sb : 1,
uavs_at_every_stage : 1,
use_64uavs : 1,
min_precision : 1,
dx11_1_double_extensions : 1,
dx11_1_shader_extensions : 1,
dx9_comparison_filtering : 1,
tiled_resources : 1,
stencil_ref : 1,
inner_coverage : 1,
typed_uav_load_additional_formats : 1,
rovs : 1,
array_layer_from_vs_or_ds : 1,
wave_ops : 1,
int64_ops : 1,
view_id : 1,
barycentrics : 1,
native_low_precision : 1,
shading_rate : 1,
raytracing_tier_1_1 : 1,
sampler_feedback : 1,
atomic_int64_typed : 1,
atomic_int64_tgsm : 1,
derivatives_in_mesh_or_amp : 1,
resource_descriptor_heap_indexing : 1,
sampler_descriptor_heap_indexing : 1,
unnamed : 1,
atomic_int64_heap_resource : 1,
advanced_texture_ops : 1,
writable_msaa : 1;
};
struct dxil_shader_info {
unsigned has_out_position:1;
unsigned has_out_depth:1;
unsigned has_per_sample_input:1;
};
struct dxil_func_def {
struct list_head head;
const struct dxil_func *func;
struct list_head instr_list;
int *basic_block_ids; /* maps from "user" ids to LLVM ids */
size_t num_basic_block_ids;
unsigned curr_block;
};
struct dxil_module {
void *ralloc_ctx;
enum dxil_shader_kind shader_kind;
unsigned major_version, minor_version;
unsigned major_validator, minor_validator;
struct dxil_features feats;
unsigned raw_and_structured_buffers : 1;
struct dxil_shader_info info;
struct dxil_buffer buf;
/* The number of entries in the arrays below */
unsigned num_sig_inputs;
unsigned num_sig_outputs;
unsigned num_sig_patch_consts;
/* The number of "vectors" of elements. This is used to determine the sizes
* of the dependency tables.
*/
unsigned num_psv_inputs;
unsigned num_psv_outputs[4];
unsigned num_psv_patch_consts;
struct dxil_signature_record inputs[DXIL_SHADER_MAX_IO_ROWS];
struct dxil_signature_record outputs[DXIL_SHADER_MAX_IO_ROWS];
struct dxil_signature_record patch_consts[DXIL_SHADER_MAX_IO_ROWS];
/* This array is indexed using var->data.driver_location, which
* is not a direct match to IO rows, since a row is a vec4, and
* variables can occupy less than that, and several vars can
* be packed in a row. Hence the x4, but I doubt we can end up
* with more than 80x4 variables in practice. Maybe this array
* should be allocated dynamically based on on the maximum
* driver_location across all input vars.
*/
unsigned input_mappings[DXIL_SHADER_MAX_IO_ROWS * 4];
struct dxil_psv_signature_element psv_inputs[DXIL_SHADER_MAX_IO_ROWS];
struct dxil_psv_signature_element psv_outputs[DXIL_SHADER_MAX_IO_ROWS];
struct dxil_psv_signature_element psv_patch_consts[DXIL_SHADER_MAX_IO_ROWS];
struct _mesa_string_buffer *sem_string_table;
struct dxil_psv_sem_index_table sem_index_table;
/* These tables are a bitmask per input, with one bit per output
* to indicate whether or not that input contributes to the output.
* Each input's bitmask size is rounded up to a uint32 (DWORD),
* so a bitbask for one output component is the same as for 8 output vec4s.
* Sizes are in number of uint32s.
* Meaning of each array entry depends on shader stage.
* GS: [i] = output stream index
* HS: [0] = control point outputs, [1] = patch constant outputs
* DS: [0] = control point inputs, [1] = patch constant inputs (only for io table)
* PS/VS: only 0 is used. */
uint32_t *serialized_dependency_table;
uint32_t *viewid_dependency_table[4];
uint32_t *io_dependency_table[4];
uint32_t dependency_table_dwords_per_input[4];
uint32_t io_dependency_table_size[4];
uint32_t serialized_dependency_table_size;
struct {
unsigned abbrev_width;
intptr_t offset;
} blocks[16];
size_t num_blocks;
struct list_head type_list;
struct list_head gvar_list;
struct list_head func_list;
struct list_head func_def_list;
struct list_head attr_set_list;
struct list_head const_list;
struct list_head mdnode_list;
struct list_head md_named_node_list;
const struct dxil_type *void_type;
const struct dxil_type *int1_type, *int8_type, *int16_type,
*int32_type, *int64_type;
const struct dxil_type *float16_type, *float32_type, *float64_type;
struct rb_tree *functions;
struct dxil_func_def *cur_emitting_func;
};
struct dxil_instr;
struct dxil_value;
void
dxil_module_init(struct dxil_module *m, void *ralloc_ctx);
void
dxil_module_release(struct dxil_module *m);
const struct dxil_value *
dxil_add_global_var(struct dxil_module *m, const char *name,
const struct dxil_type *type,
enum dxil_address_space as, int align,
const struct dxil_value *value);
const struct dxil_value *
dxil_add_global_ptr_var(struct dxil_module *m, const char *name,
const struct dxil_type *type,
enum dxil_address_space as, int align,
const struct dxil_value *value);
struct dxil_func_def *
dxil_add_function_def(struct dxil_module *m, const char *name,
const struct dxil_type *type, unsigned num_blocks,
const char *const *attr_keys, const char *const *attr_values);
const struct dxil_func *
dxil_add_function_decl(struct dxil_module *m, const char *name,
const struct dxil_type *type,
enum dxil_attr_kind attr);
const struct dxil_type *
dxil_module_get_void_type(struct dxil_module *m);
const struct dxil_type *
dxil_module_get_int_type(struct dxil_module *m, unsigned bit_size);
const struct dxil_type *
dxil_module_get_float_type(struct dxil_module *m, unsigned bit_size);
const struct dxil_type *
dxil_module_get_pointer_type(struct dxil_module *m,
const struct dxil_type *target);
const struct dxil_type *
dxil_get_overload_type(struct dxil_module *mod, enum overload_type overload);
const struct dxil_type *
dxil_module_get_handle_type(struct dxil_module *m);
const struct dxil_type *
dxil_module_get_cbuf_ret_type(struct dxil_module *mod, enum overload_type overload);
const struct dxil_type *
dxil_module_get_split_double_ret_type(struct dxil_module *mod);
const struct dxil_type *
dxil_module_get_res_type(struct dxil_module *m, enum dxil_resource_kind kind,
enum dxil_component_type comp_type, unsigned num_comps,
bool readwrite);
const struct dxil_type *
dxil_module_get_resret_type(struct dxil_module *m, enum overload_type overload);
const struct dxil_type *
dxil_module_get_dimret_type(struct dxil_module *m);
const struct dxil_type *
dxil_module_get_samplepos_type(struct dxil_module *m);
const struct dxil_type *
dxil_module_get_res_bind_type(struct dxil_module *m);
const struct dxil_type *
dxil_module_get_res_props_type(struct dxil_module *m);
const struct dxil_type *
dxil_module_get_fouri32_type(struct dxil_module *m);
const struct dxil_type *
dxil_module_get_struct_type(struct dxil_module *m,
const char *name,
const struct dxil_type **elem_types,
size_t num_elem_types);
const struct dxil_type *
dxil_module_get_array_type(struct dxil_module *m,
const struct dxil_type *elem_type,
size_t num_elems);
const struct dxil_type *
dxil_module_get_vector_type(struct dxil_module *m,
const struct dxil_type *elem_type,
size_t num_elems);
const struct dxil_type *
dxil_module_add_function_type(struct dxil_module *m,
const struct dxil_type *ret_type,
const struct dxil_type **arg_types,
size_t num_arg_types);
nir_alu_type
dxil_type_to_nir_type(const struct dxil_type *type);
bool
dxil_value_type_equal_to(const struct dxil_value *value,
const struct dxil_type *lhs);
bool
dxil_value_type_bitsize_equal_to(const struct dxil_value *value, unsigned bitsize);
const struct dxil_type *
dxil_value_get_type(const struct dxil_value *value);
const struct dxil_value *
dxil_module_get_int1_const(struct dxil_module *m, bool value);
const struct dxil_value *
dxil_module_get_int8_const(struct dxil_module *m, int8_t value);
const struct dxil_value *
dxil_module_get_int16_const(struct dxil_module *m, int16_t value);
const struct dxil_value *
dxil_module_get_int32_const(struct dxil_module *m, int32_t value);
const struct dxil_value *
dxil_module_get_int64_const(struct dxil_module *m, int64_t value);
const struct dxil_value *
dxil_module_get_int_const(struct dxil_module *m, intmax_t value,
unsigned bit_size);
const struct dxil_value *
dxil_module_get_float16_const(struct dxil_module *m, uint16_t);
const struct dxil_value *
dxil_module_get_float_const(struct dxil_module *m, float value);
const struct dxil_value *
dxil_module_get_double_const(struct dxil_module *m, double value);
const struct dxil_value *
dxil_module_get_array_const(struct dxil_module *m, const struct dxil_type *type,
const struct dxil_value **values);
const struct dxil_value *
dxil_module_get_vector_const(struct dxil_module *m, const struct dxil_type *type,
const struct dxil_value **values);
const struct dxil_value *
dxil_module_get_struct_const(struct dxil_module *m, const struct dxil_type *type,
const struct dxil_value **values);
const struct dxil_value *
dxil_module_get_undef(struct dxil_module *m, const struct dxil_type *type);
const struct dxil_value *
dxil_module_get_res_bind_const(struct dxil_module *m,
uint32_t lower_bound,
uint32_t upper_bound,
uint32_t space,
uint8_t class);
const struct dxil_value *
dxil_module_get_res_props_const(struct dxil_module *m,
enum dxil_resource_class class,
const struct dxil_mdnode *mdnode);
const struct dxil_value *
dxil_module_get_srv_res_props_const(struct dxil_module *m,
const nir_tex_instr *tex);
const struct dxil_value *
dxil_module_get_sampler_res_props_const(struct dxil_module *m,
bool is_shadow);
const struct dxil_value *
dxil_module_get_uav_res_props_const(struct dxil_module *m,
nir_intrinsic_instr *intr);
const struct dxil_value *
dxil_module_get_buffer_res_props_const(struct dxil_module *m,
enum dxil_resource_class class,
enum dxil_resource_kind kind);
const struct dxil_mdnode *
dxil_get_metadata_string(struct dxil_module *m, const char *str);
const struct dxil_mdnode *
dxil_get_metadata_value(struct dxil_module *m, const struct dxil_type *type,
const struct dxil_value *value);
const struct dxil_mdnode *
dxil_get_metadata_func(struct dxil_module *m, const struct dxil_func *func);
const struct dxil_mdnode *
dxil_get_metadata_int1(struct dxil_module *m, bool value);
const struct dxil_mdnode *
dxil_get_metadata_int8(struct dxil_module *m, int8_t value);
const struct dxil_mdnode *
dxil_get_metadata_int32(struct dxil_module *m, int32_t value);
const struct dxil_mdnode *
dxil_get_metadata_int64(struct dxil_module *m, int64_t value);
const struct dxil_mdnode *
dxil_get_metadata_float32(struct dxil_module *m, float value);
const struct dxil_mdnode *
dxil_get_metadata_node(struct dxil_module *m,
const struct dxil_mdnode *subnodes[],
size_t num_subnodes);
bool
dxil_add_metadata_named_node(struct dxil_module *m, const char *name,
const struct dxil_mdnode *subnodes[],
size_t num_subnodes);
const struct dxil_value *
dxil_emit_binop(struct dxil_module *m, enum dxil_bin_opcode opcode,
const struct dxil_value *op0, const struct dxil_value *op1,
enum dxil_opt_flags flags);
const struct dxil_value *
dxil_emit_cmp(struct dxil_module *m, enum dxil_cmp_pred pred,
const struct dxil_value *op0, const struct dxil_value *op1);
const struct dxil_value *
dxil_emit_select(struct dxil_module *m,
const struct dxil_value *op0,
const struct dxil_value *op1,
const struct dxil_value *op2);
const struct dxil_value *
dxil_emit_extractval(struct dxil_module *m, const struct dxil_value *src,
const unsigned int index);
const struct dxil_value *
dxil_emit_cast(struct dxil_module *m, enum dxil_cast_opcode opcode,
const struct dxil_type *type,
const struct dxil_value *value);
bool
dxil_emit_branch(struct dxil_module *m, const struct dxil_value *cond,
unsigned true_block, unsigned false_block);
const struct dxil_value *
dxil_instr_get_return_value(struct dxil_instr *instr);
struct dxil_instr *
dxil_emit_phi(struct dxil_module *m, const struct dxil_type *type);
bool
dxil_phi_add_incoming(struct dxil_instr *instr,
const struct dxil_value *incoming_values[],
const unsigned incoming_blocks[],
size_t num_incoming);
const struct dxil_value *
dxil_emit_call(struct dxil_module *m,
const struct dxil_func *func,
const struct dxil_value **args, size_t num_args);
bool
dxil_emit_call_void(struct dxil_module *m,
const struct dxil_func *func,
const struct dxil_value **args, size_t num_args);
bool
dxil_emit_ret_void(struct dxil_module *m);
const struct dxil_value *
dxil_emit_alloca(struct dxil_module *m, const struct dxil_type *alloc_type,
const struct dxil_value *size,
unsigned int align);
const struct dxil_value *
dxil_emit_gep_inbounds(struct dxil_module *m,
const struct dxil_value **operands,
size_t num_operands);
const struct dxil_value *
dxil_emit_load(struct dxil_module *m, const struct dxil_value *ptr,
unsigned align,
bool is_volatile);
bool
dxil_emit_store(struct dxil_module *m, const struct dxil_value *value,
const struct dxil_value *ptr, unsigned align,
bool is_volatile);
const struct dxil_value *
dxil_emit_cmpxchg(struct dxil_module *m, const struct dxil_value *cmpval,
const struct dxil_value *newval,
const struct dxil_value *ptr, bool is_volatile,
enum dxil_atomic_ordering ordering,
enum dxil_sync_scope syncscope);
const struct dxil_value *
dxil_emit_atomicrmw(struct dxil_module *m, const struct dxil_value *value,
const struct dxil_value *ptr, enum dxil_rmw_op op,
bool is_volatile, enum dxil_atomic_ordering ordering,
enum dxil_sync_scope syncscope);
bool
dxil_emit_module(struct dxil_module *m);
#ifdef __cplusplus
}
#endif
#endif