From: Timothy Arceri <tarceri@localhost.localdomain> For now this just allows an app to query VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD which for now only returns shader-db information. This will allow us to use anv with vkpipeline-db.
We should add shader disassembly in the future so that RenderDoc can display it, but that will require a bunch of changes as currently all the helper functions just fprintf everything to stderr. --- src/intel/vulkan/anv_device.c | 19 +++- src/intel/vulkan/anv_extensions.py | 1 + src/intel/vulkan/anv_pipeline.c | 129 ++++++++++++++++++++++++-- src/intel/vulkan/anv_pipeline_cache.c | 1 + src/intel/vulkan/anv_private.h | 5 + 5 files changed, 147 insertions(+), 8 deletions(-) diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index b02e1a2749..f140c6e8e5 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -36,6 +36,7 @@ #include "util/debug.h" #include "util/build_id.h" #include "util/mesa-sha1.h" +#include "util/string_buffer.h" #include "vk_util.h" #include "common/gen_defines.h" @@ -43,7 +44,15 @@ static void compiler_debug_log(void *data, const char *fmt, ...) -{ } +{ + struct _mesa_string_buffer *buf = (struct _mesa_string_buffer *)data; + va_list args; + + va_start(args, fmt); + _mesa_string_buffer_vprintf(buf, fmt, args); + _mesa_string_buffer_printf(buf, "\n"); + va_end(args); +} static void compiler_perf_log(void *data, const char *fmt, ...) @@ -1456,6 +1465,8 @@ VkResult anv_CreateDevice( assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO); + bool store_shader_info = false; + struct anv_device_extension_table enabled_extensions = { }; for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { int idx; @@ -1471,6 +1482,11 @@ VkResult anv_CreateDevice( if (!physical_device->supported_extensions.extensions[idx]) return vk_error(VK_ERROR_EXTENSION_NOT_PRESENT); + if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], + VK_AMD_SHADER_INFO_EXTENSION_NAME) == 0) { + store_shader_info = true; + } + enabled_extensions.extensions[idx] = true; } @@ -1516,6 +1532,7 @@ VkResult anv_CreateDevice( device->chipset_id = physical_device->chipset_id; device->no_hw = physical_device->no_hw; device->lost = false; + device->store_shader_info = store_shader_info; if (pAllocator) device->alloc = *pAllocator; diff --git a/src/intel/vulkan/anv_extensions.py b/src/intel/vulkan/anv_extensions.py index 8160864685..bcff5e848b 100644 --- a/src/intel/vulkan/anv_extensions.py +++ b/src/intel/vulkan/anv_extensions.py @@ -68,6 +68,7 @@ MAX_API_VERSION = None # Computed later # the those extension strings, then tests dEQP-VK.api.info.instance.extensions # and dEQP-VK.api.info.device fail due to the duplicated strings. EXTENSIONS = [ + Extension('VK_AMD_shader_info', 1, True), Extension('VK_ANDROID_native_buffer', 5, 'ANDROID'), Extension('VK_KHR_16bit_storage', 1, 'device->info.gen >= 8'), Extension('VK_KHR_bind_memory2', 1, True), diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c index 240bde036d..8be349ed19 100644 --- a/src/intel/vulkan/anv_pipeline.c +++ b/src/intel/vulkan/anv_pipeline.c @@ -28,6 +28,7 @@ #include <fcntl.h> #include "util/mesa-sha1.h" +#include "util/string_buffer.h" #include "common/gen_l3_config.h" #include "anv_private.h" #include "compiler/brw_nir.h" @@ -81,6 +82,55 @@ void anv_DestroyShaderModule( vk_free2(&device->alloc, pAllocator, module); } +VkResult anv_GetShaderInfoAMD( + VkDevice _device, + VkPipeline _pipeline, + VkShaderStageFlagBits shaderStage, + VkShaderInfoTypeAMD infoType, + size_t* pInfoSize, + void* pInfo) +{ + ANV_FROM_HANDLE(anv_pipeline, pipeline, _pipeline); + + gl_shader_stage stage = vk_to_mesa_shader_stage(shaderStage); + struct anv_shader_bin *shader = pipeline->shaders[stage]; + VkResult result = VK_SUCCESS; + + /* Spec doesn't indicate what to do if the stage is invalid, so just + * return no info for this. + */ + if (!shader) + return vk_error(VK_ERROR_FEATURE_NOT_PRESENT); + + switch (infoType) { + case VK_SHADER_INFO_TYPE_DISASSEMBLY_AMD: { + /* Need to include the null terminator. */ + size_t length = strlen(shader->shader_info) + 1; + + if (!pInfo) { + *pInfoSize = length; + } else { + size_t size = *pInfoSize; + *pInfoSize = length; + + memcpy(pInfo, shader->shader_info, MIN2(size, length)); + + if (size < length) + result = VK_INCOMPLETE; + } + break; + } + default: + /* VK_SHADER_INFO_TYPE_BINARY_AMD and VK_SHADER_INFO_TYPE_STATISTICS_AMD + * are unimplemented. + */ + result = VK_ERROR_FEATURE_NOT_PRESENT; + break; + } + + return result; +} + #define SPIR_V_MAGIC_NUMBER 0x07230203 static const uint64_t stage_to_debug[] = { @@ -557,8 +607,12 @@ anv_pipeline_compile_vs(struct anv_pipeline *pipeline, nir->info.outputs_written, nir->info.separate_shader); + struct _mesa_string_buffer *shader_info = NULL; + if (pipeline->device->store_shader_info) + shader_info = _mesa_string_buffer_create(mem_ctx, 256); + const unsigned *shader_code = - brw_compile_vs(compiler, NULL, mem_ctx, &key, &prog_data, nir, + brw_compile_vs(compiler, shader_info, mem_ctx, &key, &prog_data, nir, -1, NULL); if (shader_code == NULL) { ralloc_free(mem_ctx); @@ -575,6 +629,13 @@ anv_pipeline_compile_vs(struct anv_pipeline *pipeline, return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); } + if (shader_info) { + bin->shader_info = + vk_alloc(&pipeline->device->alloc, shader_info->length + 1, 8, + VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); + memcpy(bin->shader_info, shader_info->buf, shader_info->length + 1); + } + ralloc_free(mem_ctx); } @@ -720,12 +781,19 @@ anv_pipeline_compile_tcs_tes(struct anv_pipeline *pipeline, tes_key.inputs_read = tcs_key.outputs_written; tes_key.patch_inputs_read = tcs_key.patch_outputs_written; + struct _mesa_string_buffer *shader_info_tes = NULL; + struct _mesa_string_buffer *shader_info_tcs = NULL; + if (pipeline->device->store_shader_info) { + shader_info_tes = _mesa_string_buffer_create(mem_ctx, 256); + shader_info_tcs = _mesa_string_buffer_create(mem_ctx, 256); + } + const int shader_time_index = -1; const unsigned *shader_code; shader_code = - brw_compile_tcs(compiler, NULL, mem_ctx, &tcs_key, &tcs_prog_data, - tcs_nir, shader_time_index, NULL); + brw_compile_tcs(compiler, shader_info_tcs, mem_ctx, &tcs_key, + &tcs_prog_data, tcs_nir, shader_time_index, NULL); if (shader_code == NULL) { ralloc_free(mem_ctx); return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); @@ -744,7 +812,7 @@ anv_pipeline_compile_tcs_tes(struct anv_pipeline *pipeline, } shader_code = - brw_compile_tes(compiler, NULL, mem_ctx, &tes_key, + brw_compile_tes(compiler, shader_info_tes, mem_ctx, &tes_key, &tcs_prog_data.base.vue_map, &tes_prog_data, tes_nir, NULL, shader_time_index, NULL); if (shader_code == NULL) { @@ -764,6 +832,20 @@ anv_pipeline_compile_tcs_tes(struct anv_pipeline *pipeline, return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); } + if (pipeline->device->store_shader_info) { + tcs_bin->shader_info = + vk_alloc(&pipeline->device->alloc, shader_info_tcs->length + 1, 8, + VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); + memcpy(tcs_bin->shader_info, shader_info_tcs->buf, + shader_info_tcs->length + 1); + + tes_bin->shader_info = + vk_alloc(&pipeline->device->alloc, shader_info_tes->length + 1, 8, + VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); + memcpy(tes_bin->shader_info, shader_info_tes->buf, + shader_info_tes->length + 1); + } + ralloc_free(mem_ctx); } @@ -826,8 +908,12 @@ anv_pipeline_compile_gs(struct anv_pipeline *pipeline, nir->info.outputs_written, nir->info.separate_shader); + struct _mesa_string_buffer *shader_info = NULL; + if (pipeline->device->store_shader_info) + shader_info = _mesa_string_buffer_create(mem_ctx, 256); + const unsigned *shader_code = - brw_compile_gs(compiler, NULL, mem_ctx, &key, &prog_data, nir, + brw_compile_gs(compiler, shader_info, mem_ctx, &key, &prog_data, nir, NULL, -1, NULL); if (shader_code == NULL) { ralloc_free(mem_ctx); @@ -845,6 +931,13 @@ anv_pipeline_compile_gs(struct anv_pipeline *pipeline, return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); } + if (shader_info) { + bin->shader_info = + vk_alloc(&pipeline->device->alloc, shader_info->length + 1, 8, + VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); + memcpy(bin->shader_info, shader_info->buf, shader_info->length + 1); + } + ralloc_free(mem_ctx); } @@ -977,8 +1070,12 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline, anv_fill_binding_table(&prog_data.base, num_rts); + struct _mesa_string_buffer *shader_info = NULL; + if (pipeline->device->store_shader_info) + shader_info = _mesa_string_buffer_create(mem_ctx, 256); + const unsigned *shader_code = - brw_compile_fs(compiler, NULL, mem_ctx, &key, &prog_data, nir, + brw_compile_fs(compiler, shader_info, mem_ctx, &key, &prog_data, nir, NULL, -1, -1, true, false, NULL, NULL); if (shader_code == NULL) { ralloc_free(mem_ctx); @@ -995,6 +1092,13 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline, return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); } + if (shader_info) { + bin->shader_info = + vk_alloc(&pipeline->device->alloc, shader_info->length + 1, 8, + VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); + memcpy(bin->shader_info, shader_info->buf, shader_info->length + 1); + } + ralloc_free(mem_ctx); } @@ -1053,8 +1157,12 @@ anv_pipeline_compile_cs(struct anv_pipeline *pipeline, anv_fill_binding_table(&prog_data.base, 1); + struct _mesa_string_buffer *shader_info = NULL; + if (pipeline->device->store_shader_info) + shader_info = _mesa_string_buffer_create(mem_ctx, 256); + const unsigned *shader_code = - brw_compile_cs(compiler, NULL, mem_ctx, &key, &prog_data, nir, + brw_compile_cs(compiler, shader_info, mem_ctx, &key, &prog_data, nir, -1, NULL); if (shader_code == NULL) { ralloc_free(mem_ctx); @@ -1071,6 +1179,13 @@ anv_pipeline_compile_cs(struct anv_pipeline *pipeline, return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); } + if (shader_info) { + bin->shader_info = + vk_alloc(&pipeline->device->alloc, shader_info->length + 1, 8, + VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); + memcpy(bin->shader_info, shader_info->buf, shader_info->length + 1); + } + ralloc_free(mem_ctx); } diff --git a/src/intel/vulkan/anv_pipeline_cache.c b/src/intel/vulkan/anv_pipeline_cache.c index 82551e9f81..9865eaa84e 100644 --- a/src/intel/vulkan/anv_pipeline_cache.c +++ b/src/intel/vulkan/anv_pipeline_cache.c @@ -89,6 +89,7 @@ anv_shader_bin_destroy(struct anv_device *device, { assert(shader->ref_cnt == 0); anv_state_pool_free(&device->instruction_state_pool, shader->kernel); + vk_free(&device->alloc, shader->shader_info); vk_free(&device->alloc, shader); } diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index b47420f89e..4d675a64ec 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -980,6 +980,8 @@ struct anv_device { pthread_mutex_t mutex; pthread_cond_t queue_submit; bool lost; + + bool store_shader_info; }; static inline struct anv_state_pool * @@ -2296,6 +2298,9 @@ struct anv_shader_bin { uint32_t prog_data_size; struct anv_pipeline_bind_map bind_map; + + /* Disassembly/shader information use by VK_AMD_shader_info */ + char *shader_info; }; struct anv_shader_bin * -- 2.17.1 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev