v3dv/pipeline_cache: bare basic support for pipeline cache

And this means providing a proper cache object, and being able to
load/retrieve a cache data with a proper header. Not really caching
anything yet. That would be tackle on following patches.

Note that this no-op cache got all the specific pipeline_cache and
pipeline.cache tests passing on the rpi4.

The following tests are still crashing when using the simulator:
 dEQP-VK.synchronization.internally_synchronized_objects.pipeline_cache_compute
 dEQP-VK.synchronization.internally_synchronized_objects.pipeline_cache_graphics

But those are an issue of synchronization tests on the simulator, and
not related with the pipeline cache itself. In general synchronization
tests should be tested on the rpi4.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
This commit is contained in:
Alejandro Piñeiro 2020-07-04 13:10:49 +02:00 committed by Marge Bot
parent fd70e8e0b0
commit 1d2ae8756f
2 changed files with 121 additions and 12 deletions

View File

@ -22,14 +22,76 @@
*/
#include "v3dv_private.h"
#include "vulkan/util/vk_util.h"
static void
pipeline_cache_init(struct v3dv_pipeline_cache *cache,
struct v3dv_device *device)
{
cache->_loader_data.loaderMagic = ICD_LOADER_MAGIC;
cache->device = device;
pthread_mutex_init(&cache->mutex, NULL);
}
static void
pipeline_cache_load(struct v3dv_pipeline_cache *cache,
size_t size,
const void *data)
{
struct v3dv_device *device = cache->device;
struct v3dv_physical_device *pdevice = &device->instance->physicalDevice;
struct vk_pipeline_cache_header header;
if (size < sizeof(header))
return;
memcpy(&header, data, sizeof(header));
if (header.header_size < sizeof(header))
return;
if (header.header_version != VK_PIPELINE_CACHE_HEADER_VERSION_ONE)
return;
if (header.vendor_id != v3dv_physical_device_vendor_id(pdevice))
return;
if (header.device_id != v3dv_physical_device_device_id(pdevice))
return;
if (memcmp(header.uuid, pdevice->pipeline_cache_uuid, VK_UUID_SIZE) != 0)
return;
/* FIXME: at this point we only verify the header but we dont really load
* any data. pending to implement serialize/deserialize among other things.
*/
}
VkResult
v3dv_CreatePipelineCache(VkDevice _device,
const VkPipelineCacheCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkPipelineCache *pPipelineCache)
const VkPipelineCacheCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkPipelineCache *pPipelineCache)
{
/* FIXME: stub */
V3DV_FROM_HANDLE(v3dv_device, device, _device);
struct v3dv_pipeline_cache *cache;
assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO);
assert(pCreateInfo->flags == 0);
cache = vk_alloc2(&device->alloc, pAllocator,
sizeof(*cache), 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (cache == NULL)
return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
pipeline_cache_init(cache, device);
if (pCreateInfo->initialDataSize > 0) {
pipeline_cache_load(cache,
pCreateInfo->initialDataSize,
pCreateInfo->pInitialData);
}
*pPipelineCache = v3dv_pipeline_cache_to_handle(cache);
return VK_SUCCESS;
}
@ -38,7 +100,15 @@ v3dv_DestroyPipelineCache(VkDevice _device,
VkPipelineCache _cache,
const VkAllocationCallbacks *pAllocator)
{
/* FIXME: stub */
V3DV_FROM_HANDLE(v3dv_device, device, _device);
V3DV_FROM_HANDLE(v3dv_pipeline_cache, cache, _cache);
if (!cache)
return;
pthread_mutex_destroy(&cache->mutex);
vk_free2(&device->alloc, pAllocator, cache);
}
VkResult
@ -47,15 +117,46 @@ v3dv_MergePipelineCaches(VkDevice device,
uint32_t srcCacheCount,
const VkPipelineCache *pSrcCaches)
{
unreachable("vkMergePipelineCaches not implemented.");
return VK_ERROR_UNKNOWN;
/* FIXME: at this point there are not other content that the header cache,
* so merging pipeline caches would be always successful
*/
return VK_SUCCESS;
}
VkResult
v3dv_GetPipelineCacheData(VkDevice device,
VkPipelineCache pipelineCache,
size_t *pDataSize, void *pData)
v3dv_GetPipelineCacheData(VkDevice _device,
VkPipelineCache _cache,
size_t *pDataSize,
void *pData)
{
unreachable("vkGetPipelineCacheData not implemented.");
return VK_ERROR_UNKNOWN;
V3DV_FROM_HANDLE(v3dv_device, device, _device);
V3DV_FROM_HANDLE(v3dv_pipeline_cache, cache, _cache);
struct v3dv_physical_device *pdevice = &device->instance->physicalDevice;
struct vk_pipeline_cache_header *header;
VkResult result = VK_SUCCESS;
pthread_mutex_lock(&cache->mutex);
/* FIXME: at this point the cache data is just the header */
const size_t size = sizeof(*header);
if (pData == NULL) {
pthread_mutex_unlock(&cache->mutex);
*pDataSize = size;
return VK_SUCCESS;
}
if (*pDataSize < sizeof(*header)) {
pthread_mutex_unlock(&cache->mutex);
*pDataSize = 0;
return VK_INCOMPLETE;
}
header = pData;
header->header_size = sizeof(*header);
header->header_version = VK_PIPELINE_CACHE_HEADER_VERSION_ONE;
header->vendor_id = v3dv_physical_device_vendor_id(pdevice);
header->device_id = v3dv_physical_device_device_id(pdevice);
memcpy(header->uuid, pdevice->pipeline_cache_uuid, VK_UUID_SIZE);
pthread_mutex_unlock(&cache->mutex);
return result;
}

View File

@ -261,6 +261,13 @@ struct v3dv_meta_blit_pipeline {
#define V3DV_META_BLIT_CACHE_KEY_SIZE (3 * sizeof(uint32_t))
struct v3dv_pipeline_cache {
VK_LOADER_DATA _loader_data;
struct v3dv_device *device;
mtx_t mutex;
};
struct v3dv_device {
VK_LOADER_DATA _loader_data;
@ -1782,6 +1789,7 @@ V3DV_DEFINE_NONDISP_HANDLE_CASTS(v3dv_framebuffer, VkFramebuffer)
V3DV_DEFINE_NONDISP_HANDLE_CASTS(v3dv_image, VkImage)
V3DV_DEFINE_NONDISP_HANDLE_CASTS(v3dv_image_view, VkImageView)
V3DV_DEFINE_NONDISP_HANDLE_CASTS(v3dv_pipeline, VkPipeline)
V3DV_DEFINE_NONDISP_HANDLE_CASTS(v3dv_pipeline_cache, VkPipelineCache)
V3DV_DEFINE_NONDISP_HANDLE_CASTS(v3dv_pipeline_layout, VkPipelineLayout)
V3DV_DEFINE_NONDISP_HANDLE_CASTS(v3dv_query_pool, VkQueryPool)
V3DV_DEFINE_NONDISP_HANDLE_CASTS(v3dv_render_pass, VkRenderPass)