mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 09:38:07 +02:00
nvc0: implement transform feedback state
This commit is contained in:
parent
7fd29468ec
commit
f8a7a0b6f3
7 changed files with 163 additions and 59 deletions
|
|
@ -84,6 +84,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#define NVC0_3D_EARLY_FRAGMENT_TESTS 0x00000210
|
||||
|
||||
#define NVC0_3D_MEM_BARRIER 0x0000021c
|
||||
#define NVC0_3D_MEM_BARRIER_UNK0 0x00000001
|
||||
#define NVC0_3D_MEM_BARRIER_UNK1 0x00000002
|
||||
#define NVC0_3D_MEM_BARRIER_UNK2 0x00000004
|
||||
#define NVC0_3D_MEM_BARRIER_UNK4 0x00000010
|
||||
#define NVC0_3D_MEM_BARRIER_UNK8 0x00000100
|
||||
#define NVC0_3D_MEM_BARRIER_UNK12 0x00001000
|
||||
|
||||
#define NVC0_3D_TESS_MODE 0x00000320
|
||||
#define NVC0_3D_TESS_MODE_PRIM__MASK 0x0000000f
|
||||
#define NVC0_3D_TESS_MODE_PRIM__SHIFT 0
|
||||
|
|
@ -122,11 +130,17 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#define NVC0_3D_TFB_PRIMITIVE_ID(i0) (0x00000390 + 0x20*(i0))
|
||||
|
||||
#define NVC0_3D_TFB_UNK0700(i0) (0x00000700 + 0x10*(i0))
|
||||
#define NVC0_3D_TFB_UNK07X0(i0) (0x00000700 + 0x10*(i0))
|
||||
#define NVC0_3D_TFB_UNK07X0__ESIZE 0x00000010
|
||||
#define NVC0_3D_TFB_UNK07X0__LEN 0x00000004
|
||||
|
||||
#define NVC0_3D_TFB_VARYING_COUNT(i0) (0x00000704 + 0x10*(i0))
|
||||
#define NVC0_3D_TFB_VARYING_COUNT__ESIZE 0x00000010
|
||||
#define NVC0_3D_TFB_VARYING_COUNT__LEN 0x00000004
|
||||
|
||||
#define NVC0_3D_TFB_BUFFER_STRIDE(i0) (0x00000708 + 0x10*(i0))
|
||||
#define NVC0_3D_TFB_BUFFER_STRIDE__ESIZE 0x00000010
|
||||
#define NVC0_3D_TFB_BUFFER_STRIDE__LEN 0x00000004
|
||||
|
||||
#define NVC0_3D_TFB_ENABLE 0x00000744
|
||||
|
||||
|
|
@ -1157,9 +1171,9 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||
|
||||
#define NVC0_3D_VERT_COLOR_CLAMP_EN 0x00002600
|
||||
|
||||
#define NVC0_3D_TFB_VARYING_LOCS(i0) (0x00002800 + 0x4*(i0))
|
||||
#define NVC0_3D_TFB_VARYING_LOCS(i0, i1) (0x00002800 + 0x80*(i0) + 0x4*(i1))
|
||||
#define NVC0_3D_TFB_VARYING_LOCS__ESIZE 0x00000004
|
||||
#define NVC0_3D_TFB_VARYING_LOCS__LEN 0x00000080
|
||||
#define NVC0_3D_TFB_VARYING_LOCS__LEN 0x00000020
|
||||
|
||||
#define NVC0_3D_COLOR_MASK_BROADCAST 0x00003808
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,8 @@
|
|||
#define NVC0_NEW_CONSTBUF (1 << 18)
|
||||
#define NVC0_NEW_TEXTURES (1 << 19)
|
||||
#define NVC0_NEW_SAMPLERS (1 << 20)
|
||||
#define NVC0_NEW_TFB (1 << 21)
|
||||
#define NVC0_NEW_TFB_BUFFERS (1 << 22)
|
||||
|
||||
#define NVC0_BUFCTX_CONSTANT 0
|
||||
#define NVC0_BUFCTX_FRAME 1
|
||||
|
|
@ -123,6 +125,11 @@ struct nvc0_context {
|
|||
boolean vbo_dirty;
|
||||
boolean vbo_push_hint;
|
||||
|
||||
struct nvc0_transform_feedback_state *tfb;
|
||||
struct pipe_resource *tfbbuf[4];
|
||||
unsigned num_tfbbufs;
|
||||
unsigned tfb_offset[4];
|
||||
|
||||
struct draw_context *draw;
|
||||
};
|
||||
|
||||
|
|
@ -177,6 +184,8 @@ void nvc0_tevlprog_validate(struct nvc0_context *);
|
|||
void nvc0_gmtyprog_validate(struct nvc0_context *);
|
||||
void nvc0_fragprog_validate(struct nvc0_context *);
|
||||
|
||||
void nvc0_tfb_validate(struct nvc0_context *);
|
||||
|
||||
/* nvc0_state.c */
|
||||
extern void nvc0_init_state_functions(struct nvc0_context *);
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ nvc0_program_validate(struct nvc0_context *nvc0, struct nvc0_program *prog)
|
|||
prog->code_base + NVC0_SHADER_HEADER_SIZE,
|
||||
prog->code_size, prog->code);
|
||||
|
||||
BEGIN_RING(nvc0->screen->base.channel, RING_3D_(0x021c), 1);
|
||||
BEGIN_RING(nvc0->screen->base.channel, RING_3D(MEM_BARRIER), 1);
|
||||
OUT_RING (nvc0->screen->base.channel, 0x1111);
|
||||
|
||||
return TRUE;
|
||||
|
|
@ -178,3 +178,59 @@ nvc0_gmtyprog_validate(struct nvc0_context *nvc0)
|
|||
BEGIN_RING(chan, RING_3D(SP_GPR_ALLOC(4)), 1);
|
||||
OUT_RING (chan, gp->max_gpr);
|
||||
}
|
||||
|
||||
/* It's *is* kind of shader related. We need to inspect the program
|
||||
* to get the output locations right.
|
||||
*/
|
||||
void
|
||||
nvc0_tfb_validate(struct nvc0_context *nvc0)
|
||||
{
|
||||
struct nouveau_channel *chan = nvc0->screen->base.channel;
|
||||
struct nvc0_program *vp;
|
||||
struct nvc0_transform_feedback_state *tfb = nvc0->tfb;
|
||||
int b;
|
||||
|
||||
BEGIN_RING(chan, RING_3D(TFB_ENABLE), 1);
|
||||
if (!tfb) {
|
||||
OUT_RING(chan, 0);
|
||||
return;
|
||||
}
|
||||
OUT_RING(chan, 1);
|
||||
|
||||
vp = nvc0->vertprog ? nvc0->vertprog : nvc0->gmtyprog;
|
||||
|
||||
for (b = 0; b < nvc0->num_tfbbufs; ++b) {
|
||||
uint8_t idx, var[128];
|
||||
int i, n;
|
||||
struct nvc0_resource *buf = nvc0_resource(nvc0->tfbbuf[b]);
|
||||
|
||||
BEGIN_RING(chan, RING_3D(TFB_BUFFER_ENABLE(b)), 5);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RESRCh(chan, buf, nvc0->tfb_offset[b], NOUVEAU_BO_WR);
|
||||
OUT_RESRCl(chan, buf, nvc0->tfb_offset[b], NOUVEAU_BO_WR);
|
||||
OUT_RING (chan, buf->base.width0 - nvc0->tfb_offset[b]);
|
||||
OUT_RING (chan, 0); /* TFB_PRIMITIVE_ID <- offset ? */
|
||||
|
||||
if (!(nvc0->dirty & NVC0_NEW_TFB))
|
||||
continue;
|
||||
|
||||
BEGIN_RING(chan, RING_3D(TFB_UNK07X0(b)), 3);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, tfb->varying_count[b]);
|
||||
OUT_RING (chan, tfb->stride[b]);
|
||||
|
||||
n = b ? tfb->varying_count[b - 1] : 0;
|
||||
i = 0;
|
||||
for (; i < tfb->varying_count[b]; ++i) {
|
||||
idx = tfb->varying_index[n + i];
|
||||
var[i] = vp->vp.out_pos[idx >> 2] + (idx & 3);
|
||||
}
|
||||
for (; i & 3; ++i)
|
||||
var[i] = 0;
|
||||
|
||||
BEGIN_RING(chan, RING_3D(TFB_VARYING_LOCS(b, 0)), i / 4);
|
||||
OUT_RINGp (chan, var, i / 4);
|
||||
}
|
||||
for (; b < 4; ++b)
|
||||
IMMED_RING(chan, RING_3D(TFB_BUFFER_ENABLE(b)), 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -808,6 +808,74 @@ nvc0_vertex_state_bind(struct pipe_context *pipe, void *hwcso)
|
|||
nvc0->dirty |= NVC0_NEW_VERTEX;
|
||||
}
|
||||
|
||||
static void *
|
||||
nvc0_tfb_state_create(struct pipe_context *pipe,
|
||||
const struct pipe_stream_output_state *pso)
|
||||
{
|
||||
struct nvc0_transform_feedback_state *so;
|
||||
int n = 0;
|
||||
int i, c, b;
|
||||
|
||||
so = MALLOC(sizeof(*so) + pso->num_outputs * 4 * sizeof(uint8_t));
|
||||
if (!so)
|
||||
return NULL;
|
||||
|
||||
for (b = 0; b < 4; ++b) {
|
||||
for (i = 0; i < pso->num_outputs; ++i) {
|
||||
if (pso->output_buffer[i] != b)
|
||||
continue;
|
||||
for (c = 0; c < 4; ++c) {
|
||||
if (!(pso->register_mask[i] & (1 << c)))
|
||||
continue;
|
||||
so->varying_count[b]++;
|
||||
so->varying_index[n++] = (pso->register_index[i] << 2) | c;
|
||||
}
|
||||
}
|
||||
so->stride[b] = so->varying_count[b] * 4;
|
||||
}
|
||||
if (pso->stride)
|
||||
so->stride[0] = pso->stride;
|
||||
|
||||
return so;
|
||||
}
|
||||
|
||||
static void
|
||||
nvc0_tfb_state_delete(struct pipe_context *pipe, void *hwcso)
|
||||
{
|
||||
FREE(hwcso);
|
||||
}
|
||||
|
||||
static void
|
||||
nvc0_tfb_state_bind(struct pipe_context *pipe, void *hwcso)
|
||||
{
|
||||
nvc0_context(pipe)->tfb = hwcso;
|
||||
nvc0_context(pipe)->dirty |= NVC0_NEW_TFB;
|
||||
}
|
||||
|
||||
static void
|
||||
nvc0_set_transform_feedback_buffers(struct pipe_context *pipe,
|
||||
struct pipe_resource **buffers,
|
||||
int *offsets,
|
||||
int num_buffers)
|
||||
{
|
||||
struct nvc0_context *nvc0 = nvc0_context(pipe);
|
||||
int i;
|
||||
|
||||
assert(num_buffers >= 0 && num_buffers <= 4); /* why signed ? */
|
||||
|
||||
for (i = 0; i < num_buffers; ++i) {
|
||||
assert(offsets[i] >= 0);
|
||||
nvc0->tfb_offset[i] = offsets[i];
|
||||
pipe_resource_reference(&nvc0->tfbbuf[i], buffers[i]);
|
||||
}
|
||||
for (; i < nvc0->num_tfbbufs; ++i)
|
||||
pipe_resource_reference(&nvc0->tfbbuf[i], NULL);
|
||||
|
||||
nvc0->num_tfbbufs = num_buffers;
|
||||
|
||||
nvc0->dirty |= NVC0_NEW_TFB_BUFFERS;
|
||||
}
|
||||
|
||||
void
|
||||
nvc0_init_state_functions(struct nvc0_context *nvc0)
|
||||
{
|
||||
|
|
@ -861,5 +929,10 @@ nvc0_init_state_functions(struct nvc0_context *nvc0)
|
|||
|
||||
nvc0->pipe.set_vertex_buffers = nvc0_set_vertex_buffers;
|
||||
nvc0->pipe.set_index_buffer = nvc0_set_index_buffer;
|
||||
|
||||
nvc0->pipe.create_stream_output_state = nvc0_tfb_state_create;
|
||||
nvc0->pipe.delete_stream_output_state = nvc0_tfb_state_delete;
|
||||
nvc0->pipe.bind_stream_output_state = nvc0_tfb_state_bind;
|
||||
nvc0->pipe.set_stream_output_buffers = nvc0_set_transform_feedback_buffers;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -436,7 +436,8 @@ static struct state_validate {
|
|||
{ nvc0_constbufs_validate, NVC0_NEW_CONSTBUF },
|
||||
{ nvc0_validate_textures, NVC0_NEW_TEXTURES },
|
||||
{ nvc0_validate_samplers, NVC0_NEW_SAMPLERS },
|
||||
{ nvc0_vertex_arrays_validate, NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS }
|
||||
{ nvc0_vertex_arrays_validate, NVC0_NEW_VERTEX | NVC0_NEW_ARRAYS },
|
||||
{ nvc0_tfb_validate, NVC0_NEW_TFB | NVC0_NEW_TFB_BUFFERS }
|
||||
};
|
||||
#define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
|
||||
|
||||
|
|
|
|||
|
|
@ -69,14 +69,14 @@ struct nvc0_vertex_stateobj {
|
|||
uint32_t instance_bufs;
|
||||
unsigned vtx_size;
|
||||
unsigned vtx_per_packet_max;
|
||||
struct nvc0_vertex_element element[1];
|
||||
struct nvc0_vertex_element element[0];
|
||||
};
|
||||
|
||||
/* will have to lookup index -> location qualifier from nvc0_program */
|
||||
struct nvc0_tfb_state {
|
||||
uint8_t varying_count[4];
|
||||
struct nvc0_transform_feedback_state {
|
||||
uint32_t stride[4];
|
||||
uint8_t varying_indices[1];
|
||||
uint8_t varying_count[4];
|
||||
uint8_t varying_index[0];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ nvc0_vertex_state_create(struct pipe_context *pipe,
|
|||
assert(num_elements);
|
||||
|
||||
so = MALLOC(sizeof(*so) +
|
||||
(num_elements - 1) * sizeof(struct nvc0_vertex_element));
|
||||
num_elements * sizeof(struct nvc0_vertex_element));
|
||||
if (!so)
|
||||
return NULL;
|
||||
so->num_elements = num_elements;
|
||||
|
|
@ -351,55 +351,6 @@ nvc0_draw_vbo_flush_notify(struct nouveau_channel *chan)
|
|||
nvc0_bufctx_emit_relocs(nvc0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static struct nouveau_bo *
|
||||
nvc0_tfb_setup(struct nvc0_context *nvc0)
|
||||
{
|
||||
struct nouveau_channel *chan = nvc0->screen->base.channel;
|
||||
struct nouveau_bo *tfb = NULL;
|
||||
int ret, i;
|
||||
|
||||
ret = nouveau_bo_new(nvc0->screen->base.device,
|
||||
NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0, 4096, &tfb);
|
||||
if (ret)
|
||||
return NULL;
|
||||
|
||||
ret = nouveau_bo_map(tfb, NOUVEAU_BO_WR);
|
||||
if (ret)
|
||||
return NULL;
|
||||
memset(tfb->map, 0xee, 8 * 4 * 3);
|
||||
nouveau_bo_unmap(tfb);
|
||||
|
||||
BEGIN_RING(chan, RING_3D(TFB_ENABLE), 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, RING_3D(TFB_BUFFER_ENABLE(0)), 5);
|
||||
OUT_RING (chan, 1);
|
||||
OUT_RELOCh(chan, tfb, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR);
|
||||
OUT_RELOCl(chan, tfb, 0, NOUVEAU_BO_GART | NOUVEAU_BO_WR);
|
||||
OUT_RING (chan, tfb->size);
|
||||
OUT_RING (chan, 0); /* TFB_PRIMITIVE_ID(0) */
|
||||
BEGIN_RING(chan, RING_3D(TFB_UNK0700(0)), 3);
|
||||
OUT_RING (chan, 0);
|
||||
OUT_RING (chan, 8); /* TFB_VARYING_COUNT(0) */
|
||||
OUT_RING (chan, 32); /* TFB_BUFFER_STRIDE(0) */
|
||||
BEGIN_RING(chan, RING_3D(TFB_VARYING_LOCS(0)), 2);
|
||||
OUT_RING (chan, 0x1f1e1d1c);
|
||||
OUT_RING (chan, 0xa3a2a1a0);
|
||||
for (i = 1; i < 4; ++i) {
|
||||
BEGIN_RING(chan, RING_3D(TFB_BUFFER_ENABLE(i)), 1);
|
||||
OUT_RING (chan, 0);
|
||||
}
|
||||
BEGIN_RING(chan, RING_3D(TFB_ENABLE), 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, RING_3D_(0x135c), 1);
|
||||
OUT_RING (chan, 1);
|
||||
BEGIN_RING(chan, RING_3D_(0x135c), 1);
|
||||
OUT_RING (chan, 0);
|
||||
|
||||
return tfb;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
nvc0_draw_arrays(struct nvc0_context *nvc0,
|
||||
unsigned mode, unsigned start, unsigned count,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue