From 22a332f5acee1c8897fec905407097190c7235a2 Mon Sep 17 00:00:00 2001 From: Emma Anholt Date: Thu, 9 Sep 2021 13:13:41 -0700 Subject: [PATCH] virgl: Add support for NIR shaders when VIRGL_DEBUG=nir. This will let me incrementally fix nir-to-tgsi against virgl without having to carry around the whole "remove TGSI from mesa/st" MR. Reviewed-by: Gert Wollny Part-of: --- src/gallium/drivers/virgl/meson.build | 2 +- src/gallium/drivers/virgl/virgl_context.c | 30 +++++++++++++++++++++++++++--- src/gallium/drivers/virgl/virgl_screen.c | 22 +++++++++++++++++++--- src/gallium/drivers/virgl/virgl_screen.h | 1 + 4 files changed, 48 insertions(+), 7 deletions(-) diff --git a/src/gallium/drivers/virgl/meson.build b/src/gallium/drivers/virgl/meson.build index 6526b3b..b3adb12 100644 --- a/src/gallium/drivers/virgl/meson.build +++ b/src/gallium/drivers/virgl/meson.build @@ -37,7 +37,7 @@ libvirgl = static_library( [ files_libvirgl ], gnu_symbol_visibility : 'hidden', include_directories : [inc_include, inc_src, inc_mapi, inc_mesa, inc_gallium, inc_gallium_aux, inc_virtio], - dependencies : [dep_libdrm, idep_mesautil, idep_xmlconfig], + dependencies : [dep_libdrm, idep_mesautil, idep_xmlconfig, idep_nir], ) driver_virgl = declare_dependency( diff --git a/src/gallium/drivers/virgl/virgl_context.c b/src/gallium/drivers/virgl/virgl_context.c index b90674c..ee16ea9 100644 --- a/src/gallium/drivers/virgl/virgl_context.c +++ b/src/gallium/drivers/virgl/virgl_context.c @@ -24,10 +24,12 @@ #include #include "pipe/p_shader_tokens.h" +#include "compiler/nir/nir.h" #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" #include "pipe/p_state.h" +#include "nir/nir_to_tgsi.h" #include "util/u_draw.h" #include "util/u_inlines.h" #include "util/u_memory.h" @@ -680,10 +682,19 @@ static void *virgl_shader_encoder(struct pipe_context *ctx, { struct virgl_context *vctx = virgl_context(ctx); uint32_t handle; + const struct tgsi_token *tokens; + const struct tgsi_token *ntt_tokens = NULL; struct tgsi_token *new_tokens; int ret; - new_tokens = virgl_tgsi_transform((struct virgl_screen *)vctx->base.screen, shader->tokens); + if (shader->type == PIPE_SHADER_IR_NIR) { + nir_shader *s = nir_shader_clone(NULL, shader->ir.nir); + ntt_tokens = tokens = nir_to_tgsi(s, vctx->base.screen); /* takes ownership */ + } else { + tokens = shader->tokens; + } + + new_tokens = virgl_tgsi_transform((struct virgl_screen *)vctx->base.screen, tokens); if (!new_tokens) return NULL; @@ -693,9 +704,11 @@ static void *virgl_shader_encoder(struct pipe_context *ctx, &shader->stream_output, 0, new_tokens); if (ret) { + FREE((void *)ntt_tokens); return NULL; } + FREE((void *)ntt_tokens); FREE(new_tokens); return (void *)(unsigned long)handle; @@ -1353,19 +1366,30 @@ static void *virgl_create_compute_state(struct pipe_context *ctx, { struct virgl_context *vctx = virgl_context(ctx); uint32_t handle; - const struct tgsi_token *new_tokens = state->prog; + const struct tgsi_token *ntt_tokens = NULL; + const struct tgsi_token *tokens; struct pipe_stream_output_info so_info = {}; int ret; + if (state->ir_type == PIPE_SHADER_IR_NIR) { + nir_shader *s = nir_shader_clone(NULL, state->prog); + ntt_tokens = tokens = nir_to_tgsi(s, vctx->base.screen); /* takes ownership */ + } else { + tokens = state->prog; + } + handle = virgl_object_assign_handle(); ret = virgl_encode_shader_state(vctx, handle, PIPE_SHADER_COMPUTE, &so_info, state->req_local_mem, - new_tokens); + tokens); if (ret) { + FREE((void *)ntt_tokens); return NULL; } + FREE((void *)ntt_tokens); + return (void *)(unsigned long)handle; } diff --git a/src/gallium/drivers/virgl/virgl_screen.c b/src/gallium/drivers/virgl/virgl_screen.c index 45b2a14..a832f98 100644 --- a/src/gallium/drivers/virgl/virgl_screen.c +++ b/src/gallium/drivers/virgl/virgl_screen.c @@ -31,6 +31,7 @@ #include "util/xmlconfig.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" +#include "nir/nir_to_tgsi.h" #include "tgsi/tgsi_exec.h" @@ -45,6 +46,7 @@ int virgl_debug = 0; static const struct debug_named_value virgl_debug_options[] = { { "verbose", VIRGL_DEBUG_VERBOSE, NULL }, { "tgsi", VIRGL_DEBUG_TGSI, NULL }, + { "nir", VIRGL_DEBUG_NIR, NULL }, { "noemubgra", VIRGL_DEBUG_NO_EMULATE_BGRA, "Disable tweak to emulate BGRA as RGBA on GLES hosts"}, { "nobgraswz", VIRGL_DEBUG_NO_BGRA_DEST_SWIZZLE,"Disable tweak to swizzle emulated BGRA on GLES hosts" }, { "sync", VIRGL_DEBUG_SYNC, "Sync after every flush" }, @@ -190,6 +192,7 @@ virgl_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY: case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY: case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: + case PIPE_CAP_NIR_IMAGES_AS_DEREF: return 0; case PIPE_CAP_QUERY_TIMESTAMP: return 1; @@ -425,8 +428,10 @@ virgl_get_shader_param(struct pipe_screen *screen, return vscreen->caps.caps.v2.max_shader_image_frag_compute; else return vscreen->caps.caps.v2.max_shader_image_other_stages; + case PIPE_SHADER_CAP_PREFERRED_IR: + return (virgl_debug & VIRGL_DEBUG_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) | ((virgl_debug & VIRGL_DEBUG_NIR) ? (1 << PIPE_SHADER_IR_NIR) : 0); case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTERS: return vscreen->caps.caps.v2.max_atomic_counters[shader]; case PIPE_SHADER_CAP_MAX_HW_ATOMIC_COUNTER_BUFFERS: @@ -906,13 +911,23 @@ static void virgl_disk_cache_create(struct virgl_screen *screen) { const struct build_id_note *note = build_id_find_nhdr_for_addr(virgl_disk_cache_create); - assert(note && build_id_length(note) == 20); /* sha1 */ + unsigned build_id_len = build_id_length(note); + assert(note && build_id_len == 20); /* sha1 */ const uint8_t *id_sha1 = build_id_data(note); assert(id_sha1); + struct mesa_sha1 sha1_ctx; + _mesa_sha1_init(&sha1_ctx); + _mesa_sha1_update(&sha1_ctx, id_sha1, build_id_len); + + uint32_t shader_debug_flags = virgl_debug & VIRGL_DEBUG_NIR; + _mesa_sha1_update(&sha1_ctx, &shader_debug_flags, sizeof(shader_debug_flags)); + + uint8_t sha1[20]; + _mesa_sha1_final(&sha1_ctx, sha1); char timestamp[41]; - _mesa_sha1_format(timestamp, id_sha1); + _mesa_sha1_format(timestamp, sha1); screen->disk_cache = disk_cache_create("virgl", timestamp, 0); } @@ -969,6 +984,7 @@ virgl_create_screen(struct virgl_winsys *vws, const struct pipe_screen_config *c screen->base.get_shader_param = virgl_get_shader_param; screen->base.get_compute_param = virgl_get_compute_param; screen->base.get_paramf = virgl_get_paramf; + screen->base.get_compiler_options = nir_to_tgsi_get_compiler_options; screen->base.is_format_supported = virgl_is_format_supported; screen->base.destroy = virgl_destroy_screen; screen->base.context_create = virgl_context_create; diff --git a/src/gallium/drivers/virgl/virgl_screen.h b/src/gallium/drivers/virgl/virgl_screen.h index a604c6b..c44509f 100644 --- a/src/gallium/drivers/virgl/virgl_screen.h +++ b/src/gallium/drivers/virgl/virgl_screen.h @@ -36,6 +36,7 @@ enum virgl_debug_flags { VIRGL_DEBUG_SYNC = 1 << 4, VIRGL_DEBUG_XFER = 1 << 5, VIRGL_DEBUG_NO_COHERENT = 1 << 6, + VIRGL_DEBUG_NIR = 1 << 7, }; extern int virgl_debug; -- 2.7.4