From 46b03d5400794736e04eee5d373673309ba286ad Mon Sep 17 00:00:00 2001 From: Francisco Jerez Date: Tue, 10 Feb 2015 15:53:14 +0200 Subject: [PATCH] i965: Generalize the update_null_renderbuffer_surface vtbl hook to non-renderbuffers. Null surfaces are going to be useful to have something to point unbound image units to, as the ARB_shader_image_load_store extension requires us to behave deterministically in cases where some shader tries to access an unbound image unit: Invalid stores and atomics are supposed to be discarded and invalid loads are supposed to return zero, which is precisely what the null surface does. Reviewed-by: Kenneth Graunke --- src/mesa/drivers/dri/i965/brw_context.h | 9 ++-- src/mesa/drivers/dri/i965/brw_wm_surface_state.c | 53 +++++++++++++---------- src/mesa/drivers/dri/i965/gen7_wm_surface_state.c | 24 +++++----- src/mesa/drivers/dri/i965/gen8_surface_state.c | 25 +++++------ 4 files changed, 55 insertions(+), 56 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index 825358d..298e0fb 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -964,8 +964,6 @@ struct brw_context struct gl_renderbuffer *rb, bool layered, unsigned unit); - void (*update_null_renderbuffer_surface)(struct brw_context *brw, - unsigned unit); void (*create_raw_surface)(struct brw_context *brw, drm_intel_bo *bo, @@ -981,6 +979,11 @@ struct brw_context unsigned buffer_size, unsigned pitch, bool rw); + void (*emit_null_surface_state)(struct brw_context *brw, + unsigned width, + unsigned height, + unsigned samples, + uint32_t *out_offset); /** * Send the appropriate state packets to configure depth, stencil, and @@ -1330,7 +1333,7 @@ struct brw_context /** * Buffer object used in place of multisampled null render targets on - * Gen6. See brw_update_null_renderbuffer_surface(). + * Gen6. See brw_emit_null_surface_state(). */ drm_intel_bo *multisampled_null_render_target_bo; uint32_t fast_clear_op; diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c index 5f81402..ec4dfdb 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c @@ -516,7 +516,11 @@ const struct brw_tracked_state brw_wm_pull_constants = { * hardware discard the target 0 color output.. */ static void -brw_update_null_renderbuffer_surface(struct brw_context *brw, unsigned int unit) +brw_emit_null_surface_state(struct brw_context *brw, + unsigned width, + unsigned height, + unsigned samples, + uint32_t *out_offset) { /* From the Sandy bridge PRM, Vol4 Part1 p71 (Surface Type: Programming * Notes): @@ -536,23 +540,14 @@ brw_update_null_renderbuffer_surface(struct brw_context *brw, unsigned int unit) * * - Surface Format must be R8G8B8A8_UNORM. */ - struct gl_context *ctx = &brw->ctx; - uint32_t *surf; unsigned surface_type = BRW_SURFACE_NULL; drm_intel_bo *bo = NULL; unsigned pitch_minus_1 = 0; uint32_t multisampling_state = 0; - /* BRW_NEW_FS_PROG_DATA */ - uint32_t surf_index = - brw->wm.prog_data->binding_table.render_target_start + unit; - - /* _NEW_BUFFERS */ - const struct gl_framebuffer *fb = ctx->DrawBuffer; - - surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, 6 * 4, 32, - &brw->wm.base.surf_offset[surf_index]); + uint32_t *surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, 6 * 4, 32, + out_offset); - if (fb->Visual.samples > 1) { + if (samples > 1) { /* On Gen6, null render targets seem to cause GPU hangs when * multisampling. So work around this problem by rendering into dummy * color buffer. @@ -567,16 +562,15 @@ brw_update_null_renderbuffer_surface(struct brw_context *brw, unsigned int unit) * width_in_tiles and height_in_tiles by dividing the width and height * by 16 rather than the normal Y-tile size of 32. */ - unsigned width_in_tiles = ALIGN(fb->Width, 16) / 16; - unsigned height_in_tiles = ALIGN(fb->Height, 16) / 16; + unsigned width_in_tiles = ALIGN(width, 16) / 16; + unsigned height_in_tiles = ALIGN(height, 16) / 16; unsigned size_needed = (width_in_tiles + height_in_tiles - 1) * 4096; brw_get_scratch_bo(brw, &brw->wm.multisampled_null_render_target_bo, size_needed); bo = brw->wm.multisampled_null_render_target_bo; surface_type = BRW_SURFACE_2D; pitch_minus_1 = 127; - multisampling_state = - brw_get_surface_num_multisamples(fb->Visual.samples); + multisampling_state = brw_get_surface_num_multisamples(samples); } surf[0] = (surface_type << BRW_SURFACE_TYPE_SHIFT | @@ -588,8 +582,8 @@ brw_update_null_renderbuffer_surface(struct brw_context *brw, unsigned int unit) 1 << BRW_SURFACE_WRITEDISABLE_A_SHIFT); } surf[1] = bo ? bo->offset64 : 0; - surf[2] = ((fb->Width - 1) << BRW_SURFACE_WIDTH_SHIFT | - (fb->Height - 1) << BRW_SURFACE_HEIGHT_SHIFT); + surf[2] = ((width - 1) << BRW_SURFACE_WIDTH_SHIFT | + (height - 1) << BRW_SURFACE_HEIGHT_SHIFT); /* From Sandy bridge PRM, Vol4 Part1 p82 (Tiled Surface: Programming * Notes): @@ -603,7 +597,7 @@ brw_update_null_renderbuffer_surface(struct brw_context *brw, unsigned int unit) if (bo) { drm_intel_bo_emit_reloc(brw->batch.bo, - brw->wm.base.surf_offset[surf_index] + 4, + *out_offset + 4, bo, 0, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); } @@ -723,6 +717,8 @@ static void brw_update_renderbuffer_surfaces(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; + /* _NEW_BUFFERS */ + const struct gl_framebuffer *fb = ctx->DrawBuffer; GLuint i; /* _NEW_BUFFERS | _NEW_COLOR */ @@ -733,11 +729,21 @@ brw_update_renderbuffer_surfaces(struct brw_context *brw) brw->vtbl.update_renderbuffer_surface(brw, ctx->DrawBuffer->_ColorDrawBuffers[i], ctx->DrawBuffer->MaxNumLayers > 0, i); } else { - brw->vtbl.update_null_renderbuffer_surface(brw, i); + const uint32_t surf_index = + brw->wm.prog_data->binding_table.render_target_start + i; + + brw->vtbl.emit_null_surface_state( + brw, fb->Width, fb->Height, fb->Visual.samples, + &brw->wm.base.surf_offset[surf_index]); } } } else { - brw->vtbl.update_null_renderbuffer_surface(brw, 0); + const uint32_t surf_index = + brw->wm.prog_data->binding_table.render_target_start; + + brw->vtbl.emit_null_surface_state( + brw, fb->Width, fb->Height, fb->Visual.samples, + &brw->wm.base.surf_offset[surf_index]); } brw->state.dirty.brw |= BRW_NEW_SURFACES; } @@ -967,7 +973,6 @@ gen4_init_vtable_surface_functions(struct brw_context *brw) { brw->vtbl.update_texture_surface = brw_update_texture_surface; brw->vtbl.update_renderbuffer_surface = brw_update_renderbuffer_surface; - brw->vtbl.update_null_renderbuffer_surface = - brw_update_null_renderbuffer_surface; + brw->vtbl.emit_null_surface_state = brw_emit_null_surface_state; brw->vtbl.emit_buffer_surface_state = gen4_emit_buffer_surface_state; } diff --git a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c index 29553cd..12b588f 100644 --- a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c @@ -391,7 +391,7 @@ gen7_create_raw_surface(struct brw_context *brw, drm_intel_bo *bo, } /** - * Creates a null renderbuffer surface. + * Creates a null surface. * * This is used when the shader doesn't write to any color output. An FB * write to target 0 will still be emitted, because that's how the thread is @@ -399,7 +399,11 @@ gen7_create_raw_surface(struct brw_context *brw, drm_intel_bo *bo, * hardware discard the target 0 color output.. */ static void -gen7_update_null_renderbuffer_surface(struct brw_context *brw, unsigned unit) +gen7_emit_null_surface_state(struct brw_context *brw, + unsigned width, + unsigned height, + unsigned samples, + uint32_t *out_offset) { /* From the Ivy bridge PRM, Vol4 Part1 p62 (Surface Type: Programming * Notes): @@ -416,15 +420,8 @@ gen7_update_null_renderbuffer_surface(struct brw_context *brw, unsigned unit) * depth buffer’s corresponding state for all render target surfaces, * including null. */ - struct gl_context *ctx = &brw->ctx; - - /* _NEW_BUFFERS */ - const struct gl_framebuffer *fb = ctx->DrawBuffer; - uint32_t surf_index = - brw->wm.prog_data->binding_table.render_target_start + unit; - uint32_t *surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, 8 * 4, 32, - &brw->wm.base.surf_offset[surf_index]); + out_offset); memset(surf, 0, 8 * 4); /* From the Ivybridge PRM, Volume 4, Part 1, page 65, @@ -435,8 +432,8 @@ gen7_update_null_renderbuffer_surface(struct brw_context *brw, unsigned unit) BRW_SURFACEFORMAT_B8G8R8A8_UNORM << BRW_SURFACE_FORMAT_SHIFT | GEN7_SURFACE_TILING_Y; - surf[2] = SET_FIELD(fb->Width - 1, GEN7_SURFACE_WIDTH) | - SET_FIELD(fb->Height - 1, GEN7_SURFACE_HEIGHT); + surf[2] = SET_FIELD(width - 1, GEN7_SURFACE_WIDTH) | + SET_FIELD(height - 1, GEN7_SURFACE_HEIGHT); gen7_check_surface_setup(surf, true /* is_render_target */); } @@ -565,8 +562,7 @@ gen7_init_vtable_surface_functions(struct brw_context *brw) { brw->vtbl.update_texture_surface = gen7_update_texture_surface; brw->vtbl.update_renderbuffer_surface = gen7_update_renderbuffer_surface; - brw->vtbl.update_null_renderbuffer_surface = - gen7_update_null_renderbuffer_surface; + brw->vtbl.emit_null_surface_state = gen7_emit_null_surface_state; brw->vtbl.create_raw_surface = gen7_create_raw_surface; brw->vtbl.emit_buffer_surface_state = gen7_emit_buffer_surface_state; } diff --git a/src/mesa/drivers/dri/i965/gen8_surface_state.c b/src/mesa/drivers/dri/i965/gen8_surface_state.c index 113404c..d6b870e 100644 --- a/src/mesa/drivers/dri/i965/gen8_surface_state.c +++ b/src/mesa/drivers/dri/i965/gen8_surface_state.c @@ -290,7 +290,7 @@ gen8_create_raw_surface(struct brw_context *brw, drm_intel_bo *bo, } /** - * Creates a null renderbuffer surface. + * Creates a null surface. * * This is used when the shader doesn't write to any color output. An FB * write to target 0 will still be emitted, because that's how the thread is @@ -298,23 +298,19 @@ gen8_create_raw_surface(struct brw_context *brw, drm_intel_bo *bo, * hardware discard the target 0 color output.. */ static void -gen8_update_null_renderbuffer_surface(struct brw_context *brw, unsigned unit) +gen8_emit_null_surface_state(struct brw_context *brw, + unsigned width, + unsigned height, + unsigned samples, + uint32_t *out_offset) { - struct gl_context *ctx = &brw->ctx; - - /* _NEW_BUFFERS */ - const struct gl_framebuffer *fb = ctx->DrawBuffer; - uint32_t surf_index = - brw->wm.prog_data->binding_table.render_target_start + unit; - - uint32_t *surf = - allocate_surface_state(brw, &brw->wm.base.surf_offset[surf_index]); + uint32_t *surf = allocate_surface_state(brw, out_offset); surf[0] = BRW_SURFACE_NULL << BRW_SURFACE_TYPE_SHIFT | BRW_SURFACEFORMAT_B8G8R8A8_UNORM << BRW_SURFACE_FORMAT_SHIFT | GEN8_SURFACE_TILING_Y; - surf[2] = SET_FIELD(fb->Width - 1, GEN7_SURFACE_WIDTH) | - SET_FIELD(fb->Height - 1, GEN7_SURFACE_HEIGHT); + surf[2] = SET_FIELD(width - 1, GEN7_SURFACE_WIDTH) | + SET_FIELD(height - 1, GEN7_SURFACE_HEIGHT); } /** @@ -459,8 +455,7 @@ gen8_init_vtable_surface_functions(struct brw_context *brw) { brw->vtbl.update_texture_surface = gen8_update_texture_surface; brw->vtbl.update_renderbuffer_surface = gen8_update_renderbuffer_surface; - brw->vtbl.update_null_renderbuffer_surface = - gen8_update_null_renderbuffer_surface; + brw->vtbl.emit_null_surface_state = gen8_emit_null_surface_state; brw->vtbl.create_raw_surface = gen8_create_raw_surface; brw->vtbl.emit_buffer_surface_state = gen8_emit_buffer_surface_state; } -- 2.7.4