On Thu, Jul 5, 2018 at 2:03 AM, Dave Airlie <airl...@gmail.com> wrote: > From: Dave Airlie <airl...@redhat.com> > > This uses the common compiler passes abstraction to help radv > avoid fixed cost compiler overheads. This uses a linked list per > thread stored in thread local storage, with an entry in the list > for each target machine. > > This should remove all the fixed overheads setup costs of creating > the pass manager each time. > > This takes a demo app time to compile the radv meta shaders on nocache > and exit from 1.7s to 1s. It also has been reported to take the startup > time of uncached shaders on RoTR from 12m24s to 11m35s (Alex) > > v2: fix llvm6 build, inline emit function, handle multiple targets > in one thread > v3: rebase and port onto new structure > v4: rename some vars (Bas) > v5: drag all code into radv for now, we can refactor it out later > for radeonsi if we make it shareable > v6: use a bit more C++ in the wrapper > v7: logic bugs fixed so it actually runs again. > v8: rebase on top of radeonsi changes. > --- > src/amd/vulkan/Makefile.sources | 2 + > src/amd/vulkan/meson.build | 2 + > src/amd/vulkan/radv_debug.h | 1 + > src/amd/vulkan/radv_device.c | 1 + > src/amd/vulkan/radv_llvm_helper.cpp | 148 ++++++++++++++++++++++++++++ > src/amd/vulkan/radv_nir_to_llvm.c | 27 +---- > src/amd/vulkan/radv_shader.c | 10 +- > src/amd/vulkan/radv_shader_helper.h | 44 +++++++++ > 8 files changed, 207 insertions(+), 28 deletions(-) > create mode 100644 src/amd/vulkan/radv_llvm_helper.cpp > create mode 100644 src/amd/vulkan/radv_shader_helper.h > > diff --git a/src/amd/vulkan/Makefile.sources b/src/amd/vulkan/Makefile.sources > index 70d56e88cb3..152fdd7cb71 100644 > --- a/src/amd/vulkan/Makefile.sources > +++ b/src/amd/vulkan/Makefile.sources > @@ -54,6 +54,7 @@ VULKAN_FILES := \ > radv_meta_resolve_cs.c \ > radv_meta_resolve_fs.c \ > radv_nir_to_llvm.c \ > + radv_llvm_helper.cpp \ > radv_pass.c \ > radv_pipeline.c \ > radv_pipeline_cache.c \ > @@ -62,6 +63,7 @@ VULKAN_FILES := \ > radv_shader.c \ > radv_shader_info.c \ > radv_shader.h \ > + radv_shader_helper.h \ > radv_query.c \ > radv_util.c \ > radv_util.h \ > diff --git a/src/amd/vulkan/meson.build b/src/amd/vulkan/meson.build > index 22857926fa1..9f2842182e7 100644 > --- a/src/amd/vulkan/meson.build > +++ b/src/amd/vulkan/meson.build > @@ -67,6 +67,7 @@ libradv_files = files( > 'radv_descriptor_set.h', > 'radv_formats.c', > 'radv_image.c', > + 'radv_llvm_helper.cpp', > 'radv_meta.c', > 'radv_meta.h', > 'radv_meta_blit.c', > @@ -88,6 +89,7 @@ libradv_files = files( > 'radv_radeon_winsys.h', > 'radv_shader.c', > 'radv_shader.h', > + 'radv_shader_helper.h', > 'radv_shader_info.c', > 'radv_query.c', > 'radv_util.c', > diff --git a/src/amd/vulkan/radv_debug.h b/src/amd/vulkan/radv_debug.h > index f1b0dc26a63..9fe4c3b7404 100644 > --- a/src/amd/vulkan/radv_debug.h > +++ b/src/amd/vulkan/radv_debug.h > @@ -49,6 +49,7 @@ enum { > RADV_DEBUG_ERRORS = 0x80000, > RADV_DEBUG_STARTUP = 0x100000, > RADV_DEBUG_CHECKIR = 0x200000, > + RADV_DEBUG_NOTHREADLLVM = 0x400000, > }; > > enum { > diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c > index ad3465f594e..73c48cef1f0 100644 > --- a/src/amd/vulkan/radv_device.c > +++ b/src/amd/vulkan/radv_device.c > @@ -436,6 +436,7 @@ static const struct debug_control radv_debug_options[] = { > {"errors", RADV_DEBUG_ERRORS}, > {"startup", RADV_DEBUG_STARTUP}, > {"checkir", RADV_DEBUG_CHECKIR}, > + {"nothreadllvm", RADV_DEBUG_NOTHREADLLVM}, > {NULL, 0} > }; > > diff --git a/src/amd/vulkan/radv_llvm_helper.cpp > b/src/amd/vulkan/radv_llvm_helper.cpp > new file mode 100644 > index 00000000000..dad881f6b1a > --- /dev/null > +++ b/src/amd/vulkan/radv_llvm_helper.cpp > @@ -0,0 +1,148 @@ > +/* > + * Copyright © 2018 Red Hat. > + * > + * 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 "ac_llvm_util.h" > +#include "ac_llvm_build.h" > +#include "radv_shader_helper.h" > +#include <llvm-c/Core.h> > +#include <llvm-c/Support.h> > +#include <llvm/Target/TargetMachine.h> > +#include <llvm/Analysis/TargetLibraryInfo.h> > +#include <llvm/IR/LegacyPassManager.h> > +#if HAVE_LLVM >= 0x0700 > +#include <llvm-c/Transforms/Utils.h> > +#endif > +#if HAVE_LLVM < 0x0700 > +#include "llvm/Support/raw_ostream.h" > +#endif > + > +class radv_llvm_per_thread_info { > +public: > + radv_llvm_per_thread_info(enum radeon_family arg_family, > + enum ac_target_machine_options arg_tm_options) > + : family(arg_family), tm_options(arg_tm_options) {} > + > + ~radv_llvm_per_thread_info() > + { > + ac_destroy_llvm_passes(passes); > + ac_destroy_llvm_compiler(&llvm_info); > + } > + > + bool init(void) > + { > + if (!ac_init_llvm_compiler(&llvm_info, > + true, > + family, > + tm_options)) > + return false; > + > + passes = ac_create_llvm_passes(llvm_info.tm); > + if (!passes) > + return false; > + > + return true; > + } > + > + bool compile_to_memory_buffer(LLVMModuleRef module, > + struct ac_shader_binary *binary) > + { > + return ac_compile_module_to_binary(passes, module, binary); > + } > + > + bool is_same(enum radeon_family arg_family, > + enum ac_target_machine_options arg_tm_options) { > + if (arg_family == family && > + arg_tm_options == tm_options) > + return true; > + return false; > + } > + struct ac_llvm_compiler llvm_info; > +private: > + enum radeon_family family; > + enum ac_target_machine_options tm_options; > + struct ac_compiler_passes *passes; > +}; > + > +/* we have to store a linked list per thread due to the possiblity of > multiple gpus being required */ > +static thread_local std::list<radv_llvm_per_thread_info> > radv_llvm_per_thread_list; > + > +bool radv_compile_to_binary(struct ac_llvm_compiler *info, > + LLVMModuleRef module, > + struct ac_shader_binary *binary) > +{ > + radv_llvm_per_thread_info *thread_info = nullptr; > + > + for (auto &I : radv_llvm_per_thread_list) { > + if (I.llvm_info.tm == info->tm) { > + thread_info = &I; > + break; > + } > + } > + > + if (!thread_info) { > + struct ac_compiler_passes *passes = > ac_create_llvm_passes(info->tm); > + bool ret = ac_compile_module_to_binary(passes, module, > binary); > + ac_destroy_llvm_passes(passes); > + return ret; > + } > + > + return thread_info->compile_to_memory_buffer(module, binary); > +} > + > +bool radv_init_llvm_compiler(struct ac_llvm_compiler *info, > + bool okay_to_leak_target_library_info, > + bool thread_compiler, > + enum radeon_family family, > + enum ac_target_machine_options tm_options) > +{ > + if (thread_compiler) { > + for (auto &I : radv_llvm_per_thread_list) { > + if (I.is_same(family, tm_options)) { > + *info = I.llvm_info; > + return true; > + } > + } > + > + radv_llvm_per_thread_list.emplace_back(family, tm_options); > + radv_llvm_per_thread_info &tinfo = > radv_llvm_per_thread_list.back(); > + > + if (!tinfo.init()) > + return false;
Clean up the newly inserted list entry? > + > + *info = tinfo.llvm_info; > + return true; > + } > + > + if (!ac_init_llvm_compiler(info, > + okay_to_leak_target_library_info, > + family, > + tm_options)) > + return false; > + return true; > +} > + > +void radv_destroy_llvm_compiler(struct ac_llvm_compiler *info, > + bool thread_compiler) > +{ > + if (!thread_compiler) > + ac_destroy_llvm_compiler(info); > +} > diff --git a/src/amd/vulkan/radv_nir_to_llvm.c > b/src/amd/vulkan/radv_nir_to_llvm.c > index 15c10493022..6bebab6e6ba 100644 > --- a/src/amd/vulkan/radv_nir_to_llvm.c > +++ b/src/amd/vulkan/radv_nir_to_llvm.c > @@ -27,6 +27,7 @@ > > #include "radv_private.h" > #include "radv_shader.h" > +#include "radv_shader_helper.h" > #include "nir/nir.h" > > #include <llvm-c/Core.h> > @@ -3328,12 +3329,7 @@ static unsigned ac_llvm_compile(LLVMModuleRef M, > struct ac_llvm_compiler *ac_llvm) > { > unsigned retval = 0; > - char *err; > LLVMContextRef llvm_ctx; > - LLVMMemoryBufferRef out_buffer; > - unsigned buffer_size; > - const char *buffer_data; > - LLVMBool mem_err; > > /* Setup Diagnostic Handler*/ > llvm_ctx = LLVMGetModuleContext(M); > @@ -3342,27 +3338,8 @@ static unsigned ac_llvm_compile(LLVMModuleRef M, > &retval); > > /* Compile IR*/ > - mem_err = LLVMTargetMachineEmitToMemoryBuffer(ac_llvm->tm, M, > LLVMObjectFile, > - &err, &out_buffer); > - > - /* Process Errors/Warnings */ > - if (mem_err) { > - fprintf(stderr, "%s: %s", __FUNCTION__, err); > - free(err); > + if (!radv_compile_to_binary(ac_llvm, M, binary)) > retval = 1; > - goto out; > - } > - > - /* Extract Shader Code*/ > - buffer_size = LLVMGetBufferSize(out_buffer); > - buffer_data = LLVMGetBufferStart(out_buffer); > - > - ac_elf_read(buffer_data, buffer_size, binary); > - > - /* Clean up */ > - LLVMDisposeMemoryBuffer(out_buffer); > - > -out: > return retval; > } > > diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c > index 5cca761d89e..13990059985 100644 > --- a/src/amd/vulkan/radv_shader.c > +++ b/src/amd/vulkan/radv_shader.c > @@ -30,6 +30,7 @@ > #include "radv_debug.h" > #include "radv_private.h" > #include "radv_shader.h" > +#include "radv_shader_helper.h" > #include "nir/nir.h" > #include "nir/nir_builder.h" > #include "spirv/nir_spirv.h" > @@ -542,7 +543,7 @@ shader_variant_create(struct radv_device *device, > struct radv_shader_variant *variant; > struct ac_shader_binary binary; > struct ac_llvm_compiler ac_llvm; > - > + bool thread_compiler; > variant = calloc(1, sizeof(struct radv_shader_variant)); > if (!variant) > return NULL; > @@ -564,8 +565,11 @@ shader_variant_create(struct radv_device *device, > if (options->check_ir) > tm_options |= AC_TM_CHECK_IR; > > + thread_compiler = !(device->instance->debug_flags & > RADV_DEBUG_NOTHREADLLVM); Was NOTHREADLLVM from an earlier patch? > radv_init_llvm_once(); > - ac_init_llvm_compiler(&ac_llvm, false, chip_family, tm_options); > + radv_init_llvm_compiler(&ac_llvm, false, > + thread_compiler, > + chip_family, tm_options); > if (gs_copy_shader) { > assert(shader_count == 1); > radv_compile_gs_copy_shader(&ac_llvm, *shaders, &binary, > @@ -577,7 +581,7 @@ shader_variant_create(struct radv_device *device, > options); > } > > - ac_destroy_llvm_compiler(&ac_llvm); > + radv_destroy_llvm_compiler(&ac_llvm, thread_compiler); > > radv_fill_shader_variant(device, variant, &binary, stage); > > diff --git a/src/amd/vulkan/radv_shader_helper.h > b/src/amd/vulkan/radv_shader_helper.h > new file mode 100644 > index 00000000000..3c81f5be54a > --- /dev/null > +++ b/src/amd/vulkan/radv_shader_helper.h > @@ -0,0 +1,44 @@ > +/* > + * Copyright © 2018 Red Hat. > + * > + * 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 RADV_SHADER_HELPER_H > +#define RADV_SHADER_HELPER_H > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +bool radv_init_llvm_compiler(struct ac_llvm_compiler *info, > + bool okay_to_leak_target_library_info, > + bool thread_compiler, > + enum radeon_family family, > + enum ac_target_machine_options tm_options); > +void radv_destroy_llvm_compiler(struct ac_llvm_compiler *info, > + bool thread_compiler); > + > +bool radv_compile_to_binary(struct ac_llvm_compiler *info, > + LLVMModuleRef module, > + struct ac_shader_binary *binary); > + > +#ifdef __cplusplus > +} > +#endif > +#endif > -- > 2.17.1 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev