summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/nouveau/Automake.inc3
-rw-r--r--src/gallium/drivers/nouveau/Makefile.am5
-rw-r--r--src/gallium/drivers/nouveau/Makefile.sources1
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir.cpp3
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir.h1
-rw-r--r--src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp76
-rw-r--r--src/gallium/drivers/nouveau/meson.build9
-rw-r--r--src/gallium/drivers/nouveau/nouveau_screen.c2
-rw-r--r--src/gallium/drivers/nouveau/nouveau_screen.h2
-rw-r--r--src/gallium/drivers/nouveau/nv50/nv50_program.c19
-rw-r--r--src/gallium/drivers/nouveau/nv50/nv50_screen.c46
-rw-r--r--src/gallium/drivers/nouveau/nv50/nv50_state.c35
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_program.c18
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_screen.c99
-rw-r--r--src/gallium/drivers/nouveau/nvc0/nvc0_state.c31
15 files changed, 327 insertions, 23 deletions
diff --git a/src/gallium/drivers/nouveau/Automake.inc b/src/gallium/drivers/nouveau/Automake.inc
index 1d383fcb7b1..657790494dc 100644
--- a/src/gallium/drivers/nouveau/Automake.inc
+++ b/src/gallium/drivers/nouveau/Automake.inc
@@ -8,4 +8,7 @@ TARGET_LIB_DEPS += \
$(NOUVEAU_LIBS) \
$(LIBDRM_LIBS)
+TARGET_COMPILER_LIB_DEPS = \
+ $(top_builddir)/src/compiler/nir/libnir.la
+
endif
diff --git a/src/gallium/drivers/nouveau/Makefile.am b/src/gallium/drivers/nouveau/Makefile.am
index 48c0fdf512d..ee7191675cc 100644
--- a/src/gallium/drivers/nouveau/Makefile.am
+++ b/src/gallium/drivers/nouveau/Makefile.am
@@ -25,6 +25,10 @@ include $(top_srcdir)/src/gallium/Automake.inc
AM_CPPFLAGS = \
-I$(top_srcdir)/include \
+ -I$(top_builddir)/src/compiler/nir \
+ -I$(top_srcdir)/src/compiler/nir \
+ -I$(top_srcdir)/src/mapi \
+ -I$(top_srcdir)/src/mesa \
$(GALLIUM_DRIVER_CFLAGS) \
$(LIBDRM_CFLAGS) \
$(NOUVEAU_CFLAGS)
@@ -47,6 +51,7 @@ nouveau_compiler_SOURCES = \
nouveau_compiler_LDADD = \
libnouveau.la \
+ $(top_builddir)/src/compiler/nir/libnir.la \
$(top_builddir)/src/gallium/auxiliary/libgallium.la \
$(top_builddir)/src/util/libmesautil.la \
$(GALLIUM_COMMON_LIB_DEPS)
diff --git a/src/gallium/drivers/nouveau/Makefile.sources b/src/gallium/drivers/nouveau/Makefile.sources
index ec344c63169..c6a1aff7110 100644
--- a/src/gallium/drivers/nouveau/Makefile.sources
+++ b/src/gallium/drivers/nouveau/Makefile.sources
@@ -117,6 +117,7 @@ NV50_CODEGEN_SOURCES := \
codegen/nv50_ir_emit_nv50.cpp \
codegen/nv50_ir_from_common.cpp \
codegen/nv50_ir_from_common.h \
+ codegen/nv50_ir_from_nir.cpp \
codegen/nv50_ir_from_tgsi.cpp \
codegen/nv50_ir_graph.cpp \
codegen/nv50_ir_graph.h \
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp
index 993d01c1e44..a181a13a3b1 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir.cpp
@@ -1241,6 +1241,9 @@ nv50_ir_generate_code(struct nv50_ir_prog_info *info)
prog->optLevel = info->optLevel;
switch (info->bin.sourceRep) {
+ case PIPE_SHADER_IR_NIR:
+ ret = prog->makeFromNIR(info) ? 0 : -2;
+ break;
case PIPE_SHADER_IR_TGSI:
ret = prog->makeFromTGSI(info) ? 0 : -2;
break;
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir.h b/src/gallium/drivers/nouveau/codegen/nv50_ir.h
index 8d32a25ec23..b19751ab372 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir.h
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir.h
@@ -1284,6 +1284,7 @@ public:
inline void del(Function *fn, int& id) { allFuncs.remove(id); }
inline void add(Value *rval, int& id) { allRValues.insert(rval, id); }
+ bool makeFromNIR(struct nv50_ir_prog_info *);
bool makeFromTGSI(struct nv50_ir_prog_info *);
bool convertToSSA();
bool optimizeSSA(int level);
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
new file mode 100644
index 00000000000..b22c62fd434
--- /dev/null
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_from_nir.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2017 Red Hat Inc.
+ *
+ * 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 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.
+ *
+ * Authors: Karol Herbst <[email protected]>
+ */
+
+#include "compiler/nir/nir.h"
+
+#include "util/u_debug.h"
+
+#include "codegen/nv50_ir.h"
+#include "codegen/nv50_ir_from_common.h"
+#include "codegen/nv50_ir_lowering_helper.h"
+#include "codegen/nv50_ir_util.h"
+
+namespace {
+
+using namespace nv50_ir;
+
+class Converter : public ConverterCommon
+{
+public:
+ Converter(Program *, nir_shader *, nv50_ir_prog_info *);
+
+ bool run();
+private:
+ nir_shader *nir;
+};
+
+Converter::Converter(Program *prog, nir_shader *nir, nv50_ir_prog_info *info)
+ : ConverterCommon(prog, info),
+ nir(nir) {}
+
+bool
+Converter::run()
+{
+ return false;
+}
+
+} // unnamed namespace
+
+namespace nv50_ir {
+
+bool
+Program::makeFromNIR(struct nv50_ir_prog_info *info)
+{
+ nir_shader *nir = (nir_shader*)info->bin.source;
+ Converter converter(this, nir, info);
+ bool result = converter.run();
+ if (!result)
+ return result;
+ LoweringHelper lowering;
+ lowering.run(this);
+ tlsSize = info->bin.tlsSpace;
+ return result;
+}
+
+} // namespace nv50_ir
diff --git a/src/gallium/drivers/nouveau/meson.build b/src/gallium/drivers/nouveau/meson.build
index aff1b62436c..64138212b5b 100644
--- a/src/gallium/drivers/nouveau/meson.build
+++ b/src/gallium/drivers/nouveau/meson.build
@@ -131,6 +131,7 @@ files_libnouveau = files(
'codegen/nv50_ir_emit_nv50.cpp',
'codegen/nv50_ir_from_common.cpp',
'codegen/nv50_ir_from_common.h',
+ 'codegen/nv50_ir_from_nir.cpp',
'codegen/nv50_ir_from_tgsi.cpp',
'codegen/nv50_ir_graph.cpp',
'codegen/nv50_ir_graph.h',
@@ -210,9 +211,9 @@ files_libnouveau = files(
libnouveau = static_library(
'nouveau',
- [files_libnouveau],
+ [files_libnouveau, nir_opcodes_h],
include_directories : [
- inc_src, inc_include, inc_gallium, inc_gallium_aux,
+ inc_src, inc_include, inc_gallium, inc_gallium_aux, inc_common,
],
c_args : [c_vis_args],
cpp_args : [cpp_vis_args],
@@ -224,12 +225,12 @@ nouveau_compiler = executable(
'nouveau_compiler.c',
include_directories : [inc_src, inc_include, inc_gallium, inc_gallium_aux],
dependencies : [dep_libdrm, dep_libdrm_nouveau],
- link_with : [libnouveau, libgallium, libmesa_util],
+ link_with : [libnouveau, libgallium, libmesa_util, libnir],
build_by_default : with_tools.contains('nouveau'),
install : with_tools.contains('nouveau'),
)
driver_nouveau = declare_dependency(
compile_args : '-DGALLIUM_NOUVEAU',
- link_with : [libnouveauwinsys, libnouveau],
+ link_with : [libnouveauwinsys, libnouveau, libnir],
)
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.c b/src/gallium/drivers/nouveau/nouveau_screen.c
index e9fe04bddf7..98b44b7df0b 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.c
+++ b/src/gallium/drivers/nouveau/nouveau_screen.c
@@ -180,6 +180,8 @@ nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
if (nv_dbg)
nouveau_mesa_debug = atoi(nv_dbg);
+ screen->prefer_nir = debug_get_bool_option("NV50_PROG_USE_NIR", false);
+
/* These must be set before any failure is possible, as the cleanup
* paths assume they're responsible for deleting them.
*/
diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h
index b714f0a2aa9..4598d6a60e3 100644
--- a/src/gallium/drivers/nouveau/nouveau_screen.h
+++ b/src/gallium/drivers/nouveau/nouveau_screen.h
@@ -65,6 +65,8 @@ struct nouveau_screen {
struct disk_cache *disk_shader_cache;
+ bool prefer_nir;
+
#ifdef NOUVEAU_ENABLE_DRIVER_STATISTICS
union {
uint64_t v[29];
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_program.c b/src/gallium/drivers/nouveau/nv50/nv50_program.c
index b117790d6ec..940fb9ce25c 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_program.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_program.c
@@ -22,6 +22,8 @@
#include "pipe/p_defines.h"
+#include "compiler/nir/nir.h"
+
#include "nv50/nv50_program.h"
#include "nv50/nv50_context.h"
@@ -333,8 +335,19 @@ nv50_program_translate(struct nv50_program *prog, uint16_t chipset,
info->type = prog->type;
info->target = chipset;
- info->bin.sourceRep = PIPE_SHADER_IR_TGSI;
- info->bin.source = (void *)prog->pipe.tokens;
+
+ info->bin.sourceRep = prog->pipe.type;
+ switch (prog->pipe.type) {
+ case PIPE_SHADER_IR_TGSI:
+ info->bin.source = (void *)prog->pipe.tokens;
+ break;
+ case PIPE_SHADER_IR_NIR:
+ info->bin.source = (void *)nir_shader_clone(NULL, prog->pipe.ir.nir);
+ break;
+ default:
+ assert(!"unsupported IR!");
+ return false;
+ }
info->bin.smemSize = prog->cp.smem_size;
info->io.auxCBSlot = 15;
@@ -438,6 +451,8 @@ nv50_program_translate(struct nv50_program *prog, uint16_t chipset,
info->bin.codeSize);
out:
+ if (info->bin.sourceRep == PIPE_SHADER_IR_NIR)
+ ralloc_free((void *)info->bin.source);
FREE(info);
return !ret;
}
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
index 724457199fe..b9bfce21364 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
@@ -27,6 +27,7 @@
#include "util/u_format_s3tc.h"
#include "util/u_screen.h"
#include "pipe/p_screen.h"
+#include "compiler/nir/nir.h"
#include "nv50/nv50_context.h"
#include "nv50/nv50_screen.h"
@@ -346,6 +347,8 @@ nv50_screen_get_shader_param(struct pipe_screen *pscreen,
enum pipe_shader_type shader,
enum pipe_shader_cap param)
{
+ const struct nouveau_screen *screen = nouveau_screen(pscreen);
+
switch (shader) {
case PIPE_SHADER_VERTEX:
case PIPE_SHADER_GEOMETRY:
@@ -399,7 +402,7 @@ nv50_screen_get_shader_param(struct pipe_screen *pscreen,
case PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS:
return MIN2(16, PIPE_MAX_SAMPLERS);
case PIPE_SHADER_CAP_PREFERRED_IR:
- return PIPE_SHADER_IR_TGSI;
+ return screen->prefer_nir ? PIPE_SHADER_IR_NIR : PIPE_SHADER_IR_TGSI;
case PIPE_SHADER_CAP_MAX_UNROLL_ITERATIONS_HINT:
return 32;
case PIPE_SHADER_CAP_TGSI_DROUND_SUPPORTED:
@@ -873,6 +876,44 @@ int nv50_tls_realloc(struct nv50_screen *screen, unsigned tls_space)
return 1;
}
+static const nir_shader_compiler_options nir_options = {
+ .fuse_ffma = false, /* nir doesn't track mad vs fma */
+ .lower_flrp32 = true,
+ .lower_flrp64 = true,
+ .lower_fpow = false,
+ .lower_fmod64 = true,
+ .lower_uadd_carry = true,
+ .lower_usub_borrow = true,
+ .lower_ffract = true,
+ .lower_pack_half_2x16 = true,
+ .lower_pack_unorm_2x16 = true,
+ .lower_pack_snorm_2x16 = true,
+ .lower_pack_unorm_4x8 = true,
+ .lower_pack_snorm_4x8 = true,
+ .lower_unpack_half_2x16 = true,
+ .lower_unpack_unorm_2x16 = true,
+ .lower_unpack_snorm_2x16 = true,
+ .lower_unpack_unorm_4x8 = true,
+ .lower_unpack_snorm_4x8 = true,
+ .lower_extract_byte = true,
+ .lower_extract_word = true,
+ .lower_all_io_to_temps = false,
+ .native_integers = true,
+ .lower_cs_local_index_from_id = true,
+ .use_interpolated_input_intrinsics = true,
+ .max_unroll_iterations = 32,
+};
+
+static const void *
+nv50_screen_get_compiler_options(struct pipe_screen *pscreen,
+ enum pipe_shader_ir ir,
+ enum pipe_shader_type shader)
+{
+ if (ir == PIPE_SHADER_IR_NIR)
+ return &nir_options;
+ return NULL;
+}
+
struct nouveau_screen *
nv50_screen_create(struct nouveau_device *dev)
{
@@ -918,6 +959,9 @@ nv50_screen_create(struct nouveau_device *dev)
pscreen->get_driver_query_info = nv50_screen_get_driver_query_info;
pscreen->get_driver_query_group_info = nv50_screen_get_driver_query_group_info;
+ /* nir stuff */
+ pscreen->get_compiler_options = nv50_screen_get_compiler_options;
+
nv50_screen_init_resource_functions(pscreen);
if (screen->base.device->chipset < 0x84 ||
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_state.c b/src/gallium/drivers/nouveau/nv50/nv50_state.c
index fd4b8b64455..55167a27c09 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_state.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_state.c
@@ -28,6 +28,7 @@
#include "util/format_srgb.h"
#include "tgsi/tgsi_parse.h"
+#include "compiler/nir/nir.h"
#include "nv50/nv50_stateobj.h"
#include "nv50/nv50_context.h"
@@ -756,7 +757,19 @@ nv50_sp_state_create(struct pipe_context *pipe,
return NULL;
prog->type = type;
- prog->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+ prog->pipe.type = cso->type;
+
+ switch (cso->type) {
+ case PIPE_SHADER_IR_TGSI:
+ prog->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+ break;
+ case PIPE_SHADER_IR_NIR:
+ prog->pipe.ir.nir = cso->ir.nir;
+ break;
+ default:
+ assert(!"unsupported IR!");
+ return NULL;
+ }
if (cso->stream_output.num_outputs)
prog->pipe.stream_output = cso->stream_output;
@@ -775,7 +788,10 @@ nv50_sp_state_delete(struct pipe_context *pipe, void *hwcso)
nv50_program_destroy(nv50_context(pipe), prog);
- FREE((void *)prog->pipe.tokens);
+ if (prog->pipe.type == PIPE_SHADER_IR_TGSI)
+ FREE((void *)prog->pipe.tokens);
+ else if (prog->pipe.type == PIPE_SHADER_IR_NIR)
+ ralloc_free(prog->pipe.ir.nir);
FREE(prog);
}
@@ -837,13 +853,24 @@ nv50_cp_state_create(struct pipe_context *pipe,
if (!prog)
return NULL;
prog->type = PIPE_SHADER_COMPUTE;
+ prog->pipe.type = cso->ir_type;
+
+ switch(cso->ir_type) {
+ case PIPE_SHADER_IR_TGSI:
+ prog->pipe.tokens = tgsi_dup_tokens((const struct tgsi_token *)cso->prog);
+ break;
+ case PIPE_SHADER_IR_NIR:
+ prog->pipe.ir.nir = (nir_shader *)cso->prog;
+ break;
+ default:
+ assert(!"unsupported IR!");
+ return NULL;
+ }
prog->cp.smem_size = cso->req_local_mem;
prog->cp.lmem_size = cso->req_private_mem;
prog->parm_size = cso->req_input_mem;
- prog->pipe.tokens = tgsi_dup_tokens((const struct tgsi_token *)cso->prog);
-
return (void *)prog;
}
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c
index 008b660b8c0..c81d8952c98 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_program.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_program.c
@@ -22,6 +22,7 @@
#include "pipe/p_defines.h"
+#include "compiler/nir/nir.h"
#include "tgsi/tgsi_ureg.h"
#include "nvc0/nvc0_context.h"
@@ -582,8 +583,19 @@ nvc0_program_translate(struct nvc0_program *prog, uint16_t chipset,
info->type = prog->type;
info->target = chipset;
- info->bin.sourceRep = PIPE_SHADER_IR_TGSI;
- info->bin.source = (void *)prog->pipe.tokens;
+
+ info->bin.sourceRep = prog->pipe.type;
+ switch (prog->pipe.type) {
+ case PIPE_SHADER_IR_TGSI:
+ info->bin.source = (void *)prog->pipe.tokens;
+ break;
+ case PIPE_SHADER_IR_NIR:
+ info->bin.source = (void *)nir_shader_clone(NULL, prog->pipe.ir.nir);
+ break;
+ default:
+ assert(!"unsupported IR!");
+ return false;
+ }
#ifdef DEBUG
info->target = debug_get_num_option("NV50_PROG_CHIPSET", chipset);
@@ -711,6 +723,8 @@ nvc0_program_translate(struct nvc0_program *prog, uint16_t chipset,
#endif
out:
+ if (info->bin.sourceRep == PIPE_SHADER_IR_NIR)
+ ralloc_free((void *)info->bin.source);
FREE(info);
return !ret;
}
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
index d08d15cb9db..9d10e169d80 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
@@ -27,6 +27,7 @@
#include "util/u_format_s3tc.h"
#include "util/u_screen.h"
#include "pipe/p_screen.h"
+#include "compiler/nir/nir.h"
#include "nouveau_vp3_video.h"
@@ -106,7 +107,8 @@ static int
nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
{
const uint16_t class_3d = nouveau_screen(pscreen)->class_3d;
- struct nouveau_device *dev = nouveau_screen(pscreen)->device;
+ const struct nouveau_screen *screen = nouveau_screen(pscreen);
+ struct nouveau_device *dev = screen->device;
switch (param) {
/* non-boolean caps */
@@ -233,7 +235,6 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_USER_VERTEX_BUFFERS:
case PIPE_CAP_TEXTURE_QUERY_LOD:
case PIPE_CAP_SAMPLE_SHADING:
- case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
case PIPE_CAP_TEXTURE_GATHER_SM5:
case PIPE_CAP_TGSI_FS_FINE_DERIVATIVE:
case PIPE_CAP_CONDITIONAL_RENDER_INVERTED:
@@ -281,8 +282,9 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
return class_3d >= NVE4_3D_CLASS; /* needs testing on fermi */
case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
case PIPE_CAP_TGSI_BALLOT:
- case PIPE_CAP_BINDLESS_TEXTURE:
return class_3d >= NVE4_3D_CLASS;
+ case PIPE_CAP_BINDLESS_TEXTURE:
+ return class_3d >= NVE4_3D_CLASS && !screen->prefer_nir;
case PIPE_CAP_TGSI_ATOMFADD:
return class_3d < GM107_3D_CLASS; /* needs additional lowering */
case PIPE_CAP_POLYGON_MODE_FILL_RECTANGLE:
@@ -297,6 +299,13 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_CONSERVATIVE_RASTER_PRE_SNAP_TRIANGLES:
return class_3d >= GP100_3D_CLASS;
+ case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
+ /* TODO: nir doesn't support tg4 with multiple offsets */
+ return screen->prefer_nir ? 0 : 1;
+ /* caps has to be turned on with nir */
+ case PIPE_CAP_INT64_DIVMOD:
+ return screen->prefer_nir ? 1 : 0;
+
/* unsupported caps */
case PIPE_CAP_DEPTH_CLIP_DISABLE_SEPARATE:
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
@@ -323,7 +332,6 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_TGSI_CAN_READ_OUTPUTS:
case PIPE_CAP_NATIVE_FENCE_FD:
case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY:
- case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_SPARSE_BUFFER_PAGE_SIZE:
case PIPE_CAP_NIR_SAMPLERS_AS_DEREF:
case PIPE_CAP_MEMOBJ:
@@ -375,7 +383,8 @@ nvc0_screen_get_shader_param(struct pipe_screen *pscreen,
enum pipe_shader_type shader,
enum pipe_shader_cap param)
{
- const uint16_t class_3d = nouveau_screen(pscreen)->class_3d;
+ const struct nouveau_screen *screen = nouveau_screen(pscreen);
+ const uint16_t class_3d = screen->class_3d;
switch (shader) {
case PIPE_SHADER_VERTEX:
@@ -391,9 +400,10 @@ nvc0_screen_get_shader_param(struct pipe_screen *pscreen,
switch (param) {
case PIPE_SHADER_CAP_PREFERRED_IR:
- return PIPE_SHADER_IR_TGSI;
+ return screen->prefer_nir ? PIPE_SHADER_IR_NIR : PIPE_SHADER_IR_TGSI;
case PIPE_SHADER_CAP_SUPPORTED_IRS:
- return 1 << PIPE_SHADER_IR_TGSI;
+ return 1 << PIPE_SHADER_IR_TGSI |
+ 1 << PIPE_SHADER_IR_NIR;
case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
@@ -886,6 +896,79 @@ nvc0_screen_bind_cb_3d(struct nvc0_screen *screen, bool *can_serialize,
IMMED_NVC0(push, NVC0_3D(CB_BIND(stage)), (index << 4) | (size >= 0));
}
+static const nir_shader_compiler_options nir_options = {
+ .lower_fdiv = false,
+ .lower_ffma = false,
+ .fuse_ffma = false, /* nir doesn't track mad vs fma */
+ .lower_flrp32 = true,
+ .lower_flrp64 = true,
+ .lower_fpow = false,
+ .lower_fsat = false,
+ .lower_fsqrt = false, // TODO: only before gm200
+ .lower_fmod32 = true,
+ .lower_fmod64 = true,
+ .lower_bitfield_extract = false,
+ .lower_bitfield_extract_to_shifts = false,
+ .lower_bitfield_insert = false,
+ .lower_bitfield_insert_to_shifts = false,
+ .lower_bitfield_reverse = false,
+ .lower_bit_count = false,
+ .lower_bfm = false,
+ .lower_ifind_msb = false,
+ .lower_find_lsb = false,
+ .lower_uadd_carry = true, // TODO
+ .lower_usub_borrow = true, // TODO
+ .lower_mul_high = false,
+ .lower_negate = false,
+ .lower_sub = false, // TODO
+ .lower_scmp = true, // TODO: not implemented yet
+ .lower_idiv = true,
+ .lower_isign = false, // TODO
+ .fdot_replicates = false, // TODO
+ .lower_ffloor = false, // TODO
+ .lower_ffract = true,
+ .lower_fceil = false, // TODO
+ .lower_ldexp = true,
+ .lower_pack_half_2x16 = true,
+ .lower_pack_unorm_2x16 = true,
+ .lower_pack_snorm_2x16 = true,
+ .lower_pack_unorm_4x8 = true,
+ .lower_pack_snorm_4x8 = true,
+ .lower_unpack_half_2x16 = true,
+ .lower_unpack_unorm_2x16 = true,
+ .lower_unpack_snorm_2x16 = true,
+ .lower_unpack_unorm_4x8 = true,
+ .lower_unpack_snorm_4x8 = true,
+ .lower_extract_byte = true,
+ .lower_extract_word = true,
+ .lower_all_io_to_temps = false,
+ .native_integers = true,
+ .vertex_id_zero_based = false,
+ .lower_base_vertex = false,
+ .lower_helper_invocation = false,
+ .lower_cs_local_index_from_id = true,
+ .lower_cs_local_id_from_index = false,
+ .lower_device_index_to_zero = false, // TODO
+ .lower_wpos_pntc = false, // TODO
+ .lower_hadd = true, // TODO
+ .lower_add_sat = true, // TODO
+ .use_interpolated_input_intrinsics = true,
+ .lower_mul_2x32_64 = true, // TODO
+ .max_unroll_iterations = 32,
+ .lower_int64_options = nir_lower_divmod64, // TODO
+ .lower_doubles_options = 0, // TODO
+};
+
+static const void *
+nvc0_screen_get_compiler_options(struct pipe_screen *pscreen,
+ enum pipe_shader_ir ir,
+ enum pipe_shader_type shader)
+{
+ if (ir == PIPE_SHADER_IR_NIR)
+ return &nir_options;
+ return NULL;
+}
+
#define FAIL_SCREEN_INIT(str, err) \
do { \
NOUVEAU_ERR(str, err); \
@@ -960,6 +1043,8 @@ nvc0_screen_create(struct nouveau_device *dev)
pscreen->get_sample_pixel_grid = nvc0_screen_get_sample_pixel_grid;
pscreen->get_driver_query_info = nvc0_screen_get_driver_query_info;
pscreen->get_driver_query_group_info = nvc0_screen_get_driver_query_group_info;
+ /* nir stuff */
+ pscreen->get_compiler_options = nvc0_screen_get_compiler_options;
nvc0_screen_init_resource_functions(pscreen);
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
index 53ad47c6ed4..ed4cb869ba6 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_state.c
@@ -27,6 +27,7 @@
#include "util/u_transfer.h"
#include "tgsi/tgsi_parse.h"
+#include "compiler/nir/nir.h"
#include "nvc0/nvc0_stateobj.h"
#include "nvc0/nvc0_context.h"
@@ -595,9 +596,19 @@ nvc0_sp_state_create(struct pipe_context *pipe,
return NULL;
prog->type = type;
+ prog->pipe.type = cso->type;
- if (cso->tokens)
+ switch(cso->type) {
+ case PIPE_SHADER_IR_TGSI:
prog->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+ break;
+ case PIPE_SHADER_IR_NIR:
+ prog->pipe.ir.nir = cso->ir.nir;
+ break;
+ default:
+ assert(!"unsupported IR!");
+ return NULL;
+ }
if (cso->stream_output.num_outputs)
prog->pipe.stream_output = cso->stream_output;
@@ -616,7 +627,10 @@ nvc0_sp_state_delete(struct pipe_context *pipe, void *hwcso)
nvc0_program_destroy(nvc0_context(pipe), prog);
- FREE((void *)prog->pipe.tokens);
+ if (prog->pipe.type == PIPE_SHADER_IR_TGSI)
+ FREE((void *)prog->pipe.tokens);
+ else if (prog->pipe.type == PIPE_SHADER_IR_NIR)
+ ralloc_free(prog->pipe.ir.nir);
FREE(prog);
}
@@ -710,12 +724,23 @@ nvc0_cp_state_create(struct pipe_context *pipe,
if (!prog)
return NULL;
prog->type = PIPE_SHADER_COMPUTE;
+ prog->pipe.type = cso->ir_type;
prog->cp.smem_size = cso->req_local_mem;
prog->cp.lmem_size = cso->req_private_mem;
prog->parm_size = cso->req_input_mem;
- prog->pipe.tokens = tgsi_dup_tokens((const struct tgsi_token *)cso->prog);
+ switch(cso->ir_type) {
+ case PIPE_SHADER_IR_TGSI:
+ prog->pipe.tokens = tgsi_dup_tokens((const struct tgsi_token *)cso->prog);
+ break;
+ case PIPE_SHADER_IR_NIR:
+ prog->pipe.ir.nir = (nir_shader *)cso->prog;
+ break;
+ default:
+ assert(!"unsupported IR!");
+ return NULL;
+ }
prog->translated = nvc0_program_translate(
prog, nvc0_context(pipe)->screen->base.device->chipset,