/** * \brief Execute a blit or render pass operation. * * To execute the operation, this function manually constructs and emits a * batch to draw a rectangle primitive. The batchbuffer is flushed before * constructing and after emitting the batch. * * This function alters no GL state. */ void gen6_blorp_exec(struct brw_context *brw, const struct brw_blorp_params *params) { uint32_t cc_blend_state_offset = 0; uint32_t cc_state_offset = 0; uint32_t depthstencil_offset; uint32_t wm_push_const_offset = 0; uint32_t wm_bind_bo_offset = 0; /* Emit workaround flushes when we switch from drawing to blorping. */ brw_emit_post_sync_nonzero_flush(brw); brw_upload_state_base_address(brw); gen6_emit_3dstate_multisample(brw, params->dst.num_samples); gen6_emit_3dstate_sample_mask(brw, params->dst.num_samples > 1 ? (1 << params->dst.num_samples) - 1 : 1); gen6_blorp_emit_vertices(brw, params); gen6_blorp_emit_urb_config(brw, params); if (params->wm_prog_data) { cc_blend_state_offset = gen6_blorp_emit_blend_state(brw, params); cc_state_offset = gen6_blorp_emit_cc_state(brw); } depthstencil_offset = gen6_blorp_emit_depth_stencil_state(brw, params); gen6_blorp_emit_cc_state_pointers(brw, params, cc_blend_state_offset, depthstencil_offset, cc_state_offset); if (params->wm_prog_data) { uint32_t wm_surf_offset_renderbuffer; uint32_t wm_surf_offset_texture = 0; wm_push_const_offset = gen6_blorp_emit_wm_constants(brw, params); intel_miptree_used_for_rendering(params->dst.mt); wm_surf_offset_renderbuffer = gen6_blorp_emit_surface_state(brw, params, ¶ms->dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER); if (params->src.mt) { wm_surf_offset_texture = gen6_blorp_emit_surface_state(brw, params, ¶ms->src, I915_GEM_DOMAIN_SAMPLER, 0); } wm_bind_bo_offset = gen6_blorp_emit_binding_table(brw, wm_surf_offset_renderbuffer, wm_surf_offset_texture); } if (params->src.mt) { const uint32_t sampler_offset = gen6_blorp_emit_sampler_state(brw, BRW_MAPFILTER_LINEAR, 0, true); gen6_blorp_emit_sampler_state_pointers(brw, sampler_offset); } gen6_blorp_emit_vs_disable(brw, params); gen6_blorp_emit_gs_disable(brw, params); gen6_blorp_emit_clip_disable(brw); gen6_blorp_emit_sf_config(brw, params); if (params->wm_prog_data) gen6_blorp_emit_constant_ps(brw, params, wm_push_const_offset); else gen6_blorp_emit_constant_ps_disable(brw, params); gen6_blorp_emit_wm_config(brw, params); if (params->wm_prog_data) gen6_blorp_emit_binding_table_pointers(brw, wm_bind_bo_offset); gen6_blorp_emit_viewport_state(brw, params); if (params->depth.mt) gen6_blorp_emit_depth_stencil_config(brw, params); else gen6_blorp_emit_depth_disable(brw, params); gen6_blorp_emit_clear_params(brw, params); gen6_blorp_emit_drawing_rectangle(brw, params); gen6_blorp_emit_primitive(brw, params); }
/** * \copydoc gen6_blorp_exec() */ void gen7_blorp_exec(struct brw_context *brw, const brw_blorp_params *params) { if (brw->gen >= 8) return; brw_blorp_prog_data *prog_data = NULL; uint32_t cc_blend_state_offset = 0; uint32_t cc_state_offset = 0; uint32_t depthstencil_offset; uint32_t wm_push_const_offset = 0; uint32_t wm_bind_bo_offset = 0; uint32_t sampler_offset = 0; uint32_t prog_offset = params->get_wm_prog(brw, &prog_data); gen6_emit_3dstate_multisample(brw, params->num_samples); gen6_emit_3dstate_sample_mask(brw, params->num_samples, 1.0, false, ~0u); gen6_blorp_emit_state_base_address(brw, params); gen6_blorp_emit_vertices(brw, params); gen7_blorp_emit_urb_config(brw, params); if (params->use_wm_prog) { cc_blend_state_offset = gen6_blorp_emit_blend_state(brw, params); cc_state_offset = gen6_blorp_emit_cc_state(brw, params); gen7_blorp_emit_blend_state_pointer(brw, params, cc_blend_state_offset); gen7_blorp_emit_cc_state_pointer(brw, params, cc_state_offset); } depthstencil_offset = gen6_blorp_emit_depth_stencil_state(brw, params); gen7_blorp_emit_depth_stencil_state_pointers(brw, params, depthstencil_offset); if (params->use_wm_prog) { uint32_t wm_surf_offset_renderbuffer; uint32_t wm_surf_offset_texture = 0; wm_push_const_offset = gen6_blorp_emit_wm_constants(brw, params); intel_miptree_used_for_rendering(params->dst.mt); wm_surf_offset_renderbuffer = gen7_blorp_emit_surface_state(brw, params, ¶ms->dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, true /* is_render_target */); if (params->src.mt) { wm_surf_offset_texture = gen7_blorp_emit_surface_state(brw, params, ¶ms->src, I915_GEM_DOMAIN_SAMPLER, 0, false /* is_render_target */); } wm_bind_bo_offset = gen6_blorp_emit_binding_table(brw, params, wm_surf_offset_renderbuffer, wm_surf_offset_texture); sampler_offset = gen7_blorp_emit_sampler_state(brw, params); } gen7_blorp_emit_vs_disable(brw, params); gen7_blorp_emit_hs_disable(brw, params); gen7_blorp_emit_te_disable(brw, params); gen7_blorp_emit_ds_disable(brw, params); gen7_blorp_emit_gs_disable(brw, params); gen7_blorp_emit_streamout_disable(brw, params); gen6_blorp_emit_clip_disable(brw, params); gen7_blorp_emit_sf_config(brw, params); gen7_blorp_emit_wm_config(brw, params, prog_data); if (params->use_wm_prog) { gen7_blorp_emit_binding_table_pointers_ps(brw, params, wm_bind_bo_offset); gen7_blorp_emit_sampler_state_pointers_ps(brw, params, sampler_offset); gen7_blorp_emit_constant_ps(brw, params, wm_push_const_offset); } else { gen7_blorp_emit_constant_ps_disable(brw, params); } gen7_blorp_emit_ps_config(brw, params, prog_offset, prog_data); gen7_blorp_emit_cc_viewport(brw, params); if (params->depth.mt) gen7_blorp_emit_depth_stencil_config(brw, params); else gen7_blorp_emit_depth_disable(brw, params); gen7_blorp_emit_clear_params(brw, params); gen6_blorp_emit_drawing_rectangle(brw, params); gen7_blorp_emit_primitive(brw, params); }
/** * 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); }
static uint32_t gen8_blorp_emit_surface_states(struct brw_context *brw, const struct brw_blorp_params *params) { uint32_t wm_surf_offset_renderbuffer; uint32_t wm_surf_offset_texture = 0; intel_miptree_used_for_rendering(params->dst.mt); wm_surf_offset_renderbuffer = brw_blorp_emit_surface_state(brw, ¶ms->dst, I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER, true /* is_render_target */); if (params->src.mt) { const struct brw_blorp_surface_info *surface = ¶ms->src; struct intel_mipmap_tree *mt = surface->mt; /* If src is a 2D multisample array texture on Gen7+ using * INTEL_MSAA_LAYOUT_UMS or INTEL_MSAA_LAYOUT_CMS, src layer is the * physical layer holding sample 0. So, for example, if mt->num_samples * == 4, then logical layer n corresponds to layer == 4*n. * * Multisampled depth and stencil surfaces have the samples interleaved * (INTEL_MSAA_LAYOUT_IMS) and therefore the layer doesn't need * adjustment. */ const unsigned layer_divider = (mt->msaa_layout == INTEL_MSAA_LAYOUT_UMS || mt->msaa_layout == INTEL_MSAA_LAYOUT_CMS) ? MAX2(mt->num_samples, 1) : 1; const bool is_cube = mt->target == GL_TEXTURE_CUBE_MAP_ARRAY || mt->target == GL_TEXTURE_CUBE_MAP; const unsigned depth = (is_cube ? 6 : 1) * mt->logical_depth0; const unsigned layer = mt->target != GL_TEXTURE_3D ? surface->layer / layer_divider : 0; struct isl_view view = { .format = surface->brw_surfaceformat, .base_level = surface->level, .levels = mt->last_level - surface->level + 1, .base_array_layer = layer, .array_len = depth - layer, .channel_select = { swizzle_to_scs(GET_SWZ(surface->swizzle, 0)), swizzle_to_scs(GET_SWZ(surface->swizzle, 1)), swizzle_to_scs(GET_SWZ(surface->swizzle, 2)), swizzle_to_scs(GET_SWZ(surface->swizzle, 3)), }, .usage = ISL_SURF_USAGE_TEXTURE_BIT, }; brw_emit_surface_state(brw, mt, &view, brw->gen >= 9 ? SKL_MOCS_WB : BDW_MOCS_WB, false, &wm_surf_offset_texture, -1, I915_GEM_DOMAIN_SAMPLER, 0); } return gen6_blorp_emit_binding_table(brw, wm_surf_offset_renderbuffer, wm_surf_offset_texture); } /** * \copydoc gen6_blorp_exec() */ void gen8_blorp_exec(struct brw_context *brw, const struct brw_blorp_params *params) { uint32_t wm_bind_bo_offset = 0; brw_upload_state_base_address(brw); gen7_blorp_emit_cc_viewport(brw); gen7_l3_state.emit(brw); gen7_blorp_emit_urb_config(brw, params); const uint32_t cc_blend_state_offset = gen8_blorp_emit_blend_state(brw, params); gen7_blorp_emit_blend_state_pointer(brw, cc_blend_state_offset); const uint32_t cc_state_offset = gen6_blorp_emit_cc_state(brw); gen7_blorp_emit_cc_state_pointer(brw, cc_state_offset); gen8_blorp_disable_constant_state(brw, _3DSTATE_CONSTANT_VS); gen8_blorp_disable_constant_state(brw, _3DSTATE_CONSTANT_HS); gen8_blorp_disable_constant_state(brw, _3DSTATE_CONSTANT_DS); gen8_blorp_disable_constant_state(brw, _3DSTATE_CONSTANT_GS); gen8_blorp_disable_constant_state(brw, _3DSTATE_CONSTANT_PS); wm_bind_bo_offset = gen8_blorp_emit_surface_states(brw, params); gen7_blorp_emit_binding_table_pointers_ps(brw, wm_bind_bo_offset); if (params->src.mt) { const uint32_t sampler_offset = gen6_blorp_emit_sampler_state(brw, BRW_MAPFILTER_LINEAR, 0, true); gen7_blorp_emit_sampler_state_pointers_ps(brw, sampler_offset); } gen8_emit_3dstate_multisample(brw, params->dst.num_samples); gen6_emit_3dstate_sample_mask(brw, params->dst.num_samples > 1 ? (1 << params->dst.num_samples) - 1 : 1); gen8_disable_stages.emit(brw); gen8_blorp_emit_vs_disable(brw); gen8_blorp_emit_hs_disable(brw); gen7_blorp_emit_te_disable(brw); gen8_blorp_emit_ds_disable(brw); gen8_blorp_emit_gs_disable(brw); gen8_blorp_emit_streamout_disable(brw); gen6_blorp_emit_clip_disable(brw); gen8_blorp_emit_raster_state(brw); gen8_blorp_emit_sbe_state(brw, params); gen8_blorp_emit_sf_config(brw); gen8_blorp_emit_ps_blend(brw); gen8_blorp_emit_ps_extra(brw, params); gen8_blorp_emit_ps_config(brw, params); gen8_blorp_emit_depth_stencil_state(brw, params); gen8_blorp_emit_wm_state(brw); gen8_blorp_emit_depth_disable(brw); gen7_blorp_emit_clear_params(brw, params); gen6_blorp_emit_drawing_rectangle(brw, params); gen8_blorp_emit_vf_topology(brw); gen8_blorp_emit_vf_sys_gen_vals_state(brw); gen6_blorp_emit_vertices(brw, params); gen8_blorp_emit_vf_instancing_state(brw, params); gen8_blorp_emit_vf_state(brw); gen7_blorp_emit_primitive(brw, params); if (brw->gen < 9) gen8_write_pma_stall_bits(brw, 0); }
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)); }