diff --git a/src/amd/vulkan/radv_pipeline_cache.c b/src/amd/vulkan/radv_pipeline_cache.c index 58f62f53594..367bccfa3b9 100644 --- a/src/amd/vulkan/radv_pipeline_cache.c +++ b/src/amd/vulkan/radv_pipeline_cache.c @@ -155,7 +155,8 @@ radv_shader_deserialize(struct vk_pipeline_cache *cache, const void *key_data, s const struct radv_shader_binary *binary = blob_read_bytes(blob, sizeof(struct radv_shader_binary)); assert(key_size == SHA1_DIGEST_LENGTH); - struct radv_shader *shader = radv_shader_create_uncached(device, binary); + struct radv_shader *shader; + radv_shader_create_uncached(device, binary, false, NULL, &shader); if (!shader) return NULL; @@ -199,8 +200,11 @@ struct radv_shader * radv_shader_create(struct radv_device *device, struct vk_pipeline_cache *cache, const struct radv_shader_binary *binary, bool skip_cache) { - if (radv_is_cache_disabled(device) || skip_cache) - return radv_shader_create_uncached(device, binary); + if (radv_is_cache_disabled(device) || skip_cache) { + struct radv_shader *shader; + radv_shader_create_uncached(device, binary, false, NULL, &shader); + return shader; + } if (!cache) cache = device->mem_cache; diff --git a/src/amd/vulkan/radv_shader.c b/src/amd/vulkan/radv_shader.c index f5c483c80ec..2db93b26b42 100644 --- a/src/amd/vulkan/radv_shader.c +++ b/src/amd/vulkan/radv_shader.c @@ -2026,12 +2026,17 @@ radv_shader_upload(struct radv_device *device, struct radv_shader *shader, const return true; } -struct radv_shader * -radv_shader_create_uncached(struct radv_device *device, const struct radv_shader_binary *binary) +VkResult +radv_shader_create_uncached(struct radv_device *device, const struct radv_shader_binary *binary, bool replayable, + struct radv_serialized_shader_arena_block *replay_block, struct radv_shader **out_shader) { + VkResult result = VK_SUCCESS; struct radv_shader *shader = calloc(1, sizeof(struct radv_shader)); - if (!shader) - goto fail; + if (!shader) { + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + simple_mtx_init(&shader->replay_mtx, mtx_plain); vk_pipeline_cache_object_init(&device->vk, &shader->base, &radv_shader_ops, shader->sha1, SHA1_DIGEST_LENGTH); @@ -2047,7 +2052,8 @@ radv_shader_create_uncached(struct radv_device *device, const struct radv_shader struct ac_rtld_binary rtld_binary = {0}; if (!radv_open_rtld_binary(device, binary, &rtld_binary)) { - goto fail; + result = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; } shader->code_size = rtld_binary.rx_size; @@ -2066,21 +2072,39 @@ radv_shader_create_uncached(struct radv_device *device, const struct radv_shader } } - shader->alloc = radv_alloc_shader_memory(device, shader->code_size, false, shader); - if (!shader->alloc) - goto fail; + if (replay_block) { + shader->alloc = radv_replay_shader_arena_block(device, replay_block, shader); + if (!shader->alloc) { + result = VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS; + goto out; + } + + shader->has_replay_alloc = true; + } else { + shader->alloc = radv_alloc_shader_memory(device, shader->code_size, replayable, shader); + if (!shader->alloc) { + result = VK_ERROR_OUT_OF_DEVICE_MEMORY; + goto out; + } + } shader->bo = shader->alloc->arena->bo; shader->va = radv_buffer_get_va(shader->bo) + shader->alloc->offset; - if (!radv_shader_upload(device, shader, binary)) - goto fail; + if (!radv_shader_upload(device, shader, binary)) { + result = VK_ERROR_OUT_OF_DEVICE_MEMORY; + goto out; + } - return shader; + *out_shader = shader; -fail: - free(shader); - return NULL; +out: + if (result != VK_SUCCESS) { + free(shader); + *out_shader = NULL; + } + + return result; } bool @@ -2398,7 +2422,8 @@ radv_create_trap_handler_shader(struct radv_device *device) radv_declare_shader_args(device, &key, &info, stage, MESA_SHADER_NONE, &args); struct radv_shader_binary *binary = shader_compile(device, &b.shader, 1, stage, &info, &args, &options); - struct radv_shader *shader = radv_shader_create_uncached(device, binary); + struct radv_shader *shader; + radv_shader_create_uncached(device, binary, false, NULL, &shader); ralloc_free(b.shader); free(binary); @@ -2478,7 +2503,7 @@ radv_create_rt_prolog(struct radv_device *device) binary->info = info; radv_postprocess_binary_config(device, binary, &in_args); - prolog = radv_shader_create_uncached(device, binary); + radv_shader_create_uncached(device, binary, false, NULL, &prolog); if (!prolog) goto done; diff --git a/src/amd/vulkan/radv_shader.h b/src/amd/vulkan/radv_shader.h index b566f1bb188..328ed7bcdb9 100644 --- a/src/amd/vulkan/radv_shader.h +++ b/src/amd/vulkan/radv_shader.h @@ -552,6 +552,9 @@ union radv_shader_arena_block { struct radv_shader { struct vk_pipeline_cache_object base; + simple_mtx_t replay_mtx; + bool has_replay_alloc; + struct radeon_winsys_bo *bo; union radv_shader_arena_block *alloc; uint64_t va; @@ -624,7 +627,9 @@ struct radv_shader_args; struct radv_shader *radv_shader_create(struct radv_device *device, struct vk_pipeline_cache *cache, const struct radv_shader_binary *binary, bool skip_cache); -struct radv_shader *radv_shader_create_uncached(struct radv_device *device, const struct radv_shader_binary *binary); +VkResult radv_shader_create_uncached(struct radv_device *device, const struct radv_shader_binary *binary, + bool replayable, struct radv_serialized_shader_arena_block *replay_block, + struct radv_shader **out_shader); struct radv_shader_binary *radv_shader_nir_to_asm(struct radv_device *device, struct radv_pipeline_stage *pl_stage, struct nir_shader *const *shaders, int shader_count,