diff options
Diffstat (limited to 'src/mesa/drivers')
-rw-r--r-- | src/mesa/drivers/dri/i965/gen6_hiz.c | 300 |
1 files 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 <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); } |