Module: Mesa Branch: main Commit: 7e00380445c8d300defb0e697705222c3de5835b URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=7e00380445c8d300defb0e697705222c3de5835b
Author: Faith Ekstrand <[email protected]> Date: Thu Nov 16 15:41:31 2023 -0600 nvk: Implement VK_KHR_pipeline_executable_properties Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9621 Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26241> --- src/nouveau/vulkan/nvk_compute_pipeline.c | 5 +- src/nouveau/vulkan/nvk_graphics_pipeline.c | 5 +- src/nouveau/vulkan/nvk_physical_device.c | 4 + src/nouveau/vulkan/nvk_pipeline.c | 138 +++++++++++++++++++++++++++++ src/nouveau/vulkan/nvk_shader.c | 15 +++- src/nouveau/vulkan/nvk_shader.h | 1 + 6 files changed, 162 insertions(+), 6 deletions(-) diff --git a/src/nouveau/vulkan/nvk_compute_pipeline.c b/src/nouveau/vulkan/nvk_compute_pipeline.c index f51cddea38b..21d13fa5ef4 100644 --- a/src/nouveau/vulkan/nvk_compute_pipeline.c +++ b/src/nouveau/vulkan/nvk_compute_pipeline.c @@ -176,6 +176,9 @@ nvk_compute_pipeline_create(struct nvk_device *dev, assert(pCreateInfo->stage.stage == VK_SHADER_STAGE_COMPUTE_BIT); + VkPipelineCreateFlags2KHR pipeline_flags = + vk_compute_pipeline_create_flags(pCreateInfo); + struct vk_pipeline_robustness_state robustness; vk_pipeline_robustness_state_fill(&dev->vk, &robustness, pCreateInfo->pNext, @@ -189,7 +192,7 @@ nvk_compute_pipeline_create(struct nvk_device *dev, nvk_lower_nir(dev, nir, &robustness, false, pipeline_layout); - result = nvk_compile_nir(pdev, nir, NULL, + result = nvk_compile_nir(pdev, nir, pipeline_flags, NULL, &pipeline->base.shaders[MESA_SHADER_COMPUTE]); ralloc_free(nir); if (result != VK_SUCCESS) diff --git a/src/nouveau/vulkan/nvk_graphics_pipeline.c b/src/nouveau/vulkan/nvk_graphics_pipeline.c index bc734c77564..35bddedd548 100644 --- a/src/nouveau/vulkan/nvk_graphics_pipeline.c +++ b/src/nouveau/vulkan/nvk_graphics_pipeline.c @@ -314,6 +314,9 @@ nvk_graphics_pipeline_create(struct nvk_device *dev, if (pipeline == NULL) return vk_error(dev, VK_ERROR_OUT_OF_HOST_MEMORY); + VkPipelineCreateFlags2KHR pipeline_flags = + vk_graphics_pipeline_create_flags(pCreateInfo); + struct vk_graphics_pipeline_all_state all; struct vk_graphics_pipeline_state state = {}; result = vk_graphics_pipeline_state_fill(&dev->vk, &state, pCreateInfo, @@ -358,7 +361,7 @@ nvk_graphics_pipeline_create(struct nvk_device *dev, fs_key = &fs_key_tmp; } - result = nvk_compile_nir(pdev, nir[stage], fs_key, + result = nvk_compile_nir(pdev, nir[stage], pipeline_flags, fs_key, &pipeline->base.shaders[stage]); ralloc_free(nir[stage]); if (result != VK_SUCCESS) diff --git a/src/nouveau/vulkan/nvk_physical_device.c b/src/nouveau/vulkan/nvk_physical_device.c index 94cde20309c..86252246283 100644 --- a/src/nouveau/vulkan/nvk_physical_device.c +++ b/src/nouveau/vulkan/nvk_physical_device.c @@ -73,6 +73,7 @@ nvk_get_device_extensions(const struct nv_device_info *info, .KHR_maintenance4 = true, .KHR_map_memory2 = true, .KHR_multiview = true, + .KHR_pipeline_executable_properties = true, .KHR_push_descriptor = true, .KHR_relaxed_block_layout = true, .KHR_sampler_mirror_clamp_to_edge = true, @@ -251,6 +252,9 @@ nvk_get_device_features(const struct nv_device_info *info, .dynamicRendering = true, .maintenance4 = true, + /* VK_KHR_pipeline_executable_properties */ + .pipelineExecutableInfo = true, + /* VK_KHR_shader_clock */ .shaderSubgroupClock = true, .shaderDeviceClock = true, diff --git a/src/nouveau/vulkan/nvk_pipeline.c b/src/nouveau/vulkan/nvk_pipeline.c index 36a71c4fb56..a4ee7f8b37f 100644 --- a/src/nouveau/vulkan/nvk_pipeline.c +++ b/src/nouveau/vulkan/nvk_pipeline.c @@ -112,3 +112,141 @@ nvk_DestroyPipeline(VkDevice _device, VkPipeline _pipeline, nvk_pipeline_free(dev, pipeline, pAllocator); } + +#define WRITE_STR(field, ...) ({ \ + memset(field, 0, sizeof(field)); \ + UNUSED int i = snprintf(field, sizeof(field), __VA_ARGS__); \ + assert(i > 0 && i < sizeof(field)); \ +}) + +VKAPI_ATTR VkResult VKAPI_CALL +nvk_GetPipelineExecutablePropertiesKHR( + VkDevice device, + const VkPipelineInfoKHR *pPipelineInfo, + uint32_t *pExecutableCount, + VkPipelineExecutablePropertiesKHR *pProperties) +{ + VK_FROM_HANDLE(nvk_pipeline, pipeline, pPipelineInfo->pipeline); + VK_OUTARRAY_MAKE_TYPED(VkPipelineExecutablePropertiesKHR, out, + pProperties, pExecutableCount); + + for (gl_shader_stage stage = 0; stage < MESA_SHADER_STAGES; stage++) { + if (pipeline->shaders[stage].code_size == 0) + continue; + + vk_outarray_append_typed(VkPipelineExecutablePropertiesKHR, &out, props) { + props->stages = mesa_to_vk_shader_stage(stage); + props->subgroupSize = 32; + WRITE_STR(props->name, "%s", _mesa_shader_stage_to_string(stage)); + WRITE_STR(props->description, "%s shader", + _mesa_shader_stage_to_string(stage)); + } + } + + return vk_outarray_status(&out); +} + +static struct nvk_shader * +shader_for_exe_idx(struct nvk_pipeline *pipeline, uint32_t idx) +{ + for (gl_shader_stage stage = 0; stage < MESA_SHADER_STAGES; stage++) { + if (pipeline->shaders[stage].code_size == 0) + continue; + + if (idx == 0) + return &pipeline->shaders[stage]; + + idx--; + } + + return NULL; +} + +VKAPI_ATTR VkResult VKAPI_CALL +nvk_GetPipelineExecutableStatisticsKHR( + VkDevice device, + const VkPipelineExecutableInfoKHR *pExecutableInfo, + uint32_t *pStatisticCount, + VkPipelineExecutableStatisticKHR *pStatistics) +{ + VK_FROM_HANDLE(nvk_pipeline, pipeline, pExecutableInfo->pipeline); + VK_OUTARRAY_MAKE_TYPED(VkPipelineExecutableStatisticKHR, out, + pStatistics, pStatisticCount); + + struct nvk_shader *shader = + shader_for_exe_idx(pipeline, pExecutableInfo->executableIndex); + + vk_outarray_append_typed(VkPipelineExecutableStatisticKHR, &out, stat) { + WRITE_STR(stat->name, "Code Size"); + WRITE_STR(stat->description, + "Size of the compiled shader binary, in bytes"); + stat->format = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR; + stat->value.u64 = shader->code_size; + } + + vk_outarray_append_typed(VkPipelineExecutableStatisticKHR, &out, stat) { + WRITE_STR(stat->name, "Number of GPRs"); + WRITE_STR(stat->description, "Number of GPRs used by this pipeline"); + stat->format = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR; + stat->value.u64 = shader->info.num_gprs; + } + + vk_outarray_append_typed(VkPipelineExecutableStatisticKHR, &out, stat) { + WRITE_STR(stat->name, "SLM Size"); + WRITE_STR(stat->description, + "Size of shader local (scratch) memory, in bytes"); + stat->format = VK_PIPELINE_EXECUTABLE_STATISTIC_FORMAT_UINT64_KHR; + stat->value.u64 = shader->info.slm_size; + } + + return vk_outarray_status(&out); +} + +static bool +write_ir_text(VkPipelineExecutableInternalRepresentationKHR* ir, + const char *data) +{ + ir->isText = VK_TRUE; + + size_t data_len = strlen(data) + 1; + + if (ir->pData == NULL) { + ir->dataSize = data_len; + return true; + } + + strncpy(ir->pData, data, ir->dataSize); + if (ir->dataSize < data_len) + return false; + + ir->dataSize = data_len; + return true; +} + +VKAPI_ATTR VkResult VKAPI_CALL +nvk_GetPipelineExecutableInternalRepresentationsKHR( + VkDevice device, + const VkPipelineExecutableInfoKHR *pExecutableInfo, + uint32_t *pInternalRepresentationCount, + VkPipelineExecutableInternalRepresentationKHR* pInternalRepresentations) +{ + VK_FROM_HANDLE(nvk_pipeline, pipeline, pExecutableInfo->pipeline); + VK_OUTARRAY_MAKE_TYPED(VkPipelineExecutableInternalRepresentationKHR, out, + pInternalRepresentations, + pInternalRepresentationCount); + bool incomplete_text = false; + + struct nvk_shader *shader = + shader_for_exe_idx(pipeline, pExecutableInfo->executableIndex); + + if (shader->nak != NULL && shader->nak->asm_str != NULL) { + vk_outarray_append_typed(VkPipelineExecutableInternalRepresentationKHR, &out, ir) { + WRITE_STR(ir->name, "NAK assembly"); + WRITE_STR(ir->description, "NAK assembly"); + if (!write_ir_text(ir, shader->nak->asm_str)) + incomplete_text = true; + } + } + + return incomplete_text ? VK_INCOMPLETE : vk_outarray_status(&out); +} diff --git a/src/nouveau/vulkan/nvk_shader.c b/src/nouveau/vulkan/nvk_shader.c index b82a5572102..47435bd5523 100644 --- a/src/nouveau/vulkan/nvk_shader.c +++ b/src/nouveau/vulkan/nvk_shader.c @@ -395,10 +395,14 @@ nvk_shader_dump(struct nvk_shader *shader) static VkResult nvk_compile_nir_with_nak(struct nvk_physical_device *pdev, nir_shader *nir, + VkPipelineCreateFlagBits2KHR pipeline_flags, const struct nak_fs_key *fs_key, struct nvk_shader *shader) { - shader->nak = nak_compile_shader(nir, false, pdev->nak, fs_key); + const bool dump_asm = + pipeline_flags & VK_PIPELINE_CREATE_2_CAPTURE_INTERNAL_REPRESENTATIONS_BIT_KHR; + + shader->nak = nak_compile_shader(nir, dump_asm, pdev->nak, fs_key); shader->info = shader->nak->info; shader->code_ptr = shader->nak->code; shader->code_size = shader->nak->code_size; @@ -408,13 +412,16 @@ nvk_compile_nir_with_nak(struct nvk_physical_device *pdev, VkResult nvk_compile_nir(struct nvk_physical_device *pdev, nir_shader *nir, + VkPipelineCreateFlagBits2KHR pipeline_flags, const struct nak_fs_key *fs_key, struct nvk_shader *shader) { - if (use_nak(pdev, nir->info.stage)) - return nvk_compile_nir_with_nak(pdev, nir, fs_key, shader); - else + if (use_nak(pdev, nir->info.stage)) { + return nvk_compile_nir_with_nak(pdev, nir, pipeline_flags, + fs_key, shader); + } else { return nvk_cg_compile_nir(pdev, nir, fs_key, shader); + } } VkResult diff --git a/src/nouveau/vulkan/nvk_shader.h b/src/nouveau/vulkan/nvk_shader.h index 9e7d2430a3a..7ce8187236c 100644 --- a/src/nouveau/vulkan/nvk_shader.h +++ b/src/nouveau/vulkan/nvk_shader.h @@ -90,6 +90,7 @@ nvk_lower_nir(struct nvk_device *dev, nir_shader *nir, VkResult nvk_compile_nir(struct nvk_physical_device *dev, nir_shader *nir, + VkPipelineCreateFlagBits2KHR pipeline_flags, const struct nak_fs_key *fs_key, struct nvk_shader *shader);
