i965/gen6: Complete stubs for HiZ buffer resolves
authorChad Versace <chad.versace@linux.intel.com>
Thu, 17 Nov 2011 16:10:57 +0000 (08:10 -0800)
committerChad Versace <chad.versace@linux.intel.com>
Tue, 22 Nov 2011 18:50:50 +0000 (10:50 -0800)
Some state batches also need to be manipulated. That's done in the next
commit.

Reviewed-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Chad Versace <chad.versace@linux.intel.com>
src/mesa/drivers/dri/i965/gen6_hiz.c

index 5bb56a78348c95a5574115a518f85d8bfb5cc82e..a71c64c3f72dcca917cf611f9021dde5431817c9 100644 (file)
 
 #include "gen6_hiz.h"
 
+#include <assert.h>
+
+#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);
 }