#include "compiler/glsl/ir_uniform.h"
#include "compiler/glsl/shader_cache.h"
#include "main/mtypes.h"
+#include "util/build_id.h"
+#include "util/debug.h"
#include "util/disk_cache.h"
#include "util/macros.h"
#include "util/mesa-sha1.h"
+#include "compiler/brw_eu.h"
+#include "common/gen_debug.h"
+
#include "brw_context.h"
#include "brw_program.h"
#include "brw_cs.h"
#include "brw_vs.h"
#include "brw_wm.h"
+static bool
+debug_enabled_for_stage(gl_shader_stage stage)
+{
+ static const uint64_t stage_debug_flags[] = {
+ DEBUG_VS, DEBUG_TCS, DEBUG_TES, DEBUG_GS, DEBUG_WM, DEBUG_CS,
+ };
+ assert((int)stage >= 0 && stage < ARRAY_SIZE(stage_debug_flags));
+ return (INTEL_DEBUG & stage_debug_flags[stage]) != 0;
+}
+
static void
gen_shader_sha1(struct brw_context *brw, struct gl_program *prog,
gl_shader_stage stage, void *key, unsigned char *out_sha1)
_mesa_sha1_compute(manifest, strlen(manifest), out_sha1);
}
-static void
-write_blob_program_data(struct blob *binary, gl_shader_stage stage,
- const void *program,
- struct brw_stage_prog_data *prog_data)
-{
- /* Write prog_data to blob. */
- blob_write_bytes(binary, prog_data, brw_prog_data_size(stage));
-
- /* Write program to blob. */
- blob_write_bytes(binary, program, prog_data->program_size);
-
- /* Write push params */
- blob_write_bytes(binary, prog_data->param,
- sizeof(uint32_t) * prog_data->nr_params);
-
- /* Write pull params */
- blob_write_bytes(binary, prog_data->pull_param,
- sizeof(uint32_t) * prog_data->nr_pull_params);
-}
-
static bool
read_blob_program_data(struct blob_reader *binary, struct gl_program *prog,
gl_shader_stage stage, const uint8_t **program,
struct brw_stage_prog_data *prog_data)
{
- /* Read shader prog_data from blob. */
- blob_copy_bytes(binary, prog_data, brw_prog_data_size(stage));
- if (binary->overrun)
- return false;
-
- /* Read shader program from blob. */
- *program = blob_read_bytes(binary, prog_data->program_size);
-
- /* Read push params */
- prog_data->param = rzalloc_array(NULL, uint32_t, prog_data->nr_params);
- blob_copy_bytes(binary, prog_data->param,
- sizeof(uint32_t) * prog_data->nr_params);
-
- /* Read pull params */
- prog_data->pull_param = rzalloc_array(NULL, uint32_t,
- prog_data->nr_pull_params);
- blob_copy_bytes(binary, prog_data->pull_param,
- sizeof(uint32_t) * prog_data->nr_pull_params);
-
- return (binary->current == binary->end && !binary->overrun);
+ return
+ brw_read_blob_program_data(binary, prog, stage, program, prog_data) &&
+ (binary->current == binary->end);
}
static bool
switch (stage) {
case MESA_SHADER_VERTEX:
brw_vs_populate_key(brw, &prog_key.vs);
- /* We don't care what instance of the program it is for the disk cache
- * hash lookup, so set the id to 0 for the sha1 hashing.
- * program_string_id will be set below.
- */
- prog_key.vs.program_string_id = 0;
break;
case MESA_SHADER_TESS_CTRL:
brw_tcs_populate_key(brw, &prog_key.tcs);
- prog_key.tcs.program_string_id = 0;
break;
case MESA_SHADER_TESS_EVAL:
brw_tes_populate_key(brw, &prog_key.tes);
- prog_key.tes.program_string_id = 0;
break;
case MESA_SHADER_GEOMETRY:
brw_gs_populate_key(brw, &prog_key.gs);
- prog_key.gs.program_string_id = 0;
break;
case MESA_SHADER_FRAGMENT:
brw_wm_populate_key(brw, &prog_key.wm);
- prog_key.wm.program_string_id = 0;
break;
case MESA_SHADER_COMPUTE:
brw_cs_populate_key(brw, &prog_key.cs);
- prog_key.cs.program_string_id = 0;
break;
default:
unreachable("Unsupported stage!");
}
+ /* We don't care what instance of the program it is for the disk cache hash
+ * lookup, so set the id to 0 for the sha1 hashing. program_string_id will
+ * be set below.
+ */
+ brw_prog_key_set_id(&prog_key, stage, 0);
+
gen_shader_sha1(brw, prog, stage, &prog_key, binary_sha1);
size_t buffer_size;
}
disk_cache_remove(cache, binary_sha1);
+ ralloc_free(prog_data);
free(buffer);
return false;
}
switch (stage) {
case MESA_SHADER_VERTEX:
- prog_key.vs.program_string_id = brw_program(prog)->id;
cache_id = BRW_CACHE_VS_PROG;
stage_state = &brw->vs.base;
break;
case MESA_SHADER_TESS_CTRL:
- prog_key.tcs.program_string_id = brw_program(prog)->id;
cache_id = BRW_CACHE_TCS_PROG;
stage_state = &brw->tcs.base;
break;
case MESA_SHADER_TESS_EVAL:
- prog_key.tes.program_string_id = brw_program(prog)->id;
cache_id = BRW_CACHE_TES_PROG;
stage_state = &brw->tes.base;
break;
case MESA_SHADER_GEOMETRY:
- prog_key.gs.program_string_id = brw_program(prog)->id;
cache_id = BRW_CACHE_GS_PROG;
stage_state = &brw->gs.base;
break;
case MESA_SHADER_FRAGMENT:
- prog_key.wm.program_string_id = brw_program(prog)->id;
cache_id = BRW_CACHE_FS_PROG;
stage_state = &brw->wm.base;
break;
case MESA_SHADER_COMPUTE:
- prog_key.cs.program_string_id = brw_program(prog)->id;
cache_id = BRW_CACHE_CS_PROG;
stage_state = &brw->cs.base;
break;
unreachable("Unsupported stage!");
}
+ brw_prog_key_set_id(&prog_key, stage, brw_program(prog)->id);
+
brw_alloc_stage_scratch(brw, stage_state, prog_data->total_scratch);
+ if (unlikely(debug_enabled_for_stage(stage))) {
+ fprintf(stderr, "NIR for %s program %d loaded from disk shader cache:\n",
+ _mesa_shader_stage_to_abbrev(stage), brw_program(prog)->id);
+ brw_program_deserialize_driver_blob(&brw->ctx, prog, stage);
+ nir_shader *nir = prog->nir;
+ nir_print_shader(nir, stderr);
+ fprintf(stderr, "Native code for %s %s shader %s from disk cache:\n",
+ nir->info.label ? nir->info.label : "unnamed",
+ _mesa_shader_stage_to_string(nir->info.stage), nir->info.name);
+ brw_disassemble(&brw->screen->devinfo, program, 0,
+ prog_data->program_size, stderr);
+ }
+
brw_upload_cache(&brw->cache, cache_id, &prog_key, brw_prog_key_size(stage),
program, prog_data->program_size, prog_data,
brw_prog_data_size(stage), &stage_state->prog_offset,
prog->program_written_to_cache = true;
+ ralloc_free(prog_data);
free(buffer);
return true;
if (prog == NULL)
return false;
- /* FIXME: For now we don't read from the cache if transform feedback is
- * enabled via the API. However the shader cache does support transform
- * feedback when enabled via in shader xfb qualifiers.
- */
- if (prog->sh.LinkedTransformFeedback &&
- prog->sh.LinkedTransformFeedback->api_enabled)
- return false;
-
- if (prog->sh.data->LinkStatus != linking_skipped)
+ if (brw->ctx._Shader->Flags & GLSL_CACHE_FALLBACK)
goto fail;
if (!read_and_upload(brw, cache, prog, stage))
return true;
fail:
- /*FIXME: Fall back and compile from source here. */
+ prog->program_written_to_cache = false;
+ if (brw->ctx._Shader->Flags & GLSL_CACHE_INFO) {
+ fprintf(stderr, "falling back to nir %s.\n",
+ _mesa_shader_stage_to_abbrev(prog->info.stage));
+ }
+
+ brw_program_deserialize_driver_blob(&brw->ctx, prog, stage);
+
return false;
}
* generation time when the program is in normal memory accessible with
* cache to the CPU. Another easier change would be to use
* _mesa_streaming_load_memcpy to read from the program mapped memory. */
- write_blob_program_data(&binary, stage, program_map, prog_data);
+ brw_write_blob_program_data(&binary, stage, program_map, prog_data);
unsigned char sha1[20];
char buf[41];
MESA_SHADER_COMPUTE);
}
}
+
+void
+brw_disk_cache_init(struct intel_screen *screen)
+{
+#ifdef ENABLE_SHADER_CACHE
+ if (INTEL_DEBUG & DEBUG_DISK_CACHE_DISABLE_MASK)
+ return;
+
+ /* array length: print length + null char + 1 extra to verify it is unused */
+ char renderer[11];
+ MAYBE_UNUSED int len = snprintf(renderer, sizeof(renderer), "i965_%04x",
+ screen->deviceID);
+ assert(len == sizeof(renderer) - 2);
+
+ const struct build_id_note *note =
+ build_id_find_nhdr_for_addr(brw_disk_cache_init);
+ assert(note && build_id_length(note) == 20 /* sha1 */);
+
+ const uint8_t *id_sha1 = build_id_data(note);
+ assert(id_sha1);
+
+ char timestamp[41];
+ _mesa_sha1_format(timestamp, id_sha1);
+
+ const uint64_t driver_flags = INTEL_DEBUG & DEBUG_DISK_CACHE_MASK;
+ screen->disk_cache = disk_cache_create(renderer, timestamp, driver_flags);
+#endif
+}