}
}
+static void
+get_struct_type_field_and_pointer_sizes(size_t *s_field_size,
+ size_t *s_field_ptrs)
+{
+ *s_field_size = sizeof(glsl_struct_field);
+ *s_field_ptrs =
+ sizeof(((glsl_struct_field *)0)->type) +
+ sizeof(((glsl_struct_field *)0)->name);
+}
+
static void
encode_type_to_blob(struct blob *blob, const glsl_type *type)
{
uint32_t encoding;
+ if (!type) {
+ blob_write_uint32(blob, 0);
+ return;
+ }
+
switch (type->base_type) {
case GLSL_TYPE_UINT:
case GLSL_TYPE_INT:
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);
+
+ size_t s_field_size, s_field_ptrs;
+ get_struct_type_field_and_pointer_sizes(&s_field_size, &s_field_ptrs);
+
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);
+
+ /* Write the struct field skipping the pointers */
+ blob_write_bytes(blob,
+ ((char *)&type->fields.structure[i]) + s_field_ptrs,
+ s_field_size - s_field_ptrs);
}
- if (type->base_type == GLSL_TYPE_INTERFACE) {
+ if (type->is_interface()) {
blob_write_uint32(blob, type->interface_packing);
blob_write_uint32(blob, type->interface_row_major);
}
decode_type_from_blob(struct blob_reader *blob)
{
uint32_t u = blob_read_uint32(blob);
+
+ if (u == 0) {
+ return NULL;
+ }
+
glsl_base_type base_type = (glsl_base_type) (u >> 24);
switch (base_type) {
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);
+
+ size_t s_field_size, s_field_ptrs;
+ get_struct_type_field_and_pointer_sizes(&s_field_size, &s_field_ptrs);
+
+ glsl_struct_field *fields =
+ (glsl_struct_field *) malloc(s_field_size * 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);
+
+ blob_copy_bytes(blob, ((uint8_t *) &fields[i]) + s_field_ptrs,
+ s_field_size - s_field_ptrs);
}
+ const glsl_type *t;
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);
+ t = glsl_type::get_interface_instance(fields, num_fields, packing,
+ row_major, name);
} else {
- return glsl_type::get_record_instance(fields, num_fields, name);
+ t = glsl_type::get_record_instance(fields, num_fields, name);
}
+
+ free(fields);
+ return t;
}
case GLSL_TYPE_VOID:
case GLSL_TYPE_ERROR:
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 =
- values_for_type(prog->data->UniformStorage[i].type) *
+ prog->data->UniformStorage[i].type->component_slots() *
MAX2(prog->data->UniformStorage[i].array_elements, 1);
blob_write_bytes(metadata, prog->data->UniformStorage[i].storage,
sizeof(union gl_constant_value) * vec_size);
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 =
- values_for_type(prog->data->UniformStorage[i].type) *
+ prog->data->UniformStorage[i].type->component_slots() *
MAX2(prog->data->UniformStorage[i].array_elements, 1);
blob_copy_bytes(metadata,
(uint8_t *) prog->data->UniformStorage[i].storage,
}
}
+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);
+ }
+
write_shader_parameters(metadata, glprog->Parameters);
}
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);
+ }
+ }
+
glprog->Parameters = _mesa_new_parameter_list();
read_shader_parameters(metadata, glprog->Parameters);
}
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);
* TODO: In future we should use another method to generate a key for ff
* programs.
*/
- if (*prog->data->sha1 == 0)
+ static const char zero[sizeof(prog->data->sha1)] = {0};
+ if (memcmp(prog->data->sha1, zero, sizeof(prog->data->sha1)) == 0)
return;
- struct blob *metadata = blob_create(NULL);
+ struct blob *metadata = blob_create();
write_uniforms(metadata, prog);
if (sh) {
write_shader_metadata(metadata, sh);
- /* Store nir shader info */
- blob_write_bytes(metadata, &sh->Program->info, sizeof(shader_info));
-
if (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);
+ 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_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) {
- fprintf(stderr, "marking shader: %s\n",
- _mesa_sha1_format(sha1_buf, prog->Shaders[i]->sha1));
+ _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);
-
- ralloc_free(metadata);
+ disk_cache_put(cache, prog->data->sha1, metadata->data, metadata->size,
+ &cache_item_metadata);
if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
- fprintf(stderr, "putting program metadata in cache: %s\n",
- _mesa_sha1_format(sha1_buf, prog->data->sha1));
+ _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_destroy(metadata);
}
bool
return false;
struct disk_cache *cache = ctx->Cache;
- if (!cache || prog->data->cache_fallback)
+ if (!cache || prog->data->cache_fallback || prog->data->skip_cache)
return false;
/* Include bindings when creating sha1. These bindings change the resulting
ctx->API, ctx->Const.GLSLVersion,
ctx->Const.ForceGLSLVersion);
+ /* We run the preprocessor on shaders after hashing them, so we need to
+ * add any extension override vars to the hash. If we don't do this the
+ * preprocessor could result in different output and we could load the
+ * wrong shader.
+ */
+ char *ext_override = getenv("MESA_EXTENSION_OVERRIDE");
+ if (ext_override) {
+ ralloc_asprintf_append(&buf, "ext:%s", ext_override);
+ }
+
+ /* DRI config options may also change the output from the compiler so
+ * include them as an input to sha1 creation.
+ */
char sha1buf[41];
+ _mesa_sha1_format(sha1buf, ctx->Const.dri_config_options_sha1);
+ ralloc_strcat(&buf, sha1buf);
+
for (unsigned i = 0; i < prog->NumShaders; i++) {
struct gl_shader *sh = prog->Shaders[i];
+ _mesa_sha1_format(sha1buf, sh->sha1);
ralloc_asprintf_append(&buf, "%s: %s\n",
- _mesa_shader_stage_to_abbrev(sh->Stage),
- _mesa_sha1_format(sha1buf, sh->sha1));
+ _mesa_shader_stage_to_abbrev(sh->Stage), sha1buf);
}
- _mesa_sha1_compute(buf, strlen(buf), prog->data->sha1);
+ disk_cache_compute_key(cache, buf, strlen(buf), prog->data->sha1);
ralloc_free(buf);
size_t size;
}
if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
+ _mesa_sha1_format(sha1buf, prog->data->sha1);
fprintf(stderr, "loading shader program meta data from cache: %s\n",
- _mesa_sha1_format(sha1buf, prog->data->sha1));
+ sha1buf);
}
struct blob_reader metadata;
/* This is used to flag a shader retrieved from cache */
prog->data->LinkStatus = linking_skipped;
+ /* Since the program load was successful, CompileStatus of all shaders at
+ * this point should normally be compile_skipped. However because of how
+ * the eviction works, it may happen that some of the individual shader keys
+ * have been evicted, resulting in unnecessary recompiles on this load, so
+ * mark them again to skip such recompiles next time.
+ */
+ char sha1_buf[41];
+ for (unsigned i = 0; i < prog->NumShaders; i++) {
+ if (prog->Shaders[i]->CompileStatus == compiled_no_opts) {
+ disk_cache_put_key(cache, prog->Shaders[i]->sha1);
+ if (ctx->_Shader->Flags & GLSL_CACHE_INFO) {
+ _mesa_sha1_format(sha1_buf, prog->Shaders[i]->sha1);
+ fprintf(stderr, "re-marking shader: %s\n", sha1_buf);
+ }
+ }
+ }
+
free (buffer);
return true;