aboutsummaryrefslogtreecommitdiffstats
path: root/src/intel/vulkan/anv_pipeline.c
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2016-08-25 01:49:49 -0700
committerJason Ekstrand <[email protected]>2016-08-30 15:08:23 -0700
commit10f9901bcef7724cb72fb2fe7e3dd8d6660d2f34 (patch)
tree007712bd01daea07fe9389b2aad6de234d45df77 /src/intel/vulkan/anv_pipeline.c
parent689971847005219178f5a484dffecf9e5e515192 (diff)
anv: Rework pipeline caching
The original pipeline cache the Kristian wrote was based on a now-false premise that the shaders can be stored in the pipeline cache. The Vulkan 1.0 spec explicitly states that the pipeline cache object is transiant and you are allowed to delete it after using it to create a pipeline with no ill effects. As nice as Kristian's design was, it doesn't jive with the expectation provided by the Vulkan spec. The new pipeline cache uses reference-counted anv_shader_bin objects that are backed by a large state pool. The cache itself is just a hash table mapping keys hashes to anv_shader_bin objects. This has the added advantage of removing one more hand-rolled hash table from mesa. Signed-off-by: Jason Ekstrand <[email protected]> Cc: "12.0" <[email protected]> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=97476 Acked-by: Kristian Høgsberg Kristensen <[email protected]>
Diffstat (limited to 'src/intel/vulkan/anv_pipeline.c')
-rw-r--r--src/intel/vulkan/anv_pipeline.c161
1 files changed, 91 insertions, 70 deletions
diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c
index e6afdc1a4b3..52ab7d0bf2d 100644
--- a/src/intel/vulkan/anv_pipeline.c
+++ b/src/intel/vulkan/anv_pipeline.c
@@ -205,6 +205,12 @@ void anv_DestroyPipeline(
pAllocator ? pAllocator : &device->alloc);
if (pipeline->blend_state.map)
anv_state_pool_free(&device->dynamic_state_pool, pipeline->blend_state);
+
+ for (unsigned s = 0; s < MESA_SHADER_STAGES; s++) {
+ if (pipeline->shaders[s])
+ anv_shader_bin_unref(device, pipeline->shaders[s]);
+ }
+
anv_free2(&device->alloc, pAllocator, pipeline);
}
@@ -394,15 +400,34 @@ anv_fill_binding_table(struct brw_stage_prog_data *prog_data, unsigned bias)
prog_data->binding_table.image_start = bias;
}
+static struct anv_shader_bin *
+anv_pipeline_upload_kernel(struct anv_pipeline *pipeline,
+ struct anv_pipeline_cache *cache,
+ const void *key_data, uint32_t key_size,
+ const void *kernel_data, uint32_t kernel_size,
+ const void *prog_data, uint32_t prog_data_size,
+ const struct anv_pipeline_bind_map *bind_map)
+{
+ if (cache) {
+ return anv_pipeline_cache_upload_kernel(cache, key_data, key_size,
+ kernel_data, kernel_size,
+ prog_data, prog_data_size,
+ bind_map);
+ } else {
+ return anv_shader_bin_create(pipeline->device, key_data, key_size,
+ kernel_data, kernel_size,
+ prog_data, prog_data_size, bind_map);
+ }
+}
+
+
static void
anv_pipeline_add_compiled_stage(struct anv_pipeline *pipeline,
gl_shader_stage stage,
- const struct brw_stage_prog_data *prog_data,
- struct anv_pipeline_bind_map *map)
+ struct anv_shader_bin *shader)
{
- pipeline->prog_data[stage] = prog_data;
+ pipeline->shaders[stage] = shader;
pipeline->active_stages |= mesa_to_vk_shader_stage(stage);
- pipeline->bindings[stage] = *map;
}
static VkResult
@@ -415,21 +440,20 @@ anv_pipeline_compile_vs(struct anv_pipeline *pipeline,
{
const struct brw_compiler *compiler =
pipeline->device->instance->physicalDevice.compiler;
- const struct brw_stage_prog_data *stage_prog_data;
struct anv_pipeline_bind_map map;
struct brw_vs_prog_key key;
- uint32_t kernel = NO_KERNEL;
+ struct anv_shader_bin *bin = NULL;
unsigned char sha1[20];
populate_vs_prog_key(&pipeline->device->info, &key);
- if (module->size > 0) {
+ if (cache) {
anv_hash_shader(sha1, &key, sizeof(key), module, entrypoint,
pipeline->layout, spec_info);
- kernel = anv_pipeline_cache_search(cache, sha1, &stage_prog_data, &map);
+ bin = anv_pipeline_cache_search(cache, sha1, 20);
}
- if (kernel == NO_KERNEL) {
+ if (bin == NULL) {
struct brw_vs_prog_data prog_data = { 0, };
struct anv_pipeline_binding surface_to_descriptor[256];
struct anv_pipeline_binding sampler_to_descriptor[256];
@@ -468,28 +492,29 @@ anv_pipeline_compile_vs(struct anv_pipeline *pipeline,
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
}
- stage_prog_data = &prog_data.base.base;
- kernel = anv_pipeline_cache_upload_kernel(cache,
- module->size > 0 ? sha1 : NULL,
- shader_code, code_size,
- &stage_prog_data, sizeof(prog_data),
- &map);
+ bin = anv_pipeline_upload_kernel(pipeline, cache, sha1, 20,
+ shader_code, code_size,
+ &prog_data, sizeof(prog_data), &map);
+ if (!bin) {
+ ralloc_free(mem_ctx);
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+ }
+
ralloc_free(mem_ctx);
}
const struct brw_vs_prog_data *vs_prog_data =
- (const struct brw_vs_prog_data *) stage_prog_data;
+ (const struct brw_vs_prog_data *)anv_shader_bin_get_prog_data(bin);
if (vs_prog_data->base.dispatch_mode == DISPATCH_MODE_SIMD8) {
- pipeline->vs_simd8 = kernel;
+ pipeline->vs_simd8 = bin->kernel.offset;
pipeline->vs_vec4 = NO_KERNEL;
} else {
pipeline->vs_simd8 = NO_KERNEL;
- pipeline->vs_vec4 = kernel;
+ pipeline->vs_vec4 = bin->kernel.offset;
}
- anv_pipeline_add_compiled_stage(pipeline, MESA_SHADER_VERTEX,
- stage_prog_data, &map);
+ anv_pipeline_add_compiled_stage(pipeline, MESA_SHADER_VERTEX, bin);
return VK_SUCCESS;
}
@@ -504,21 +529,20 @@ anv_pipeline_compile_gs(struct anv_pipeline *pipeline,
{
const struct brw_compiler *compiler =
pipeline->device->instance->physicalDevice.compiler;
- const struct brw_stage_prog_data *stage_prog_data;
struct anv_pipeline_bind_map map;
struct brw_gs_prog_key key;
- uint32_t kernel = NO_KERNEL;
+ struct anv_shader_bin *bin = NULL;
unsigned char sha1[20];
populate_gs_prog_key(&pipeline->device->info, &key);
- if (module->size > 0) {
+ if (cache) {
anv_hash_shader(sha1, &key, sizeof(key), module, entrypoint,
pipeline->layout, spec_info);
- kernel = anv_pipeline_cache_search(cache, sha1, &stage_prog_data, &map);
+ bin = anv_pipeline_cache_search(cache, sha1, 20);
}
- if (kernel == NO_KERNEL) {
+ if (bin == NULL) {
struct brw_gs_prog_data prog_data = { 0, };
struct anv_pipeline_binding surface_to_descriptor[256];
struct anv_pipeline_binding sampler_to_descriptor[256];
@@ -556,20 +580,20 @@ anv_pipeline_compile_gs(struct anv_pipeline *pipeline,
}
/* TODO: SIMD8 GS */
- stage_prog_data = &prog_data.base.base;
- kernel = anv_pipeline_cache_upload_kernel(cache,
- module->size > 0 ? sha1 : NULL,
- shader_code, code_size,
- &stage_prog_data, sizeof(prog_data),
- &map);
+ bin = anv_pipeline_upload_kernel(pipeline, cache, sha1, 20,
+ shader_code, code_size,
+ &prog_data, sizeof(prog_data), &map);
+ if (!bin) {
+ ralloc_free(mem_ctx);
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+ }
ralloc_free(mem_ctx);
}
- pipeline->gs_kernel = kernel;
+ pipeline->gs_kernel = bin->kernel.offset;
- anv_pipeline_add_compiled_stage(pipeline, MESA_SHADER_GEOMETRY,
- stage_prog_data, &map);
+ anv_pipeline_add_compiled_stage(pipeline, MESA_SHADER_GEOMETRY, bin);
return VK_SUCCESS;
}
@@ -585,21 +609,20 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,
{
const struct brw_compiler *compiler =
pipeline->device->instance->physicalDevice.compiler;
- const struct brw_stage_prog_data *stage_prog_data;
struct anv_pipeline_bind_map map;
struct brw_wm_prog_key key;
+ struct anv_shader_bin *bin = NULL;
unsigned char sha1[20];
populate_wm_prog_key(&pipeline->device->info, info, extra, &key);
- if (module->size > 0) {
+ if (cache) {
anv_hash_shader(sha1, &key, sizeof(key), module, entrypoint,
pipeline->layout, spec_info);
- pipeline->ps_ksp0 =
- anv_pipeline_cache_search(cache, sha1, &stage_prog_data, &map);
+ bin = anv_pipeline_cache_search(cache, sha1, 20);
}
- if (pipeline->ps_ksp0 == NO_KERNEL) {
+ if (bin == NULL) {
struct brw_wm_prog_data prog_data = { 0, };
struct anv_pipeline_binding surface_to_descriptor[256];
struct anv_pipeline_binding sampler_to_descriptor[256];
@@ -688,19 +711,20 @@ anv_pipeline_compile_fs(struct anv_pipeline *pipeline,
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
}
- stage_prog_data = &prog_data.base;
- pipeline->ps_ksp0 =
- anv_pipeline_cache_upload_kernel(cache,
- module->size > 0 ? sha1 : NULL,
- shader_code, code_size,
- &stage_prog_data, sizeof(prog_data),
- &map);
+ bin = anv_pipeline_upload_kernel(pipeline, cache, sha1, 20,
+ shader_code, code_size,
+ &prog_data, sizeof(prog_data), &map);
+ if (!bin) {
+ ralloc_free(mem_ctx);
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+ }
ralloc_free(mem_ctx);
}
- anv_pipeline_add_compiled_stage(pipeline, MESA_SHADER_FRAGMENT,
- stage_prog_data, &map);
+ pipeline->ps_ksp0 = bin->kernel.offset;
+
+ anv_pipeline_add_compiled_stage(pipeline, MESA_SHADER_FRAGMENT, bin);
return VK_SUCCESS;
}
@@ -715,21 +739,20 @@ anv_pipeline_compile_cs(struct anv_pipeline *pipeline,
{
const struct brw_compiler *compiler =
pipeline->device->instance->physicalDevice.compiler;
- const struct brw_stage_prog_data *stage_prog_data;
struct anv_pipeline_bind_map map;
struct brw_cs_prog_key key;
- uint32_t kernel = NO_KERNEL;
+ struct anv_shader_bin *bin = NULL;
unsigned char sha1[20];
populate_cs_prog_key(&pipeline->device->info, &key);
- if (module->size > 0) {
+ if (cache) {
anv_hash_shader(sha1, &key, sizeof(key), module, entrypoint,
pipeline->layout, spec_info);
- kernel = anv_pipeline_cache_search(cache, sha1, &stage_prog_data, &map);
+ bin = anv_pipeline_cache_search(cache, sha1, 20);
}
- if (module->size == 0 || kernel == NO_KERNEL) {
+ if (bin == NULL) {
struct brw_cs_prog_data prog_data = { 0, };
struct anv_pipeline_binding surface_to_descriptor[256];
struct anv_pipeline_binding sampler_to_descriptor[256];
@@ -761,20 +784,20 @@ anv_pipeline_compile_cs(struct anv_pipeline *pipeline,
return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
}
- stage_prog_data = &prog_data.base;
- kernel = anv_pipeline_cache_upload_kernel(cache,
- module->size > 0 ? sha1 : NULL,
- shader_code, code_size,
- &stage_prog_data, sizeof(prog_data),
- &map);
+ bin = anv_pipeline_upload_kernel(pipeline, cache, sha1, 20,
+ shader_code, code_size,
+ &prog_data, sizeof(prog_data), &map);
+ if (!bin) {
+ ralloc_free(mem_ctx);
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+ }
ralloc_free(mem_ctx);
}
- pipeline->cs_simd = kernel;
+ pipeline->cs_simd = bin->kernel.offset;
- anv_pipeline_add_compiled_stage(pipeline, MESA_SHADER_COMPUTE,
- stage_prog_data, &map);
+ anv_pipeline_add_compiled_stage(pipeline, MESA_SHADER_COMPUTE, bin);
return VK_SUCCESS;
}
@@ -1168,8 +1191,7 @@ anv_pipeline_init(struct anv_pipeline *pipeline,
/* When we free the pipeline, we detect stages based on the NULL status
* of various prog_data pointers. Make them NULL by default.
*/
- memset(pipeline->prog_data, 0, sizeof(pipeline->prog_data));
- memset(pipeline->bindings, 0, sizeof(pipeline->bindings));
+ memset(pipeline->shaders, 0, sizeof(pipeline->shaders));
pipeline->vs_simd8 = NO_KERNEL;
pipeline->vs_vec4 = NO_KERNEL;
@@ -1278,6 +1300,11 @@ anv_pipeline_init(struct anv_pipeline *pipeline,
return VK_SUCCESS;
compile_fail:
+ for (unsigned s = 0; s < MESA_SHADER_STAGES; s++) {
+ if (pipeline->shaders[s])
+ anv_shader_bin_unref(device, pipeline->shaders[s]);
+ }
+
anv_reloc_list_finish(&pipeline->batch_relocs, alloc);
return result;
@@ -1295,9 +1322,6 @@ anv_graphics_pipeline_create(
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_pipeline_cache, cache, _cache);
- if (cache == NULL)
- cache = &device->default_pipeline_cache;
-
switch (device->info.gen) {
case 7:
if (device->info.is_haswell)
@@ -1351,9 +1375,6 @@ static VkResult anv_compute_pipeline_create(
ANV_FROM_HANDLE(anv_device, device, _device);
ANV_FROM_HANDLE(anv_pipeline_cache, cache, _cache);
- if (cache == NULL)
- cache = &device->default_pipeline_cache;
-
switch (device->info.gen) {
case 7:
if (device->info.is_haswell)