From: Marek Olšák <marek.ol...@amd.com> let's skip these state changes --- src/gallium/auxiliary/util/u_blitter.c | 95 +++++++++++++++++++-------- src/gallium/drivers/radeon/r600_pipe_common.c | 79 +++++++++++----------- 2 files changed, 109 insertions(+), 65 deletions(-)
diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index 2d0d782..bebef8e 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -109,20 +109,21 @@ struct blitter_context_priv /* Depth stencil alpha state. */ void *dsa_write_depth_stencil; void *dsa_write_depth_keep_stencil; void *dsa_keep_depth_stencil; void *dsa_keep_depth_write_stencil; /* Vertex elements states. */ void *velem_state; void *velem_state_readbuf[4]; /**< X, XY, XYZ, XYZW */ + bool had_vs_inputs; /* Sampler state. */ void *sampler_state; void *sampler_state_linear; void *sampler_state_rect; void *sampler_state_rect_linear; /* Rasterizer state. */ void *rs_state, *rs_state_scissor, *rs_discard_state; @@ -567,27 +568,31 @@ static void blitter_check_saved_vertex_states(struct blitter_context_priv *ctx) assert(ctx->base.saved_rs_state != INVALID_PTR); } void util_blitter_restore_vertex_states(struct blitter_context *blitter) { struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; struct pipe_context *pipe = ctx->base.pipe; unsigned i; /* Vertex buffer. */ - pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, - &ctx->base.saved_vertex_buffer); + if (ctx->had_vs_inputs) { + pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, + &ctx->base.saved_vertex_buffer); + } pipe_vertex_buffer_unreference(&ctx->base.saved_vertex_buffer); /* Vertex elements. */ - pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state); + if (ctx->had_vs_inputs) + pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state); ctx->base.saved_velem_state = INVALID_PTR; + ctx->had_vs_inputs = false; /* Vertex shader. */ pipe->bind_vs_state(pipe, ctx->base.saved_vs); ctx->base.saved_vs = INVALID_PTR; /* Geometry shader. */ if (ctx->has_geometry_shader) { pipe->bind_gs_state(pipe, ctx->base.saved_gs); ctx->base.saved_gs = INVALID_PTR; } @@ -1240,46 +1245,54 @@ static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx, if (ctx->has_tessellation) { pipe->bind_tcs_state(pipe, NULL); pipe->bind_tes_state(pipe, NULL); } if (ctx->has_stream_out) pipe->set_stream_output_targets(pipe, 0, NULL, NULL); } static void blitter_draw(struct blitter_context_priv *ctx, int x1, int y1, int x2, int y2, float depth, - unsigned num_instances) + unsigned num_instances, + enum blitter_attrib_type type) { struct pipe_context *pipe = ctx->base.pipe; struct pipe_vertex_buffer vb = {0}; blitter_set_rectangle(ctx, x1, y1, x2, y2, depth); - if (ctx->has_vertex_id) { - vb.stride = 4 * sizeof(float); + /* NONE doesn't have any GENERIC input. If VertexID is supported, POSITION + * is generated from VertexID, so there are no vertex attributes. + */ + if (!ctx->has_vertex_id || type != UTIL_BLITTER_ATTRIB_NONE) { + if (ctx->has_vertex_id) { + vb.stride = 4 * sizeof(float); - /* Align vertices to a cache line. */ - u_upload_data(pipe->stream_uploader, 0, sizeof(ctx->vertices_nopos), 64, - ctx->vertices_nopos, &vb.buffer_offset, - &vb.buffer.resource); - } else { - vb.stride = 8 * sizeof(float); + /* Align vertices to a cache line. */ + u_upload_data(pipe->stream_uploader, 0, sizeof(ctx->vertices_nopos), 64, + ctx->vertices_nopos, &vb.buffer_offset, + &vb.buffer.resource); + } else { + vb.stride = 8 * sizeof(float); + + /* Align vertices to a cache line. */ + u_upload_data(pipe->stream_uploader, 0, sizeof(ctx->vertices), 64, + ctx->vertices, &vb.buffer_offset, &vb.buffer.resource); + } + + if (!vb.buffer.resource) + return; + u_upload_unmap(pipe->stream_uploader); - /* Align vertices to a cache line. */ - u_upload_data(pipe->stream_uploader, 0, sizeof(ctx->vertices), 64, - ctx->vertices, &vb.buffer_offset, &vb.buffer.resource); + pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb); } - if (!vb.buffer.resource) - return; - u_upload_unmap(pipe->stream_uploader); - pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb); util_draw_arrays_instanced(pipe, PIPE_PRIM_TRIANGLE_FAN, 0, 4, 0, num_instances); pipe_resource_reference(&vb.buffer.resource, NULL); } void util_blitter_draw_rectangle(struct blitter_context *blitter, int x1, int y1, int x2, int y2, float depth, unsigned num_instances, enum blitter_attrib_type type, const union blitter_attrib *attrib) @@ -1308,21 +1321,21 @@ void util_blitter_draw_rectangle(struct blitter_context *blitter, case UTIL_BLITTER_ATTRIB_TEXCOORD_XY: if (ctx->has_vertex_id) set_texcoords_in_vertices(attrib, &ctx->vertices_nopos[0][0], 4); else set_texcoords_in_vertices(attrib, &ctx->vertices[0][1][0], 8); break; default:; } - blitter_draw(ctx, x1, y1, x2, y2, depth, num_instances); + blitter_draw(ctx, x1, y1, x2, y2, depth, num_instances, type); } static void *get_clear_blend_state(struct blitter_context_priv *ctx, unsigned clear_buffers) { struct pipe_context *pipe = ctx->base.pipe; int index; clear_buffers &= PIPE_CLEAR_COLOR; @@ -1391,36 +1404,40 @@ static void util_blitter_clear_custom(struct blitter_context *blitter, unsigned width, unsigned height, unsigned num_layers, unsigned clear_buffers, const union pipe_color_union *color, double depth, unsigned stencil, void *custom_blend, void *custom_dsa) { struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; struct pipe_context *pipe = ctx->base.pipe; struct pipe_stencil_ref sr = { { 0 } }; + bool pass_generic = (clear_buffers & PIPE_CLEAR_COLOR) != 0; assert(ctx->has_layered || num_layers <= 1); util_blitter_common_clear_setup(blitter, clear_buffers, custom_blend, custom_dsa); sr.ref_value[0] = stencil & 0xff; pipe->set_stencil_ref(pipe, &sr); - pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + if (!ctx->has_vertex_id || pass_generic) { + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + ctx->had_vs_inputs = true; + } + bind_fs_write_all_cbufs(ctx); union blitter_attrib attrib; memcpy(attrib.color, color->ui, sizeof(color->ui)); - bool pass_generic = (clear_buffers & PIPE_CLEAR_COLOR) != 0; enum blitter_attrib_type type = pass_generic ? UTIL_BLITTER_ATTRIB_COLOR : UTIL_BLITTER_ATTRIB_NONE; if (num_layers > 1 && ctx->has_layered) { blitter_set_common_draw_rect_state(ctx, false, true, pass_generic); blitter->draw_rectangle(blitter, 0, 0, width, height, (float) depth, num_layers, type, &attrib); } else { blitter_set_common_draw_rect_state(ctx, false, false, pass_generic); blitter->draw_rectangle(blitter, 0, 0, width, height, (float) depth, @@ -1660,21 +1677,21 @@ blitter_draw_tex(struct blitter_context_priv *ctx, util_map_texcoords2d_onto_cubemap((unsigned)layer % 6, /* pointer, stride in floats */ &face_coord[0][0], 2, &ctx->vertices[0][1][0], 8, false); for (unsigned i = 0; i < 4; i++) ctx->vertices[i][1][3] = coord.texcoord.w; } /* Cubemaps don't use draw_rectangle. */ - blitter_draw(ctx, dst_x1, dst_y1, dst_x2, dst_y2, 0, 1); + blitter_draw(ctx, dst_x1, dst_y1, dst_x2, dst_y2, 0, 1, type); } else { ctx->base.draw_rectangle(&ctx->base, dst_x1, dst_y1, dst_x2, dst_y2, 0, 1, type, &coord); } } static void do_blits(struct blitter_context_priv *ctx, struct pipe_surface *dst, const struct pipe_box *dstbox, struct pipe_sampler_view *src, @@ -1968,20 +1985,22 @@ void util_blitter_blit_generic(struct blitter_context *blitter, 0, 1, &sampler_state); pipe_sampler_view_reference(&view, NULL); } else { pipe->set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, 1, &src); pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0, 1, &sampler_state); } pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + ctx->had_vs_inputs = true; + if (scissor) { pipe->set_scissor_states(pipe, 0, 1, scissor); } blitter_set_common_draw_rect_state(ctx, scissor != NULL, false, true); do_blits(ctx, dst, dstbox, src, src_width0, src_height0, srcbox, blit_depth || blit_stencil, use_txf); util_blitter_restore_vertex_states(blitter); @@ -2079,20 +2098,22 @@ void util_blitter_generate_mipmap(struct blitter_context *blitter, if (target == PIPE_TEXTURE_RECT) { sampler_state = ctx->sampler_state_rect_linear; } else { sampler_state = ctx->sampler_state_linear; } pipe->bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0, 1, &sampler_state); pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + ctx->had_vs_inputs = true; + blitter_set_common_draw_rect_state(ctx, false, false, true); for (src_level = base_level; src_level < last_level; src_level++) { struct pipe_box dstbox = {0}, srcbox = {0}; unsigned dst_level = src_level + 1; dstbox.width = u_minify(tex->width0, dst_level); dstbox.height = u_minify(tex->height0, dst_level); srcbox.width = u_minify(tex->width0, src_level); @@ -2154,21 +2175,23 @@ void util_blitter_clear_render_target(struct blitter_context *blitter, util_blitter_set_running_flag(blitter); blitter_check_saved_vertex_states(ctx); blitter_check_saved_fragment_states(ctx); blitter_check_saved_fb_state(ctx); blitter_disable_render_cond(ctx); /* bind states */ pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA][0]); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); bind_fs_write_one_cbuf(ctx); + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + ctx->had_vs_inputs = true; /* set a framebuffer state */ fb_state.width = dstsurf->width; fb_state.height = dstsurf->height; fb_state.nr_cbufs = 1; fb_state.cbufs[0] = dstsurf; fb_state.zsbuf = 0; pipe->set_framebuffer_state(pipe, &fb_state); pipe->set_sample_mask(pipe, ~0); @@ -2232,21 +2255,25 @@ void util_blitter_clear_depth_stencil(struct blitter_context *blitter, else if (clear_flags & PIPE_CLEAR_STENCIL) { sr.ref_value[0] = stencil & 0xff; pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil); pipe->set_stencil_ref(pipe, &sr); } else /* hmm that should be illegal probably, or make it a no-op somewhere */ pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); bind_fs_empty(ctx); - pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + + if (!ctx->has_vertex_id) { + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + ctx->had_vs_inputs = true; + } /* set a framebuffer state */ fb_state.width = dstsurf->width; fb_state.height = dstsurf->height; fb_state.nr_cbufs = 0; fb_state.cbufs[0] = 0; fb_state.zsbuf = dstsurf; pipe->set_framebuffer_state(pipe, &fb_state); pipe->set_sample_mask(pipe, ~0); @@ -2293,21 +2320,25 @@ void util_blitter_custom_depth_stencil(struct blitter_context *blitter, blitter_disable_render_cond(ctx); /* bind states */ pipe->bind_blend_state(pipe, cbsurf ? ctx->blend[PIPE_MASK_RGBA][0] : ctx->blend[0][0]); pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage); if (cbsurf) bind_fs_write_one_cbuf(ctx); else bind_fs_empty(ctx); - pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + + if (!ctx->has_vertex_id) { + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + ctx->had_vs_inputs = true; + } /* set a framebuffer state */ fb_state.width = zsurf->width; fb_state.height = zsurf->height; fb_state.nr_cbufs = 1; if (cbsurf) { fb_state.cbufs[0] = cbsurf; fb_state.nr_cbufs = 1; } else { fb_state.cbufs[0] = NULL; @@ -2369,20 +2400,22 @@ void util_blitter_copy_buffer(struct blitter_context *blitter, blitter_check_saved_vertex_states(ctx); blitter_disable_render_cond(ctx); vb.is_user_buffer = false; vb.buffer.resource = src; vb.buffer_offset = srcx; vb.stride = 4; pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb); pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf[0]); + ctx->had_vs_inputs = true; + bind_vs_pos_only(ctx, 1); if (ctx->has_geometry_shader) pipe->bind_gs_state(pipe, NULL); if (ctx->has_tessellation) { pipe->bind_tcs_state(pipe, NULL); pipe->bind_tes_state(pipe, NULL); } pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state); so_target = pipe->create_stream_output_target(pipe, dst, dstx, size); @@ -2436,20 +2469,22 @@ void util_blitter_clear_buffer(struct blitter_context *blitter, vb.stride = 0; util_blitter_set_running_flag(blitter); blitter_check_saved_vertex_states(ctx); blitter_disable_render_cond(ctx); pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb); pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf[num_channels-1]); + ctx->had_vs_inputs = true; + bind_vs_pos_only(ctx, num_channels); if (ctx->has_geometry_shader) pipe->bind_gs_state(pipe, NULL); if (ctx->has_tessellation) { pipe->bind_tcs_state(pipe, NULL); pipe->bind_tes_state(pipe, NULL); } pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state); so_target = pipe->create_stream_output_target(pipe, dst, offset, size); @@ -2482,21 +2517,24 @@ void util_blitter_custom_resolve_color(struct blitter_context *blitter, struct pipe_surface *srcsurf, *dstsurf, surf_tmpl; util_blitter_set_running_flag(blitter); blitter_check_saved_vertex_states(ctx); blitter_check_saved_fragment_states(ctx); blitter_disable_render_cond(ctx); /* bind states */ pipe->bind_blend_state(pipe, custom_blend); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); - pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + if (!ctx->has_vertex_id) { + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + ctx->had_vs_inputs = true; + } bind_fs_write_one_cbuf(ctx); pipe->set_sample_mask(pipe, sample_mask); memset(&surf_tmpl, 0, sizeof(surf_tmpl)); surf_tmpl.format = format; surf_tmpl.u.tex.level = dst_level; surf_tmpl.u.tex.first_layer = dst_layer; surf_tmpl.u.tex.last_layer = dst_layer; dstsurf = pipe->create_surface(pipe, dst, &surf_tmpl); @@ -2546,21 +2584,24 @@ void util_blitter_custom_color(struct blitter_context *blitter, blitter_check_saved_vertex_states(ctx); blitter_check_saved_fragment_states(ctx); blitter_check_saved_fb_state(ctx); blitter_disable_render_cond(ctx); /* bind states */ pipe->bind_blend_state(pipe, custom_blend ? custom_blend : ctx->blend[PIPE_MASK_RGBA][0]); pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil); bind_fs_write_one_cbuf(ctx); - pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + if (!ctx->has_vertex_id) { + pipe->bind_vertex_elements_state(pipe, ctx->velem_state); + ctx->had_vs_inputs = true; + } pipe->set_sample_mask(pipe, (1ull << MAX2(1, dstsurf->texture->nr_samples)) - 1); /* set a framebuffer state */ fb_state.width = dstsurf->width; fb_state.height = dstsurf->height; fb_state.nr_cbufs = 1; fb_state.cbufs[0] = dstsurf; fb_state.zsbuf = 0; pipe->set_framebuffer_state(pipe, &fb_state); pipe->set_sample_mask(pipe, ~0); diff --git a/src/gallium/drivers/radeon/r600_pipe_common.c b/src/gallium/drivers/radeon/r600_pipe_common.c index 3539803..f3bd181 100644 --- a/src/gallium/drivers/radeon/r600_pipe_common.c +++ b/src/gallium/drivers/radeon/r600_pipe_common.c @@ -206,80 +206,83 @@ void r600_gfx_wait_fence(struct r600_common_context *ctx, void r600_draw_rectangle(struct blitter_context *blitter, int x1, int y1, int x2, int y2, float depth, unsigned num_instances, enum blitter_attrib_type type, const union blitter_attrib *attrib) { struct r600_common_context *rctx = (struct r600_common_context*)util_blitter_get_pipe(blitter); struct pipe_viewport_state viewport; - struct pipe_resource *buf = NULL; - unsigned offset = 0; - float *vb; /* Some operations (like color resolve on r6xx) don't work * with the conventional primitive types. * One that works is PT_RECTLIST, which we use here. */ /* setup viewport */ int width = x2 - x1; int height = y2 - y1; viewport.scale[0] = width / 2.0; viewport.scale[1] = height / 2.0; viewport.scale[2] = 0; viewport.translate[0] = width / 2.0 + x1; viewport.translate[1] = height / 2.0 + y1; viewport.translate[2] = depth; rctx->b.set_viewport_states(&rctx->b, 0, 1, &viewport); - /* Upload vertices. The hw rectangle has only 3 vertices, - * The 4th one is derived from the first 3. - * The vertex specification should match u_blitter's vertex element state. */ - u_upload_alloc(rctx->b.stream_uploader, 0, sizeof(float) * 12, - rctx->screen->info.tcc_cache_line_size, - &offset, &buf, (void**)&vb); - if (!buf) - return; + if (type != UTIL_BLITTER_ATTRIB_NONE) { + struct pipe_vertex_buffer vbuffer = {}; + float *vb; - switch (type) { - case UTIL_BLITTER_ATTRIB_COLOR: - memcpy(vb, attrib->color, sizeof(float)*4); - memcpy(vb+4, attrib->color, sizeof(float)*4); - memcpy(vb+8, attrib->color, sizeof(float)*4); - break; - case UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW: - vb[2] = vb[6] = vb[10] = attrib->texcoord.z; - vb[3] = vb[7] = vb[11] = attrib->texcoord.w; - /* fall through */ - case UTIL_BLITTER_ATTRIB_TEXCOORD_XY: - vb[0] = attrib->texcoord.x1; - vb[1] = attrib->texcoord.y1; - vb[4] = attrib->texcoord.x2; - vb[5] = attrib->texcoord.y1; - vb[8] = attrib->texcoord.x2; - vb[9] = attrib->texcoord.y2; - break; - default:; /* Nothing to do. */ - } + vbuffer.stride = 4 * sizeof(float); /* vertex size */ + + /* Upload vertices. The hw rectangle has only 3 vertices, + * The 4th one is derived from the first 3. + * The vertex specification should match u_blitter's vertex + * element state. + */ + u_upload_alloc(rctx->b.stream_uploader, 0, vbuffer.stride * 3, + rctx->screen->info.tcc_cache_line_size, + &vbuffer.buffer_offset, + &vbuffer.buffer.resource, (void**)&vb); + if (!vbuffer.buffer.resource) + return; - /* draw */ - struct pipe_vertex_buffer vbuffer = {}; - vbuffer.buffer.resource = buf; - vbuffer.stride = 4 * sizeof(float); /* vertex size */ - vbuffer.buffer_offset = offset; + switch (type) { + case UTIL_BLITTER_ATTRIB_COLOR: + memcpy(vb, attrib->color, sizeof(float)*4); + memcpy(vb+4, attrib->color, sizeof(float)*4); + memcpy(vb+8, attrib->color, sizeof(float)*4); + break; + case UTIL_BLITTER_ATTRIB_TEXCOORD_XYZW: + vb[2] = vb[6] = vb[10] = attrib->texcoord.z; + vb[3] = vb[7] = vb[11] = attrib->texcoord.w; + /* fall through */ + case UTIL_BLITTER_ATTRIB_TEXCOORD_XY: + vb[0] = attrib->texcoord.x1; + vb[1] = attrib->texcoord.y1; + vb[4] = attrib->texcoord.x2; + vb[5] = attrib->texcoord.y1; + vb[8] = attrib->texcoord.x2; + vb[9] = attrib->texcoord.y2; + break; + default: + assert(0); + } + + rctx->b.set_vertex_buffers(&rctx->b, blitter->vb_slot, 1, &vbuffer); + pipe_resource_reference(&vbuffer.buffer.resource, NULL); + } - rctx->b.set_vertex_buffers(&rctx->b, blitter->vb_slot, 1, &vbuffer); util_draw_arrays_instanced(&rctx->b, R600_PRIM_RECTANGLE_LIST, 0, 3, 0, num_instances); - pipe_resource_reference(&buf, NULL); } static void r600_dma_emit_wait_idle(struct r600_common_context *rctx) { struct radeon_winsys_cs *cs = rctx->dma.cs; /* NOP waits for idle on Evergreen and later. */ if (rctx->chip_class >= CIK) radeon_emit(cs, 0x00000000); /* NOP */ else if (rctx->chip_class >= EVERGREEN) -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev