}
}
+static void
+intel_renderbuffer_move_temp_back(struct brw_context *brw,
+ struct intel_renderbuffer *irb)
+{
+ if (irb->align_wa_mt == NULL)
+ return;
+
+ brw_render_cache_set_check_flush(brw, irb->align_wa_mt->bo);
+
+ intel_miptree_copy_slice(brw, irb->align_wa_mt, 0, 0,
+ irb->mt,
+ irb->Base.Base.TexImage->Level, irb->mt_layer);
+
+ intel_miptree_reference(&irb->align_wa_mt, NULL);
+
+ /* Finally restore the x,y to correspond to full miptree. */
+ intel_renderbuffer_set_draw_offset(irb);
+
+ /* Make sure render surface state gets re-emitted with updated miptree. */
+ brw->NewGLState |= _NEW_BUFFERS;
+}
+
+static void
+brw_postdraw_reconcile_align_wa_slices(struct brw_context *brw)
+{
+ struct gl_context *ctx = &brw->ctx;
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+
+ struct intel_renderbuffer *depth_irb =
+ intel_get_renderbuffer(fb, BUFFER_DEPTH);
+ struct intel_renderbuffer *stencil_irb =
+ intel_get_renderbuffer(fb, BUFFER_STENCIL);
+
+ if (depth_irb && depth_irb->align_wa_mt)
+ intel_renderbuffer_move_temp_back(brw, depth_irb);
+
+ if (stencil_irb && stencil_irb->align_wa_mt)
+ intel_renderbuffer_move_temp_back(brw, stencil_irb);
+
+ for (unsigned i = 0; i < fb->_NumColorDrawBuffers; i++) {
+ struct intel_renderbuffer *irb =
+ intel_renderbuffer(fb->_ColorDrawBuffers[i]);
+
+ if (!irb || irb->align_wa_mt == NULL)
+ continue;
+
+ intel_renderbuffer_move_temp_back(brw, irb);
+ }
+}
+
/* May fail if out of video memory for texture or vbo upload, or on
* fallback conditions.
*/
intel_batchbuffer_flush(brw);
brw_program_cache_check_size(brw);
+ brw_postdraw_reconcile_align_wa_slices(brw);
brw_postdraw_set_buffers_need_resolve(brw);
return;
return NULL;
if (irb->mt->stencil_mt)
return irb->mt->stencil_mt;
- return irb->mt;
+ return intel_renderbuffer_get_mt(irb);
}
static bool
/* _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_mipmap_tree *depth_mt = depth_irb ? depth_irb->mt : NULL;
+ struct intel_mipmap_tree *depth_mt = intel_renderbuffer_get_mt(depth_irb);
struct intel_mipmap_tree *stencil_mt = get_stencil_miptree(stencil_irb);
uint32_t tile_x = brw->depthstencil.tile_x;
uint32_t tile_y = brw->depthstencil.tile_y;
* miptree and render into that.
*/
intel_renderbuffer_move_to_temp(brw, irb, false);
- mt = irb->mt;
+ assert(irb->align_wa_mt);
+ mt = irb->align_wa_mt;
}
}
intel_get_image_dims(rb->TexImage, &width, &height, &depth);
- new_mt = intel_miptree_create(brw, rb->TexImage->TexObject->Target,
+ assert(irb->align_wa_mt == NULL);
+ new_mt = intel_miptree_create(brw, GL_TEXTURE_2D,
intel_image->base.Base.TexFormat,
- intel_image->base.Base.Level,
- intel_image->base.Base.Level,
- width, height, depth,
+ 0, 0,
+ width, height, 1,
irb->mt->num_samples,
layout_flags);
intel_miptree_alloc_hiz(brw, new_mt);
}
- intel_miptree_copy_teximage(brw, intel_image, new_mt, invalidate);
+ if (!invalidate)
+ intel_miptree_copy_slice(brw, intel_image->mt,
+ intel_image->base.Base.Level, irb->mt_layer,
+ new_mt, 0, 0);
- intel_miptree_reference(&irb->mt, intel_image->mt);
- intel_renderbuffer_set_draw_offset(irb);
+ intel_miptree_reference(&irb->align_wa_mt, new_mt);
intel_miptree_release(&new_mt);
+
+ irb->draw_x = 0;
+ irb->draw_y = 0;
}
void
*/
struct intel_mipmap_tree *singlesample_mt;
+ /* Gen < 6 doesn't have layer specifier for render targets or depth. Driver
+ * needs to manually offset surfaces to correct level/layer. There are,
+ * however, alignment restrictions to respect as well and in come cases
+ * the only option is to use temporary single slice surface which driver
+ * copies after rendering to the full miptree.
+ *
+ * See intel_renderbuffer_move_to_temp().
+ */
+ struct intel_mipmap_tree *align_wa_mt;
+
/**
* \name Miptree view
* \{
return NULL;
}
+static inline struct intel_mipmap_tree *
+intel_renderbuffer_get_mt(struct intel_renderbuffer *irb)
+{
+ if (!irb)
+ return NULL;
+
+ return (irb->align_wa_mt) ? irb->align_wa_mt : irb->mt;
+}
/**
* \brief Return the framebuffer attachment specified by attIndex.
uint32_t *tile_x,
uint32_t *tile_y)
{
+ if (irb->align_wa_mt) {
+ *tile_x = 0;
+ *tile_y = 0;
+ return 0;
+ }
+
return intel_miptree_get_tile_offsets(irb->mt, irb->mt_level, irb->mt_layer,
tile_x, tile_y);
}
}
}
-static void
+void
intel_miptree_copy_slice(struct brw_context *brw,
struct intel_mipmap_tree *src_mt,
unsigned src_level, unsigned src_layer,
GLuint level,
GLuint img, GLuint x, GLuint y);
+void
+intel_miptree_copy_slice(struct brw_context *brw,
+ struct intel_mipmap_tree *src_mt,
+ unsigned src_level, unsigned src_layer,
+ struct intel_mipmap_tree *dst_mt,
+ unsigned dst_level, unsigned dst_layer);
+
void
intel_miptree_copy_teximage(struct brw_context *brw,
struct intel_texture_image *intelImage,