Commit b9c61379 authored by Erik Faye-Lund 's avatar Erik Faye-Lund Committed by Marge Bot
Browse files

microsoft/compiler: translate nir to dxil



Here's the code to emit DXIL code from NIR. It's big and bulky as-is,
and it needs to be split up a bit.

This is the combination of a lot of commits from our development branch,
containing code by several authors.
Co-authored-by: Bill Kristiansen's avatarBill Kristiansen <billkris@microsoft.com>
Co-authored-by: Boris Brezillon's avatarBoris Brezillon <boris.brezillon@collabora.com>
Co-authored-by: Daniel Stone's avatarDaniel Stone <daniels@collabora.com>
Co-authored-by: Gert Wollny's avatarGert Wollny <gert.wollny@collabora.com>
Co-authored-by: Jesse Natalie's avatarJesse Natalie <jenatali@microsoft.com>
Co-authored-by: Louis-Francis Ratté-Boulianne's avatarLouis-Francis Ratté-Boulianne <lfrb@collabora.com>
Acked-by: Jason Ekstrand's avatarJason Ekstrand <jason@jlekstrand.net>
Part-of: <!7477>
parent dd5fe2f3
...@@ -945,6 +945,10 @@ load("global_ir3", [2, 1], indices=[ACCESS, ALIGN_MUL, ALIGN_OFFSET], flags=[CAN ...@@ -945,6 +945,10 @@ load("global_ir3", [2, 1], indices=[ACCESS, ALIGN_MUL, ALIGN_OFFSET], flags=[CAN
# Note that this doesn't actually turn into a HW instruction. # Note that this doesn't actually turn into a HW instruction.
intrinsic("bindless_resource_ir3", [1], dest_comp=1, indices=[DESC_SET], flags=[CAN_ELIMINATE, CAN_REORDER]) intrinsic("bindless_resource_ir3", [1], dest_comp=1, indices=[DESC_SET], flags=[CAN_ELIMINATE, CAN_REORDER])
# DXIL specific intrinsics
# src[] = { index, 16-byte-based-offset }
load("ubo_dxil", [1, 1], [], [CAN_ELIMINATE])
# Intrinsics used by the Midgard/Bifrost blend pipeline. These are defined # Intrinsics used by the Midgard/Bifrost blend pipeline. These are defined
# within a blend shader to read/write the raw value from the tile buffer, # within a blend shader to read/write the raw value from the tile buffer,
# without applying any format conversion in the process. If the shader needs # without applying any format conversion in the process. If the shader needs
......
/*
* 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.
*/
#include "dxil_nir.h"
#include "nir_builder.h"
#include "nir_deref.h"
#include "util/u_math.h"
static void
extract_comps_from_vec32(nir_builder *b, nir_ssa_def *vec32,
unsigned dst_bit_size,
nir_ssa_def **dst_comps,
unsigned num_dst_comps)
{
unsigned step = DIV_ROUND_UP(dst_bit_size, 32);
unsigned comps_per32b = 32 / dst_bit_size;
nir_ssa_def *tmp;
for (unsigned i = 0; i < vec32->num_components; i += step) {
switch (dst_bit_size) {
case 64:
tmp = nir_pack_64_2x32_split(b, nir_channel(b, vec32, i),
nir_channel(b, vec32, i + 1));
dst_comps[i / 2] = tmp;
break;
case 32:
dst_comps[i] = nir_channel(b, vec32, i);
break;
case 16:
case 8:
unsigned dst_offs = i * comps_per32b;
tmp = nir_unpack_bits(b, nir_channel(b, vec32, i), dst_bit_size);
for (unsigned j = 0; j < comps_per32b && dst_offs + j < num_dst_comps; j++)
dst_comps[dst_offs + j] = nir_channel(b, tmp, j);
break;
}
}
}
static nir_ssa_def *
ubo_load_select_32b_comps(nir_builder *b, nir_ssa_def *vec32,
nir_ssa_def *offset, unsigned num_bytes)
{
assert(num_bytes == 16 || num_bytes == 12 || num_bytes == 8 ||
num_bytes == 4 || num_bytes == 3 || num_bytes == 2 ||
num_bytes == 1);
assert(vec32->num_components == 4);
/* 16 and 12 byte types are always aligned on 16 bytes. */
if (num_bytes > 8)
return vec32;
nir_ssa_def *comps[4];
nir_ssa_def *cond;
for (unsigned i = 0; i < 4; i++)
comps[i] = nir_channel(b, vec32, i);
/* If we have 8bytes or less to load, select which half the vec4 should
* be used.
*/
cond = nir_ine(b, nir_iand(b, offset, nir_imm_int(b, 0x8)),
nir_imm_int(b, 0));
comps[0] = nir_bcsel(b, cond, comps[2], comps[0]);
comps[1] = nir_bcsel(b, cond, comps[3], comps[1]);
/* Thanks to the CL alignment constraints, if we want 8 bytes we're done. */
if (num_bytes == 8)
return nir_vec(b, comps, 2);
/* 4 bytes or less needed, select which of the 32bit component should be
* used and return it. The sub-32bit split is handled in
* extract_comps_from_vec32().
*/
cond = nir_ine(b, nir_iand(b, offset, nir_imm_int(b, 0x4)),
nir_imm_int(b, 0));
return nir_bcsel(b, cond, comps[1], comps[0]);
}
nir_ssa_def *
build_load_ubo_dxil(nir_builder *b, nir_ssa_def *buffer,
nir_ssa_def *offset, unsigned num_components,
unsigned bit_size)
{
nir_ssa_def *idx = nir_ushr(b, offset, nir_imm_int(b, 4));
nir_ssa_def *comps[NIR_MAX_VEC_COMPONENTS];
unsigned num_bits = num_components * bit_size;
unsigned comp_idx = 0;
/* We need to split loads in 16byte chunks because that's the
* granularity of cBufferLoadLegacy().
*/
for (unsigned i = 0; i < num_bits; i += (16 * 8)) {
/* For each 16byte chunk (or smaller) we generate a 32bit ubo vec
* load.
*/
unsigned subload_num_bits = MIN2(num_bits - i, 16 * 8);
nir_intrinsic_instr *load =
nir_intrinsic_instr_create(b->shader,
nir_intrinsic_load_ubo_dxil);
load->num_components = 4;
load->src[0] = nir_src_for_ssa(buffer);
load->src[1] = nir_src_for_ssa(nir_iadd(b, idx, nir_imm_int(b, i / (16 * 8))));
nir_ssa_dest_init(&load->instr, &load->dest, load->num_components,
32, NULL);
nir_builder_instr_insert(b, &load->instr);
nir_ssa_def *vec32 = &load->dest.ssa;
/* First re-arrange the vec32 to account for intra 16-byte offset. */
vec32 = ubo_load_select_32b_comps(b, vec32, offset, subload_num_bits / 8);
/* If we have 2 bytes or less to load we need to adjust the u32 value so
* we can always extract the LSB.
*/
if (subload_num_bits <= 16) {
nir_ssa_def *shift = nir_imul(b, nir_iand(b, offset,
nir_imm_int(b, 3)),
nir_imm_int(b, 8));
vec32 = nir_ushr(b, vec32, shift);
}
/* And now comes the pack/unpack step to match the original type. */
extract_comps_from_vec32(b, vec32, bit_size, &comps[comp_idx],
subload_num_bits / bit_size);
comp_idx += subload_num_bits / bit_size;
}
assert(comp_idx == num_components);
return nir_vec(b, comps, num_components);
}
/*
* 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.
*/
#ifndef DXIL_NIR_H
#define DXIL_NIR_H
#include <stdbool.h>
#include "nir.h"
#include "nir_builder.h"
bool dxil_nir_lower_8bit_conv(nir_shader *shader);
bool dxil_nir_lower_x2b(nir_shader *shader);
bool dxil_nir_lower_inot(nir_shader *shader);
nir_ssa_def *
build_load_ubo_dxil(nir_builder *b, nir_ssa_def *buffer,
nir_ssa_def *offset, unsigned num_components,
unsigned bit_size);
#endif /* DXIL_NIR_H */
#
# Copyright (C) 2020 Microsoft Corporation
#
# Copyright (C) 2018 Alyssa Rosenzweig
#
# Copyright (C) 2016 Intel 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.
import argparse
import sys
import math
a = 'a'
# The nir_lower_bit_size() pass gets rid of all 8bit ALUs but insert new u2u8
# and i2i8 operations to convert the result back to the original type after the
# arithmetic operation is done. Those u2u8 and i2i8 operations, as any other
# 8bit operations, are not supported by DXIL and needs to be discarded. The
# dxil_nir_lower_8bit_conv() pass is here for that.
# Similarly, some hardware doesn't support 16bit values
no_8bit_conv = []
no_16bit_conv = []
def remove_unsupported_casts(arr, bit_size, mask, max_unsigned_float, min_signed_float, max_signed_float):
for outer_op_type in ('u2u', 'i2i', 'u2f', 'i2f'):
for outer_op_sz in (16, 32, 64):
if outer_op_sz == bit_size:
continue
outer_op = outer_op_type + str(int(outer_op_sz))
for inner_op_type in ('u2u', 'i2i'):
inner_op = inner_op_type + str(int(bit_size))
for src_sz in (16, 32, 64):
if (src_sz == bit_size):
continue
# Coming from integral, truncate appropriately
orig_seq = (outer_op, (inner_op, 'a@' + str(int(src_sz))))
if (outer_op[0] == 'u'):
new_seq = ('iand', a, mask)
else:
shift = src_sz - bit_size
new_seq = ('ishr', ('ishl', a, shift), shift)
# Make sure the destination is the right type/size
if outer_op_sz != src_sz or outer_op[2] != inner_op[0]:
new_seq = (outer_op, new_seq)
arr += [(orig_seq, new_seq)]
for inner_op_type in ('f2u', 'f2i'):
inner_op = inner_op_type + str(int(bit_size))
if (outer_op[2] == 'f'):
# From float and to float, just truncate via min/max, and ensure the right float size
for src_sz in (16, 32, 64):
if (src_sz == bit_size):
continue
orig_seq = (outer_op, (inner_op, 'a@' + str(int(src_sz))))
if (outer_op[0] == 'u'):
new_seq = ('fmin', ('fmax', a, 0.0), max_unsigned_float)
else:
new_seq = ('fmin', ('fmax', a, min_signed_float), max_signed_float)
if outer_op_sz != src_sz:
new_seq = ('f2f' + str(int(outer_op_sz)), new_seq)
arr += [(orig_seq, new_seq)]
else:
# From float to integral, convert to integral type first, then truncate
orig_seq = (outer_op, (inner_op, a))
float_conv = ('f2' + inner_op[2] + str(int(outer_op_sz)), a)
if (outer_op[0] == 'u'):
new_seq = ('iand', float_conv, mask)
else:
shift = outer_op_sz - bit_size
new_seq = ('ishr', ('ishl', float_conv, shift), shift)
arr += [(orig_seq, new_seq)]
remove_unsupported_casts(no_8bit_conv, 8, 0xff, 255.0, -128.0, 127.0)
remove_unsupported_casts(no_16bit_conv, 16, 0xffff, 65535.0, -32768.0, 32767.0)
lower_x2b = [
(('b2b32', 'a'), ('b2i32', 'a')),
(('b2b1', 'a'), ('i2b1', 'a')),
(('i2b1', 'a'), ('ine', a, 0)),
(('f2b1', 'a'), ('fneu', a, 0)),
]
no_16bit_conv += [
(('f2f32', ('u2u16', 'a@32')), ('unpack_half_2x16_split_x', 'a')),
(('u2u32', ('f2f16_rtz', 'a@32')), ('pack_half_2x16_split', 'a', 0)),
]
lower_inot = [
(('inot', a), ('ixor', a, -1)),
]
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-p', '--import-path', required=True)
args = parser.parse_args()
sys.path.insert(0, args.import_path)
run()
def run():
import nir_algebraic # pylint: disable=import-error
print('#include "dxil_nir.h"')
print(nir_algebraic.AlgebraicPass("dxil_nir_lower_8bit_conv",
no_8bit_conv).render())
print(nir_algebraic.AlgebraicPass("dxil_nir_lower_16bit_conv",
no_16bit_conv).render())
print(nir_algebraic.AlgebraicPass("dxil_nir_lower_x2b",
lower_x2b).render())
print(nir_algebraic.AlgebraicPass("dxil_nir_lower_inot",
lower_inot).render())
if __name__ == '__main__':
main()
This diff is collapsed.
/*
* 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
* 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.
*/
#ifndef DXIL_NIR_LOWER_INT_SAMPLERS_H
#define DXIL_NIR_LOWER_INT_SAMPLERS_H
#include "pipe/p_state.h"
#include "nir.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
unsigned swizzle_r:3;
unsigned swizzle_g:3;
unsigned swizzle_b:3;
unsigned swizzle_a:3;
} dxil_texture_swizzle_state;
typedef struct {
float border_color[4];
float lod_bias;
float min_lod, max_lod;
int last_level;
uint8_t wrap[3];
uint8_t is_int_sampler:1;
uint8_t is_nonnormalized_coords:1;
uint8_t is_linear_filtering:1;
uint8_t skip_boundary_conditions:1;
uint8_t unused:4;
} dxil_wrap_sampler_state;
bool
dxil_lower_sample_to_txf_for_integer_tex(nir_shader *s,
dxil_wrap_sampler_state *wrap_states,
dxil_texture_swizzle_state *tex_swizzles,
float max_bias);
#ifdef __cplusplus
}
#endif
#endif // DXIL_NIR_LOWER_INT_SAMPLERS_H
...@@ -26,12 +26,27 @@ files_libdxil_compiler = files( ...@@ -26,12 +26,27 @@ files_libdxil_compiler = files(
'dxil_enums.c', 'dxil_enums.c',
'dxil_function.c', 'dxil_function.c',
'dxil_module.c', 'dxil_module.c',
'dxil_nir.c',
'dxil_nir_lower_int_samplers.c',
'dxil_signature.c', 'dxil_signature.c',
'nir_to_dxil.c',
)
dxil_nir_algebraic_c = custom_target(
'dxil_nir_algebraic.c',
input : 'dxil_nir_algebraic.py',
output : 'dxil_nir_algebraic.c',
command : [
prog_python, '@INPUT@',
'-p', join_paths(meson.source_root(), 'src/compiler/nir/'),
],
capture : true,
depend_files : nir_algebraic_py,
) )
libdxil_compiler = static_library( libdxil_compiler = static_library(
'dxil_compiler', 'dxil_compiler',
[files_libdxil_compiler, sha1_h], [files_libdxil_compiler, dxil_nir_algebraic_c, sha1_h],
include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_compiler, inc_gallium], include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_compiler, inc_gallium],
dependencies: [idep_nir_headers], dependencies: [idep_nir_headers],
gnu_symbol_visibility : 'hidden', gnu_symbol_visibility : 'hidden',
......
This diff is collapsed.
/*
* 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.
*/
#ifndef NIR_TO_DXIL_H
#define NIR_TO_DXIL_H
#include <stdbool.h>
#include "nir.h"
#ifdef __cplusplus
extern "C" {
#endif
struct blob;
const char *
dxil_vs_attr_index_to_name(unsigned index);
enum dxil_sysvalue_type {
DXIL_NO_SYSVALUE = 0,
DXIL_SYSVALUE,
DXIL_GENERATED_SYSVALUE
};
enum dxil_sysvalue_type
nir_var_to_dxil_sysvalue_type(nir_variable *var, uint64_t other_stage_mask);
struct nir_to_dxil_options {
bool interpolate_at_vertex;
bool lower_int16;
bool disable_math_refactoring;
unsigned ubo_binding_offset;
unsigned provoking_vertex;
};
bool
nir_to_dxil(struct nir_shader *s, const struct nir_to_dxil_options *opts,
struct blob *blob);
const nir_shader_compiler_options*
dxil_get_nir_compiler_options(void);
#ifdef __cplusplus
}
#endif
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment