Browse Source

nvc0: implement transform feedback state

tags/android-x86-2.2-r2
Christoph Bumiller 15 years ago
parent
commit
f8a7a0b6f3

+ 17
- 3
src/gallium/drivers/nvc0/nvc0_3d.xml.h View File

@@ -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


+ 9
- 0
src/gallium/drivers/nvc0/nvc0_context.h View File

@@ -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 *);


+ 57
- 1
src/gallium/drivers/nvc0/nvc0_shader_state.c View File

@@ -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);
}

+ 73
- 0
src/gallium/drivers/nvc0/nvc0_state.c View File

@@ -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;
}


+ 2
- 1
src/gallium/drivers/nvc0/nvc0_state_validate.c View File

@@ -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]))


+ 4
- 4
src/gallium/drivers/nvc0/nvc0_stateobj.h View File

@@ -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

+ 1
- 50
src/gallium/drivers/nvc0/nvc0_vbo.c View File

@@ -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…
Cancel
Save