* ``PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY``: This CAP describes
a hw limitation. If true, pipe_vertex_element::src_offset must always be
aligned to 4. If false, there are no restrictions on src_offset.
+* ``PIPE_CAP_COMPUTE``: Whether the implementation supports the
+ compute entry points defined in pipe_context and pipe_screen.
+ * ``PIPE_CAP_USER_INDEX_BUFFERS``: Whether user index buffers are supported.
+ If not, the state tracker must upload all indices which are not in hw
+ resources.
+ * ``PIPE_CAP_USER_CONSTANT_BUFFERS``: Whether user constant buffers are
+ supported. If not, the state tracker must upload constants which are not in hw
+ resources.
+ * ``PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT``: Describes the required
+ alignment of pipe_constant_buffer::buffer_offset.
+
.. _pipe_capf:
If unsupported, only float opcodes are supported.
* ``PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS``: THe maximum number of texture
samplers.
+* ``PIPE_SHADER_CAP_PREFERRED_IR``: Preferred representation of the
+ program. It should be one of the ``pipe_shader_ir`` enum values.
+.. _pipe_compute_cap:
+
+PIPE_COMPUTE_CAP_*
+^^^^^^^^^^^^^^^^^^
+
+Compute-specific capabilities. They can be queried using
+pipe_screen::get_compute_param.
+
+* ``PIPE_COMPUTE_CAP_GRID_DIMENSION``: Number of supported dimensions
+ for grid and block coordinates. Value type: ``uint64_t``.
+* ``PIPE_COMPUTE_CAP_MAX_GRID_SIZE``: Maximum grid size in block
+ units. Value type: ``uint64_t []``.
+* ``PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE``: Maximum block size in thread
+ units. Value type: ``uint64_t []``.
+* ``PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE``: Maximum size of the GLOBAL
+ resource. Value type: ``uint64_t``.
+* ``PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE``: Maximum size of the LOCAL
+ resource. Value type: ``uint64_t``.
+* ``PIPE_COMPUTE_CAP_MAX_PRIVATE_SIZE``: Maximum size of the PRIVATE
+ resource. Value type: ``uint64_t``.
+* ``PIPE_COMPUTE_CAP_MAX_INPUT_SIZE``: Maximum size of the INPUT
+ resource. Value type: ``uint64_t``.
+
.. _pipe_bind:
PIPE_BIND_*
* ``PIPE_BIND_SCANOUT``: A front color buffer or scanout buffer.
* ``PIPE_BIND_SHARED``: A sharable buffer that can be given to another
process.
+* ``PIPE_BIND_GLOBAL``: A buffer that can be mapped into the global
+ address space of a compute program.
+* ``PIPE_BIND_SHADER_RESOURCE``: A buffer or texture that can be
+ bound to the graphics pipeline as a shader resource.
+* ``PIPE_BIND_COMPUTE_RESOURCE``: A buffer or texture that can be
+ bound to the compute program as a shader resource.
.. _pipe_usage:
const struct lp_fragment_shader_variant_key *key)
{
struct lp_fragment_shader_variant *variant;
+ const struct util_format_description *cbuf0_format_desc;
boolean fullcolormask;
variant = CALLOC_STRUCT(lp_fragment_shader_variant);
*/
fullcolormask = FALSE;
if (key->nr_cbufs == 1) {
- const struct util_format_description *format_desc;
- format_desc = util_format_description(key->cbuf_format[0]);
- if ((~key->blend.rt[0].colormask &
- util_format_colormask(format_desc)) == 0) {
- fullcolormask = TRUE;
- }
+ cbuf0_format_desc = util_format_description(key->cbuf_format[0]);
+ fullcolormask = util_format_colormask_full(cbuf0_format_desc, key->blend.rt[0].colormask);
}
variant->opaque =
static void
llvmpipe_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
- struct pipe_resource *constants)
+ struct pipe_constant_buffer *cb)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
- unsigned size = constants ? constants->width0 : 0;
- const void *data = constants ? llvmpipe_resource_data(constants) : NULL;
+ struct pipe_resource *constants = cb ? cb->buffer : NULL;
+ unsigned size;
+ const void *data;
+
+ if (cb && cb->user_buffer) {
+ constants = llvmpipe_user_buffer_create(pipe->screen, cb->user_buffer,
+ cb->buffer_size,
+ PIPE_BIND_CONSTANT_BUFFER);
+ }
+
+ size = constants ? constants->width0 : 0;
+ data = constants ? llvmpipe_resource_data(constants) : NULL;
assert(shader < PIPE_SHADER_TYPES);
assert(index < PIPE_MAX_CONSTANT_BUFFERS);
}
llvmpipe->dirty |= LP_NEW_CONSTANTS;
+
+ if (cb && cb->user_buffer) {
+ pipe_resource_reference(&constants, NULL);
+ }
}
buffer->base.width0 = bytes;
buffer->base.height0 = 1;
buffer->base.depth0 = 1;
- buffer->base.user_ptr = ptr;
buffer->data = ptr;
buffer->status = NOUVEAU_BUFFER_STATUS_USER_MEMORY;
{
if (!nv->scratch.nr_runout)
return;
- while (nv->scratch.nr_runout--)
+ do {
+ --nv->scratch.nr_runout;
nouveau_bo_ref(NULL, &nv->scratch.runout[nv->scratch.nr_runout]);
+ } while (nv->scratch.nr_runout);
FREE(nv->scratch.runout);
nv->scratch.end = 0;
static int
nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
{
+ const uint16_t class_3d = nouveau_screen(pscreen)->class_3d;
+
switch (param) {
case PIPE_CAP_MAX_COMBINED_SAMPLERS:
return 64;
return 12;
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
return 14;
- case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: /* shader support missing */
- return 0;
+ case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
+ return 512;
case PIPE_CAP_MIN_TEXEL_OFFSET:
return -8;
case PIPE_CAP_MAX_TEXEL_OFFSET:
case PIPE_CAP_ANISOTROPIC_FILTER:
case PIPE_CAP_SCALED_RESOLVE:
return 1;
- case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
case PIPE_CAP_SEAMLESS_CUBE_MAP:
return nv50_screen(pscreen)->tesla->oclass >= NVA0_3D_CLASS;
case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
- return 0;
+ return 4;
case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
- return 128;
case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
- return 32;
+ return 64;
+ case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
+ return (class_3d >= NVA0_3D_CLASS) ? 1 : 0;
case PIPE_CAP_BLEND_EQUATION_SEPARATE:
case PIPE_CAP_INDEP_BLEND_ENABLE:
return 1;
return 1;
case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS:
case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
- return 0; /* state trackers will know better */
case PIPE_CAP_USER_VERTEX_BUFFERS:
+ case PIPE_CAP_USER_INDEX_BUFFERS:
+ return 0; /* state trackers will know better */
+ case PIPE_CAP_USER_CONSTANT_BUFFERS:
return 1;
+ case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
+ return 256;
case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
prog->type = type;
prog->pipe.tokens = tgsi_dup_tokens(cso->tokens);
+ if (cso->stream_output.num_outputs)
+ prog->pipe.stream_output = cso->stream_output;
+
return (void *)prog;
}
static void
nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
- struct pipe_resource *res)
+ struct pipe_constant_buffer *cb)
{
struct nv50_context *nv50 = nv50_context(pipe);
+ struct pipe_resource *res = cb ? cb->buffer : NULL;
+
+ if (cb && cb->user_buffer) {
+ res = nouveau_user_buffer_create(pipe->screen, cb->user_buffer,
+ cb->buffer_size,
+ PIPE_BIND_CONSTANT_BUFFER);
+ }
pipe_resource_reference(&nv50->constbuf[shader][index], res);
nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_CB(shader, index));
nv50->dirty |= NV50_NEW_CONSTBUF;
+
+ if (cb && cb->user_buffer) {
+ pipe_resource_reference(&res, NULL);
+ }
}
/* =============================================================================
nv50->dirty |= NV50_NEW_VERTEX;
}
+static struct pipe_stream_output_target *
+nv50_so_target_create(struct pipe_context *pipe,
+ struct pipe_resource *res,
+ unsigned offset, unsigned size)
+{
+ struct nv50_so_target *targ = MALLOC_STRUCT(nv50_so_target);
+ if (!targ)
+ return NULL;
+
+ if (nouveau_context(pipe)->screen->class_3d >= NVA0_3D_CLASS) {
+ targ->pq = pipe->create_query(pipe,
+ NVA0_QUERY_STREAM_OUTPUT_BUFFER_OFFSET);
+ if (!targ->pq) {
+ FREE(targ);
+ return NULL;
+ }
+ } else {
+ targ->pq = NULL;
+ }
+ targ->clean = TRUE;
+
+ targ->pipe.buffer_size = size;
+ targ->pipe.buffer_offset = offset;
+ targ->pipe.context = pipe;
+ targ->pipe.buffer = NULL;
+ pipe_resource_reference(&targ->pipe.buffer, res);
+ pipe_reference_init(&targ->pipe.reference, 1);
+
+ return &targ->pipe;
+}
+
+static void
+nv50_so_target_destroy(struct pipe_context *pipe,
+ struct pipe_stream_output_target *ptarg)
+{
+ struct nv50_so_target *targ = nv50_so_target(ptarg);
+ if (targ->pq)
+ pipe->destroy_query(pipe, targ->pq);
+ FREE(targ);
+}
+
+static void
+nv50_set_stream_output_targets(struct pipe_context *pipe,
+ unsigned num_targets,
+ struct pipe_stream_output_target **targets,
+ unsigned append_mask)
+{
+ struct nv50_context *nv50 = nv50_context(pipe);
+ unsigned i;
+ boolean serialize = TRUE;
+ const boolean can_resume = nv50->screen->base.class_3d >= NVA0_3D_CLASS;
+
+ assert(num_targets <= 4);
+
+ for (i = 0; i < num_targets; ++i) {
+ const boolean changed = nv50->so_target[i] != targets[i];
+ if (!changed && (append_mask & (1 << i)))
+ continue;
+ nv50->so_targets_dirty |= 1 << i;
+
+ if (can_resume && changed && nv50->so_target[i]) {
+ nva0_so_target_save_offset(pipe, nv50->so_target[i], i, serialize);
+ serialize = FALSE;
+ }
+
+ if (targets[i] && !(append_mask & (1 << i)))
+ nv50_so_target(targets[i])->clean = TRUE;
+
+ pipe_so_target_reference(&nv50->so_target[i], targets[i]);
+ }
+ for (; i < nv50->num_so_targets; ++i) {
+ if (can_resume && nv50->so_target[i]) {
+ nva0_so_target_save_offset(pipe, nv50->so_target[i], i, serialize);
+ serialize = FALSE;
+ }
+ pipe_so_target_reference(&nv50->so_target[i], NULL);
+ nv50->so_targets_dirty |= 1 << i;
+ }
+ nv50->num_so_targets = num_targets;
+
+ if (nv50->so_targets_dirty)
+ nv50->dirty |= NV50_NEW_STRMOUT;
+}
+
void
nv50_init_state_functions(struct nv50_context *nv50)
{
pipe->set_vertex_buffers = nv50_set_vertex_buffers;
pipe->set_index_buffer = nv50_set_index_buffer;
-}
-
- pipe->redefine_user_buffer = u_default_redefine_user_buffer;
+ pipe->create_stream_output_target = nv50_so_target_create;
+ pipe->stream_output_target_destroy = nv50_so_target_destroy;
+ pipe->set_stream_output_targets = nv50_set_stream_output_targets;
-
+}
alpha_test_control |= S_028410_ALPHA_TEST_ENABLE(1);
alpha_ref = fui(state->alpha.ref_value);
}
+ dsa->sx_alpha_test_control = alpha_test_control & 0xff;
dsa->alpha_ref = alpha_ref;
/* misc */
db_render_control = 0;
- r600_pipe_state_add_reg(rstate, R_028410_SX_ALPHA_TEST_CONTROL, alpha_test_control);
r600_pipe_state_add_reg(rstate, R_028800_DB_DEPTH_CONTROL, db_depth_control);
r600_pipe_state_add_reg(rstate, R_028000_DB_RENDER_CONTROL, db_render_control);
return rstate;
{
struct r600_context *rctx = (struct r600_context *)ctx;
struct r600_pipe_state *rstate = CALLOC_STRUCT(r600_pipe_state);
- struct pipe_resource *cbuf;
+ struct pipe_constant_buffer cb;
if (rstate == NULL)
return;
rctx->states[R600_PIPE_STATE_CLIP] = rstate;
r600_context_pipe_state_set(rctx, rstate);
- cbuf = pipe_user_buffer_create(ctx->screen,
- state->ucp,
- 4*4*8, /* 8*4 floats */
- PIPE_BIND_CONSTANT_BUFFER);
- r600_set_constant_buffer(ctx, PIPE_SHADER_VERTEX, 1, cbuf);
- pipe_resource_reference(&cbuf, NULL);
+ cb.buffer = NULL;
+ cb.user_buffer = state->ucp;
+ cb.buffer_offset = 0;
+ cb.buffer_size = 4*4*8;
+ r600_set_constant_buffer(ctx, PIPE_SHADER_VERTEX, 1, &cb);
+ pipe_resource_reference(&cb.buffer, NULL);
}
static void evergreen_set_polygon_stipple(struct pipe_context *ctx,
blend_bypass = 1;
}
+ if (ntype == V_028C70_NUMBER_UINT || ntype == V_028C70_NUMBER_SINT)
+ rctx->sx_alpha_test_control |= S_028410_ALPHA_TEST_BYPASS(1);
+ else
+ rctx->sx_alpha_test_control &= C_028410_ALPHA_TEST_BYPASS;
+
color_info |= S_028C70_FORMAT(format) |
S_028C70_COMP_SWAP(swap) |
S_028C70_BLEND_CLAMP(blend_clamp) |
uint32_t dirty_mask = state->dirty_mask;
while (dirty_mask) {
- struct r600_constant_buffer *cb;
+ struct pipe_constant_buffer *cb;
struct r600_resource *rbuffer;
uint64_t va;
unsigned buffer_index = ffs(dirty_mask) - 1;
rctx->context.set_vertex_sampler_views = evergreen_set_vs_sampler_view;
rctx->context.set_viewport_state = evergreen_set_viewport_state;
rctx->context.sampler_view_destroy = r600_sampler_view_destroy;
- rctx->context.redefine_user_buffer = u_default_redefine_user_buffer;
rctx->context.texture_barrier = r600_texture_barrier;
rctx->context.create_stream_output_target = r600_create_so_target;
rctx->context.stream_output_target_destroy = r600_so_target_destroy;
ubyte valuemask[2];
ubyte writemask[2];
bool is_flush;
+ unsigned sx_alpha_test_control;
};
struct r600_vertex_element
ubyte writemask[2];
};
- struct r600_constant_buffer
- {
- struct pipe_resource *buffer;
- unsigned buffer_offset;
- unsigned buffer_size;
- };
-
struct r600_constbuf_state
{
struct r600_atom atom;
- struct r600_constant_buffer cb[PIPE_MAX_CONSTANT_BUFFERS];
+ struct pipe_constant_buffer cb[PIPE_MAX_CONSTANT_BUFFERS];
uint32_t enabled_mask;
uint32_t dirty_mask;
};
struct pipe_framebuffer_state framebuffer;
unsigned cb_target_mask;
unsigned fb_cb_shader_mask;
+ unsigned sx_alpha_test_control;
unsigned cb_shader_mask;
unsigned cb_color_control;
unsigned pa_sc_line_stipple;
void r600_delete_vs_shader(struct pipe_context *ctx, void *state);
void r600_constant_buffers_dirty(struct r600_context *rctx, struct r600_constbuf_state *state);
void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
- struct pipe_resource *buffer);
+ struct pipe_constant_buffer *cb);
struct pipe_stream_output_target *
r600_create_so_target(struct pipe_context *ctx,
struct pipe_resource *buffer,
alpha_test_control |= S_028410_ALPHA_TEST_ENABLE(1);
alpha_ref = fui(state->alpha.ref_value);
}
+ dsa->sx_alpha_test_control = alpha_test_control & 0xff;
dsa->alpha_ref = alpha_ref;
- r600_pipe_state_add_reg(rstate, R_028410_SX_ALPHA_TEST_CONTROL, alpha_test_control);
r600_pipe_state_add_reg(rstate, R_028800_DB_DEPTH_CONTROL, db_depth_control);
return rstate;
}
{
struct r600_context *rctx = (struct r600_context *)ctx;
struct r600_pipe_state *rstate = CALLOC_STRUCT(r600_pipe_state);
- struct pipe_resource * cbuf;
+ struct pipe_constant_buffer cb;
if (rstate == NULL)
return;
rctx->states[R600_PIPE_STATE_CLIP] = rstate;
r600_context_pipe_state_set(rctx, rstate);
- cbuf = pipe_user_buffer_create(ctx->screen,
- state->ucp,
- 4*4*8, /* 8*4 floats */
- PIPE_BIND_CONSTANT_BUFFER);
- r600_set_constant_buffer(ctx, PIPE_SHADER_VERTEX, 1, cbuf);
- pipe_resource_reference(&cbuf, NULL);
+ cb.buffer = NULL;
+ cb.user_buffer = state->ucp;
+ cb.buffer_offset = 0;
+ cb.buffer_size = 4*4*8;
+ r600_set_constant_buffer(ctx, PIPE_SHADER_VERTEX, 1, &cb);
+ pipe_resource_reference(&cb.buffer, NULL);
}
static void r600_set_polygon_stipple(struct pipe_context *ctx,
blend_bypass = 1;
}
+ if (ntype == V_0280A0_NUMBER_UINT || ntype == V_0280A0_NUMBER_SINT)
+ rctx->sx_alpha_test_control |= S_028410_ALPHA_TEST_BYPASS(1);
+ else
+ rctx->sx_alpha_test_control &= C_028410_ALPHA_TEST_BYPASS;
+
color_info |= S_0280A0_FORMAT(format) |
S_0280A0_COMP_SWAP(swap) |
S_0280A0_BLEND_BYPASS(blend_bypass) |
uint32_t dirty_mask = state->dirty_mask;
while (dirty_mask) {
- struct r600_constant_buffer *cb;
+ struct pipe_constant_buffer *cb;
struct r600_resource *rbuffer;
unsigned offset;
unsigned buffer_index = ffs(dirty_mask) - 1;
rctx->context.set_vertex_sampler_views = r600_set_vs_sampler_views;
rctx->context.set_viewport_state = r600_set_viewport_state;
rctx->context.sampler_view_destroy = r600_sampler_view_destroy;
- rctx->context.redefine_user_buffer = u_default_redefine_user_buffer;
rctx->context.texture_barrier = r600_texture_barrier;
rctx->context.create_stream_output_target = r600_create_so_target;
rctx->context.stream_output_target_destroy = r600_so_target_destroy;
return;
rstate = &dsa->rstate;
rctx->states[rstate->id] = rstate;
+ rctx->sx_alpha_test_control &= ~0xff;
+ rctx->sx_alpha_test_control |= dsa->sx_alpha_test_control;
rctx->alpha_ref = dsa->alpha_ref;
rctx->alpha_ref_dirty = true;
r600_context_pipe_state_set(rctx, rstate);
}
void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
- struct pipe_resource *buffer)
+ struct pipe_constant_buffer *input)
{
struct r600_context *rctx = (struct r600_context *)ctx;
struct r600_constbuf_state *state;
- struct r600_constant_buffer *cb;
- uint8_t *ptr;
+ struct pipe_constant_buffer *cb;
+ const uint8_t *ptr;
switch (shader) {
case PIPE_SHADER_VERTEX:
/* Note that the state tracker can unbind constant buffers by
* passing NULL here.
*/
- if (unlikely(!buffer)) {
+ if (unlikely(!input)) {
state->enabled_mask &= ~(1 << index);
state->dirty_mask &= ~(1 << index);
pipe_resource_reference(&state->cb[index].buffer, NULL);
}
cb = &state->cb[index];
- cb->buffer_size = buffer->width0;
+ cb->buffer_size = input->buffer_size;
- ptr = buffer->user_ptr;
+ ptr = input->user_buffer;
if (ptr) {
/* Upload the user buffer. */
if (R600_BIG_ENDIAN) {
uint32_t *tmpPtr;
- unsigned i, size = buffer->width0;
+ unsigned i, size = input->buffer_size;
if (!(tmpPtr = malloc(size))) {
R600_ERR("Failed to allocate BE swap buffer.\n");
u_upload_data(rctx->uploader, 0, size, tmpPtr, &cb->buffer_offset, &cb->buffer);
free(tmpPtr);
} else {
- u_upload_data(rctx->uploader, 0, buffer->width0, ptr, &cb->buffer_offset, &cb->buffer);
+ u_upload_data(rctx->uploader, 0, input->buffer_size, ptr, &cb->buffer_offset, &cb->buffer);
}
} else {
/* Setup the hw buffer. */
- cb->buffer_offset = 0;
- pipe_resource_reference(&cb->buffer, buffer);
+ cb->buffer_offset = input->buffer_offset;
+ pipe_resource_reference(&cb->buffer, input->buffer);
}
state->enabled_mask |= 1 << index;
uint8_t *ptr;
if ((!info.count && (info.indexed || !info.count_from_stream_output)) ||
- (info.indexed && !rctx->index_buffer.buffer) ||
!r600_conv_pipe_prim(info.mode, &prim)) {
assert(0);
return;
if (info.indexed) {
/* Initialize the index buffer struct. */
pipe_resource_reference(&ib.buffer, rctx->index_buffer.buffer);
+ ib.user_buffer = rctx->index_buffer.user_buffer;
ib.index_size = rctx->index_buffer.index_size;
ib.offset = rctx->index_buffer.offset + info.start * ib.index_size;
/* Translate or upload, if needed. */
r600_translate_index_buffer(rctx, &ib, info.count);
- ptr = ib.buffer->user_ptr;
- if (ptr) {
+ ptr = (uint8_t*)ib.user_buffer;
+ if (!ib.buffer && ptr) {
u_upload_data(rctx->uploader, 0, info.count * ib.index_size,
ptr, &ib.offset, &ib.buffer);
}
r600_pipe_state_add_reg(&rctx->vgt, R_02823C_CB_SHADER_MASK, 0);
r600_pipe_state_add_reg(&rctx->vgt, R_028408_VGT_INDX_OFFSET, info.index_bias);
r600_pipe_state_add_reg(&rctx->vgt, R_02840C_VGT_MULTI_PRIM_IB_RESET_INDX, info.restart_index);
+ r600_pipe_state_add_reg(&rctx->vgt, R_028410_SX_ALPHA_TEST_CONTROL, 0);
r600_pipe_state_add_reg(&rctx->vgt, R_028A94_VGT_MULTI_PRIM_IB_RESET_EN, info.primitive_restart);
r600_pipe_state_add_reg(&rctx->vgt, R_03CFF4_SQ_VTX_START_INST_LOC, info.start_instance);
r600_pipe_state_add_reg(&rctx->vgt, R_028A0C_PA_SC_LINE_STIPPLE, 0);
r600_pipe_state_mod_reg(&rctx->vgt, rctx->cb_shader_mask);
r600_pipe_state_mod_reg(&rctx->vgt, info.index_bias);
r600_pipe_state_mod_reg(&rctx->vgt, info.restart_index);
+ r600_pipe_state_mod_reg(&rctx->vgt, rctx->sx_alpha_test_control);
r600_pipe_state_mod_reg(&rctx->vgt, info.primitive_restart);
r600_pipe_state_mod_reg(&rctx->vgt, info.start_instance);
free(state);
}
-static unsigned si_map_swizzle(unsigned swizzle)
-{
- switch (swizzle) {
- case UTIL_FORMAT_SWIZZLE_Y:
- return V_008F1C_SQ_SEL_Y;
- case UTIL_FORMAT_SWIZZLE_Z:
- return V_008F1C_SQ_SEL_Z;
- case UTIL_FORMAT_SWIZZLE_W:
- return V_008F1C_SQ_SEL_W;
- case UTIL_FORMAT_SWIZZLE_0:
- return V_008F1C_SQ_SEL_0;
- case UTIL_FORMAT_SWIZZLE_1:
- return V_008F1C_SQ_SEL_1;
- default: /* UTIL_FORMAT_SWIZZLE_X */
- return V_008F1C_SQ_SEL_X;
- }
-}
-
static struct pipe_sampler_view *evergreen_create_sampler_view(struct pipe_context *ctx,
struct pipe_resource *texture,
const struct pipe_sampler_view *state)
va = r600_resource_va(ctx->screen, texture);
view->state[0] = (va + tmp->offset[0]) >> 8;
- view->state[1] = ((va + tmp->offset[0]) >> 40) & 0xff;
- view->state[1] |= (S_008F14_DATA_FORMAT(format) |
- S_008F14_NUM_FORMAT(num_format));
+ view->state[1] = (S_008F14_BASE_ADDRESS_HI((va + tmp->offset[0]) >> 40) |
+ S_008F14_DATA_FORMAT(format) |
+ S_008F14_NUM_FORMAT(num_format));
view->state[2] = (S_008F18_WIDTH(texture->width0 - 1) |
S_008F18_HEIGHT(height - 1));
view->state[3] = (S_008F1C_DST_SEL_X(si_map_swizzle(swizzle[0])) |
rctx->context.set_vertex_sampler_views = evergreen_set_vs_sampler_view;
rctx->context.set_viewport_state = evergreen_set_viewport_state;
rctx->context.sampler_view_destroy = r600_sampler_view_destroy;
- rctx->context.redefine_user_buffer = u_default_redefine_user_buffer;
rctx->context.texture_barrier = r600_texture_barrier;
rctx->context.create_stream_output_target = r600_create_so_target;
rctx->context.stream_output_target_destroy = r600_so_target_destroy;
r600_pipe_state_add_reg(rstate,
R_02870C_SPI_SHADER_POS_FORMAT,
S_02870C_POS0_EXPORT_FORMAT(V_02870C_SPI_SHADER_4COMP) |
- S_02870C_POS1_EXPORT_FORMAT(V_02870C_SPI_SHADER_4COMP) |
- S_02870C_POS2_EXPORT_FORMAT(V_02870C_SPI_SHADER_4COMP) |
- S_02870C_POS3_EXPORT_FORMAT(V_02870C_SPI_SHADER_4COMP),
+ S_02870C_POS1_EXPORT_FORMAT(V_02870C_SPI_SHADER_NONE) |
+ S_02870C_POS2_EXPORT_FORMAT(V_02870C_SPI_SHADER_NONE) |
+ S_02870C_POS3_EXPORT_FORMAT(V_02870C_SPI_SHADER_NONE),
NULL, 0);
va = r600_resource_va(ctx->screen, (void *)shader->bo);
}
void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
- struct pipe_resource *buffer)
+ struct pipe_constant_buffer *cb)
{
struct r600_context *rctx = (struct r600_context *)ctx;
- struct r600_resource *rbuffer = r600_resource(buffer);
+ struct r600_resource *rbuffer = cb ? r600_resource(cb->buffer) : NULL;
struct r600_pipe_state *rstate;
uint64_t va_offset;
uint32_t offset;
/* Note that the state tracker can unbind constant buffers by
* passing NULL here.
*/
- if (buffer == NULL) {
+ if (cb == NULL) {
return;
}
r600_inval_shader_cache(rctx);
- r600_upload_const_buffer(rctx, &rbuffer, &offset);
+ if (cb->user_buffer)
+ r600_upload_const_buffer(rctx, &rbuffer, cb->user_buffer, cb->buffer_size, &offset);
+ else
+ offset = 0;
va_offset = r600_resource_va(ctx->screen, (void*)rbuffer);
va_offset += offset;
//va_offset >>= 8;
r600_context_pipe_state_set(rctx, rstate);
- if (buffer != &rbuffer->b.b)
+ if (cb->buffer != &rbuffer->b.b)
pipe_resource_reference((struct pipe_resource**)&rbuffer, NULL);
}
ptr[0] = va & 0xFFFFFFFF;
ptr[1] = (S_008F04_BASE_ADDRESS_HI(va >> 32) |
S_008F04_STRIDE(vertex_buffer->stride));
- ptr[2] = (vertex_buffer->buffer->width0 - offset) / vertex_buffer->stride;
- /* XXX: Hardcoding RGBA */
- ptr[3] = (S_008F0C_DST_SEL_X(V_008F0C_SQ_SEL_X) |
- S_008F0C_DST_SEL_Y(V_008F0C_SQ_SEL_Y) |
- S_008F0C_DST_SEL_Z(V_008F0C_SQ_SEL_Z) |
- S_008F0C_DST_SEL_W(V_008F0C_SQ_SEL_W) |
+ if (vertex_buffer->stride > 0)
+ ptr[2] = ((vertex_buffer->buffer->width0 - offset) /
+ vertex_buffer->stride);
+ else
+ ptr[2] = vertex_buffer->buffer->width0 - offset;
+ ptr[3] = (S_008F0C_DST_SEL_X(si_map_swizzle(desc->swizzle[0])) |
+ S_008F0C_DST_SEL_Y(si_map_swizzle(desc->swizzle[1])) |
+ S_008F0C_DST_SEL_Z(si_map_swizzle(desc->swizzle[2])) |
+ S_008F0C_DST_SEL_W(si_map_swizzle(desc->swizzle[3])) |
S_008F0C_NUM_FORMAT(num_format) |
S_008F0C_DATA_FORMAT(data_format));
/* Translate or upload, if needed. */
r600_translate_index_buffer(rctx, &ib, info.count);
- if (ib.buffer->user_ptr) {
+ if (ib.user_buffer) {
r600_upload_index_buffer(rctx, &ib, info.count);
}
#include "r600.h"
#include "radeonsi_public.h"
#include "r600_resource.h"
+#include "sid.h"
#define R600_MAX_CONST_BUFFERS 1
#define R600_MAX_CONST_BUFFER_SIZE 4096
void r600_delete_ps_shader(struct pipe_context *ctx, void *state);
void r600_delete_vs_shader(struct pipe_context *ctx, void *state);
void r600_set_constant_buffer(struct pipe_context *ctx, uint shader, uint index,
- struct pipe_resource *buffer);
+ struct pipe_constant_buffer *cb);
struct pipe_stream_output_target *
r600_create_so_target(struct pipe_context *ctx,
struct pipe_resource *buffer,
}
#define ALIGN_DIVUP(x, y) (((x) + (y) - 1) / (y))
+static INLINE unsigned si_map_swizzle(unsigned swizzle)
+{
+ switch (swizzle) {
+ case UTIL_FORMAT_SWIZZLE_Y:
+ return V_008F0C_SQ_SEL_Y;
+ case UTIL_FORMAT_SWIZZLE_Z:
+ return V_008F0C_SQ_SEL_Z;
+ case UTIL_FORMAT_SWIZZLE_W:
+ return V_008F0C_SQ_SEL_W;
+ case UTIL_FORMAT_SWIZZLE_0:
+ return V_008F0C_SQ_SEL_0;
+ case UTIL_FORMAT_SWIZZLE_1:
+ return V_008F0C_SQ_SEL_1;
+ default: /* UTIL_FORMAT_SWIZZLE_X */
+ return V_008F0C_SQ_SEL_X;
+ }
+}
+
static inline unsigned r600_tex_aniso_filter(unsigned filter)
{
if (filter <= 1) return 0;
case PIPE_CAP_TEXTURE_SWIZZLE:
return 1;
case PIPE_CAP_USER_VERTEX_BUFFERS:
+ case PIPE_CAP_USER_INDEX_BUFFERS:
+ return 0;
+ case PIPE_CAP_USER_CONSTANT_BUFFERS:
return 1;
+ case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
+ return 16;
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
{
case PIPE_CAP_TGSI_CAN_COMPACT_VARYINGS:
case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
case PIPE_CAP_GLSL_FEATURE_LEVEL:
+ case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
+ case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
return 0;
+ case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
+ return 1;
default:
debug_printf("Unexpected PIPE_CAP_ query %u\n", param);
struct pipe_blend_state;
struct pipe_box;
struct pipe_clip_state;
+ struct pipe_constant_buffer;
struct pipe_depth_stencil_alpha_state;
struct pipe_draw_info;
struct pipe_fence_handle;
struct pipe_video_buffer;
struct pipe_video_decoder;
struct pipe_viewport_state;
+struct pipe_compute_state;
union pipe_color_union;
union pipe_query_result;
void (*bind_geometry_sampler_states)(struct pipe_context *,
unsigned num_samplers,
void **samplers);
+ void (*bind_compute_sampler_states)(struct pipe_context *,
+ unsigned start_slot,
+ unsigned num_samplers,
+ void **samplers);
void (*delete_sampler_state)(struct pipe_context *, void *);
void * (*create_rasterizer_state)(struct pipe_context *,
void (*set_constant_buffer)( struct pipe_context *,
uint shader, uint index,
- struct pipe_resource *buf );
+ struct pipe_constant_buffer *buf );
void (*set_framebuffer_state)( struct pipe_context *,
const struct pipe_framebuffer_state * );
unsigned num_views,
struct pipe_sampler_view **);
+ void (*set_compute_sampler_views)(struct pipe_context *,
+ unsigned start_slot, unsigned num_views,
+ struct pipe_sampler_view **);
+
+ /**
+ * Bind an array of shader resources that will be used by the
+ * graphics pipeline. Any resources that were previously bound to
+ * the specified range will be unbound after this call.
+ *
+ * \param first first resource to bind.
+ * \param count number of consecutive resources to bind.
+ * \param resources array of pointers to the resources to bind, it
+ * should contain at least \a count elements
+ * unless it's NULL, in which case no new
+ * resources will be bound.
+ */
+ void (*set_shader_resources)(struct pipe_context *,
+ unsigned start, unsigned count,
+ struct pipe_surface **resources);
+
void (*set_vertex_buffers)( struct pipe_context *,
unsigned num_buffers,
const struct pipe_vertex_buffer * );
unsigned stride,
unsigned layer_stride);
-
- /* Notify a driver that a content of a user buffer has been changed.
- * The changed range is [offset, offset+size-1].
- * The new width0 of the buffer is offset+size. */
- void (*redefine_user_buffer)(struct pipe_context *,
- struct pipe_resource *,
- unsigned offset,
- unsigned size);
-
/**
* Flush any pending framebuffer writes and invalidate texture caches.
*/
*/
struct pipe_video_buffer *(*create_video_buffer)( struct pipe_context *context,
const struct pipe_video_buffer *templat );
+
+ /**
+ * Compute kernel execution
+ */
+ /*@{*/
+ /**
+ * Define the compute program and parameters to be used by
+ * pipe_context::launch_grid.
+ */
+ void *(*create_compute_state)(struct pipe_context *context,
+ const struct pipe_compute_state *);
+ void (*bind_compute_state)(struct pipe_context *, void *);
+ void (*delete_compute_state)(struct pipe_context *, void *);
+
+ /**
+ * Bind an array of shader resources that will be used by the
+ * compute program. Any resources that were previously bound to
+ * the specified range will be unbound after this call.
+ *
+ * \param first first resource to bind.
+ * \param count number of consecutive resources to bind.
+ * \param resources array of pointers to the resources to bind, it
+ * should contain at least \a count elements
+ * unless it's NULL, in which case no new
+ * resources will be bound.
+ */
+ void (*set_compute_resources)(struct pipe_context *,
+ unsigned start, unsigned count,
+ struct pipe_surface **resources);
+
+ /**
+ * Bind an array of buffers to be mapped into the address space of
+ * the GLOBAL resource. Any buffers that were previously bound
+ * between [first, first + count - 1] are unbound after this call.
+ *
+ * \param first first buffer to map.
+ * \param count number of consecutive buffers to map.
+ * \param resources array of pointers to the buffers to map, it
+ * should contain at least \a count elements
+ * unless it's NULL, in which case no new
+ * resources will be bound.
+ * \param handles array of pointers to the memory locations that
+ * will be filled with the respective base
+ * addresses each buffer will be mapped to. It
+ * should contain at least \a count elements,
+ * unless \a resources is NULL in which case \a
+ * handles should be NULL as well.
+ *
+ * Note that the driver isn't required to make any guarantees about
+ * the contents of the \a handles array being valid anytime except
+ * during the subsequent calls to pipe_context::launch_grid. This
+ * means that the only sensible location handles[i] may point to is
+ * somewhere within the INPUT buffer itself. This is so to
+ * accommodate implementations that lack virtual memory but
+ * nevertheless migrate buffers on the fly, leading to resource
+ * base addresses that change on each kernel invocation or are
+ * unknown to the pipe driver.
+ */
+ void (*set_global_binding)(struct pipe_context *context,
+ unsigned first, unsigned count,
+ struct pipe_resource **resources,
+ uint32_t **handles);
+
+ /**
+ * Launch the compute kernel starting from instruction \a pc of the
+ * currently bound compute program.
+ *
+ * \a grid_layout and \a block_layout are arrays of size \a
+ * PIPE_COMPUTE_CAP_GRID_DIMENSION that determine the layout of the
+ * grid (in block units) and working block (in thread units) to be
+ * used, respectively.
+ *
+ * \a input will be used to initialize the INPUT resource, and it
+ * should point to a buffer of at least
+ * pipe_compute_state::req_input_mem bytes.
+ */
+ void (*launch_grid)(struct pipe_context *context,
+ const uint *block_layout, const uint *grid_layout,
+ uint32_t pc, const void *input);
+ /*@}*/
};
#define PIPE_BIND_STREAM_OUTPUT (1 << 11) /* set_stream_output_buffers */
#define PIPE_BIND_CURSOR (1 << 16) /* mouse cursor */
#define PIPE_BIND_CUSTOM (1 << 17) /* state-tracker/winsys usages */
+#define PIPE_BIND_GLOBAL (1 << 18) /* set_global_binding */
+#define PIPE_BIND_SHADER_RESOURCE (1 << 19) /* set_shader_resources */
+#define PIPE_BIND_COMPUTE_RESOURCE (1 << 20) /* set_compute_resources */
/* The first two flags above were previously part of the amorphous
* TEXTURE_USAGE, most of which are now descriptions of the ways a
#define PIPE_SHADER_VERTEX 0
#define PIPE_SHADER_FRAGMENT 1
#define PIPE_SHADER_GEOMETRY 2
-#define PIPE_SHADER_TYPES 3
+#define PIPE_SHADER_COMPUTE 3
+#define PIPE_SHADER_TYPES 4
/**
PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY = 65,
PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY = 66,
PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY = 67,
- PIPE_CAP_COMPUTE = 68
- PIPE_CAP_USER_INDEX_BUFFERS = 68,
- PIPE_CAP_USER_CONSTANT_BUFFERS = 69,
- PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT = 70
++ PIPE_CAP_COMPUTE = 68,
++ PIPE_CAP_USER_INDEX_BUFFERS = 69,
++ PIPE_CAP_USER_CONSTANT_BUFFERS = 70,
++ PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT = 71
};
/**
PIPE_SHADER_CAP_INDIRECT_CONST_ADDR = 15,
PIPE_SHADER_CAP_SUBROUTINES = 16, /* BGNSUB, ENDSUB, CAL, RET */
PIPE_SHADER_CAP_INTEGERS = 17,
- PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS = 18
+ PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS = 18,
+ PIPE_SHADER_CAP_PREFERRED_IR = 19
};
+/**
+ * Shader intermediate representation.
+ */
+enum pipe_shader_ir
+{
+ PIPE_SHADER_IR_TGSI
+};
+
+/**
+ * Compute-specific implementation capability. They can be queried
+ * using pipe_screen::get_compute_param.
+ */
+enum pipe_compute_cap
+{
+ PIPE_COMPUTE_CAP_GRID_DIMENSION,
+ PIPE_COMPUTE_CAP_MAX_GRID_SIZE,
+ PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE,
+ PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE,
+ PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE,
+ PIPE_COMPUTE_CAP_MAX_PRIVATE_SIZE,
+ PIPE_COMPUTE_CAP_MAX_INPUT_SIZE
+};
/**
* Composite query types
#define PIPE_MAX_GEOMETRY_SAMPLERS 16
#define PIPE_MAX_SHADER_INPUTS 32
#define PIPE_MAX_SHADER_OUTPUTS 32
+#define PIPE_MAX_SHADER_SAMPLER_VIEWS 32
#define PIPE_MAX_SHADER_RESOURCES 32
#define PIPE_MAX_TEXTURE_LEVELS 16
#define PIPE_MAX_SO_BUFFERS 4
unsigned height; /**< logical height in pixels */
unsigned usage; /**< bitmask of PIPE_BIND_x */
+ unsigned writable:1; /**< writable shader resource */
union {
struct {
unsigned bind; /**< bitmask of PIPE_BIND_x */
unsigned flags; /**< bitmask of PIPE_RESOURCE_FLAG_x */
-
- /* XXX this is only temporary and will be removed once it's not needed */
- uint8_t *user_ptr; /**< user buffer pointer */
};
unsigned stride; /**< stride to same attrib in next vertex, in bytes */
unsigned buffer_offset; /**< offset to start of data in buffer, in bytes */
struct pipe_resource *buffer; /**< the actual buffer */
+ const void *user_buffer; /**< pointer to a user buffer if buffer == NULL */
+ };
+
+
+ /**
+ * A constant buffer. A subrange of an existing buffer can be set
+ * as a constant buffer.
+ */
+ struct pipe_constant_buffer {
+ struct pipe_resource *buffer; /**< the actual buffer */
+ unsigned buffer_offset; /**< offset to start of data in buffer, in bytes */
+ unsigned buffer_size; /**< how much data can be read in shader */
+ const void *user_buffer; /**< pointer to a user buffer if buffer == NULL */
};
unsigned index_size; /**< size of an index, in bytes */
unsigned offset; /**< offset to start of data in buffer, in bytes */
struct pipe_resource *buffer; /**< the actual buffer */
+ const void *user_buffer; /**< pointer to a user buffer if buffer == NULL */
};
unsigned mask; /**< PIPE_MASK_RGBA, Z, S or ZS */
};
+struct pipe_compute_state
+{
+ const void *prog; /**< Compute program to be executed. */
+ unsigned req_local_mem; /**< Required size of the LOCAL resource. */
+ unsigned req_private_mem; /**< Required size of the PRIVATE resource. */
+ unsigned req_input_mem; /**< Required size of the INPUT resource. */
+};
#ifdef __cplusplus
}
#include "util/u_inlines.h"
#include "util/u_upload_mgr.h"
#include "cso_cache/cso_context.h"
- #include "util/u_vbuf.h"
DEBUG_GET_ONCE_BOOL_OPTION(mesa_mvp_dp4, "MESA_MVP_DP4", FALSE)
}
- static void st_init_vbuf(struct st_context *st)
- {
- struct u_vbuf_caps caps;
-
- u_vbuf_get_caps(st->pipe->screen, &caps);
-
- /* Create u_vbuf if there is anything unsupported. */
- if (!caps.buffer_offset_unaligned ||
- !caps.buffer_stride_unaligned ||
- !caps.velem_src_offset_unaligned ||
- !caps.format_fixed32 ||
- !caps.format_float16 ||
- !caps.format_float64 ||
- !caps.format_norm32 ||
- !caps.format_scaled32 ||
- !caps.user_vertex_buffers) {
- /* XXX user vertex buffers are always uploaded regardless of the CAP. */
- st->vbuf = u_vbuf_create(st->pipe, &caps);
- cso_install_vbuf(st->cso_context, st->vbuf);
- }
- }
static struct st_context *
st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe )
{
+ struct pipe_screen *screen = pipe->screen;
uint i;
struct st_context *st = ST_CALLOC_STRUCT( st_context );
st->dirty.st = ~0;
st->uploader = u_upload_create(st->pipe, 65536, 4, PIPE_BIND_VERTEX_BUFFER);
+
+ if (!screen->get_param(screen, PIPE_CAP_USER_INDEX_BUFFERS)) {
+ st->indexbuf_uploader = u_upload_create(st->pipe, 128 * 1024, 4,
+ PIPE_BIND_INDEX_BUFFER);
+ }
+
+ if (!screen->get_param(screen, PIPE_CAP_USER_CONSTANT_BUFFERS)) {
+ unsigned alignment =
+ screen->get_param(screen, PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT);
+
+ st->constbuf_uploader = u_upload_create(pipe, 128 * 1024, alignment,
+ PIPE_BIND_CONSTANT_BUFFER);
+ }
+
st->cso_context = cso_create_context(pipe);
- st_init_vbuf(st);
st_init_atoms( st );
st_init_bitmap(st);
st_init_clear(st);
return st;
}
+static void st_init_driver_flags(struct gl_driver_flags *f)
+{
+ f->NewArray = ST_NEW_VERTEX_ARRAYS;
+}
struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
const struct gl_config *visual,
return NULL;
}
+ st_init_driver_flags(&ctx->DriverFlags);
+
/* XXX: need a capability bit in gallium to query if the pipe
* driver prefers DP4 or MUL/MAD for vertex transformation.
*/
st_destroy_drawpix(st);
st_destroy_drawtex(st);
- /* Unreference any user vertex buffers. */
- for (i = 0; i < st->num_user_attribs; i++) {
- pipe_resource_reference(&st->user_attrib[i].buffer, NULL);
- }
-
for (i = 0; i < Elements(st->state.sampler_views); i++) {
pipe_sampler_view_reference(&st->state.sampler_views[i], NULL);
}
}
u_upload_destroy(st->uploader);
+ if (st->indexbuf_uploader) {
+ u_upload_destroy(st->indexbuf_uploader);
+ }
+ if (st->constbuf_uploader) {
+ u_upload_destroy(st->constbuf_uploader);
+ }
free( st );
}
void st_destroy_context( struct st_context *st )
{
struct pipe_context *pipe = st->pipe;
- struct u_vbuf *vbuf = st->vbuf;
struct cso_context *cso = st->cso_context;
struct gl_context *ctx = st->ctx;
GLuint i;
st_destroy_context_priv(st);
st = NULL;
- if (vbuf)
- u_vbuf_destroy(vbuf);
-
cso_destroy_context(cso);
pipe->destroy( pipe );
struct st_context;
struct st_fragment_program;
struct u_upload_mgr;
- struct u_vbuf;
#define ST_NEW_MESA (1 << 0) /* Mesa state has changed */
#define ST_NEW_FRAMEBUFFER (1 << 3)
#define ST_NEW_EDGEFLAGS_DATA (1 << 4)
#define ST_NEW_GEOMETRY_PROGRAM (1 << 5)
+#define ST_NEW_VERTEX_ARRAYS (1 << 6)
struct st_state_flags {
struct pipe_context *pipe;
- struct u_upload_mgr *uploader;
- struct u_vbuf *vbuf;
+ struct u_upload_mgr *uploader, *indexbuf_uploader, *constbuf_uploader;
struct draw_context *draw; /**< For selection/feedback/rastpos only */
struct draw_stage *feedback_stage; /**< For GL_FEEDBACK rendermode */
int force_msaa;
void *winsys_drawable_handle;
- /* User vertex buffers. */
- struct {
- struct pipe_resource *buffer;
-
- /** Element size */
- GLuint element_size;
-
- /** Attribute stride */
- GLsizei stride;
- } user_attrib[PIPE_MAX_ATTRIBS];
- unsigned num_user_attribs;
-
/* Active render condition. */
struct pipe_query *render_condition;
unsigned condition_mode;
#include "util/u_format.h"
#include "util/u_prim.h"
#include "util/u_draw_quad.h"
+ #include "util/u_upload_mgr.h"
#include "draw/draw_context.h"
#include "cso_cache/cso_context.h"
const struct st_vp_variant *vpv,
const struct gl_client_array **arrays,
struct pipe_vertex_buffer *vbuffer,
- struct pipe_vertex_element velements[],
- unsigned max_index,
- unsigned num_instances)
+ struct pipe_vertex_element velements[])
{
- struct st_context *st = st_context(ctx);
- struct pipe_context *pipe = st->pipe;
GLuint attr;
const GLubyte *low_addr = NULL;
GLboolean usingVBO; /* all arrays in a VBO? */
struct gl_buffer_object *bufobj;
- GLuint user_buffer_size = 0;
- GLuint vertex_size = 0; /* bytes per vertex, in bytes */
GLsizei stride;
/* Find the lowest address of the arrays we're drawing,
array->Normalized,
array->Integer);
assert(velements[attr].src_format);
-
- if (!usingVBO) {
- /* how many bytes referenced by this attribute array? */
- uint divisor = array->InstanceDivisor;
- uint last_index = divisor ? num_instances / divisor : max_index;
- uint bytes = src_offset + stride * last_index + element_size;
-
- user_buffer_size = MAX2(user_buffer_size, bytes);
-
- /* update vertex size */
- vertex_size = MAX2(vertex_size, src_offset + element_size);
- }
}
/*
if (vpv->num_inputs == 0) {
/* just defensive coding here */
vbuffer->buffer = NULL;
+ vbuffer->user_buffer = NULL;
vbuffer->buffer_offset = 0;
vbuffer->stride = 0;
- st->num_user_attribs = 0;
}
else if (usingVBO) {
/* all interleaved arrays in a VBO */
return GL_FALSE;
}
- vbuffer->buffer = NULL;
- pipe_resource_reference(&vbuffer->buffer, stobj->buffer);
+ vbuffer->buffer = stobj->buffer;
+ vbuffer->user_buffer = NULL;
vbuffer->buffer_offset = pointer_to_offset(low_addr);
vbuffer->stride = stride;
- st->num_user_attribs = 0;
}
else {
/* all interleaved arrays in user memory */
- vbuffer->buffer = pipe_user_buffer_create(pipe->screen,
- (void*) low_addr,
- user_buffer_size,
- PIPE_BIND_VERTEX_BUFFER);
+ vbuffer->buffer = NULL;
+ vbuffer->user_buffer = low_addr;
vbuffer->buffer_offset = 0;
vbuffer->stride = stride;
-
- /* Track user vertex buffers. */
- pipe_resource_reference(&st->user_attrib[0].buffer, vbuffer->buffer);
- st->user_attrib[0].element_size = vertex_size;
- st->user_attrib[0].stride = stride;
- st->num_user_attribs = 1;
}
return GL_TRUE;
const struct st_vp_variant *vpv,
const struct gl_client_array **arrays,
struct pipe_vertex_buffer vbuffer[],
- struct pipe_vertex_element velements[],
- unsigned max_index,
- unsigned num_instances)
+ struct pipe_vertex_element velements[])
{
- struct st_context *st = st_context(ctx);
- struct pipe_context *pipe = st->pipe;
GLuint attr;
for (attr = 0; attr < vpv->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
const struct gl_client_array *array = arrays[mesaAttr];
struct gl_buffer_object *bufobj = array->BufferObj;
- GLuint element_size = array->_ElementSize;
GLsizei stride = array->StrideB;
- assert(element_size == array->Size * _mesa_sizeof_type(array->Type));
+ assert(array->_ElementSize == array->Size * _mesa_sizeof_type(array->Type));
if (_mesa_is_bufferobj(bufobj)) {
/* Attribute data is in a VBO.
return GL_FALSE;
}
- vbuffer[attr].buffer = NULL;
- pipe_resource_reference(&vbuffer[attr].buffer, stobj->buffer);
+ vbuffer[attr].buffer = stobj->buffer;
+ vbuffer[attr].user_buffer = NULL;
vbuffer[attr].buffer_offset = pointer_to_offset(array->Ptr);
}
else {
/* wrap user data */
- uint bytes;
void *ptr;
if (array->Ptr) {
- uint divisor = array->InstanceDivisor;
- uint last_index = divisor ? num_instances / divisor : max_index;
-
- bytes = stride * last_index + element_size;
-
ptr = (void *) array->Ptr;
}
else {
/* no array, use ctx->Current.Attrib[] value */
- bytes = element_size = sizeof(ctx->Current.Attrib[0]);
ptr = (void *) ctx->Current.Attrib[mesaAttr];
stride = 0;
}
assert(ptr);
- assert(bytes);
-
- vbuffer[attr].buffer =
- pipe_user_buffer_create(pipe->screen, ptr, bytes,
- PIPE_BIND_VERTEX_BUFFER);
+ vbuffer[attr].buffer = NULL;
+ vbuffer[attr].user_buffer = ptr;
vbuffer[attr].buffer_offset = 0;
-
- /* Track user vertex buffers. */
- pipe_resource_reference(&st->user_attrib[attr].buffer, vbuffer[attr].buffer);
- st->user_attrib[attr].element_size = element_size;
- st->user_attrib[attr].stride = stride;
- st->num_user_attribs = MAX2(st->num_user_attribs, attr + 1);
-
- if (!vbuffer[attr].buffer) {
- /* probably ran out of memory */
- return GL_FALSE;
- }
}
/* common-case setup */
static void
- setup_index_buffer(struct gl_context *ctx,
+ setup_index_buffer(struct st_context *st,
const struct _mesa_index_buffer *ib,
struct pipe_index_buffer *ibuffer)
{
- struct st_context *st = st_context(ctx);
- struct pipe_context *pipe = st->pipe;
+ struct gl_buffer_object *bufobj = ib->obj;
- memset(ibuffer, 0, sizeof(*ibuffer));
- if (ib) {
- struct gl_buffer_object *bufobj = ib->obj;
-
- ibuffer->index_size = vbo_sizeof_ib_type(ib->type);
+ ibuffer->index_size = vbo_sizeof_ib_type(ib->type);
- /* get/create the index buffer object */
- if (_mesa_is_bufferobj(bufobj)) {
- /* elements/indexes are in a real VBO */
- struct st_buffer_object *stobj = st_buffer_object(bufobj);
- pipe_resource_reference(&ibuffer->buffer, stobj->buffer);
- ibuffer->offset = pointer_to_offset(ib->ptr);
- }
- else {
- /* element/indicies are in user space memory */
- ibuffer->buffer =
- pipe_user_buffer_create(pipe->screen, (void *) ib->ptr,
- ib->count * ibuffer->index_size,
- PIPE_BIND_INDEX_BUFFER);
- }
+ /* get/create the index buffer object */
+ if (_mesa_is_bufferobj(bufobj)) {
+ /* indices are in a real VBO */
+ ibuffer->buffer = st_buffer_object(bufobj)->buffer;
+ ibuffer->offset = pointer_to_offset(ib->ptr);
}
+ else if (st->indexbuf_uploader) {
+ u_upload_data(st->indexbuf_uploader, 0, ib->count * ibuffer->index_size,
+ ib->ptr, &ibuffer->offset, &ibuffer->buffer);
+ u_upload_unmap(st->indexbuf_uploader);
+ }
+ else {
+ /* indices are in user space memory */
+ ibuffer->user_buffer = ib->ptr;
+ }
+
+ cso_set_index_buffer(st->cso_context, ibuffer);
}
unsigned num_sub_prims;
assert(info.indexed);
- assert(ibuffer->buffer);
+ assert(ibuffer->buffer || ibuffer->user_buffer);
assert(ib);
- if (!ibuffer->buffer || !ib)
+ if (!ibuffer->buffer || !ibuffer->user_buffer || !ib)
return;
info.primitive_restart = FALSE;
*/
static GLboolean
st_validate_varrays(struct gl_context *ctx,
- const struct gl_client_array **arrays,
- unsigned max_index,
- unsigned num_instances)
+ const struct gl_client_array **arrays)
{
struct st_context *st = st_context(ctx);
const struct st_vertex_program *vp;
struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
unsigned num_vbuffers, num_velements;
- GLuint attr;
- unsigned i;
/* must get these after state validation! */
vp = st->vp;
memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs);
- /* Unreference any user vertex buffers. */
- for (i = 0; i < st->num_user_attribs; i++) {
- pipe_resource_reference(&st->user_attrib[i].buffer, NULL);
- }
- st->num_user_attribs = 0;
-
/*
* Setup the vbuffer[] and velements[] arrays.
*/
if (is_interleaved_arrays(vp, vpv, arrays)) {
- if (!setup_interleaved_attribs(ctx, vp, vpv, arrays, vbuffer, velements,
- max_index, num_instances)) {
+ if (!setup_interleaved_attribs(ctx, vp, vpv, arrays, vbuffer,
+ velements)) {
return GL_FALSE;
}
}
else {
if (!setup_non_interleaved_attribs(ctx, vp, vpv, arrays,
- vbuffer, velements, max_index,
- num_instances)) {
+ vbuffer, velements)) {
return GL_FALSE;
}
cso_set_vertex_buffers(st->cso_context, num_vbuffers, vbuffer);
cso_set_vertex_elements(st->cso_context, num_velements, velements);
- /* unreference buffers (frees wrapped user-space buffer objects)
- * This is OK, because the pipe driver should reference buffers by itself
- * in set_vertex_buffers. */
- for (attr = 0; attr < num_vbuffers; attr++) {
- pipe_resource_reference(&vbuffer[attr].buffer, NULL);
- assert(!vbuffer[attr].buffer);
- }
-
return GL_TRUE;
}
*/
void
st_draw_vbo(struct gl_context *ctx,
- const struct gl_client_array **arrays,
const struct _mesa_prim *prims,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
- struct pipe_index_buffer ibuffer;
+ struct pipe_index_buffer ibuffer = {0};
struct pipe_draw_info info;
- unsigned i, num_instances = 1;
- unsigned max_index_plus_base;
+ const struct gl_client_array **arrays = ctx->Array._DrawArrays;
- GLboolean new_array =
- st->dirty.st &&
- (st->dirty.mesa & (_NEW_ARRAY | _NEW_PROGRAM | _NEW_BUFFER_OBJECT)) != 0;
+ unsigned i;
+ GLboolean new_array;
/* Mesa core state should have been validated already */
assert(ctx->NewState == 0x0);
- if (ib) {
- int max_base_vertex = 0;
-
- /* Gallium probably doesn't want this in some cases. */
- if (!index_bounds_valid)
- if (!all_varyings_in_vbos(arrays))
- vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index,
- nr_prims);
-
- for (i = 0; i < nr_prims; i++) {
- num_instances = MAX2(num_instances, prims[i].num_instances);
- max_base_vertex = MAX2(max_base_vertex, prims[i].basevertex);
- }
-
- /* Compute the sum of max_index and max_base_vertex. That's the value
- * we need to use when creating buffers.
- */
- if (max_index == ~0)
- max_index_plus_base = max_index;
- else
- max_index_plus_base = max_index + max_base_vertex;
- }
- else {
- /* Get min/max index for non-indexed drawing. */
- min_index = ~0;
- max_index = 0;
-
- for (i = 0; i < nr_prims; i++) {
- min_index = MIN2(min_index, prims[i].start);
- max_index = MAX2(max_index, prims[i].start + prims[i].count - 1);
- num_instances = MAX2(num_instances, prims[i].num_instances);
- }
-
- /* The base vertex offset only applies to indexed drawing */
- max_index_plus_base = max_index;
- }
-
+ /* Get Mesa driver state. */
+ st->dirty.st |= ctx->NewDriverState;
+ ctx->NewDriverState = 0;
+
+ new_array =
+ (st->dirty.st & (ST_NEW_VERTEX_ARRAYS | ST_NEW_VERTEX_PROGRAM)) ||
+ (st->dirty.mesa & (_NEW_PROGRAM | _NEW_BUFFER_OBJECT)) != 0;
+
/* Validate state. */
if (st->dirty.st) {
GLboolean vertDataEdgeFlags;
st_validate_state(st);
if (new_array) {
- if (!st_validate_varrays(ctx, arrays, max_index_plus_base,
- num_instances)) {
+ if (!st_validate_varrays(ctx, arrays)) {
/* probably out of memory, no-op the draw call */
return;
}
#endif
}
- /* Notify the driver that the content of user buffers may have been
- * changed. */
- assert(max_index >= min_index);
- if (!new_array && st->num_user_attribs) {
- for (i = 0; i < st->num_user_attribs; i++) {
- if (st->user_attrib[i].buffer) {
- unsigned element_size = st->user_attrib[i].element_size;
- unsigned stride = st->user_attrib[i].stride;
- unsigned min_offset = min_index * stride;
- unsigned max_offset = max_index_plus_base * stride + element_size;
-
- assert(max_offset > min_offset);
-
- pipe->redefine_user_buffer(pipe, st->user_attrib[i].buffer,
- min_offset,
- max_offset - min_offset);
- }
- }
- }
-
- setup_index_buffer(ctx, ib, &ibuffer);
- cso_set_index_buffer(st->cso_context, &ibuffer);
-
util_draw_init_info(&info);
if (ib) {
+ /* Get index bounds for user buffers. */
+ if (!index_bounds_valid)
+ if (!all_varyings_in_vbos(arrays))
+ vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index,
+ nr_prims);
+
+ setup_index_buffer(st, ib, &ibuffer);
+
info.indexed = TRUE;
if (min_index != ~0 && max_index != ~0) {
info.min_index = min_index;
info.primitive_restart = ctx->Array.PrimitiveRestart;
info.restart_index = ctx->Array.RestartIndex;
}
-
- /* Set info.count_from_stream_output. */
- if (tfb_vertcount) {
- st_transform_feedback_draw_init(tfb_vertcount, &info);
+ else {
+ /* Transform feedback drawing is always non-indexed. */
+ /* Set info.count_from_stream_output. */
+ if (tfb_vertcount) {
+ st_transform_feedback_draw_init(tfb_vertcount, &info);
+ }
}
/* do actual drawing */
cso_draw_vbo(st->cso_context, &info);
}
- pipe_resource_reference(&ibuffer.buffer, NULL);
+ if (ib && st->indexbuf_uploader && !_mesa_is_bufferobj(ib->obj)) {
+ pipe_resource_reference(&ibuffer.buffer, NULL);
+ }
}
*/
void
st_feedback_draw_vbo(struct gl_context *ctx,
- const struct gl_client_array **arrays,
const struct _mesa_prim *prims,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
struct pipe_vertex_buffer vbuffers[PIPE_MAX_SHADER_INPUTS];
struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
struct pipe_index_buffer ibuffer;
- struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
+ struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {NULL};
struct pipe_transfer *ib_transfer = NULL;
+ const struct gl_client_array **arrays = ctx->Array._DrawArrays;
GLuint attr, i;
const GLubyte *low_addr = NULL;
const void *mapped_indices = NULL;
assert(stobj->buffer);
vbuffers[attr].buffer = NULL;
+ vbuffers[attr].user_buffer = NULL;
pipe_resource_reference(&vbuffers[attr].buffer, stobj->buffer);
vbuffers[attr].buffer_offset = pointer_to_offset(low_addr);
velements[attr].src_offset = arrays[mesaAttr]->Ptr - low_addr;
+
+ /* map the attrib buffer */
+ map = pipe_buffer_map(pipe, vbuffers[attr].buffer,
+ PIPE_TRANSFER_READ,
+ &vb_transfer[attr]);
+ draw_set_mapped_vertex_buffer(draw, attr, map);
}
else {
- /* attribute data is in user-space memory, not a VBO */
- uint bytes = (arrays[mesaAttr]->Size
- * _mesa_sizeof_type(arrays[mesaAttr]->Type)
- * (max_index + 1));
-
- /* wrap user data */
- vbuffers[attr].buffer
- = pipe_user_buffer_create(pipe->screen, (void *) arrays[mesaAttr]->Ptr,
- bytes,
- PIPE_BIND_VERTEX_BUFFER);
+ vbuffers[attr].buffer = NULL;
+ vbuffers[attr].user_buffer = arrays[mesaAttr]->Ptr;
vbuffers[attr].buffer_offset = 0;
velements[attr].src_offset = 0;
+
+ draw_set_mapped_vertex_buffer(draw, attr, vbuffers[attr].user_buffer);
}
/* common-case setup */
#if 0
draw_set_vertex_buffer(draw, attr, &vbuffer[attr]);
#endif
-
- /* map the attrib buffer */
- map = pipe_buffer_map(pipe, vbuffers[attr].buffer,
- PIPE_TRANSFER_READ,
- &vb_transfer[attr]);
- draw_set_mapped_vertex_buffer(draw, attr, map);
}
draw_set_vertex_buffers(draw, vp->num_inputs, vbuffers);
out_unref_vertex:
for (attr = 0; attr < vp->num_inputs; attr++) {
- pipe_buffer_unmap(pipe, vb_transfer[attr]);
+ if (vb_transfer[attr])
+ pipe_buffer_unmap(pipe, vb_transfer[attr]);
draw_set_mapped_vertex_buffer(draw, attr, NULL);
pipe_resource_reference(&vbuffers[attr].buffer, NULL);
}