mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 09:08:10 +02:00
anv: Add a struct for storing a compiled shader
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 struct is very similar to the old cache_entry struct except that it
is reference counted and stores the actual pipeline_bind_map. Similarly to
cache_entry, much of the actual data is floating-size and stored after the
main struct. Unlike cache_entry, which was storred in GPU-accessable
memory, the storage for anv_shader_bin 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@jlekstrand.net>
Cc: "12.0" <mesa-stable@lists.freedesktop.org>
Acked-by: Kristian Høgsberg Kristensen <krh@bitplanet.net>
(cherry picked from commit 6899718470)
This commit is contained in:
parent
2566315063
commit
a8e4b59cfd
3 changed files with 160 additions and 0 deletions
|
|
@ -875,6 +875,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);
|
||||
|
|
@ -950,6 +952,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);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,116 @@
|
|||
#include "util/debug.h"
|
||||
#include "anv_private.h"
|
||||
|
||||
struct shader_bin_key {
|
||||
uint32_t size;
|
||||
uint8_t data[0];
|
||||
};
|
||||
|
||||
static size_t
|
||||
anv_shader_bin_size(uint32_t prog_data_size, uint32_t key_size,
|
||||
uint32_t surface_count, uint32_t sampler_count)
|
||||
{
|
||||
const uint32_t binding_data_size =
|
||||
(surface_count + sampler_count) * sizeof(struct anv_pipeline_binding);
|
||||
|
||||
return align_u32(sizeof(struct anv_shader_bin), 8) +
|
||||
align_u32(prog_data_size, 8) +
|
||||
align_u32(sizeof(uint32_t) + key_size, 8) +
|
||||
align_u32(binding_data_size, 8);
|
||||
}
|
||||
|
||||
static inline const struct shader_bin_key *
|
||||
anv_shader_bin_get_key(const struct anv_shader_bin *shader)
|
||||
{
|
||||
const void *data = shader;
|
||||
data += align_u32(sizeof(struct anv_shader_bin), 8);
|
||||
data += align_u32(shader->prog_data_size, 8);
|
||||
return data;
|
||||
}
|
||||
|
||||
struct anv_shader_bin *
|
||||
anv_shader_bin_create(struct anv_device *device,
|
||||
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)
|
||||
{
|
||||
const size_t size =
|
||||
anv_shader_bin_size(prog_data_size, key_size,
|
||||
bind_map->surface_count, bind_map->sampler_count);
|
||||
|
||||
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->kernel =
|
||||
anv_state_pool_alloc(&device->instruction_state_pool, kernel_size, 64);
|
||||
memcpy(shader->kernel.map, kernel_data, kernel_size);
|
||||
shader->kernel_size = kernel_size;
|
||||
shader->bind_map = *bind_map;
|
||||
shader->prog_data_size = prog_data_size;
|
||||
|
||||
/* Now we fill out the floating data at the end */
|
||||
void *data = shader;
|
||||
data += align_u32(sizeof(struct anv_shader_bin), 8);
|
||||
|
||||
memcpy(data, prog_data, prog_data_size);
|
||||
data += align_u32(prog_data_size, 8);
|
||||
|
||||
struct shader_bin_key *key = data;
|
||||
key->size = key_size;
|
||||
memcpy(key->data, key_data, key_size);
|
||||
data += align_u32(sizeof(*key) + key_size, 8);
|
||||
|
||||
shader->bind_map.surface_to_descriptor = data;
|
||||
memcpy(data, bind_map->surface_to_descriptor,
|
||||
bind_map->surface_count * sizeof(struct anv_pipeline_binding));
|
||||
data += bind_map->surface_count * sizeof(struct anv_pipeline_binding);
|
||||
|
||||
shader->bind_map.sampler_to_descriptor = data;
|
||||
memcpy(data, bind_map->sampler_to_descriptor,
|
||||
bind_map->sampler_count * sizeof(struct anv_pipeline_binding));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static size_t
|
||||
anv_shader_bin_data_size(const struct anv_shader_bin *shader)
|
||||
{
|
||||
return anv_shader_bin_size(shader->prog_data_size,
|
||||
anv_shader_bin_get_key(shader)->size,
|
||||
shader->bind_map.surface_count,
|
||||
shader->bind_map.sampler_count) +
|
||||
align_u32(shader->kernel_size, 8);
|
||||
}
|
||||
|
||||
static void
|
||||
anv_shader_bin_write_data(const struct anv_shader_bin *shader, void *data)
|
||||
{
|
||||
size_t struct_size =
|
||||
anv_shader_bin_size(shader->prog_data_size,
|
||||
anv_shader_bin_get_key(shader)->size,
|
||||
shader->bind_map.surface_count,
|
||||
shader->bind_map.sampler_count);
|
||||
|
||||
memcpy(data, shader, struct_size);
|
||||
data += struct_size;
|
||||
|
||||
memcpy(data, shader->kernel.map, shader->kernel_size);
|
||||
}
|
||||
|
||||
/* Remaining work:
|
||||
*
|
||||
* - Compact binding table layout so it's tight and not dependent on
|
||||
|
|
|
|||
|
|
@ -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,52 @@ struct anv_pipeline_bind_map {
|
|||
struct anv_pipeline_binding * sampler_to_descriptor;
|
||||
};
|
||||
|
||||
struct anv_shader_bin {
|
||||
uint32_t ref_cnt;
|
||||
|
||||
struct anv_state kernel;
|
||||
uint32_t kernel_size;
|
||||
|
||||
struct anv_pipeline_bind_map bind_map;
|
||||
|
||||
uint32_t prog_data_size;
|
||||
|
||||
/* Prog data follows, then the key, both aligned to 8-bytes */
|
||||
};
|
||||
|
||||
struct anv_shader_bin *
|
||||
anv_shader_bin_create(struct anv_device *device,
|
||||
const void *key, uint32_t key_size,
|
||||
const void *kernel, uint32_t kernel_size,
|
||||
const void *prog_data, uint32_t prog_data_size,
|
||||
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);
|
||||
}
|
||||
|
||||
static inline const struct brw_stage_prog_data *
|
||||
anv_shader_bin_get_prog_data(const struct anv_shader_bin *shader)
|
||||
{
|
||||
const void *data = shader;
|
||||
data += align_u32(sizeof(struct anv_shader_bin), 8);
|
||||
return data;
|
||||
}
|
||||
|
||||
struct anv_pipeline {
|
||||
struct anv_device * device;
|
||||
struct anv_batch batch;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue