This new anv_shader_bin struct stores the compiled kernel (as an anv_state) as well as all of the metadata that is generated at shader compile time. The storage for the kernels comes from a state pool. The struct itself is reference-counted so that it can be used by multiple pipelines at a time without fear of allocation issues.
Signed-off-by: Jason Ekstrand <ja...@jlekstrand.net> --- src/intel/vulkan/anv_device.c | 3 ++ src/intel/vulkan/anv_pipeline_cache.c | 86 +++++++++++++++++++++++++++++++++++ src/intel/vulkan/anv_private.h | 55 +++++++++++++++++++++- 3 files changed, 143 insertions(+), 1 deletion(-) diff --git a/src/intel/vulkan/anv_device.c b/src/intel/vulkan/anv_device.c index 0d79ed9..765dc6e 100644 --- a/src/intel/vulkan/anv_device.c +++ b/src/intel/vulkan/anv_device.c @@ -879,6 +879,8 @@ VkResult anv_CreateDevice( &device->dynamic_state_block_pool); anv_block_pool_init(&device->instruction_block_pool, device, 128 * 1024); + anv_state_pool_init(&device->instruction_state_pool, + &device->instruction_block_pool); anv_pipeline_cache_init(&device->default_pipeline_cache, device); anv_block_pool_init(&device->surface_state_block_pool, device, 4096); @@ -954,6 +956,7 @@ void anv_DestroyDevice( anv_bo_pool_finish(&device->batch_bo_pool); anv_state_pool_finish(&device->dynamic_state_pool); anv_block_pool_finish(&device->dynamic_state_block_pool); + anv_state_pool_finish(&device->instruction_state_pool); anv_block_pool_finish(&device->instruction_block_pool); anv_state_pool_finish(&device->surface_state_pool); anv_block_pool_finish(&device->surface_state_block_pool); diff --git a/src/intel/vulkan/anv_pipeline_cache.c b/src/intel/vulkan/anv_pipeline_cache.c index 3f111a1..a2b9d3b 100644 --- a/src/intel/vulkan/anv_pipeline_cache.c +++ b/src/intel/vulkan/anv_pipeline_cache.c @@ -25,6 +25,92 @@ #include "util/debug.h" #include "anv_private.h" +static size_t +anv_shader_bin_size(const struct anv_pipeline_bind_map *bind_map) +{ + return sizeof(struct anv_shader_bin) + + bind_map->surface_count * sizeof(struct anv_pipeline_binding) + + bind_map->sampler_count * sizeof(struct anv_pipeline_binding); +} + +struct anv_shader_bin * +anv_shader_bin_create(struct anv_device *device, + gl_shader_stage stage, + const unsigned char *src_sha1, + const void *kernel, size_t kernel_size, + const struct brw_stage_prog_data *prog_data, + const struct anv_pipeline_bind_map *bind_map) +{ + const size_t size = anv_shader_bin_size(bind_map); + + struct anv_shader_bin *shader = + anv_alloc(&device->alloc, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); + if (!shader) + return NULL; + + shader->ref_cnt = 1; + + shader->stage = stage; + + shader->kernel = + anv_state_pool_alloc(&device->instruction_state_pool, kernel_size, 64); + memcpy(shader->kernel.map, kernel, kernel_size); + shader->kernel_size = kernel_size; + + switch (stage) { + case MESA_SHADER_VERTEX: + shader->prog_data.vs = *(struct brw_vs_prog_data *)prog_data; + break; + case MESA_SHADER_GEOMETRY: + shader->prog_data.gs = *(struct brw_gs_prog_data *)prog_data; + break; + case MESA_SHADER_TESS_CTRL: + shader->prog_data.tcs = *(struct brw_tcs_prog_data *)prog_data; + break; + case MESA_SHADER_TESS_EVAL: + shader->prog_data.tes = *(struct brw_tes_prog_data *)prog_data; + break; + case MESA_SHADER_FRAGMENT: + shader->prog_data.fs = *(struct brw_wm_prog_data *)prog_data; + break; + case MESA_SHADER_COMPUTE: + shader->prog_data.cs = *(struct brw_cs_prog_data *)prog_data; + break; + default: + unreachable("Invalid shader stage"); + } + + shader->bind_map.surface_count = bind_map->surface_count; + shader->bind_map.sampler_count = bind_map->sampler_count; + shader->bind_map.image_count = bind_map->image_count; + + struct anv_pipeline_binding *bindings = shader->bindings; + + shader->bind_map.surface_to_descriptor = bindings; + typed_memcpy(shader->bind_map.surface_to_descriptor, + bind_map->surface_to_descriptor, bind_map->surface_count); + bindings += bind_map->surface_count; + + shader->bind_map.sampler_to_descriptor = bindings; + typed_memcpy(shader->bind_map.sampler_to_descriptor, + bind_map->sampler_to_descriptor, bind_map->sampler_count); + bindings += bind_map->sampler_count; + + if (src_sha1) + memcpy(shader->src_sha1, src_sha1, sizeof(shader->src_sha1)); + + return shader; +} + +void +anv_shader_bin_destroy(struct anv_device *device, + struct anv_shader_bin *shader) +{ + assert(shader->ref_cnt == 0); + anv_state_pool_free(&device->instruction_state_pool, shader->kernel); + anv_free(&device->alloc, shader); +} + /* Remaining work: * * - Compact binding table layout so it's tight and not dependent on diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 4ebb635..84d1031 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -400,7 +400,7 @@ struct anv_fixed_size_state_pool { }; #define ANV_MIN_STATE_SIZE_LOG2 6 -#define ANV_MAX_STATE_SIZE_LOG2 10 +#define ANV_MAX_STATE_SIZE_LOG2 16 #define ANV_STATE_BUCKETS (ANV_MAX_STATE_SIZE_LOG2 - ANV_MIN_STATE_SIZE_LOG2) @@ -704,6 +704,7 @@ struct anv_device { struct anv_state_pool dynamic_state_pool; struct anv_block_pool instruction_block_pool; + struct anv_state_pool instruction_state_pool; struct anv_pipeline_cache default_pipeline_cache; struct anv_block_pool surface_state_block_pool; @@ -1463,6 +1464,58 @@ struct anv_pipeline_bind_map { struct anv_pipeline_binding * sampler_to_descriptor; }; +struct anv_shader_bin { + uint32_t ref_cnt; + + gl_shader_stage stage; + + struct anv_state kernel; + uint32_t kernel_size; + + union { + struct brw_stage_prog_data base; + struct brw_vs_prog_data vs; + struct brw_gs_prog_data gs; + struct brw_tcs_prog_data tcs; + struct brw_tes_prog_data tes; + struct brw_wm_prog_data fs; + struct brw_cs_prog_data cs; + } prog_data; + + struct anv_pipeline_bind_map bind_map; + + unsigned char src_sha1[20]; + + /* Bindings in the bind_map. Surfaces first, then samplers */ + struct anv_pipeline_binding bindings[0]; +}; + +struct anv_shader_bin * +anv_shader_bin_create(struct anv_device *device, + gl_shader_stage stage, + const unsigned char *src_sha1, + const void *kernel, size_t kernel_size, + const struct brw_stage_prog_data *prog_data, + const struct anv_pipeline_bind_map *bind_map); + +void +anv_shader_bin_destroy(struct anv_device *device, struct anv_shader_bin *shader); + +static inline void +anv_shader_bin_ref(struct anv_shader_bin *shader) +{ + assert(shader->ref_cnt >= 1); + __sync_fetch_and_add(&shader->ref_cnt, 1); +} + +static inline void +anv_shader_bin_unref(struct anv_device *device, struct anv_shader_bin *shader) +{ + assert(shader->ref_cnt >= 1); + if (__sync_fetch_and_add(&shader->ref_cnt, -1) == 1) + anv_shader_bin_destroy(device, shader); +} + struct anv_pipeline { struct anv_device * device; struct anv_batch batch; -- 2.5.0.400.gff86faf _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev