vulkan: Add a vk_pipeline_hash_shader_stage() helper

All drivers implement some sort of shader hashing, but each of
them does it slightly differently. Let's provide a generic helper
to avoid new copies of the same logic and encourage new drivers
to use one of the already implemented function.

Reviewed-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Reviewed-by: Jason Ekstrand <jason.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17186>
This commit is contained in:
Boris Brezillon
2022-06-22 04:14:38 -07:00
committed by Marge Bot
parent 5e5b54c9d1
commit 542538cf02
2 changed files with 75 additions and 0 deletions

View File

@@ -28,6 +28,10 @@
#include "vk_shader_module.h"
#include "vk_util.h"
#include "nir_serialize.h"
#include "util/mesa-sha1.h"
VkResult
vk_pipeline_shader_stage_to_nir(struct vk_device *device,
const VkPipelineShaderStageCreateInfo *info,
@@ -86,3 +90,59 @@ vk_pipeline_shader_stage_to_nir(struct vk_device *device,
return VK_SUCCESS;
}
void
vk_pipeline_hash_shader_stage(const VkPipelineShaderStageCreateInfo *info,
unsigned char *stage_sha1)
{
VK_FROM_HANDLE(vk_shader_module, module, info->module);
if (module && module->nir) {
/* Internal NIR module: serialize and hash the NIR shader.
* We don't need to hash other info fields since they should match the
* NIR data.
*/
assert(module->nir->info.stage == vk_to_mesa_shader_stage(info->stage));
ASSERTED nir_function_impl *entrypoint = nir_shader_get_entrypoint(module->nir);
assert(strcmp(entrypoint->function->name, info->pName) == 0);
assert(info->pSpecializationInfo == NULL);
struct blob blob;
blob_init(&blob);
nir_serialize(&blob, module->nir, false);
assert(!blob.out_of_memory);
_mesa_sha1_compute(blob.data, blob.size, stage_sha1);
blob_finish(&blob);
return;
}
struct mesa_sha1 ctx;
_mesa_sha1_init(&ctx);
if (module) {
_mesa_sha1_update(&ctx, module->sha1, sizeof(module->sha1));
} else {
const VkShaderModuleCreateInfo *minfo =
vk_find_struct_const(info->pNext, SHADER_MODULE_CREATE_INFO);
unsigned char spirv_sha1[SHA1_DIGEST_LENGTH];
assert(minfo);
_mesa_sha1_compute(minfo->pCode, minfo->codeSize, spirv_sha1);
_mesa_sha1_update(&ctx, spirv_sha1, sizeof(spirv_sha1));
}
_mesa_sha1_update(&ctx, info->pName, strlen(info->pName));
assert(util_bitcount(info->stage) == 1);
_mesa_sha1_update(&ctx, &info->stage, sizeof(info->stage));
if (info->pSpecializationInfo) {
_mesa_sha1_update(&ctx, info->pSpecializationInfo->pMapEntries,
info->pSpecializationInfo->mapEntryCount *
sizeof(*info->pSpecializationInfo->pMapEntries));
_mesa_sha1_update(&ctx, info->pSpecializationInfo->pData,
info->pSpecializationInfo->dataSize);
}
_mesa_sha1_final(&ctx, stage_sha1);
}

View File

@@ -42,6 +42,21 @@ vk_pipeline_shader_stage_to_nir(struct vk_device *device,
const struct nir_shader_compiler_options *nir_options,
void *mem_ctx, struct nir_shader **nir_out);
/** Hash VkPipelineShaderStageCreateInfo info
*
* Returns the hash of a VkPipelineShaderStageCreateInfo:
* SHA1(info->module->sha1,
* info->pName,
* vk_stage_to_mesa_stage(info->stage),
* info->pSpecializationInfo)
*
* Can only be used if VkPipelineShaderStageCreateInfo::module is a
* vk_shader_module object.
*/
void
vk_pipeline_hash_shader_stage(const VkPipelineShaderStageCreateInfo *info,
unsigned char *stage_sha1);
#ifdef __cplusplus
}
#endif