diff --git a/.pick_status.json b/.pick_status.json index ee2192f2c10..99925b320bc 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -4424,7 +4424,7 @@ "description": "anv: don't relocate memory from blob", "nominated": true, "nomination_type": 2, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "d39e443ef888ffd9c3385ed4c40e727868626b6b", "notes": null diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 2da159a3fa4..1bc7bf6cce0 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -1301,6 +1301,12 @@ void anv_shader_heap_upload(struct anv_shader_heap *heap, struct anv_shader { struct vk_shader vk; + /** + * Code of the shader on the host + * + * This is before relocations are applied so that can always return the + * same blob of data for serialization. + */ void *code; struct anv_shader_alloc kernel; diff --git a/src/intel/vulkan/anv_shader.c b/src/intel/vulkan/anv_shader.c index 8e24c1378c0..8f887e8e706 100644 --- a/src/intel/vulkan/anv_shader.c +++ b/src/intel/vulkan/anv_shader.c @@ -519,35 +519,59 @@ anv_shader_set_relocs(struct anv_device *device, return rv_count; } +struct anv_shader_reloc { + struct anv_device *device; + const VkAllocationCallbacks *alloc; + const void *in_code; + uint32_t *code_size; + + void *relocated_code; +}; + static VkResult -anv_shader_reloc(struct anv_device *device, - void *code, - struct anv_shader *shader, - const VkAllocationCallbacks *pAllocator) +anv_shader_reloc_begin(struct anv_shader_reloc *reloc, + struct anv_device *device, + const void *in_code, + struct anv_shader *shader, + const VkAllocationCallbacks *alloc) { + memset(reloc, 0, sizeof(*reloc)); + reloc->device = device; + reloc->alloc = alloc; + const uint32_t max_relocs = BRW_SHADER_RELOC_EMBEDDED_SAMPLER_HANDLE + shader->bind_map.embedded_sampler_count; - uint32_t rv_count; - struct intel_shader_reloc_value *reloc_values = - vk_zalloc2(&device->vk.alloc, pAllocator, - sizeof(struct intel_shader_reloc_value) * max_relocs, 8, - VK_SYSTEM_ALLOCATION_SCOPE_COMMAND); - if (reloc_values == NULL) + VK_MULTIALLOC(ma); + VK_MULTIALLOC_DECL_SIZE(&ma, void, code, shader->prog_data->program_size); + VK_MULTIALLOC_DECL(&ma, struct intel_shader_reloc_value, reloc_values, max_relocs); + + if (!vk_multialloc_zalloc2(&ma, &device->vk.alloc, alloc, + VK_SYSTEM_ALLOCATION_SCOPE_DEVICE)) return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); - rv_count = anv_shader_set_relocs(device, reloc_values, shader); + /* Make a copy of the code to relocate it, we don't know where the data + * comes from, could be read-only, could app-managed, ... + */ + reloc->relocated_code = code; + memcpy(reloc->relocated_code, in_code, shader->prog_data->program_size); + + uint32_t rv_count = anv_shader_set_relocs(device, reloc_values, shader); assert(rv_count <= max_relocs); brw_write_shader_relocs(&device->physical->compiler->isa, - code, shader->prog_data, + reloc->relocated_code, shader->prog_data, reloc_values, rv_count); - vk_free2(&device->vk.alloc, pAllocator, reloc_values); - return VK_SUCCESS; } +static void +anv_shader_reloc_end(struct anv_shader_reloc *reloc) +{ + vk_free2(&reloc->device->vk.alloc, reloc->alloc, reloc->relocated_code); +} + struct internal_representation { char *nir_str; uint32_t nir_str_len; @@ -681,14 +705,19 @@ anv_shader_create(struct anv_device *device, shader->instance_multiplier = shader_data->instance_multiplier; - result = anv_shader_reloc(device, shader_data->code, shader, pAllocator); + struct anv_shader_reloc reloc; + result = anv_shader_reloc_begin(&reloc, device, shader_data->code, + shader, pAllocator); if (result != VK_SUCCESS) goto error_state; anv_shader_heap_upload(&device->shader_heap, - shader->kernel, shader_data->code, + shader->kernel, + reloc.relocated_code, shader_data->prog_data.base.program_size); + anv_shader_reloc_end(&reloc); + if (mesa_shader_stage_is_rt(shader->vk.stage)) { const struct brw_bs_prog_data *bs_prog_data = (const struct brw_bs_prog_data *)shader->prog_data;