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>
This commit is contained in:
Faith Ekstrand 2023-11-16 15:41:31 -06:00 committed by Marge Bot
parent 3b3b157961
commit 7e00380445
6 changed files with 162 additions and 6 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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,

View file

@ -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);
}

View file

@ -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

View file

@ -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);