mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-31 16:20:13 +01:00
radv: add initial support for pipeline binaries
Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/30812>
This commit is contained in:
parent
32a4c9e117
commit
be06bfcbed
7 changed files with 612 additions and 0 deletions
|
|
@ -127,6 +127,8 @@ libradv_files = files(
|
|||
'radv_physical_device.c',
|
||||
'radv_pipeline.c',
|
||||
'radv_pipeline.h',
|
||||
'radv_pipeline_binary.c',
|
||||
'radv_pipeline_binary.h',
|
||||
'radv_pipeline_cache.c',
|
||||
'radv_pipeline_cache.h',
|
||||
'radv_pipeline_compute.c',
|
||||
|
|
|
|||
446
src/amd/vulkan/radv_pipeline_binary.c
Normal file
446
src/amd/vulkan/radv_pipeline_binary.c
Normal file
|
|
@ -0,0 +1,446 @@
|
|||
/*
|
||||
* Copyright © 2024 Valve Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "radv_pipeline_binary.h"
|
||||
#include "util/disk_cache.h"
|
||||
#include "util/macros.h"
|
||||
#include "util/mesa-blake3.h"
|
||||
#include "util/mesa-sha1.h"
|
||||
#include "util/u_atomic.h"
|
||||
#include "util/u_debug.h"
|
||||
#include "nir_serialize.h"
|
||||
#include "radv_debug.h"
|
||||
#include "radv_device.h"
|
||||
#include "radv_entrypoints.h"
|
||||
#include "radv_pipeline_cache.h"
|
||||
#include "radv_pipeline_graphics.h"
|
||||
#include "radv_pipeline_rt.h"
|
||||
#include "radv_shader.h"
|
||||
#include "vk_log.h"
|
||||
#include "vk_pipeline.h"
|
||||
#include "vk_util.h"
|
||||
|
||||
static VkResult
|
||||
radv_get_pipeline_key(struct radv_device *device, const VkPipelineCreateInfoKHR *pPipelineCreateInfo,
|
||||
unsigned char *key)
|
||||
{
|
||||
VkResult result = VK_SUCCESS;
|
||||
|
||||
switch (((VkBaseInStructure *)pPipelineCreateInfo->pNext)->sType) {
|
||||
case VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO: {
|
||||
const VkGraphicsPipelineCreateInfo *graphics_create_info =
|
||||
(VkGraphicsPipelineCreateInfo *)pPipelineCreateInfo->pNext;
|
||||
struct radv_graphics_pipeline_state gfx_state;
|
||||
|
||||
result = radv_generate_graphics_pipeline_state(device, graphics_create_info, &gfx_state);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
radv_graphics_pipeline_hash(device, &gfx_state, key);
|
||||
radv_graphics_pipeline_state_finish(device, &gfx_state);
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO: {
|
||||
const VkComputePipelineCreateInfo *compute_create_info =
|
||||
(VkComputePipelineCreateInfo *)pPipelineCreateInfo->pNext;
|
||||
|
||||
radv_compute_pipeline_hash(device, compute_create_info, key);
|
||||
break;
|
||||
}
|
||||
case VK_STRUCTURE_TYPE_RAY_TRACING_PIPELINE_CREATE_INFO_KHR: {
|
||||
const VkRayTracingPipelineCreateInfoKHR *rt_create_info =
|
||||
(VkRayTracingPipelineCreateInfoKHR *)pPipelineCreateInfo->pNext;
|
||||
struct radv_ray_tracing_state_key rt_state;
|
||||
|
||||
result = radv_generate_ray_tracing_state_key(device, rt_create_info, &rt_state);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
radv_ray_tracing_pipeline_hash(device, rt_create_info, &rt_state, key);
|
||||
radv_ray_tracing_state_key_finish(&rt_state);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
unreachable("unsupported pipeline create info struct");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL
|
||||
radv_GetPipelineKeyKHR(VkDevice _device, const VkPipelineCreateInfoKHR *pPipelineCreateInfo,
|
||||
VkPipelineBinaryKeyKHR *pPipelineKey)
|
||||
{
|
||||
VK_FROM_HANDLE(radv_device, device, _device);
|
||||
VkResult result;
|
||||
|
||||
memset(pPipelineKey->key, 0, sizeof(pPipelineKey->key));
|
||||
|
||||
/* Return the global key that applies to all pipelines. */
|
||||
if (!pPipelineCreateInfo) {
|
||||
static_assert(sizeof(device->cache_hash) <= sizeof(pPipelineKey->key), "mismatch pipeline binary key size");
|
||||
|
||||
memcpy(pPipelineKey->key, device->cache_hash, sizeof(device->cache_hash));
|
||||
pPipelineKey->keySize = sizeof(device->cache_hash);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
result = radv_get_pipeline_key(device, pPipelineCreateInfo, pPipelineKey->key);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
pPipelineKey->keySize = SHA1_DIGEST_LENGTH;
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
radv_create_pipeline_binary(struct radv_device *device, const VkAllocationCallbacks *pAllocator, const blake3_hash key,
|
||||
const void *data, size_t data_size, struct radv_pipeline_binary **pipeline_binary_out)
|
||||
{
|
||||
struct radv_pipeline_binary *pipeline_binary;
|
||||
|
||||
pipeline_binary =
|
||||
vk_zalloc2(&device->vk.alloc, pAllocator, sizeof(*pipeline_binary), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (pipeline_binary == NULL)
|
||||
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
|
||||
|
||||
vk_object_base_init(&device->vk, &pipeline_binary->base, VK_OBJECT_TYPE_PIPELINE_BINARY_KHR);
|
||||
|
||||
pipeline_binary->data = (void *)data;
|
||||
pipeline_binary->size = data_size;
|
||||
|
||||
memcpy(pipeline_binary->key, key, sizeof(*key));
|
||||
|
||||
*pipeline_binary_out = pipeline_binary;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
radv_create_pipeline_binary_from_data(struct radv_device *device, const VkAllocationCallbacks *pAllocator,
|
||||
const VkPipelineBinaryDataKHR *pData, const VkPipelineBinaryKeyKHR *pKey,
|
||||
struct util_dynarray *pipeline_binaries, uint32_t *num_binaries)
|
||||
{
|
||||
struct radv_pipeline_binary *pipeline_binary;
|
||||
VkResult result;
|
||||
void *data;
|
||||
|
||||
if (!pipeline_binaries) {
|
||||
(*num_binaries)++;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
data = malloc(pData->dataSize);
|
||||
if (!data)
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
|
||||
memcpy(data, pData->pData, pData->dataSize);
|
||||
|
||||
result = radv_create_pipeline_binary(device, pAllocator, pKey->key, data, pData->dataSize, &pipeline_binary);
|
||||
if (result != VK_SUCCESS) {
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
util_dynarray_append(pipeline_binaries, struct radv_pipeline_binary *, pipeline_binary);
|
||||
return result;
|
||||
}
|
||||
|
||||
VkResult
|
||||
radv_create_pipeline_binary_from_shader(struct radv_device *device, const VkAllocationCallbacks *pAllocator,
|
||||
struct radv_shader *shader, struct util_dynarray *pipeline_binaries,
|
||||
uint32_t *num_binaries)
|
||||
{
|
||||
struct radv_pipeline_binary *pipeline_binary;
|
||||
struct blob blob;
|
||||
size_t data_size;
|
||||
VkResult result;
|
||||
void *data;
|
||||
|
||||
if (!pipeline_binaries) {
|
||||
(*num_binaries)++;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
blob_init(&blob);
|
||||
radv_shader_serialize(shader, &blob);
|
||||
blob_finish_get_buffer(&blob, &data, &data_size);
|
||||
|
||||
result = radv_create_pipeline_binary(device, pAllocator, shader->hash, data, data_size, &pipeline_binary);
|
||||
if (result != VK_SUCCESS) {
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
util_dynarray_append(pipeline_binaries, struct radv_pipeline_binary *, pipeline_binary);
|
||||
return result;
|
||||
}
|
||||
|
||||
VkResult
|
||||
radv_create_pipeline_binary_from_rt_shader(struct radv_device *device, const VkAllocationCallbacks *pAllocator,
|
||||
struct radv_shader *shader, bool is_traversal_shader,
|
||||
const uint8_t stage_sha1[SHA1_DIGEST_LENGTH],
|
||||
const struct radv_ray_tracing_stage_info *rt_stage_info, uint32_t stack_size,
|
||||
struct vk_pipeline_cache_object *nir,
|
||||
struct util_dynarray *pipeline_binaries, uint32_t *num_binaries)
|
||||
{
|
||||
struct radv_pipeline_binary *pipeline_binary;
|
||||
struct mesa_blake3 ctx;
|
||||
struct blob blob;
|
||||
size_t data_size;
|
||||
blake3_hash key;
|
||||
VkResult result;
|
||||
void *data;
|
||||
|
||||
if (!pipeline_binaries) {
|
||||
(*num_binaries)++;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
_mesa_blake3_init(&ctx);
|
||||
_mesa_blake3_update(&ctx, stage_sha1, sizeof(*stage_sha1));
|
||||
_mesa_blake3_final(&ctx, key);
|
||||
|
||||
struct radv_ray_tracing_binary_header header = {
|
||||
.is_traversal_shader = is_traversal_shader,
|
||||
.has_shader = !!shader,
|
||||
.has_nir = !!nir,
|
||||
.stack_size = stack_size,
|
||||
};
|
||||
|
||||
memcpy(header.stage_sha1, stage_sha1, sizeof(header.stage_sha1));
|
||||
memcpy(&header.stage_info, rt_stage_info, sizeof(header.stage_info));
|
||||
|
||||
blob_init(&blob);
|
||||
blob_write_bytes(&blob, &header, sizeof(header));
|
||||
if (header.has_shader)
|
||||
radv_shader_serialize(shader, &blob);
|
||||
if (header.has_nir) {
|
||||
struct vk_raw_data_cache_object *nir_object = container_of(nir, struct vk_raw_data_cache_object, base);
|
||||
blob_write_bytes(&blob, nir_object->data, nir_object->data_size);
|
||||
}
|
||||
blob_finish_get_buffer(&blob, &data, &data_size);
|
||||
|
||||
result = radv_create_pipeline_binary(device, pAllocator, key, data, data_size, &pipeline_binary);
|
||||
if (result != VK_SUCCESS) {
|
||||
free(data);
|
||||
return result;
|
||||
}
|
||||
|
||||
util_dynarray_append(pipeline_binaries, struct radv_pipeline_binary *, pipeline_binary);
|
||||
return result;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
radv_create_pipeline_binary_from_pipeline(struct radv_device *device, const VkAllocationCallbacks *pAllocator,
|
||||
struct radv_pipeline *pipeline, struct util_dynarray *pipeline_binaries,
|
||||
uint32_t *num_binaries)
|
||||
{
|
||||
VkResult result = VK_SUCCESS;
|
||||
|
||||
if (pipeline->type == RADV_PIPELINE_RAY_TRACING) {
|
||||
struct radv_ray_tracing_pipeline *rt_pipeline = radv_pipeline_to_ray_tracing(pipeline);
|
||||
|
||||
for (uint32_t i = 0; i < rt_pipeline->non_imported_stage_count; i++) {
|
||||
struct radv_ray_tracing_stage *rt_stage = &rt_pipeline->stages[i];
|
||||
|
||||
result = radv_create_pipeline_binary_from_rt_shader(device, pAllocator, rt_stage->shader, false,
|
||||
rt_stage->sha1, &rt_stage->info, rt_stage->stack_size,
|
||||
rt_stage->nir, pipeline_binaries, num_binaries);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
|
||||
struct radv_shader *traversal_shader = rt_pipeline->base.base.shaders[MESA_SHADER_INTERSECTION];
|
||||
if (traversal_shader) {
|
||||
result = radv_create_pipeline_binary_from_rt_shader(device, pAllocator, traversal_shader, true,
|
||||
traversal_shader->hash, NULL, 0, NULL, pipeline_binaries,
|
||||
num_binaries);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < MESA_VULKAN_SHADER_STAGES; i++) {
|
||||
if (!pipeline->shaders[i])
|
||||
continue;
|
||||
|
||||
result = radv_create_pipeline_binary_from_shader(device, pAllocator, pipeline->shaders[i], pipeline_binaries,
|
||||
num_binaries);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
|
||||
if (pipeline->gs_copy_shader) {
|
||||
result = radv_create_pipeline_binary_from_shader(device, pAllocator, pipeline->gs_copy_shader,
|
||||
pipeline_binaries, num_binaries);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
radv_create_pipeline_binary_from_cache(struct radv_device *device, const VkAllocationCallbacks *pAllocator,
|
||||
const VkPipelineCreateInfoKHR *pPipelineCreateInfo,
|
||||
struct util_dynarray *pipeline_binaries, uint32_t *num_binaries)
|
||||
{
|
||||
unsigned char key[SHA1_DIGEST_LENGTH];
|
||||
bool found_in_internal_cache;
|
||||
VkResult result;
|
||||
|
||||
assert(pPipelineCreateInfo);
|
||||
|
||||
result = radv_get_pipeline_key(device, pPipelineCreateInfo, key);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
result = radv_pipeline_cache_get_binaries(device, pAllocator, key, pipeline_binaries, num_binaries,
|
||||
&found_in_internal_cache);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
|
||||
return found_in_internal_cache ? VK_SUCCESS : VK_PIPELINE_BINARY_MISSING_KHR;
|
||||
}
|
||||
|
||||
static VkResult
|
||||
radv_create_pipeline_binaries(struct radv_device *device, const VkPipelineBinaryCreateInfoKHR *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator, struct util_dynarray *pipeline_binaries,
|
||||
uint32_t *num_binaries)
|
||||
{
|
||||
VkResult result = VK_SUCCESS;
|
||||
|
||||
if (pCreateInfo->pKeysAndDataInfo) {
|
||||
const VkPipelineBinaryKeysAndDataKHR *pKeysAndDataInfo = pCreateInfo->pKeysAndDataInfo;
|
||||
|
||||
for (uint32_t i = 0; i < pKeysAndDataInfo->binaryCount; i++) {
|
||||
const VkPipelineBinaryDataKHR *pData = &pKeysAndDataInfo->pPipelineBinaryData[i];
|
||||
const VkPipelineBinaryKeyKHR *pKey = &pKeysAndDataInfo->pPipelineBinaryKeys[i];
|
||||
|
||||
result =
|
||||
radv_create_pipeline_binary_from_data(device, pAllocator, pData, pKey, pipeline_binaries, num_binaries);
|
||||
if (result != VK_SUCCESS)
|
||||
return result;
|
||||
}
|
||||
} else if (pCreateInfo->pipeline) {
|
||||
VK_FROM_HANDLE(radv_pipeline, pipeline, pCreateInfo->pipeline);
|
||||
|
||||
result = radv_create_pipeline_binary_from_pipeline(device, pAllocator, pipeline, pipeline_binaries, num_binaries);
|
||||
} else {
|
||||
result = radv_create_pipeline_binary_from_cache(device, pAllocator, pCreateInfo->pPipelineCreateInfo,
|
||||
pipeline_binaries, num_binaries);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
radv_destroy_pipeline_binary(struct radv_device *device, const VkAllocationCallbacks *pAllocator,
|
||||
struct radv_pipeline_binary *pipeline_binary)
|
||||
{
|
||||
if (!pipeline_binary)
|
||||
return;
|
||||
|
||||
free(pipeline_binary->data);
|
||||
|
||||
vk_object_base_finish(&pipeline_binary->base);
|
||||
vk_free2(&device->vk.alloc, pAllocator, pipeline_binary);
|
||||
}
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL
|
||||
radv_CreatePipelineBinariesKHR(VkDevice _device, const VkPipelineBinaryCreateInfoKHR *pCreateInfo,
|
||||
const VkAllocationCallbacks *pAllocator, VkPipelineBinaryHandlesInfoKHR *pBinaries)
|
||||
{
|
||||
VK_FROM_HANDLE(radv_device, device, _device);
|
||||
struct util_dynarray pipeline_binaries;
|
||||
VkResult result;
|
||||
|
||||
if (!pBinaries->pPipelineBinaries) {
|
||||
result = radv_create_pipeline_binaries(device, pCreateInfo, pAllocator, NULL, &pBinaries->pipelineBinaryCount);
|
||||
return result;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < pBinaries->pipelineBinaryCount; i++)
|
||||
pBinaries->pPipelineBinaries[i] = VK_NULL_HANDLE;
|
||||
|
||||
util_dynarray_init(&pipeline_binaries, NULL);
|
||||
|
||||
/* Get all pipeline binaries from the pCreateInfo first to simplify the creation. */
|
||||
result = radv_create_pipeline_binaries(device, pCreateInfo, pAllocator, &pipeline_binaries, NULL);
|
||||
if (result != VK_SUCCESS) {
|
||||
util_dynarray_foreach (&pipeline_binaries, struct radv_pipeline_binary *, pipeline_binary)
|
||||
radv_destroy_pipeline_binary(device, pAllocator, *pipeline_binary);
|
||||
util_dynarray_fini(&pipeline_binaries);
|
||||
return result;
|
||||
}
|
||||
|
||||
const uint32_t num_binaries = util_dynarray_num_elements(&pipeline_binaries, struct radv_pipeline_binary *);
|
||||
|
||||
for (uint32_t i = 0; i < num_binaries; i++) {
|
||||
struct radv_pipeline_binary **pipeline_binary =
|
||||
util_dynarray_element(&pipeline_binaries, struct radv_pipeline_binary *, i);
|
||||
|
||||
if (i < pBinaries->pipelineBinaryCount) {
|
||||
pBinaries->pPipelineBinaries[i] = radv_pipeline_binary_to_handle(*pipeline_binary);
|
||||
} else {
|
||||
/* Free the pipeline binary that couldn't be returned. */
|
||||
radv_destroy_pipeline_binary(device, pAllocator, *pipeline_binary);
|
||||
}
|
||||
}
|
||||
|
||||
result = pBinaries->pipelineBinaryCount < num_binaries ? VK_INCOMPLETE : result;
|
||||
pBinaries->pipelineBinaryCount = MIN2(num_binaries, pBinaries->pipelineBinaryCount);
|
||||
|
||||
util_dynarray_fini(&pipeline_binaries);
|
||||
return result;
|
||||
}
|
||||
|
||||
VKAPI_ATTR void VKAPI_CALL
|
||||
radv_DestroyPipelineBinaryKHR(VkDevice _device, VkPipelineBinaryKHR pipelineBinary,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
VK_FROM_HANDLE(radv_pipeline_binary, pipeline_binary, pipelineBinary);
|
||||
VK_FROM_HANDLE(radv_device, device, _device);
|
||||
|
||||
radv_destroy_pipeline_binary(device, pAllocator, pipeline_binary);
|
||||
}
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL
|
||||
radv_GetPipelineBinaryDataKHR(VkDevice _device, const VkPipelineBinaryDataInfoKHR *pInfo,
|
||||
VkPipelineBinaryKeyKHR *pPipelineBinaryKey, size_t *pPipelineBinaryDataSize,
|
||||
void *pPipelineBinaryData)
|
||||
{
|
||||
VK_FROM_HANDLE(radv_pipeline_binary, pipeline_binary, pInfo->pipelineBinary);
|
||||
const size_t size = pipeline_binary->size;
|
||||
|
||||
if (!pPipelineBinaryData) {
|
||||
*pPipelineBinaryDataSize = size;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
if (*pPipelineBinaryDataSize < size) {
|
||||
*pPipelineBinaryDataSize = size;
|
||||
return VK_ERROR_NOT_ENOUGH_SPACE_KHR;
|
||||
}
|
||||
|
||||
memcpy(pPipelineBinaryData, pipeline_binary->data, size);
|
||||
*pPipelineBinaryDataSize = size;
|
||||
|
||||
memcpy(pPipelineBinaryKey->key, pipeline_binary->key, sizeof(pipeline_binary->key));
|
||||
pPipelineBinaryKey->keySize = sizeof(pipeline_binary->key);
|
||||
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
|
||||
VKAPI_ATTR VkResult VKAPI_CALL
|
||||
radv_ReleaseCapturedPipelineDataKHR(VkDevice _device, const VkReleaseCapturedPipelineDataInfoKHR *pInfo,
|
||||
const VkAllocationCallbacks *pAllocator)
|
||||
{
|
||||
/* no-op */
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
42
src/amd/vulkan/radv_pipeline_binary.h
Normal file
42
src/amd/vulkan/radv_pipeline_binary.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright © 2024 Valve Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#ifndef RADV_PIPELINE_BINARY_H
|
||||
#define RADV_PIPELINE_BINARY_H
|
||||
|
||||
#include "vk_object.h"
|
||||
|
||||
#include "util/mesa-blake3.h"
|
||||
#include "util/mesa-sha1.h"
|
||||
|
||||
struct radv_device;
|
||||
struct radv_ray_tracing_stage_info;
|
||||
struct radv_shader;
|
||||
struct util_dynarray;
|
||||
struct vk_pipeline_cache_object;
|
||||
|
||||
struct radv_pipeline_binary {
|
||||
struct vk_object_base base;
|
||||
|
||||
blake3_hash key;
|
||||
void *data;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
VK_DEFINE_NONDISP_HANDLE_CASTS(radv_pipeline_binary, base, VkPipelineBinaryKHR, VK_OBJECT_TYPE_PIPELINE_BINARY_KHR)
|
||||
|
||||
VkResult radv_create_pipeline_binary_from_shader(struct radv_device *device, const VkAllocationCallbacks *pAllocator,
|
||||
struct radv_shader *shader, struct util_dynarray *pipeline_binaries,
|
||||
uint32_t *num_binaries);
|
||||
|
||||
VkResult radv_create_pipeline_binary_from_rt_shader(struct radv_device *device, const VkAllocationCallbacks *pAllocator,
|
||||
struct radv_shader *shader, bool is_traversal_shader,
|
||||
const uint8_t stage_sha1[SHA1_DIGEST_LENGTH],
|
||||
const struct radv_ray_tracing_stage_info *rt_stage_info,
|
||||
uint32_t stack_size, struct vk_pipeline_cache_object *nir,
|
||||
struct util_dynarray *pipeline_binaries, uint32_t *num_binaries);
|
||||
|
||||
#endif /* RADV_PIPELINE_BINARY_H */
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
#include "radv_pipeline.h"
|
||||
#include "radv_pipeline_compute.h"
|
||||
#include "radv_pipeline_graphics.h"
|
||||
#include "radv_pipeline_binary.h"
|
||||
#include "radv_pipeline_rt.h"
|
||||
#include "radv_shader.h"
|
||||
#include "vk_pipeline.h"
|
||||
|
|
@ -627,3 +628,105 @@ radv_pipeline_cache_nir_to_handle(struct radv_device *device, struct vk_pipeline
|
|||
free(data);
|
||||
return object;
|
||||
}
|
||||
|
||||
VkResult
|
||||
radv_pipeline_cache_get_binaries(struct radv_device *device, const VkAllocationCallbacks *pAllocator,
|
||||
const unsigned char *sha1, struct util_dynarray *pipeline_binaries,
|
||||
uint32_t *num_binaries, bool *found_in_internal_cache)
|
||||
{
|
||||
struct vk_pipeline_cache *cache = device->mem_cache;
|
||||
VkResult result;
|
||||
|
||||
*found_in_internal_cache = false;
|
||||
|
||||
if (radv_is_cache_disabled(device, cache))
|
||||
return VK_SUCCESS;
|
||||
|
||||
struct vk_pipeline_cache_object *object =
|
||||
vk_pipeline_cache_lookup_object(cache, sha1, SHA1_DIGEST_LENGTH, &radv_pipeline_ops, NULL);
|
||||
if (!object)
|
||||
return VK_SUCCESS;
|
||||
|
||||
struct radv_pipeline_cache_object *pipeline_obj = container_of(object, struct radv_pipeline_cache_object, base);
|
||||
|
||||
bool complete = true;
|
||||
bool is_rt = false;
|
||||
for (unsigned i = 0; i < pipeline_obj->num_shaders; i++) {
|
||||
if (gl_shader_stage_is_rt(pipeline_obj->shaders[i]->info.stage)) {
|
||||
is_rt = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_rt) {
|
||||
struct radv_ray_tracing_pipeline_cache_data *data = pipeline_obj->data;
|
||||
struct radv_shader *traversal_shader = NULL;
|
||||
unsigned idx = 0;
|
||||
|
||||
if (data->has_traversal_shader)
|
||||
traversal_shader = pipeline_obj->shaders[idx++];
|
||||
|
||||
for (unsigned i = 0; i < data->num_stages; i++) {
|
||||
const struct radv_ray_tracing_stage_cache_data *stage_data = &data->stages[i];
|
||||
struct vk_pipeline_cache_object *nir = NULL;
|
||||
struct radv_shader *shader = NULL;
|
||||
|
||||
if (stage_data->has_shader)
|
||||
shader = pipeline_obj->shaders[idx++];
|
||||
|
||||
if (data->is_library)
|
||||
nir = radv_pipeline_cache_lookup_nir_handle(device, cache, data->stages[i].sha1);
|
||||
|
||||
result = radv_create_pipeline_binary_from_rt_shader(device, pAllocator, shader, false, data->stages[i].sha1,
|
||||
&stage_data->info, stage_data->stack_size, nir,
|
||||
pipeline_binaries, num_binaries);
|
||||
|
||||
if (data->is_library)
|
||||
complete &= nir != NULL;
|
||||
|
||||
if (nir)
|
||||
vk_pipeline_cache_object_unref(&device->vk, nir);
|
||||
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (traversal_shader) {
|
||||
result = radv_create_pipeline_binary_from_rt_shader(device, pAllocator, traversal_shader, true,
|
||||
traversal_shader->hash, NULL, 0, NULL, pipeline_binaries,
|
||||
num_binaries);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
struct radv_shader *gs_copy_shader = NULL;
|
||||
|
||||
for (unsigned i = 0; i < pipeline_obj->num_shaders; i++) {
|
||||
struct radv_shader *shader = pipeline_obj->shaders[i];
|
||||
gl_shader_stage s = shader->info.stage;
|
||||
|
||||
if (s == MESA_SHADER_VERTEX && i > 0) {
|
||||
/* The GS copy-shader is a VS placed after all other stages */
|
||||
gs_copy_shader = shader;
|
||||
} else {
|
||||
result =
|
||||
radv_create_pipeline_binary_from_shader(device, pAllocator, shader, pipeline_binaries, num_binaries);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (gs_copy_shader) {
|
||||
result = radv_create_pipeline_binary_from_shader(device, pAllocator, gs_copy_shader, pipeline_binaries,
|
||||
num_binaries);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
*found_in_internal_cache = complete;
|
||||
|
||||
fail:
|
||||
vk_pipeline_cache_object_unref(&device->vk, &pipeline_obj->base);
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ struct radv_ray_tracing_stage;
|
|||
struct radv_shader_binary;
|
||||
struct radv_shader_stage;
|
||||
struct radv_spirv_to_nir_options;
|
||||
struct util_dynarray;
|
||||
|
||||
void radv_hash_graphics_spirv_to_nir(blake3_hash hash, const struct radv_shader_stage *stage,
|
||||
const struct radv_spirv_to_nir_options *options);
|
||||
|
|
@ -75,4 +76,8 @@ void radv_shader_serialize(struct radv_shader *shader, struct blob *blob);
|
|||
struct radv_shader *radv_shader_deserialize(struct radv_device *device, const void *key_data, size_t key_size,
|
||||
struct blob_reader *blob);
|
||||
|
||||
VkResult radv_pipeline_cache_get_binaries(struct radv_device *device, const VkAllocationCallbacks *pAllocator,
|
||||
const unsigned char *sha1, struct util_dynarray *pipeline_binaries,
|
||||
uint32_t *num_binaries, bool *found_in_internal_cache);
|
||||
|
||||
#endif /* RADV_PIPELINE_CACHE_H */
|
||||
|
|
|
|||
|
|
@ -2505,11 +2505,16 @@ radv_is_fast_linking_enabled(const VkGraphicsPipelineCreateInfo *pCreateInfo)
|
|||
static bool
|
||||
radv_skip_graphics_pipeline_compile(const struct radv_device *device, const VkGraphicsPipelineCreateInfo *pCreateInfo)
|
||||
{
|
||||
const VkPipelineBinaryInfoKHR *binary_info = vk_find_struct_const(pCreateInfo->pNext, PIPELINE_BINARY_INFO_KHR);
|
||||
const VkPipelineCreateFlags2KHR create_flags = vk_graphics_pipeline_create_flags(pCreateInfo);
|
||||
const struct radv_physical_device *pdev = radv_device_physical(device);
|
||||
VkShaderStageFlagBits binary_stages = 0;
|
||||
VkShaderStageFlags active_stages = 0;
|
||||
|
||||
/* No compilation when pipeline binaries are imported. */
|
||||
if (binary_info)
|
||||
return true;
|
||||
|
||||
/* Do not skip for libraries. */
|
||||
if (create_flags & VK_PIPELINE_CREATE_2_LIBRARY_BIT_KHR)
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -121,4 +121,13 @@ VkResult radv_generate_ray_tracing_state_key(struct radv_device *device,
|
|||
|
||||
void radv_ray_tracing_state_key_finish(struct radv_ray_tracing_state_key *rt_state);
|
||||
|
||||
struct radv_ray_tracing_binary_header {
|
||||
uint32_t is_traversal_shader : 1;
|
||||
uint32_t has_shader : 1;
|
||||
uint32_t has_nir : 1;
|
||||
uint8_t stage_sha1[SHA1_DIGEST_LENGTH];
|
||||
uint32_t stack_size;
|
||||
struct radv_ray_tracing_stage_info stage_info;
|
||||
};
|
||||
|
||||
#endif /* RADV_PIPELINE_RT */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue