/** * Sets up a DRIImage structure to point to our shared image in a region */ static void intel_setup_image_from_mipmap_tree(struct intel_context *intel, __DRIimage *image, struct intel_mipmap_tree *mt, GLuint level, GLuint zoffset) { unsigned int draw_x, draw_y; uint32_t mask_x, mask_y; intel_miptree_check_level_layer(mt, level, zoffset); intel_region_get_tile_masks(mt->region, &mask_x, &mask_y, false); intel_miptree_get_image_offset(mt, level, zoffset, &draw_x, &draw_y); image->width = mt->level[level].width; image->height = mt->level[level].height; image->tile_x = draw_x & mask_x; image->tile_y = draw_y & mask_y; image->offset = intel_region_get_aligned_offset(mt->region, draw_x & ~mask_x, draw_y & ~mask_y, false); intel_region_reference(&image->region, mt->region); }
void brw_blorp_mip_info::set(struct intel_mipmap_tree *mt, unsigned int level, unsigned int layer) { intel_miptree_check_level_layer(mt, level, layer); this->mt = mt; this->level = level; this->layer = layer; }
static bool intel_renderbuffer_update_wrapper(struct intel_context *intel, struct intel_renderbuffer *irb, struct gl_texture_image *image, uint32_t layer) { struct gl_renderbuffer *rb = &irb->Base.Base; struct intel_texture_image *intel_image = intel_texture_image(image); struct intel_mipmap_tree *mt = intel_image->mt; int level = image->Level; rb->Format = image->TexFormat; rb->InternalFormat = image->InternalFormat; rb->_BaseFormat = image->_BaseFormat; rb->NumSamples = mt->num_samples; if (mt->msaa_layout != INTEL_MSAA_LAYOUT_NONE) { assert(level == 0); rb->Width = mt->logical_width0; rb->Height = mt->logical_height0; } else { rb->Width = mt->level[level].width; rb->Height = mt->level[level].height; } rb->Delete = intel_delete_renderbuffer; rb->AllocStorage = intel_nop_alloc_storage; intel_miptree_check_level_layer(mt, level, layer); irb->mt_level = level; switch (mt->msaa_layout) { case INTEL_MSAA_LAYOUT_UMS: case INTEL_MSAA_LAYOUT_CMS: irb->mt_layer = layer * mt->num_samples; break; default: irb->mt_layer = layer; } intel_miptree_reference(&irb->mt, mt); intel_renderbuffer_set_draw_offset(irb); if (mt->hiz_mt == NULL && intel->vtbl.is_hiz_depth_format(intel, rb->Format)) { intel_miptree_alloc_hiz(intel, mt, 0 /* num_samples */); if (!mt->hiz_mt) return false; } return true; }
void brw_blorp_mip_info::set(struct intel_mipmap_tree *mt, unsigned int level, unsigned int layer) { intel_miptree_check_level_layer(mt, level, layer); this->mt = mt; this->level = level; this->layer = layer; this->width = mt->level[level].width; this->height = mt->level[level].height; intel_miptree_get_image_offset(mt, level, layer, &x_offset, &y_offset); }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(struct gl_context * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct intel_context *intel = intel_context(ctx); struct gl_renderbuffer *rb = att->Renderbuffer; struct intel_renderbuffer *irb = intel_renderbuffer(rb); struct gl_texture_image *image = rb->TexImage; struct intel_texture_image *intel_image = intel_texture_image(image); struct intel_mipmap_tree *mt = intel_image->mt; int layer; (void) fb; if (att->CubeMapFace > 0) { assert(att->Zoffset == 0); layer = att->CubeMapFace; } else { layer = att->Zoffset; } if (!intel_image->mt) { /* Fallback on drawing to a texture that doesn't have a miptree * (has a border, width/height 0, etc.) */ _swrast_render_texture(ctx, fb, att); return; } intel_miptree_check_level_layer(mt, att->TextureLevel, layer); if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) { _swrast_render_texture(ctx, fb, att); return; } DBG("Begin render %s texture tex=%u w=%d h=%d d=%d refcount=%d\n", _mesa_get_format_name(image->TexFormat), att->Texture->Name, image->Width, image->Height, image->Depth, rb->RefCount); /* update drawing region, etc */ intel_draw_buffer(ctx); }
/** * Sets up a DRIImage structure to point to a slice out of a miptree. */ static void intel_setup_image_from_mipmap_tree(struct brw_context *brw, __DRIimage *image, struct intel_mipmap_tree *mt, GLuint level, GLuint zoffset) { intel_miptree_make_shareable(brw, mt); intel_miptree_check_level_layer(mt, level, zoffset); image->width = minify(mt->physical_width0, level - mt->first_level); image->height = minify(mt->physical_height0, level - mt->first_level); image->pitch = mt->pitch; image->offset = intel_miptree_get_tile_offsets(mt, level, zoffset, &image->tile_x, &image->tile_y); drm_intel_bo_unreference(image->bo); image->bo = mt->bo; drm_intel_bo_reference(mt->bo); }
static bool intel_renderbuffer_update_wrapper(struct brw_context *brw, struct intel_renderbuffer *irb, struct gl_texture_image *image, uint32_t layer) { struct gl_renderbuffer *rb = &irb->Base.Base; struct intel_texture_image *intel_image = intel_texture_image(image); struct intel_mipmap_tree *mt = intel_image->mt; int level = image->Level; rb->Depth = image->Depth; rb->AllocStorage = intel_nop_alloc_storage; intel_miptree_check_level_layer(mt, level, layer); irb->mt_level = level; switch (mt->msaa_layout) { case INTEL_MSAA_LAYOUT_UMS: case INTEL_MSAA_LAYOUT_CMS: irb->mt_layer = layer * mt->num_samples; break; default: irb->mt_layer = layer; } intel_miptree_reference(&irb->mt, mt); intel_renderbuffer_set_draw_offset(irb); if (mt->hiz_mt == NULL && brw_is_hiz_depth_format(brw, rb->Format)) { intel_miptree_alloc_hiz(brw, mt); if (!mt->hiz_mt) return false; } return true; }
void brw_blorp_mip_info::set(struct intel_mipmap_tree *mt, unsigned int level, unsigned int layer) { /* Layer is a physical layer, so if this is a 2D multisample array texture * using INTEL_MSAA_LAYOUT_UMS or INTEL_MSAA_LAYOUT_CMS, then it had better * be a multiple of num_samples. */ if (mt->msaa_layout == INTEL_MSAA_LAYOUT_UMS || mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) { assert(layer % mt->num_samples == 0); } intel_miptree_check_level_layer(mt, level, layer); this->mt = mt; this->level = level; this->layer = layer; this->width = minify(mt->physical_width0, level - mt->first_level); this->height = minify(mt->physical_height0, level - mt->first_level); intel_miptree_get_image_offset(mt, level, layer, &x_offset, &y_offset); }
static bool intel_renderbuffer_update_wrapper(struct intel_context *intel, struct intel_renderbuffer *irb, struct gl_texture_image *image, uint32_t layer) { struct gl_renderbuffer *rb = &irb->Base.Base; struct intel_texture_image *intel_image = intel_texture_image(image); struct intel_mipmap_tree *mt = intel_image->mt; int level = image->Level; rb->AllocStorage = intel_nop_alloc_storage; intel_miptree_check_level_layer(mt, level, layer); irb->mt_level = level; irb->mt_layer = layer; intel_miptree_reference(&irb->mt, mt); intel_renderbuffer_set_draw_offset(irb); return true; }
static bool intel_renderbuffer_update_wrapper(struct intel_context *intel, struct intel_renderbuffer *irb, struct gl_texture_image *image, uint32_t layer) { struct gl_renderbuffer *rb = &irb->Base.Base; struct intel_texture_image *intel_image = intel_texture_image(image); struct intel_mipmap_tree *mt = intel_image->mt; int level = image->Level; rb->Format = image->TexFormat; rb->InternalFormat = image->InternalFormat; rb->_BaseFormat = image->_BaseFormat; rb->Width = mt->level[level].width; rb->Height = mt->level[level].height; rb->Delete = intel_delete_renderbuffer; rb->AllocStorage = intel_nop_alloc_storage; intel_miptree_check_level_layer(mt, level, layer); irb->mt_level = level; irb->mt_layer = layer; intel_miptree_reference(&irb->mt, mt); intel_renderbuffer_set_draw_offset(irb); if (mt->hiz_mt == NULL && intel->vtbl.is_hiz_depth_format(intel, rb->Format)) { intel_miptree_alloc_hiz(intel, mt, 0 /* num_samples */); if (!mt->hiz_mt) return false; } return true; }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(struct gl_context * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct intel_context *intel = intel_context(ctx); struct gl_texture_image *image = _mesa_get_attachment_teximage(att); struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); struct intel_texture_image *intel_image = intel_texture_image(image); struct intel_mipmap_tree *mt = intel_image->mt; int layer; (void) fb; if (att->CubeMapFace > 0) { assert(att->Zoffset == 0); layer = att->CubeMapFace; } else { layer = att->Zoffset; } if (!intel_image->mt) { /* Fallback on drawing to a texture that doesn't have a miptree * (has a border, width/height 0, etc.) */ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; } else if (!irb) { intel_miptree_check_level_layer(mt, att->TextureLevel, layer); irb = (struct intel_renderbuffer *)intel_new_renderbuffer(ctx, ~0); if (irb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base.Base); } else { /* fallback to software rendering */ _swrast_render_texture(ctx, fb, att); return; } } if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; } irb->tex_image = image; DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n", _mesa_get_format_name(image->TexFormat), att->Texture->Name, image->Width, image->Height, irb->Base.Base.RefCount); /* update drawing region, etc */ intel_draw_buffer(ctx); }
static void blorp_surf_for_miptree(struct brw_context *brw, struct blorp_surf *surf, struct intel_mipmap_tree *mt, bool is_render_target, uint32_t safe_aux_usage, unsigned *level, unsigned start_layer, unsigned num_layers, struct isl_surf tmp_surfs[2]) { if (mt->msaa_layout == INTEL_MSAA_LAYOUT_UMS || mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) { const unsigned num_samples = MAX2(1, mt->num_samples); for (unsigned i = 0; i < num_layers; i++) { for (unsigned s = 0; s < num_samples; s++) { const unsigned phys_layer = (start_layer + i) * num_samples + s; intel_miptree_check_level_layer(mt, *level, phys_layer); } } } else { for (unsigned i = 0; i < num_layers; i++) intel_miptree_check_level_layer(mt, *level, start_layer + i); } intel_miptree_get_isl_surf(brw, mt, &tmp_surfs[0]); surf->surf = &tmp_surfs[0]; surf->addr = (struct blorp_address) { .buffer = mt->bo, .offset = mt->offset, .read_domains = is_render_target ? I915_GEM_DOMAIN_RENDER : I915_GEM_DOMAIN_SAMPLER, .write_domain = is_render_target ? I915_GEM_DOMAIN_RENDER : 0, }; if (brw->gen == 6 && mt->format == MESA_FORMAT_S_UINT8 && mt->array_layout == ALL_SLICES_AT_EACH_LOD) { /* Sandy bridge stencil and HiZ use this ALL_SLICES_AT_EACH_LOD hack in * order to allow for layered rendering. The hack makes each LOD of the * stencil or HiZ buffer a single tightly packed array surface at some * offset into the surface. Since ISL doesn't know how to deal with the * crazy ALL_SLICES_AT_EACH_LOD layout and since we have to do a manual * offset of it anyway, we might as well do the offset here and keep the * hacks inside the i965 driver. * * See also gen6_depth_stencil_state.c */ uint32_t offset; apply_gen6_stencil_hiz_offset(&tmp_surfs[0], mt, *level, &offset); surf->addr.offset += offset; *level = 0; } struct isl_surf *aux_surf = &tmp_surfs[1]; intel_miptree_get_aux_isl_surf(brw, mt, aux_surf, &surf->aux_usage); if (surf->aux_usage != ISL_AUX_USAGE_NONE) { if (surf->aux_usage == ISL_AUX_USAGE_HIZ) { /* If we're not going to use it as a depth buffer, resolve HiZ */ if (!(safe_aux_usage & (1 << ISL_AUX_USAGE_HIZ))) { for (unsigned i = 0; i < num_layers; i++) { intel_miptree_slice_resolve_depth(brw, mt, *level, start_layer + i); /* If we're rendering to it then we'll need a HiZ resolve once * we're done before we can use it with HiZ again. */ if (is_render_target) intel_miptree_slice_set_needs_hiz_resolve(mt, *level, start_layer + i); } surf->aux_usage = ISL_AUX_USAGE_NONE; } } else if (!(safe_aux_usage & (1 << surf->aux_usage))) { uint32_t flags = 0; if (safe_aux_usage & (1 << ISL_AUX_USAGE_CCS_E)) flags |= INTEL_MIPTREE_IGNORE_CCS_E; intel_miptree_resolve_color(brw, mt, *level, start_layer, num_layers, flags); assert(!intel_miptree_has_color_unresolved(mt, *level, 1, start_layer, num_layers)); surf->aux_usage = ISL_AUX_USAGE_NONE; } } if (is_render_target) intel_miptree_used_for_rendering(brw, mt, *level, start_layer, num_layers); if (surf->aux_usage != ISL_AUX_USAGE_NONE) { /* We only really need a clear color if we also have an auxiliary * surface. Without one, it does nothing. */ surf->clear_color = intel_miptree_get_isl_clear_color(brw, mt); surf->aux_surf = aux_surf; surf->aux_addr = (struct blorp_address) { .read_domains = is_render_target ? I915_GEM_DOMAIN_RENDER : I915_GEM_DOMAIN_SAMPLER, .write_domain = is_render_target ? I915_GEM_DOMAIN_RENDER : 0, }; if (mt->mcs_buf) { surf->aux_addr.buffer = mt->mcs_buf->bo; surf->aux_addr.offset = mt->mcs_buf->offset; } else { assert(surf->aux_usage == ISL_AUX_USAGE_HIZ); struct intel_mipmap_tree *hiz_mt = mt->hiz_buf->mt; if (hiz_mt) { surf->aux_addr.buffer = hiz_mt->bo; if (brw->gen == 6 && hiz_mt->array_layout == ALL_SLICES_AT_EACH_LOD) { /* gen6 requires the HiZ buffer to be manually offset to the * right location. We could fixup the surf but it doesn't * matter since most of those fields don't matter. */ apply_gen6_stencil_hiz_offset(aux_surf, hiz_mt, *level, &surf->aux_addr.offset); } else { surf->aux_addr.offset = 0; } assert(hiz_mt->pitch == aux_surf->row_pitch); } else { surf->aux_addr.buffer = mt->hiz_buf->aux_base.bo; surf->aux_addr.offset = mt->hiz_buf->aux_base.offset; } } } else { surf->aux_addr = (struct blorp_address) { .buffer = NULL, }; memset(&surf->clear_color, 0, sizeof(surf->clear_color)); } assert((surf->aux_usage == ISL_AUX_USAGE_NONE) == (surf->aux_addr.buffer == NULL)); }
/** * \copydoc gen6_hiz_exec() */ static void gen7_hiz_exec(struct intel_context *intel, struct intel_mipmap_tree *mt, unsigned int level, unsigned int layer, enum gen6_hiz_op op) { struct gl_context *ctx = &intel->ctx; struct brw_context *brw = brw_context(ctx); assert(op != GEN6_HIZ_OP_DEPTH_CLEAR); /* Not implemented yet. */ assert(mt->hiz_mt != NULL); intel_miptree_check_level_layer(mt, level, layer); uint32_t depth_format; switch (mt->format) { case MESA_FORMAT_Z16: depth_format = BRW_DEPTHFORMAT_D16_UNORM; break; case MESA_FORMAT_Z32_FLOAT: depth_format = BRW_DEPTHFORMAT_D32_FLOAT; break; case MESA_FORMAT_X8_Z24: depth_format = BRW_DEPTHFORMAT_D24_UNORM_X8_UINT; break; default: assert(0); break; } gen6_hiz_emit_batch_head(brw); gen6_hiz_emit_vertices(brw, mt, level, layer); /* 3DSTATE_URB_VS * 3DSTATE_URB_HS * 3DSTATE_URB_DS * 3DSTATE_URB_GS * * If the 3DSTATE_URB_VS is emitted, than the others must be also. From the * BSpec, Volume 2a "3D Pipeline Overview", Section 1.7.1 3DSTATE_URB_VS: * 3DSTATE_URB_HS, 3DSTATE_URB_DS, and 3DSTATE_URB_GS must also be * programmed in order for the programming of this state to be * valid. */ { /* The minimum valid value is 32. See 3DSTATE_URB_VS, * Dword 1.15:0 "VS Number of URB Entries". */ int num_vs_entries = 32; BEGIN_BATCH(2); OUT_BATCH(_3DSTATE_URB_VS << 16 | (2 - 2)); OUT_BATCH(1 << GEN7_URB_ENTRY_SIZE_SHIFT | 0 << GEN7_URB_STARTING_ADDRESS_SHIFT | num_vs_entries); ADVANCE_BATCH(); BEGIN_BATCH(2); OUT_BATCH(_3DSTATE_URB_GS << 16 | (2 - 2)); OUT_BATCH(0); ADVANCE_BATCH(); BEGIN_BATCH(2); OUT_BATCH(_3DSTATE_URB_HS << 16 | (2 - 2)); OUT_BATCH(0); ADVANCE_BATCH(); BEGIN_BATCH(2); OUT_BATCH(_3DSTATE_URB_DS << 16 | (2 - 2)); OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_DEPTH_STENCIL_STATE_POINTERS * * The offset is relative to CMD_STATE_BASE_ADDRESS.DynamicStateBaseAddress. */ { uint32_t depthstencil_offset; gen6_hiz_emit_depth_stencil_state(brw, op, &depthstencil_offset); BEGIN_BATCH(2); OUT_BATCH(_3DSTATE_DEPTH_STENCIL_STATE_POINTERS << 16 | (2 - 2)); OUT_BATCH(depthstencil_offset | 1); ADVANCE_BATCH(); } /* 3DSTATE_VS * * Disable vertex shader. */ { BEGIN_BATCH(6); OUT_BATCH(_3DSTATE_VS << 16 | (6 - 2)); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_HS * * Disable the hull shader. */ { BEGIN_BATCH(7); OUT_BATCH(_3DSTATE_HS << 16 | (7 - 2)); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_TE * * Disable the tesselation engine. */ { BEGIN_BATCH(4); OUT_BATCH(_3DSTATE_TE << 16 | (4 - 2)); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_DS * * Disable the domain shader. */ { BEGIN_BATCH(6); OUT_BATCH(_3DSTATE_DS << 16 | (6 - 2)); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_GS * * Disable the geometry shader. */ { BEGIN_BATCH(7); OUT_BATCH(_3DSTATE_GS << 16 | (7 - 2)); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_STREAMOUT * * Disable streamout. */ { BEGIN_BATCH(3); OUT_BATCH(_3DSTATE_STREAMOUT << 16 | (3 - 2)); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_CLIP * * Disable the clipper. * * The HiZ op emits a rectangle primitive, which requires clipping to * be disabled. From page 10 of the Sandy Bridge PRM Volume 2 Part 1 * Section 1.3 "3D Primitives Overview": * RECTLIST: * Either the CLIP unit should be DISABLED, or the CLIP unit's Clip * Mode should be set to a value other than CLIPMODE_NORMAL. * * Also disable perspective divide. This doesn't change the clipper's * output, but does spare a few electrons. */ { BEGIN_BATCH(4); OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2)); OUT_BATCH(0); OUT_BATCH(GEN6_CLIP_PERSPECTIVE_DIVIDE_DISABLE); OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_SF * * Disable ViewportTransformEnable (dw1.1) * * From the SandyBridge 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). * * A solid rectangle must be rendered, so set FrontFaceFillMode (dw1.6:5) * and BackFaceFillMode (dw1.4:3) to SOLID(0). * * From the Sandy Bridge PRM, Volume 2, Part 1, Section * 6.4.1.1 3DSTATE_SF, Field FrontFaceFillMode: * 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. */ { BEGIN_BATCH(7); OUT_BATCH(_3DSTATE_SF << 16 | (7 - 2)); OUT_BATCH(depth_format << GEN7_SF_DEPTH_BUFFER_SURFACE_FORMAT_SHIFT); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_SBE */ { BEGIN_BATCH(14); OUT_BATCH(_3DSTATE_SBE << 16 | (14 - 2)); OUT_BATCH((1 - 1) << GEN7_SBE_NUM_OUTPUTS_SHIFT | /* only position */ 1 << GEN7_SBE_URB_ENTRY_READ_LENGTH_SHIFT | 0 << GEN7_SBE_URB_ENTRY_READ_OFFSET_SHIFT); for (int i = 0; i < 12; ++i) OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_WM * * Disable PS thread dispatch (dw1.29) and enable the HiZ op. */ { uint32_t dw1 = 0; switch (op) { case GEN6_HIZ_OP_DEPTH_CLEAR: assert(!"not implemented"); dw1 |= GEN7_WM_DEPTH_CLEAR; break; case GEN6_HIZ_OP_DEPTH_RESOLVE: dw1 |= GEN7_WM_DEPTH_RESOLVE; break; case GEN6_HIZ_OP_HIZ_RESOLVE: dw1 |= GEN7_WM_HIERARCHICAL_DEPTH_RESOLVE; break; default: assert(0); break; } BEGIN_BATCH(3); OUT_BATCH(_3DSTATE_WM << 16 | (3 - 2)); OUT_BATCH(dw1); OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_PS * * Pixel shader dispatch is disabled above in 3DSTATE_WM, dw1.29. Despite * that, thread dispatch info must still be specified. * - Maximum Number of Threads (dw4.24:31) must be nonzero, as the BSpec * states that the valid range for this field is [0x3, 0x2f]. * - A dispatch mode must be given; that is, at least one of the * "N Pixel Dispatch Enable" (N=8,16,32) fields must be set. This was * discovered through simulator error messages. */ { BEGIN_BATCH(8); OUT_BATCH(_3DSTATE_PS << 16 | (8 - 2)); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(((brw->max_wm_threads - 1) << IVB_PS_MAX_THREADS_SHIFT) | GEN7_PS_32_DISPATCH_ENABLE); OUT_BATCH(0); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_DEPTH_BUFFER */ { uint32_t width = mt->level[level].width; uint32_t height = mt->level[level].height; uint32_t tile_x; uint32_t tile_y; uint32_t offset; { /* Construct a dummy renderbuffer just to extract tile offsets. */ struct intel_renderbuffer rb; rb.mt = mt; rb.mt_level = level; rb.mt_layer = layer; intel_renderbuffer_set_draw_offset(&rb); offset = intel_renderbuffer_tile_offsets(&rb, &tile_x, &tile_y); } intel_emit_depth_stall_flushes(intel); BEGIN_BATCH(7); OUT_BATCH(GEN7_3DSTATE_DEPTH_BUFFER << 16 | (7 - 2)); OUT_BATCH(((mt->region->pitch * mt->region->cpp) - 1) | depth_format << 18 | 1 << 22 | /* hiz enable */ 1 << 28 | /* depth write */ BRW_SURFACE_2D << 29); OUT_RELOC(mt->region->bo, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, offset); OUT_BATCH((width + tile_x - 1) << 4 | (height + tile_y - 1) << 18); OUT_BATCH(0); OUT_BATCH(tile_x | tile_y << 16); OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_HIER_DEPTH_BUFFER */ { struct intel_region *hiz_region = mt->hiz_mt->region; BEGIN_BATCH(3); OUT_BATCH((GEN7_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, 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(); } /* 3DSTATE_CLEAR_PARAMS * * From the BSpec, Volume 2a.11 Windower, Section 1.5.6.3.2 * 3DSTATE_CLEAR_PARAMS: * [DevIVB] 3DSTATE_CLEAR_PARAMS must always be programmed in the along * with the other Depth/Stencil state commands(i.e. 3DSTATE_DEPTH_BUFFER, * 3DSTATE_STENCIL_BUFFER, or 3DSTATE_HIER_DEPTH_BUFFER). */ { BEGIN_BATCH(3); OUT_BATCH(GEN7_3DSTATE_CLEAR_PARAMS << 16 | (3 - 2)); OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DSTATE_DRAWING_RECTANGLE */ { BEGIN_BATCH(4); OUT_BATCH(_3DSTATE_DRAWING_RECTANGLE << 16 | (4 - 2)); OUT_BATCH(0); OUT_BATCH(((mt->level[level].width - 1) & 0xffff) | ((mt->level[level].height - 1) << 16)); OUT_BATCH(0); ADVANCE_BATCH(); } /* 3DPRIMITIVE */ { BEGIN_BATCH(7); OUT_BATCH(CMD_3D_PRIM << 16 | (7 - 2)); OUT_BATCH(GEN7_3DPRIM_VERTEXBUFFER_ACCESS_SEQUENTIAL | _3DPRIM_RECTLIST); OUT_BATCH(3); /* vertex count per instance */ OUT_BATCH(0); OUT_BATCH(1); /* instance count */ OUT_BATCH(0); OUT_BATCH(0); ADVANCE_BATCH(); } /* See comments above at first invocation of intel_flush() in * gen6_hiz_emit_batch_head(). */ intel_flush(ctx); /* Be safe. */ brw->state.dirty.brw = ~0; brw->state.dirty.cache = ~0; }
/** * Called by glFramebufferTexture[123]DEXT() (and other places) to * prepare for rendering into texture memory. This might be called * many times to choose different texture levels, cube faces, etc * before intel_finish_render_texture() is ever called. */ static void intel_render_texture(struct gl_context * ctx, struct gl_framebuffer *fb, struct gl_renderbuffer_attachment *att) { struct intel_context *intel = intel_context(ctx); struct gl_texture_image *image = _mesa_get_attachment_teximage(att); struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); struct intel_texture_image *intel_image = intel_texture_image(image); struct intel_mipmap_tree *mt = intel_image->mt; int layer; (void) fb; if (att->CubeMapFace > 0) { assert(att->Zoffset == 0); layer = att->CubeMapFace; } else { layer = att->Zoffset; } if (!intel_image->mt) { /* Fallback on drawing to a texture that doesn't have a miptree * (has a border, width/height 0, etc.) */ _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; } else if (!irb) { intel_miptree_check_level_layer(mt, att->TextureLevel, layer); irb = (struct intel_renderbuffer *)intel_new_renderbuffer(ctx, ~0); if (irb) { /* bind the wrapper to the attachment point */ _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base.Base); } else { /* fallback to software rendering */ _swrast_render_texture(ctx, fb, att); return; } } if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) { _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); _swrast_render_texture(ctx, fb, att); return; } DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n", _mesa_get_format_name(image->TexFormat), att->Texture->Name, image->Width, image->Height, irb->Base.Base.RefCount); intel_image->used_as_render_target = true; #ifndef I915 if (need_tile_offset_workaround(brw_context(ctx), irb)) { /* Original gen4 hardware couldn't draw to a non-tile-aligned * destination in a miptree unless you actually setup your * renderbuffer as a miptree and used the fragile * lod/array_index/etc. controls to select the image. So, * instead, we just make a new single-level miptree and render * into that. */ struct intel_context *intel = intel_context(ctx); struct intel_mipmap_tree *new_mt; int width, height, depth; intel_miptree_get_dimensions_for_image(image, &width, &height, &depth); new_mt = intel_miptree_create(intel, image->TexObject->Target, intel_image->base.Base.TexFormat, intel_image->base.Base.Level, intel_image->base.Base.Level, width, height, depth, true); intel_miptree_copy_teximage(intel, intel_image, new_mt); intel_renderbuffer_set_draw_offset(irb); intel_miptree_reference(&irb->mt, intel_image->mt); intel_miptree_release(&new_mt); } #endif /* update drawing region, etc */ intel_draw_buffer(ctx); }