[Mesa-dev] [PATCH 5/6] anv: Add a struct for storing a compiled shader
Jason Ekstrand
jason at jlekstrand.net
Thu Aug 25 22:28:17 UTC 2016
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 <jason at 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
More information about the mesa-dev
mailing list