#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)
{
}
}
+static void
+write_buffer_block(struct blob *metadata, struct gl_uniform_block *b)
+{
+ blob_write_string(metadata, b->Name);
+ blob_write_uint32(metadata, b->NumUniforms);
+ blob_write_uint32(metadata, b->Binding);
+ blob_write_uint32(metadata, b->UniformBufferSize);
+ blob_write_uint32(metadata, b->stageref);
+
+ for (unsigned j = 0; j < b->NumUniforms; j++) {
+ blob_write_string(metadata, b->Uniforms[j].Name);
+ blob_write_string(metadata, b->Uniforms[j].IndexName);
+ encode_type_to_blob(metadata, b->Uniforms[j].Type);
+ blob_write_uint32(metadata, b->Uniforms[j].Offset);
+ }
+}
+
+static void
+write_buffer_blocks(struct blob *metadata, struct gl_shader_program *prog)
+{
+ blob_write_uint32(metadata, prog->data->NumUniformBlocks);
+ blob_write_uint32(metadata, prog->data->NumShaderStorageBlocks);
+
+ for (unsigned i = 0; i < prog->data->NumUniformBlocks; i++) {
+ write_buffer_block(metadata, &prog->data->UniformBlocks[i]);
+ }
+
+ for (unsigned i = 0; i < prog->data->NumShaderStorageBlocks; i++) {
+ write_buffer_block(metadata, &prog->data->ShaderStorageBlocks[i]);
+ }
+
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_linked_shader *sh = prog->_LinkedShaders[i];
+ if (!sh)
+ continue;
+
+ struct gl_program *glprog = sh->Program;
+
+ blob_write_uint32(metadata, glprog->info.num_ubos);
+ blob_write_uint32(metadata, glprog->info.num_ssbos);
+
+ for (unsigned j = 0; j < glprog->info.num_ubos; j++) {
+ uint32_t offset =
+ glprog->sh.UniformBlocks[j] - prog->data->UniformBlocks;
+ blob_write_uint32(metadata, offset);
+ }
+
+ for (unsigned j = 0; j < glprog->info.num_ssbos; j++) {
+ uint32_t offset = glprog->sh.ShaderStorageBlocks[j] -
+ prog->data->ShaderStorageBlocks;
+ blob_write_uint32(metadata, offset);
+ }
+ }
+}
+
+static void
+read_buffer_block(struct blob_reader *metadata, struct gl_uniform_block *b,
+ struct gl_shader_program *prog)
+{
+ b->Name = ralloc_strdup(prog->data, blob_read_string (metadata));
+ b->NumUniforms = blob_read_uint32(metadata);
+ b->Binding = blob_read_uint32(metadata);
+ b->UniformBufferSize = blob_read_uint32(metadata);
+ b->stageref = blob_read_uint32(metadata);
+
+ b->Uniforms =
+ rzalloc_array(prog->data, struct gl_uniform_buffer_variable,
+ b->NumUniforms);
+ for (unsigned j = 0; j < b->NumUniforms; j++) {
+ b->Uniforms[j].Name = ralloc_strdup(prog->data,
+ blob_read_string (metadata));
+
+ char *index_name = blob_read_string(metadata);
+ if (strcmp(b->Uniforms[j].Name, index_name) == 0) {
+ b->Uniforms[j].IndexName = b->Uniforms[j].Name;
+ } else {
+ b->Uniforms[j].IndexName = ralloc_strdup(prog->data, index_name);
+ }
+
+ b->Uniforms[j].Type = decode_type_from_blob(metadata);
+ b->Uniforms[j].Offset = blob_read_uint32(metadata);
+ }
+}
+
+static void
+read_buffer_blocks(struct blob_reader *metadata,
+ struct gl_shader_program *prog)
+{
+ prog->data->NumUniformBlocks = blob_read_uint32(metadata);
+ prog->data->NumShaderStorageBlocks = blob_read_uint32(metadata);
+
+ prog->data->UniformBlocks =
+ rzalloc_array(prog->data, struct gl_uniform_block,
+ prog->data->NumUniformBlocks);
+
+ prog->data->ShaderStorageBlocks =
+ rzalloc_array(prog->data, struct gl_uniform_block,
+ prog->data->NumShaderStorageBlocks);
+
+ for (unsigned i = 0; i < prog->data->NumUniformBlocks; i++) {
+ read_buffer_block(metadata, &prog->data->UniformBlocks[i], prog);
+ }
+
+ for (unsigned i = 0; i < prog->data->NumShaderStorageBlocks; i++) {
+ read_buffer_block(metadata, &prog->data->ShaderStorageBlocks[i], prog);
+ }
+
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_linked_shader *sh = prog->_LinkedShaders[i];
+ if (!sh)
+ continue;
+
+ struct gl_program *glprog = sh->Program;
+
+ glprog->info.num_ubos = blob_read_uint32(metadata);
+ glprog->info.num_ssbos = blob_read_uint32(metadata);
+
+ glprog->sh.UniformBlocks =
+ rzalloc_array(glprog, gl_uniform_block *, glprog->info.num_ubos);
+ glprog->sh.ShaderStorageBlocks =
+ rzalloc_array(glprog, gl_uniform_block *, glprog->info.num_ssbos);
+
+ for (unsigned j = 0; j < glprog->info.num_ubos; j++) {
+ uint32_t offset = blob_read_uint32(metadata);
+ glprog->sh.UniformBlocks[j] = prog->data->UniformBlocks + offset;
+ }
+
+ for (unsigned j = 0; j < glprog->info.num_ssbos; j++) {
+ uint32_t offset = blob_read_uint32(metadata);
+ glprog->sh.ShaderStorageBlocks[j] =
+ prog->data->ShaderStorageBlocks + offset;
+ }
+ }
+}
+
+static void
+write_atomic_buffers(struct blob *metadata, struct gl_shader_program *prog)
+{
+ blob_write_uint32(metadata, prog->data->NumAtomicBuffers);
+
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+ if (prog->_LinkedShaders[i]) {
+ struct gl_program *glprog = prog->_LinkedShaders[i]->Program;
+ blob_write_uint32(metadata, glprog->info.num_abos);
+ }
+ }
+
+ for (unsigned i = 0; i < prog->data->NumAtomicBuffers; i++) {
+ blob_write_uint32(metadata, prog->data->AtomicBuffers[i].Binding);
+ blob_write_uint32(metadata, prog->data->AtomicBuffers[i].MinimumSize);
+ blob_write_uint32(metadata, prog->data->AtomicBuffers[i].NumUniforms);
+
+ blob_write_bytes(metadata, prog->data->AtomicBuffers[i].StageReferences,
+ sizeof(prog->data->AtomicBuffers[i].StageReferences));
+
+ for (unsigned j = 0; j < prog->data->AtomicBuffers[i].NumUniforms; j++) {
+ blob_write_uint32(metadata, prog->data->AtomicBuffers[i].Uniforms[j]);
+ }
+ }
+}
+
+static void
+read_atomic_buffers(struct blob_reader *metadata,
+ struct gl_shader_program *prog)
+{
+ prog->data->NumAtomicBuffers = blob_read_uint32(metadata);
+ prog->data->AtomicBuffers =
+ rzalloc_array(prog, gl_active_atomic_buffer,
+ prog->data->NumAtomicBuffers);
+
+ struct gl_active_atomic_buffer **stage_buff_list[MESA_SHADER_STAGES];
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+ if (prog->_LinkedShaders[i]) {
+ struct gl_program *glprog = prog->_LinkedShaders[i]->Program;
+
+ glprog->info.num_abos = blob_read_uint32(metadata);
+ glprog->sh.AtomicBuffers =
+ rzalloc_array(glprog, gl_active_atomic_buffer *,
+ glprog->info.num_abos);
+ stage_buff_list[i] = glprog->sh.AtomicBuffers;
+ }
+ }
+
+ for (unsigned i = 0; i < prog->data->NumAtomicBuffers; i++) {
+ prog->data->AtomicBuffers[i].Binding = blob_read_uint32(metadata);
+ prog->data->AtomicBuffers[i].MinimumSize = blob_read_uint32(metadata);
+ prog->data->AtomicBuffers[i].NumUniforms = blob_read_uint32(metadata);
+
+ blob_copy_bytes(metadata,
+ (uint8_t *) &prog->data->AtomicBuffers[i].StageReferences,
+ sizeof(prog->data->AtomicBuffers[i].StageReferences));
+
+ prog->data->AtomicBuffers[i].Uniforms = rzalloc_array(prog, unsigned,
+ prog->data->AtomicBuffers[i].NumUniforms);
+
+ for (unsigned j = 0; j < prog->data->AtomicBuffers[i].NumUniforms; j++) {
+ prog->data->AtomicBuffers[i].Uniforms[j] = blob_read_uint32(metadata);
+ }
+
+ for (unsigned j = 0; j < MESA_SHADER_STAGES; j++) {
+ if (prog->data->AtomicBuffers[i].StageReferences[j]) {
+ *stage_buff_list[j] = &prog->data->AtomicBuffers[i];
+ stage_buff_list[j]++;
+ }
+ }
+ }
+}
+
static void
write_xfb(struct blob *metadata, struct gl_shader_program *shProg)
{
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].atomic_buffer_index);
blob_write_uint32(metadata, prog->data->UniformStorage[i].offset);
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));
}
+
+ /* Here we cache all uniform values. We do this to retain values for
+ * uniforms with initialisers and also hidden uniforms that may be lowered
+ * constant arrays. We could possibly just store the values we need but for
+ * now we just store everything.
+ */
+ blob_write_uint32(metadata, prog->data->NumHiddenUniforms);
+ for (unsigned i = 0; i < prog->data->NumUniformStorage; i++) {
+ if (has_uniform_storage(prog, i)) {
+ unsigned vec_size =
+ 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);
+ }
+ }
}
static void
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].atomic_buffer_index = blob_read_uint32(metadata);
uniforms[i].offset = 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 (has_uniform_storage(prog, i)) {
+ unsigned vec_size =
+ 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,
+ sizeof(union gl_constant_value) * vec_size);
+
+ assert(vec_size + prog->data->UniformStorage[i].storage <=
+ data + prog->data->NumUniformDataSlots);
+ }
+ }
}
enum uniform_remap_type
}
static void
-write_uniform_remap_table(struct blob *metadata,
- struct gl_shader_program *prog)
+write_uniform_remap_tables(struct blob *metadata,
+ struct gl_shader_program *prog)
{
blob_write_uint32(metadata, prog->NumUniformRemapTable);
write_uniform_remap_table_entry(metadata, prog->data->UniformStorage,
prog->UniformRemapTable[i]);
}
+
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_linked_shader *sh = prog->_LinkedShaders[i];
+ if (sh) {
+ struct gl_program *glprog = sh->Program;
+ blob_write_uint32(metadata, glprog->sh.NumSubroutineUniformRemapTable);
+
+ for (unsigned j = 0; j < glprog->sh.NumSubroutineUniformRemapTable; j++) {
+ write_uniform_remap_table_entry(metadata,
+ prog->data->UniformStorage,
+ glprog->sh.SubroutineUniformRemapTable[j]);
+ }
+ }
+ }
}
static void
}
static void
-read_uniform_remap_table(struct blob_reader *metadata,
- struct gl_shader_program *prog)
+read_uniform_remap_tables(struct blob_reader *metadata,
+ struct gl_shader_program *prog)
{
prog->NumUniformRemapTable = blob_read_uint32(metadata);
read_uniform_remap_table_entry(metadata, prog->data->UniformStorage,
&prog->UniformRemapTable[i], type);
}
+
+ for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
+ struct gl_linked_shader *sh = prog->_LinkedShaders[i];
+ if (sh) {
+ struct gl_program *glprog = sh->Program;
+ glprog->sh.NumSubroutineUniformRemapTable = blob_read_uint32(metadata);
+
+ glprog->sh.SubroutineUniformRemapTable =
+ rzalloc_array(glprog, struct gl_uniform_storage *,
+ glprog->sh.NumSubroutineUniformRemapTable);
+
+ for (unsigned j = 0; j < glprog->sh.NumSubroutineUniformRemapTable; j++) {
+ enum uniform_remap_type type =
+ (enum uniform_remap_type) blob_read_uint32(metadata);
+
+ read_uniform_remap_table_entry(metadata,
+ prog->data->UniformStorage,
+ &glprog->sh.SubroutineUniformRemapTable[j],
+ type);
+ }
+ }
+ }
}
struct whte_closure
}
}
+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:
+ for (unsigned i = 0; i < prog->data->NumUniformBlocks; i++) {
+ if (strcmp(((gl_uniform_block *)res->Data)->Name,
+ prog->data->UniformBlocks[i].Name) == 0) {
+ blob_write_uint32(metadata, i);
+ break;
+ }
+ }
+ break;
+ case GL_SHADER_STORAGE_BLOCK:
+ for (unsigned i = 0; i < prog->data->NumShaderStorageBlocks; i++) {
+ if (strcmp(((gl_uniform_block *)res->Data)->Name,
+ prog->data->ShaderStorageBlocks[i].Name) == 0) {
+ blob_write_uint32(metadata, i);
+ break;
+ }
+ }
+ break;
case GL_BUFFER_VARIABLE:
case GL_VERTEX_SUBROUTINE_UNIFORM:
case GL_GEOMETRY_SUBROUTINE_UNIFORM:
}
}
break;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ for (unsigned i = 0; i < prog->data->NumAtomicBuffers; i++) {
+ if (((gl_active_atomic_buffer *)res->Data)->Binding ==
+ prog->data->AtomicBuffers[i].Binding) {
+ blob_write_uint32(metadata, i);
+ break;
+ }
+ }
+ break;
case GL_TRANSFORM_FEEDBACK_BUFFER:
for (unsigned i = 0; i < MAX_FEEDBACK_BUFFERS; i++) {
if (((gl_transform_feedback_buffer *)res->Data)->Binding ==
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;
}
+ case GL_UNIFORM_BLOCK:
+ res->Data = &prog->data->UniformBlocks[blob_read_uint32(metadata)];
+ break;
+ case GL_SHADER_STORAGE_BLOCK:
+ res->Data = &prog->data->ShaderStorageBlocks[blob_read_uint32(metadata)];
+ break;
case GL_BUFFER_VARIABLE:
case GL_VERTEX_SUBROUTINE_UNIFORM:
case GL_GEOMETRY_SUBROUTINE_UNIFORM:
case GL_UNIFORM:
res->Data = &prog->data->UniformStorage[blob_read_uint32(metadata)];
break;
+ case GL_ATOMIC_COUNTER_BUFFER:
+ res->Data = &prog->data->AtomicBuffers[blob_read_uint32(metadata)];
+ break;
case GL_TRANSFORM_FEEDBACK_BUFFER:
res->Data = &prog->last_vert_prog->
sh.LinkedTransformFeedback->Buffers[blob_read_uint32(metadata)];
uint32_t i = 0;
uint32_t num_parameters = blob_read_uint32(metadata);
+ _mesa_reserve_parameter_storage(params, num_parameters);
while (i < num_parameters) {
gl_register_file type = (gl_register_file) blob_read_uint32(metadata);
const char *name = blob_read_string(metadata);
{
assert(shader->Program);
struct gl_program *glprog = shader->Program;
+ unsigned i;
blob_write_bytes(metadata, glprog->TexturesUsed,
sizeof(glprog->TexturesUsed));
sizeof(glprog->sh.SamplerTargets));
blob_write_uint32(metadata, glprog->ShadowSamplers);
+ blob_write_bytes(metadata, glprog->sh.ImageAccess,
+ sizeof(glprog->sh.ImageAccess));
+ 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);
sizeof(glprog->sh.SamplerTargets));
glprog->ShadowSamplers = blob_read_uint32(metadata);
+ blob_copy_bytes(metadata, (uint8_t *) glprog->sh.ImageAccess,
+ sizeof(glprog->sh.ImageAccess));
+ 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);
* 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_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_table(metadata, prog);
+ write_atomic_buffers(&metadata, prog);
- write_subroutines(metadata, prog);
+ write_buffer_blocks(&metadata, prog);
- write_program_resource_list(metadata, prog);
+ write_subroutines(&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) {
- 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_finish(&metadata);
}
bool
return false;
struct disk_cache *cache = ctx->Cache;
- if (!cache)
+ if (!cache || prog->data->skip_cache)
return false;
/* Include bindings when creating sha1. These bindings change the resulting
ralloc_asprintf_append(&buf, "sso: %s\n",
prog->SeparateShader ? "T" : "F");
+ /* A shader might end up producing different output depending on the glsl
+ * version supported by the compiler. For example a different path might be
+ * taken by the preprocessor, so add the version to the hash input.
+ */
+ ralloc_asprintf_append(&buf, "api: %d glsl: %d fglsl: %d\n",
+ 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;
read_xfb(&metadata, prog);
- read_uniform_remap_table(&metadata, prog);
+ read_uniform_remap_tables(&metadata, prog);
+
+ read_atomic_buffers(&metadata, prog);
+
+ read_buffer_blocks(&metadata, prog);
read_subroutines(&metadata, prog);
/* 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;