levels. This corresponds to GL's ``PATCH_DEFAULT_OUTER_LEVEL``.
* ``default_inner_level`` is the default value for the inner tessellation
levels. This corresponds to GL's ``PATCH_DEFAULT_INNER_LEVEL``.
+* ``set_patch_vertices`` sets the number of vertices per input patch
+ for tessellation.
* ``set_debug_callback`` sets the callback to be used for reporting
various debug messages, eventually reported via KHR_debug and
unsigned drawid_offset,
const struct pipe_draw_indirect_info *indirect,
const struct pipe_draw_start_count_bias *draws,
- unsigned num_draws);
+ unsigned num_draws,
+ uint8_t patch_vertices);
/*******************************************************************************
unsigned drawid_offset,
const struct pipe_draw_indirect_info *indirect,
const struct pipe_draw_start_count_bias *draws,
- unsigned num_draws)
+ unsigned num_draws,
+ uint8_t patch_vertices)
{
unsigned index_limit;
unsigned fpstate = util_fpstate_get();
draw->pt.user.drawid = drawid_offset;
draw->pt.user.increment_draw_id = use_info->increment_draw_id;
draw->pt.user.viewid = 0;
- draw->pt.vertices_per_patch = use_info->vertices_per_patch;
+ draw->pt.vertices_per_patch = patch_vertices;
if (0) {
for (unsigned i = 0; i < num_draws; i++)
pipe->set_tess_state(pipe, default_outer_level, default_inner_level);
}
+static void dd_context_set_patch_vertices(struct pipe_context *_pipe,
+ uint8_t patch_vertices)
+{
+ struct dd_context *dctx = dd_context(_pipe);
+ struct pipe_context *pipe = dctx->pipe;
+
+ pipe->set_patch_vertices(pipe, patch_vertices);
+}
+
static void dd_context_set_window_rectangles(struct pipe_context *_pipe,
bool include,
unsigned num_rectangles,
CTX_INIT(set_viewport_states);
CTX_INIT(set_sampler_views);
CTX_INIT(set_tess_state);
+ CTX_INIT(set_patch_vertices);
CTX_INIT(set_shader_buffers);
CTX_INIT(set_shader_images);
CTX_INIT(set_vertex_buffers);
{
}
+static void noop_set_patch_vertices(struct pipe_context *ctx,
+ uint8_t patch_vertices)
+{
+}
+
void noop_init_state_functions(struct pipe_context *ctx);
void noop_init_state_functions(struct pipe_context *ctx)
ctx->create_image_handle = noop_create_image_handle;
ctx->delete_image_handle = noop_delete_image_handle;
ctx->make_image_handle_resident = noop_make_image_handle_resident;
+ ctx->set_patch_vertices = noop_set_patch_vertices;
}
context->set_tess_state(context, default_outer_level, default_inner_level);
}
+static void
+trace_context_set_patch_vertices(struct pipe_context *_context,
+ uint8_t patch_vertices)
+{
+ struct trace_context *tr_context = trace_context(_context);
+ struct pipe_context *context = tr_context->pipe;
+
+ trace_dump_call_begin("pipe_context", "set_patch_vertices");
+ trace_dump_arg(ptr, context);
+ trace_dump_arg(uint, patch_vertices);
+ trace_dump_call_end();
+
+ context->set_patch_vertices(context, patch_vertices);
+}
static void trace_context_set_shader_buffers(struct pipe_context *_context,
enum pipe_shader_type shader,
TR_CTX_INIT(memory_barrier);
TR_CTX_INIT(resource_commit);
TR_CTX_INIT(set_tess_state);
+ TR_CTX_INIT(set_patch_vertices);
TR_CTX_INIT(set_shader_buffers);
TR_CTX_INIT(launch_grid);
TR_CTX_INIT(set_shader_images);
trace_dump_member(uint, state, start_instance);
trace_dump_member(uint, state, instance_count);
- trace_dump_member(uint, state, vertices_per_patch);
-
trace_dump_member(uint, state, min_index);
trace_dump_member(uint, state, max_index);
util_dump_member(stream, uint, state, start_instance);
util_dump_member(stream, uint, state, instance_count);
- util_dump_member(stream, uint, state, vertices_per_patch);
-
util_dump_member(stream, uint, state, min_index);
util_dump_member(stream, uint, state, max_index);
memcpy(p + 4, default_inner_level, 2 * sizeof(float));
}
+struct tc_patch_vertices {
+ struct tc_call_base base;
+ ubyte patch_vertices;
+};
+
+static uint16_t
+tc_call_set_patch_vertices(struct pipe_context *pipe, void *call, uint64_t *last)
+{
+ uint8_t patch_vertices = to_call(call, tc_patch_vertices)->patch_vertices;
+
+ pipe->set_patch_vertices(pipe, patch_vertices);
+ return call_size(tc_patch_vertices);
+}
+
+static void
+tc_set_patch_vertices(struct pipe_context *_pipe, uint8_t patch_vertices)
+{
+ struct threaded_context *tc = threaded_context(_pipe);
+
+ tc_add_call(tc, TC_CALL_set_patch_vertices,
+ tc_patch_vertices)->patch_vertices = patch_vertices;
+}
+
struct tc_constant_buffer_base {
struct tc_call_base base;
ubyte shader, index;
info->index_bounds_valid = false;
info->take_index_buffer_ownership = false;
info->index_bias_varies = false;
+ info->_pad = 0;
/* This shouldn't be set when merging single draws. */
info->increment_draw_id = false;
- if (info->mode != PIPE_PRIM_PATCHES)
- info->vertices_per_patch = 0;
-
if (info->index_size) {
if (!info->primitive_restart)
info->restart_index = 0;
CTX_INIT(set_window_rectangles);
CTX_INIT(set_sampler_views);
CTX_INIT(set_tess_state);
+ CTX_INIT(set_patch_vertices);
CTX_INIT(set_shader_buffers);
CTX_INIT(set_shader_images);
CTX_INIT(set_vertex_buffers);
CALL(bind_sampler_states)
CALL(set_framebuffer_state)
CALL(set_tess_state)
+CALL(set_patch_vertices)
CALL(set_constant_buffer)
CALL(set_inlinable_constants)
CALL(set_sample_locations)
enum pipe_prim_type prim_mode:8;
bool prim_is_points_or_lines;
uint8_t vertices_per_patch;
+ uint8_t patch_vertices;
bool window_space_position;
}
if (info->mode == PIPE_PRIM_PATCHES &&
- ice->state.vertices_per_patch != info->vertices_per_patch) {
- ice->state.vertices_per_patch = info->vertices_per_patch;
+ ice->state.vertices_per_patch != ice->state.patch_vertices) {
+ ice->state.vertices_per_patch = ice->state.patch_vertices;
if (screen->devinfo.ver == 8)
ice->state.dirty |= CROCUS_DIRTY_GEN8_VF_TOPOLOGY;
}
static void
+crocus_set_patch_vertices(struct pipe_context *ctx, uint8_t patch_vertices)
+{
+ struct crocus_context *ice = (struct crocus_context *) ctx;
+
+ ice->state.patch_vertices = patch_vertices;
+}
+
+static void
crocus_surface_destroy(struct pipe_context *ctx, struct pipe_surface *p_surf)
{
struct crocus_surface *surf = (void *) p_surf;
if (dirty & CROCUS_DIRTY_GEN8_VF_TOPOLOGY) {
crocus_emit_cmd(batch, GENX(3DSTATE_VF_TOPOLOGY), topo) {
topo.PrimitiveTopologyType =
- translate_prim_type(draw->mode, draw->vertices_per_patch);
+ translate_prim_type(draw->mode, ice->state.patch_vertices);
}
}
#endif
prim.PredicateEnable = use_predicate;
#endif
- prim.PrimitiveTopologyType = translate_prim_type(ice->state.prim_mode, draw->vertices_per_patch);
+ prim.PrimitiveTopologyType = translate_prim_type(ice->state.prim_mode, ice->state.patch_vertices);
if (indirect) {
// XXX Probably have to do something for gen6 here?
#if GFX_VER >= 7
ctx->set_shader_images = crocus_set_shader_images;
ctx->set_sampler_views = crocus_set_sampler_views;
ctx->set_tess_state = crocus_set_tess_state;
+ ctx->set_patch_vertices = crocus_set_patch_vertices;
ctx->set_framebuffer_state = crocus_set_framebuffer_state;
ctx->set_polygon_stipple = crocus_set_polygon_stipple;
ctx->set_sample_mask = crocus_set_sample_mask;
* size is dwords, since that's what LDG/STG use.
*/
unsigned num_vertices = emit->hs
- ? emit->info->vertices_per_patch
+ ? emit->patch_vertices
: emit->gs->shader->nir->info.gs.vertices_in;
uint32_t vs_params[4] = {
uint32_t hs_params[4] = {
emit->vs->output_size * num_vertices * 4, /* vs primitive stride */
emit->vs->output_size * 4, /* vs vertex stride */
- emit->hs->output_size, emit->info->vertices_per_patch};
+ emit->hs->output_size, emit->patch_vertices};
emit_stage_tess_consts(constobj, emit->hs, hs_params,
ARRAY_SIZE(hs_params));
.sprite_coord_enable = ctx->rasterizer->sprite_coord_enable,
.sprite_coord_mode = ctx->rasterizer->sprite_coord_mode,
.primitive_restart = info->primitive_restart && info->index_size,
+ .patch_vertices = ctx->patch_vertices,
};
if (!(ctx->prog.vs && ctx->prog.fs))
unreachable("bad tessmode");
}
- draw0.prim_type = DI_PT_PATCHES0 + info->vertices_per_patch;
+ draw0.prim_type = DI_PT_PATCHES0 + ctx->patch_vertices;
draw0.tess_enable = true;
const unsigned max_count = 2048;
* limit. But in the indirect-draw case we must assume the worst.
*/
if (indirect && indirect->buffer) {
- count = ALIGN_NPOT(max_count, info->vertices_per_patch);
+ count = ALIGN_NPOT(max_count, ctx->patch_vertices);
} else {
count = MIN2(max_count, draw->count);
- count = ALIGN_NPOT(count, info->vertices_per_patch);
+ count = ALIGN_NPOT(count, ctx->patch_vertices);
}
OUT_PKT7(ring, CP_SET_SUBDRAW_SIZE, 1);
bool sprite_coord_mode;
bool rasterflat;
bool primitive_restart;
+ uint8_t patch_vertices;
/* cached to avoid repeated lookups: */
const struct fd6_program_state *prog;
struct list_head acc_active_queries dt;
/*@}*/
+ uint8_t patch_vertices;
+
/* Whether we need to recheck the active_queries list next
* fd_batch_update_queries().
*/
}
static void
+fd_set_patch_vertices(struct pipe_context *pctx, uint8_t patch_vertices) in_dt
+{
+ struct fd_context *ctx = fd_context(pctx);
+
+ ctx->patch_vertices = patch_vertices;
+}
+
+static void
fd_vs_state_bind(struct pipe_context *pctx, void *hwcso) in_dt
{
struct fd_context *ctx = fd_context(pctx);
pctx->bind_tes_state = fd_tes_state_bind;
pctx->bind_gs_state = fd_gs_state_bind;
pctx->bind_fs_state = fd_fs_state_bind;
+ pctx->set_patch_vertices = fd_set_patch_vertices;
ctx->solid_prog.fs = assemble_tgsi(pctx, solid_fs, true);
ctx->solid_prog.vs = assemble_tgsi(pctx, solid_vs, false);
/*
* Do the drawing
*/
- draw_vbo(i915->draw, info, drawid_offset, NULL, draws, num_draws);
+ draw_vbo(i915->draw, info, drawid_offset, NULL, draws, num_draws, 0);
/*
* unmap vertex/index buffers
/** Bitfield of which vertex buffers are bound (non-null). */
uint64_t bound_vertex_buffers;
+ uint8_t patch_vertices;
bool primitive_restart;
unsigned cut_index;
enum pipe_prim_type prim_mode:8;
}
if (info->mode == PIPE_PRIM_PATCHES &&
- ice->state.vertices_per_patch != info->vertices_per_patch) {
- ice->state.vertices_per_patch = info->vertices_per_patch;
+ ice->state.vertices_per_patch != ice->state.patch_vertices) {
+ ice->state.vertices_per_patch = ice->state.patch_vertices;
ice->state.dirty |= IRIS_DIRTY_VF_TOPOLOGY;
/* 8_PATCH TCS needs this for key->input_vertices */
}
static void
+iris_set_patch_vertices(struct pipe_context *ctx, uint8_t patch_vertices)
+{
+ struct iris_context *ice = (struct iris_context *) ctx;
+
+ ice->state.patch_vertices = patch_vertices;
+}
+
+static void
iris_surface_destroy(struct pipe_context *ctx, struct pipe_surface *p_surf)
{
struct iris_surface *surf = (void *) p_surf;
if (dirty & IRIS_DIRTY_VF_TOPOLOGY) {
iris_emit_cmd(batch, GENX(3DSTATE_VF_TOPOLOGY), topo) {
topo.PrimitiveTopologyType =
- translate_prim_type(draw->mode, draw->vertices_per_patch);
+ translate_prim_type(draw->mode, ice->state.vertices_per_patch);
}
}
ctx->set_compute_resources = iris_set_compute_resources;
ctx->set_global_binding = iris_set_global_binding;
ctx->set_tess_state = iris_set_tess_state;
+ ctx->set_patch_vertices = iris_set_patch_vertices;
ctx->set_framebuffer_state = iris_set_framebuffer_state;
ctx->set_polygon_stipple = iris_set_polygon_stipple;
ctx->set_sample_mask = iris_set_sample_mask;
/** Vertex format */
struct vertex_info vertex_info;
+
+ uint8_t patch_vertices;
/** Which vertex shader output slot contains color */
int8_t color_slot[2];
!lp->queries_disabled);
/* draw! */
- draw_vbo(draw, info, drawid_offset, indirect, draws, num_draws);
+ draw_vbo(draw, info, drawid_offset, indirect, draws, num_draws,
+ lp->patch_vertices);
/*
* unmap vertex/index buffers
draw_set_tess_state(llvmpipe->draw, default_outer_level, default_inner_level);
}
+static void
+llvmpipe_set_patch_vertices(struct pipe_context *pipe, uint8_t patch_vertices)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+
+ llvmpipe->patch_vertices = patch_vertices;
+}
+
void
llvmpipe_init_tess_funcs(struct llvmpipe_context *llvmpipe)
{
llvmpipe->pipe.delete_tes_state = llvmpipe_delete_tes_state;
llvmpipe->pipe.set_tess_state = llvmpipe_set_tess_state;
+ llvmpipe->pipe.set_patch_vertices = llvmpipe_set_patch_vertices;
}
draw_set_indexes(draw, NULL, 0, 0);
}
- draw_vbo(draw, info, drawid_offset, NULL, draw_one, 1);
+ draw_vbo(draw, info, drawid_offset, NULL, draw_one, 1, 0);
draw_flush(draw);
if (info->index_size && transferi)
float default_tess_outer[4];
float default_tess_inner[2];
+ uint8_t patch_vertices;
bool vbo_push_hint;
}
static void
+nvc0_set_patch_vertices(struct pipe_context *pipe, uint8_t patch_vertices)
+{
+ struct nvc0_context *nvc0 = nvc0_context(pipe);
+
+ nvc0->patch_vertices = patch_vertices;
+}
+
+static void
nvc0_set_vertex_buffers(struct pipe_context *pipe,
unsigned start_slot, unsigned count,
unsigned unbind_num_trailing_slots,
pipe->set_viewport_states = nvc0_set_viewport_states;
pipe->set_window_rectangles = nvc0_set_window_rectangles;
pipe->set_tess_state = nvc0_set_tess_state;
+ pipe->set_patch_vertices = nvc0_set_patch_vertices;
pipe->create_vertex_elements_state = nvc0_vertex_state_create;
pipe->delete_vertex_elements_state = nvc0_vertex_state_delete;
}
if (info->mode == PIPE_PRIM_PATCHES &&
- nvc0->state.patch_vertices != info->vertices_per_patch) {
- nvc0->state.patch_vertices = info->vertices_per_patch;
+ nvc0->state.patch_vertices != nvc0->patch_vertices) {
+ nvc0->state.patch_vertices = nvc0->patch_vertices;
PUSH_SPACE(push, 1);
IMMED_NVC0(push, NVC0_3D(PATCH_VERTICES), nvc0->state.patch_vertices);
}
r300_update_derived_state(r300);
- draw_vbo(r300->draw, info, drawid_offset, NULL, &draw, 1);
+ draw_vbo(r300->draw, info, drawid_offset, NULL, &draw, 1, 0);
draw_flush(r300->draw);
}
rctx->driver_consts[PIPE_SHADER_TESS_CTRL].tcs_default_levels_dirty = true;
}
+static void evergreen_set_patch_vertices(struct pipe_context *ctx, uint8_t patch_vertices)
+{
+ struct r600_context *rctx = (struct r600_context *)ctx;
+
+ rctx->patch_vertices = patch_vertices;
+}
+
static void evergreen_setup_immed_buffer(struct r600_context *rctx,
struct r600_image_view *rview,
enum pipe_format pformat)
rctx->b.b.set_polygon_stipple = evergreen_set_polygon_stipple;
rctx->b.b.set_min_samples = evergreen_set_min_samples;
rctx->b.b.set_tess_state = evergreen_set_tess_state;
+ rctx->b.b.set_patch_vertices = evergreen_set_patch_vertices;
rctx->b.b.set_hw_atomic_buffers = evergreen_set_hw_atomic_buffers;
rctx->b.b.set_shader_images = evergreen_set_shader_images;
rctx->b.b.set_shader_buffers = evergreen_set_shader_buffers;
struct pipe_constant_buffer constbuf = {0};
struct r600_pipe_shader_selector *tcs = rctx->tcs_shader ? rctx->tcs_shader : rctx->tes_shader;
struct r600_pipe_shader_selector *ls = rctx->vs_shader;
- unsigned num_tcs_input_cp = info->vertices_per_patch;
+ unsigned num_tcs_input_cp = rctx->patch_vertices;
unsigned num_tcs_outputs;
unsigned num_tcs_output_cp;
unsigned num_tcs_patch_outputs;
num_output_cp = rctx->tcs_shader ?
rctx->tcs_shader->info.properties[TGSI_PROPERTY_TCS_VERTICES_OUT] :
- info->vertices_per_patch;
+ rctx->patch_vertices;
return S_028B58_NUM_PATCHES(num_patches) |
- S_028B58_HS_NUM_INPUT_CP(info->vertices_per_patch) |
+ S_028B58_HS_NUM_INPUT_CP(rctx->patch_vertices) |
S_028B58_HS_NUM_OUTPUT_CP(num_output_cp);
}
struct r600_resource *trace_buf;
unsigned trace_id;
+ uint8_t patch_vertices;
bool cmd_buf_is_compute;
struct pipe_resource *append_fence;
uint32_t append_fence_id;
bool compute_image_sgprs_dirty;
bool vs_uses_base_instance;
bool vs_uses_draw_id;
+ uint8_t patch_vertices;
/* shader descriptors */
struct si_descriptors descriptors[SI_NUM_DESCS];
si_set_internal_const_buffer(sctx, SI_HS_CONST_DEFAULT_TESS_LEVELS, &cb);
}
+static void si_set_patch_vertices(struct pipe_context *ctx, uint8_t patch_vertices)
+{
+ struct si_context *sctx = (struct si_context *)ctx;
+
+ sctx->patch_vertices = patch_vertices;
+}
+
static void si_texture_barrier(struct pipe_context *ctx, unsigned flags)
{
struct si_context *sctx = (struct si_context *)ctx;
sctx->b.texture_barrier = si_texture_barrier;
sctx->b.set_min_samples = si_set_min_samples;
sctx->b.set_tess_state = si_set_tess_state;
+ sctx->b.set_patch_vertices = si_set_patch_vertices;
sctx->b.set_active_query_state = si_set_active_query_state;
}
si_emit_rasterizer_prim_state<GFX_VERSION, HAS_TESS, HAS_GS, NGG>(sctx);
if (HAS_TESS)
- si_emit_derived_tess_state(sctx, info->vertices_per_patch, &num_patches);
+ si_emit_derived_tess_state(sctx, sctx->patch_vertices, &num_patches);
/* Emit state atoms. */
unsigned mask = sctx->dirty_atoms & ~skip_atom_mask;
/* Emit draw states. */
si_emit_vs_state<GFX_VERSION, HAS_TESS, HAS_GS, NGG>(sctx, info->index_size);
si_emit_draw_registers<GFX_VERSION, HAS_TESS, HAS_GS, NGG>
- (sctx, indirect, prim, num_patches, instance_count, info->vertices_per_patch,
- primitive_restart, info->restart_index, min_vertex_count);
+ (sctx, indirect, prim, num_patches, instance_count, sctx->patch_vertices, primitive_restart,
+ info->restart_index, min_vertex_count);
}
static bool si_all_vs_resources_read_only(struct si_context *sctx, struct pipe_resource *indexbuf)
/* The rarely occuring tcs == NULL case is not optimized. */
bool same_patch_vertices =
GFX_VERSION >= GFX9 &&
- tcs && info->vertices_per_patch == tcs->info.base.tess.tcs_vertices_out;
+ tcs && sctx->patch_vertices == tcs->info.base.tess.tcs_vertices_out;
if (sctx->same_patch_vertices != same_patch_vertices) {
sctx->same_patch_vertices = same_patch_vertices;
* function TCS.
*/
bool ls_vgpr_fix =
- tcs && info->vertices_per_patch > tcs->info.base.tess.tcs_vertices_out;
+ tcs && sctx->patch_vertices > tcs->info.base.tess.tcs_vertices_out;
if (ls_vgpr_fix != sctx->ls_vgpr_fix) {
sctx->ls_vgpr_fix = ls_vgpr_fix;
sp->active_statistics_queries > 0);
/* draw! */
- draw_vbo(draw, info, drawid_offset, indirect, draws, num_draws);
+ draw_vbo(draw, info, drawid_offset, indirect, draws, num_draws, 0);
/* unmap vertex/index buffers - will cause draw module to flush */
for (i = 0; i < sp->num_vertex_buffers; i++) {
boolean render_condition;
boolean disable_rasterizer; /* Set if to disable rasterization */
+ uint8_t patch_vertices;
struct {
struct svga_tcs_shader *passthrough_tcs;
gen_prim, index_offset, count,
info->start_instance,
info->instance_count,
- info->vertices_per_patch);
+ hwtnl->svga->patch_vertices);
pipe_resource_reference(&index_buffer, NULL);
}
else {
gen_nr,
info->start_instance,
info->instance_count,
- info->vertices_per_patch);
+ hwtnl->svga->patch_vertices);
}
if (gen_buf) {
unsigned hw_count;
range.primType = svga_translate_prim(info->mode, 12, &hw_count,
- info->vertices_per_patch);
+ svga->patch_vertices);
range.primitiveCount = 0;
range.indexArray.surfaceId = SVGA3D_INVALID_ID;
range.indexArray.offset = 0;
unsigned hw_count;
range.primType = svga_translate_prim(info->mode, 12, &hw_count,
- info->vertices_per_patch);
+ svga->patch_vertices);
range.primitiveCount = 0; /* specified in indirect buffer */
range.indexArray.surfaceId = SVGA3D_INVALID_ID;
range.indexArray.offset = 0;
svga->dirty |= SVGA_NEW_VS_CONSTS;
}
- if (svga->curr.vertices_per_patch != info->vertices_per_patch) {
- svga->curr.vertices_per_patch = info->vertices_per_patch;
+ if (svga->curr.vertices_per_patch != svga->patch_vertices) {
+ svga->curr.vertices_per_patch = svga->patch_vertices;
/* If input patch size changes, we need to notifiy the TCS
* code to reevaluate the shader variant since the
else {
ret = retry_draw_arrays(svga, info->mode, draws[0].start, count,
info->start_instance, info->instance_count,
- info->vertices_per_patch);
+ svga->patch_vertices);
}
}
}
+static void
+svga_set_patch_vertices(struct pipe_context *pipe, uint8_t patch_vertices)
+{
+ struct svga_context *svga = svga_context(pipe);
+
+ svga->patch_vertices = patch_vertices;
+}
+
+
static void *
svga_create_tcs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
svga_init_ts_functions(struct svga_context *svga)
{
svga->pipe.set_tess_state = svga_set_tess_state;
+ svga->pipe.set_patch_vertices = svga_set_patch_vertices;
svga->pipe.create_tcs_state = svga_create_tcs_state;
svga->pipe.bind_tcs_state = svga_bind_tcs_state;
svga->pipe.delete_tcs_state = svga_delete_tcs_state;
svga->curr.constbufs[PIPE_SHADER_VERTEX][i].buffer->width0);
}
- draw_vbo(draw, info, drawid_offset, indirect, draw_one, 1);
+ draw_vbo(draw, info, drawid_offset, indirect, draw_one, 1,
+ svga->patch_vertices);
draw_flush(svga->swtnl.draw);
SWR_TILE_INTERFACE tileApi;
uint32_t max_draws_in_flight;
+ uint8_t patch_vertices;
};
static INLINE struct swr_context *
// trick copied from softpipe to modify const struct *info
memcpy(&resolved_info, (void*)info, sizeof(struct pipe_draw_info));
resolved_draw.start = draws[0].start;
- resolved_draw.count = ctx->so_primCounter * resolved_info.vertices_per_patch;
+ resolved_draw.count = ctx->so_primCounter * ctx->patch_vertices;
resolved_info.max_index = resolved_draw.count - 1;
info = &resolved_info;
indirect = NULL;
if (info->index_size)
ctx->api.pfnSwrDrawIndexedInstanced(ctx->swrContext,
- swr_convert_prim_topology(info->mode, info->vertices_per_patch),
+ swr_convert_prim_topology(info->mode, ctx->patch_vertices),
draws[0].count,
info->instance_count,
draws[0].start,
info->start_instance);
else
ctx->api.pfnSwrDrawInstanced(ctx->swrContext,
- swr_convert_prim_topology(info->mode, info->vertices_per_patch),
+ swr_convert_prim_topology(info->mode, ctx->patch_vertices),
draws[0].count,
info->instance_count,
draws[0].start,
SWR_NEW_SAMPLER |
SWR_NEW_SAMPLER_VIEW)) {
if (ctx->tcs) {
- ctx->tcs->vertices_per_patch = p_draw_info->vertices_per_patch;
+ ctx->tcs->vertices_per_patch = ctx->patch_vertices;
swr_jit_tcs_key key;
swr_generate_tcs_key(key, ctx, ctx->tcs);
swr->dirty |= SWR_NEW_SO;
}
+static void
+swr_set_patch_vertices(struct pipe_context *pipe, uint8_t patch_vertices)
+{
+ struct swr_context *swr = swr_context(pipe);
+
+ swr->patch_vertices = patch_vertices;
+}
+
void
swr_state_init(struct pipe_context *pipe)
pipe->create_stream_output_target = swr_create_so_target;
pipe->stream_output_target_destroy = swr_destroy_so_target;
pipe->set_stream_output_targets = swr_set_so_targets;
+
+ pipe->set_patch_vertices = swr_set_patch_vertices;
}
virgl_encode_set_tess_state(vctx, default_outer_level, default_inner_level);
}
+static void virgl_set_patch_vertices(struct pipe_context *ctx, uint8_t patch_vertices)
+{
+ struct virgl_context *vctx = virgl_context(ctx);
+
+ vctx->patch_vertices = patch_vertices;
+}
+
static void virgl_resource_copy_region(struct pipe_context *ctx,
struct pipe_resource *dst,
unsigned dst_level,
vctx->base.set_constant_buffer = virgl_set_constant_buffer;
vctx->base.set_tess_state = virgl_set_tess_state;
+ vctx->base.set_patch_vertices = virgl_set_patch_vertices;
vctx->base.create_vs_state = virgl_create_vs_state;
vctx->base.create_tcs_state = virgl_create_tcs_state;
vctx->base.create_tes_state = virgl_create_tes_state;
struct virgl_staging_mgr staging;
bool encoded_transfers;
bool supports_staging;
+ uint8_t patch_vertices;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
unsigned num_vertex_buffers;
else
virgl_encoder_write_dword(ctx->cbuf, 0);
if (length >= VIRGL_DRAW_VBO_SIZE_TESS) {
- virgl_encoder_write_dword(ctx->cbuf, info->vertices_per_patch); /* vertices per patch */
+ virgl_encoder_write_dword(ctx->cbuf, ctx->patch_vertices); /* vertices per patch */
virgl_encoder_write_dword(ctx->cbuf, drawid_offset); /* drawid */
}
if (length == VIRGL_DRAW_VBO_SIZE_INDIRECT) {
memcpy(&ctx->default_outer_level, default_outer_level, sizeof(ctx->default_outer_level));
}
+static void
+zink_set_patch_vertices(struct pipe_context *pctx, uint8_t patch_vertices)
+{
+ struct zink_context *ctx = zink_context(pctx);
+ ctx->gfx_pipeline_state.patch_vertices = patch_vertices;
+}
+
static uint32_t
hash_render_pass_state(const void *key)
{
ctx->base.set_clip_state = zink_set_clip_state;
ctx->base.set_blend_color = zink_set_blend_color;
ctx->base.set_tess_state = zink_set_tess_state;
+ ctx->base.set_patch_vertices = zink_set_patch_vertices;
ctx->base.set_sample_mask = zink_set_sample_mask;
update_barriers(ctx, false);
- if (ctx->gfx_pipeline_state.vertices_per_patch != dinfo->vertices_per_patch)
+ if (ctx->gfx_pipeline_state.vertices_per_patch != ctx->gfx_pipeline_state.patch_vertices)
ctx->gfx_pipeline_state.dirty = true;
bool drawid_broken = ctx->drawid_broken;
ctx->drawid_broken = false;
(HAS_MULTIDRAW && num_draws > 1 && !dinfo->increment_draw_id));
if (drawid_broken != ctx->drawid_broken)
ctx->dirty_shader_stages |= BITFIELD_BIT(PIPE_SHADER_VERTEX);
- ctx->gfx_pipeline_state.vertices_per_patch = dinfo->vertices_per_patch;
+ ctx->gfx_pipeline_state.vertices_per_patch = ctx->gfx_pipeline_state.patch_vertices;
if (ctx->rast_state->base.point_quad_rasterization &&
ctx->gfx_prim_mode != mode) {
if (ctx->gfx_prim_mode == PIPE_PRIM_POINTS || mode == PIPE_PRIM_POINTS)
VkPipeline pipeline;
enum pipe_prim_type mode : 8;
+
+ uint8_t patch_vertices;
};
struct zink_compute_pipeline_state {
int num_viewports;
struct pipe_viewport_state viewports[16];
+ uint8_t patch_vertices;
ubyte index_size;
unsigned index_offset;
struct pipe_resource *index_buffer;
if (pipeline->graphics_create_info.pTessellationState) {
if (!dynamic_states[conv_dynamic_state_idx(VK_DYNAMIC_STATE_PATCH_CONTROL_POINTS_EXT)]) {
const VkPipelineTessellationStateCreateInfo *ts = pipeline->graphics_create_info.pTessellationState;
- state->info.vertices_per_patch = ts->patchControlPoints;
+ state->patch_vertices = ts->patchControlPoints;
}
} else
- state->info.vertices_per_patch = 0;
+ state->patch_vertices = 0;
if (pipeline->graphics_create_info.pViewportState) {
const VkPipelineViewportStateCreateInfo *vpi= pipeline->graphics_create_info.pViewportState;
if (cmd->u.draw.draw_count > 1)
state->info.increment_draw_id = true;
+ state->pctx->set_patch_vertices(state->pctx, state->patch_vertices);
state->pctx->draw_vbo(state->pctx, &state->info, 0, NULL, cmd->u.draw.draws, cmd->u.draw.draw_count);
}
cmd->u.draw_indexed.calc_start = false;
}
state->info.index_bias_varies = cmd->u.draw_indexed.vertex_offset_changes;
+ state->pctx->set_patch_vertices(state->pctx, state->patch_vertices);
state->pctx->draw_vbo(state->pctx, &state->info, 0, NULL, cmd->u.draw_indexed.draws, cmd->u.draw_indexed.draw_count);
}
state->indirect_info.buffer = cmd->u.draw_indirect.buffer->bo;
state->info.view_mask = subpass->view_mask;
+ state->pctx->set_patch_vertices(state->pctx, state->patch_vertices);
state->pctx->draw_vbo(state->pctx, &state->info, 0, &state->indirect_info, &draw, 1);
}
state->indirect_info.indirect_draw_count = cmd->u.draw_indirect_count.count_buffer->bo;
state->info.view_mask = subpass->view_mask;
+ state->pctx->set_patch_vertices(state->pctx, state->patch_vertices);
state->pctx->draw_vbo(state->pctx, &state->info, 0, &state->indirect_info, &draw, 1);
}
draw.count /= cmd->u.draw_indirect_byte_count.vertex_stride;
state->info.view_mask = subpass->view_mask;
+ state->pctx->set_patch_vertices(state->pctx, state->patch_vertices);
state->pctx->draw_vbo(state->pctx, &state->info, 0, &state->indirect_info, &draw, 1);
}
static void handle_set_patch_control_points(struct lvp_cmd_buffer_entry *cmd,
struct rendering_state *state)
{
- state->info.vertices_per_patch = cmd->u.set_patch_control_points.vertices_per_patch;
+ state->patch_vertices = cmd->u.set_patch_control_points.vertices_per_patch;
}
static void handle_set_primitive_restart_enable(struct lvp_cmd_buffer_entry *cmd,
const float default_inner_level[2]);
/**
+ * Set the number of vertices per input patch for tessellation.
+ */
+ void (*set_patch_vertices)(struct pipe_context *ctx, uint8_t patch_vertices);
+
+ /**
* Sets the debug callback. If the pointer is null, then no callback is
* set, otherwise a copy of the data should be made.
*/
struct pipe_draw_info
{
enum pipe_prim_type mode:8; /**< the mode of the primitive */
- ubyte vertices_per_patch; /**< the number of vertices per patch */
- unsigned index_size:4; /**< if 0, the draw is not indexed. */
- unsigned view_mask:6; /**< mask of multiviews for this draw */
+ uint8_t index_size; /**< if 0, the draw is not indexed. */
+ uint8_t view_mask; /**< mask of multiviews for this draw */
bool primitive_restart:1;
bool has_user_indices:1; /**< if true, use index.user_buffer */
bool index_bounds_valid:1; /**< whether min_index and max_index are valid;
bool take_index_buffer_ownership:1; /**< callee inherits caller's refcount
(no need to reference indexbuf, but still needs to unreference it) */
bool index_bias_varies:1; /**< true if index_bias varies between draws */
+ uint8_t _pad:2;
unsigned start_instance; /**< first instance id */
unsigned instance_count; /**< number of instances */
ctx->DriverFlags.NewTextureBuffer = BRW_NEW_TEXTURE_BUFFER;
ctx->DriverFlags.NewAtomicBuffer = BRW_NEW_UNIFORM_BUFFER;
ctx->DriverFlags.NewImageUnits = BRW_NEW_IMAGE_UNITS;
- ctx->DriverFlags.NewDefaultTessLevels = BRW_NEW_DEFAULT_TESS_LEVELS;
+ ctx->DriverFlags.NewTessState = BRW_NEW_DEFAULT_TESS_LEVELS;
ctx->DriverFlags.NewIntelConservativeRasterization = BRW_NEW_CONSERVATIVE_RASTERIZATION;
}
struct pipe_draw_start_count_bias draw;
info.mode = mode;
- info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
info.index_size = 0;
/* Packed section begin. */
info.primitive_restart = false;
ALLOC_PRIMS(draw, primcount, "glMultiDrawElements");
info.mode = mode;
- info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
info.index_size = 0;
/* Packed section begin. */
info.primitive_restart = false;
struct gl_buffer_object *index_bo = ctx->Array.VAO->IndexBufferObj;
info.mode = mode;
- info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
info.index_size = 1 << index_size_shift;
/* Packed section begin. */
info.primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift];
struct pipe_draw_info info;
info.mode = mode;
- info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
info.index_size = 1 << index_size_shift;
/* Packed section begin. */
info.primitive_restart = ctx->Array._PrimitiveRestart[index_size_shift];
/**
* gl_context::TessCtrlProgram::patch_default_*
+ * gl_context::TessCtrlProgram::patch_vertices
*/
- uint64_t NewDefaultTessLevels;
+ uint64_t NewTessState;
/**
* gl_context::IntelConservativeRasterization
}
+static void
+set_patch_vertices(struct gl_context *ctx, GLint value)
+{
+ if (ctx->TessCtrlProgram.patch_vertices != value) {
+ FLUSH_VERTICES(ctx, 0, GL_CURRENT_BIT);
+ ctx->NewDriverState |= ctx->DriverFlags.NewTessState;
+ ctx->TessCtrlProgram.patch_vertices = value;
+ }
+}
+
/**
* For GL_ARB_tessellation_shader
*/
_mesa_PatchParameteri_no_error(GLenum pname, GLint value)
{
GET_CURRENT_CONTEXT(ctx);
- FLUSH_VERTICES(ctx, 0, GL_CURRENT_BIT);
- ctx->TessCtrlProgram.patch_vertices = value;
+
+ set_patch_vertices(ctx, value);
}
return;
}
- FLUSH_VERTICES(ctx, 0, GL_CURRENT_BIT);
- ctx->TessCtrlProgram.patch_vertices = value;
+ set_patch_vertices(ctx, value);
}
FLUSH_VERTICES(ctx, 0, 0);
memcpy(ctx->TessCtrlProgram.patch_default_outer_level, values,
4 * sizeof(GLfloat));
- ctx->NewDriverState |= ctx->DriverFlags.NewDefaultTessLevels;
+ ctx->NewDriverState |= ctx->DriverFlags.NewTessState;
return;
case GL_PATCH_DEFAULT_INNER_LEVEL:
FLUSH_VERTICES(ctx, 0, 0);
memcpy(ctx->TessCtrlProgram.patch_default_inner_level, values,
2 * sizeof(GLfloat));
- ctx->NewDriverState |= ctx->DriverFlags.NewDefaultTessLevels;
+ ctx->NewDriverState |= ctx->DriverFlags.NewTessState;
return;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "glPatchParameterfv");
const struct gl_context *ctx = st->ctx;
struct pipe_context *pipe = st->pipe;
- if (!pipe->set_tess_state)
- return;
+ if (pipe->set_tess_state) {
+ pipe->set_tess_state(pipe,
+ ctx->TessCtrlProgram.patch_default_outer_level,
+ ctx->TessCtrlProgram.patch_default_inner_level);
+ }
- pipe->set_tess_state(pipe,
- ctx->TessCtrlProgram.patch_default_outer_level,
- ctx->TessCtrlProgram.patch_default_inner_level);
+ if (pipe->set_patch_vertices)
+ pipe->set_patch_vertices(pipe, ctx->TessCtrlProgram.patch_vertices);
}
f->NewRasterizerDiscard = ST_NEW_RASTERIZER;
f->NewTileRasterOrder = ST_NEW_RASTERIZER;
f->NewUniformBuffer = ST_NEW_UNIFORM_BUFFER;
- f->NewDefaultTessLevels = ST_NEW_TESS_STATE;
+ f->NewTessState = ST_NEW_TESS_STATE;
/* Shader resources */
f->NewTextureBuffer = ST_NEW_SAMPLER_VIEWS;
}
info.mode = translate_prim(ctx, mode);
- info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
indirect.buffer = st_buffer_object(indirect_data)->buffer;
indirect.offset = indirect_offset;
util_draw_init_info(&info);
info.max_index = ~0u; /* so that u_vbuf can tell that it's unknown */
info.mode = translate_prim(ctx, mode);
- info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
info.instance_count = num_instances;
/* Transform feedback drawing is always non-indexed. */
/* Initialize pipe_draw_info. */
info.primitive_restart = false;
info.take_index_buffer_ownership = false;
- info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
info.restart_index = 0;
info.view_mask = 0;
info.max_index = d.start + d.count - 1;
}
- draw_vbo(draw, &info, prims[i].draw_id, NULL, &d, 1);
+ draw_vbo(draw, &info, prims[i].draw_id, NULL, &d, 1,
+ ctx->TessCtrlProgram.patch_vertices);
}
/* unmap images */
printf("%s %d %d\n", __func__, exec->vtx.prim_count,
exec->vtx.vert_count);
- exec->vtx.info.vertices_per_patch =
- ctx->TessCtrlProgram.patch_vertices;
-
ctx->Driver.DrawGalliumMultiMode(ctx, &exec->vtx.info,
exec->vtx.draw,
exec->vtx.mode,
assert(ctx->NewState == 0);
struct pipe_draw_info *info = (struct pipe_draw_info *) &node->merged.info;
- info->vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
void *gl_bo = info->index.gl_bo;
if (node->merged.mode) {
ctx->Driver.DrawGalliumMultiMode(ctx, info,