#include "program.h"
#include "shader_cache.h"
#include "util/mesa-sha1.h"
-#include "util/string_to_uint_map.h"
+#include "string_to_uint_map.h"
extern "C" {
#include "main/enums.h"
}
}
-static void
-encode_type_to_blob(struct blob *blob, const glsl_type *type)
-{
- uint32_t encoding;
-
- switch (type->base_type) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_BOOL:
- case GLSL_TYPE_DOUBLE:
- case GLSL_TYPE_UINT64:
- case GLSL_TYPE_INT64:
- encoding = (type->base_type << 24) |
- (type->vector_elements << 4) |
- (type->matrix_columns);
- break;
- case GLSL_TYPE_SAMPLER:
- encoding = (type->base_type) << 24 |
- (type->sampler_dimensionality << 4) |
- (type->sampler_shadow << 3) |
- (type->sampler_array << 2) |
- (type->sampled_type);
- break;
- case GLSL_TYPE_SUBROUTINE:
- encoding = type->base_type << 24;
- blob_write_uint32(blob, encoding);
- blob_write_string(blob, type->name);
- return;
- case GLSL_TYPE_IMAGE:
- encoding = (type->base_type) << 24 |
- (type->sampler_dimensionality << 3) |
- (type->sampler_array << 2) |
- (type->sampled_type);
- break;
- case GLSL_TYPE_ATOMIC_UINT:
- encoding = (type->base_type << 24);
- break;
- case GLSL_TYPE_ARRAY:
- blob_write_uint32(blob, (type->base_type) << 24);
- blob_write_uint32(blob, type->length);
- encode_type_to_blob(blob, type->fields.array);
- return;
- case GLSL_TYPE_STRUCT:
- case GLSL_TYPE_INTERFACE:
- blob_write_uint32(blob, (type->base_type) << 24);
- blob_write_string(blob, type->name);
- blob_write_uint32(blob, type->length);
- blob_write_bytes(blob, type->fields.structure,
- sizeof(glsl_struct_field) * type->length);
- for (unsigned i = 0; i < type->length; i++) {
- encode_type_to_blob(blob, type->fields.structure[i].type);
- blob_write_string(blob, type->fields.structure[i].name);
- }
-
- if (type->base_type == GLSL_TYPE_INTERFACE) {
- blob_write_uint32(blob, type->interface_packing);
- blob_write_uint32(blob, type->interface_row_major);
- }
- return;
- case GLSL_TYPE_VOID:
- case GLSL_TYPE_ERROR:
- default:
- assert(!"Cannot encode type!");
- encoding = 0;
- break;
- }
-
- blob_write_uint32(blob, encoding);
-}
-
-static const glsl_type *
-decode_type_from_blob(struct blob_reader *blob)
-{
- uint32_t u = blob_read_uint32(blob);
- glsl_base_type base_type = (glsl_base_type) (u >> 24);
-
- switch (base_type) {
- case GLSL_TYPE_UINT:
- case GLSL_TYPE_INT:
- case GLSL_TYPE_FLOAT:
- case GLSL_TYPE_BOOL:
- case GLSL_TYPE_DOUBLE:
- case GLSL_TYPE_UINT64:
- case GLSL_TYPE_INT64:
- return glsl_type::get_instance(base_type, (u >> 4) & 0x0f, u & 0x0f);
- case GLSL_TYPE_SAMPLER:
- return glsl_type::get_sampler_instance((enum glsl_sampler_dim) ((u >> 4) & 0x07),
- (u >> 3) & 0x01,
- (u >> 2) & 0x01,
- (glsl_base_type) ((u >> 0) & 0x03));
- case GLSL_TYPE_SUBROUTINE:
- return glsl_type::get_subroutine_instance(blob_read_string(blob));
- case GLSL_TYPE_IMAGE:
- return glsl_type::get_image_instance((enum glsl_sampler_dim) ((u >> 3) & 0x07),
- (u >> 2) & 0x01,
- (glsl_base_type) ((u >> 0) & 0x03));
- case GLSL_TYPE_ATOMIC_UINT:
- return glsl_type::atomic_uint_type;
- case GLSL_TYPE_ARRAY: {
- unsigned length = blob_read_uint32(blob);
- return glsl_type::get_array_instance(decode_type_from_blob(blob),
- length);
- }
- case GLSL_TYPE_STRUCT:
- case GLSL_TYPE_INTERFACE: {
- char *name = blob_read_string(blob);
- unsigned num_fields = blob_read_uint32(blob);
- glsl_struct_field *fields = (glsl_struct_field *)
- blob_read_bytes(blob, sizeof(glsl_struct_field) * num_fields);
- for (unsigned i = 0; i < num_fields; i++) {
- fields[i].type = decode_type_from_blob(blob);
- fields[i].name = blob_read_string(blob);
- }
-
- if (base_type == GLSL_TYPE_INTERFACE) {
- enum glsl_interface_packing packing =
- (glsl_interface_packing) blob_read_uint32(blob);
- bool row_major = blob_read_uint32(blob);
- return glsl_type::get_interface_instance(fields, num_fields,
- packing, row_major, name);
- } else {
- return glsl_type::get_record_instance(fields, num_fields, name);
- }
- }
- case GLSL_TYPE_VOID:
- case GLSL_TYPE_ERROR:
- default:
- assert(!"Cannot decode type!");
- return NULL;
- }
-}
-
static void
write_subroutines(struct blob *metadata, struct gl_shader_program *prog)
{
MAX_FEEDBACK_BUFFERS);
}
+static bool
+has_uniform_storage(struct gl_shader_program *prog, unsigned idx)
+{
+ if (!prog->data->UniformStorage[idx].builtin &&
+ !prog->data->UniformStorage[idx].is_shader_storage &&
+ prog->data->UniformStorage[idx].block_index == -1)
+ return true;
+
+ return false;
+}
+
static void
write_uniforms(struct blob *metadata, struct gl_shader_program *prog)
{
encode_type_to_blob(metadata, prog->data->UniformStorage[i].type);
blob_write_uint32(metadata, prog->data->UniformStorage[i].array_elements);
blob_write_string(metadata, prog->data->UniformStorage[i].name);
- blob_write_uint32(metadata, prog->data->UniformStorage[i].storage -
- prog->data->UniformDataSlots);
blob_write_uint32(metadata, prog->data->UniformStorage[i].builtin);
blob_write_uint32(metadata, prog->data->UniformStorage[i].remap_location);
blob_write_uint32(metadata, prog->data->UniformStorage[i].block_index);
blob_write_uint32(metadata, prog->data->UniformStorage[i].array_stride);
blob_write_uint32(metadata, prog->data->UniformStorage[i].hidden);
blob_write_uint32(metadata, prog->data->UniformStorage[i].is_shader_storage);
+ blob_write_uint32(metadata, prog->data->UniformStorage[i].active_shader_mask);
blob_write_uint32(metadata, prog->data->UniformStorage[i].matrix_stride);
blob_write_uint32(metadata, prog->data->UniformStorage[i].row_major);
+ blob_write_uint32(metadata, prog->data->UniformStorage[i].is_bindless);
blob_write_uint32(metadata,
prog->data->UniformStorage[i].num_compatible_subroutines);
blob_write_uint32(metadata,
prog->data->UniformStorage[i].top_level_array_size);
blob_write_uint32(metadata,
prog->data->UniformStorage[i].top_level_array_stride);
+
+ if (has_uniform_storage(prog, i)) {
+ blob_write_uint32(metadata, prog->data->UniformStorage[i].storage -
+ prog->data->UniformDataSlots);
+ }
+
blob_write_bytes(metadata, prog->data->UniformStorage[i].opaque,
sizeof(prog->data->UniformStorage[i].opaque));
}
*/
blob_write_uint32(metadata, prog->data->NumHiddenUniforms);
for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
- if (!prog->data->UniformStorage[i].builtin &&
- !prog->data->UniformStorage[i].is_shader_storage &&
- prog->data->UniformStorage[i].block_index == -1) {
+ if (has_uniform_storage(prog, i)) {
unsigned vec_size =
prog->data->UniformStorage[i].type->component_slots() *
MAX2(prog->data->UniformStorage[i].array_elements, 1);
uniforms[i].type = decode_type_from_blob(metadata);
uniforms[i].array_elements = blob_read_uint32(metadata);
uniforms[i].name = ralloc_strdup(prog, blob_read_string (metadata));
- uniforms[i].storage = data + blob_read_uint32(metadata);
uniforms[i].builtin = blob_read_uint32(metadata);
uniforms[i].remap_location = blob_read_uint32(metadata);
uniforms[i].block_index = blob_read_uint32(metadata);
uniforms[i].array_stride = blob_read_uint32(metadata);
uniforms[i].hidden = blob_read_uint32(metadata);
uniforms[i].is_shader_storage = blob_read_uint32(metadata);
+ uniforms[i].active_shader_mask = blob_read_uint32(metadata);
uniforms[i].matrix_stride = blob_read_uint32(metadata);
uniforms[i].row_major = blob_read_uint32(metadata);
+ uniforms[i].is_bindless = blob_read_uint32(metadata);
uniforms[i].num_compatible_subroutines = blob_read_uint32(metadata);
uniforms[i].top_level_array_size = blob_read_uint32(metadata);
uniforms[i].top_level_array_stride = blob_read_uint32(metadata);
prog->UniformHash->put(i, uniforms[i].name);
+ if (has_uniform_storage(prog, i)) {
+ uniforms[i].storage = data + blob_read_uint32(metadata);
+ }
+
memcpy(uniforms[i].opaque,
blob_read_bytes(metadata, sizeof(uniforms[i].opaque)),
sizeof(uniforms[i].opaque));
/* Restore uniform values. */
prog->data->NumHiddenUniforms = blob_read_uint32(metadata);
for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
- if (!prog->data->UniformStorage[i].builtin &&
- !prog->data->UniformStorage[i].is_shader_storage &&
- prog->data->UniformStorage[i].block_index == -1) {
+ if (has_uniform_storage(prog, i)) {
unsigned vec_size =
prog->data->UniformStorage[i].type->component_slots() *
MAX2(prog->data->UniformStorage[i].array_elements, 1);
}
}
+static void
+get_shader_var_and_pointer_sizes(size_t *s_var_size, size_t *s_var_ptrs,
+ const gl_shader_variable *var)
+{
+ *s_var_size = sizeof(gl_shader_variable);
+ *s_var_ptrs =
+ sizeof(var->type) +
+ sizeof(var->interface_type) +
+ sizeof(var->outermost_struct_type) +
+ sizeof(var->name);
+}
+
static void
write_program_resource_data(struct blob *metadata,
struct gl_shader_program *prog,
case GL_PROGRAM_INPUT:
case GL_PROGRAM_OUTPUT: {
const gl_shader_variable *var = (gl_shader_variable *)res->Data;
- blob_write_bytes(metadata, var, sizeof(gl_shader_variable));
+
encode_type_to_blob(metadata, var->type);
+ encode_type_to_blob(metadata, var->interface_type);
+ encode_type_to_blob(metadata, var->outermost_struct_type);
- if (var->interface_type)
- encode_type_to_blob(metadata, var->interface_type);
+ blob_write_string(metadata, var->name);
- if (var->outermost_struct_type)
- encode_type_to_blob(metadata, var->outermost_struct_type);
+ size_t s_var_size, s_var_ptrs;
+ get_shader_var_and_pointer_sizes(&s_var_size, &s_var_ptrs, var);
- blob_write_string(metadata, var->name);
+ /* Write gl_shader_variable skipping over the pointers */
+ blob_write_bytes(metadata, ((char *)var) + s_var_ptrs,
+ s_var_size - s_var_ptrs);
break;
}
case GL_UNIFORM_BLOCK:
case GL_PROGRAM_OUTPUT: {
gl_shader_variable *var = ralloc(prog, struct gl_shader_variable);
- blob_copy_bytes(metadata, (uint8_t *) var, sizeof(gl_shader_variable));
var->type = decode_type_from_blob(metadata);
+ var->interface_type = decode_type_from_blob(metadata);
+ var->outermost_struct_type = decode_type_from_blob(metadata);
- if (var->interface_type)
- var->interface_type = decode_type_from_blob(metadata);
+ var->name = ralloc_strdup(prog, blob_read_string(metadata));
- if (var->outermost_struct_type)
- var->outermost_struct_type = decode_type_from_blob(metadata);
+ size_t s_var_size, s_var_ptrs;
+ get_shader_var_and_pointer_sizes(&s_var_size, &s_var_ptrs, var);
- var->name = ralloc_strdup(prog, blob_read_string(metadata));
+ blob_copy_bytes(metadata, ((uint8_t *) var) + s_var_ptrs,
+ s_var_size - s_var_ptrs);
res->Data = var;
break;
{
assert(shader->Program);
struct gl_program *glprog = shader->Program;
+ unsigned i;
blob_write_bytes(metadata, glprog->TexturesUsed,
sizeof(glprog->TexturesUsed));
blob_write_bytes(metadata, glprog->sh.ImageUnits,
sizeof(glprog->sh.ImageUnits));
+ size_t ptr_size = sizeof(GLvoid *);
+
+ blob_write_uint32(metadata, glprog->sh.NumBindlessSamplers);
+ blob_write_uint32(metadata, glprog->sh.HasBoundBindlessSampler);
+ for (i = 0; i < glprog->sh.NumBindlessSamplers; i++) {
+ blob_write_bytes(metadata, &glprog->sh.BindlessSamplers[i],
+ sizeof(struct gl_bindless_sampler) - ptr_size);
+ }
+
+ blob_write_uint32(metadata, glprog->sh.NumBindlessImages);
+ blob_write_uint32(metadata, glprog->sh.HasBoundBindlessImage);
+ for (i = 0; i < glprog->sh.NumBindlessImages; i++) {
+ blob_write_bytes(metadata, &glprog->sh.BindlessImages[i],
+ sizeof(struct gl_bindless_image) - ptr_size);
+ }
+
+ blob_write_bytes(metadata, &glprog->sh.fs.BlendSupport,
+ sizeof(glprog->sh.fs.BlendSupport));
+
write_shader_parameters(metadata, glprog->Parameters);
+
+ assert((glprog->driver_cache_blob == NULL) ==
+ (glprog->driver_cache_blob_size == 0));
+ blob_write_uint32(metadata, (uint32_t)glprog->driver_cache_blob_size);
+ if (glprog->driver_cache_blob_size > 0) {
+ blob_write_bytes(metadata, glprog->driver_cache_blob,
+ glprog->driver_cache_blob_size);
+ }
}
static void
struct gl_program *glprog,
gl_linked_shader *linked)
{
+ unsigned i;
+
blob_copy_bytes(metadata, (uint8_t *) glprog->TexturesUsed,
sizeof(glprog->TexturesUsed));
glprog->SamplersUsed = blob_read_uint64(metadata);
blob_copy_bytes(metadata, (uint8_t *) glprog->sh.ImageUnits,
sizeof(glprog->sh.ImageUnits));
+ size_t ptr_size = sizeof(GLvoid *);
+
+ glprog->sh.NumBindlessSamplers = blob_read_uint32(metadata);
+ glprog->sh.HasBoundBindlessSampler = blob_read_uint32(metadata);
+ if (glprog->sh.NumBindlessSamplers > 0) {
+ glprog->sh.BindlessSamplers =
+ rzalloc_array(glprog, gl_bindless_sampler,
+ glprog->sh.NumBindlessSamplers);
+
+ for (i = 0; i < glprog->sh.NumBindlessSamplers; i++) {
+ blob_copy_bytes(metadata, (uint8_t *) &glprog->sh.BindlessSamplers[i],
+ sizeof(struct gl_bindless_sampler) - ptr_size);
+ }
+ }
+
+ glprog->sh.NumBindlessImages = blob_read_uint32(metadata);
+ glprog->sh.HasBoundBindlessImage = blob_read_uint32(metadata);
+ if (glprog->sh.NumBindlessImages > 0) {
+ glprog->sh.BindlessImages =
+ rzalloc_array(glprog, gl_bindless_image,
+ glprog->sh.NumBindlessImages);
+
+ for (i = 0; i < glprog->sh.NumBindlessImages; i++) {
+ blob_copy_bytes(metadata, (uint8_t *) &glprog->sh.BindlessImages[i],
+ sizeof(struct gl_bindless_image) - ptr_size);
+ }
+ }
+
+ blob_copy_bytes(metadata, (uint8_t *) &glprog->sh.fs.BlendSupport,
+ sizeof(glprog->sh.fs.BlendSupport));
+
glprog->Parameters = _mesa_new_parameter_list();
read_shader_parameters(metadata, glprog->Parameters);
+
+ glprog->driver_cache_blob_size = (size_t)blob_read_uint32(metadata);
+ if (glprog->driver_cache_blob_size > 0) {
+ glprog->driver_cache_blob =
+ (uint8_t*)ralloc_size(glprog, glprog->driver_cache_blob_size);
+ blob_copy_bytes(metadata, glprog->driver_cache_blob,
+ glprog->driver_cache_blob_size);
+ }
}
static void
ralloc_asprintf_append(bindings_str, "%s:%u,", key, value);
}
+static void
+get_shader_info_and_pointer_sizes(size_t *s_info_size, size_t *s_info_ptrs,
+ shader_info *info)
+{
+ *s_info_size = sizeof(shader_info);
+ *s_info_ptrs = sizeof(info->name) + sizeof(info->label);
+}
+
static void
create_linked_shader_and_program(struct gl_context *ctx,
gl_shader_stage stage,
read_shader_metadata(metadata, glprog, linked);
+ glprog->info.name = ralloc_strdup(glprog, blob_read_string(metadata));
+ glprog->info.label = ralloc_strdup(glprog, blob_read_string(metadata));
+
+ size_t s_info_size, s_info_ptrs;
+ get_shader_info_and_pointer_sizes(&s_info_size, &s_info_ptrs,
+ &glprog->info);
+
/* Restore shader info */
- blob_copy_bytes(metadata, (uint8_t *) &glprog->info, sizeof(shader_info));
- if (glprog->info.name)
- glprog->info.name = ralloc_strdup(glprog, blob_read_string(metadata));
- if (glprog->info.label)
- glprog->info.label = ralloc_strdup(glprog, blob_read_string(metadata));
+ blob_copy_bytes(metadata, ((uint8_t *) &glprog->info) + s_info_ptrs,
+ s_info_size - s_info_ptrs);
_mesa_reference_shader_program_data(ctx, &glprog->sh.data, prog->data);
_mesa_reference_program(ctx, &linked->Program, glprog);
if (memcmp(prog->data->sha1, zero, sizeof(prog->data->sha1)) == 0)
return;
- struct blob *metadata = blob_create();
+ struct blob metadata;
+ blob_init(&metadata);
- write_uniforms(metadata, prog);
+ write_uniforms(&metadata, prog);
- write_hash_tables(metadata, prog);
+ write_hash_tables(&metadata, prog);
- blob_write_uint32(metadata, prog->data->Version);
- blob_write_uint32(metadata, prog->data->linked_stages);
+ blob_write_uint32(&metadata, prog->data->Version);
+ blob_write_uint32(&metadata, prog->data->linked_stages);
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
struct gl_linked_shader *sh = prog->_LinkedShaders[i];
if (sh) {
- write_shader_metadata(metadata, sh);
-
- /* Store nir shader info */
- blob_write_bytes(metadata, &sh->Program->info, sizeof(shader_info));
+ write_shader_metadata(&metadata, sh);
if (sh->Program->info.name)
- blob_write_string(metadata, sh->Program->info.name);
+ blob_write_string(&metadata, sh->Program->info.name);
+ else
+ blob_write_string(&metadata, "");
if (sh->Program->info.label)
- blob_write_string(metadata, sh->Program->info.label);
+ blob_write_string(&metadata, sh->Program->info.label);
+ else
+ blob_write_string(&metadata, "");
+
+ size_t s_info_size, s_info_ptrs;
+ get_shader_info_and_pointer_sizes(&s_info_size, &s_info_ptrs,
+ &sh->Program->info);
+
+ /* Store shader info */
+ blob_write_bytes(&metadata,
+ ((char *) &sh->Program->info) + s_info_ptrs,
+ s_info_size - s_info_ptrs);
}
}
- write_xfb(metadata, prog);
+ write_xfb(&metadata, prog);
- write_uniform_remap_tables(metadata, prog);
+ write_uniform_remap_tables(&metadata, prog);
- write_atomic_buffers(metadata, prog);
+ write_atomic_buffers(&metadata, prog);
- write_buffer_blocks(metadata, prog);
+ write_buffer_blocks(&metadata, prog);
- write_subroutines(metadata, prog);
+ write_subroutines(&metadata, prog);
- write_program_resource_list(metadata, prog);
+ write_program_resource_list(&metadata, prog);
+
+ struct cache_item_metadata cache_item_metadata;
+ cache_item_metadata.type = CACHE_ITEM_TYPE_GLSL;
+ cache_item_metadata.keys =
+ (cache_key *) malloc(prog->NumShaders * sizeof(cache_key));
+ cache_item_metadata.num_keys = prog->NumShaders;
+
+ if (!cache_item_metadata.keys)
+ goto fail;
char sha1_buf[41];
for (unsigned i = 0; i < prog->NumShaders; i++) {
disk_cache_put_key(cache, prog->Shaders[i]->sha1);
+ memcpy(cache_item_metadata.keys[i], prog->Shaders[i]->sha1,
+ sizeof(cache_key));
if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
_mesa_sha1_format(sha1_buf, prog->Shaders[i]->sha1);
fprintf(stderr, "marking shader: %s\n", sha1_buf);
}
}
- disk_cache_put(cache, prog->data->sha1, metadata->data, metadata->size);
-
- blob_destroy(metadata);
+ disk_cache_put(cache, prog->data->sha1, metadata.data, metadata.size,
+ &cache_item_metadata);
if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
_mesa_sha1_format(sha1_buf, prog->data->sha1);
fprintf(stderr, "putting program metadata in cache: %s\n", sha1_buf);
}
+
+fail:
+ free(cache_item_metadata.keys);
+ blob_finish(&metadata);
}
bool
return false;
struct disk_cache *cache = ctx->Cache;
- if (!cache || prog->data->cache_fallback)
+ if (!cache || prog->data->skip_cache)
return false;
/* Include bindings when creating sha1. These bindings change the resulting