#include "ac_nir_to_llvm.h"
struct cache_entry_variant_info {
- struct ac_shader_variant_info variant_info;
+ struct radv_shader_variant_info variant_info;
struct ac_shader_config config;
uint32_t rsrc1, rsrc2;
};
cache->hash_table = malloc(byte_size);
/* We don't consider allocation failure fatal, we just start with a 0-sized
- * cache. */
+ * cache. Disable caching when we want to keep shader debug info, since
+ * we don't get the debug info on cached shaders. */
if (cache->hash_table == NULL ||
- (device->instance->debug_flags & RADV_DEBUG_NO_CACHE))
+ (device->instance->debug_flags & RADV_DEBUG_NO_CACHE) ||
+ device->keep_shader_info)
cache->table_size = 0;
else
memset(cache->hash_table, 0, byte_size);
return entry;
}
+static void
+radv_pipeline_cache_set_entry(struct radv_pipeline_cache *cache,
+ struct cache_entry *entry)
+{
+ const uint32_t mask = cache->table_size - 1;
+ const uint32_t start = entry->sha1_dw[0];
+
+ /* We'll always be able to insert when we get here. */
+ assert(cache->kernel_count < cache->table_size / 2);
+
+ for (uint32_t i = 0; i < cache->table_size; i++) {
+ const uint32_t index = (start + i) & mask;
+ if (!cache->hash_table[index]) {
+ cache->hash_table[index] = entry;
+ break;
+ }
+ }
+
+ cache->total_size += entry_size(entry);
+ cache->kernel_count++;
+}
+
+
+static VkResult
+radv_pipeline_cache_grow(struct radv_pipeline_cache *cache)
+{
+ const uint32_t table_size = cache->table_size * 2;
+ const uint32_t old_table_size = cache->table_size;
+ const size_t byte_size = table_size * sizeof(cache->hash_table[0]);
+ struct cache_entry **table;
+ struct cache_entry **old_table = cache->hash_table;
+
+ table = malloc(byte_size);
+ if (table == NULL)
+ return vk_error(cache->device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ cache->hash_table = table;
+ cache->table_size = table_size;
+ cache->kernel_count = 0;
+ cache->total_size = 0;
+
+ memset(cache->hash_table, 0, byte_size);
+ for (uint32_t i = 0; i < old_table_size; i++) {
+ struct cache_entry *entry = old_table[i];
+ if (!entry)
+ continue;
+
+ radv_pipeline_cache_set_entry(cache, entry);
+ }
+
+ free(old_table);
+
+ return VK_SUCCESS;
+}
+
+static void
+radv_pipeline_cache_add_entry(struct radv_pipeline_cache *cache,
+ struct cache_entry *entry)
+{
+ if (cache->kernel_count == cache->table_size / 2)
+ radv_pipeline_cache_grow(cache);
+
+ /* Failing to grow that hash table isn't fatal, but may mean we don't
+ * have enough space to add this new kernel. Only add it if there's room.
+ */
+ if (cache->kernel_count < cache->table_size / 2)
+ radv_pipeline_cache_set_entry(cache, entry);
+}
+
+static bool
+radv_is_cache_disabled(struct radv_device *device)
+{
+ /* Pipeline caches can be disabled with RADV_DEBUG=nocache, with
+ * MESA_GLSL_CACHE_DISABLE=1, and when VK_AMD_shader_info is requested.
+ */
+ return (device->instance->debug_flags & RADV_DEBUG_NO_CACHE) ||
+ device->keep_shader_info;
+}
+
bool
radv_create_shader_variants_from_pipeline_cache(struct radv_device *device,
struct radv_pipeline_cache *cache,
const unsigned char *sha1,
- struct radv_shader_variant **variants)
+ struct radv_shader_variant **variants,
+ bool *found_in_application_cache)
{
struct cache_entry *entry;
- if (!cache)
+ if (!cache) {
cache = device->mem_cache;
+ *found_in_application_cache = false;
+ }
pthread_mutex_lock(&cache->mutex);
entry = radv_pipeline_cache_search_unlocked(cache, sha1);
if (!entry) {
- if (!device->physical_device->disk_cache ||
- (device->instance->debug_flags & RADV_DEBUG_NO_CACHE)) {
+ *found_in_application_cache = false;
+
+ /* Don't cache when we want debug info, since this isn't
+ * present in the cache.
+ */
+ if (radv_is_cache_disabled(device) || !device->physical_device->disk_cache) {
pthread_mutex_unlock(&cache->mutex);
return false;
}
if (!entry) {
pthread_mutex_unlock(&cache->mutex);
return false;
+ } else {
+ size_t size = entry_size(entry);
+ struct cache_entry *new_entry = vk_alloc(&cache->alloc, size, 8,
+ VK_SYSTEM_ALLOCATION_SCOPE_CACHE);
+ if (!new_entry) {
+ free(entry);
+ pthread_mutex_unlock(&cache->mutex);
+ return false;
+ }
+
+ memcpy(new_entry, entry, entry_size(entry));
+ free(entry);
+ entry = new_entry;
+
+ radv_pipeline_cache_add_entry(cache, new_entry);
}
}
return true;
}
-
-static void
-radv_pipeline_cache_set_entry(struct radv_pipeline_cache *cache,
- struct cache_entry *entry)
-{
- const uint32_t mask = cache->table_size - 1;
- const uint32_t start = entry->sha1_dw[0];
-
- /* We'll always be able to insert when we get here. */
- assert(cache->kernel_count < cache->table_size / 2);
-
- for (uint32_t i = 0; i < cache->table_size; i++) {
- const uint32_t index = (start + i) & mask;
- if (!cache->hash_table[index]) {
- cache->hash_table[index] = entry;
- break;
- }
- }
-
- cache->total_size += entry_size(entry);
- cache->kernel_count++;
-}
-
-
-static VkResult
-radv_pipeline_cache_grow(struct radv_pipeline_cache *cache)
-{
- const uint32_t table_size = cache->table_size * 2;
- const uint32_t old_table_size = cache->table_size;
- const size_t byte_size = table_size * sizeof(cache->hash_table[0]);
- struct cache_entry **table;
- struct cache_entry **old_table = cache->hash_table;
-
- table = malloc(byte_size);
- if (table == NULL)
- return VK_ERROR_OUT_OF_HOST_MEMORY;
-
- cache->hash_table = table;
- cache->table_size = table_size;
- cache->kernel_count = 0;
- cache->total_size = 0;
-
- memset(cache->hash_table, 0, byte_size);
- for (uint32_t i = 0; i < old_table_size; i++) {
- struct cache_entry *entry = old_table[i];
- if (!entry)
- continue;
-
- radv_pipeline_cache_set_entry(cache, entry);
- }
-
- free(old_table);
-
- return VK_SUCCESS;
-}
-
-static void
-radv_pipeline_cache_add_entry(struct radv_pipeline_cache *cache,
- struct cache_entry *entry)
-{
- if (cache->kernel_count == cache->table_size / 2)
- radv_pipeline_cache_grow(cache);
-
- /* Failing to grow that hash table isn't fatal, but may mean we don't
- * have enough space to add this new kernel. Only add it if there's room.
- */
- if (cache->kernel_count < cache->table_size / 2)
- radv_pipeline_cache_set_entry(cache, entry);
-}
-
void
radv_pipeline_cache_insert_shaders(struct radv_device *device,
struct radv_pipeline_cache *cache,
pthread_mutex_unlock(&cache->mutex);
return;
}
+
+ /* Don't cache when we want debug info, since this isn't
+ * present in the cache.
+ */
+ if (radv_is_cache_disabled(device)) {
+ pthread_mutex_unlock(&cache->mutex);
+ return;
+ }
+
size_t size = sizeof(*entry);
for (int i = 0; i < MESA_SHADER_STAGES; ++i)
if (variants[i])
char* p = entry->code;
struct cache_entry_variant_info info;
+ memset(&info, 0, sizeof(info));
for (int i = 0; i < MESA_SHADER_STAGES; ++i) {
if (!variants[i])
uint8_t uuid[VK_UUID_SIZE];
};
-void
+bool
radv_pipeline_cache_load(struct radv_pipeline_cache *cache,
const void *data, size_t size)
{
struct cache_header header;
if (size < sizeof(header))
- return;
+ return false;
memcpy(&header, data, sizeof(header));
if (header.header_size < sizeof(header))
- return;
+ return false;
if (header.header_version != VK_PIPELINE_CACHE_HEADER_VERSION_ONE)
- return;
+ return false;
if (header.vendor_id != ATI_VENDOR_ID)
- return;
+ return false;
if (header.device_id != device->physical_device->rad_info.pci_id)
- return;
+ return false;
if (memcmp(header.uuid, device->physical_device->cache_uuid, VK_UUID_SIZE) != 0)
- return;
+ return false;
char *end = (void *) data + size;
char *p = (void *) data + header.header_size;
}
p += size;
}
+
+ return true;
}
VkResult radv_CreatePipelineCache(
sizeof(*cache), 8,
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (cache == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+ return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
if (pAllocator)
cache->alloc = *pAllocator;