From 16f2e7e0fb1213b09c8c355ac3c67e25c9ab34ca Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Thu, 17 Nov 2011 10:17:06 +1000 Subject: [PATCH 01/41] nvc0: add support for GF119 (NVD9) Signed-off-by: Ben Skeggs --- src/gallium/drivers/nv50/codegen/nv50_ir_target.cpp | 1 + src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c | 1 + 2 files changed, 2 insertions(+) diff --git a/src/gallium/drivers/nv50/codegen/nv50_ir_target.cpp b/src/gallium/drivers/nv50/codegen/nv50_ir_target.cpp index b1c696899c7..6cd916004bb 100644 --- a/src/gallium/drivers/nv50/codegen/nv50_ir_target.cpp +++ b/src/gallium/drivers/nv50/codegen/nv50_ir_target.cpp @@ -59,6 +59,7 @@ Target *Target::create(unsigned int chipset) { switch (chipset & 0xf0) { case 0xc0: + case 0xd0: return getTargetNVC0(chipset); case 0x50: case 0x80: diff --git a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c index 648d6c8a8e2..7d7a2769fa4 100644 --- a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c +++ b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c @@ -51,6 +51,7 @@ nouveau_drm_screen_create(int fd) init = nv50_screen_create; break; case 0xc0: + case 0xd0: init = nvc0_screen_create; break; default: From 3d2235e6c76a8a6aef2a14ca57c68403cf056921 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Wed, 16 Nov 2011 22:10:11 -0800 Subject: [PATCH 02/41] intel: Don't use special stencil span accessors The special stencil span accessors, as set by intel_span_init_funcs. perform software W detiling. Since intel_renderbuffer_map() now uses MapRenderbuffer, rb->Data points to an *untiled* stencil buffer. Fixes several Piglit tests on gen7. Reviewed-by: Eric Anholt Reviewed-by: Kenneth Graunke Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_span.c | 43 +------------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_span.c b/src/mesa/drivers/dri/intel/intel_span.c index 31f2828c395..afb0f32a833 100644 --- a/src/mesa/drivers/dri/intel/intel_span.c +++ b/src/mesa/drivers/dri/intel/intel_span.c @@ -114,40 +114,6 @@ intel_set_span_functions(struct intel_context *intel, #define TAG2(x,y) intel_##x##y##_A8 #include "spantmp2.h" -/* ------------------------------------------------------------------------- */ -/* s8 stencil span and pixel functions */ -/* ------------------------------------------------------------------------- */ - -/* - * HAVE_HW_STENCIL_SPANS determines if stencil buffer read/writes are done with - * memcpy or for loops. Since the stencil buffer is interleaved, memcpy won't - * work. - */ -#define HAVE_HW_STENCIL_SPANS 0 - -#define LOCAL_STENCIL_VARS \ - (void) ctx; \ - int minx = 0; \ - int miny = 0; \ - int maxx = rb->Width; \ - int maxy = rb->Height; \ - \ - /* \ - * Here we ignore rb->Data and rb->RowStride as set by \ - * intelSpanRenderStart. Since intel_offset_S8 decodes the W tile \ - * manually, the region's *real* base address and stride is \ - * required. \ - */ \ - struct intel_renderbuffer *irb = intel_renderbuffer(rb); \ - uint8_t *buf = irb->region->bo->virtual; \ - unsigned stride = irb->region->pitch; \ - bool flip = rb->Name == 0; \ - int y_scale = flip ? -1 : 1; \ - int y_bias = flip ? (rb->Height - 1) : 0; \ - -#undef Y_FLIP -#define Y_FLIP(y) (y_scale * (y) + y_bias) - /** * \brief Get pointer offset into stencil buffer. * @@ -210,13 +176,6 @@ intel_offset_S8(uint32_t stride, uint32_t x, uint32_t y) return u; } -#define WRITE_STENCIL(x, y, src) buf[intel_offset_S8(stride, x, y)] = src; -#define READ_STENCIL(dest, x, y) dest = buf[intel_offset_S8(stride, x, y)] -#define TAG(x) intel_##x##_S8 -#include "stenciltmp.h" - -/* ------------------------------------------------------------------------- */ - void intel_renderbuffer_map(struct intel_context *intel, struct gl_renderbuffer *rb) { @@ -405,7 +364,7 @@ static span_init_func intel_span_init_funcs[MESA_FORMAT_COUNT] = [MESA_FORMAT_Z16] = _mesa_set_renderbuffer_accessors, [MESA_FORMAT_X8_Z24] = _mesa_set_renderbuffer_accessors, [MESA_FORMAT_S8_Z24] = _mesa_set_renderbuffer_accessors, - [MESA_FORMAT_S8] = intel_InitStencilPointers_S8, + [MESA_FORMAT_S8] = _mesa_set_renderbuffer_accessors, [MESA_FORMAT_R8] = _mesa_set_renderbuffer_accessors, [MESA_FORMAT_RG88] = _mesa_set_renderbuffer_accessors, [MESA_FORMAT_R16] = _mesa_set_renderbuffer_accessors, From af35a3523df7f555427de4835ae092d1836c3c95 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Sun, 13 Nov 2011 17:45:51 -0800 Subject: [PATCH 03/41] intel: Fix swrast_render_start() for depthstencil buffers with separate stencil 1. Don't map the depthstencil buffer twice Place a guard in intel_renderbuffer_map() to prevent a renderbuffer from being mapped twice. This happened if a single buffer was attached to the framebuffer's depth and stencil attachment points. (Interestingly, because intel_map_renderbuffer_gtt() is idempotent, the double mapping did not cause bugs for depthstencil buffers *without* separate stencil). 2. Stop overriding gl_framebuffer::_DepthBuffer,_StencilBuffer Normally, if a depthstencil buffer is attached to the framebuffer's depth attachment point, then _mesa_update_framebuffer() installs a wrapper depth renderbuffer at gl_framebuffer::_DepthBuffer. Ditto for the stencil attachment point and gl_framebuffer::_StencilBuffer A depthstencil intel_renderbuffer with separate stencil contains hidden depth and stencil renderbuffers, which are the *real* renderbuffers. In order to force swrast to work, we were installing, in brw_update_draw_buffer(), the hidden renderbuffers at gl_framebuffer::_DepthBuffer and _StencilBuffer, thus overriding the behavior of _mesa_update_framebuffer(). However, now that intel_renderbuffer_map() is implemented with MapRenderbuffer(), overriding _mesa_update_framebuffer's introduces bugs. This patch removes the override code. Fixes several Piglit tests on gen7. Reviewed-by: Eric Anholt Reviewed-by: Kenneth Graunke Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i965/brw_vtbl.c | 22 +--------------------- src/mesa/drivers/dri/intel/intel_span.c | 22 ++++++++++++++-------- 2 files changed, 15 insertions(+), 29 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_vtbl.c b/src/mesa/drivers/dri/i965/brw_vtbl.c index 7c40f278b8a..7c23faa8fff 100644 --- a/src/mesa/drivers/dri/i965/brw_vtbl.c +++ b/src/mesa/drivers/dri/i965/brw_vtbl.c @@ -95,7 +95,7 @@ brw_update_draw_buffer(struct intel_context *intel) { struct gl_context *ctx = &intel->ctx; struct gl_framebuffer *fb = ctx->DrawBuffer; - struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL; + struct intel_renderbuffer *irbStencil = NULL; bool fb_has_hiz = intel_framebuffer_has_hiz(fb); if (!fb) { @@ -103,27 +103,7 @@ brw_update_draw_buffer(struct intel_context *intel) return; } - /* - * If intel_context is using separate stencil, but the depth attachment - * (gl_framebuffer.Attachment[BUFFER_DEPTH]) has a packed depth/stencil - * format, then we must install the real depth buffer at fb->_DepthBuffer - * and set fb->_DepthBuffer->Wrapped before calling _mesa_update_framebuffer. - * Otherwise, _mesa_update_framebuffer will create and install a swras - * depth wrapper instead. - * - * Ditto for stencil. - */ - irbDepth = intel_get_renderbuffer(fb, BUFFER_DEPTH); - if (irbDepth && irbDepth->Base.Format == MESA_FORMAT_X8_Z24) { - _mesa_reference_renderbuffer(&fb->_DepthBuffer, &irbDepth->Base); - irbDepth->Base.Wrapped = fb->Attachment[BUFFER_DEPTH].Renderbuffer; - } - irbStencil = intel_get_renderbuffer(fb, BUFFER_STENCIL); - if (irbStencil && irbStencil->Base.Format == MESA_FORMAT_S8) { - _mesa_reference_renderbuffer(&fb->_StencilBuffer, &irbStencil->Base); - irbStencil->Base.Wrapped = fb->Attachment[BUFFER_STENCIL].Renderbuffer; - } /* Do this here, not core Mesa, since this function is called from * many places within the driver. diff --git a/src/mesa/drivers/dri/intel/intel_span.c b/src/mesa/drivers/dri/intel/intel_span.c index afb0f32a833..b103bbd9f7f 100644 --- a/src/mesa/drivers/dri/intel/intel_span.c +++ b/src/mesa/drivers/dri/intel/intel_span.c @@ -187,10 +187,13 @@ intel_renderbuffer_map(struct intel_context *intel, struct gl_renderbuffer *rb) if (!irb) return; - if (irb->wrapped_depth) - intel_renderbuffer_map(intel, irb->wrapped_depth); - if (irb->wrapped_stencil) - intel_renderbuffer_map(intel, irb->wrapped_stencil); + if (rb->Data) { + /* Renderbuffer is already mapped. This usually happens when a single + * buffer is attached to the framebuffer's depth and stencil attachment + * points. + */ + return; + } ctx->Driver.MapRenderbuffer(ctx, rb, 0, 0, rb->Width, rb->Height, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, @@ -211,10 +214,13 @@ intel_renderbuffer_unmap(struct intel_context *intel, if (!irb) return; - if (irb->wrapped_depth) - intel_renderbuffer_unmap(intel, irb->wrapped_depth); - if (irb->wrapped_stencil) - intel_renderbuffer_unmap(intel, irb->wrapped_stencil); + if (!rb->Data) { + /* Renderbuffer is already unmapped. This usually happens when a single + * buffer is attached to the framebuffer's depth and stencil attachment + * points. + */ + return; + } ctx->Driver.UnmapRenderbuffer(ctx, rb); From 190aec75a4362b56b9b311975a777c56e8e6c67d Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Wed, 16 Nov 2011 16:02:39 -0800 Subject: [PATCH 04/41] intel: Always gather stencil buffer in intel_map_renderbuffer_separate_s8z24() The function gathered the stencil buffer into the depth buffer only when the map mode contained the read bit. But we must do the gather even if the map mode is write-only. If we do not, then, when the depth buffer's stencil bits are scattered into the stencil buffer by intel_unmap_renderbuffer(), some of the scattered stencil bits would be invalid. Reviewed-by: Eric Anholt Reviewed-by: Kenneth Graunke Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_fbo.c | 50 ++++++++++---------------- 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index a724f1d97b3..1bd16f06a38 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -321,11 +321,12 @@ intel_map_renderbuffer_separate_s8z24(struct gl_context *ctx, struct intel_context *intel = intel_context(ctx); struct intel_renderbuffer *irb = intel_renderbuffer(rb); - GLbitfield adjusted_mode; - uint8_t *s8z24_map; int32_t s8z24_stride; + struct intel_renderbuffer *s8_irb; + uint8_t *s8_map; + assert(rb->Name != 0); assert(rb->Format == MESA_FORMAT_S8_Z24); assert(irb->wrapped_depth != NULL); @@ -337,42 +338,29 @@ intel_map_renderbuffer_separate_s8z24(struct gl_context *ctx, irb->map_w = w; irb->map_h = h; - if (mode & GL_MAP_READ_BIT) { - /* Since the caller may read the stencil bits, we must copy the stencil - * buffer's contents into the depth buffer. This necessitates that the - * depth buffer be mapped in write mode. - */ - adjusted_mode = mode | GL_MAP_WRITE_BIT; - } else { - adjusted_mode = mode; - } - + /* Map with write mode for the gather below. */ intel_map_renderbuffer_gtt(ctx, irb->wrapped_depth, - x, y, w, h, adjusted_mode, + x, y, w, h, mode | GL_MAP_WRITE_BIT, &s8z24_map, &s8z24_stride); - if (mode & GL_MAP_READ_BIT) { - struct intel_renderbuffer *s8_irb; - uint8_t *s8_map; + s8_irb = intel_renderbuffer(irb->wrapped_stencil); + s8_map = intel_region_map(intel, s8_irb->region, GL_MAP_READ_BIT); - s8_irb = intel_renderbuffer(irb->wrapped_stencil); - s8_map = intel_region_map(intel, s8_irb->region, GL_MAP_READ_BIT); - - for (uint32_t pix_y = 0; pix_y < h; ++pix_y) { - for (uint32_t pix_x = 0; pix_x < w; ++pix_x) { - ptrdiff_t s8_offset = intel_offset_S8(s8_irb->region->pitch, - x + pix_x, - y + pix_y); - ptrdiff_t s8z24_offset = pix_y * s8z24_stride - + pix_x * 4 - + 3; - s8z24_map[s8z24_offset] = s8_map[s8_offset]; - } + /* Gather the stencil buffer into the depth buffer. */ + for (uint32_t pix_y = 0; pix_y < h; ++pix_y) { + for (uint32_t pix_x = 0; pix_x < w; ++pix_x) { + ptrdiff_t s8_offset = intel_offset_S8(s8_irb->region->pitch, + x + pix_x, + y + pix_y); + ptrdiff_t s8z24_offset = pix_y * s8z24_stride + + pix_x * 4 + + 3; + s8z24_map[s8z24_offset] = s8_map[s8_offset]; } - - intel_region_unmap(intel, s8_irb->region); } + intel_region_unmap(intel, s8_irb->region); + *out_map = s8z24_map; *out_stride = s8z24_stride; } From 7e9b3c098c58af49a809afbc17d508f23eab21c2 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Sun, 13 Nov 2011 23:02:04 -0800 Subject: [PATCH 05/41] intel: Temporarily disable HiZ for textures A great refactor thrashing begins after this commit for HiZ and separate stencil. Removing code for texture HiZ will make that refactoring easier, because then we don't have to maintain that code during the refactor. To disable HiZ for textures, I've removed the hook in intel_update_wrapper() that allocates a HiZ buffer when attaching a depth texture to a framebuffer. HiZ was broken for textures anyway, so there's no regression here. Reviewed-by: Eric Anholt Reviewed-by: Kenneth Graunke Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_fbo.c | 62 ++------------------------ 1 file changed, 3 insertions(+), 59 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index 1bd16f06a38..16b49ae311d 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -926,16 +926,10 @@ intel_framebuffer_renderbuffer(struct gl_context * ctx, intel_draw_buffer(ctx); } -static bool -intel_update_tex_wrapper_regions(struct intel_context *intel, - struct intel_renderbuffer *irb, - struct intel_texture_image *intel_image); - static bool intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb, struct gl_texture_image *texImage) { - struct intel_context *intel = intel_context(ctx); struct intel_texture_image *intel_image = intel_texture_image(texImage); int width, height, depth; @@ -961,70 +955,20 @@ intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb, if (intel_image->stencil_rb) { /* The tex image has packed depth/stencil format, but is using separate - * stencil. */ - - bool ok; - struct intel_renderbuffer *depth_irb = - intel_renderbuffer(intel_image->depth_rb); - - /* Update the hiz region if necessary. */ - ok = intel_update_tex_wrapper_regions(intel, depth_irb, intel_image); - if (!ok) { - return false; - } - - /* The tex image shares its embedded depth and stencil renderbuffers with - * the renderbuffer wrapper. */ + * stencil. It shares its embedded depth and stencil renderbuffers with + * the renderbuffer wrapper. + */ _mesa_reference_renderbuffer(&irb->wrapped_depth, intel_image->depth_rb); _mesa_reference_renderbuffer(&irb->wrapped_stencil, intel_image->stencil_rb); - - return true; } else { - return intel_update_tex_wrapper_regions(intel, irb, intel_image); - } -} - -/** - * FIXME: The handling of the hiz region is broken for mipmapped depth textures - * FIXME: because intel_finalize_mipmap_tree is unaware of it. - */ -static bool -intel_update_tex_wrapper_regions(struct intel_context *intel, - struct intel_renderbuffer *irb, - struct intel_texture_image *intel_image) -{ - struct gl_renderbuffer *rb = &irb->Base; - - /* Point the renderbuffer's region to the texture's region. */ - if (irb->region != intel_image->mt->region) { intel_region_reference(&irb->region, intel_image->mt->region); } - /* Allocate the texture's hiz region if necessary. */ - if (intel->vtbl.is_hiz_depth_format(intel, rb->Format) - && !intel_image->mt->hiz_region) { - intel_image->mt->hiz_region = - intel_region_alloc(intel->intelScreen, - I915_TILING_Y, - _mesa_get_format_bytes(rb->Format), - rb->Width, - rb->Height, - true); - if (!intel_image->mt->hiz_region) - return false; - } - - /* Point the renderbuffer's hiz region to the texture's hiz region. */ - if (irb->hiz_region != intel_image->mt->hiz_region) { - intel_region_reference(&irb->hiz_region, intel_image->mt->hiz_region); - } - return true; } - /** * When glFramebufferTexture[123]D is called this function sets up the * gl_renderbuffer wrapper around the texture image. From 19faa12bb751eabc1590d042adbd345b89542de0 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Sun, 13 Nov 2011 23:05:47 -0800 Subject: [PATCH 06/41] intel: Kill intel_framebuffer_get_hiz_region() The only user of intel_framebuffer_get_hiz_region() was intel_framebuffer_has_hiz(). So I folded the body of the former into the latter. Reviewed-by: Eric Anholt Reviewed-by: Kenneth Graunke Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_fbo.h | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_fbo.h b/src/mesa/drivers/dri/intel/intel_fbo.h index 4cc57fe60be..b46700a2509 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.h +++ b/src/mesa/drivers/dri/intel/intel_fbo.h @@ -134,27 +134,13 @@ intel_get_renderbuffer(struct gl_framebuffer *fb, gl_buffer_index attIndex) return irb; } -/** - * If the framebuffer has a depth buffer attached, then return its HiZ region. - * The HiZ region may be null. - */ -static INLINE struct intel_region* -intel_framebuffer_get_hiz_region(struct gl_framebuffer *fb) +static inline bool +intel_framebuffer_has_hiz(struct gl_framebuffer *fb) { struct intel_renderbuffer *rb = NULL; if (fb) rb = intel_get_renderbuffer(fb, BUFFER_DEPTH); - - if (rb) - return rb->hiz_region; - else - return NULL; -} - -static INLINE bool -intel_framebuffer_has_hiz(struct gl_framebuffer *fb) -{ - return intel_framebuffer_get_hiz_region(fb) != NULL; + return rb && rb->hiz_region; } extern struct intel_renderbuffer * From c3c7cbd15418293208034e8970d626b5998abd4b Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Sun, 13 Nov 2011 23:06:17 -0800 Subject: [PATCH 07/41] intel: Move inline functions from intel_fbo.h to .c Move the following inline functions: intel_get_rb_region intel_framebuffer_has_hiz A future commit will replace the renderbuffer's region with a miptree. This small refactor will eliminate the need for intel_fbo.h to include intel_mipmap_tree.h on that commit. I'd like to avoid the situation where each header transitively includes every other header. Reviewed-by: Eric Anholt Reviewed-by: Kenneth Graunke Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_fbo.c | 19 +++++++++++++++++++ src/mesa/drivers/dri/intel/intel_fbo.h | 21 ++++----------------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index 16b49ae311d..429529c81c4 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -55,6 +55,25 @@ #define FILE_DEBUG_FLAG DEBUG_FBO +bool +intel_framebuffer_has_hiz(struct gl_framebuffer *fb) +{ + struct intel_renderbuffer *rb = NULL; + if (fb) + rb = intel_get_renderbuffer(fb, BUFFER_DEPTH); + return rb && rb->hiz_region; +} + +struct intel_region* +intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex) +{ + struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex); + if (irb) + return irb->region; + else + return NULL; +} + /** * Create a new framebuffer object. */ diff --git a/src/mesa/drivers/dri/intel/intel_fbo.h b/src/mesa/drivers/dri/intel/intel_fbo.h index b46700a2509..63da6659296 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.h +++ b/src/mesa/drivers/dri/intel/intel_fbo.h @@ -134,14 +134,8 @@ intel_get_renderbuffer(struct gl_framebuffer *fb, gl_buffer_index attIndex) return irb; } -static inline bool -intel_framebuffer_has_hiz(struct gl_framebuffer *fb) -{ - struct intel_renderbuffer *rb = NULL; - if (fb) - rb = intel_get_renderbuffer(fb, BUFFER_DEPTH); - return rb && rb->hiz_region; -} +bool +intel_framebuffer_has_hiz(struct gl_framebuffer *fb); extern struct intel_renderbuffer * intel_create_renderbuffer(gl_format format); @@ -174,14 +168,7 @@ intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb, uint32_t *tile_x, uint32_t *tile_y); -static INLINE struct intel_region * -intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex) -{ - struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex); - if (irb) - return irb->region; - else - return NULL; -} +struct intel_region* +intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex); #endif /* INTEL_FBO_H */ From 005149d5860ad55c5e58e2de8a138e3a763f2036 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Sun, 13 Nov 2011 23:04:24 -0800 Subject: [PATCH 08/41] intel: Define intel_miptree_create_for_renderbuffer() This function creates a miptree that is suitable as storage for a non-texture renderbuffer. Reviewed-by: Eric Anholt Reviewed-by: Kenneth Graunke Signed-off-by: Chad Versace --- .../drivers/dri/intel/intel_mipmap_tree.c | 21 +++++++++++++++++++ .../drivers/dri/intel/intel_mipmap_tree.h | 15 +++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 19f151f4fa3..33247d2ced0 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -171,6 +171,27 @@ intel_miptree_create_for_region(struct intel_context *intel, return mt; } +struct intel_mipmap_tree* +intel_miptree_create_for_renderbuffer(struct intel_context *intel, + gl_format format, + uint32_t tiling, + uint32_t cpp, + uint32_t width, + uint32_t height) +{ + struct intel_region *region; + struct intel_mipmap_tree *mt; + + region = intel_region_alloc(intel->intelScreen, + tiling, cpp, width, height, true); + if (!region) + return NULL; + + mt = intel_miptree_create_for_region(intel, GL_TEXTURE_2D, format, region); + intel_region_release(®ion); + return mt; +} + void intel_miptree_reference(struct intel_mipmap_tree **dst, struct intel_mipmap_tree *src) diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index e29b9431939..611519d18d5 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -151,6 +151,21 @@ intel_miptree_create_for_region(struct intel_context *intel, gl_format format, struct intel_region *region); +/** + * Create a miptree appropriate as the storage for a non-texture renderbuffer. + * The miptree has the following properties: + * - The target is GL_TEXTURE_2D. + * - There are no levels other than the base level 0. + * - Depth is 1. + */ +struct intel_mipmap_tree* +intel_miptree_create_for_renderbuffer(struct intel_context *intel, + gl_format format, + uint32_t tiling, + uint32_t cpp, + uint32_t width, + uint32_t height); + int intel_miptree_pitch_align (struct intel_context *intel, struct intel_mipmap_tree *mt, uint32_t tiling, From da2816a45e6e3a33246a341fee72e6f893f315d9 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Wed, 16 Nov 2011 14:04:25 -0800 Subject: [PATCH 09/41] intel: Replace intel_renderbuffer::region with a miptree [v3] Essentially, this patch just globally substitutes `irb->region` with `irb->mt->region` and then does some minor cleanups to avoid segfaults and other problems. This is in preparation for 1. Fixing scatter/gather for mipmapped separate stencil textures. 2. Supporting HiZ for mipmapped depth textures. As a nice benefit, this lays down some preliminary groundwork for easily texturing from any renderbuffer, even those of the window system. A future commit will replace intel_mipmap_tree::hiz_region with a miptree. v2: - Return early in intel_process_dri2_buffer_*() if region allocation fails. - Fix double semicolon. - Fix miptree reference leaks in the following functions: intel_process_dri2_buffer_with_separate_stencil() intel_image_target_renderbuffer_storage() v3: - [anholt] Fix check for hiz allocation failure. Replace ``if (!irb->mt)` with ``if(!irb->mt->hiz_region)``. Reviewed-by: Eric Anholt Reviewed-by: Kenneth Graunke Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i965/brw_misc_state.c | 21 ++- src/mesa/drivers/dri/i965/brw_vtbl.c | 2 +- .../drivers/dri/i965/brw_wm_surface_state.c | 2 +- src/mesa/drivers/dri/i965/gen7_misc_state.c | 11 +- .../drivers/dri/i965/gen7_wm_surface_state.c | 2 +- src/mesa/drivers/dri/intel/intel_blit.c | 21 ++- .../drivers/dri/intel/intel_buffer_objects.c | 8 +- src/mesa/drivers/dri/intel/intel_buffers.c | 9 +- src/mesa/drivers/dri/intel/intel_context.c | 78 ++++++--- src/mesa/drivers/dri/intel/intel_fbo.c | 151 +++++++++--------- src/mesa/drivers/dri/intel/intel_fbo.h | 7 +- src/mesa/drivers/dri/intel/intel_pixel_copy.c | 5 +- src/mesa/drivers/dri/intel/intel_screen.c | 3 +- src/mesa/drivers/dri/intel/intel_span.c | 3 +- src/mesa/drivers/dri/intel/intel_tex_copy.c | 14 +- src/mesa/drivers/dri/intel/intel_tex_image.c | 6 +- 16 files changed, 203 insertions(+), 140 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c index 514c990ed25..4119afa4c49 100644 --- a/src/mesa/drivers/dri/i965/brw_misc_state.c +++ b/src/mesa/drivers/dri/i965/brw_misc_state.c @@ -33,6 +33,7 @@ #include "intel_batchbuffer.h" #include "intel_fbo.h" +#include "intel_mipmap_tree.h" #include "intel_regions.h" #include "brw_context.h" @@ -204,9 +205,14 @@ static void emit_depthbuffer(struct brw_context *brw) /* _NEW_BUFFERS */ struct intel_renderbuffer *depth_irb = intel_get_renderbuffer(fb, BUFFER_DEPTH); struct intel_renderbuffer *stencil_irb = intel_get_renderbuffer(fb, BUFFER_STENCIL); - struct intel_region *hiz_region = depth_irb ? depth_irb->hiz_region : NULL; + struct intel_region *hiz_region = NULL; unsigned int len; + if (depth_irb && + depth_irb->mt) { + hiz_region = depth_irb->mt->hiz_region; + } + /* 3DSTATE_DEPTH_BUFFER, 3DSTATE_STENCIL_BUFFER are both * non-pipelined state that will need the PIPE_CONTROL workaround. */ @@ -272,6 +278,8 @@ static void emit_depthbuffer(struct brw_context *brw) * [DevGT]: This field must be set to the same value (enabled or * disabled) as Hierarchical Depth Buffer Enable */ + struct intel_region *region = stencil_irb->mt->region; + assert(intel->has_separate_stencil); assert(stencil_irb->Base.Format == MESA_FORMAT_S8); @@ -283,8 +291,8 @@ static void emit_depthbuffer(struct brw_context *brw) (BRW_TILEWALK_YMAJOR << 26) | (BRW_SURFACE_2D << 29)); OUT_BATCH(0); - OUT_BATCH(((stencil_irb->region->width - 1) << 6) | - (2 * stencil_irb->region->height - 1) << 19); + OUT_BATCH(((region->width - 1) << 6) | + (2 * region->height - 1) << 19); OUT_BATCH(0); OUT_BATCH(0); @@ -294,7 +302,7 @@ static void emit_depthbuffer(struct brw_context *brw) ADVANCE_BATCH(); } else { - struct intel_region *region = depth_irb->region; + struct intel_region *region = depth_irb->mt->region; unsigned int format; uint32_t tile_x, tile_y, offset; @@ -379,10 +387,11 @@ static void emit_depthbuffer(struct brw_context *brw) /* Emit stencil buffer. */ if (stencil_irb) { + struct intel_region *region = stencil_irb->mt->region; BEGIN_BATCH(3); OUT_BATCH((_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2)); - OUT_BATCH(stencil_irb->region->pitch * stencil_irb->region->cpp - 1); - OUT_RELOC(stencil_irb->region->bo, + OUT_BATCH(region->pitch * region->cpp - 1); + OUT_RELOC(region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); ADVANCE_BATCH(); diff --git a/src/mesa/drivers/dri/i965/brw_vtbl.c b/src/mesa/drivers/dri/i965/brw_vtbl.c index 7c23faa8fff..9302b276347 100644 --- a/src/mesa/drivers/dri/i965/brw_vtbl.c +++ b/src/mesa/drivers/dri/i965/brw_vtbl.c @@ -126,7 +126,7 @@ brw_update_draw_buffer(struct intel_context *intel) /* Check some stencil invariants. These should probably be in * emit_depthbuffer(). */ - if (irbStencil && irbStencil->region) { + if (irbStencil && irbStencil->mt) { if (!intel->has_separate_stencil) assert(irbStencil->Base.Format == MESA_FORMAT_S8_Z24); if (fb_has_hiz || intel->must_use_separate_stencil) 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 0cc62017cbe..0c2c804b133 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c @@ -447,7 +447,7 @@ brw_update_renderbuffer_surface(struct brw_context *brw, struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; struct intel_renderbuffer *irb = intel_renderbuffer(rb); - struct intel_region *region = irb->region; + struct intel_region *region = irb->mt->region; uint32_t *surf; uint32_t tile_x, tile_y; uint32_t format = 0; diff --git a/src/mesa/drivers/dri/i965/gen7_misc_state.c b/src/mesa/drivers/dri/i965/gen7_misc_state.c index 6a3c086ac96..25e1b1d0fe1 100644 --- a/src/mesa/drivers/dri/i965/gen7_misc_state.c +++ b/src/mesa/drivers/dri/i965/gen7_misc_state.c @@ -22,6 +22,7 @@ */ #include "intel_batchbuffer.h" +#include "intel_mipmap_tree.h" #include "intel_regions.h" #include "intel_fbo.h" #include "brw_context.h" @@ -38,7 +39,7 @@ gen7_depth_format(struct brw_context *brw) struct intel_region *region = NULL; if (drb) - region = drb->region; + region = drb->mt->region; else return BRW_DEPTHFORMAT_D32_FLOAT; @@ -78,7 +79,7 @@ static void emit_depthbuffer(struct brw_context *brw) if (srb == NULL) { dw1 |= (BRW_SURFACE_NULL << 29); } else { - struct intel_region *region = srb->region; + struct intel_region *region = srb->mt->region; /* _NEW_STENCIL: enable stencil buffer writes */ dw1 |= ((ctx->Stencil.WriteMask != 0) << 27); @@ -98,7 +99,7 @@ static void emit_depthbuffer(struct brw_context *brw) OUT_BATCH(0); ADVANCE_BATCH(); } else { - struct intel_region *region = drb->region; + struct intel_region *region = drb->mt->region; uint32_t tile_x, tile_y, offset; offset = intel_renderbuffer_tile_offsets(drb, &tile_x, &tile_y); @@ -140,8 +141,8 @@ static void emit_depthbuffer(struct brw_context *brw) } else { BEGIN_BATCH(3); OUT_BATCH(GEN7_3DSTATE_STENCIL_BUFFER << 16 | (3 - 2)); - OUT_BATCH(srb->region->pitch * srb->region->cpp - 1); - OUT_RELOC(srb->region->bo, + OUT_BATCH(srb->mt->region->pitch * srb->mt->region->cpp - 1); + OUT_RELOC(srb->mt->region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); ADVANCE_BATCH(); 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 f74198b2468..e1c3910af95 100644 --- a/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/gen7_wm_surface_state.c @@ -192,7 +192,7 @@ gen7_update_renderbuffer_surface(struct brw_context *brw, struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; struct intel_renderbuffer *irb = intel_renderbuffer(rb); - struct intel_region *region = irb->region; + struct intel_region *region = irb->mt->region; struct gen7_surface_state *surf; uint32_t tile_x, tile_y; diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c index 8d7693d7b88..b1a839ac706 100644 --- a/src/mesa/drivers/dri/intel/intel_blit.c +++ b/src/mesa/drivers/dri/intel/intel_blit.c @@ -267,13 +267,18 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask) int x1, y1, x2, y2; uint32_t clear_val; uint32_t BR13, CMD; + struct intel_region *region; int pitch, cpp; drm_intel_bo *aper_array[2]; mask &= ~(1 << buf); irb = intel_get_renderbuffer(fb, buf); - if (irb == NULL || irb->region == NULL || irb->region->bo == NULL) { + if (irb && irb->mt) { + region = irb->mt->region; + assert(region); + assert(region->bo); + } else { fail_mask |= 1 << buf; continue; } @@ -284,12 +289,12 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask) x2 = cx + cw + irb->draw_x; y2 = cy + ch + irb->draw_y; - pitch = irb->region->pitch; - cpp = irb->region->cpp; + pitch = region->pitch; + cpp = region->cpp; DBG("%s dst:buf(%p)/%d %d,%d sz:%dx%d\n", __FUNCTION__, - irb->region->bo, (pitch * cpp), + region->bo, (pitch * cpp), x1, y1, x2 - x1, y2 - y1); BR13 = 0xf0 << 16; @@ -305,10 +310,10 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask) } } - assert(irb->region->tiling != I915_TILING_Y); + assert(region->tiling != I915_TILING_Y); #ifndef I915 - if (irb->region->tiling != I915_TILING_NONE) { + if (region->tiling != I915_TILING_NONE) { CMD |= XY_DST_TILED; pitch /= 4; } @@ -357,7 +362,7 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask) /* do space check before going any further */ aper_array[0] = intel->batch.bo; - aper_array[1] = irb->region->bo; + aper_array[1] = region->bo; if (drm_intel_bufmgr_check_aperture_space(aper_array, ARRAY_SIZE(aper_array)) != 0) { @@ -369,7 +374,7 @@ intelClearWithBlit(struct gl_context *ctx, GLbitfield mask) OUT_BATCH(BR13); OUT_BATCH((y1 << 16) | x1); OUT_BATCH((y2 << 16) | x2); - OUT_RELOC_FENCED(irb->region->bo, + OUT_RELOC_FENCED(region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); OUT_BATCH(clear_val); diff --git a/src/mesa/drivers/dri/intel/intel_buffer_objects.c b/src/mesa/drivers/dri/intel/intel_buffer_objects.c index 75d95b1fe70..4a1a8165be5 100644 --- a/src/mesa/drivers/dri/intel/intel_buffer_objects.c +++ b/src/mesa/drivers/dri/intel/intel_buffer_objects.c @@ -766,10 +766,10 @@ intel_render_object_purgeable(struct gl_context * ctx, (void) option; intel = intel_renderbuffer(obj); - if (intel->region == NULL) + if (intel->mt == NULL) return GL_RELEASED_APPLE; - return intel_buffer_purgeable(intel->region->bo); + return intel_buffer_purgeable(intel->mt->region->bo); } static GLenum @@ -823,10 +823,10 @@ intel_render_object_unpurgeable(struct gl_context * ctx, (void) option; intel = intel_renderbuffer(obj); - if (intel->region == NULL) + if (intel->mt == NULL) return GL_UNDEFINED_APPLE; - return intel_buffer_unpurgeable(intel->region->bo); + return intel_buffer_unpurgeable(intel->mt->region->bo); } #endif diff --git a/src/mesa/drivers/dri/intel/intel_buffers.c b/src/mesa/drivers/dri/intel/intel_buffers.c index 08f5c4decd3..4632751935a 100644 --- a/src/mesa/drivers/dri/intel/intel_buffers.c +++ b/src/mesa/drivers/dri/intel/intel_buffers.c @@ -28,6 +28,7 @@ #include "intel_context.h" #include "intel_buffers.h" #include "intel_fbo.h" +#include "intel_mipmap_tree.h" #include "main/framebuffer.h" #include "main/renderbuffer.h" @@ -40,8 +41,8 @@ intel_drawbuf_region(struct intel_context *intel) { struct intel_renderbuffer *irbColor = intel_renderbuffer(intel->ctx.DrawBuffer->_ColorDrawBuffers[0]); - if (irbColor) - return irbColor->region; + if (irbColor && irbColor->mt) + return irbColor->mt->region; else return NULL; } @@ -54,8 +55,8 @@ intel_readbuf_region(struct intel_context *intel) { struct intel_renderbuffer *irb = intel_renderbuffer(intel->ctx.ReadBuffer->_ColorReadBuffer); - if (irb) - return irb->region; + if (irb && irb->mt) + return irb->mt->region; else return NULL; } diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index d89b38875b8..3f55c512357 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -53,6 +53,7 @@ #include "intel_fbo.h" #include "intel_bufmgr.h" #include "intel_screen.h" +#include "intel_mipmap_tree.h" #include "utils.h" #include "../glsl/ralloc.h" @@ -1153,7 +1154,9 @@ intel_process_dri2_buffer_no_separate_stencil(struct intel_context *intel, if (!rb) return; - if (rb->region && rb->region->name == buffer->name) + if (rb->mt && + rb->mt->region && + rb->mt->region->name == buffer->name) return; if (unlikely(INTEL_DEBUG & DEBUG_DRI)) { @@ -1167,23 +1170,34 @@ intel_process_dri2_buffer_no_separate_stencil(struct intel_context *intel, if (buffer->attachment == __DRI_BUFFER_STENCIL) { struct intel_renderbuffer *depth_rb = intel_get_renderbuffer(fb, BUFFER_DEPTH); - identify_depth_and_stencil = depth_rb && depth_rb->region; + identify_depth_and_stencil = depth_rb && depth_rb->mt; } if (identify_depth_and_stencil) { if (unlikely(INTEL_DEBUG & DEBUG_DRI)) { fprintf(stderr, "(reusing depth buffer as stencil)\n"); } - intel_region_reference(&rb->region, depth_rb->region); + intel_miptree_reference(&rb->mt, depth_rb->mt); } else { - intel_region_release(&rb->region); - rb->region = intel_region_alloc_for_handle(intel->intelScreen, + intel_miptree_release(&rb->mt); + struct intel_region *region = + intel_region_alloc_for_handle(intel->intelScreen, buffer->cpp, drawable->w, drawable->h, buffer->pitch / buffer->cpp, buffer->name, buffer_name); + if (!region) + return; + + rb->mt = intel_miptree_create_for_region(intel, + GL_TEXTURE_2D, + rb->Base.Format, + region); + intel_region_release(®ion); + if (!rb->mt) + return; } if (buffer->attachment == __DRI_BUFFER_DEPTH_STENCIL) { @@ -1196,7 +1210,7 @@ intel_process_dri2_buffer_no_separate_stencil(struct intel_context *intel, /* The rb passed in is the BUFFER_DEPTH attachment, and we need * to associate this region to BUFFER_STENCIL as well. */ - intel_region_reference(&stencil_rb->region, rb->region); + intel_miptree_reference(&stencil_rb->mt, rb->mt); } } @@ -1338,11 +1352,13 @@ intel_process_dri2_buffer_with_separate_stencil(struct intel_context *intel, /* If the renderbuffer's and DRIbuffer's regions match, then continue. */ if ((buffer->attachment != __DRI_BUFFER_HIZ && - rb->region && - rb->region->name == buffer->name) || + rb->mt && + rb->mt->region && + rb->mt->region->name == buffer->name) || (buffer->attachment == __DRI_BUFFER_HIZ && - rb->hiz_region && - rb->hiz_region->name == buffer->name)) { + rb->mt && + rb->mt->hiz_region && + rb->mt->hiz_region->name == buffer->name)) { return; } @@ -1371,6 +1387,15 @@ intel_process_dri2_buffer_with_separate_stencil(struct intel_context *intel, buffer_height = drawable->h; } + /* Release the buffer storage now in case we have to return early + * due to region allocation failure. + */ + if (buffer->attachment == __DRI_BUFFER_HIZ) { + intel_region_release(&rb->mt->hiz_region); + } else { + intel_miptree_release(&rb->mt); + } + struct intel_region *region = intel_region_alloc_for_handle(intel->intelScreen, buffer->cpp, @@ -1379,14 +1404,19 @@ intel_process_dri2_buffer_with_separate_stencil(struct intel_context *intel, buffer->pitch / buffer->cpp, buffer->name, buffer_name); + if (!region) + return; + /* Associate buffer with new storage. */ if (buffer->attachment == __DRI_BUFFER_HIZ) { - intel_region_reference(&rb->hiz_region, region); + rb->mt->hiz_region = region; } else { - intel_region_reference(&rb->region, region); + rb->mt = intel_miptree_create_for_region(intel, + GL_TEXTURE_2D, + rb->Base.Format, + region); + intel_region_release(®ion); } - - intel_region_release(®ion); } /** @@ -1463,7 +1493,7 @@ intel_verify_dri2_has_hiz(struct intel_context *intel, assert(stencil_rb->Base.Format == MESA_FORMAT_S8); assert(depth_rb && depth_rb->Base.Format == MESA_FORMAT_X8_Z24); - if (stencil_rb->region->tiling == I915_TILING_NONE) { + if (stencil_rb->mt->region->tiling == I915_TILING_NONE) { /* * The stencil buffer is actually W tiled. The region's tiling is * I915_TILING_NONE, however, because the GTT is incapable of W @@ -1544,11 +1574,21 @@ intel_verify_dri2_has_hiz(struct intel_context *intel, / depth_stencil_buffer->cpp, depth_stencil_buffer->name, "dri2 depth / stencil buffer"); - intel_region_reference(&intel_get_renderbuffer(fb, BUFFER_DEPTH)->region, - region); - intel_region_reference(&intel_get_renderbuffer(fb, BUFFER_STENCIL)->region, - region); + if (!region) + return; + + struct intel_mipmap_tree *mt = + intel_miptree_create_for_region(intel, + GL_TEXTURE_2D, + depth_stencil_rb->Base.Format, + region); intel_region_release(®ion); + if (!mt) + return; + + intel_miptree_reference(&intel_get_renderbuffer(fb, BUFFER_DEPTH)->mt, mt); + intel_miptree_reference(&intel_get_renderbuffer(fb, BUFFER_STENCIL)->mt, mt); + intel_miptree_release(&mt); } } diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index 429529c81c4..e5328df2ff5 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -61,15 +61,15 @@ intel_framebuffer_has_hiz(struct gl_framebuffer *fb) struct intel_renderbuffer *rb = NULL; if (fb) rb = intel_get_renderbuffer(fb, BUFFER_DEPTH); - return rb && rb->hiz_region; + return rb && rb->mt && rb->mt->hiz_region; } struct intel_region* intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex) { struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex); - if (irb) - return irb->region; + if (irb && irb->mt) + return irb->mt->region; else return NULL; } @@ -95,8 +95,7 @@ intel_delete_renderbuffer(struct gl_renderbuffer *rb) ASSERT(irb); - intel_region_release(&irb->region); - intel_region_release(&irb->hiz_region); + intel_miptree_release(&irb->mt); _mesa_reference_renderbuffer(&irb->wrapped_depth, NULL); _mesa_reference_renderbuffer(&irb->wrapped_stencil, NULL); @@ -122,7 +121,7 @@ intel_map_renderbuffer_gtt(struct gl_context *ctx, GLubyte *map; int stride, flip_stride; - assert(irb->region); + assert(irb->mt); irb->map_mode = mode; irb->map_x = x; @@ -130,10 +129,10 @@ intel_map_renderbuffer_gtt(struct gl_context *ctx, irb->map_w = w; irb->map_h = h; - stride = irb->region->pitch * irb->region->cpp; + stride = irb->mt->region->pitch * irb->mt->region->cpp; if (rb->Name == 0) { - y = irb->region->height - 1 - y; + y = irb->mt->region->height - 1 - y; flip_stride = -stride; } else { x += irb->draw_x; @@ -141,14 +140,14 @@ intel_map_renderbuffer_gtt(struct gl_context *ctx, flip_stride = stride; } - if (drm_intel_bo_references(intel->batch.bo, irb->region->bo)) { + if (drm_intel_bo_references(intel->batch.bo, irb->mt->region->bo)) { intel_batchbuffer_flush(intel); } - drm_intel_gem_bo_map_gtt(irb->region->bo); + drm_intel_gem_bo_map_gtt(irb->mt->region->bo); - map = irb->region->bo->virtual; - map += x * irb->region->cpp; + map = irb->mt->region->bo->virtual; + map += x * irb->mt->region->cpp; map += (int)y * stride; *out_map = map; @@ -186,10 +185,10 @@ intel_map_renderbuffer_blit(struct gl_context *ctx, int src_x, src_y; int dst_stride; - assert(irb->region); + assert(irb->mt->region); assert(intel->gen >= 6); assert(!(mode & GL_MAP_WRITE_BIT)); - assert(irb->region->tiling == I915_TILING_X); + assert(irb->mt->region->tiling == I915_TILING_X); irb->map_mode = mode; irb->map_x = x; @@ -197,14 +196,14 @@ intel_map_renderbuffer_blit(struct gl_context *ctx, irb->map_w = w; irb->map_h = h; - dst_stride = ALIGN(w * irb->region->cpp, 4); + dst_stride = ALIGN(w * irb->mt->region->cpp, 4); if (rb->Name) { src_x = x + irb->draw_x; src_y = y + irb->draw_y; } else { src_x = x; - src_y = irb->region->height - y - h; + src_y = irb->mt->region->height - y - h; } irb->map_bo = drm_intel_bo_alloc(intel->bufmgr, "MapRenderbuffer() temp", @@ -215,10 +214,10 @@ intel_map_renderbuffer_blit(struct gl_context *ctx, */ if (irb->map_bo && intelEmitCopyBlit(intel, - irb->region->cpp, - irb->region->pitch, irb->region->bo, - 0, irb->region->tiling, - dst_stride / irb->region->cpp, irb->map_bo, + irb->mt->region->cpp, + irb->mt->region->pitch, irb->mt->region->bo, + 0, irb->mt->region->tiling, + dst_stride / irb->mt->region->cpp, irb->map_bo, 0, I915_TILING_NONE, src_x, src_y, 0, 0, @@ -277,7 +276,7 @@ intel_map_renderbuffer_s8(struct gl_context *ctx, uint8_t *untiled_s8_map; assert(rb->Format == MESA_FORMAT_S8); - assert(irb->region); + assert(irb->mt); irb->map_mode = mode; irb->map_x = x; @@ -291,12 +290,12 @@ intel_map_renderbuffer_s8(struct gl_context *ctx, irb->map_buffer = malloc(w * h); untiled_s8_map = irb->map_buffer; - tiled_s8_map = intel_region_map(intel, irb->region, mode); + tiled_s8_map = intel_region_map(intel, irb->mt->region, mode); for (uint32_t pix_y = 0; pix_y < h; pix_y++) { for (uint32_t pix_x = 0; pix_x < w; pix_x++) { uint32_t flipped_y = y_flip * (int32_t)(y + pix_y) + y_bias; - ptrdiff_t offset = intel_offset_S8(irb->region->pitch, + ptrdiff_t offset = intel_offset_S8(irb->mt->region->pitch, x + pix_x, flipped_y); untiled_s8_map[pix_y * w + pix_x] = tiled_s8_map[offset]; @@ -363,12 +362,12 @@ intel_map_renderbuffer_separate_s8z24(struct gl_context *ctx, &s8z24_map, &s8z24_stride); s8_irb = intel_renderbuffer(irb->wrapped_stencil); - s8_map = intel_region_map(intel, s8_irb->region, GL_MAP_READ_BIT); + s8_map = intel_region_map(intel, s8_irb->mt->region, GL_MAP_READ_BIT); /* Gather the stencil buffer into the depth buffer. */ for (uint32_t pix_y = 0; pix_y < h; ++pix_y) { for (uint32_t pix_x = 0; pix_x < w; ++pix_x) { - ptrdiff_t s8_offset = intel_offset_S8(s8_irb->region->pitch, + ptrdiff_t s8_offset = intel_offset_S8(s8_irb->mt->region->pitch, x + pix_x, y + pix_y); ptrdiff_t s8z24_offset = pix_y * s8z24_stride @@ -378,7 +377,7 @@ intel_map_renderbuffer_separate_s8z24(struct gl_context *ctx, } } - intel_region_unmap(intel, s8_irb->region); + intel_region_unmap(intel, s8_irb->mt->region); *out_map = s8z24_map; *out_stride = s8z24_stride; @@ -399,7 +398,7 @@ intel_map_renderbuffer(struct gl_context *ctx, struct intel_renderbuffer *irb = intel_renderbuffer(rb); /* We sometimes get called with this by our intel_span.c usage. */ - if (!irb->region && !irb->wrapped_depth) { + if (!irb->mt && !irb->wrapped_depth) { *out_map = NULL; *out_stride = 0; return; @@ -413,7 +412,7 @@ intel_map_renderbuffer(struct gl_context *ctx, out_map, out_stride); } else if (intel->gen >= 6 && !(mode & GL_MAP_WRITE_BIT) && - irb->region->tiling == I915_TILING_X) { + irb->mt->region->tiling == I915_TILING_X) { intel_map_renderbuffer_blit(ctx, rb, x, y, w, h, mode, out_map, out_stride); } else { @@ -445,7 +444,7 @@ intel_unmap_renderbuffer_s8(struct gl_context *ctx, * the real buffer. */ uint8_t *untiled_s8_map = irb->map_buffer; - uint8_t *tiled_s8_map = irb->region->bo->virtual; + uint8_t *tiled_s8_map = irb->mt->region->bo->virtual; /* Flip the Y axis for the default framebuffer. */ int y_flip = (rb->Name == 0) ? -1 : 1; @@ -454,7 +453,7 @@ intel_unmap_renderbuffer_s8(struct gl_context *ctx, for (uint32_t pix_y = 0; pix_y < irb->map_h; pix_y++) { for (uint32_t pix_x = 0; pix_x < irb->map_w; pix_x++) { uint32_t flipped_y = y_flip * (int32_t)(pix_y + irb->map_y) + y_bias; - ptrdiff_t offset = intel_offset_S8(irb->region->pitch, + ptrdiff_t offset = intel_offset_S8(irb->mt->region->pitch, pix_x + irb->map_x, flipped_y); tiled_s8_map[offset] = @@ -463,7 +462,7 @@ intel_unmap_renderbuffer_s8(struct gl_context *ctx, } } - intel_region_unmap(intel, irb->region); + intel_region_unmap(intel, irb->mt->region); free(irb->map_buffer); irb->map_buffer = NULL; } @@ -501,16 +500,16 @@ intel_unmap_renderbuffer_separate_s8z24(struct gl_context *ctx, uint8_t *s8_map; s8_irb = intel_renderbuffer(irb->wrapped_stencil); - s8_map = intel_region_map(intel, s8_irb->region, GL_MAP_WRITE_BIT); + s8_map = intel_region_map(intel, s8_irb->mt->region, GL_MAP_WRITE_BIT); - int32_t s8z24_stride = 4 * s8z24_irb->region->pitch; - uint8_t *s8z24_map = s8z24_irb->region->bo->virtual + int32_t s8z24_stride = 4 * s8z24_irb->mt->region->pitch; + uint8_t *s8z24_map = s8z24_irb->mt->region->bo->virtual + map_y * s8z24_stride + map_x * 4; for (uint32_t pix_y = 0; pix_y < map_h; ++pix_y) { for (uint32_t pix_x = 0; pix_x < map_w; ++pix_x) { - ptrdiff_t s8_offset = intel_offset_S8(s8_irb->region->pitch, + ptrdiff_t s8_offset = intel_offset_S8(s8_irb->mt->region->pitch, map_x + pix_x, map_y + pix_y); ptrdiff_t s8z24_offset = pix_y * s8z24_stride @@ -520,10 +519,10 @@ intel_unmap_renderbuffer_separate_s8z24(struct gl_context *ctx, } } - intel_region_unmap(intel, s8_irb->region); + intel_region_unmap(intel, s8_irb->mt->region); } - drm_intel_gem_bo_unmap_gtt(s8z24_irb->region->bo); + drm_intel_gem_bo_unmap_gtt(s8z24_irb->mt->region->bo); } /** @@ -549,11 +548,11 @@ intel_unmap_renderbuffer(struct gl_context *ctx, irb->map_bo = 0; } else { /* Paired with intel_map_renderbuffer_gtt(). */ - if (irb->region) { - /* The region may be null when intel_map_renderbuffer() is + if (irb->mt) { + /* The miptree may be null when intel_map_renderbuffer() is * called from intel_span.c. */ - drm_intel_gem_bo_unmap_gtt(irb->region->bo); + drm_intel_gem_bo_unmap_gtt(irb->mt->region->bo); } } } @@ -620,13 +619,7 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer intel_flush(ctx); - /* free old region */ - if (irb->region) { - intel_region_release(&irb->region); - } - if (irb->hiz_region) { - intel_region_release(&irb->hiz_region); - } + intel_miptree_release(&irb->mt); DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__, _mesa_lookup_enum_by_nr(internalFormat), @@ -658,14 +651,15 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer * * If we neglect to double the pitch, then render corruption occurs. */ - irb->region = intel_region_alloc(intel->intelScreen, - I915_TILING_NONE, - cpp * 2, - ALIGN(width, 64), - ALIGN((height + 1) / 2, 64), - true); - if (!irb->region) - return false; + irb->mt = intel_miptree_create_for_renderbuffer( + intel, + rb->Format, + I915_TILING_NONE, + cpp * 2, + ALIGN(width, 64), + ALIGN((height + 1) / 2, 64)); + if (!irb->mt) + return false; } else if (irb->Base.Format == MESA_FORMAT_S8_Z24 && intel->must_use_separate_stencil) { @@ -702,20 +696,21 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer _mesa_reference_renderbuffer(&irb->wrapped_stencil, stencil_rb); } else { - irb->region = intel_region_alloc(intel->intelScreen, tiling, cpp, - width, height, true); - if (!irb->region) + irb->mt = intel_miptree_create_for_renderbuffer(intel, rb->Format, + tiling, cpp, + width, height); + if (!irb->mt) return false; if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) { - irb->hiz_region = intel_region_alloc(intel->intelScreen, - I915_TILING_Y, - irb->region->cpp, - irb->region->width, - irb->region->height, - true); - if (!irb->hiz_region) { - intel_region_release(&irb->region); + irb->mt->hiz_region = intel_region_alloc(intel->intelScreen, + I915_TILING_Y, + cpp, + rb->Width, + rb->Height, + true); + if (!irb->mt->hiz_region) { + intel_miptree_release(&irb->mt); return false; } } @@ -754,7 +749,13 @@ intel_image_target_renderbuffer_storage(struct gl_context *ctx, } irb = intel_renderbuffer(rb); - intel_region_reference(&irb->region, image->region); + intel_miptree_release(&irb->mt); + irb->mt = intel_miptree_create_for_region(intel, + GL_TEXTURE_2D, + image->format, + image->region); + if (!irb->mt) + return; rb->InternalFormat = image->internal_format; rb->Width = image->region->width; @@ -982,9 +983,8 @@ intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb, _mesa_reference_renderbuffer(&irb->wrapped_stencil, intel_image->stencil_rb); } else { - intel_region_reference(&irb->region, intel_image->mt->region); + intel_miptree_reference(&irb->mt, intel_image->mt); } - return true; } @@ -1050,20 +1050,21 @@ intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb, uint32_t *tile_x, uint32_t *tile_y) { - int cpp = irb->region->cpp; - uint32_t pitch = irb->region->pitch * cpp; + struct intel_region *region = irb->mt->region; + int cpp = region->cpp; + uint32_t pitch = region->pitch * cpp; - if (irb->region->tiling == I915_TILING_NONE) { + if (region->tiling == I915_TILING_NONE) { *tile_x = 0; *tile_y = 0; return irb->draw_x * cpp + irb->draw_y * pitch; - } else if (irb->region->tiling == I915_TILING_X) { + } else if (region->tiling == I915_TILING_X) { *tile_x = irb->draw_x % (512 / cpp); *tile_y = irb->draw_y % 8; return ((irb->draw_y / 8) * (8 * pitch) + (irb->draw_x - *tile_x) / (512 / cpp) * 4096); } else { - assert(irb->region->tiling == I915_TILING_Y); + assert(region->tiling == I915_TILING_Y); *tile_x = irb->draw_x % (128 / cpp); *tile_y = irb->draw_y % 32; return ((irb->draw_y / 32) * (32 * pitch) + @@ -1164,7 +1165,7 @@ intel_render_texture(struct gl_context * ctx, intel_miptree_copy_teximage(intel, intel_image, new_mt); intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset); - intel_region_reference(&irb->region, intel_image->mt->region); + intel_miptree_reference(&irb->mt, intel_image->mt); intel_miptree_release(&new_mt); } #endif diff --git a/src/mesa/drivers/dri/intel/intel_fbo.h b/src/mesa/drivers/dri/intel/intel_fbo.h index 63da6659296..34d2f9a61cf 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.h +++ b/src/mesa/drivers/dri/intel/intel_fbo.h @@ -35,6 +35,7 @@ #include "intel_screen.h" struct intel_context; +struct intel_mipmap_tree; struct intel_texture_image; /** @@ -43,15 +44,13 @@ struct intel_texture_image; struct intel_renderbuffer { struct gl_renderbuffer Base; - struct intel_region *region; + struct intel_mipmap_tree *mt; /**< The renderbuffer storage. */ drm_intel_bo *map_bo; + void *map_buffer; GLuint map_x, map_y, map_w, map_h; GLbitfield map_mode; - /** Only used by depth renderbuffers for which HiZ is enabled. */ - struct intel_region *hiz_region; - /** * \name Packed depth/stencil unwrappers * diff --git a/src/mesa/drivers/dri/intel/intel_pixel_copy.c b/src/mesa/drivers/dri/intel/intel_pixel_copy.c index 89d5c51ef15..2682e152abc 100644 --- a/src/mesa/drivers/dri/intel/intel_pixel_copy.c +++ b/src/mesa/drivers/dri/intel/intel_pixel_copy.c @@ -34,6 +34,7 @@ #include "intel_context.h" #include "intel_buffers.h" +#include "intel_mipmap_tree.h" #include "intel_regions.h" #include "intel_pixel.h" #include "intel_fbo.h" @@ -188,8 +189,8 @@ do_blit_copypixels(struct gl_context * ctx, dsty += draw_irb->draw_y; if (!intel_region_copy(intel, - draw_irb->region, 0, dstx, dsty, - read_irb->region, 0, srcx, srcy, + draw_irb->mt->region, 0, dstx, dsty, + read_irb->mt->region, 0, srcx, srcy, width, height, flip, ctx->Color.ColorLogicOpEnabled ? ctx->Color.LogicOp : GL_COPY)) { diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 5a73030660f..67dccdf6006 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -86,6 +86,7 @@ const GLuint __driNConfigOptions = 11; #include "intel_bufmgr.h" #include "intel_chipset.h" #include "intel_fbo.h" +#include "intel_mipmap_tree.h" #include "intel_screen.h" #include "intel_tex.h" #include "intel_regions.h" @@ -201,7 +202,7 @@ intel_create_image_from_renderbuffer(__DRIcontext *context, image->format = rb->Format; image->data_type = rb->DataType; image->data = loaderPrivate; - intel_region_reference(&image->region, irb->region); + intel_region_reference(&image->region, irb->mt->region); return image; } diff --git a/src/mesa/drivers/dri/intel/intel_span.c b/src/mesa/drivers/dri/intel/intel_span.c index b103bbd9f7f..83676b9313d 100644 --- a/src/mesa/drivers/dri/intel/intel_span.c +++ b/src/mesa/drivers/dri/intel/intel_span.c @@ -39,6 +39,7 @@ #include "intel_buffers.h" #include "intel_fbo.h" +#include "intel_mipmap_tree.h" #include "intel_screen.h" #include "intel_span.h" #include "intel_regions.h" @@ -58,7 +59,7 @@ intel_set_span_functions(struct intel_context *intel, int minx = 0, miny = 0; \ int maxx = rb->Width; \ int maxy = rb->Height; \ - int pitch = rb->RowStride * irb->region->cpp; \ + int pitch = rb->RowStride * irb->mt->region->cpp; \ void *buf = rb->Data; \ GLuint p; \ (void) p; diff --git a/src/mesa/drivers/dri/intel/intel_tex_copy.c b/src/mesa/drivers/dri/intel/intel_tex_copy.c index 2df4ef6a7f6..543326a0580 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_copy.c +++ b/src/mesa/drivers/dri/intel/intel_tex_copy.c @@ -71,6 +71,7 @@ intel_copy_texsubimage(struct intel_context *intel, { struct gl_context *ctx = &intel->ctx; struct intel_renderbuffer *irb; + struct intel_region *region; const GLenum internalFormat = intelImage->base.Base.InternalFormat; bool copy_supported = false; bool copy_supported_with_alpha_override = false; @@ -78,11 +79,14 @@ intel_copy_texsubimage(struct intel_context *intel, intel_prepare_render(intel); irb = get_teximage_readbuffer(intel, internalFormat); - if (!intelImage->mt || !irb || !irb->region) { + if (!intelImage->mt || !irb || !irb->mt) { if (unlikely(INTEL_DEBUG & DEBUG_FALLBACKS)) fprintf(stderr, "%s fail %p %p (0x%08x)\n", __FUNCTION__, intelImage->mt, irb, internalFormat); return false; + } else { + region = irb->mt->region; + assert(region); } copy_supported = intelImage->base.Base.TexFormat == irb->Base.Format; @@ -127,19 +131,19 @@ intel_copy_texsubimage(struct intel_context *intel, if (ctx->ReadBuffer->Name == 0) { /* Flip vertical orientation for system framebuffers */ y = ctx->ReadBuffer->Height - (y + height); - src_pitch = -irb->region->pitch; + src_pitch = -region->pitch; } else { /* reading from a FBO, y is already oriented the way we like */ - src_pitch = irb->region->pitch; + src_pitch = region->pitch; } /* blit from src buffer to texture */ if (!intelEmitCopyBlit(intel, intelImage->mt->cpp, src_pitch, - irb->region->bo, + region->bo, 0, - irb->region->tiling, + region->tiling, intelImage->mt->region->pitch, intelImage->mt->region->bo, 0, diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index 3fc2128536c..90e409094d5 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -306,7 +306,7 @@ intel_tex_image_s8z24_create_renderbuffers(struct intel_context *intel, idrb = intel_renderbuffer(drb); isrb = intel_renderbuffer(srb); - intel_region_reference(&idrb->region, image->mt->region); + intel_miptree_reference(&idrb->mt, image->mt); ok = intel_alloc_renderbuffer_storage(ctx, srb, GL_STENCIL_INDEX8, width, height); @@ -471,7 +471,7 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, /* If the region isn't set, then intel_update_renderbuffers was unable * to get the buffers for the drawable. */ - if (rb->region == NULL) + if (!rb || !rb->mt) return; if (texture_format == __DRI_TEXTURE_FORMAT_RGB) { @@ -485,7 +485,7 @@ intelSetTexBuffer2(__DRIcontext *pDRICtx, GLint target, _mesa_lock_texture(&intel->ctx, texObj); texImage = _mesa_get_tex_image(ctx, texObj, target, level); - intel_set_texture_image_region(ctx, texImage, rb->region, target, + intel_set_texture_image_region(ctx, texImage, rb->mt->region, target, internalFormat, texFormat); _mesa_unlock_texture(&intel->ctx, texObj); } From c2ddde70daece24d1eb7185946032158993a9e4d Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Mon, 14 Nov 2011 08:56:26 -0800 Subject: [PATCH 10/41] intel: Refactor intel_mipmap_level offsets Add a new field, intel_mipmap_level::slice, and move the offset fields into it. Also add some much needed documentation for these fields. Before this patch, a separate array was allocated for the intel_mipmap_level::{x,y}_offsets. This was just silly; it incurred an extra call to malloc and diminished memory locality. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- .../drivers/dri/intel/intel_mipmap_tree.c | 31 +++++++++---------- .../drivers/dri/intel/intel_mipmap_tree.h | 31 +++++++++++++------ 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 33247d2ced0..7f9e606cd16 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -226,8 +226,7 @@ intel_miptree_release(struct intel_mipmap_tree **mt) intel_region_release(&((*mt)->hiz_region)); for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { - free((*mt)->level[i].x_offset); - free((*mt)->level[i].y_offset); + free((*mt)->level[i].slice); } free(*mt); @@ -303,12 +302,11 @@ intel_miptree_set_level_info(struct intel_mipmap_tree *mt, level, w, h, d, x, y); assert(nr_images); - assert(!mt->level[level].x_offset); + assert(mt->level[level].slice == NULL); - mt->level[level].x_offset = malloc(nr_images * sizeof(GLuint)); - mt->level[level].x_offset[0] = mt->level[level].level_x; - mt->level[level].y_offset = malloc(nr_images * sizeof(GLuint)); - mt->level[level].y_offset[0] = mt->level[level].level_y; + mt->level[level].slice = malloc(nr_images * sizeof(*mt->level[0].slice)); + mt->level[level].slice[0].x_offset = mt->level[level].level_x; + mt->level[level].slice[0].y_offset = mt->level[level].level_y; } @@ -322,12 +320,13 @@ intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, assert(img < mt->level[level].nr_images); - mt->level[level].x_offset[img] = mt->level[level].level_x + x; - mt->level[level].y_offset[img] = mt->level[level].level_y + y; + mt->level[level].slice[img].x_offset = mt->level[level].level_x + x; + mt->level[level].slice[img].y_offset = mt->level[level].level_y + y; DBG("%s level %d img %d pos %d,%d\n", __FUNCTION__, level, img, - mt->level[level].x_offset[img], mt->level[level].y_offset[img]); + mt->level[level].slice[img].x_offset, + mt->level[level].slice[img].y_offset); } @@ -338,19 +337,19 @@ intel_miptree_get_image_offset(struct intel_mipmap_tree *mt, { switch (mt->target) { case GL_TEXTURE_CUBE_MAP_ARB: - *x = mt->level[level].x_offset[face]; - *y = mt->level[level].y_offset[face]; + *x = mt->level[level].slice[face].x_offset; + *y = mt->level[level].slice[face].y_offset; break; case GL_TEXTURE_3D: case GL_TEXTURE_2D_ARRAY_EXT: case GL_TEXTURE_1D_ARRAY_EXT: assert(depth < mt->level[level].nr_images); - *x = mt->level[level].x_offset[depth]; - *y = mt->level[level].y_offset[depth]; + *x = mt->level[level].slice[depth].x_offset; + *y = mt->level[level].slice[depth].y_offset; break; default: - *x = mt->level[level].x_offset[0]; - *y = mt->level[level].y_offset[0]; + *x = mt->level[level].slice[0].x_offset; + *y = mt->level[level].slice[0].y_offset; break; } } diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index 611519d18d5..2cad793acf3 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -74,17 +74,30 @@ struct intel_mipmap_level /** Number of images at this level: 1 for 1D/2D, 6 for CUBE, depth for 3D */ GLuint nr_images; - /** @{ - * offsets from level_[xy] to the image for each cube face or depth - * level. + /** + * \brief List of 2D images in this mipmap level. * - * Pretty much have to accept that hardware formats - * are going to be so diverse that there is no unified way to - * compute the offsets of depth/cube images within a mipmap level, - * so have to store them as a lookup table. + * This may be a list of cube faces, array slices in 2D array texture, or + * layers in a 3D texture. The list's length is \c nr_images. */ - GLuint *x_offset, *y_offset; - /** @} */ + struct intel_mipmap_slice { + /** + * \name Offset to slice + * \{ + * + * Hardware formats are so diverse that that there is no unified way to + * compute the slice offsets, so we store them in this table. + * + * The (x, y) offset to slice \c s at level \c l relative the miptrees + * base address is + * \code + * x = mt->level[l].slice[s].x_offset + * y = mt->level[l].slice[s].y_offset + */ + GLuint x_offset; + GLuint y_offset; + /** \} */ + } *slice; }; struct intel_mipmap_tree From 278e77a1192d5251c5b70a555e676f72b446e8e1 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Wed, 16 Nov 2011 22:26:38 -0800 Subject: [PATCH 11/41] intel: Refactor intel_miptree_copy_teximage() Extract the body of the inner loop into a new function, intel_miptree_copy_slice(). This is in preparation for adding support for separate stencil and HiZ to intel_miptree_copy_teximage(). When copying a slice of a depthstencil miptree that uses separate stencil, we will also need to copy the corresponding slice of the stencil miptree. The easiest way to do this will be to call intel_miptree_copy_slice() recursively. Analogous reasoning applies to copying a slice of a depth miptree with HiZ. Reviewed-by: Eric Anholt Reviewed-by: Kenneth Graunke Signed-off-by: Chad Versace --- .../drivers/dri/intel/intel_mipmap_tree.c | 122 ++++++++++-------- 1 file changed, 66 insertions(+), 56 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 7f9e606cd16..8f10101a233 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -354,6 +354,69 @@ intel_miptree_get_image_offset(struct intel_mipmap_tree *mt, } } +static void +intel_miptree_copy_slice(struct intel_context *intel, + struct intel_mipmap_tree *dst_mt, + struct intel_mipmap_tree *src_mt, + int level, + int face, + int depth) + +{ + gl_format format = src_mt->format; + uint32_t width = src_mt->level[level].width; + uint32_t height = src_mt->level[level].height; + + assert(depth < src_mt->level[level].depth); + + if (dst_mt->compressed) { + uint32_t align_w, align_h; + intel_get_texture_alignment_unit(format, + &align_w, &align_h); + height = ALIGN(height, align_h) / align_h; + width = ALIGN(width, align_w); + } + + uint32_t dst_x, dst_y, src_x, src_y; + intel_miptree_get_image_offset(dst_mt, level, face, depth, + &dst_x, &dst_y); + intel_miptree_get_image_offset(src_mt, level, face, depth, + &src_x, &src_y); + + DBG("validate blit mt %p %d,%d/%d -> mt %p %d,%d/%d (%dx%d)\n", + src_mt, src_x, src_y, src_mt->region->pitch * src_mt->region->cpp, + dst_mt, dst_x, dst_y, dst_mt->region->pitch * dst_mt->region->cpp, + width, height); + + if (!intelEmitCopyBlit(intel, + dst_mt->region->cpp, + src_mt->region->pitch, src_mt->region->bo, + 0, src_mt->region->tiling, + dst_mt->region->pitch, dst_mt->region->bo, + 0, dst_mt->region->tiling, + src_x, src_y, + dst_x, dst_y, + width, height, + GL_COPY)) { + + fallback_debug("miptree validate blit for %s failed\n", + _mesa_get_format_name(format)); + void *dst = intel_region_map(intel, dst_mt->region, GL_MAP_WRITE_BIT); + void *src = intel_region_map(intel, src_mt->region, GL_MAP_READ_BIT); + + _mesa_copy_rect(dst, + dst_mt->cpp, + dst_mt->region->pitch, + dst_x, dst_y, + width, height, + src, src_mt->region->pitch, + src_x, src_y); + + intel_region_unmap(intel, dst_mt->region); + intel_region_unmap(intel, src_mt->region); + } +} + /** * Copies the image's current data to the given miptree, and associates that * miptree with the image. @@ -366,65 +429,12 @@ intel_miptree_copy_teximage(struct intel_context *intel, struct intel_mipmap_tree *src_mt = intelImage->mt; int level = intelImage->base.Base.Level; int face = intelImage->base.Base.Face; - GLuint width = src_mt->level[level].width; - GLuint height = src_mt->level[level].height; GLuint depth = src_mt->level[level].depth; - int slice; - void *src, *dst; - if (dst_mt->compressed) { - unsigned int align_w, align_h; - - intel_get_texture_alignment_unit(intelImage->base.Base.TexFormat, - &align_w, &align_h); - height = ALIGN(height, align_h) / align_h; - width = ALIGN(width, align_w); - } - - for (slice = 0; slice < depth; slice++) { - unsigned int dst_x, dst_y, src_x, src_y; - - intel_miptree_get_image_offset(dst_mt, level, face, slice, - &dst_x, &dst_y); - - /* Copy potentially with the blitter: - */ - intel_miptree_get_image_offset(src_mt, level, face, slice, - &src_x, &src_y); - - DBG("validate blit mt %p %d,%d/%d -> mt %p %d,%d/%d (%dx%d)\n", - src_mt, src_x, src_y, src_mt->region->pitch * src_mt->region->cpp, - dst_mt, dst_x, dst_y, dst_mt->region->pitch * dst_mt->region->cpp, - width, height); - - if (!intelEmitCopyBlit(intel, - dst_mt->region->cpp, - src_mt->region->pitch, src_mt->region->bo, - 0, src_mt->region->tiling, - dst_mt->region->pitch, dst_mt->region->bo, - 0, dst_mt->region->tiling, - src_x, src_y, - dst_x, dst_y, - width, height, - GL_COPY)) { - - fallback_debug("miptree validate blit for %s failed\n", - _mesa_get_format_name(intelImage->base.Base.TexFormat)); - dst = intel_region_map(intel, dst_mt->region, GL_MAP_WRITE_BIT); - src = intel_region_map(intel, src_mt->region, GL_MAP_READ_BIT); - - _mesa_copy_rect(dst, - dst_mt->cpp, - dst_mt->region->pitch, - dst_x, dst_y, - width, height, - src, src_mt->region->pitch, - src_x, src_y); - - intel_region_unmap(intel, dst_mt->region); - intel_region_unmap(intel, src_mt->region); - } + for (int slice = 0; slice < depth; slice++) { + intel_miptree_copy_slice(intel, dst_mt, src_mt, level, face, slice); } intel_miptree_reference(&intelImage->mt, dst_mt); } + From d7b33309fe160212f2eb73f471f3aedcb5d0b5c1 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 09:55:40 -0800 Subject: [PATCH 12/41] intel: Kill intel_mipmap_level::nr_images [v4] For all texture targets except GL_TEXTURE_CUBE_MAP, the 'nr_images' and 'depth' fields of intel_mipmap_level were identical. In the exceptional case, nr_images == 6 and depth == 1. It is simple to determine if a texture is a cube or not, so the presence of two fields here was not helpful. Worse, it was confusing. When we eventually implement GL_ARB_texture_cube_map_array, this mess would have become even more confusing. This patch removes 'nr_images' and assigns to 'depth' a consistent meaning: depth is the number of 2D slices at each miplevel. The exact semantics of depth varies according to the texture target: - For GL_TEXTURE_CUBE_MAP, depth is 6. - For GL_TEXTURE_2D_ARRAY, depth is the number of array slices. It is identical for all miplevels in the texture. - For GL_TEXTURE_3D, it is the texture's depth at each miplevel. Its value, like width and height, varies with miplevel. - For other texture types, depth is 1. As a consequence, parameters were removed from the following function signatures: intel_miptree_set_level_info Remove 'nr_images'. i945_miptree_layout brw_miptree_layout_texture brw_miptree_layout_texture_array Remove 'slices'. v2: - Replace "It's" with "Its". - Remove all hunks in intel_fbo.c. The hunks were spurious and sneaked in during a rebase. - Remove unneeded hunk in intel_tex_map_image_for_swrast(). It was a little refactor of the for-loop's upper bound. v4: In intel_miptree_get_image_offset(), document the conditions under which different if-branches are taken. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i965/brw_tex_layout.c | 17 +++--- .../drivers/dri/intel/intel_mipmap_tree.c | 56 +++++++++++-------- .../drivers/dri/intel/intel_mipmap_tree.h | 18 ++++-- src/mesa/drivers/dri/intel/intel_tex_layout.c | 4 +- src/mesa/drivers/dri/intel/intel_tex_layout.h | 3 +- .../drivers/dri/intel/intel_tex_validate.c | 2 +- 6 files changed, 57 insertions(+), 43 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c index d77bf4d7cd9..ac6ade60959 100644 --- a/src/mesa/drivers/dri/i965/brw_tex_layout.c +++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c @@ -41,8 +41,7 @@ static void brw_miptree_layout_texture_array(struct intel_context *intel, - struct intel_mipmap_tree *mt, - int slices) + struct intel_mipmap_tree *mt) { GLuint align_w; GLuint align_h; @@ -58,14 +57,14 @@ brw_miptree_layout_texture_array(struct intel_context *intel, if (mt->compressed) qpitch /= 4; - i945_miptree_layout_2d(mt, slices); + i945_miptree_layout_2d(mt); for (level = mt->first_level; level <= mt->last_level; level++) { - for (q = 0; q < slices; q++) { + for (q = 0; q < mt->depth0; q++) { intel_miptree_set_image_offset(mt, level, q, 0, q * qpitch); } } - mt->total_height = qpitch * slices; + mt->total_height = qpitch * mt->depth0; } void @@ -82,7 +81,7 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt) * pitch of qpitch rows, where qpitch is defined by the equation given * in Volume 1 of the BSpec. */ - brw_miptree_layout_texture_array(intel, mt, 6); + brw_miptree_layout_texture_array(intel, mt); break; } /* FALLTHROUGH */ @@ -117,7 +116,7 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt) GLint y = 0; GLint q, j; - intel_miptree_set_level_info(mt, level, nr_images, + intel_miptree_set_level_info(mt, level, 0, mt->total_height, width, height, depth); @@ -170,11 +169,11 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt) case GL_TEXTURE_2D_ARRAY: case GL_TEXTURE_1D_ARRAY: - brw_miptree_layout_texture_array(intel, mt, mt->depth0); + brw_miptree_layout_texture_array(intel, mt); break; default: - i945_miptree_layout_2d(mt, 1); + i945_miptree_layout_2d(mt); break; } DBG("%s: %dx%dx%d\n", __FUNCTION__, diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 8f10101a233..53e669d58ae 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -82,11 +82,17 @@ intel_miptree_create_internal(struct intel_context *intel, mt->last_level = last_level; mt->width0 = width0; mt->height0 = height0; - mt->depth0 = depth0; mt->cpp = compress_byte ? compress_byte : _mesa_get_format_bytes(mt->format); mt->compressed = compress_byte ? 1 : 0; mt->refcount = 1; + if (target == GL_TEXTURE_CUBE_MAP) { + assert(depth0 == 1); + mt->depth0 = 6; + } else { + mt->depth0 = depth0; + } + #ifdef I915 (void) intel; if (intel->is_945) @@ -287,7 +293,6 @@ intel_miptree_match_image(struct intel_mipmap_tree *mt, void intel_miptree_set_level_info(struct intel_mipmap_tree *mt, GLuint level, - GLuint nr_images, GLuint x, GLuint y, GLuint w, GLuint h, GLuint d) { @@ -296,15 +301,13 @@ intel_miptree_set_level_info(struct intel_mipmap_tree *mt, mt->level[level].depth = d; mt->level[level].level_x = x; mt->level[level].level_y = y; - mt->level[level].nr_images = nr_images; DBG("%s level %d size: %d,%d,%d offset %d,%d\n", __FUNCTION__, level, w, h, d, x, y); - assert(nr_images); assert(mt->level[level].slice == NULL); - mt->level[level].slice = malloc(nr_images * sizeof(*mt->level[0].slice)); + mt->level[level].slice = malloc(d * sizeof(*mt->level[0].slice)); mt->level[level].slice[0].x_offset = mt->level[level].level_x; mt->level[level].slice[0].y_offset = mt->level[level].level_y; } @@ -318,7 +321,7 @@ intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, if (img == 0 && level == 0) assert(x == 0 && y == 0); - assert(img < mt->level[level].nr_images); + assert(img < mt->level[level].depth); mt->level[level].slice[img].x_offset = mt->level[level].level_x + x; mt->level[level].slice[img].y_offset = mt->level[level].level_y + y; @@ -330,28 +333,33 @@ intel_miptree_set_image_offset(struct intel_mipmap_tree *mt, } +/** + * For cube map textures, either the \c face parameter can be used, of course, + * or the cube face can be interpreted as a depth layer and the \c layer + * parameter used. + */ void intel_miptree_get_image_offset(struct intel_mipmap_tree *mt, - GLuint level, GLuint face, GLuint depth, + GLuint level, GLuint face, GLuint layer, GLuint *x, GLuint *y) { - switch (mt->target) { - case GL_TEXTURE_CUBE_MAP_ARB: - *x = mt->level[level].slice[face].x_offset; - *y = mt->level[level].slice[face].y_offset; - break; - case GL_TEXTURE_3D: - case GL_TEXTURE_2D_ARRAY_EXT: - case GL_TEXTURE_1D_ARRAY_EXT: - assert(depth < mt->level[level].nr_images); - *x = mt->level[level].slice[depth].x_offset; - *y = mt->level[level].slice[depth].y_offset; - break; - default: - *x = mt->level[level].slice[0].x_offset; - *y = mt->level[level].slice[0].y_offset; - break; + int slice; + + if (face > 0) { + assert(mt->target == GL_TEXTURE_CUBE_MAP); + assert(face < 6); + assert(layer == 0); + slice = face; + } else { + /* This branch may be taken even if the texture target is a cube map. In + * that case, the caller chose to interpret each cube face as a layer. + */ + assert(face == 0); + slice = layer; } + + *x = mt->level[level].slice[slice].x_offset; + *y = mt->level[level].slice[slice].y_offset; } static void @@ -429,7 +437,7 @@ intel_miptree_copy_teximage(struct intel_context *intel, struct intel_mipmap_tree *src_mt = intelImage->mt; int level = intelImage->base.Base.Level; int face = intelImage->base.Base.Face; - GLuint depth = src_mt->level[level].depth; + GLuint depth = intelImage->base.Base.Depth; for (int slice = 0; slice < depth; slice++) { intel_miptree_copy_slice(intel, dst_mt, src_mt, level, face, slice); diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index 2cad793acf3..8f024f9524f 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -69,16 +69,25 @@ struct intel_mipmap_level GLuint level_y; GLuint width; GLuint height; - /** Depth of the mipmap at this level: 1 for 1D/2D/CUBE, n for 3D. */ + + /** + * \brief Number of 2D slices in this miplevel. + * + * The exact semantics of depth varies according to the texture target: + * - For GL_TEXTURE_CUBE_MAP, depth is 6. + * - For GL_TEXTURE_2D_ARRAY, depth is the number of array slices. It is + * identical for all miplevels in the texture. + * - For GL_TEXTURE_3D, it is the texture's depth at this miplevel. Its + * value, like width and height, varies with miplevel. + * - For other texture types, depth is 1. + */ GLuint depth; - /** Number of images at this level: 1 for 1D/2D, 6 for CUBE, depth for 3D */ - GLuint nr_images; /** * \brief List of 2D images in this mipmap level. * * This may be a list of cube faces, array slices in 2D array texture, or - * layers in a 3D texture. The list's length is \c nr_images. + * layers in a 3D texture. The list's length is \c depth. */ struct intel_mipmap_slice { /** @@ -205,7 +214,6 @@ intel_miptree_get_dimensions_for_image(struct gl_texture_image *image, void intel_miptree_set_level_info(struct intel_mipmap_tree *mt, GLuint level, - GLuint nr_images, GLuint x, GLuint y, GLuint w, GLuint h, GLuint d); diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.c b/src/mesa/drivers/dri/intel/intel_tex_layout.c index 64f4a70c52c..e6324cf2eea 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_layout.c +++ b/src/mesa/drivers/dri/intel/intel_tex_layout.c @@ -50,7 +50,7 @@ intel_get_texture_alignment_unit(gl_format format, } } -void i945_miptree_layout_2d(struct intel_mipmap_tree *mt, int nr_images) +void i945_miptree_layout_2d(struct intel_mipmap_tree *mt) { GLuint align_h, align_w; GLuint level; @@ -93,7 +93,7 @@ void i945_miptree_layout_2d(struct intel_mipmap_tree *mt, int nr_images) for ( level = mt->first_level ; level <= mt->last_level ; level++ ) { GLuint img_height; - intel_miptree_set_level_info(mt, level, nr_images, x, y, width, + intel_miptree_set_level_info(mt, level, x, y, width, height, depth); img_height = ALIGN(height, align_h); diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.h b/src/mesa/drivers/dri/intel/intel_tex_layout.h index 257c07ce476..c6c865d2c80 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_layout.h +++ b/src/mesa/drivers/dri/intel/intel_tex_layout.h @@ -38,7 +38,6 @@ static INLINE GLuint minify( GLuint d ) return MAX2(1, d>>1); } -extern void i945_miptree_layout_2d(struct intel_mipmap_tree *mt, - int nr_images); +extern void i945_miptree_layout_2d(struct intel_mipmap_tree *mt); void intel_get_texture_alignment_unit(gl_format format, unsigned int *w, unsigned int *h); diff --git a/src/mesa/drivers/dri/intel/intel_tex_validate.c b/src/mesa/drivers/dri/intel/intel_tex_validate.c index f4c1a688657..748fbdca2b9 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_validate.c +++ b/src/mesa/drivers/dri/intel/intel_tex_validate.c @@ -154,7 +154,7 @@ intel_tex_map_image_for_swrast(struct intel_context *intel, intel_image->base.Data = intel_region_map(intel, mt->region, mode); } else { - assert(mt->level[level].depth == 1); + assert(intel_image->base.Base.Depth == 1); intel_miptree_get_image_offset(mt, level, face, 0, &x, &y); DBG("%s: (%d,%d) -> (%d, %d)/%d\n", From 24da7335b22432ef4c2d57cab86e4b8fbe8733d5 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 10:05:21 -0800 Subject: [PATCH 13/41] intel: Track the miptree layer wrapped by a renderbuffer [v2] TODO: Make v2 for kwg. Add two fields to intel_renderbuffer: mt_level mt_layer Multiple renderbuffers may simultaneously wrap a single texture and each provide a different view into that texture. [Consider glFramebufferTextureLayer()]. The new fields indicate which slice of the miptree is wrapped by the renderbuffer. The buffer resolve operations, to be introduced in the future, require these fields in order to resolve the correct slice in the miptree. To add the fields, it was necessary to replace the type of some function parameters from gl_texture_image to gl_renderbuffer_attachment. v2: [kwg] Replace confusing condition `CubeMapFace > 0` with the more sensible `Target == GL_TEXTURE_CUBE_MAP`. Reviewed-by: Eric Anholt Reviewed-by: Kenneth Graunke Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_fbo.c | 37 ++++++++++++++++++++++---- src/mesa/drivers/dri/intel/intel_fbo.h | 17 ++++++++++++ 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index e5328df2ff5..252f2425f2a 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -948,8 +948,9 @@ intel_framebuffer_renderbuffer(struct gl_context * ctx, static bool intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb, - struct gl_texture_image *texImage) + struct gl_renderbuffer_attachment *att) { + struct gl_texture_image *texImage = _mesa_get_attachment_teximage(att); struct intel_texture_image *intel_image = intel_texture_image(texImage); int width, height, depth; @@ -973,15 +974,40 @@ intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb, irb->Base.Delete = intel_delete_renderbuffer; irb->Base.AllocStorage = intel_nop_alloc_storage; + irb->mt_level = att->TextureLevel; + if (texImage->TexObject->Target == GL_TEXTURE_CUBE_MAP) { + assert(att->Zoffset == 0); + irb->mt_layer = att->CubeMapFace; + } else { + assert(att->CubeMapFace == 0); + irb->mt_layer= att->Zoffset; + } + if (intel_image->stencil_rb) { /* The tex image has packed depth/stencil format, but is using separate * stencil. It shares its embedded depth and stencil renderbuffers with * the renderbuffer wrapper. + * + * FIXME: glFramebufferTexture*() is broken for depthstencil textures + * FIXME: with separate stencil. To fix this, we must create a separate + * FIXME: pair of depth/stencil renderbuffers for each attached slice + * FIXME: of the miptree. */ + struct intel_renderbuffer *depth_irb; + struct intel_renderbuffer *stencil_irb; + _mesa_reference_renderbuffer(&irb->wrapped_depth, intel_image->depth_rb); _mesa_reference_renderbuffer(&irb->wrapped_stencil, intel_image->stencil_rb); + + depth_irb = intel_renderbuffer(intel_image->depth_rb); + depth_irb->mt_level = irb->mt_level; + depth_irb->mt_layer = irb->mt_layer; + + stencil_irb = intel_renderbuffer(intel_image->stencil_rb); + stencil_irb->mt_level = irb->mt_level; + stencil_irb->mt_layer = irb->mt_layer; } else { intel_miptree_reference(&irb->mt, intel_image->mt); } @@ -994,7 +1020,8 @@ intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb, * This will have the region info needed for hardware rendering. */ static struct intel_renderbuffer * -intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage) +intel_wrap_texture(struct gl_context * ctx, + struct gl_renderbuffer_attachment *att) { const GLuint name = ~0; /* not significant, but distinct for debugging */ struct intel_renderbuffer *irb; @@ -1009,7 +1036,7 @@ intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage) _mesa_init_renderbuffer(&irb->Base, name); irb->Base.ClassID = INTEL_RB_CLASS; - if (!intel_update_wrapper(ctx, irb, texImage)) { + if (!intel_update_wrapper(ctx, irb, att)) { free(irb); return NULL; } @@ -1114,7 +1141,7 @@ intel_render_texture(struct gl_context * ctx, return; } else if (!irb) { - irb = intel_wrap_texture(ctx, image); + irb = intel_wrap_texture(ctx, att); if (irb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base); @@ -1126,7 +1153,7 @@ intel_render_texture(struct gl_context * ctx, } } - if (!intel_update_wrapper(ctx, irb, image)) { + if (!intel_update_wrapper(ctx, irb, att)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; diff --git a/src/mesa/drivers/dri/intel/intel_fbo.h b/src/mesa/drivers/dri/intel/intel_fbo.h index 34d2f9a61cf..3a213745e38 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.h +++ b/src/mesa/drivers/dri/intel/intel_fbo.h @@ -51,6 +51,23 @@ struct intel_renderbuffer GLuint map_x, map_y, map_w, map_h; GLbitfield map_mode; + /** + * \name Miptree view + * \{ + * + * Multiple renderbuffers may simultaneously wrap a single texture and each + * provide a different view into that texture. The fields below indicate + * which miptree slice is wrapped by this renderbuffer. The fields' values + * are consistent with the 'level' and 'layer' parameters of + * glFramebufferTextureLayer(). + * + * For renderbuffers not created with glFramebufferTexture*(), mt_level and + * mt_layer are 0. + */ + unsigned int mt_level; + unsigned int mt_layer; + /** \} */ + /** * \name Packed depth/stencil unwrappers * From 3b38b33c1648b07e75dc4d8340758171e109c598 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 10:22:14 -0800 Subject: [PATCH 14/41] intel: Remove unneeded params from intel_renderbuffer_set_draw_offset() Since the renderbuffer tracks the miptree level and layer that it wraps, the 'tex_image' and 'zoffset' params are no longer needed to calculate the draw offsets. Not only are they no longer needed, but their presence would prevent calculating the renderbuffer draw offsets in situations where there were no texture image. Such situations will occur during the HiZ meta-op and during scatter/gather of separate stencil textures. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_fbo.c | 16 +++++++--------- src/mesa/drivers/dri/intel/intel_fbo.h | 4 +--- src/mesa/drivers/dri/intel/intel_tex_image.c | 4 ++-- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index 252f2425f2a..dd7adfbb051 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -1045,17 +1045,15 @@ intel_wrap_texture(struct gl_context * ctx, } void -intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb, - struct intel_texture_image *intel_image, - int zoffset) +intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb) { unsigned int dst_x, dst_y; /* compute offset of the particular 2D image within the texture region */ - intel_miptree_get_image_offset(intel_image->mt, - intel_image->base.Base.Level, - intel_image->base.Base.Face, - zoffset, + intel_miptree_get_image_offset(irb->mt, + irb->mt_level, + 0, /* face, which we ignore */ + irb->mt_layer, &dst_x, &dst_y); irb->draw_x = dst_x; @@ -1164,7 +1162,7 @@ intel_render_texture(struct gl_context * ctx, att->Texture->Name, image->Width, image->Height, irb->Base.RefCount); - intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset); + intel_renderbuffer_set_draw_offset(irb); intel_image->used_as_render_target = true; #ifndef I915 @@ -1190,7 +1188,7 @@ intel_render_texture(struct gl_context * ctx, true); intel_miptree_copy_teximage(intel, intel_image, new_mt); - intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset); + intel_renderbuffer_set_draw_offset(irb); intel_miptree_reference(&irb->mt, intel_image->mt); intel_miptree_release(&new_mt); diff --git a/src/mesa/drivers/dri/intel/intel_fbo.h b/src/mesa/drivers/dri/intel/intel_fbo.h index 3a213745e38..6da370dbd26 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.h +++ b/src/mesa/drivers/dri/intel/intel_fbo.h @@ -175,9 +175,7 @@ extern void intel_flip_renderbuffers(struct gl_framebuffer *fb); void -intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb, - struct intel_texture_image *intel_image, - int zoffset); +intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb); uint32_t intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb, diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index 90e409094d5..024490a4115 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -316,8 +316,8 @@ intel_tex_image_s8z24_create_renderbuffers(struct intel_context *intel, return false; } - intel_renderbuffer_set_draw_offset(idrb, image, 0); - intel_renderbuffer_set_draw_offset(isrb, image, 0); + intel_renderbuffer_set_draw_offset(idrb); + intel_renderbuffer_set_draw_offset(isrb); _mesa_reference_renderbuffer(&image->depth_rb, drb); _mesa_reference_renderbuffer(&image->stencil_rb, srb); From 73540690f71280a2bdda51b45203fd4ed43a1760 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Wed, 16 Nov 2011 22:42:44 -0800 Subject: [PATCH 15/41] intel: Define intel_miptree_check_level_layer() This is a small helper function that asserts that a given level and layer are valid for a miptree. I will be extensively using it in the future miptree HiZ functions. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_mipmap_tree.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index 8f024f9524f..d6134f8c780 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -28,6 +28,8 @@ #ifndef INTEL_MIPMAP_TREE_H #define INTEL_MIPMAP_TREE_H +#include + #include "intel_regions.h" /* A layer on top of the intel_regions code which adds: @@ -188,6 +190,17 @@ intel_miptree_create_for_renderbuffer(struct intel_context *intel, uint32_t width, uint32_t height); +/** \brief Assert that the level and layer are valid for the miptree. */ +static inline void +intel_miptree_check_level_layer(struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer) +{ + assert(level >= mt->first_level); + assert(level <= mt->last_level); + assert(layer < mt->level[level].depth); +} + int intel_miptree_pitch_align (struct intel_context *intel, struct intel_mipmap_tree *mt, uint32_t tiling, From c80b31fdee1fa96b8d45ad2537ecdb5b9151973e Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 22:11:33 -0800 Subject: [PATCH 16/41] intel: Refactor intel_render_texture() [v2] This is in preparation for properly implementing glFramebufferTexture*() for mipmapped depthstencil textures. The FIXME comments deleted by this patch give a rough explanation of what was broken. This refactor does the following: - In intel_update_wrapper() and intel_wrap_texture(), change the parameters to prepare to remove functions' dependency on gl_texture_image. - Move the call to intel_renderbuffer_set_draw_offsets() from intel_render_texture() into intel_udpate_wrapper(). Each time I encounter those functions, I dislike their vague names. (Update which wrapper? What is wrapped? What is the wrapper?). So, while I was mucking around, I also renamed the functions. v2: In addition to the ``GLenum internal_format`` parameter to intel_wrap_miptree(), add a ``gl_format format`` parameter. This removes the need to recalculate for the true format from internal_format with ChooseNewTextureFormat, which was just weird. Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_fbo.c | 121 ++++++++++++++++++------- 1 file changed, 88 insertions(+), 33 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index dd7adfbb051..71ac638c061 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -946,42 +946,52 @@ intel_framebuffer_renderbuffer(struct gl_context * ctx, intel_draw_buffer(ctx); } +/** + * NOTE: The 'att' parameter is a kludge that will soon be removed. Its + * presence allows us to refactor the wrapping of depthstencil textures that + * use separate stencil in two easily manageable steps, rather than in one + * large, hairy step. First, refactor the common wrapping code used by all + * texture formats. Second, refactor the separate stencil code paths. + */ static bool -intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb, - struct gl_renderbuffer_attachment *att) +intel_renderbuffer_update_wrapper(struct intel_context *intel, + struct intel_renderbuffer *irb, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer, + gl_format format, + GLenum internal_format, + struct gl_renderbuffer_attachment *att) { + struct gl_renderbuffer *rb = &irb->Base; + + /* The image variables are a kludge. See the note above for the att + * parameter. + */ struct gl_texture_image *texImage = _mesa_get_attachment_teximage(att); struct intel_texture_image *intel_image = intel_texture_image(texImage); - int width, height, depth; - if (!intel_span_supports_format(texImage->TexFormat)) { + rb->Format = format; + if (!intel_span_supports_format(rb->Format)) { DBG("Render to texture BAD FORMAT %s\n", - _mesa_get_format_name(texImage->TexFormat)); + _mesa_get_format_name(rb->Format)); return false; } else { - DBG("Render to texture %s\n", _mesa_get_format_name(texImage->TexFormat)); + DBG("Render to texture %s\n", _mesa_get_format_name(rb->Format)); } - intel_miptree_get_dimensions_for_image(texImage, &width, &height, &depth); - - irb->Base.Format = texImage->TexFormat; - irb->Base.DataType = intel_mesa_format_to_rb_datatype(texImage->TexFormat); - irb->Base.InternalFormat = texImage->InternalFormat; - irb->Base._BaseFormat = _mesa_base_tex_format(ctx, irb->Base.InternalFormat); - irb->Base.Width = width; - irb->Base.Height = height; + rb->InternalFormat = internal_format; + rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format); + rb->_BaseFormat = _mesa_get_format_base_format(rb->Format); + rb->Width = mt->level[level].width; + rb->Height = mt->level[level].height; irb->Base.Delete = intel_delete_renderbuffer; irb->Base.AllocStorage = intel_nop_alloc_storage; - irb->mt_level = att->TextureLevel; - if (texImage->TexObject->Target == GL_TEXTURE_CUBE_MAP) { - assert(att->Zoffset == 0); - irb->mt_layer = att->CubeMapFace; - } else { - assert(att->CubeMapFace == 0); - irb->mt_layer= att->Zoffset; - } + intel_miptree_check_level_layer(mt, level, layer); + irb->mt_level = level; + irb->mt_layer = layer; if (intel_image->stencil_rb) { /* The tex image has packed depth/stencil format, but is using separate @@ -1004,29 +1014,51 @@ intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb, depth_irb = intel_renderbuffer(intel_image->depth_rb); depth_irb->mt_level = irb->mt_level; depth_irb->mt_layer = irb->mt_layer; + intel_renderbuffer_set_draw_offset(depth_irb); stencil_irb = intel_renderbuffer(intel_image->stencil_rb); stencil_irb->mt_level = irb->mt_level; stencil_irb->mt_layer = irb->mt_layer; + intel_renderbuffer_set_draw_offset(stencil_irb); } else { intel_miptree_reference(&irb->mt, intel_image->mt); + intel_renderbuffer_set_draw_offset(irb); } + return true; } /** - * When glFramebufferTexture[123]D is called this function sets up the - * gl_renderbuffer wrapper around the texture image. - * This will have the region info needed for hardware rendering. + * \brief Wrap a renderbuffer around a single slice of a miptree. + * + * Called by glFramebufferTexture*(). This just allocates a + * ``struct intel_renderbuffer`` then calls + * intel_renderbuffer_update_wrapper() to do the real work. + * + * NOTE: The 'att' parameter is a kludge that will soon be removed. Its + * presence allows us to refactor the wrapping of depthstencil textures that + * use separate stencil in two easily manageable steps, rather than in one + * large, hairy step. First, refactor the common wrapping code used by all + * texture formats. Second, refactor the separate stencil code paths. + * + * \see intel_renderbuffer_update_wrapper() */ -static struct intel_renderbuffer * -intel_wrap_texture(struct gl_context * ctx, - struct gl_renderbuffer_attachment *att) +static struct intel_renderbuffer* +intel_renderbuffer_wrap_miptree(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer, + gl_format format, + GLenum internal_format, + struct gl_renderbuffer_attachment *att) + { const GLuint name = ~0; /* not significant, but distinct for debugging */ + struct gl_context *ctx = &intel->ctx; struct intel_renderbuffer *irb; - /* make an intel_renderbuffer to wrap the texture image */ + intel_miptree_check_level_layer(mt, level, layer); + irb = CALLOC_STRUCT(intel_renderbuffer); if (!irb) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture"); @@ -1036,7 +1068,10 @@ intel_wrap_texture(struct gl_context * ctx, _mesa_init_renderbuffer(&irb->Base, name); irb->Base.ClassID = INTEL_RB_CLASS; - if (!intel_update_wrapper(ctx, irb, att)) { + if (!intel_renderbuffer_update_wrapper(intel, irb, + mt, level, layer, + format, internal_format, + att)) { free(irb); return NULL; } @@ -1124,12 +1159,22 @@ intel_render_texture(struct gl_context * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { + struct intel_context *intel = intel_context(ctx); struct gl_texture_image *image = _mesa_get_attachment_teximage(att); struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); struct intel_texture_image *intel_image = intel_texture_image(image); + struct intel_mipmap_tree *mt = intel_image->mt; (void) fb; + int layer; + if (att->CubeMapFace > 0) { + assert(att->Zoffset == 0); + layer = att->CubeMapFace; + } else { + layer = att->Zoffset; + } + if (!intel_image->mt) { /* Fallback on drawing to a texture that doesn't have a miptree * (has a border, width/height 0, etc.) @@ -1139,7 +1184,14 @@ intel_render_texture(struct gl_context * ctx, return; } else if (!irb) { - irb = intel_wrap_texture(ctx, att); + irb = intel_renderbuffer_wrap_miptree(intel, + mt, + att->TextureLevel, + layer, + image->TexFormat, + image->InternalFormat, + att); + if (irb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base); @@ -1151,7 +1203,11 @@ intel_render_texture(struct gl_context * ctx, } } - if (!intel_update_wrapper(ctx, irb, att)) { + if (!intel_renderbuffer_update_wrapper(intel, irb, + mt, att->TextureLevel, layer, + image->TexFormat, + image->InternalFormat, + att)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; @@ -1162,7 +1218,6 @@ intel_render_texture(struct gl_context * ctx, att->Texture->Name, image->Width, image->Height, irb->Base.RefCount); - intel_renderbuffer_set_draw_offset(irb); intel_image->used_as_render_target = true; #ifndef I915 From 3eb12dfaeed03f77e31943eea164acb03e86bbc9 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 22:17:34 -0800 Subject: [PATCH 17/41] intel: Replace intel_texture_image::stencil_irb with intel_mipmap_tree::stencil_mt [v3] For depthstencil textures using separate stencil, we embedded a stencil buffer in intel_texture_image. The intention was that the embedded stencil buffer would be the golden copy of the texture's stencil bits. When necessary, we scattered/gathered the stencil bits between the texture miptree and the embedded stencil buffer. This approach had a serious deficiency for mipmapped or multi-layer textures. Any given moment the embedded stencil buffer was consistent with exactly one miptree slice, the most recent one to be scattered. This permitted tests of type A to pass, but broke tests of type B. Test A: 1. Create a depthstencil texture. 2. Upload data into (level=x1,layer=y1). 3. Read and test stencil data at (level=x1, layer=y1). 4. Upload data into (level=x2,layer=y2). 5. Read and test stencil data at (level=x2, layer=y2). Test B: 1. Create a depthstencil texture. 2. Upload data into (level=x1,layer=y1). 3. Upload data into (level=x2,layer=y2). 4. Read and test stencil data at (level=x1, layer=y1). 5. Read and test stencil data at (level=x2, layer=y2). v2: Only allocate stencil miptree if intel->must_use_separate_stencil, because we don't make the conversion from must_use_separate_stencil to has_separate_stencil until commit intel: Use separate stencil whenever possible v3: Don't call ChooseNewTexture in intel_renderbuffer_wrap_miptree() in order to determine the renderbuffer format. Instead, pass the format as a param to that function. CC: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_fbo.c | 114 ++++++++------- .../drivers/dri/intel/intel_mipmap_tree.c | 134 +++++++++++++++++- .../drivers/dri/intel/intel_mipmap_tree.h | 37 +++++ src/mesa/drivers/dri/intel/intel_tex.c | 41 +++--- src/mesa/drivers/dri/intel/intel_tex_image.c | 128 ----------------- src/mesa/drivers/dri/intel/intel_tex_obj.h | 30 ---- 6 files changed, 250 insertions(+), 234 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index 71ac638c061..9aa0f98501a 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -36,6 +36,8 @@ #include "main/renderbuffer.h" #include "main/context.h" #include "main/teximage.h" +#include "main/image.h" + #include "swrast/swrast.h" #include "drivers/common/meta.h" @@ -946,12 +948,26 @@ intel_framebuffer_renderbuffer(struct gl_context * ctx, intel_draw_buffer(ctx); } +static struct intel_renderbuffer* +intel_renderbuffer_wrap_miptree(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer, + gl_format format, + GLenum internal_format); + /** - * NOTE: The 'att' parameter is a kludge that will soon be removed. Its - * presence allows us to refactor the wrapping of depthstencil textures that - * use separate stencil in two easily manageable steps, rather than in one - * large, hairy step. First, refactor the common wrapping code used by all - * texture formats. Second, refactor the separate stencil code paths. + * \par Special case for separate stencil + * + * When wrapping a depthstencil texture that uses separate stencil, this + * function is recursively called twice: once to create \c + * irb->wrapped_depth and again to create \c irb->wrapped_stencil. On the + * call to create \c irb->wrapped_depth, the \c format and \c + * internal_format parameters do not match \c mt->format. In that case, \c + * mt->format is MESA_FORMAT_S8_Z24 and \c format is \c + * MESA_FORMAT_X8_Z24. + * + * @return true on success */ static bool intel_renderbuffer_update_wrapper(struct intel_context *intel, @@ -960,17 +976,10 @@ intel_renderbuffer_update_wrapper(struct intel_context *intel, uint32_t level, uint32_t layer, gl_format format, - GLenum internal_format, - struct gl_renderbuffer_attachment *att) + GLenum internal_format) { struct gl_renderbuffer *rb = &irb->Base; - /* The image variables are a kludge. See the note above for the att - * parameter. - */ - struct gl_texture_image *texImage = _mesa_get_attachment_teximage(att); - struct intel_texture_image *intel_image = intel_texture_image(texImage); - rb->Format = format; if (!intel_span_supports_format(rb->Format)) { DBG("Render to texture BAD FORMAT %s\n", @@ -993,35 +1002,50 @@ intel_renderbuffer_update_wrapper(struct intel_context *intel, irb->mt_level = level; irb->mt_layer = layer; - if (intel_image->stencil_rb) { - /* The tex image has packed depth/stencil format, but is using separate - * stencil. It shares its embedded depth and stencil renderbuffers with - * the renderbuffer wrapper. - * - * FIXME: glFramebufferTexture*() is broken for depthstencil textures - * FIXME: with separate stencil. To fix this, we must create a separate - * FIXME: pair of depth/stencil renderbuffers for each attached slice - * FIXME: of the miptree. - */ + if (mt->stencil_mt && _mesa_is_depthstencil_format(rb->InternalFormat)) { + assert((irb->wrapped_depth == NULL) == (irb->wrapped_stencil == NULL)); + struct intel_renderbuffer *depth_irb; struct intel_renderbuffer *stencil_irb; - _mesa_reference_renderbuffer(&irb->wrapped_depth, - intel_image->depth_rb); - _mesa_reference_renderbuffer(&irb->wrapped_stencil, - intel_image->stencil_rb); + if (!irb->wrapped_depth) { + depth_irb = intel_renderbuffer_wrap_miptree(intel, + mt, level, layer, + MESA_FORMAT_X8_Z24, + GL_DEPTH_COMPONENT24); + stencil_irb = intel_renderbuffer_wrap_miptree(intel, + mt->stencil_mt, + level, layer, + MESA_FORMAT_S8, + GL_STENCIL_INDEX8); + _mesa_reference_renderbuffer(&irb->wrapped_depth, &depth_irb->Base); + _mesa_reference_renderbuffer(&irb->wrapped_stencil, &stencil_irb->Base); - depth_irb = intel_renderbuffer(intel_image->depth_rb); - depth_irb->mt_level = irb->mt_level; - depth_irb->mt_layer = irb->mt_layer; - intel_renderbuffer_set_draw_offset(depth_irb); + if (!irb->wrapped_depth || !irb->wrapped_stencil) + return false; + } else { + bool ok = true; - stencil_irb = intel_renderbuffer(intel_image->stencil_rb); - stencil_irb->mt_level = irb->mt_level; - stencil_irb->mt_layer = irb->mt_layer; - intel_renderbuffer_set_draw_offset(stencil_irb); + depth_irb = intel_renderbuffer(irb->wrapped_depth); + stencil_irb = intel_renderbuffer(irb->wrapped_stencil); + + ok &= intel_renderbuffer_update_wrapper(intel, + depth_irb, + mt, + level, layer, + MESA_FORMAT_X8_Z24, + GL_DEPTH_COMPONENT24); + ok &= intel_renderbuffer_update_wrapper(intel, + stencil_irb, + mt->stencil_mt, + level, layer, + MESA_FORMAT_S8, + GL_STENCIL_INDEX8); + if (!ok) + return false; + } } else { - intel_miptree_reference(&irb->mt, intel_image->mt); + intel_miptree_reference(&irb->mt, mt); intel_renderbuffer_set_draw_offset(irb); } @@ -1035,12 +1059,6 @@ intel_renderbuffer_update_wrapper(struct intel_context *intel, * ``struct intel_renderbuffer`` then calls * intel_renderbuffer_update_wrapper() to do the real work. * - * NOTE: The 'att' parameter is a kludge that will soon be removed. Its - * presence allows us to refactor the wrapping of depthstencil textures that - * use separate stencil in two easily manageable steps, rather than in one - * large, hairy step. First, refactor the common wrapping code used by all - * texture formats. Second, refactor the separate stencil code paths. - * * \see intel_renderbuffer_update_wrapper() */ static struct intel_renderbuffer* @@ -1049,8 +1067,7 @@ intel_renderbuffer_wrap_miptree(struct intel_context *intel, uint32_t level, uint32_t layer, gl_format format, - GLenum internal_format, - struct gl_renderbuffer_attachment *att) + GLenum internal_format) { const GLuint name = ~0; /* not significant, but distinct for debugging */ @@ -1070,8 +1087,7 @@ intel_renderbuffer_wrap_miptree(struct intel_context *intel, if (!intel_renderbuffer_update_wrapper(intel, irb, mt, level, layer, - format, internal_format, - att)) { + format, internal_format)) { free(irb); return NULL; } @@ -1189,8 +1205,7 @@ intel_render_texture(struct gl_context * ctx, att->TextureLevel, layer, image->TexFormat, - image->InternalFormat, - att); + image->InternalFormat); if (irb) { /* bind the wrapper to the attachment point */ @@ -1206,8 +1221,7 @@ intel_render_texture(struct gl_context * ctx, if (!intel_renderbuffer_update_wrapper(intel, irb, mt, att->TextureLevel, layer, image->TexFormat, - image->InternalFormat, - att)) { + image->InternalFormat)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 53e669d58ae..b55e16a4554 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -25,14 +25,18 @@ * **************************************************************************/ +#include "intel_batchbuffer.h" #include "intel_context.h" #include "intel_mipmap_tree.h" #include "intel_regions.h" +#include "intel_span.h" #include "intel_tex_layout.h" #include "intel_tex.h" #include "intel_blit.h" + #include "main/enums.h" #include "main/formats.h" +#include "main/image.h" #include "main/teximage.h" #define FILE_DEBUG_FLAG DEBUG_MIPTREE @@ -54,7 +58,6 @@ target_to_target(GLenum target) } } - static struct intel_mipmap_tree * intel_miptree_create_internal(struct intel_context *intel, GLenum target, @@ -93,6 +96,16 @@ intel_miptree_create_internal(struct intel_context *intel, mt->depth0 = depth0; } + if (format == MESA_FORMAT_S8) { + /* The stencil buffer has quirky pitch requirements. From Vol 2a, + * 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch": + * The pitch must be set to 2x the value computed based on width, as + * the stencil buffer is stored with two rows interleaved. + */ + assert(intel->has_separate_stencil); + mt->cpp = 2; + } + #ifdef I915 (void) intel; if (intel->is_945) @@ -103,6 +116,23 @@ intel_miptree_create_internal(struct intel_context *intel, brw_miptree_layout(intel, mt); #endif + if (intel->must_use_separate_stencil && + _mesa_is_depthstencil_format(_mesa_get_format_base_format(format))) { + mt->stencil_mt = intel_miptree_create(intel, + mt->target, + MESA_FORMAT_S8, + mt->first_level, + mt->last_level, + mt->width0, + mt->height0, + mt->depth0, + true); + if (!mt->stencil_mt) { + intel_miptree_release(&mt); + return NULL; + } + } + return mt; } @@ -127,6 +157,8 @@ intel_miptree_create(struct intel_context *intel, (base_format == GL_DEPTH_COMPONENT || base_format == GL_DEPTH_STENCIL_EXT)) tiling = I915_TILING_Y; + else if (format == MESA_FORMAT_S8) + tiling = I915_TILING_NONE; else if (width0 >= 64) tiling = I915_TILING_X; } @@ -230,6 +262,7 @@ intel_miptree_release(struct intel_mipmap_tree **mt) intel_region_release(&((*mt)->region)); intel_region_release(&((*mt)->hiz_region)); + intel_miptree_release(&(*mt)->stencil_mt); for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { free((*mt)->level[i].slice); @@ -423,6 +456,12 @@ intel_miptree_copy_slice(struct intel_context *intel, intel_region_unmap(intel, dst_mt->region); intel_region_unmap(intel, src_mt->region); } + + if (src_mt->stencil_mt) { + intel_miptree_copy_slice(intel, + dst_mt->stencil_mt, src_mt->stencil_mt, + level, face, depth); + } } /** @@ -446,3 +485,96 @@ intel_miptree_copy_teximage(struct intel_context *intel, intel_miptree_reference(&intelImage->mt, dst_mt); } +/** + * \param scatter Scatter if true. Gather if false. + * + * \see intel_miptree_s8z24_scatter() + * \see intel_miptree_s8z24_gather() + */ +static void +intel_miptree_s8z24_scattergather(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer, + bool scatter) +{ + /* Check function inputs. */ + assert(level >= mt->first_level); + assert(level <= mt->last_level); + assert(layer < mt->level[level].depth); + + /* Label everything and its bit layout, just to make the code easier to + * read. + */ + struct intel_mipmap_tree *s8_mt = mt->stencil_mt; + struct intel_mipmap_level *s8_level = &s8_mt->level[level]; + struct intel_mipmap_slice *s8_slice = &s8_mt->level[level].slice[layer]; + + struct intel_mipmap_tree *s8z24_mt = mt; + struct intel_mipmap_level *s8z24_level = &s8z24_mt->level[level]; + struct intel_mipmap_slice *s8z24_slice = &s8z24_mt->level[level].slice[layer]; + + /* Check that both miptree levels have the same dimensions. */ + assert(s8_level->width == s8z24_level->width); + assert(s8_level->height == s8z24_level->height); + assert(s8_level->depth == s8z24_level->depth); + + /* Map the buffers. */ + if (drm_intel_bo_references(intel->batch.bo, s8_mt->region->bo) || + drm_intel_bo_references(intel->batch.bo, s8z24_mt->region->bo)) { + intel_batchbuffer_flush(intel); + } + drm_intel_gem_bo_map_gtt(s8_mt->region->bo); + drm_intel_gem_bo_map_gtt(s8z24_mt->region->bo); + + /* Define the invariant values outside the for loop, because I don't trust + * GCC to do it for us. + */ + uint8_t *s8_map = s8_mt->region->bo->virtual + + s8_slice->x_offset + + s8_slice->y_offset; + + uint8_t *s8z24_map = s8z24_mt->region->bo->virtual + + s8z24_slice->x_offset + + s8z24_slice->y_offset; + + ptrdiff_t s8z24_stride = s8z24_mt->region->pitch * s8z24_mt->region->cpp; + + uint32_t w = s8_level->width; + uint32_t h = s8_level->height; + + for (uint32_t y = 0; y < h; ++y) { + for (uint32_t x = 0; x < w; ++x) { + ptrdiff_t s8_offset = intel_offset_S8(s8_mt->region->pitch, x, y); + ptrdiff_t s8z24_offset = y * s8z24_stride + + x * 4 + + 3; + if (scatter) { + s8_map[s8_offset] = s8z24_map[s8z24_offset]; + } else { + s8z24_map[s8z24_offset] = s8_map[s8_offset]; + } + } + } + + drm_intel_gem_bo_unmap_gtt(s8_mt->region->bo); + drm_intel_gem_bo_unmap_gtt(s8z24_mt->region->bo); +} + +void +intel_miptree_s8z24_scatter(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer) +{ + intel_miptree_s8z24_scattergather(intel, mt, level, layer, true); +} + +void +intel_miptree_s8z24_gather(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer) +{ + intel_miptree_s8z24_scattergather(intel, mt, level, layer, false); +} diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index d6134f8c780..f22e6852197 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -152,6 +152,19 @@ struct intel_mipmap_tree */ struct intel_region *hiz_region; + /** + * \brief Stencil miptree for depthstencil textures. + * + * This miptree is used for depthstencil textures that require separate + * stencil. The stencil miptree's data is the golden copy of the + * parent miptree's stencil bits. When necessary, we scatter/gather the + * stencil bits between the parent miptree and the stencil miptree. + * + * \see intel_miptree_s8z24_scatter() + * \see intel_miptree_s8z24_gather() + */ + struct intel_mipmap_tree *stencil_mt; + /* These are also refcounted: */ GLuint refcount; @@ -239,6 +252,30 @@ intel_miptree_copy_teximage(struct intel_context *intel, struct intel_texture_image *intelImage, struct intel_mipmap_tree *dst_mt); +/** + * Copy the stencil data from \c mt->stencil_mt->region to \c mt->region for + * the given miptree slice. + * + * \see intel_mipmap_tree::stencil_mt + */ +void +intel_miptree_s8z24_scatter(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t slice); + +/** + * Copy the stencil data in \c mt->stencil_mt->region to \c mt->region for the + * given miptree slice. + * + * \see intel_mipmap_tree::stencil_mt + */ +void +intel_miptree_s8z24_gather(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer); + /* i915_mipmap_tree.c: */ void i915_miptree_layout(struct intel_mipmap_tree *mt); diff --git a/src/mesa/drivers/dri/intel/intel_tex.c b/src/mesa/drivers/dri/intel/intel_tex.c index 05b0748bc3c..505e617d709 100644 --- a/src/mesa/drivers/dri/intel/intel_tex.c +++ b/src/mesa/drivers/dri/intel/intel_tex.c @@ -69,11 +69,6 @@ intel_alloc_texture_image_buffer(struct gl_context *ctx, */ ctx->Driver.FreeTextureImageBuffer(ctx, image); - if (intel->must_use_separate_stencil - && image->TexFormat == MESA_FORMAT_S8_Z24) { - intel_tex_image_s8z24_create_renderbuffers(intel, intel_image); - } - /* Allocate the swrast_texture_image::ImageOffsets array now */ switch (texobj->Target) { case GL_TEXTURE_3D: @@ -107,11 +102,6 @@ intel_alloc_texture_image_buffer(struct gl_context *ctx, */ intel_miptree_reference(&intel_texobj->mt, intel_image->mt); - if (intel->must_use_separate_stencil - && image->TexFormat == MESA_FORMAT_S8_Z24) { - intel_tex_image_s8z24_create_renderbuffers(intel, intel_image); - } - DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n", __FUNCTION__, texobj, image->Level, width, height, depth, intel_image->mt); @@ -139,9 +129,6 @@ intel_free_texture_image_buffer(struct gl_context * ctx, free(intelImage->base.ImageOffsets); intelImage->base.ImageOffsets = NULL; } - - _mesa_reference_renderbuffer(&intelImage->depth_rb, NULL); - _mesa_reference_renderbuffer(&intelImage->stencil_rb, NULL); } /** @@ -174,13 +161,14 @@ intel_map_texture_image(struct gl_context *ctx, assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY || h == 1); - if (intel_image->stencil_rb) { - /* - * The texture has packed depth/stencil format, but uses separate - * stencil. The texture's embedded stencil buffer contains the real - * stencil data, so copy that into the miptree. + if (mt->stencil_mt) { + /* The miptree has depthstencil format, but uses separate stencil. The + * embedded stencil miptree contains the real stencil data, so gather + * that into the depthstencil miptree. + * + * FIXME: Avoid the gather if the texture is mapped as write-only. */ - intel_tex_image_s8z24_gather(intel, intel_image); + intel_miptree_s8z24_gather(intel, mt, tex_image->Level, slice); } /* For compressed formats, the stride is the number of bytes per @@ -211,16 +199,19 @@ intel_unmap_texture_image(struct gl_context *ctx, { struct intel_context *intel = intel_context(ctx); struct intel_texture_image *intel_image = intel_texture_image(tex_image); + struct intel_mipmap_tree *mt = intel_image->mt; intel_region_unmap(intel, intel_image->mt->region); - if (intel_image->stencil_rb) { - /* - * The texture has packed depth/stencil format, but uses separate - * stencil. The texture's embedded stencil buffer contains the real - * stencil data, so copy that into the miptree. + if (mt->stencil_mt) { + /* The miptree has depthstencil format, but uses separate stencil. The + * embedded stencil miptree must contain the real stencil data after + * unmapping, so copy it from the depthstencil miptree into the stencil + * miptree. + * + * FIXME: Avoid the scatter if the texture was mapped as read-only. */ - intel_tex_image_s8z24_scatter(intel, intel_image); + intel_miptree_s8z24_scatter(intel, mt, tex_image->Level, slice); } } diff --git a/src/mesa/drivers/dri/intel/intel_tex_image.c b/src/mesa/drivers/dri/intel/intel_tex_image.c index 024490a4115..dd0c6d34c63 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_image.c +++ b/src/mesa/drivers/dri/intel/intel_tex_image.c @@ -197,134 +197,6 @@ try_pbo_upload(struct gl_context *ctx, return true; } -/** - * \param scatter Scatter if true. Gather if false. - * - * \see intel_tex_image_x8z24_scatter - * \see intel_tex_image_x8z24_gather - */ -static void -intel_tex_image_s8z24_scattergather(struct intel_context *intel, - struct intel_texture_image *intel_image, - bool scatter) -{ - struct gl_context *ctx = &intel->ctx; - struct gl_renderbuffer *depth_rb = intel_image->depth_rb; - struct gl_renderbuffer *stencil_rb = intel_image->stencil_rb; - int w, h, d; - - intel_miptree_get_dimensions_for_image(&intel_image->base.Base, &w, &h, &d); - assert(d == 1); /* FINISHME */ - - uint32_t depth_row[w]; - uint8_t stencil_row[w]; - - intel_renderbuffer_map(intel, depth_rb); - intel_renderbuffer_map(intel, stencil_rb); - - if (scatter) { - for (int y = 0; y < h; ++y) { - depth_rb->GetRow(ctx, depth_rb, w, 0, y, depth_row); - for (int x = 0; x < w; ++x) { - stencil_row[x] = depth_row[x] >> 24; - } - stencil_rb->PutRow(ctx, stencil_rb, w, 0, y, stencil_row, NULL); - } - } else { /* gather */ - for (int y = 0; y < h; ++y) { - depth_rb->GetRow(ctx, depth_rb, w, 0, y, depth_row); - stencil_rb->GetRow(ctx, stencil_rb, w, 0, y, stencil_row); - for (int x = 0; x < w; ++x) { - uint32_t s8_x24 = stencil_row[x] << 24; - uint32_t x8_z24 = depth_row[x] & 0x00ffffff; - depth_row[x] = s8_x24 | x8_z24; - } - depth_rb->PutRow(ctx, depth_rb, w, 0, y, depth_row, NULL); - } - } - - intel_renderbuffer_unmap(intel, depth_rb); - intel_renderbuffer_unmap(intel, stencil_rb); -} - -/** - * Copy the x8 bits from intel_image->depth_rb to intel_image->stencil_rb. - */ -void -intel_tex_image_s8z24_scatter(struct intel_context *intel, - struct intel_texture_image *intel_image) -{ - intel_tex_image_s8z24_scattergather(intel, intel_image, true); -} - -/** - * Copy the data in intel_image->stencil_rb to the x8 bits in - * intel_image->depth_rb. - */ -void -intel_tex_image_s8z24_gather(struct intel_context *intel, - struct intel_texture_image *intel_image) -{ - intel_tex_image_s8z24_scattergather(intel, intel_image, false); -} - -bool -intel_tex_image_s8z24_create_renderbuffers(struct intel_context *intel, - struct intel_texture_image *image) -{ - struct gl_context *ctx = &intel->ctx; - bool ok = true; - int width, height, depth; - struct gl_renderbuffer *drb; - struct gl_renderbuffer *srb; - struct intel_renderbuffer *idrb; - struct intel_renderbuffer *isrb; - - intel_miptree_get_dimensions_for_image(&image->base.Base, - &width, &height, &depth); - assert(depth == 1); /* FINISHME */ - - assert(intel->has_separate_stencil); - assert(image->base.Base.TexFormat == MESA_FORMAT_S8_Z24); - assert(image->mt != NULL); - - drb = intel_create_wrapped_renderbuffer(ctx, width, height, - MESA_FORMAT_X8_Z24); - srb = intel_create_wrapped_renderbuffer(ctx, width, height, - MESA_FORMAT_S8); - - if (!drb || !srb) { - if (drb) { - drb->Delete(drb); - } - if (srb) { - srb->Delete(srb); - } - return false; - } - - idrb = intel_renderbuffer(drb); - isrb = intel_renderbuffer(srb); - - intel_miptree_reference(&idrb->mt, image->mt); - ok = intel_alloc_renderbuffer_storage(ctx, srb, GL_STENCIL_INDEX8, - width, height); - - if (!ok) { - drb->Delete(drb); - srb->Delete(srb); - return false; - } - - intel_renderbuffer_set_draw_offset(idrb); - intel_renderbuffer_set_draw_offset(isrb); - - _mesa_reference_renderbuffer(&image->depth_rb, drb); - _mesa_reference_renderbuffer(&image->stencil_rb, srb); - - return true; -} - static void intelTexImage(struct gl_context * ctx, GLint dims, diff --git a/src/mesa/drivers/dri/intel/intel_tex_obj.h b/src/mesa/drivers/dri/intel/intel_tex_obj.h index 06904e4869b..8b278ba9875 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_obj.h +++ b/src/mesa/drivers/dri/intel/intel_tex_obj.h @@ -66,36 +66,6 @@ struct intel_texture_image */ struct intel_mipmap_tree *mt; bool used_as_render_target; - - /** - * \name Renderbuffers for faking packed depth/stencil - * - * These renderbuffers are non-null only if the intel_context is using - * separate stencil and this texture has a packed depth/stencil format. When - * glFramebufferTexture is called on this image, the resultant renderbuffer - * wrapper reuses these renderbuffers as its own. - * - * \see intel_wrap_texture - * \see intel_tex_image_s8z24_create_renderbuffers - * \see intel_tex_image_s8z24_scatter - * \see intel_tex_image_s8z24_gather - * - * \{ - */ - - /** - * The depth buffer has format X8_Z24. The x8 bits are undefined unless - * intel_tex_image_s8z24_gather has been immediately called. The depth - * buffer reuses the image miptree's region and hiz_region as its own. - */ - struct gl_renderbuffer *depth_rb; - - /** - * The stencil buffer has format S8 and keeps its data in its own region. - */ - struct gl_renderbuffer *stencil_rb; - - /** \} */ }; static INLINE struct intel_texture_object * From a2e44b0813e956440c451c107cf5564b56cbe98e Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Wed, 16 Nov 2011 23:14:39 -0800 Subject: [PATCH 18/41] intel: Replace intel_mipmap_tree::hiz_region with a miptree [v2] This is required to correctly implement HiZ for mipmapped and multi-layered textures. v2: Accomodate refcount fixes in intel_process_dri2_buffer_*() that were introduced in v2 of commit intel: Replace intel_renderbuffer::region with a miptree [v2] Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i965/brw_misc_state.c | 5 ++-- src/mesa/drivers/dri/intel/intel_context.c | 23 +++++++++++-------- src/mesa/drivers/dri/intel/intel_fbo.c | 11 +++------ .../drivers/dri/intel/intel_mipmap_tree.c | 19 ++++++++++++++- .../drivers/dri/intel/intel_mipmap_tree.h | 22 ++++++++++-------- 5 files changed, 50 insertions(+), 30 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c index 4119afa4c49..17da46099ed 100644 --- a/src/mesa/drivers/dri/i965/brw_misc_state.c +++ b/src/mesa/drivers/dri/i965/brw_misc_state.c @@ -209,8 +209,9 @@ static void emit_depthbuffer(struct brw_context *brw) unsigned int len; if (depth_irb && - depth_irb->mt) { - hiz_region = depth_irb->mt->hiz_region; + depth_irb->mt && + depth_irb->mt->hiz_mt) { + hiz_region = depth_irb->mt->hiz_mt->region; } /* 3DSTATE_DEPTH_BUFFER, 3DSTATE_STENCIL_BUFFER are both diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c index 3f55c512357..9af21c8dace 100644 --- a/src/mesa/drivers/dri/intel/intel_context.c +++ b/src/mesa/drivers/dri/intel/intel_context.c @@ -1357,8 +1357,8 @@ intel_process_dri2_buffer_with_separate_stencil(struct intel_context *intel, rb->mt->region->name == buffer->name) || (buffer->attachment == __DRI_BUFFER_HIZ && rb->mt && - rb->mt->hiz_region && - rb->mt->hiz_region->name == buffer->name)) { + rb->mt->hiz_mt && + rb->mt->hiz_mt->region->name == buffer->name)) { return; } @@ -1388,10 +1388,10 @@ intel_process_dri2_buffer_with_separate_stencil(struct intel_context *intel, } /* Release the buffer storage now in case we have to return early - * due to region allocation failure. + * due to failure to allocate new storage. */ if (buffer->attachment == __DRI_BUFFER_HIZ) { - intel_region_release(&rb->mt->hiz_region); + intel_miptree_release(&rb->mt->hiz_mt); } else { intel_miptree_release(&rb->mt); } @@ -1407,15 +1407,18 @@ intel_process_dri2_buffer_with_separate_stencil(struct intel_context *intel, if (!region) return; + struct intel_mipmap_tree *mt = + intel_miptree_create_for_region(intel, + GL_TEXTURE_2D, + rb->Base.Format, + region); + intel_region_release(®ion); + /* Associate buffer with new storage. */ if (buffer->attachment == __DRI_BUFFER_HIZ) { - rb->mt->hiz_region = region; + rb->mt->hiz_mt = mt; } else { - rb->mt = intel_miptree_create_for_region(intel, - GL_TEXTURE_2D, - rb->Base.Format, - region); - intel_region_release(®ion); + rb->mt = mt; } } diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index 9aa0f98501a..94f74e00c5e 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -63,7 +63,7 @@ intel_framebuffer_has_hiz(struct gl_framebuffer *fb) struct intel_renderbuffer *rb = NULL; if (fb) rb = intel_get_renderbuffer(fb, BUFFER_DEPTH); - return rb && rb->mt && rb->mt->hiz_region; + return rb && rb->mt && rb->mt->hiz_mt; } struct intel_region* @@ -705,13 +705,8 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer return false; if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) { - irb->mt->hiz_region = intel_region_alloc(intel->intelScreen, - I915_TILING_Y, - cpp, - rb->Width, - rb->Height, - true); - if (!irb->mt->hiz_region) { + bool ok = intel_miptree_alloc_hiz(intel, irb->mt); + if (!ok) { intel_miptree_release(&irb->mt); return false; } diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index b55e16a4554..900b260cdf9 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -261,8 +261,8 @@ intel_miptree_release(struct intel_mipmap_tree **mt) DBG("%s deleting %p\n", __FUNCTION__, *mt); intel_region_release(&((*mt)->region)); - intel_region_release(&((*mt)->hiz_region)); intel_miptree_release(&(*mt)->stencil_mt); + intel_miptree_release(&(*mt)->hiz_mt); for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { free((*mt)->level[i].slice); @@ -578,3 +578,20 @@ intel_miptree_s8z24_gather(struct intel_context *intel, { intel_miptree_s8z24_scattergather(intel, mt, level, layer, false); } + +bool +intel_miptree_alloc_hiz(struct intel_context *intel, + struct intel_mipmap_tree *mt) +{ + assert(mt->hiz_mt == NULL); + mt->hiz_mt = intel_miptree_create(intel, + mt->target, + MESA_FORMAT_X8_Z24, + mt->first_level, + mt->last_level, + mt->width0, + mt->height0, + mt->depth0, + true); + return mt->hiz_mt != NULL; +} diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index f22e6852197..2b20d061412 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -139,18 +139,13 @@ struct intel_mipmap_tree struct intel_region *region; /** - * This points to an auxillary hiz region if all of the following hold: - * 1. The texture has been attached to an FBO as a depthbuffer. - * 2. The texture format is hiz compatible. - * 3. The intel context supports hiz. + * \brief HiZ miptree * - * When a texture is attached to multiple FBO's, a separate renderbuffer - * wrapper is created for each attachment. This necessitates storing the - * hiz region in the texture itself instead of the renderbuffer wrapper. + * This is non-null only if HiZ is enabled for this miptree. * - * \see intel_fbo.c:intel_wrap_texture() + * \see intel_miptree_alloc_hiz() */ - struct intel_region *hiz_region; + struct intel_mipmap_tree *hiz_mt; /** * \brief Stencil miptree for depthstencil textures. @@ -276,6 +271,15 @@ intel_miptree_s8z24_gather(struct intel_context *intel, uint32_t level, uint32_t layer); +/** + * \brief Allocate the miptree's embedded HiZ miptree. + * \see intel_mipmap_tree:hiz_mt + * \return false if allocation failed + */ +bool +intel_miptree_alloc_hiz(struct intel_context *intel, + struct intel_mipmap_tree *mt); + /* i915_mipmap_tree.c: */ void i915_miptree_layout(struct intel_mipmap_tree *mt); From c0151839473c83a2d0eea6285a649c1674466752 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Wed, 16 Nov 2011 23:10:48 -0800 Subject: [PATCH 19/41] intel: Remove unused HiZ functions Remove the following functions: i830_hiz_resolve_noop i915_hiz_resolve_noop brw_hiz_resolve_noop My original strategy for how intel->vtbl.resolve_*buffer was used has substantially changed. The above functions are no longer called in the current strategy. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i915/i830_vtbl.c | 9 --------- src/mesa/drivers/dri/i915/i915_vtbl.c | 9 --------- src/mesa/drivers/dri/i965/brw_vtbl.c | 9 --------- 3 files changed, 27 deletions(-) diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c index 86c805148cd..d29f9799a86 100644 --- a/src/mesa/drivers/dri/i915/i830_vtbl.c +++ b/src/mesa/drivers/dri/i915/i830_vtbl.c @@ -885,13 +885,6 @@ i830_is_hiz_depth_format(struct intel_context *intel, gl_format format) return false; } -static void -i830_hiz_resolve_noop(struct intel_context *intel, - struct intel_region *region) -{ - /* empty */ -} - void i830InitVtbl(struct i830_context *i830) { @@ -910,6 +903,4 @@ i830InitVtbl(struct i830_context *i830) i830->intel.vtbl.invalidate_state = i830_invalidate_state; i830->intel.vtbl.render_target_supported = i830_render_target_supported; i830->intel.vtbl.is_hiz_depth_format = i830_is_hiz_depth_format; - i830->intel.vtbl.hiz_resolve_depthbuffer = i830_hiz_resolve_noop; - i830->intel.vtbl.hiz_resolve_hizbuffer = i830_hiz_resolve_noop; } diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c index fa02dfa3654..072a692767a 100644 --- a/src/mesa/drivers/dri/i915/i915_vtbl.c +++ b/src/mesa/drivers/dri/i915/i915_vtbl.c @@ -852,13 +852,6 @@ i915_is_hiz_depth_format(struct intel_context *intel, return false; } -static void -i915_hiz_resolve_noop(struct intel_context *intel, - struct intel_region *region) -{ - /* empty */ -} - static void i915_invalidate_state(struct intel_context *intel, GLuint new_state) { @@ -887,6 +880,4 @@ i915InitVtbl(struct i915_context *i915) i915->intel.vtbl.invalidate_state = i915_invalidate_state; i915->intel.vtbl.render_target_supported = i915_render_target_supported; i915->intel.vtbl.is_hiz_depth_format = i915_is_hiz_depth_format; - i915->intel.vtbl.hiz_resolve_depthbuffer = i915_hiz_resolve_noop; - i915->intel.vtbl.hiz_resolve_hizbuffer = i915_hiz_resolve_noop; } diff --git a/src/mesa/drivers/dri/i965/brw_vtbl.c b/src/mesa/drivers/dri/i965/brw_vtbl.c index 9302b276347..75e8b2645b6 100644 --- a/src/mesa/drivers/dri/i965/brw_vtbl.c +++ b/src/mesa/drivers/dri/i965/brw_vtbl.c @@ -218,12 +218,6 @@ static bool brw_is_hiz_depth_format(struct intel_context *intel, return intel->has_hiz && (format == MESA_FORMAT_X8_Z24); } -static void brw_hiz_resolve_noop(struct intel_context *intel, - struct intel_region *depth_region) -{ - /* empty */ -} - void brwInitVtbl( struct brw_context *brw ) { brw->intel.vtbl.check_vertex_size = 0; @@ -244,9 +238,6 @@ void brwInitVtbl( struct brw_context *brw ) if (brw->intel.has_hiz) { brw->intel.vtbl.hiz_resolve_hizbuffer = gen6_hiz_resolve_hizbuffer; brw->intel.vtbl.hiz_resolve_depthbuffer = gen6_hiz_resolve_depthbuffer; - } else { - brw->intel.vtbl.hiz_resolve_hizbuffer = brw_hiz_resolve_noop; - brw->intel.vtbl.hiz_resolve_depthbuffer = brw_hiz_resolve_noop; } if (brw->intel.gen >= 7) { From f17b12278dcc0e370d04a2a9a73677ab4c9f2c26 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Wed, 16 Nov 2011 23:23:30 -0800 Subject: [PATCH 20/41] intel: Change signature of HiZ resolve functions Now that intel_renderbuffer::region has been replaced with a miptree, the HiZ functions region parameter must be replaced with a miptree parameter. Change the return type from bool to void. Rename the 'depth' parameter to 'layer', because it will correspond to irb->mt_layer. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i965/brw_vtbl.c | 4 ++-- src/mesa/drivers/dri/i965/gen6_hiz.c | 18 ++++++++++-------- src/mesa/drivers/dri/i965/gen6_hiz.h | 16 +++++++++++----- src/mesa/drivers/dri/intel/intel_context.h | 13 +++++++++---- 4 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_vtbl.c b/src/mesa/drivers/dri/i965/brw_vtbl.c index 75e8b2645b6..dd2e05a3669 100644 --- a/src/mesa/drivers/dri/i965/brw_vtbl.c +++ b/src/mesa/drivers/dri/i965/brw_vtbl.c @@ -236,8 +236,8 @@ void brwInitVtbl( struct brw_context *brw ) brw->intel.vtbl.is_hiz_depth_format = brw_is_hiz_depth_format; if (brw->intel.has_hiz) { - brw->intel.vtbl.hiz_resolve_hizbuffer = gen6_hiz_resolve_hizbuffer; - brw->intel.vtbl.hiz_resolve_depthbuffer = gen6_hiz_resolve_depthbuffer; + brw->intel.vtbl.resolve_depth_slice = gen6_resolve_depth_slice; + brw->intel.vtbl.resolve_hiz_slice = gen6_resolve_hiz_slice; } if (brw->intel.gen >= 7) { diff --git a/src/mesa/drivers/dri/i965/gen6_hiz.c b/src/mesa/drivers/dri/i965/gen6_hiz.c index fc6344b0aa9..5bb56a78348 100644 --- a/src/mesa/drivers/dri/i965/gen6_hiz.c +++ b/src/mesa/drivers/dri/i965/gen6_hiz.c @@ -23,18 +23,20 @@ #include "gen6_hiz.h" -#include - void -gen6_hiz_resolve_depthbuffer(struct intel_context *intel, - struct intel_region *depth_region) +gen6_resolve_hiz_slice(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer) { - assert("!stub"); + /* FINISHME: stub */ } void -gen6_hiz_resolve_hizbuffer(struct intel_context *intel, - struct intel_region *depth_region) +gen6_resolve_depth_slice(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer) { - assert("!stub"); + /* FINISHME: stub */ } diff --git a/src/mesa/drivers/dri/i965/gen6_hiz.h b/src/mesa/drivers/dri/i965/gen6_hiz.h index 4611182b980..49290123ff0 100644 --- a/src/mesa/drivers/dri/i965/gen6_hiz.h +++ b/src/mesa/drivers/dri/i965/gen6_hiz.h @@ -23,13 +23,19 @@ #pragma once +#include + struct intel_context; -struct intel_region; +struct intel_mipmap_tree; void -gen6_hiz_resolve_depthbuffer(struct intel_context *intel, - struct intel_region *depth_region); +gen6_resolve_hiz_slice(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer); void -gen6_hiz_resolve_hizbuffer(struct intel_context *intel, - struct intel_region *depth_region); +gen6_resolve_depth_slice(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer); diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h index f2be5973851..efaf721ae82 100644 --- a/src/mesa/drivers/dri/intel/intel_context.h +++ b/src/mesa/drivers/dri/intel/intel_context.h @@ -166,10 +166,15 @@ struct intel_context * - 7.5.3.3 Hierarchical Depth Buffer Resolve * \{ */ - void (*hiz_resolve_depthbuffer)(struct intel_context *intel, - struct intel_region *depth_region); - void (*hiz_resolve_hizbuffer)(struct intel_context *intel, - struct intel_region *depth_region); + void (*resolve_hiz_slice)(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer); + + void (*resolve_depth_slice)(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer); /** \} */ /** From 8d3aa14e893d2912c393ac1ad9e142699d561018 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Wed, 16 Nov 2011 23:43:56 -0800 Subject: [PATCH 21/41] intel: Define struct intel_resolve_map [v2] This is a map of miptree slices to needed resolves, implemented as a linked list. A future commit will embed such a list in intel_mipmap_tree. If you think I'm crazy to put a list in a miptree, read the Doxygen in this patch for intel_resolve_map. v2: [anholt] Move Doxygen from functin prototypes to definitions. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i965/Makefile.sources | 1 + src/mesa/drivers/dri/i965/intel_resolve_map.c | 1 + .../drivers/dri/intel/intel_resolve_map.c | 111 ++++++++++++++++++ .../drivers/dri/intel/intel_resolve_map.h | 83 +++++++++++++ 4 files changed, 196 insertions(+) create mode 120000 src/mesa/drivers/dri/i965/intel_resolve_map.c create mode 100644 src/mesa/drivers/dri/intel/intel_resolve_map.c create mode 100644 src/mesa/drivers/dri/intel/intel_resolve_map.h diff --git a/src/mesa/drivers/dri/i965/Makefile.sources b/src/mesa/drivers/dri/i965/Makefile.sources index 1b9ca6f2321..cd6a8f48b5a 100644 --- a/src/mesa/drivers/dri/i965/Makefile.sources +++ b/src/mesa/drivers/dri/i965/Makefile.sources @@ -15,6 +15,7 @@ i965_C_SOURCES := \ intel_fbo.c \ intel_mipmap_tree.c \ intel_regions.c \ + intel_resolve_map.c \ intel_screen.c \ intel_span.c \ intel_pixel.c \ diff --git a/src/mesa/drivers/dri/i965/intel_resolve_map.c b/src/mesa/drivers/dri/i965/intel_resolve_map.c new file mode 120000 index 00000000000..77e50fbaea4 --- /dev/null +++ b/src/mesa/drivers/dri/i965/intel_resolve_map.c @@ -0,0 +1 @@ +../intel/intel_resolve_map.c \ No newline at end of file diff --git a/src/mesa/drivers/dri/intel/intel_resolve_map.c b/src/mesa/drivers/dri/intel/intel_resolve_map.c new file mode 100644 index 00000000000..e7d82faee11 --- /dev/null +++ b/src/mesa/drivers/dri/intel/intel_resolve_map.c @@ -0,0 +1,111 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include "intel_resolve_map.h" + +#include +#include + +/** + * \brief Set that the miptree slice at (level, layer) needs a resolve. + * + * \pre If a map element already exists with the given key, then + * the new and existing element value must be identical. + */ +void +intel_resolve_map_set(struct intel_resolve_map *head, + uint32_t level, + uint32_t layer, + enum intel_need_resolve need) +{ + struct intel_resolve_map **tail = &head->next; + struct intel_resolve_map *prev = head; + + while (*tail) { + if ((*tail)->level == level && (*tail)->layer == layer) { + assert((*tail)->need == need); + return; + } + prev = *tail; + tail = &(*tail)->next; + } + + *tail = malloc(sizeof(**tail)); + (*tail)->prev = prev; + (*tail)->next = NULL; + (*tail)->level = level; + (*tail)->layer = layer; + (*tail)->need = need; +} + +/** + * \brief Get an element from the map. + * \return null if element is not contained in map. + */ +struct intel_resolve_map* +intel_resolve_map_get(struct intel_resolve_map *head, + uint32_t level, + uint32_t layer) +{ + struct intel_resolve_map *item = head->next; + + while (item) { + if (item->level == level && item->layer == layer) + break; + else + item = item->next; + } + + return item; +} + +/** + * \brief Remove and free an element from the map. + */ +void +intel_resolve_map_remove(struct intel_resolve_map *elem) +{ + if (elem->prev) + elem->prev->next = elem->next; + if (elem->next) + elem->next->prev = elem->prev; + free(elem); +} + +/** + * \brief Remove and free all elements of the map. + */ +void +intel_resolve_map_clear(struct intel_resolve_map *head) +{ + struct intel_resolve_map *next = head->next; + struct intel_resolve_map *trash; + + while (next) { + trash = next; + next = next->next; + free(trash); + } + + head->next = NULL; +} diff --git a/src/mesa/drivers/dri/intel/intel_resolve_map.h b/src/mesa/drivers/dri/intel/intel_resolve_map.h new file mode 100644 index 00000000000..1082c10e214 --- /dev/null +++ b/src/mesa/drivers/dri/intel/intel_resolve_map.h @@ -0,0 +1,83 @@ +/* + * Copyright © 2011 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#pragma once + +#include + +enum intel_need_resolve { + INTEL_NEED_HIZ_RESOLVE, + INTEL_NEED_DEPTH_RESOLVE, +}; + +/** + * \brief Map of miptree slices to needed resolves. + * + * The map is implemented as a linear doubly-linked list. + * + * In the intel_resolve_map*() functions, the \c head argument is not + * inspected for its data. It only serves as an anchor for the list. + * + * \par Design Discussion + * + * There are two possible ways to record which miptree slices need + * resolves. 1) Maintain a flag for every miptree slice in the texture, + * likely in intel_mipmap_level::slice, or 2) maintain a list of only + * those slices that need a resolve. + * + * Immediately before drawing, a full depth resolve performed on each + * enabled depth texture. If design 1 were chosen, then at each draw call + * it would be necessary to iterate over each miptree slice of each + * enabled depth texture in order to query if each slice needed a resolve. + * In the worst case, this would require 2^16 iterations: 16 texture + * units, 16 miplevels, and 256 depth layers (assuming maximums for OpenGL + * 2.1). + * + * By choosing design 2, the number of iterations is exactly the minimum + * necessary. + */ +struct intel_resolve_map { + uint32_t level; + uint32_t layer; + enum intel_need_resolve need; + + struct intel_resolve_map *next; + struct intel_resolve_map *prev; +}; + +void +intel_resolve_map_set(struct intel_resolve_map *head, + uint32_t level, + uint32_t layer, + enum intel_need_resolve need); + +struct intel_resolve_map* +intel_resolve_map_get(struct intel_resolve_map *head, + uint32_t level, + uint32_t layer); + +void +intel_resolve_map_remove(struct intel_resolve_map *elem); + +void +intel_resolve_map_clear(struct intel_resolve_map *head); From cf5e08c8e41473467a8732fc834cec52f8b10dc8 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Thu, 17 Nov 2011 07:42:21 -0800 Subject: [PATCH 22/41] intel: Add field intel_mipmap_tree::hiz_map This is a map of miptree slices to needed resolves. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_mipmap_tree.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index 2b20d061412..9531f20297c 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -31,6 +31,7 @@ #include #include "intel_regions.h" +#include "intel_resolve_map.h" /* A layer on top of the intel_regions code which adds: * @@ -58,6 +59,7 @@ * temporary system buffers. */ +struct intel_resolve_map; struct intel_texture_image; /** @@ -147,6 +149,17 @@ struct intel_mipmap_tree */ struct intel_mipmap_tree *hiz_mt; + /** + * \brief Map of miptree slices to needed resolves. + * + * This is used only when the miptree has a child HiZ miptree. + * + * Let \c mt be a depth miptree with HiZ enabled. Then the resolve map is + * \c mt->hiz_map. The resolve map of the child HiZ miptree, \c + * mt->hiz_mt->hiz_map, is unused. + */ + struct intel_resolve_map hiz_map; + /** * \brief Stencil miptree for depthstencil textures. * From 2945abea338031cbe90665df60152982bfca6177 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 18:20:02 -0800 Subject: [PATCH 23/41] intel: Add resolve functions for miptrees Add functions that - set a miptree slice as needing a resolve - resolve a single slice of a miptree - resolve all slices of a miptree Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- .../drivers/dri/intel/intel_mipmap_tree.c | 118 +++++++++++++++++- .../drivers/dri/intel/intel_mipmap_tree.h | 57 +++++++++ 2 files changed, 174 insertions(+), 1 deletion(-) diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 900b260cdf9..b4f6bb31897 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -29,6 +29,7 @@ #include "intel_context.h" #include "intel_mipmap_tree.h" #include "intel_regions.h" +#include "intel_resolve_map.h" #include "intel_span.h" #include "intel_tex_layout.h" #include "intel_tex.h" @@ -41,7 +42,6 @@ #define FILE_DEBUG_FLAG DEBUG_MIPTREE - static GLenum target_to_target(GLenum target) { @@ -263,6 +263,7 @@ intel_miptree_release(struct intel_mipmap_tree **mt) intel_region_release(&((*mt)->region)); intel_miptree_release(&(*mt)->stencil_mt); intel_miptree_release(&(*mt)->hiz_mt); + intel_resolve_map_clear(&(*mt)->hiz_map); for (i = 0; i < MAX_TEXTURE_LEVELS; i++) { free((*mt)->level[i].slice); @@ -595,3 +596,118 @@ intel_miptree_alloc_hiz(struct intel_context *intel, true); return mt->hiz_mt != NULL; } + +void +intel_miptree_slice_set_needs_hiz_resolve(struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer) +{ + intel_miptree_check_level_layer(mt, level, layer); + + if (!mt->hiz_mt) + return; + + intel_resolve_map_set(&mt->hiz_map, + level, layer, INTEL_NEED_HIZ_RESOLVE); +} + + +void +intel_miptree_slice_set_needs_depth_resolve(struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer) +{ + intel_miptree_check_level_layer(mt, level, layer); + + if (!mt->hiz_mt) + return; + + intel_resolve_map_set(&mt->hiz_map, + level, layer, INTEL_NEED_DEPTH_RESOLVE); +} + +typedef void (*resolve_func_t)(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer); + +static bool +intel_miptree_slice_resolve(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer, + enum intel_need_resolve need, + resolve_func_t func) +{ + intel_miptree_check_level_layer(mt, level, layer); + + struct intel_resolve_map *item = + intel_resolve_map_get(&mt->hiz_map, level, layer); + + if (!item || item->need != need) + return false; + + func(intel, mt, level, layer); + intel_resolve_map_remove(item); + return true; +} + +bool +intel_miptree_slice_resolve_hiz(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer) +{ + return intel_miptree_slice_resolve(intel, mt, level, layer, + INTEL_NEED_HIZ_RESOLVE, + intel->vtbl.resolve_hiz_slice); +} + +bool +intel_miptree_slice_resolve_depth(struct intel_context *intel, + struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t layer) +{ + return intel_miptree_slice_resolve(intel, mt, level, layer, + INTEL_NEED_DEPTH_RESOLVE, + intel->vtbl.resolve_depth_slice); +} + +static bool +intel_miptree_all_slices_resolve(struct intel_context *intel, + struct intel_mipmap_tree *mt, + enum intel_need_resolve need, + resolve_func_t func) +{ + bool did_resolve = false; + struct intel_resolve_map *i; + + for (i = mt->hiz_map.next; i; i = i->next) { + if (i->need != need) + continue; + func(intel, mt, i->level, i->layer); + intel_resolve_map_remove(i); + did_resolve = true; + } + + return did_resolve; +} + +bool +intel_miptree_all_slices_resolve_hiz(struct intel_context *intel, + struct intel_mipmap_tree *mt) +{ + return intel_miptree_all_slices_resolve(intel, mt, + INTEL_NEED_HIZ_RESOLVE, + intel->vtbl.resolve_hiz_slice); +} + +bool +intel_miptree_all_slices_resolve_depth(struct intel_context *intel, + struct intel_mipmap_tree *mt) +{ + return intel_miptree_all_slices_resolve(intel, mt, + INTEL_NEED_DEPTH_RESOLVE, + intel->vtbl.resolve_depth_slice); +} diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index 9531f20297c..2cecd29f33e 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -284,15 +284,72 @@ intel_miptree_s8z24_gather(struct intel_context *intel, uint32_t level, uint32_t layer); +/** + * \name Miptree HiZ functions + * \{ + * + * It is safe to call the "slice_set_need_resolve" and "slice_resolve" + * functions on a miptree without HiZ. In that case, each function is a no-op. + */ + /** * \brief Allocate the miptree's embedded HiZ miptree. * \see intel_mipmap_tree:hiz_mt * \return false if allocation failed */ + bool intel_miptree_alloc_hiz(struct intel_context *intel, struct intel_mipmap_tree *mt); +void +intel_miptree_slice_set_needs_hiz_resolve(struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t depth); +void +intel_miptree_slice_set_needs_depth_resolve(struct intel_mipmap_tree *mt, + uint32_t level, + uint32_t depth); +void +intel_miptree_all_slices_set_need_hiz_resolve(struct intel_mipmap_tree *mt); + +void +intel_miptree_all_slices_set_need_depth_resolve(struct intel_mipmap_tree *mt); + +/** + * \return false if no resolve was needed + */ +bool +intel_miptree_slice_resolve_hiz(struct intel_context *intel, + struct intel_mipmap_tree *mt, + unsigned int level, + unsigned int depth); + +/** + * \return false if no resolve was needed + */ +bool +intel_miptree_slice_resolve_depth(struct intel_context *intel, + struct intel_mipmap_tree *mt, + unsigned int level, + unsigned int depth); + +/** + * \return false if no resolve was needed + */ +bool +intel_miptree_all_slices_resolve_hiz(struct intel_context *intel, + struct intel_mipmap_tree *mt); + +/** + * \return false if no resolve was needed + */ +bool +intel_miptree_all_slices_resolve_depth(struct intel_context *intel, + struct intel_mipmap_tree *mt); + +/**\}*/ + /* i915_mipmap_tree.c: */ void i915_miptree_layout(struct intel_mipmap_tree *mt); From 1383e56bd916f9fc4357a6224aac4e8c691303cb Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Thu, 17 Nov 2011 08:03:48 -0800 Subject: [PATCH 24/41] intel: Add resolve functions for renderbuffers Add the following functions: intel_renderbuffer_resolve_hiz intel_renderbuffer_resolve_depth Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_fbo.c | 63 ++++++++++++++++++++++++++ src/mesa/drivers/dri/intel/intel_fbo.h | 31 +++++++++++++ 2 files changed, 94 insertions(+) diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index 94f74e00c5e..13486f7de83 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -1436,6 +1436,69 @@ intel_blit_framebuffer(struct gl_context *ctx, mask, filter); } +void +intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb) +{ + if (irb->mt) { + intel_miptree_slice_set_needs_hiz_resolve(irb->mt, + irb->mt_level, + irb->mt_layer); + } else if (irb->wrapped_depth) { + intel_renderbuffer_set_needs_hiz_resolve( + intel_renderbuffer(irb->wrapped_depth)); + } else { + return; + } +} + +void +intel_renderbuffer_set_needs_depth_resolve(struct intel_renderbuffer *irb) +{ + if (irb->mt) { + intel_miptree_slice_set_needs_depth_resolve(irb->mt, + irb->mt_level, + irb->mt_layer); + } else if (irb->wrapped_depth) { + intel_renderbuffer_set_needs_depth_resolve( + intel_renderbuffer(irb->wrapped_depth)); + } else { + return; + } +} + +bool +intel_renderbuffer_resolve_hiz(struct intel_context *intel, + struct intel_renderbuffer *irb) +{ + if (irb->mt) + return intel_miptree_slice_resolve_hiz(intel, + irb->mt, + irb->mt_level, + irb->mt_layer); + if (irb->wrapped_depth) + return intel_renderbuffer_resolve_hiz(intel, + intel_renderbuffer(irb->wrapped_depth)); + + return false; +} + +bool +intel_renderbuffer_resolve_depth(struct intel_context *intel, + struct intel_renderbuffer *irb) +{ + if (irb->mt) + return intel_miptree_slice_resolve_depth(intel, + irb->mt, + irb->mt_level, + irb->mt_layer); + + if (irb->wrapped_depth) + return intel_renderbuffer_resolve_depth(intel, + intel_renderbuffer(irb->wrapped_depth)); + + return false; +} + /** * Do one-time context initializations related to GL_EXT_framebuffer_object. * Hook in device driver functions. diff --git a/src/mesa/drivers/dri/intel/intel_fbo.h b/src/mesa/drivers/dri/intel/intel_fbo.h index 6da370dbd26..bb943099fd3 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.h +++ b/src/mesa/drivers/dri/intel/intel_fbo.h @@ -185,4 +185,35 @@ intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb, struct intel_region* intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex); +void +intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb); + +void +intel_renderbuffer_set_needs_depth_resolve(struct intel_renderbuffer *irb); + + +/** + * \brief Perform a HiZ resolve on the renderbuffer. + * + * It is safe to call this function on a renderbuffer without HiZ. In that + * case, the function is a no-op. + * + * \return false if no resolve was needed + */ +bool +intel_renderbuffer_resolve_hiz(struct intel_context *intel, + struct intel_renderbuffer *irb); + +/** + * \brief Perform a depth resolve on the renderbuffer. + * + * It is safe to call this function on a renderbuffer without HiZ. In that + * case, the function is a no-op. + * + * \return false if no resolve was needed + */ +bool +intel_renderbuffer_resolve_depth(struct intel_context *intel, + struct intel_renderbuffer *irb); + #endif /* INTEL_FBO_H */ From 77a18428fffc938a4e3fa9b592e3e104dda0fe7f Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 18:20:20 -0800 Subject: [PATCH 25/41] i965: Add HiZ operation state to brw_context brw_context::hiz contains state needed to perform HiZ meta-ops and indicates if a HiZ operation is currently in progress. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i965/brw_context.h | 35 +++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index e5d2d140b1e..fa2fc72e435 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -899,6 +899,41 @@ struct brw_context enum state_struct_type type; } *state_batch_list; int state_batch_count; + + /** + * \brief State needed to execute HiZ meta-ops + * + * All fields except \c op are initialized by gen6_hiz_init(). + */ + struct brw_hiz_state { + /** + * \brief Indicates which HiZ operation is in progress. + * + * See the following sections of the Sandy Bridge PRM, Volume 1, Part2: + * - 7.5.3.1 Depth Buffer Clear + * - 7.5.3.2 Depth Buffer Resolve + * - 7.5.3.3 Hierarchical Depth Buffer Resolve + */ + enum brw_hiz_op { + BRW_HIZ_OP_NONE = 0, + BRW_HIZ_OP_DEPTH_CLEAR, + BRW_HIZ_OP_DEPTH_RESOLVE, + BRW_HIZ_OP_HIZ_RESOLVE, + } op; + + /** \brief Shader state */ + struct { + GLuint program; + GLuint position_vbo; + GLint position_location; + } shader; + + /** \brief VAO for the rectangle primitive's vertices. */ + GLuint vao; + + GLuint fbo; + struct gl_renderbuffer *depth_rb; + } hiz; }; From d1f1d348d8ff6ce9249cd9971e79e5bce0e60756 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Thu, 17 Nov 2011 08:10:57 -0800 Subject: [PATCH 26/41] i965/gen6: Complete stubs for HiZ buffer resolves Some state batches also need to be manipulated. That's done in the next commit. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i965/gen6_hiz.c | 300 ++++++++++++++++++++++++++- 1 file changed, 298 insertions(+), 2 deletions(-) diff --git a/src/mesa/drivers/dri/i965/gen6_hiz.c b/src/mesa/drivers/dri/i965/gen6_hiz.c index 5bb56a78348..a71c64c3f72 100644 --- a/src/mesa/drivers/dri/i965/gen6_hiz.c +++ b/src/mesa/drivers/dri/i965/gen6_hiz.c @@ -23,20 +23,316 @@ #include "gen6_hiz.h" +#include + +#include "mesa/drivers/common/meta.h" + +#include "mesa/main/arrayobj.h" +#include "mesa/main/bufferobj.h" +#include "mesa/main/depth.h" +#include "mesa/main/enable.h" +#include "mesa/main/fbobject.h" +#include "mesa/main/framebuffer.h" +#include "mesa/main/get.h" +#include "mesa/main/renderbuffer.h" +#include "mesa/main/shaderapi.h" +#include "mesa/main/varray.h" + +#include "intel_fbo.h" +#include "intel_mipmap_tree.h" +#include "intel_regions.h" +#include "intel_tex.h" + +#include "brw_context.h" +#include "brw_defines.h" + +static const uint32_t gen6_hiz_meta_save = + + /* Disable alpha, depth, and stencil test. + * + * See the following sections of the Sandy Bridge PRM, Volume 1, Part2: + * - 7.5.3.1 Depth Buffer Clear + * - 7.5.3.2 Depth Buffer Resolve + * - 7.5.3.3 Hierarchical Depth Buffer Resolve + */ + MESA_META_ALPHA_TEST | + MESA_META_DEPTH_TEST | + MESA_META_STENCIL_TEST | + + /* Disable viewport mapping. + * + * From page 11 of the Sandy Bridge PRM, Volume 2, Part 1, Section 1.3 + * 3D Primitives Overview: + * RECTLIST: + * Viewport Mapping must be DISABLED (as is typical with the use of + * screen- space coordinates). + * + * We must also manually disable 3DSTATE_SF.Viewport_Transform_Enable. + */ + MESA_META_VIEWPORT | + + /* Disable clipping. + * + * From page 11 of the Sandy Bridge PRM, Volume 2, Part 1, Section 1.3 + * 3D Primitives Overview: + * Either the CLIP unit should be DISABLED, or the CLIP unit’s Clip + * Mode should be set to a value other than CLIPMODE_NORMAL. + */ + MESA_META_CLIP | + + /* Render a solid rectangle (set 3DSTATE_SF.FrontFace_Fill_Mode). + * + * From page 249 of the Sandy Bridge PRM, Volume 2, Part 1, Section + * 6.4.1.1 3DSTATE_SF, FrontFace_Fill_Mode: + * SOLID: Any triangle or rectangle object found to be front-facing + * is rendered as a solid object. This setting is required when + * (rendering rectangle (RECTLIST) objects. + * Also see field BackFace_Fill_Mode. + * + * Note: MESA_META_RASTERIZAION also disables culling, but that is + * irrelevant. See 3DSTATE_SF.Cull_Mode. + */ + MESA_META_RASTERIZATION | + + /* Each HiZ operation uses a vertex shader and VAO. */ + MESA_META_SHADER | + MESA_META_VERTEX | + + /* Disable scissoring. + * + * Scissoring is disabled for resolves because a resolve operation + * should resolve the entire buffer. Scissoring is disabled for depth + * clears because, if we are performing a partial depth clear, then we + * specify the clear region with the RECTLIST vertices. + */ + MESA_META_SCISSOR | + + MESA_META_SELECT_FEEDBACK; + +/** + * Initialize static data needed for HiZ operations. + */ +static void +gen6_hiz_init(struct brw_context *brw) +{ + struct gl_context *ctx = &brw->intel.ctx; + struct brw_hiz_state *hiz = &brw->hiz; + + if (hiz->fbo != 0) + return; + + /* Create depthbuffer. + * + * Until glRenderbufferStorage is called, the renderbuffer hash table + * maps the renderbuffer name to a dummy renderbuffer. We need the + * renderbuffer to be registered in the hash table so that framebuffer + * validation succeeds, so we hackishly allocate storage then immediately + * discard it. + */ + GLuint depth_rb_name; + _mesa_GenRenderbuffersEXT(1, &depth_rb_name); + _mesa_BindRenderbufferEXT(GL_RENDERBUFFER, depth_rb_name); + _mesa_RenderbufferStorageEXT(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, 32, 32); + _mesa_reference_renderbuffer(&hiz->depth_rb, + _mesa_lookup_renderbuffer(ctx, depth_rb_name)); + intel_miptree_release(&((struct intel_renderbuffer*) hiz->depth_rb)->mt); + + /* Setup FBO. */ + _mesa_GenFramebuffersEXT(1, &hiz->fbo); + _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, hiz->fbo); + _mesa_FramebufferRenderbufferEXT(GL_DRAW_FRAMEBUFFER, + GL_DEPTH_ATTACHMENT, + GL_RENDERBUFFER, + hiz->depth_rb->Name); + + /* Compile vertex shader. */ + const char *vs_source = + "attribute vec4 position;\n" + "void main()\n" + "{\n" + " gl_Position = position;\n" + "}\n"; + GLuint vs = _mesa_CreateShaderObjectARB(GL_VERTEX_SHADER); + _mesa_ShaderSourceARB(vs, 1, &vs_source, NULL); + _mesa_CompileShaderARB(vs); + + /* Compile fragment shader. */ + const char *fs_source = "void main() {}"; + GLuint fs = _mesa_CreateShaderObjectARB(GL_FRAGMENT_SHADER); + _mesa_ShaderSourceARB(fs, 1, &fs_source, NULL); + _mesa_CompileShaderARB(fs); + + /* Link and use program. */ + hiz->shader.program = _mesa_CreateProgramObjectARB(); + _mesa_AttachShader(hiz->shader.program, vs); + _mesa_AttachShader(hiz->shader.program, fs); + _mesa_LinkProgramARB(hiz->shader.program); + _mesa_UseProgramObjectARB(hiz->shader.program); + + /* Create and bind VAO. */ + _mesa_GenVertexArrays(1, &hiz->vao); + _mesa_BindVertexArray(hiz->vao); + + /* Setup VBO for 'position'. */ + hiz->shader.position_location = + _mesa_GetAttribLocationARB(hiz->shader.program, "position"); + _mesa_GenBuffersARB(1, &hiz->shader.position_vbo); + _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, hiz->shader.position_vbo); + _mesa_VertexAttribPointerARB(hiz->shader.position_location, + 2, /*components*/ + GL_FLOAT, + GL_FALSE, /*normalized?*/ + 0, /*stride*/ + NULL); + _mesa_EnableVertexAttribArrayARB(hiz->shader.position_location); + + /* Cleanup. */ + _mesa_DeleteShader(vs); + _mesa_DeleteShader(fs); +} + +/** + * Wrap \c brw->hiz.depth_rb around a miptree. + * + * \see gen6_hiz_teardown_depth_buffer() + */ +static void +gen6_hiz_setup_depth_buffer(struct brw_context *brw, + struct intel_mipmap_tree *mt, + unsigned int level, + unsigned int layer) +{ + struct gl_renderbuffer *rb = brw->hiz.depth_rb; + struct intel_renderbuffer *irb = intel_renderbuffer(rb); + + rb->Format = mt->format; + rb->_BaseFormat = _mesa_get_format_base_format(rb->Format); + rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format); + rb->InternalFormat = rb->_BaseFormat; + rb->Width = mt->level[level].width; + rb->Height = mt->level[level].height; + + irb->mt_level = level; + irb->mt_layer = layer; + + intel_miptree_reference(&irb->mt, mt); + intel_renderbuffer_set_draw_offset(irb); +} + +/** + * Release the region from \c brw->hiz.depth_rb. + * + * \see gen6_hiz_setup_depth_buffer() + */ +static void +gen6_hiz_teardown_depth_buffer(struct gl_renderbuffer *rb) +{ + struct intel_renderbuffer *irb = intel_renderbuffer(rb); + intel_miptree_release(&irb->mt); +} + +static void +gen6_resolve_slice(struct intel_context *intel, + struct intel_mipmap_tree *mt, + unsigned int level, + unsigned int layer, + enum brw_hiz_op op) +{ + struct gl_context *ctx = &intel->ctx; + struct brw_context *brw = brw_context(ctx); + struct brw_hiz_state *hiz = &brw->hiz; + + /* Do not recurse. */ + assert(!brw->hiz.op); + + assert(mt->hiz_mt != NULL); + assert(level >= mt->first_level); + assert(level <= mt->last_level); + assert(layer < mt->level[level].depth); + + /* Save state. */ + GLint save_drawbuffer; + GLint save_renderbuffer; + _mesa_meta_begin(ctx, gen6_hiz_meta_save); + _mesa_GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &save_drawbuffer); + _mesa_GetIntegerv(GL_RENDERBUFFER_BINDING, &save_renderbuffer); + + /* Initialize context data for HiZ operations. */ + gen6_hiz_init(brw); + + /* Set depth state. */ + if (!ctx->Depth.Mask) { + /* This sets 3DSTATE_WM.Depth_Buffer_Write_Enable. */ + _mesa_DepthMask(GL_TRUE); + } + if (op == BRW_HIZ_OP_DEPTH_RESOLVE) { + _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE); + _mesa_DepthFunc(GL_NEVER); + } + + /* Setup FBO. */ + gen6_hiz_setup_depth_buffer(brw, mt, level, layer); + _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, hiz->fbo); + + + /* A rectangle primitive (3DPRIM_RECTLIST) consists of only three vertices. + * The vertices reside in screen space with DirectX coordinates (this is, + * (0, 0) is the upper left corner). + * + * v2 ------ implied + * | | + * | | + * v0 ----- v1 + */ + const int width = hiz->depth_rb->Width; + const int height = hiz->depth_rb->Height; + const GLfloat positions[] = { + 0, height, + width, height, + 0, 0, + }; + + /* Setup program and vertex attributes. */ + _mesa_UseProgramObjectARB(hiz->shader.program); + _mesa_BindVertexArray(hiz->vao); + _mesa_BindBufferARB(GL_ARRAY_BUFFER, hiz->shader.position_vbo); + _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(positions), positions, + GL_DYNAMIC_DRAW_ARB); + + /* Execute the HiZ operation. */ + brw->hiz.op = op; + _mesa_DrawArrays(GL_TRIANGLES, 0, 3); + brw->hiz.op = BRW_HIZ_OP_NONE; + + /* Restore state. + * + * The order in which state is restored is significant. The draw buffer + * used for the HiZ op has no stencil buffer, and glStencilFunc() clamps + * the stencil reference value to the range allowed by the draw buffer's + * number of stencil bits. So, the draw buffer binding must be restored + * before the stencil state, or else the stencil ref will be clamped to 0. + */ + gen6_hiz_teardown_depth_buffer(hiz->depth_rb); + _mesa_BindRenderbufferEXT(GL_RENDERBUFFER, save_renderbuffer); + _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, save_drawbuffer); + _mesa_meta_end(ctx); +} + void gen6_resolve_hiz_slice(struct intel_context *intel, struct intel_mipmap_tree *mt, uint32_t level, uint32_t layer) { - /* FINISHME: stub */ + gen6_resolve_slice(intel, mt, level, layer, BRW_HIZ_OP_HIZ_RESOLVE); } + void gen6_resolve_depth_slice(struct intel_context *intel, struct intel_mipmap_tree *mt, uint32_t level, uint32_t layer) { - /* FINISHME: stub */ + gen6_resolve_slice(intel, mt, level, layer, BRW_HIZ_OP_DEPTH_RESOLVE); } From 12498553462c7807034814cf843d86d52c407380 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 18:20:31 -0800 Subject: [PATCH 27/41] i965/gen6: Manipulate state batches for HiZ meta-ops [v4] A lot of the state manipulation is handled by the meta-op state setup. However, some batches need manual intervention. v2: Do not special-case the 3DSTATE_DEPTH_STENCIL.Depth_Test_Enable bit for HiZ in gen6_upload_depth_stencil(). The HiZ meta-op sets ctx->Depth.Test, just read the value from that. v3: Add a new dirty flag, BRW_STATE_HIZ, for brw_tracked_state. Flag it immediately before and after executing the HiZ operation in gen6_resolve_slice(). Add the flag to the the dirty bits for the following state packets: gen6_clip_state gen6_depth_stencil_state gen6_sf_state gen6_wm_state v4: - Add BRW_NEW_STATE_HIZ to the dirty bit table in brw_state_upload.c. This is needed for INTEL_DEBUG=state. - Align brw dirty bit for gen6_depth_stencil_state. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i965/brw_context.h | 2 ++ src/mesa/drivers/dri/i965/brw_draw.c | 9 ++++++++- src/mesa/drivers/dri/i965/brw_state_upload.c | 1 + src/mesa/drivers/dri/i965/gen6_clip_state.c | 20 ++++++++++++++++++- src/mesa/drivers/dri/i965/gen6_depthstencil.c | 11 +++++++--- src/mesa/drivers/dri/i965/gen6_hiz.c | 2 ++ src/mesa/drivers/dri/i965/gen6_sf_state.c | 18 ++++++++++++++--- src/mesa/drivers/dri/i965/gen6_wm_state.c | 20 ++++++++++++++++++- 8 files changed, 74 insertions(+), 9 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index fa2fc72e435..ec05fb75869 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -144,6 +144,7 @@ enum brw_state_id { BRW_STATE_VS_CONSTBUF, BRW_STATE_PROGRAM_CACHE, BRW_STATE_STATE_BASE_ADDRESS, + BRW_STATE_HIZ, }; #define BRW_NEW_URB_FENCE (1 << BRW_STATE_URB_FENCE) @@ -172,6 +173,7 @@ enum brw_state_id { #define BRW_NEW_VS_CONSTBUF (1 << BRW_STATE_VS_CONSTBUF) #define BRW_NEW_PROGRAM_CACHE (1 << BRW_STATE_PROGRAM_CACHE) #define BRW_NEW_STATE_BASE_ADDRESS (1 << BRW_STATE_STATE_BASE_ADDRESS) +#define BRW_NEW_HIZ (1 << BRW_STATE_HIZ) struct brw_state_flags { /** State update flags signalled by mesa internals */ diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index 1571fb74d6c..d2ae0877e8d 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -117,10 +117,17 @@ static void brw_set_prim(struct brw_context *brw, static void gen6_set_prim(struct brw_context *brw, const struct _mesa_prim *prim) { - uint32_t hw_prim = prim_to_hw_prim[prim->mode]; + uint32_t hw_prim; DBG("PRIM: %s\n", _mesa_lookup_enum_by_nr(prim->mode)); + if (brw->hiz.op) { + assert(prim->mode == GL_TRIANGLES); + hw_prim = _3DPRIM_RECTLIST; + } else { + hw_prim = prim_to_hw_prim[prim->mode]; + } + if (hw_prim != brw->primitive) { brw->primitive = hw_prim; brw->state.dirty.brw |= BRW_NEW_PRIMITIVE; diff --git a/src/mesa/drivers/dri/i965/brw_state_upload.c b/src/mesa/drivers/dri/i965/brw_state_upload.c index 730a0e8a12b..bd32815d08c 100644 --- a/src/mesa/drivers/dri/i965/brw_state_upload.c +++ b/src/mesa/drivers/dri/i965/brw_state_upload.c @@ -368,6 +368,7 @@ static struct dirty_bit_map brw_bits[] = { DEFINE_BIT(BRW_NEW_GS_BINDING_TABLE), DEFINE_BIT(BRW_NEW_PS_BINDING_TABLE), DEFINE_BIT(BRW_NEW_STATE_BASE_ADDRESS), + DEFINE_BIT(BRW_NEW_HIZ), {0, 0, 0} }; diff --git a/src/mesa/drivers/dri/i965/gen6_clip_state.c b/src/mesa/drivers/dri/i965/gen6_clip_state.c index b3bb8aee3ec..d2a5f755726 100644 --- a/src/mesa/drivers/dri/i965/gen6_clip_state.c +++ b/src/mesa/drivers/dri/i965/gen6_clip_state.c @@ -67,6 +67,23 @@ upload_clip_state(struct brw_context *brw) GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE; } + if (brw->hiz.op) { + /* HiZ operations emit a rectangle primitive, which requires clipping to + * be disabled. From page 10 of the Sandy Bridge PRM Volume 2 Part 1 + * Section 1.3 3D Primitives Overview: + * RECTLIST: + * Either the CLIP unit should be DISABLED, or the CLIP unit's Clip + * Mode should be set to a value other than CLIPMODE_NORMAL. + */ + BEGIN_BATCH(4); + OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2)); + OUT_BATCH(0); + OUT_BATCH(0); + OUT_BATCH(0); + ADVANCE_BATCH(); + return; + } + if (!ctx->Transform.DepthClamp) depth_clamp = GEN6_CLIP_Z_TEST; @@ -107,7 +124,8 @@ const struct brw_tracked_state gen6_clip_state = { .dirty = { .mesa = _NEW_TRANSFORM | _NEW_LIGHT, .brw = (BRW_NEW_CONTEXT | - BRW_NEW_FRAGMENT_PROGRAM), + BRW_NEW_FRAGMENT_PROGRAM | + BRW_NEW_HIZ), .cache = 0 }, .emit = upload_clip_state, diff --git a/src/mesa/drivers/dri/i965/gen6_depthstencil.c b/src/mesa/drivers/dri/i965/gen6_depthstencil.c index 72e86879b2b..eec1bf69015 100644 --- a/src/mesa/drivers/dri/i965/gen6_depthstencil.c +++ b/src/mesa/drivers/dri/i965/gen6_depthstencil.c @@ -77,8 +77,12 @@ gen6_upload_depth_stencil_state(struct brw_context *brw) } /* _NEW_DEPTH */ - if (ctx->Depth.Test) { - ds->ds2.depth_test_enable = 1; + if (ctx->Depth.Test || brw->hiz.op) { + assert(brw->hiz.op != BRW_HIZ_OP_DEPTH_RESOLVE || ctx->Depth.Test); + assert(brw->hiz.op != BRW_HIZ_OP_HIZ_RESOLVE || !ctx->Depth.Test); + assert(brw->hiz.op != BRW_HIZ_OP_DEPTH_CLEAR || !ctx->Depth.Test); + + ds->ds2.depth_test_enable = ctx->Depth.Test; ds->ds2.depth_test_func = intel_translate_compare_func(ctx->Depth.Func); ds->ds2.depth_write_enable = ctx->Depth.Mask; } @@ -89,7 +93,8 @@ gen6_upload_depth_stencil_state(struct brw_context *brw) const struct brw_tracked_state gen6_depth_stencil_state = { .dirty = { .mesa = _NEW_DEPTH | _NEW_STENCIL, - .brw = BRW_NEW_BATCH, + .brw = (BRW_NEW_BATCH | + BRW_NEW_HIZ), .cache = 0, }, .emit = gen6_upload_depth_stencil_state, diff --git a/src/mesa/drivers/dri/i965/gen6_hiz.c b/src/mesa/drivers/dri/i965/gen6_hiz.c index a71c64c3f72..e28251182c9 100644 --- a/src/mesa/drivers/dri/i965/gen6_hiz.c +++ b/src/mesa/drivers/dri/i965/gen6_hiz.c @@ -301,7 +301,9 @@ gen6_resolve_slice(struct intel_context *intel, /* Execute the HiZ operation. */ brw->hiz.op = op; + brw->state.dirty.brw |= BRW_NEW_HIZ; _mesa_DrawArrays(GL_TRIANGLES, 0, 3); + brw->state.dirty.brw |= BRW_NEW_HIZ; brw->hiz.op = BRW_HIZ_OP_NONE; /* Restore state. diff --git a/src/mesa/drivers/dri/i965/gen6_sf_state.c b/src/mesa/drivers/dri/i965/gen6_sf_state.c index 67119d8d182..4c4ff308054 100644 --- a/src/mesa/drivers/dri/i965/gen6_sf_state.c +++ b/src/mesa/drivers/dri/i965/gen6_sf_state.c @@ -147,8 +147,19 @@ upload_sf_state(struct brw_context *brw) num_outputs << GEN6_SF_NUM_OUTPUTS_SHIFT | urb_entry_read_length << GEN6_SF_URB_ENTRY_READ_LENGTH_SHIFT | urb_entry_read_offset << GEN6_SF_URB_ENTRY_READ_OFFSET_SHIFT; - dw2 = GEN6_SF_VIEWPORT_TRANSFORM_ENABLE | - GEN6_SF_STATISTICS_ENABLE; + + dw2 = GEN6_SF_STATISTICS_ENABLE; + + /* Enable viewport transform only if no HiZ operation is progress + * + * From page 11 of the SandyBridge PRM, Volume 2, Part 1, Section 1.3, "3D + * Primitives Overview": + * RECTLIST: Viewport Mapping must be DISABLED (as is typical with the + * use of screen- space coordinates). + */ + if (!brw->hiz.op) + dw2 |= GEN6_SF_VIEWPORT_TRANSFORM_ENABLE; + dw3 = 0; dw4 = 0; dw16 = 0; @@ -334,7 +345,8 @@ const struct brw_tracked_state gen6_sf_state = { _NEW_POINT | _NEW_TRANSFORM), .brw = (BRW_NEW_CONTEXT | - BRW_NEW_FRAGMENT_PROGRAM), + BRW_NEW_FRAGMENT_PROGRAM | + BRW_NEW_HIZ), .cache = CACHE_NEW_VS_PROG }, .emit = upload_sf_state, diff --git a/src/mesa/drivers/dri/i965/gen6_wm_state.c b/src/mesa/drivers/dri/i965/gen6_wm_state.c index 271a9aeca78..070220a5077 100644 --- a/src/mesa/drivers/dri/i965/gen6_wm_state.c +++ b/src/mesa/drivers/dri/i965/gen6_wm_state.c @@ -147,6 +147,23 @@ upload_wm_state(struct brw_context *brw) dw4 |= (brw->wm.prog_data->first_curbe_grf_16 << GEN6_WM_DISPATCH_START_GRF_SHIFT_2); + switch (brw->hiz.op) { + case BRW_HIZ_OP_NONE: + break; + case BRW_HIZ_OP_DEPTH_CLEAR: + dw4 |= GEN6_WM_DEPTH_CLEAR; + break; + case BRW_HIZ_OP_DEPTH_RESOLVE: + dw4 |= GEN6_WM_DEPTH_RESOLVE; + break; + case BRW_HIZ_OP_HIZ_RESOLVE: + dw4 |= GEN6_WM_HIERARCHICAL_DEPTH_RESOLVE; + break; + default: + assert(0); + break; + } + dw5 |= (brw->max_wm_threads - 1) << GEN6_WM_MAX_THREADS_SHIFT; /* CACHE_NEW_WM_PROG */ @@ -215,7 +232,8 @@ const struct brw_tracked_state gen6_wm_state = { _NEW_POLYGON), .brw = (BRW_NEW_FRAGMENT_PROGRAM | BRW_NEW_URB_FENCE | - BRW_NEW_BATCH), + BRW_NEW_BATCH | + BRW_NEW_HIZ), .cache = (CACHE_NEW_SAMPLER | CACHE_NEW_WM_PROG) }, From b95986729ef3522a65b7357aea99c6358f9d53c8 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 18:20:34 -0800 Subject: [PATCH 28/41] i965: Prevent recursive calls to FLUSH_VERTICES [v2] To do so, we must resolve all buffers on entering a glBegin/glEnd block. For the detailed explanation, see the Doxygen comments in this patch. v2: - Fix typo: s/enusure/ensure/. - In brwPrepareExecBegin(), do the same resolves as done by brw_predraw_resolve_buffers(). Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i965/brw_context.c | 66 +++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c index 9b506a6529f..531ce5bd0d8 100644 --- a/src/mesa/drivers/dri/i965/brw_context.c +++ b/src/mesa/drivers/dri/i965/brw_context.c @@ -33,11 +33,23 @@ #include "main/imports.h" #include "main/macros.h" #include "main/simple_list.h" + +#include "vbo/vbo_context.h" + #include "brw_context.h" #include "brw_defines.h" #include "brw_draw.h" #include "brw_state.h" + +#include "gen6_hiz.h" + +#include "intel_fbo.h" +#include "intel_mipmap_tree.h" +#include "intel_regions.h" #include "intel_span.h" +#include "intel_tex.h" +#include "intel_tex_obj.h" + #include "tnl/t_pipeline.h" #include "glsl/ralloc.h" @@ -45,12 +57,66 @@ * Mesa's Driver Functions ***************************************/ +/** + * \brief Prepare for entry into glBegin/glEnd block. + * + * Resolve buffers before entering a glBegin/glEnd block. This is + * necessary to prevent recursive calls to FLUSH_VERTICES. + * + * This resolves the depth buffer of each enabled depth texture and the HiZ + * buffer of the attached depth renderbuffer. + * + * Details + * ------- + * When vertices are queued during a glBegin/glEnd block, those vertices must + * be drawn before any rendering state changes. To ensure this, Mesa calls + * FLUSH_VERTICES as a prehook to such state changes. Therefore, + * FLUSH_VERTICES itself cannot change rendering state without falling into a + * recursive trap. + * + * This precludes meta-ops, namely buffer resolves, from occurring while any + * vertices are queued. To prevent that situation, we resolve some buffers on + * entering a glBegin/glEnd + * + * \see brwCleanupExecEnd() + */ +static void brwPrepareExecBegin(struct gl_context *ctx) +{ + struct brw_context *brw = brw_context(ctx); + struct intel_context *intel = &brw->intel; + struct intel_renderbuffer *draw_irb; + struct intel_texture_object *tex_obj; + + if (!intel->has_hiz) { + /* The context uses no feature that requires buffer resolves. */ + return; + } + + /* Resolve each enabled texture. */ + for (int i = 0; i < ctx->Const.MaxTextureImageUnits; i++) { + if (!ctx->Texture.Unit[i]._ReallyEnabled) + continue; + tex_obj = intel_texture_object(ctx->Texture.Unit[i]._Current); + if (!tex_obj || !tex_obj->mt) + continue; + intel_miptree_all_slices_resolve_depth(intel, tex_obj->mt); + } + + /* Resolve the attached depth buffer. */ + draw_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH); + if (draw_irb) { + intel_renderbuffer_resolve_hiz(intel, draw_irb); + } +} + static void brwInitDriverFunctions( struct dd_function_table *functions ) { intelInitDriverFunctions( functions ); brwInitFragProgFuncs( functions ); brw_init_queryobj_functions(functions); + + functions->PrepareExecBegin = brwPrepareExecBegin; } bool From 3b0d295e122f8ca6e0ebe4593a1e0660308a18c3 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 18:20:39 -0800 Subject: [PATCH 29/41] i965: Resolve buffers before drawing [v2] Before emitting primitives in brw_try_draw_prims(), resolve the depth buffer's HiZ buffer and resolve the depth buffer of each enabled depth texture. v2: [anholt] The driver no longer validates drm bo's, so update a comment to reflect that. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i965/brw_draw.c | 73 ++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index d2ae0877e8d..35196a7e1a0 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -44,6 +44,9 @@ #include "brw_state.h" #include "intel_batchbuffer.h" +#include "intel_fbo.h" +#include "intel_mipmap_tree.h" +#include "intel_regions.h" #define FILE_DEBUG_FLAG DEBUG_PRIMS @@ -287,6 +290,71 @@ static void brw_merge_inputs( struct brw_context *brw, brw->state.dirty.brw |= BRW_NEW_INPUT_DIMENSIONS; } +/* + * \brief Resolve buffers before drawing. + * + * Resolve the depth buffer's HiZ buffer and resolve the depth buffer of each + * enabled depth texture. + * + * (In the future, this will also perform MSAA resolves). + */ +static void +brw_predraw_resolve_buffers(struct brw_context *brw) +{ + struct gl_context *ctx = &brw->intel.ctx; + struct intel_context *intel = &brw->intel; + struct intel_renderbuffer *depth_irb; + struct intel_texture_object *tex_obj; + bool did_resolve = false; + + /* Avoid recursive HiZ op. */ + if (brw->hiz.op) { + return; + } + + /* Resolve the depth buffer's HiZ buffer. */ + depth_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH); + if (depth_irb && depth_irb->mt) { + did_resolve |= intel_renderbuffer_resolve_hiz(intel, depth_irb); + } + + /* Resolve depth buffer of each enabled depth texture. */ + for (int i = 0; i < BRW_MAX_TEX_UNIT; i++) { + if (!ctx->Texture.Unit[i]._ReallyEnabled) + continue; + tex_obj = intel_texture_object(ctx->Texture.Unit[i]._Current); + if (!tex_obj || !tex_obj->mt) + continue; + did_resolve |= intel_miptree_all_slices_resolve_depth(intel, tex_obj->mt); + } + + if (did_resolve) { + /* Call vbo_bind_array() to synchronize the vbo module's vertex + * attributes to the gl_context's. + * + * Details + * ------- + * The vbo module tracks vertex attributes separately from the + * gl_context. Specifically, the vbo module maintins vertex attributes + * in vbo_exec_context::array::inputs, which is synchronized with + * gl_context::Array::ArrayObj::VertexAttrib by vbo_bind_array(). + * vbo_draw_arrays() calls vbo_bind_array() to perform the + * synchronization before calling the real draw call, + * vbo_context::draw_arrays. + * + * At this point (after performing a resolve meta-op but before calling + * vbo_bind_array), the gl_context's vertex attributes have been + * restored to their original state (that is, their state before the + * meta-op began), but the vbo module's vertex attribute are those used + * in the last meta-op. Therefore we must manually synchronize the two with + * vbo_bind_array() before continuing with the original draw command. + */ + _mesa_update_state(ctx); + vbo_bind_arrays(ctx); + _mesa_update_state(ctx); + } +} + /* May fail if out of video memory for texture or vbo upload, or on * fallback conditions. */ @@ -316,6 +384,11 @@ static bool brw_try_draw_prims( struct gl_context *ctx, */ brw_validate_textures( brw ); + /* Resolves must occur after updating state and finalizing textures but + * before setting up any hardware state for this draw call. + */ + brw_predraw_resolve_buffers(brw); + /* Bind all inputs, derive varying and size information: */ brw_merge_inputs( brw, arrays ); From 1eede4aa8771c058bc560123d4b7c5625e23c8b6 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 18:20:57 -0800 Subject: [PATCH 30/41] intel: Refactor intelSpanRenderStart Factor the mapping loops from intelSpanRenderStart() into intel_span_map_buffers(). This in preparation for the next commit, which resolves the buffers before mapping. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_span.c | 41 +++++++++++++++---------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_span.c b/src/mesa/drivers/dri/intel/intel_span.c index 83676b9313d..e73e804c548 100644 --- a/src/mesa/drivers/dri/intel/intel_span.c +++ b/src/mesa/drivers/dri/intel/intel_span.c @@ -253,6 +253,30 @@ intel_framebuffer_unmap(struct intel_context *intel, struct gl_framebuffer *fb) } } +/** + * Map the regions needed by intelSpanRenderStart(). + */ +static void +intel_span_map_buffers(struct intel_context *intel) +{ + struct gl_context *ctx = &intel->ctx; + struct intel_texture_object *tex_obj; + + for (int i = 0; i < ctx->Const.MaxTextureImageUnits; i++) { + if (!ctx->Texture.Unit[i]._ReallyEnabled) + continue; + tex_obj = intel_texture_object(ctx->Texture.Unit[i]._Current); + intel_finalize_mipmap_tree(intel, i); + intel_tex_map_images(intel, tex_obj, + GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); + } + + intel_framebuffer_map(intel, ctx->DrawBuffer); + if (ctx->ReadBuffer != ctx->DrawBuffer) { + intel_framebuffer_map(intel, ctx->ReadBuffer); + } +} + /** * Prepare for software rendering. Map current read/draw framebuffers' * renderbuffes and all currently bound texture objects. @@ -263,25 +287,10 @@ void intelSpanRenderStart(struct gl_context * ctx) { struct intel_context *intel = intel_context(ctx); - GLuint i; intel_flush(&intel->ctx); intel_prepare_render(intel); - - for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) { - if (ctx->Texture.Unit[i]._ReallyEnabled) { - struct gl_texture_object *texObj = ctx->Texture.Unit[i]._Current; - - intel_finalize_mipmap_tree(intel, i); - intel_tex_map_images(intel, intel_texture_object(texObj), - GL_MAP_READ_BIT | GL_MAP_WRITE_BIT); - } - } - - intel_framebuffer_map(intel, ctx->DrawBuffer); - if (ctx->ReadBuffer != ctx->DrawBuffer) { - intel_framebuffer_map(intel, ctx->ReadBuffer); - } + intel_span_map_buffers(intel); } /** From 622bae07a5da91bc966d173fd6df92a640e4f574 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 18:21:05 -0800 Subject: [PATCH 31/41] intel: Resolve buffers in intelSpanRenderStart Resolve all buffers that will be mapped by intelSpanRenderStart. This comprises resolving the depth buffer of each enabled texture and of the read and draw buffers. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_span.c | 40 ++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/mesa/drivers/dri/intel/intel_span.c b/src/mesa/drivers/dri/intel/intel_span.c index e73e804c548..042bc30da7d 100644 --- a/src/mesa/drivers/dri/intel/intel_span.c +++ b/src/mesa/drivers/dri/intel/intel_span.c @@ -253,6 +253,42 @@ intel_framebuffer_unmap(struct intel_context *intel, struct gl_framebuffer *fb) } } +/** + * Resolve all buffers that will be mapped by intelSpanRenderStart(). + * + * Resolve the depth buffer of each enabled texture and of the read and draw + * buffers. + * + * (Note: In the future this will also perform MSAA resolves.) + */ +static void +intel_span_resolve_buffers(struct intel_context *intel) +{ + struct gl_context *ctx = &intel->ctx; + struct intel_renderbuffer *draw_irb; + struct intel_renderbuffer *read_irb; + struct intel_texture_object *tex_obj; + + /* Resolve depth buffer of each enabled texture. */ + for (int i = 0; i < ctx->Const.MaxTextureImageUnits; i++) { + if (!ctx->Texture.Unit[i]._ReallyEnabled) + continue; + tex_obj = intel_texture_object(ctx->Texture.Unit[i]._Current); + intel_finalize_mipmap_tree(intel, i); + if (!tex_obj || !tex_obj->mt) + continue; + intel_miptree_all_slices_resolve_depth(intel, tex_obj->mt); + } + + /* Resolve each attached depth buffer. */ + draw_irb = intel_get_renderbuffer(ctx->DrawBuffer, BUFFER_DEPTH); + read_irb = intel_get_renderbuffer(ctx->ReadBuffer, BUFFER_DEPTH); + if (draw_irb) + intel_renderbuffer_resolve_depth(intel, draw_irb); + if (read_irb != draw_irb && read_irb) + intel_renderbuffer_resolve_depth(intel, read_irb); +} + /** * Map the regions needed by intelSpanRenderStart(). */ @@ -288,8 +324,10 @@ intelSpanRenderStart(struct gl_context * ctx) { struct intel_context *intel = intel_context(ctx); - intel_flush(&intel->ctx); + intel_flush(ctx); intel_prepare_render(intel); + intel_span_resolve_buffers(intel); + intel_flush(ctx); intel_span_map_buffers(intel); } From 1b2baf3b08d545c772e9636fb0a0614c489c3916 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 18:20:43 -0800 Subject: [PATCH 32/41] i965: Mark that depth buffer needs depth resolve after drawing After brw_try_draw_prims() emits a batch, mark that the depth buffer needs a depth resolve if the buffer was written to and if it has an accompanying HiZ buffer. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i965/brw_draw.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c index 35196a7e1a0..bf3c95cbebc 100644 --- a/src/mesa/drivers/dri/i965/brw_draw.c +++ b/src/mesa/drivers/dri/i965/brw_draw.c @@ -355,6 +355,28 @@ brw_predraw_resolve_buffers(struct brw_context *brw) } } +/** + * \brief Call this after drawing to mark which buffers need resolving + * + * If the depth buffer was written to and if it has an accompanying HiZ + * buffer, then mark that it needs a depth resolve. + * + * (In the future, this will also mark needed MSAA resolves). + */ +static void brw_postdraw_set_buffers_need_resolve(struct brw_context *brw) +{ + struct gl_context *ctx = &brw->intel.ctx; + struct gl_framebuffer *fb = ctx->DrawBuffer; + struct intel_renderbuffer *depth_irb = + intel_get_renderbuffer(fb, BUFFER_DEPTH); + + if (depth_irb && + ctx->Depth.Mask && + !brw->hiz.op) { + intel_renderbuffer_set_needs_depth_resolve(depth_irb); + } +} + /* May fail if out of video memory for texture or vbo upload, or on * fallback conditions. */ @@ -483,6 +505,7 @@ retry: out: brw_state_cache_check_size(brw); + brw_postdraw_set_buffers_need_resolve(brw); return retval; } From 3d760664e6349c72624aa6d54d40df0233995c8e Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 18:21:09 -0800 Subject: [PATCH 33/41] intel: Mark needed resolves when first enabling HiZ on a miptree Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- .../drivers/dri/intel/intel_mipmap_tree.c | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index b4f6bb31897..ffceda27029 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -594,7 +594,26 @@ intel_miptree_alloc_hiz(struct intel_context *intel, mt->height0, mt->depth0, true); - return mt->hiz_mt != NULL; + + if (!mt->hiz_mt) + return false; + + /* Mark that all slices need a HiZ resolve. */ + struct intel_resolve_map *head = &mt->hiz_map; + for (int level = mt->first_level; level <= mt->last_level; ++level) { + for (int layer = 0; layer < mt->level[level].depth; ++layer) { + head->next = malloc(sizeof(*head->next)); + head->next->prev = head; + head->next->next = NULL; + head = head->next; + + head->level = level; + head->layer = layer; + head->need = INTEL_NEED_HIZ_RESOLVE; + } + } + + return true; } void From d2e35a5460c5c4b3951c0aaca4fdb867b20478bb Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 18:21:12 -0800 Subject: [PATCH 34/41] intel: Resolve buffers in intel_map_texture_image() Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_tex.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mesa/drivers/dri/intel/intel_tex.c b/src/mesa/drivers/dri/intel/intel_tex.c index 505e617d709..9884a57d0fe 100644 --- a/src/mesa/drivers/dri/intel/intel_tex.c +++ b/src/mesa/drivers/dri/intel/intel_tex.c @@ -171,6 +171,11 @@ intel_map_texture_image(struct gl_context *ctx, intel_miptree_s8z24_gather(intel, mt, tex_image->Level, slice); } + intel_miptree_slice_resolve_depth(intel, mt, tex_image->Level, slice); + if (mode & GL_MAP_WRITE_BIT) { + intel_miptree_slice_set_needs_hiz_resolve(mt, tex_image->Level, slice); + } + /* For compressed formats, the stride is the number of bytes per * row of blocks. intel_miptree_get_image_offset() already does * the divide. From b264698d30d3c789bbe1fc64fd72c731f342877a Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 18:25:39 -0800 Subject: [PATCH 35/41] intel: Resolve buffers in intel_map_renderbuffer() Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_fbo.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index 13486f7de83..4930999cdb2 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -125,6 +125,11 @@ intel_map_renderbuffer_gtt(struct gl_context *ctx, assert(irb->mt); + intel_renderbuffer_resolve_depth(intel, irb); + if (mode & GL_MAP_WRITE_BIT) { + intel_renderbuffer_set_needs_hiz_resolve(irb); + } + irb->map_mode = mode; irb->map_x = x; irb->map_y = y; From 293e9a7ccfeb64efd54464658518e4ded054a13c Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Tue, 15 Nov 2011 22:51:35 -0800 Subject: [PATCH 36/41] intel: Enable HiZ for texture renderbuffers When a depth texture is first attached to framebuffer, allocate a HiZ miptree for it. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_fbo.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index 4930999cdb2..c96430d41bd 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -1047,6 +1047,13 @@ intel_renderbuffer_update_wrapper(struct intel_context *intel, } else { intel_miptree_reference(&irb->mt, mt); intel_renderbuffer_set_draw_offset(irb); + + if (mt->hiz_mt == NULL && + intel->vtbl.is_hiz_depth_format(intel, rb->Format)) { + intel_miptree_alloc_hiz(intel, mt); + if (!mt->hiz_mt) + return false; + } } return true; From 017c13d55b5b086774d6afea2ca754482c624c6a Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Thu, 17 Nov 2011 08:30:30 -0800 Subject: [PATCH 37/41] intel: Store miptree alignment units in the miptree This allows us to replace all the calls to intel_get_texture_alignment_unit() with a single call at miptree creation. Reviewed-by: Eric Anholt Reviewed-by: Kenneth Graunke Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i965/brw_tex_layout.c | 26 ++++++------------- .../drivers/dri/intel/intel_mipmap_tree.c | 9 +++---- .../drivers/dri/intel/intel_mipmap_tree.h | 7 +++++ src/mesa/drivers/dri/intel/intel_tex_layout.c | 16 +++++------- 4 files changed, 26 insertions(+), 32 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_tex_layout.c b/src/mesa/drivers/dri/i965/brw_tex_layout.c index ac6ade60959..eaea49bf55f 100644 --- a/src/mesa/drivers/dri/i965/brw_tex_layout.c +++ b/src/mesa/drivers/dri/i965/brw_tex_layout.c @@ -43,17 +43,13 @@ static void brw_miptree_layout_texture_array(struct intel_context *intel, struct intel_mipmap_tree *mt) { - GLuint align_w; - GLuint align_h; GLuint level; GLuint qpitch = 0; int h0, h1, q; - intel_get_texture_alignment_unit(mt->format, &align_w, &align_h); - - h0 = ALIGN(mt->height0, align_h); - h1 = ALIGN(minify(mt->height0), align_h); - qpitch = (h0 + h1 + (intel->gen >= 7 ? 12 : 11) * align_h); + h0 = ALIGN(mt->height0, mt->align_h); + h1 = ALIGN(minify(mt->height0), mt->align_h); + qpitch = (h0 + h1 + (intel->gen >= 7 ? 12 : 11) * mt->align_h); if (mt->compressed) qpitch /= 4; @@ -70,9 +66,6 @@ brw_miptree_layout_texture_array(struct intel_context *intel, void brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt) { - /* XXX: these vary depending on image format: */ - /* GLint align_w = 4; */ - switch (mt->target) { case GL_TEXTURE_CUBE_MAP: if (intel->gen >= 5) { @@ -93,18 +86,15 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt) GLuint pack_x_pitch, pack_x_nr; GLuint pack_y_pitch; GLuint level; - GLuint align_h = 2; - GLuint align_w = 4; mt->total_height = 0; - intel_get_texture_alignment_unit(mt->format, &align_w, &align_h); if (mt->compressed) { - mt->total_width = ALIGN(width, align_w); + mt->total_width = ALIGN(width, mt->align_w); pack_y_pitch = (height + 3) / 4; } else { mt->total_width = mt->width0; - pack_y_pitch = ALIGN(mt->height0, align_h); + pack_y_pitch = ALIGN(mt->height0, mt->align_h); } pack_x_pitch = width; @@ -139,8 +129,8 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt) if (mt->compressed) { pack_y_pitch = (height + 3) / 4; - if (pack_x_pitch > ALIGN(width, align_w)) { - pack_x_pitch = ALIGN(width, align_w); + if (pack_x_pitch > ALIGN(width, mt->align_w)) { + pack_x_pitch = ALIGN(width, mt->align_w); pack_x_nr <<= 1; } } else { @@ -152,7 +142,7 @@ brw_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree *mt) if (pack_y_pitch > 2) { pack_y_pitch >>= 1; - pack_y_pitch = ALIGN(pack_y_pitch, align_h); + pack_y_pitch = ALIGN(pack_y_pitch, mt->align_h); } } diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index ffceda27029..2c326f9096b 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -89,6 +89,8 @@ intel_miptree_create_internal(struct intel_context *intel, mt->compressed = compress_byte ? 1 : 0; mt->refcount = 1; + intel_get_texture_alignment_unit(format, &mt->align_w, &mt->align_h); + if (target == GL_TEXTURE_CUBE_MAP) { assert(depth0 == 1); mt->depth0 = 6; @@ -412,11 +414,8 @@ intel_miptree_copy_slice(struct intel_context *intel, assert(depth < src_mt->level[level].depth); if (dst_mt->compressed) { - uint32_t align_w, align_h; - intel_get_texture_alignment_unit(format, - &align_w, &align_h); - height = ALIGN(height, align_h) / align_h; - width = ALIGN(width, align_w); + height = ALIGN(height, dst_mt->align_h) / dst_mt->align_h; + width = ALIGN(width, dst_mt->align_w); } uint32_t dst_x, dst_y, src_x, src_y; diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h index 2cecd29f33e..fda704b9065 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.h +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.h @@ -120,6 +120,13 @@ struct intel_mipmap_tree GLenum target; gl_format format; + /** + * The X offset of each image in the miptree must be aligned to this. See + * the "Alignment Unit Size" section of the BSpec. + */ + unsigned int align_w; + unsigned int align_h; /**< \see align_w */ + GLuint first_level; GLuint last_level; diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.c b/src/mesa/drivers/dri/intel/intel_tex_layout.c index e6324cf2eea..a428d56a23b 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_layout.c +++ b/src/mesa/drivers/dri/intel/intel_tex_layout.c @@ -52,7 +52,6 @@ intel_get_texture_alignment_unit(gl_format format, void i945_miptree_layout_2d(struct intel_mipmap_tree *mt) { - GLuint align_h, align_w; GLuint level; GLuint x = 0; GLuint y = 0; @@ -61,10 +60,9 @@ void i945_miptree_layout_2d(struct intel_mipmap_tree *mt) GLuint depth = mt->depth0; /* number of array layers. */ mt->total_width = mt->width0; - intel_get_texture_alignment_unit(mt->format, &align_w, &align_h); if (mt->compressed) { - mt->total_width = ALIGN(mt->width0, align_w); + mt->total_width = ALIGN(mt->width0, mt->align_w); } /* May need to adjust width to accomodate the placement of @@ -76,10 +74,10 @@ void i945_miptree_layout_2d(struct intel_mipmap_tree *mt) GLuint mip1_width; if (mt->compressed) { - mip1_width = ALIGN(minify(mt->width0), align_w) - + ALIGN(minify(minify(mt->width0)), align_w); + mip1_width = ALIGN(minify(mt->width0), mt->align_w) + + ALIGN(minify(minify(mt->width0)), mt->align_w); } else { - mip1_width = ALIGN(minify(mt->width0), align_w) + mip1_width = ALIGN(minify(mt->width0), mt->align_w) + minify(minify(mt->width0)); } @@ -96,9 +94,9 @@ void i945_miptree_layout_2d(struct intel_mipmap_tree *mt) intel_miptree_set_level_info(mt, level, x, y, width, height, depth); - img_height = ALIGN(height, align_h); + img_height = ALIGN(height, mt->align_h); if (mt->compressed) - img_height /= align_h; + img_height /= mt->align_h; /* Because the images are packed better, the final offset * might not be the maximal one: @@ -108,7 +106,7 @@ void i945_miptree_layout_2d(struct intel_mipmap_tree *mt) /* Layout_below: step right after second mipmap. */ if (level == mt->first_level + 1) { - x += ALIGN(width, align_w); + x += ALIGN(width, mt->align_w); } else { y += img_height; From dd0e46c4102976b7d317104ecd1bb565ac34613a Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Thu, 17 Nov 2011 09:09:56 -0800 Subject: [PATCH 38/41] i965/gen6: Set vertical alignment in SURFACE_STATE batch Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/i965/brw_defines.h | 9 +++++---- src/mesa/drivers/dri/i965/brw_wm_surface_state.c | 8 ++++++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h index 746c89f87cc..bb79bfbafdf 100644 --- a/src/mesa/drivers/dri/i965/brw_defines.h +++ b/src/mesa/drivers/dri/i965/brw_defines.h @@ -458,10 +458,11 @@ #define BRW_SURFACE_MIN_LOD_MASK INTEL_MASK(31, 28) /* Surface state DW5 */ -#define BRW_SURFACE_X_OFFSET_SHIFT 25 -#define BRW_SURFACE_X_OFFSET_MASK INTEL_MASK(31, 25) -#define BRW_SURFACE_Y_OFFSET_SHIFT 20 -#define BRW_SURFACE_Y_OFFSET_MASK INTEL_MASK(23, 20) +#define BRW_SURFACE_X_OFFSET_SHIFT 25 +#define BRW_SURFACE_X_OFFSET_MASK INTEL_MASK(31, 25) +#define BRW_SURFACE_VERTICAL_ALIGN_ENABLE (1 << 24) +#define BRW_SURFACE_Y_OFFSET_SHIFT 20 +#define BRW_SURFACE_Y_OFFSET_MASK INTEL_MASK(23, 20) #define BRW_TEXCOORDMODE_WRAP 0 #define BRW_TEXCOORDMODE_MIRROR 1 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 0c2c804b133..984a7bc2239 100644 --- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c +++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c @@ -262,6 +262,7 @@ brw_update_texture_surface( struct gl_context *ctx, GLuint unit ) struct brw_context *brw = brw_context(ctx); struct gl_texture_object *tObj = ctx->Texture.Unit[unit]._Current; struct intel_texture_object *intelObj = intel_texture_object(tObj); + struct intel_mipmap_tree *mt = intelObj->mt; struct gl_texture_image *firstImage = tObj->Image[0][tObj->BaseLevel]; struct gl_sampler_object *sampler = _mesa_get_samplerobj(ctx, unit); const GLuint surf_index = SURF_INDEX_TEXTURE(unit); @@ -294,7 +295,8 @@ brw_update_texture_surface( struct gl_context *ctx, GLuint unit ) BRW_SURFACE_PITCH_SHIFT); surf[4] = 0; - surf[5] = 0; + + surf[5] = (mt->align_h == 4) ? BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0; /* Emit relocation to surface contents */ drm_intel_bo_emit_reloc(brw->intel.batch.bo, @@ -447,6 +449,7 @@ brw_update_renderbuffer_surface(struct brw_context *brw, struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; struct intel_renderbuffer *irb = intel_renderbuffer(rb); + struct intel_mipmap_tree *mt = irb->mt; struct intel_region *region = irb->mt->region; uint32_t *surf; uint32_t tile_x, tile_y; @@ -509,7 +512,8 @@ brw_update_renderbuffer_surface(struct brw_context *brw, assert(tile_x % 4 == 0); assert(tile_y % 2 == 0); surf[5] = ((tile_x / 4) << BRW_SURFACE_X_OFFSET_SHIFT | - (tile_y / 2) << BRW_SURFACE_Y_OFFSET_SHIFT); + (tile_y / 2) << BRW_SURFACE_Y_OFFSET_SHIFT | + (mt->align_h == 4 ? BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0)); if (intel->gen < 6) { /* _NEW_COLOR */ From e7e81714f3ecf67a975d35e74bdb7fd15d924e4d Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Mon, 7 Nov 2011 15:58:43 -0800 Subject: [PATCH 39/41] i965: Implement the actual tables for texture alignment units [v2] I implemented functions for horizontal/vertical alignment units separately because I find it easier to read that way...especially with all the corner-cases. [chad] Corrected the vertical alignment calculation by checking for depthstencil formats. v2: - Fix typos in intel_horizontal_texture_alignment_unit(): s/height/width/ and s/VALIGN/HALIGN. - Remove special case for compressed formats in intel_get_texture_alignment unit(). Compressed formats are already handled in the halign and valign functions. - Replace check ``_mesa_is_depth_format(...) || _mesa_is_depthstencil_format(...)`` with explcitit checks against GL_DEPTH_COMPONENT and GL_DEPTH_STENCIL. Reviewed-by: Eric Anholt Signed-off-by: Kenneth Graunke Signed-off-by: Chad Versace --- .../drivers/dri/intel/intel_mipmap_tree.c | 3 +- src/mesa/drivers/dri/intel/intel_tex_layout.c | 108 ++++++++++++++++-- src/mesa/drivers/dri/intel/intel_tex_layout.h | 7 +- 3 files changed, 105 insertions(+), 13 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index 2c326f9096b..f875edb9730 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -89,7 +89,8 @@ intel_miptree_create_internal(struct intel_context *intel, mt->compressed = compress_byte ? 1 : 0; mt->refcount = 1; - intel_get_texture_alignment_unit(format, &mt->align_w, &mt->align_h); + intel_get_texture_alignment_unit(intel, format, + &mt->align_w, &mt->align_h); if (target == GL_TEXTURE_CUBE_MAP) { assert(depth0 == 1); diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.c b/src/mesa/drivers/dri/intel/intel_tex_layout.c index a428d56a23b..65645bc46a4 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_layout.c +++ b/src/mesa/drivers/dri/intel/intel_tex_layout.c @@ -33,21 +33,109 @@ #include "intel_mipmap_tree.h" #include "intel_tex_layout.h" #include "intel_context.h" + +#include "main/image.h" #include "main/macros.h" +static unsigned int +intel_horizontal_texture_alignment_unit(struct intel_context *intel, + gl_format format) +{ + /** + * From the "Alignment Unit Size" section of various specs, namely: + * - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4 + * - i965 and G45 PRMs: Volume 1, Section 6.17.3.4. + * - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4 + * - BSpec (for Ivybridge and slight variations in separate stencil) + * + * +----------------------------------------------------------------------+ + * | | alignment unit width ("i") | + * | Surface Property |-----------------------------| + * | | 915 | 965 | ILK | SNB | IVB | + * +----------------------------------------------------------------------+ + * | YUV 4:2:2 format | 8 | 4 | 4 | 4 | 4 | + * | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 | + * | FXT1 compressed format | 8 | 8 | 8 | 8 | 8 | + * | Depth Buffer (16-bit) | 4 | 4 | 4 | 4 | 8 | + * | Depth Buffer (other) | 4 | 4 | 4 | 4 | 4 | + * | Separate Stencil Buffer | N/A | N/A | 8 | 8 | 8 | + * | All Others | 4 | 4 | 4 | 4 | 4 | + * +----------------------------------------------------------------------+ + * + * On IVB+, non-special cases can be overridden by setting the SURFACE_STATE + * "Surface Horizontal Alignment" field to HALIGN_4 or HALIGN_8. + */ + if (_mesa_is_format_compressed(format)) { + /* The hardware alignment requirements for compressed textures + * happen to match the block boundaries. + */ + unsigned int i, j; + _mesa_get_format_block_size(format, &i, &j); + return i; + } + + if (format == MESA_FORMAT_S8) + return 8; + + if (intel->gen >= 7 && format == MESA_FORMAT_Z16) + return 8; + + return 4; +} + +static unsigned int +intel_vertical_texture_alignment_unit(struct intel_context *intel, + gl_format format) +{ + /** + * From the "Alignment Unit Size" section of various specs, namely: + * - Gen3 Spec: "Memory Data Formats" Volume, Section 1.20.1.4 + * - i965 and G45 PRMs: Volume 1, Section 6.17.3.4. + * - Ironlake and Sandybridge PRMs: Volume 1, Part 1, Section 7.18.3.4 + * - BSpec (for Ivybridge and slight variations in separate stencil) + * + * +----------------------------------------------------------------------+ + * | | alignment unit height ("j") | + * | Surface Property |-----------------------------| + * | | 915 | 965 | ILK | SNB | IVB | + * +----------------------------------------------------------------------+ + * | BC1-5 compressed format (DXTn/S3TC) | 4 | 4 | 4 | 4 | 4 | + * | FXT1 compressed format | 4 | 4 | 4 | 4 | 4 | + * | Depth Buffer | 2 | 2 | 2 | 4 | 4 | + * | Separate Stencil Buffer | N/A | N/A | N/A | 4 | 8 | + * | Multisampled (4x or 8x) render target | N/A | N/A | N/A | 4 | 4 | + * | All Others | 2 | 2 | 2 | 2 | 2 | + * +----------------------------------------------------------------------+ + * + * On SNB+, non-special cases can be overridden by setting the SURFACE_STATE + * "Surface Vertical Alignment" field to VALIGN_2 or VALIGN_4. + * + * We currently don't support multisampling. + */ + if (_mesa_is_format_compressed(format)) + return 4; + + if (format == MESA_FORMAT_S8) + return intel->gen >= 7 ? 8 : 4; + + GLenum base_format = _mesa_get_format_base_format(format); + + if (intel->gen >= 6 && + (base_format == GL_DEPTH_COMPONENT || + base_format == GL_DEPTH_STENCIL)) { + return 4; + } + + return 2; +} + void -intel_get_texture_alignment_unit(gl_format format, +intel_get_texture_alignment_unit(struct intel_context *intel, + gl_format format, unsigned int *w, unsigned int *h) { - if (_mesa_is_format_compressed(format)) { - /* The hardware alignment requirements for compressed textures - * happen to match the block boundaries. - */ - _mesa_get_format_block_size(format, w, h); - } else { - *w = 4; - *h = 2; - } + *w = intel_horizontal_texture_alignment_unit(intel, format); + *h = intel_vertical_texture_alignment_unit(intel, format); } void i945_miptree_layout_2d(struct intel_mipmap_tree *mt) diff --git a/src/mesa/drivers/dri/intel/intel_tex_layout.h b/src/mesa/drivers/dri/intel/intel_tex_layout.h index c6c865d2c80..12ed16d8216 100644 --- a/src/mesa/drivers/dri/intel/intel_tex_layout.h +++ b/src/mesa/drivers/dri/intel/intel_tex_layout.h @@ -39,5 +39,8 @@ static INLINE GLuint minify( GLuint d ) } extern void i945_miptree_layout_2d(struct intel_mipmap_tree *mt); -void intel_get_texture_alignment_unit(gl_format format, - unsigned int *w, unsigned int *h); + +void +intel_get_texture_alignment_unit(struct intel_context *intel, + gl_format format, + unsigned int *w, unsigned int *h); From b18875d441ca4b7b1a4098659fb4298a4bf265f6 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Thu, 17 Nov 2011 08:50:05 -0800 Subject: [PATCH 40/41] intel: Use separate stencil whenever possible For depthstencil renderbuffers, we were using separate stencil only if the hardware required it. Since the performance gains from HiZ is so high, we should always use separate stencil if the hardware supports it. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_fbo.c | 2 +- src/mesa/drivers/dri/intel/intel_mipmap_tree.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c index c96430d41bd..dc3e5dda14f 100644 --- a/src/mesa/drivers/dri/intel/intel_fbo.c +++ b/src/mesa/drivers/dri/intel/intel_fbo.c @@ -669,7 +669,7 @@ intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer return false; } else if (irb->Base.Format == MESA_FORMAT_S8_Z24 - && intel->must_use_separate_stencil) { + && intel->has_separate_stencil) { bool ok = true; struct gl_renderbuffer *depth_rb; diff --git a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c index f875edb9730..f8ef2625df3 100644 --- a/src/mesa/drivers/dri/intel/intel_mipmap_tree.c +++ b/src/mesa/drivers/dri/intel/intel_mipmap_tree.c @@ -119,7 +119,7 @@ intel_miptree_create_internal(struct intel_context *intel, brw_miptree_layout(intel, mt); #endif - if (intel->must_use_separate_stencil && + if (intel->has_separate_stencil && _mesa_is_depthstencil_format(_mesa_get_format_base_format(format))) { mt->stencil_mt = intel_miptree_create(intel, mt->target, From e5411d8fdc6a7dda18d82746b84197ef83ee0a13 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Thu, 17 Nov 2011 08:53:39 -0800 Subject: [PATCH 41/41] i965/gen6: Enable HiZ by default Regresses one Piglit test: bugs/fdo10370. I'm not enabling HiZ for gen7 yet because it causes a mysterious performance regression. Reviewed-by: Eric Anholt Signed-off-by: Chad Versace --- src/mesa/drivers/dri/intel/intel_screen.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 67dccdf6006..46b822cb319 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -680,13 +680,9 @@ __DRIconfig **intelInitScreen2(__DRIscreen *psp) intelScreen->gen = 2; } - /* - * FIXME: The hiz and separate stencil fields need updating once the - * FIXME: features are completely implemented for a given chipset. - */ - intelScreen->hw_has_separate_stencil = intelScreen->gen >= 7; + intelScreen->hw_has_separate_stencil = intelScreen->gen >= 6; intelScreen->hw_must_use_separate_stencil = intelScreen->gen >= 7; - intelScreen->hw_has_hiz = false; + intelScreen->hw_has_hiz = intelScreen->gen == 6; /* Not yet for gen7. */ intelScreen->dri2_has_hiz = INTEL_DRI2_HAS_HIZ_UNKNOWN; intel_override_hiz(intelScreen);