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:

committed by
Marge Bot

parent
5e5b54c9d1
commit
542538cf02
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
Reference in New Issue
Block a user