#include "program/prog_parameter.h"
#include "program/program.h"
#include "intel_mipmap_tree.h"
+#include "brw_nir.h"
#include "util/ralloc.h"
return BRW_PSCDEPTH_OFF;
}
-bool
-brw_wm_prog_data_compare(const void *in_a, const void *in_b)
+static void
+assign_fs_binding_table_offsets(const struct brw_device_info *devinfo,
+ const struct gl_shader_program *shader_prog,
+ const struct gl_program *prog,
+ const struct brw_wm_prog_key *key,
+ struct brw_wm_prog_data *prog_data)
{
- const struct brw_wm_prog_data *a = in_a;
- const struct brw_wm_prog_data *b = in_b;
+ uint32_t next_binding_table_offset = 0;
- /* Compare the base structure. */
- if (!brw_stage_prog_data_compare(&a->base, &b->base))
- return false;
-
- /* Compare the rest of the structure. */
- const unsigned offset = sizeof(struct brw_stage_prog_data);
- if (memcmp(((char *) a) + offset, ((char *) b) + offset,
- sizeof(struct brw_wm_prog_data) - offset))
- return false;
+ /* If there are no color regions, we still perform an FB write to a null
+ * renderbuffer, which we place at surface index 0.
+ */
+ prog_data->binding_table.render_target_start = next_binding_table_offset;
+ next_binding_table_offset += MAX2(key->nr_color_regions, 1);
- return true;
+ brw_assign_common_binding_table_offsets(MESA_SHADER_FRAGMENT, devinfo,
+ shader_prog, prog, &prog_data->base,
+ next_binding_table_offset);
}
/**
void *mem_ctx = ralloc_context(NULL);
struct brw_wm_prog_data prog_data;
const GLuint *program;
- struct gl_shader *fs = NULL;
+ struct brw_shader *fs = NULL;
GLuint program_size;
+ bool start_busy = false;
+ double start_time = 0;
if (prog)
- fs = prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
+ fs = (struct brw_shader *)prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
memset(&prog_data, 0, sizeof(prog_data));
/* key->alpha_test_func means simulating alpha testing via discards,
fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK);
prog_data.computed_depth_mode = computed_depth_mode(&fp->program);
- prog_data.early_fragment_tests = fs && fs->EarlyFragmentTests;
+ prog_data.early_fragment_tests = fs && fs->base.EarlyFragmentTests;
/* Use ALT floating point mode for ARB programs so that 0^0 == 1. */
if (!prog)
prog_data.base.use_alt_mode = true;
+ assign_fs_binding_table_offsets(brw->intelScreen->devinfo, prog,
+ &fp->program.Base, key, &prog_data);
+
/* Allocate the references to the uniforms that will end up in the
* prog_data associated with the compiled program, and which will be freed
* by the state cache.
*/
- int param_count;
- if (fs) {
- param_count = fs->num_uniform_components +
- fs->NumImages * BRW_IMAGE_PARAM_SIZE;
- prog_data.base.nr_image_params = fs->NumImages;
- } else {
- param_count = fp->program.Base.Parameters->NumParameters * 4;
- }
+ int param_count = fp->program.Base.nir->num_uniforms;
+ if (fs)
+ prog_data.base.nr_image_params = fs->base.NumImages;
/* The backend also sometimes adds params for texture size. */
param_count += 2 * ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits;
prog_data.base.param =
prog_data.base.nr_image_params);
prog_data.base.nr_params = param_count;
+ if (prog) {
+ brw_nir_setup_glsl_uniforms(fp->program.Base.nir, prog, &fp->program.Base,
+ &prog_data.base, true);
+ } else {
+ brw_nir_setup_arb_uniforms(fp->program.Base.nir, &fp->program.Base,
+ &prog_data.base);
+ }
+
prog_data.barycentric_interp_modes =
brw_compute_barycentric_interp_modes(brw, key->flat_shade,
key->persample_shading,
&fp->program);
+ if (unlikely(brw->perf_debug)) {
+ start_busy = (brw->batch.last_bo &&
+ drm_intel_bo_busy(brw->batch.last_bo));
+ start_time = get_time();
+ }
+
program = brw_wm_fs_emit(brw, mem_ctx, key, &prog_data,
&fp->program, prog, &program_size);
if (program == NULL) {
return false;
}
+ if (unlikely(brw->perf_debug) && fs) {
+ if (fs->compiled_once)
+ brw_wm_debug_recompile(brw, prog, key);
+ fs->compiled_once = true;
+
+ if (start_busy && !drm_intel_bo_busy(brw->batch.last_bo)) {
+ perf_debug("FS compile took %.03f ms and stalled the GPU\n",
+ (get_time() - start_time) * 1000);
+ }
+ }
+
if (prog_data.base.total_scratch) {
brw_get_scratch_bo(brw, &brw->wm.base.scratch_bo,
prog_data.base.total_scratch * brw->max_wm_threads);