cache: Attempt to use disk cache instead when appropriate.

When the disk cache is used, the cache we give back to applications is a
dummy. Therefore, try to use the disk cache blob if we detect a useless
application blob.

Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no>
This commit is contained in:
Hans-Kristian Arntzen 2022-03-11 16:48:23 +01:00
parent 6c8542f7d6
commit ae0dafa3a1
3 changed files with 63 additions and 4 deletions

View File

@ -299,8 +299,8 @@ static bool vkd3d_serialized_pipeline_stream_entry_validate(const uint8_t *data,
return checksum == entry->checksum;
}
static const struct vkd3d_pipeline_blob_chunk *find_blob_chunk(const struct vkd3d_pipeline_blob_chunk *chunk,
size_t size, uint32_t type)
static const struct vkd3d_pipeline_blob_chunk *find_blob_chunk_masked(const struct vkd3d_pipeline_blob_chunk *chunk,
size_t size, uint32_t type, uint32_t mask)
{
uint32_t aligned_chunk_size;
@ -310,7 +310,7 @@ static const struct vkd3d_pipeline_blob_chunk *find_blob_chunk(const struct vkd3
VKD3D_PIPELINE_BLOB_CHUNK_ALIGN);
if (aligned_chunk_size > size)
return NULL;
if (chunk->type == type)
if ((chunk->type & mask) == type)
return chunk;
chunk = (const struct vkd3d_pipeline_blob_chunk *)&chunk->data[align(chunk->size, VKD3D_PIPELINE_BLOB_CHUNK_ALIGN)];
@ -320,6 +320,12 @@ static const struct vkd3d_pipeline_blob_chunk *find_blob_chunk(const struct vkd3
return NULL;
}
static const struct vkd3d_pipeline_blob_chunk *find_blob_chunk(const struct vkd3d_pipeline_blob_chunk *chunk,
size_t size, uint32_t type)
{
return find_blob_chunk_masked(chunk, size, type, ~0u);
}
static uint32_t d3d12_cached_pipeline_state_to_flags(const struct d3d12_cached_pipeline_state *state)
{
uint32_t pipeline_library_flags;
@ -435,6 +441,41 @@ HRESULT d3d12_cached_pipeline_state_validate(struct d3d12_device *device,
return S_OK;
}
bool d3d12_cached_pipeline_state_is_dummy(const struct d3d12_cached_pipeline_state *state)
{
const struct vkd3d_pipeline_blob *blob = state->blob.pCachedBlob;
const struct vkd3d_pipeline_blob_chunk *chunk;
size_t payload_size;
if (!state->blob.CachedBlobSizeInBytes)
return true;
if (state->blob.CachedBlobSizeInBytes < sizeof(*blob) || blob->version != VKD3D_CACHE_BLOB_VERSION)
return true;
payload_size = state->blob.CachedBlobSizeInBytes - offsetof(struct vkd3d_pipeline_blob, data);
chunk = CONST_CAST_CHUNK_BASE(blob);
/* Try to find any PSO cache or SPIR-V entry. If they exist, this is not a dummy blob. */
if (find_blob_chunk(chunk, payload_size, VKD3D_PIPELINE_BLOB_CHUNK_TYPE_PIPELINE_CACHE))
return false;
if (find_blob_chunk(chunk, payload_size, VKD3D_PIPELINE_BLOB_CHUNK_TYPE_PIPELINE_CACHE_LINK))
return false;
if (find_blob_chunk_masked(chunk, payload_size,
VKD3D_PIPELINE_BLOB_CHUNK_TYPE_VARINT_SPIRV,
VKD3D_PIPELINE_BLOB_CHUNK_TYPE_MASK))
return false;
if (find_blob_chunk_masked(chunk, payload_size,
VKD3D_PIPELINE_BLOB_CHUNK_TYPE_VARINT_SPIRV_LINK,
VKD3D_PIPELINE_BLOB_CHUNK_TYPE_MASK))
return false;
return true;
}
static struct vkd3d_pipeline_blob_chunk *finish_and_iterate_blob_chunk(struct vkd3d_pipeline_blob_chunk *chunk)
{
uint32_t aligned_size = align(chunk->size, VKD3D_PIPELINE_BLOB_CHUNK_ALIGN);

View File

@ -3694,7 +3694,17 @@ HRESULT d3d12_pipeline_state_create(struct d3d12_device *device, VkPipelineBindP
return hr;
}
}
else if (device->disk_cache.library)
/* If we rely on internal shader cache, the PSO blob app provides us might be a pure metadata blob,
* and therefore kinda useless. Try to use disk cache blob instead.
* Also, consider that we might have to serialize this pipeline if we don't find anything in disk cache. */
if (d3d12_cached_pipeline_state_is_dummy(&desc->cached_pso))
{
memset(&cached_pso, 0, sizeof(cached_pso));
desc_cached_pso = &cached_pso;
}
if (desc_cached_pso->blob.CachedBlobSizeInBytes == 0 && device->disk_cache.library)
{
if (SUCCEEDED(vkd3d_pipeline_library_find_cached_blob_from_disk_cache(&device->disk_cache,
&object->pipeline_cache_compat, &cached_pso)))
@ -3704,7 +3714,14 @@ HRESULT d3d12_pipeline_state_create(struct d3d12_device *device, VkPipelineBindP
* However, unlike app-proved blob, it's not fatal if we fail, so just fall back. */
if (SUCCEEDED(hr = d3d12_cached_pipeline_state_validate(device, &cached_pso,
&object->pipeline_cache_compat)))
{
if ((vkd3d_config_flags & VKD3D_CONFIG_FLAG_PIPELINE_LIBRARY_LOG) &&
desc->cached_pso.blob.CachedBlobSizeInBytes)
{
INFO("Application provided cached PSO blob, but we opted for disk cache blob instead.\n");
}
desc_cached_pso = &cached_pso;
}
else
FIXME("Failed to validate internal pipeline which was fetched from disk cache. This should not happen.\n");
}

View File

@ -1755,6 +1755,7 @@ VkResult vkd3d_serialize_pipeline_state(struct d3d12_pipeline_library *pipeline_
HRESULT d3d12_cached_pipeline_state_validate(struct d3d12_device *device,
const struct d3d12_cached_pipeline_state *state,
const struct vkd3d_pipeline_cache_compatibility *compat);
bool d3d12_cached_pipeline_state_is_dummy(const struct d3d12_cached_pipeline_state *state);
void vkd3d_pipeline_cache_compat_from_state_desc(struct vkd3d_pipeline_cache_compatibility *compat,
const struct d3d12_pipeline_state_desc *desc);