static dri_bo * brw_create_texture_surface( struct brw_context *brw, struct brw_surface_key *key ) { struct brw_surface_state surf; dri_bo *bo; memset(&surf, 0, sizeof(surf)); surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; surf.ss0.surface_type = translate_tex_target(key->target); surf.ss0.surface_format = translate_tex_format(key->format, key->internal_format, key->depthmode); /* This is ok for all textures with channel width 8bit or less: */ /* surf.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */ surf.ss1.base_addr = key->bo->offset; /* reloc */ surf.ss2.mip_count = key->last_level - key->first_level; surf.ss2.width = key->width - 1; surf.ss2.height = key->height - 1; brw_set_surface_tiling(&surf, key->tiling); surf.ss3.pitch = (key->pitch * key->cpp) - 1; surf.ss3.depth = key->depth - 1; surf.ss4.min_lod = 0; if (key->target == GL_TEXTURE_CUBE_MAP) { surf.ss0.cube_pos_x = 1; surf.ss0.cube_pos_y = 1; surf.ss0.cube_pos_z = 1; surf.ss0.cube_neg_x = 1; surf.ss0.cube_neg_y = 1; surf.ss0.cube_neg_z = 1; } bo = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE, key, sizeof(*key), &key->bo, 1, &surf, sizeof(surf)); /* Emit relocation to surface contents */ drm_intel_bo_emit_reloc(bo, offsetof(struct brw_surface_state, ss1), key->bo, 0, I915_GEM_DOMAIN_SAMPLER, 0); return bo; }
static void brw_update_texture_surface( GLcontext *ctx, GLuint unit, struct brw_surface_state *surf ) { struct intel_context *intel = intel_context(ctx); struct brw_context *brw = brw_context(ctx); struct gl_texture_object *tObj = brw->attribs.Texture->Unit[unit]._Current; struct intel_texture_object *intelObj = intel_texture_object(tObj); struct gl_texture_image *firstImage = tObj->Image[0][intelObj->firstLevel]; memset(surf, 0, sizeof(*surf)); surf->ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW; surf->ss0.surface_type = translate_tex_target(tObj->Target); surf->ss0.surface_format = translate_tex_format(firstImage->TexFormat->MesaFormat, tObj->DepthMode); /* This is ok for all textures with channel width 8bit or less: */ /* surf->ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */ /* BRW_NEW_LOCK */ surf->ss1.base_addr = bmBufferOffset(intel, intelObj->mt->region->buffer); surf->ss2.mip_count = intelObj->lastLevel - intelObj->firstLevel; surf->ss2.width = firstImage->Width - 1; surf->ss2.height = firstImage->Height - 1; surf->ss3.tile_walk = BRW_TILEWALK_XMAJOR; surf->ss3.tiled_surface = intelObj->mt->region->tiled; /* always zero */ surf->ss3.pitch = (intelObj->mt->pitch * intelObj->mt->cpp) - 1; surf->ss3.depth = firstImage->Depth - 1; surf->ss4.min_lod = 0; if (tObj->Target == GL_TEXTURE_CUBE_MAP) { surf->ss0.cube_pos_x = 1; surf->ss0.cube_pos_y = 1; surf->ss0.cube_pos_z = 1; surf->ss0.cube_neg_x = 1; surf->ss0.cube_neg_y = 1; surf->ss0.cube_neg_z = 1; } }
void gen7_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; const uint8_t mocs = GEN7_MOCS_L3; 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; intel_emit_depth_stall_flushes(brw); 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->Layered || !irb) { min_array_element = 0; } else if (irb->mt->num_samples > 1) { /* Convert physical layer 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->physical_width0; height = mt->physical_height0; } /* _NEW_DEPTH, _NEW_STENCIL, _NEW_BUFFERS */ BEGIN_BATCH(7); /* 3DSTATE_DEPTH_BUFFER dw0 */ OUT_BATCH(GEN7_3DSTATE_DEPTH_BUFFER << 16 | (7 - 2)); /* 3DSTATE_DEPTH_BUFFER dw1 */ OUT_BATCH((depth_mt ? depth_mt->region->pitch - 1 : 0) | (depthbuffer_format << 18) | ((hiz ? 1 : 0) << 22) | ((stencil_mt != NULL && ctx->Stencil._WriteEnabled) << 27) | ((ctx->Depth.Mask != 0) << 28) | (surftype << 29)); /* 3DSTATE_DEPTH_BUFFER dw2 */ if (depth_mt) { OUT_RELOC(depth_mt->region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); } else { OUT_BATCH(0); } /* 3DSTATE_DEPTH_BUFFER dw3 */ OUT_BATCH(((width - 1) << 4) | ((height - 1) << 18) | lod); /* 3DSTATE_DEPTH_BUFFER dw4 */ OUT_BATCH(((depth - 1) << 21) | (min_array_element << 10) | mocs); /* 3DSTATE_DEPTH_BUFFER dw5 */ OUT_BATCH(0); /* 3DSTATE_DEPTH_BUFFER dw6 */ OUT_BATCH((depth - 1) << 21); ADVANCE_BATCH(); if (!hiz) { BEGIN_BATCH(3); OUT_BATCH(GEN7_3DSTATE_HIER_DEPTH_BUFFER << 16 | (3 - 2)); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } else { struct intel_mipmap_tree *hiz_mt = depth_mt->hiz_mt; BEGIN_BATCH(3); OUT_BATCH(GEN7_3DSTATE_HIER_DEPTH_BUFFER << 16 | (3 - 2)); OUT_BATCH((mocs << 25) | (hiz_mt->region->pitch - 1)); OUT_RELOC(hiz_mt->region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); ADVANCE_BATCH(); } if (stencil_mt == NULL) { BEGIN_BATCH(3); OUT_BATCH(GEN7_3DSTATE_STENCIL_BUFFER << 16 | (3 - 2)); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } else { const int enabled = brw->is_haswell ? HSW_STENCIL_ENABLED : 0; BEGIN_BATCH(3); OUT_BATCH(GEN7_3DSTATE_STENCIL_BUFFER << 16 | (3 - 2)); /* The stencil buffer has quirky pitch requirements. From the * Sandybridge PRM, Volume 2 Part 1, page 329 (3DSTATE_STENCIL_BUFFER * dword 1 bits 16:0 - 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. * * While the Ivybridge PRM lacks this comment, the BSpec contains the * same text, and experiments indicate that this is necessary. */ OUT_BATCH(enabled | mocs << 25 | (2 * stencil_mt->region->pitch - 1)); OUT_RELOC(stencil_mt->region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); ADVANCE_BATCH(); } BEGIN_BATCH(3); OUT_BATCH(GEN7_3DSTATE_CLEAR_PARAMS << 16 | (3 - 2)); OUT_BATCH(depth_mt ? depth_mt->depth_clear_value : 0); OUT_BATCH(1); ADVANCE_BATCH(); }
static void gen6_blorp_emit_depth_stencil_config(struct brw_context *brw, const struct brw_blorp_params *params) { uint32_t surfwidth, surfheight; uint32_t surftype; unsigned int depth = MAX2(params->depth.mt->logical_depth0, 1); GLenum gl_target = params->depth.mt->target; unsigned int lod; 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; } const unsigned min_array_element = params->depth.layer; lod = params->depth.level - params->depth.mt->first_level; if (params->hiz_op != GEN6_HIZ_OP_NONE && lod == 0) { /* HIZ ops for lod 0 may set the width & height a little * larger to allow the fast depth clear to fit the hardware * alignment requirements. (8x4) */ surfwidth = params->depth.width; surfheight = params->depth.height; } else { surfwidth = params->depth.mt->logical_width0; surfheight = params->depth.mt->logical_height0; } /* 3DSTATE_DEPTH_BUFFER */ { brw_emit_depth_stall_flushes(brw); BEGIN_BATCH(7); /* 3DSTATE_DEPTH_BUFFER dw0 */ OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (7 - 2)); /* 3DSTATE_DEPTH_BUFFER dw1 */ OUT_BATCH((params->depth.mt->pitch - 1) | params->depth_format << 18 | 1 << 21 | /* separate stencil enable */ 1 << 22 | /* hiz enable */ BRW_TILEWALK_YMAJOR << 26 | 1 << 27 | /* y-tiled */ surftype << 29); /* 3DSTATE_DEPTH_BUFFER dw2 */ OUT_RELOC(params->depth.mt->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); /* 3DSTATE_DEPTH_BUFFER dw3 */ OUT_BATCH(BRW_SURFACE_MIPMAPLAYOUT_BELOW << 1 | (surfwidth - 1) << 6 | (surfheight - 1) << 19 | lod << 2); /* 3DSTATE_DEPTH_BUFFER dw4 */ OUT_BATCH((depth - 1) << 21 | min_array_element << 10 | (depth - 1) << 1); /* 3DSTATE_DEPTH_BUFFER dw5 */ OUT_BATCH(0); /* 3DSTATE_DEPTH_BUFFER dw6 */ OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_HIER_DEPTH_BUFFER */ { struct intel_mipmap_tree *hiz_mt = params->depth.mt->hiz_buf->mt; uint32_t offset = 0; if (hiz_mt->array_layout == ALL_SLICES_AT_EACH_LOD) { offset = intel_miptree_get_aligned_offset(hiz_mt, hiz_mt->level[lod].level_x, hiz_mt->level[lod].level_y, false); } BEGIN_BATCH(3); OUT_BATCH((_3DSTATE_HIER_DEPTH_BUFFER << 16) | (3 - 2)); OUT_BATCH(hiz_mt->pitch - 1); OUT_RELOC(hiz_mt->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, offset); ADVANCE_BATCH(); } /* 3DSTATE_STENCIL_BUFFER */ { BEGIN_BATCH(3); OUT_BATCH((_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2)); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } }
static void gen7_blorp_emit_depth_stencil_config(struct brw_context *brw, const brw_blorp_params *params) { const uint8_t mocs = GEN7_MOCS_L3; uint32_t surfwidth, surfheight; uint32_t surftype; unsigned int depth = MAX2(params->depth.mt->logical_depth0, 1); unsigned int min_array_element; GLenum gl_target = params->depth.mt->target; unsigned int lod; 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; } min_array_element = params->depth.layer; if (params->depth.mt->num_samples > 1) { /* Convert physical layer to logical layer. */ min_array_element /= params->depth.mt->num_samples; } lod = params->depth.level - params->depth.mt->first_level; if (params->hiz_op != GEN6_HIZ_OP_NONE && lod == 0) { /* HIZ ops for lod 0 may set the width & height a little * larger to allow the fast depth clear to fit the hardware * alignment requirements. (8x4) */ surfwidth = params->depth.width; surfheight = params->depth.height; } else { surfwidth = params->depth.mt->logical_width0; surfheight = params->depth.mt->logical_height0; } /* 3DSTATE_DEPTH_BUFFER */ { intel_emit_depth_stall_flushes(brw); BEGIN_BATCH(7); OUT_BATCH(GEN7_3DSTATE_DEPTH_BUFFER << 16 | (7 - 2)); OUT_BATCH((params->depth.mt->region->pitch - 1) | params->depth_format << 18 | 1 << 22 | /* hiz enable */ 1 << 28 | /* depth write */ surftype << 29); OUT_RELOC(params->depth.mt->region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); OUT_BATCH((surfwidth - 1) << 4 | (surfheight - 1) << 18 | lod); OUT_BATCH(((depth - 1) << 21) | (min_array_element << 10) | mocs); OUT_BATCH(0); OUT_BATCH((depth - 1) << 21); ADVANCE_BATCH(); } /* 3DSTATE_HIER_DEPTH_BUFFER */ { struct intel_region *hiz_region = params->depth.mt->hiz_mt->region; BEGIN_BATCH(3); OUT_BATCH((GEN7_3DSTATE_HIER_DEPTH_BUFFER << 16) | (3 - 2)); OUT_BATCH((mocs << 25) | (hiz_region->pitch - 1)); OUT_RELOC(hiz_region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); ADVANCE_BATCH(); } /* 3DSTATE_STENCIL_BUFFER */ { BEGIN_BATCH(3); OUT_BATCH((GEN7_3DSTATE_STENCIL_BUFFER << 16) | (3 - 2)); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } }
/** * Sets up a surface state structure to point at the given region. * While it is only used for the front/back buffer currently, it should be * usable for further buffers when doing ARB_draw_buffer support. */ static void gen6_update_renderbuffer_surface(struct brw_context *brw, struct gl_renderbuffer *rb, bool layered, unsigned int unit) { struct gl_context *ctx = &brw->ctx; struct intel_renderbuffer *irb = intel_renderbuffer(rb); struct intel_mipmap_tree *mt = irb->mt; uint32_t *surf; uint32_t format = 0; /* _NEW_BUFFERS */ mesa_format rb_format = _mesa_get_render_format(ctx, intel_rb_format(irb)); uint32_t surftype; int depth = MAX2(irb->layer_count, 1); const GLenum gl_target = rb->TexImage ? rb->TexImage->TexObject->Target : GL_TEXTURE_2D; uint32_t surf_index = brw->wm.prog_data->binding_table.render_target_start + unit; intel_miptree_used_for_rendering(irb->mt); surf = brw_state_batch(brw, AUB_TRACE_SURFACE_STATE, 6 * 4, 32, &brw->wm.base.surf_offset[surf_index]); format = brw->render_target_format[rb_format]; if (unlikely(!brw->format_supported_as_render_target[rb_format])) { _mesa_problem(ctx, "%s: renderbuffer format %s unsupported\n", __func__, _mesa_get_format_name(rb_format)); } switch (gl_target) { case GL_TEXTURE_CUBE_MAP_ARRAY: case GL_TEXTURE_CUBE_MAP: surftype = BRW_SURFACE_2D; depth *= 6; break; case GL_TEXTURE_3D: depth = MAX2(irb->mt->logical_depth0, 1); /* fallthrough */ default: surftype = translate_tex_target(gl_target); break; } const int min_array_element = layered ? 0 : irb->mt_layer; surf[0] = SET_FIELD(surftype, BRW_SURFACE_TYPE) | SET_FIELD(format, BRW_SURFACE_FORMAT); /* reloc */ assert(mt->offset % mt->cpp == 0); surf[1] = mt->bo->offset64 + mt->offset; /* In the gen6 PRM Volume 1 Part 1: Graphics Core, Section 7.18.3.7.1 * (Surface Arrays For all surfaces other than separate stencil buffer): * * "[DevSNB] Errata: Sampler MSAA Qpitch will be 4 greater than the value * calculated in the equation above , for every other odd Surface Height * starting from 1 i.e. 1,5,9,13" * * Since this Qpitch errata only impacts the sampler, we have to adjust the * input for the rendering surface to achieve the same qpitch. For the * affected heights, we increment the height by 1 for the rendering * surface. */ int height0 = irb->mt->logical_height0; if (brw->gen == 6 && irb->mt->num_samples > 1 && (height0 % 4) == 1) height0++; surf[2] = SET_FIELD(mt->logical_width0 - 1, BRW_SURFACE_WIDTH) | SET_FIELD(height0 - 1, BRW_SURFACE_HEIGHT) | SET_FIELD(irb->mt_level - irb->mt->first_level, BRW_SURFACE_LOD); surf[3] = brw_get_surface_tiling_bits(mt->tiling) | SET_FIELD(depth - 1, BRW_SURFACE_DEPTH) | SET_FIELD(mt->pitch - 1, BRW_SURFACE_PITCH); surf[4] = brw_get_surface_num_multisamples(mt->num_samples) | SET_FIELD(min_array_element, BRW_SURFACE_MIN_ARRAY_ELEMENT) | SET_FIELD(depth - 1, BRW_SURFACE_RENDER_TARGET_VIEW_EXTENT); surf[5] = (mt->align_h == 4 ? BRW_SURFACE_VERTICAL_ALIGN_ENABLE : 0); drm_intel_bo_emit_reloc(brw->batch.bo, brw->wm.base.surf_offset[surf_index] + 4, mt->bo, surf[1] - mt->bo->offset64, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); }
void gen6_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; 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; /* Enable the hiz bit if we're doing separate stencil, 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 */ bool enable_hiz_ss = hiz || separate_stencil; brw_emit_depth_stall_flushes(brw); 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(irb->layer_count, 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; case GL_TEXTURE_3D: assert(mt); depth = MAX2(mt->logical_depth0, 1); /* fallthrough */ default: surftype = translate_tex_target(gl_target); break; } const unsigned min_array_element = irb ? irb->mt_layer : 0; lod = irb ? irb->mt_level - irb->mt->first_level : 0; if (mt) { width = mt->logical_width0; height = mt->logical_height0; } BEGIN_BATCH(7); /* 3DSTATE_DEPTH_BUFFER dw0 */ OUT_BATCH(_3DSTATE_DEPTH_BUFFER << 16 | (7 - 2)); /* 3DSTATE_DEPTH_BUFFER dw1 */ OUT_BATCH((depth_mt ? depth_mt->pitch - 1 : 0) | (depthbuffer_format << 18) | ((enable_hiz_ss ? 1 : 0) << 21) | /* separate stencil enable */ ((enable_hiz_ss ? 1 : 0) << 22) | /* hiz enable */ (BRW_TILEWALK_YMAJOR << 26) | ((depth_mt ? depth_mt->tiling != I915_TILING_NONE : 1) << 27) | (surftype << 29)); /* 3DSTATE_DEPTH_BUFFER dw2 */ if (depth_mt) { OUT_RELOC(depth_mt->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 0); } else { OUT_BATCH(0); } /* 3DSTATE_DEPTH_BUFFER dw3 */ OUT_BATCH(((width - 1) << 6) | ((height - 1) << 19) | lod << 2); /* 3DSTATE_DEPTH_BUFFER dw4 */ OUT_BATCH((depth - 1) << 21 | min_array_element << 10 | (depth - 1) << 1); /* 3DSTATE_DEPTH_BUFFER dw5 */ OUT_BATCH(0); assert(tile_x == 0 && tile_y == 0); /* 3DSTATE_DEPTH_BUFFER dw6 */ OUT_BATCH(0); ADVANCE_BATCH(); if (hiz || 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) { struct intel_mipmap_tree *hiz_mt = depth_mt->hiz_buf->mt; uint32_t offset = 0; if (hiz_mt->array_layout == ALL_SLICES_AT_EACH_LOD) { offset = intel_miptree_get_aligned_offset( hiz_mt, hiz_mt->level[lod].level_x, hiz_mt->level[lod].level_y, false); } BEGIN_BATCH(3); OUT_BATCH((_3DSTATE_HIER_DEPTH_BUFFER << 16) | (3 - 2)); OUT_BATCH(hiz_mt->pitch - 1); OUT_RELOC(hiz_mt->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 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) { uint32_t offset = 0; if (stencil_mt->array_layout == ALL_SLICES_AT_EACH_LOD) { if (stencil_mt->format == MESA_FORMAT_S_UINT8) { /* Note: we can't compute the stencil offset using * intel_region_get_aligned_offset(), because stencil_region * claims that the region is untiled even though it's W tiled. */ offset = stencil_mt->level[lod].level_y * stencil_mt->pitch + stencil_mt->level[lod].level_x * 64; } else { offset = intel_miptree_get_aligned_offset( stencil_mt, stencil_mt->level[lod].level_x, stencil_mt->level[lod].level_y, false); } } 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 * stencil_mt->pitch - 1); OUT_RELOC(stencil_mt->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, 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. */ BEGIN_BATCH(2); OUT_BATCH(_3DSTATE_CLEAR_PARAMS << 16 | GEN5_DEPTH_CLEAR_VALID | (2 - 2)); OUT_BATCH(depth_mt ? depth_mt->depth_clear_value : 0); 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); }