diff --git a/docs/relnotes/new_features.txt b/docs/relnotes/new_features.txt index 3b0033ac016..b1a31c6e691 100644 --- a/docs/relnotes/new_features.txt +++ b/docs/relnotes/new_features.txt @@ -8,3 +8,4 @@ panfrost Valhall support (conformant OpenGL ES 3.1 on Mali-G57) VK_EXT_primitives_generated_query on RADV VK_EXT_non_seamless_cube_map on RADV, ANV VK_EXT_border_color_swizzle on lavapipe, ANV, turnip, RADV +VK_EXT_shader_module_identifier on RADV diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index 118600adb9e..66af2ef4664 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -526,6 +526,7 @@ radv_physical_device_get_supported_extensions(const struct radv_physical_device #endif .EXT_shader_demote_to_helper_invocation = true, .EXT_shader_image_atomic_int64 = true, + .EXT_shader_module_identifier = true, .EXT_shader_stencil_export = true, .EXT_shader_subgroup_ballot = true, .EXT_shader_subgroup_vote = true, @@ -1773,6 +1774,12 @@ radv_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice, features->borderColorSwizzleFromImage = true; break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_FEATURES_EXT: { + VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT *features = + (VkPhysicalDeviceShaderModuleIdentifierFeaturesEXT *)ext; + features->shaderModuleIdentifier = true; + break; + } default: break; } @@ -2457,6 +2464,16 @@ radv_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, break; } + case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_MODULE_IDENTIFIER_PROPERTIES_EXT: { + VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT *properties = + (VkPhysicalDeviceShaderModuleIdentifierPropertiesEXT *)ext; + STATIC_ASSERT(sizeof(vk_shaderModuleIdentifierAlgorithmUUID) == + sizeof(properties->shaderModuleIdentifierAlgorithmUUID)); + memcpy(properties->shaderModuleIdentifierAlgorithmUUID, + vk_shaderModuleIdentifierAlgorithmUUID, + sizeof(properties->shaderModuleIdentifierAlgorithmUUID)); + break; + } default: break; } diff --git a/src/amd/vulkan/radv_pipeline.c b/src/amd/vulkan/radv_pipeline.c index 361cb9683c2..1e130f56ec2 100644 --- a/src/amd/vulkan/radv_pipeline.c +++ b/src/amd/vulkan/radv_pipeline.c @@ -202,10 +202,14 @@ radv_pipeline_destroy(struct radv_device *device, struct radv_pipeline *pipeline free(library_pipeline->groups); for (uint32_t i = 0; i < library_pipeline->stage_count; i++) { RADV_FROM_HANDLE(vk_shader_module, module, library_pipeline->stages[i].module); - vk_object_base_finish(&module->base); - ralloc_free(module); + if (module) { + vk_object_base_finish(&module->base); + ralloc_free(module); + } } free(library_pipeline->stages); + free(library_pipeline->identifiers); + free(library_pipeline->hashes); } if (pipeline->slab) @@ -4460,8 +4464,10 @@ radv_pipeline_stage_init(const VkPipelineShaderStageCreateInfo *sinfo, { const VkShaderModuleCreateInfo *minfo = vk_find_struct_const(sinfo->pNext, SHADER_MODULE_CREATE_INFO); + const VkPipelineShaderStageModuleIdentifierCreateInfoEXT *iinfo = + vk_find_struct_const(sinfo->pNext, PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT); - if (sinfo->module == VK_NULL_HANDLE && !minfo) + if (sinfo->module == VK_NULL_HANDLE && !minfo && !iinfo) return; memset(out_stage, 0, sizeof(*out_stage)); @@ -4481,7 +4487,7 @@ radv_pipeline_stage_init(const VkPipelineShaderStageCreateInfo *sinfo, if (module->nir) out_stage->internal_nir = module->nir; - } else { + } else if (minfo) { out_stage->spirv.data = (const char *) minfo->pCode; out_stage->spirv.size = minfo->codeSize; } diff --git a/src/amd/vulkan/radv_pipeline_cache.c b/src/amd/vulkan/radv_pipeline_cache.c index 25fe1bbae97..2d73211925f 100644 --- a/src/amd/vulkan/radv_pipeline_cache.c +++ b/src/amd/vulkan/radv_pipeline_cache.c @@ -166,7 +166,18 @@ radv_hash_rt_shaders(unsigned char *hash, const VkRayTracingPipelineCreateInfoKH RADV_FROM_HANDLE(vk_shader_module, module, pCreateInfo->pStages[i].module); const VkSpecializationInfo *spec_info = pCreateInfo->pStages[i].pSpecializationInfo; - _mesa_sha1_update(&ctx, module->sha1, sizeof(module->sha1)); + const VkPipelineShaderStageModuleIdentifierCreateInfoEXT *iinfo = + vk_find_struct_const(pCreateInfo->pStages[i].pNext, + PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT); + + if (module) { + _mesa_sha1_update(&ctx, module->sha1, sizeof(module->sha1)); + } else { + assert(iinfo); + assert(iinfo->identifierSize <= VK_MAX_SHADER_MODULE_IDENTIFIER_SIZE_EXT); + _mesa_sha1_update(&ctx, iinfo->pIdentifier, iinfo->identifierSize); + } + _mesa_sha1_update(&ctx, pCreateInfo->pStages[i].pName, strlen(pCreateInfo->pStages[i].pName)); if (spec_info && spec_info->mapEntryCount) { _mesa_sha1_update(&ctx, spec_info->pMapEntries, diff --git a/src/amd/vulkan/radv_pipeline_rt.c b/src/amd/vulkan/radv_pipeline_rt.c index ef82b4d9630..670b27f5edc 100644 --- a/src/amd/vulkan/radv_pipeline_rt.c +++ b/src/amd/vulkan/radv_pipeline_rt.c @@ -122,11 +122,38 @@ radv_rt_pipeline_library_create(VkDevice _device, VkPipelineCache _cache, memcpy(pipeline->stages, local_create_info.pStages, size); + pipeline->hashes = malloc(sizeof(*pipeline->hashes) * local_create_info.stageCount); + if (!pipeline->hashes) + goto fail; + + pipeline->identifiers = malloc(sizeof(*pipeline->identifiers) * local_create_info.stageCount); + if (!pipeline->identifiers) + goto fail; + for (uint32_t i = 0; i < local_create_info.stageCount; i++) { RADV_FROM_HANDLE(vk_shader_module, module, pipeline->stages[i].module); - struct vk_shader_module *new_module = vk_shader_module_clone(NULL, module); - pipeline->stages[i].module = vk_shader_module_to_handle(new_module); + const VkPipelineShaderStageModuleIdentifierCreateInfoEXT *iinfo = + vk_find_struct_const(pCreateInfo->pStages[i].pNext, + PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT); + + if (module) { + struct vk_shader_module *new_module = vk_shader_module_clone(NULL, module); + pipeline->stages[i].module = vk_shader_module_to_handle(new_module); + pipeline->stages[i].pNext = NULL; + } else { + assert(iinfo); + pipeline->identifiers[i].identifierSize = + MIN2(iinfo->identifierSize, sizeof(pipeline->hashes[i].sha1)); + memcpy(pipeline->hashes[i].sha1, iinfo->pIdentifier, + pipeline->identifiers[i].identifierSize); + pipeline->stages[i].module = VK_NULL_HANDLE; + pipeline->stages[i].pNext = &pipeline->identifiers[i]; + pipeline->identifiers[i].sType = + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_MODULE_IDENTIFIER_CREATE_INFO_EXT; + pipeline->identifiers[i].pNext = NULL; + pipeline->identifiers[i].pIdentifier = pipeline->hashes[i].sha1; + } } } @@ -147,6 +174,8 @@ radv_rt_pipeline_library_create(VkDevice _device, VkPipelineCache _cache, fail: free(pipeline->groups); free(pipeline->stages); + free(pipeline->hashes); + free(pipeline->identifiers); free((void *)local_create_info.pGroups); free((void *)local_create_info.pStages); return VK_ERROR_OUT_OF_HOST_MEMORY; @@ -1860,7 +1889,11 @@ radv_rt_pipeline_create(VkDevice _device, VkPipelineCache _cache, * generating the nir. */ result = radv_compute_pipeline_create(_device, _cache, &compute_info, pAllocator, hash, stack_sizes, local_create_info.groupCount, pPipeline); + if (result == VK_PIPELINE_COMPILE_REQUIRED) { + if (pCreateInfo->flags & VK_PIPELINE_CREATE_FAIL_ON_PIPELINE_COMPILE_REQUIRED_BIT) + goto fail; + stack_sizes = calloc(sizeof(*stack_sizes), local_create_info.groupCount); if (!stack_sizes) { result = VK_ERROR_OUT_OF_HOST_MEMORY; diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index fe97a61b21a..b681087e247 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -2136,6 +2136,10 @@ struct radv_library_pipeline { VkPipelineShaderStageCreateInfo *stages; unsigned group_count; VkRayTracingShaderGroupCreateInfoKHR *groups; + VkPipelineShaderStageModuleIdentifierCreateInfoEXT *identifiers; + struct { + uint8_t sha1[SHA1_DIGEST_LENGTH]; + } *hashes; }; #define RADV_DECL_PIPELINE_DOWNCAST(pipe_type, pipe_enum) \