static void upload_sf_state(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; uint32_t dw1, dw2, dw3; float point_size; /* _NEW_BUFFERS */ bool render_to_fbo = _mesa_is_user_fbo(brw->intel.ctx.DrawBuffer); bool multisampled_fbo = ctx->DrawBuffer->Visual.samples > 1; dw1 = GEN6_SF_STATISTICS_ENABLE | GEN6_SF_VIEWPORT_TRANSFORM_ENABLE; /* _NEW_BUFFERS */ dw1 |= (brw_depthbuffer_format(brw) << GEN7_SF_DEPTH_BUFFER_SURFACE_FORMAT_SHIFT); /* _NEW_POLYGON */ if ((ctx->Polygon.FrontFace == GL_CCW) ^ render_to_fbo) dw1 |= GEN6_SF_WINDING_CCW; if (ctx->Polygon.OffsetFill) dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_SOLID; if (ctx->Polygon.OffsetLine) dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_WIREFRAME; if (ctx->Polygon.OffsetPoint) dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_POINT; switch (ctx->Polygon.FrontMode) { case GL_FILL: dw1 |= GEN6_SF_FRONT_SOLID; break; case GL_LINE: dw1 |= GEN6_SF_FRONT_WIREFRAME; break; case GL_POINT: dw1 |= GEN6_SF_FRONT_POINT; break; default: assert(0); break; } switch (ctx->Polygon.BackMode) { case GL_FILL: dw1 |= GEN6_SF_BACK_SOLID; break; case GL_LINE: dw1 |= GEN6_SF_BACK_WIREFRAME; break; case GL_POINT: dw1 |= GEN6_SF_BACK_POINT; break; default: assert(0); break; } dw2 = 0; if (ctx->Polygon.CullFlag) { switch (ctx->Polygon.CullFaceMode) { case GL_FRONT: dw2 |= GEN6_SF_CULL_FRONT; break; case GL_BACK: dw2 |= GEN6_SF_CULL_BACK; break; case GL_FRONT_AND_BACK: dw2 |= GEN6_SF_CULL_BOTH; break; default: assert(0); break; } } else { dw2 |= GEN6_SF_CULL_NONE; } /* _NEW_SCISSOR */ if (ctx->Scissor.Enabled) dw2 |= GEN6_SF_SCISSOR_ENABLE; /* _NEW_LINE */ { uint32_t line_width_u3_7 = U_FIXED(CLAMP(ctx->Line.Width, 0.0, 7.99), 7); /* TODO: line width of 0 is not allowed when MSAA enabled */ if (line_width_u3_7 == 0) line_width_u3_7 = 1; dw2 |= line_width_u3_7 << GEN6_SF_LINE_WIDTH_SHIFT; } if (ctx->Line.SmoothFlag) { dw2 |= GEN6_SF_LINE_AA_ENABLE; dw2 |= GEN6_SF_LINE_END_CAP_WIDTH_1_0; } if (ctx->Line.StippleFlag && intel->is_haswell) { dw2 |= HSW_SF_LINE_STIPPLE_ENABLE; } /* _NEW_MULTISAMPLE */ if (multisampled_fbo && ctx->Multisample.Enabled) dw2 |= GEN6_SF_MSRAST_ON_PATTERN; /* FINISHME: Last Pixel Enable? Vertex Sub Pixel Precision Select? */ dw3 = GEN6_SF_LINE_AA_MODE_TRUE; /* _NEW_PROGRAM | _NEW_POINT */ if (!(ctx->VertexProgram.PointSizeEnabled || ctx->Point._Attenuated)) dw3 |= GEN6_SF_USE_STATE_POINT_WIDTH; /* Clamp to ARB_point_parameters user limits */ point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize); /* Clamp to the hardware limits and convert to fixed point */ dw3 |= U_FIXED(CLAMP(point_size, 0.125, 255.875), 3); /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) { dw3 |= (2 << GEN6_SF_TRI_PROVOKE_SHIFT) | (2 << GEN6_SF_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_SF_LINE_PROVOKE_SHIFT); } else { dw3 |= (1 << GEN6_SF_TRIFAN_PROVOKE_SHIFT); } BEGIN_BATCH(7); OUT_BATCH(_3DSTATE_SF << 16 | (7 - 2)); OUT_BATCH(dw1); OUT_BATCH(dw2); OUT_BATCH(dw3); OUT_BATCH_F(ctx->Polygon.OffsetUnits * 2); /* constant. copied from gen4 */ OUT_BATCH_F(ctx->Polygon.OffsetFactor); /* scale */ OUT_BATCH_F(0.0); /* XXX: global depth offset clamp */ ADVANCE_BATCH(); }
void brw_emit_depthbuffer(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; struct gl_framebuffer *fb = ctx->DrawBuffer; /* _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 = brw->depthstencil.depth_mt; struct intel_mipmap_tree *stencil_mt = brw->depthstencil.stencil_mt; struct intel_mipmap_tree *hiz_mt = brw->depthstencil.hiz_mt; uint32_t tile_x = brw->depthstencil.tile_x; uint32_t tile_y = brw->depthstencil.tile_y; bool separate_stencil = false; uint32_t depth_surface_type = BRW_SURFACE_NULL; uint32_t depthbuffer_format = BRW_DEPTHFORMAT_D32_FLOAT; uint32_t depth_offset = 0; uint32_t width = 1, height = 1; if (stencil_mt) { separate_stencil = stencil_mt->format == MESA_FORMAT_S8; /* Gen7 supports only separate stencil */ assert(separate_stencil || intel->gen < 7); } /* If there's a packed depth/stencil bound to stencil only, we need to * emit the packed depth/stencil buffer packet. */ if (!depth_irb && stencil_irb && !separate_stencil) { depth_irb = stencil_irb; depth_mt = stencil_mt; } if (depth_irb && depth_mt) { struct intel_region *region = depth_mt->region; /* When 3DSTATE_DEPTH_BUFFER.Separate_Stencil_Enable is set, then * 3DSTATE_DEPTH_BUFFER.Surface_Format is not permitted to be a packed * depthstencil format. * * Gens prior to 7 require that HiZ_Enable and Separate_Stencil_Enable be * set to the same value. Gens after 7 implicitly always set * Separate_Stencil_Enable; software cannot disable it. */ if ((intel->gen < 7 && depth_mt->hiz_mt) || intel->gen >= 7) { assert(!_mesa_is_format_packed_depth_stencil(depth_mt->format)); } /* Prior to Gen7, if using separate stencil, hiz must be enabled. */ assert(intel->gen >= 7 || !separate_stencil || hiz_mt); assert(intel->gen < 6 || region->tiling == I915_TILING_Y); assert(!hiz_mt || region->tiling == I915_TILING_Y); depthbuffer_format = brw_depthbuffer_format(brw); depth_surface_type = BRW_SURFACE_2D; depth_offset = brw->depthstencil.depth_offset; width = depth_irb->Base.Base.Width; height = depth_irb->Base.Base.Height; } else if (separate_stencil) { /* * There exists a separate stencil buffer but no depth buffer. * * The stencil buffer inherits most of its fields from * 3DSTATE_DEPTH_BUFFER: namely the tile walk, surface type, width, and * height. * * The tiled bit must be set. From the Sandybridge PRM, Volume 2, Part 1, * Section 7.5.5.1.1 3DSTATE_DEPTH_BUFFER, Bit 1.27 Tiled Surface: * [DevGT+]: This field must be set to TRUE. */ assert(intel->has_separate_stencil); depth_surface_type = BRW_SURFACE_2D; width = stencil_irb->Base.Base.Width; height = stencil_irb->Base.Base.Height; } intel->vtbl.emit_depth_stencil_hiz(brw, depth_mt, depth_offset, depthbuffer_format, depth_surface_type, stencil_mt, hiz_mt, separate_stencil, width, height, tile_x, tile_y); }
static void emit_depthbuffer(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; struct gl_framebuffer *fb = ctx->DrawBuffer; /* _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 = brw->depthstencil.depth_mt; struct intel_mipmap_tree *stencil_mt = brw->depthstencil.stencil_mt; struct intel_mipmap_tree *hiz_mt = brw->depthstencil.hiz_mt; uint32_t tile_x = brw->depthstencil.tile_x; uint32_t tile_y = brw->depthstencil.tile_y; unsigned int len; bool separate_stencil = false; if (stencil_mt && stencil_mt->format == MESA_FORMAT_S8) separate_stencil = true; /* 3DSTATE_DEPTH_BUFFER, 3DSTATE_STENCIL_BUFFER are both * non-pipelined state that will need the PIPE_CONTROL workaround. */ if (intel->gen == 6) { intel_emit_post_sync_nonzero_flush(intel); intel_emit_depth_stall_flushes(intel); } /* If there's a packed depth/stencil bound to stencil only, we need to * emit the packed depth/stencil buffer packet. */ if (!depth_irb && stencil_irb && !separate_stencil) { depth_irb = stencil_irb; depth_mt = stencil_mt; } if (intel->gen >= 6) len = 7; else if (intel->is_g4x || intel->gen == 5) len = 6; else len = 5; if (!depth_irb && !separate_stencil) { BEGIN_BATCH(len); OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (len - 2)); OUT_BATCH((BRW_DEPTHFORMAT_D32_FLOAT << 18) | (BRW_SURFACE_NULL << 29)); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); if (intel->is_g4x || intel->gen >= 5) OUT_BATCH(0); if (intel->gen >= 6) OUT_BATCH(0); ADVANCE_BATCH(); } else if (!depth_irb && separate_stencil) { /* * There exists a separate stencil buffer but no depth buffer. * * The stencil buffer inherits most of its fields from * 3DSTATE_DEPTH_BUFFER: namely the tile walk, surface type, width, and * height. * * Enable the hiz bit because it and the separate stencil bit must have * the same value. From Section 2.11.5.6.1.1 3DSTATE_DEPTH_BUFFER, Bit * 1.21 "Separate Stencil Enable": * [DevIL]: If this field is enabled, Hierarchical Depth Buffer * Enable must also be enabled. * * [DevGT]: This field must be set to the same value (enabled or * disabled) as Hierarchical Depth Buffer Enable * * The tiled bit must be set. From the Sandybridge PRM, Volume 2, Part 1, * Section 7.5.5.1.1 3DSTATE_DEPTH_BUFFER, Bit 1.27 Tiled Surface: * [DevGT+]: This field must be set to TRUE. */ assert(intel->has_separate_stencil); BEGIN_BATCH(len); OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (len - 2)); OUT_BATCH((BRW_DEPTHFORMAT_D32_FLOAT << 18) | (1 << 21) | /* separate stencil enable */ (1 << 22) | /* hiz enable */ (BRW_TILEWALK_YMAJOR << 26) | (1 << 27) | /* tiled surface */ (BRW_SURFACE_2D << 29)); OUT_BATCH(0); OUT_BATCH(((stencil_irb->Base.Base.Width + tile_x - 1) << 6) | (stencil_irb->Base.Base.Height + tile_y - 1) << 19); OUT_BATCH(0); if (intel->is_g4x || intel->gen >= 5) OUT_BATCH(tile_x | (tile_y << 16)); else assert(tile_x == 0 && tile_y == 0); if (intel->gen >= 6) OUT_BATCH(0); ADVANCE_BATCH(); } else { struct intel_region *region = depth_mt->region; /* If using separate stencil, hiz must be enabled. */ assert(!separate_stencil || hiz_mt); assert(intel->gen < 6 || region->tiling == I915_TILING_Y); assert(!hiz_mt || region->tiling == I915_TILING_Y); BEGIN_BATCH(len); OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (len - 2)); OUT_BATCH((region->pitch - 1) | (brw_depthbuffer_format(brw) << 18) | ((hiz_mt ? 1 : 0) << 21) | /* separate stencil enable */ ((hiz_mt ? 1 : 0) << 22) | /* hiz enable */ (BRW_TILEWALK_YMAJOR << 26) | ((region->tiling != I915_TILING_NONE) << 27) | (BRW_SURFACE_2D << 29)); OUT_RELOC(region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, brw->depthstencil.depth_offset); OUT_BATCH((BRW_SURFACE_MIPMAPLAYOUT_BELOW << 1) | (((depth_irb->Base.Base.Width + tile_x) - 1) << 6) | (((depth_irb->Base.Base.Height + tile_y) - 1) << 19)); OUT_BATCH(0); if (intel->is_g4x || intel->gen >= 5) OUT_BATCH(tile_x | (tile_y << 16)); else assert(tile_x == 0 && tile_y == 0); if (intel->gen >= 6) OUT_BATCH(0); ADVANCE_BATCH(); } if (hiz_mt || separate_stencil) { /* * In the 3DSTATE_DEPTH_BUFFER batch emitted above, the 'separate * stencil enable' and 'hiz enable' bits were set. Therefore we must * emit 3DSTATE_HIER_DEPTH_BUFFER and 3DSTATE_STENCIL_BUFFER. Even if * there is no stencil buffer, 3DSTATE_STENCIL_BUFFER must be emitted; * failure to do so causes hangs on gen5 and a stall on gen6. */ /* Emit hiz buffer. */ if (hiz_mt) { BEGIN_BATCH(3); OUT_BATCH((_3DSTATE_HIER_DEPTH_BUFFER << 16) | (3 - 2)); OUT_BATCH(hiz_mt->region->pitch - 1); OUT_RELOC(hiz_mt->region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, brw->depthstencil.hiz_offset); ADVANCE_BATCH(); } else { BEGIN_BATCH(3); OUT_BATCH((_3DSTATE_HIER_DEPTH_BUFFER << 16) | (3 - 2)); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } /* Emit stencil buffer. */ if (separate_stencil) { struct intel_region *region = stencil_mt->region; BEGIN_BATCH(3); OUT_BATCH((_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2)); /* 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. */ OUT_BATCH(2 * region->pitch - 1); OUT_RELOC(region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, brw->depthstencil.stencil_offset); ADVANCE_BATCH(); } else { BEGIN_BATCH(3); OUT_BATCH((_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2)); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } } /* * On Gen >= 6, emit clear params for safety. If using hiz, then clear * params must be emitted. * * From Section 2.11.5.6.4.1 3DSTATE_CLEAR_PARAMS: * 3DSTATE_CLEAR_PARAMS packet must follow the DEPTH_BUFFER_STATE packet * when HiZ is enabled and the DEPTH_BUFFER_STATE changes. */ if (intel->gen >= 6 || hiz_mt) { if (intel->gen == 6) intel_emit_post_sync_nonzero_flush(intel); BEGIN_BATCH(2); OUT_BATCH(_3DSTATE_CLEAR_PARAMS << 16 | GEN5_DEPTH_CLEAR_VALID | (2 - 2)); OUT_BATCH(depth_irb ? depth_irb->mt->depth_clear_value : 0); ADVANCE_BATCH(); } }
static void upload_sf_state(struct brw_context *brw) { struct gl_context *ctx = &brw->ctx; uint32_t dw1, dw2, dw3; float point_size; /* _NEW_BUFFERS */ bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer); const bool multisampled_fbo = _mesa_geometric_samples(ctx->DrawBuffer) > 1; dw1 = GEN6_SF_STATISTICS_ENABLE; if (brw->sf.viewport_transform_enable) dw1 |= GEN6_SF_VIEWPORT_TRANSFORM_ENABLE; /* _NEW_BUFFERS */ dw1 |= (brw_depthbuffer_format(brw) << GEN7_SF_DEPTH_BUFFER_SURFACE_FORMAT_SHIFT); /* _NEW_POLYGON */ if (ctx->Polygon._FrontBit == render_to_fbo) dw1 |= GEN6_SF_WINDING_CCW; if (ctx->Polygon.OffsetFill) dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_SOLID; if (ctx->Polygon.OffsetLine) dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_WIREFRAME; if (ctx->Polygon.OffsetPoint) dw1 |= GEN6_SF_GLOBAL_DEPTH_OFFSET_POINT; switch (ctx->Polygon.FrontMode) { case GL_FILL: dw1 |= GEN6_SF_FRONT_SOLID; break; case GL_LINE: dw1 |= GEN6_SF_FRONT_WIREFRAME; break; case GL_POINT: dw1 |= GEN6_SF_FRONT_POINT; break; default: unreachable("not reached"); } switch (ctx->Polygon.BackMode) { case GL_FILL: dw1 |= GEN6_SF_BACK_SOLID; break; case GL_LINE: dw1 |= GEN6_SF_BACK_WIREFRAME; break; case GL_POINT: dw1 |= GEN6_SF_BACK_POINT; break; default: unreachable("not reached"); } dw2 = 0; if (ctx->Polygon.CullFlag) { switch (ctx->Polygon.CullFaceMode) { case GL_FRONT: dw2 |= GEN6_SF_CULL_FRONT; break; case GL_BACK: dw2 |= GEN6_SF_CULL_BACK; break; case GL_FRONT_AND_BACK: dw2 |= GEN6_SF_CULL_BOTH; break; default: unreachable("not reached"); } } else { dw2 |= GEN6_SF_CULL_NONE; } /* _NEW_SCISSOR _NEW_POLYGON BRW_NEW_GEOMETRY_PROGRAM BRW_NEW_PRIMITIVE */ if (ctx->Scissor.EnableFlags || is_drawing_points(brw) || is_drawing_lines(brw)) dw2 |= GEN6_SF_SCISSOR_ENABLE; /* _NEW_LINE */ { uint32_t line_width_u3_7 = brw_get_line_width(brw); dw2 |= line_width_u3_7 << GEN6_SF_LINE_WIDTH_SHIFT; } if (ctx->Line.SmoothFlag) { dw2 |= GEN6_SF_LINE_AA_ENABLE; dw2 |= GEN6_SF_LINE_END_CAP_WIDTH_1_0; } if (ctx->Line.StippleFlag && brw->is_haswell) { dw2 |= HSW_SF_LINE_STIPPLE_ENABLE; } /* _NEW_MULTISAMPLE */ if (multisampled_fbo && ctx->Multisample.Enabled) dw2 |= GEN6_SF_MSRAST_ON_PATTERN; /* FINISHME: Last Pixel Enable? Vertex Sub Pixel Precision Select? */ dw3 = GEN6_SF_LINE_AA_MODE_TRUE; /* _NEW_PROGRAM | _NEW_POINT */ if (!(ctx->VertexProgram.PointSizeEnabled || ctx->Point._Attenuated)) dw3 |= GEN6_SF_USE_STATE_POINT_WIDTH; /* Clamp to ARB_point_parameters user limits */ point_size = CLAMP(ctx->Point.Size, ctx->Point.MinSize, ctx->Point.MaxSize); /* Clamp to the hardware limits and convert to fixed point */ dw3 |= U_FIXED(CLAMP(point_size, 0.125f, 255.875f), 3); /* _NEW_LIGHT */ if (ctx->Light.ProvokingVertex != GL_FIRST_VERTEX_CONVENTION) { dw3 |= (2 << GEN6_SF_TRI_PROVOKE_SHIFT) | (2 << GEN6_SF_TRIFAN_PROVOKE_SHIFT) | (1 << GEN6_SF_LINE_PROVOKE_SHIFT); } else { dw3 |= (1 << GEN6_SF_TRIFAN_PROVOKE_SHIFT); } BEGIN_BATCH(7); OUT_BATCH(_3DSTATE_SF << 16 | (7 - 2)); OUT_BATCH(dw1); OUT_BATCH(dw2); OUT_BATCH(dw3); OUT_BATCH_F(ctx->Polygon.OffsetUnits * 2); /* constant. copied from gen4 */ OUT_BATCH_F(ctx->Polygon.OffsetFactor); /* scale */ OUT_BATCH_F(ctx->Polygon.OffsetClamp); /* global depth offset clamp */ ADVANCE_BATCH(); }
/* Awful vtable-compatible function; should be cleaned up in the future. */ void gen8_emit_depth_stencil_hiz(struct brw_context *brw, struct intel_mipmap_tree *depth_mt, uint32_t depth_offset, uint32_t depthbuffer_format, uint32_t depth_surface_type, struct intel_mipmap_tree *stencil_mt, bool hiz, bool separate_stencil, uint32_t width, uint32_t height, uint32_t tile_x, uint32_t tile_y) { struct gl_context *ctx = &brw->ctx; struct gl_framebuffer *fb = ctx->DrawBuffer; uint32_t surftype; unsigned int depth = 1; unsigned int min_array_element; GLenum gl_target = GL_TEXTURE_2D; unsigned int lod; const struct intel_mipmap_tree *mt = depth_mt ? depth_mt : stencil_mt; const struct intel_renderbuffer *irb = NULL; const struct gl_renderbuffer *rb = NULL; irb = intel_get_renderbuffer(fb, BUFFER_DEPTH); if (!irb) irb = intel_get_renderbuffer(fb, BUFFER_STENCIL); rb = (struct gl_renderbuffer *) irb; if (rb) { depth = MAX2(rb->Depth, 1); if (rb->TexImage) gl_target = rb->TexImage->TexObject->Target; } switch (gl_target) { case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_CUBE_MAP: /* The PRM claims that we should use BRW_SURFACE_CUBE for this * situation, but experiments show that gl_Layer doesn't work when we do * this. So we use BRW_SURFACE_2D, since for rendering purposes this is * equivalent. */ surftype = BRW_SURFACE_2D; depth *= 6; break; default: surftype = translate_tex_target(gl_target); break; } if (fb->MaxNumLayers > 0 || !irb) { min_array_element = 0; } else if (irb->mt->num_samples > 1) { /* Convert physical to logical layer. */ min_array_element = irb->mt_layer / irb->mt->num_samples; } else { min_array_element = irb->mt_layer; } lod = irb ? irb->mt_level - irb->mt->first_level : 0; if (mt) { width = mt->logical_width0; height = mt->logical_height0; } emit_depth_packets(brw, depth_mt, brw_depthbuffer_format(brw), surftype, ctx->Depth.Mask != 0, stencil_mt, ctx->Stencil._WriteEnabled, brw->depthstencil.stencil_offset, hiz, width, height, depth, lod, min_array_element); }
static void emit_depthbuffer(struct brw_context *brw) { struct intel_context *intel = &brw->intel; struct gl_context *ctx = &intel->ctx; struct gl_framebuffer *fb = ctx->DrawBuffer; /* _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 *stencil_mt = NULL; struct intel_region *hiz_region = NULL; unsigned int len; bool separate_stencil = false; /* Amount by which drawing should be offset in order to draw to the * appropriate miplevel/zoffset/cubeface. We will extract these values * from depth_irb or stencil_irb once we determine which is present. */ uint32_t draw_x = 0, draw_y = 0; /* Masks used to determine how much of the draw_x and draw_y offsets should * be performed using the fine adjustment of "depth coordinate offset X/Y" * (dw5 of 3DSTATE_DEPTH_BUFFER). Any remaining coarse adjustment will be * performed by changing the base addresses of the buffers. * * Since the HiZ, depth, and stencil buffers all use the same "depth * coordinate offset X/Y" values, we need to make sure that the coarse * adjustment will be possible to apply to all three buffers. Since coarse * adjustment can only be applied in multiples of the tile size, we will OR * together the tile masks of all the buffers to determine which offsets to * perform as fine adjustments. */ uint32_t tile_mask_x = 0, tile_mask_y = 0; if (depth_irb) { intel_region_get_tile_masks(depth_irb->mt->region, &tile_mask_x, &tile_mask_y); } if (depth_irb && depth_irb->mt && depth_irb->mt->hiz_mt) { hiz_region = depth_irb->mt->hiz_mt->region; uint32_t hiz_tile_mask_x, hiz_tile_mask_y; intel_region_get_tile_masks(hiz_region, &hiz_tile_mask_x, &hiz_tile_mask_y); /* Each HiZ row represents 2 rows of pixels */ hiz_tile_mask_y = hiz_tile_mask_y << 1 | 1; tile_mask_x |= hiz_tile_mask_x; tile_mask_y |= hiz_tile_mask_y; } /* 3DSTATE_DEPTH_BUFFER, 3DSTATE_STENCIL_BUFFER are both * non-pipelined state that will need the PIPE_CONTROL workaround. */ if (intel->gen == 6) { intel_emit_post_sync_nonzero_flush(intel); intel_emit_depth_stall_flushes(intel); } /* Find the real separate stencil mt if present. */ if (stencil_irb) { stencil_mt = stencil_irb->mt; if (stencil_mt->stencil_mt) stencil_mt = stencil_mt->stencil_mt; if (stencil_mt->format == MESA_FORMAT_S8) { separate_stencil = true; /* Separate stencil buffer uses 64x64 tiles. */ tile_mask_x |= 63; tile_mask_y |= 63; } else { uint32_t stencil_tile_mask_x, stencil_tile_mask_y; intel_region_get_tile_masks(stencil_mt->region, &stencil_tile_mask_x, &stencil_tile_mask_y); tile_mask_x |= stencil_tile_mask_x; tile_mask_y |= stencil_tile_mask_y; } } /* If there's a packed depth/stencil bound to stencil only, we need to * emit the packed depth/stencil buffer packet. */ if (!depth_irb && stencil_irb && !separate_stencil) depth_irb = stencil_irb; if (intel->gen >= 6) len = 7; else if (intel->is_g4x || intel->gen == 5) len = 6; else len = 5; if (!depth_irb && !separate_stencil) { BEGIN_BATCH(len); OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (len - 2)); OUT_BATCH((BRW_DEPTHFORMAT_D32_FLOAT << 18) | (BRW_SURFACE_NULL << 29)); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); if (intel->is_g4x || intel->gen >= 5) OUT_BATCH(0); if (intel->gen >= 6) OUT_BATCH(0); ADVANCE_BATCH(); } else if (!depth_irb && separate_stencil) { uint32_t tile_x, tile_y; /* * There exists a separate stencil buffer but no depth buffer. * * The stencil buffer inherits most of its fields from * 3DSTATE_DEPTH_BUFFER: namely the tile walk, surface type, width, and * height. * * Enable the hiz bit because it and the separate stencil bit must have * the same value. From Section 2.11.5.6.1.1 3DSTATE_DEPTH_BUFFER, Bit * 1.21 "Separate Stencil Enable": * [DevIL]: If this field is enabled, Hierarchical Depth Buffer * Enable must also be enabled. * * [DevGT]: This field must be set to the same value (enabled or * disabled) as Hierarchical Depth Buffer Enable * * The tiled bit must be set. From the Sandybridge PRM, Volume 2, Part 1, * Section 7.5.5.1.1 3DSTATE_DEPTH_BUFFER, Bit 1.27 Tiled Surface: * [DevGT+]: This field must be set to TRUE. */ assert(intel->has_separate_stencil); draw_x = stencil_irb->draw_x; draw_y = stencil_irb->draw_y; tile_x = draw_x & tile_mask_x; tile_y = draw_y & tile_mask_y; /* According to the Sandy Bridge PRM, volume 2 part 1, pp326-327 * (3DSTATE_DEPTH_BUFFER dw5), in the documentation for "Depth * Coordinate Offset X/Y": * * "The 3 LSBs of both offsets must be zero to ensure correct * alignment" * * We have no guarantee that tile_x and tile_y are correctly aligned, * since they are determined by the mipmap layout, which is only aligned * to multiples of 4. * * So, to avoid hanging the GPU, just smash the low order 3 bits of * tile_x and tile_y to 0. This is a temporary workaround until we come * up with a better solution. */ tile_x &= ~7; tile_y &= ~7; BEGIN_BATCH(len); OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (len - 2)); OUT_BATCH((BRW_DEPTHFORMAT_D32_FLOAT << 18) | (1 << 21) | /* separate stencil enable */ (1 << 22) | /* hiz enable */ (BRW_TILEWALK_YMAJOR << 26) | (1 << 27) | /* tiled surface */ (BRW_SURFACE_2D << 29)); OUT_BATCH(0); OUT_BATCH(((stencil_irb->Base.Base.Width + tile_x - 1) << 6) | (stencil_irb->Base.Base.Height + tile_y - 1) << 19); OUT_BATCH(0); if (intel->is_g4x || intel->gen >= 5) OUT_BATCH(tile_x | (tile_y << 16)); else assert(tile_x == 0 && tile_y == 0); if (intel->gen >= 6) OUT_BATCH(0); ADVANCE_BATCH(); } else { struct intel_region *region = depth_irb->mt->region; uint32_t tile_x, tile_y, offset; /* If using separate stencil, hiz must be enabled. */ assert(!separate_stencil || hiz_region); assert(intel->gen < 6 || region->tiling == I915_TILING_Y); assert(!hiz_region || region->tiling == I915_TILING_Y); draw_x = depth_irb->draw_x; draw_y = depth_irb->draw_y; tile_x = draw_x & tile_mask_x; tile_y = draw_y & tile_mask_y; /* According to the Sandy Bridge PRM, volume 2 part 1, pp326-327 * (3DSTATE_DEPTH_BUFFER dw5), in the documentation for "Depth * Coordinate Offset X/Y": * * "The 3 LSBs of both offsets must be zero to ensure correct * alignment" * * We have no guarantee that tile_x and tile_y are correctly aligned, * since they are determined by the mipmap layout, which is only aligned * to multiples of 4. * * So, to avoid hanging the GPU, just smash the low order 3 bits of * tile_x and tile_y to 0. This is a temporary workaround until we come * up with a better solution. */ tile_x &= ~7; tile_y &= ~7; offset = intel_region_get_aligned_offset(region, draw_x & ~tile_mask_x, draw_y & ~tile_mask_y); BEGIN_BATCH(len); OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (len - 2)); OUT_BATCH(((region->pitch * region->cpp) - 1) | (brw_depthbuffer_format(brw) << 18) | ((hiz_region ? 1 : 0) << 21) | /* separate stencil enable */ ((hiz_region ? 1 : 0) << 22) | /* hiz enable */ (BRW_TILEWALK_YMAJOR << 26) | ((region->tiling != I915_TILING_NONE) << 27) | (BRW_SURFACE_2D << 29)); OUT_RELOC(region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, offset); OUT_BATCH((BRW_SURFACE_MIPMAPLAYOUT_BELOW << 1) | (((depth_irb->Base.Base.Width + tile_x) - 1) << 6) | (((depth_irb->Base.Base.Height + tile_y) - 1) << 19)); OUT_BATCH(0); if (intel->is_g4x || intel->gen >= 5) OUT_BATCH(tile_x | (tile_y << 16)); else assert(tile_x == 0 && tile_y == 0); if (intel->gen >= 6) OUT_BATCH(0); ADVANCE_BATCH(); } if (hiz_region || separate_stencil) { /* * In the 3DSTATE_DEPTH_BUFFER batch emitted above, the 'separate * stencil enable' and 'hiz enable' bits were set. Therefore we must * emit 3DSTATE_HIER_DEPTH_BUFFER and 3DSTATE_STENCIL_BUFFER. Even if * there is no stencil buffer, 3DSTATE_STENCIL_BUFFER must be emitted; * failure to do so causes hangs on gen5 and a stall on gen6. */ /* Emit hiz buffer. */ if (hiz_region) { uint32_t hiz_offset = intel_region_get_aligned_offset(hiz_region, draw_x & ~tile_mask_x, (draw_y & ~tile_mask_y) / 2); BEGIN_BATCH(3); OUT_BATCH((_3DSTATE_HIER_DEPTH_BUFFER << 16) | (3 - 2)); OUT_BATCH(hiz_region->pitch * hiz_region->cpp - 1); OUT_RELOC(hiz_region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, hiz_offset); ADVANCE_BATCH(); } else { BEGIN_BATCH(3); OUT_BATCH((_3DSTATE_HIER_DEPTH_BUFFER << 16) | (3 - 2)); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } /* Emit stencil buffer. */ if (separate_stencil) { struct intel_region *region = stencil_mt->region; /* Note: we can't compute the stencil offset using * intel_region_get_aligned_offset(), because stencil_region claims * that the region is untiled; in fact it's W tiled. */ uint32_t stencil_offset = (draw_y & ~tile_mask_y) * region->pitch + (draw_x & ~tile_mask_x) * 64; BEGIN_BATCH(3); OUT_BATCH((_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2)); /* 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. */ OUT_BATCH(2 * region->pitch * region->cpp - 1); OUT_RELOC(region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, stencil_offset); ADVANCE_BATCH(); } else { BEGIN_BATCH(3); OUT_BATCH((_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2)); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } } /* * On Gen >= 6, emit clear params for safety. If using hiz, then clear * params must be emitted. * * From Section 2.11.5.6.4.1 3DSTATE_CLEAR_PARAMS: * 3DSTATE_CLEAR_PARAMS packet must follow the DEPTH_BUFFER_STATE packet * when HiZ is enabled and the DEPTH_BUFFER_STATE changes. */ if (intel->gen >= 6 || hiz_region) { if (intel->gen == 6) intel_emit_post_sync_nonzero_flush(intel); BEGIN_BATCH(2); OUT_BATCH(_3DSTATE_CLEAR_PARAMS << 16 | GEN5_DEPTH_CLEAR_VALID | (2 - 2)); OUT_BATCH(depth_irb ? depth_irb->mt->depth_clear_value : 0); ADVANCE_BATCH(); } }