Browse Source

nv50,nvc0: handle user constbufs without wrapping them in a resource

tags/i965-primitive-restart-v2
Christoph Bumiller 13 years ago
parent
commit
fcb2868210

+ 3
- 2
src/gallium/drivers/nv50/nv50_context.c View File

@@ -86,8 +86,9 @@ nv50_context_unreference_resources(struct nv50_context *nv50)
for (i = 0; i < nv50->num_textures[s]; ++i)
pipe_sampler_view_reference(&nv50->textures[s][i], NULL);

for (i = 0; i < 16; ++i)
pipe_resource_reference(&nv50->constbuf[s][i], NULL);
for (i = 0; i < NV50_MAX_PIPE_CONSTBUFS; ++i)
if (!nv50->constbuf[s][i].user)
pipe_resource_reference(&nv50->constbuf[s][i].u.buf, NULL);
}
}


+ 16
- 1
src/gallium/drivers/nv50/nv50_context.h View File

@@ -90,6 +90,7 @@ struct nv50_context {
uint32_t semantic_color;
uint32_t semantic_psize;
int32_t index_bias;
boolean uniform_buffer_bound[3];
boolean prim_restart;
boolean point_sprite;
boolean rt_serialize;
@@ -113,7 +114,7 @@ struct nv50_context {
struct nv50_program *gmtyprog;
struct nv50_program *fragprog;

struct pipe_resource *constbuf[3][16];
struct nv50_constbuf constbuf[3][NV50_MAX_PIPE_CONSTBUFS];
uint16_t constbuf_dirty[3];
uint16_t constbuf_valid[3];

@@ -163,6 +164,20 @@ nv50_context_screen(struct nv50_context *nv50)
return nv50_screen(&nv50->base.screen->base);
}

/* return index used in nv50_context arrays for a specific shader type */
static INLINE unsigned
nv50_context_shader_stage(unsigned pipe)
{
switch (pipe) {
case PIPE_SHADER_VERTEX: return 0;
case PIPE_SHADER_FRAGMENT: return 1;
case PIPE_SHADER_GEOMETRY: return 2;
case PIPE_SHADER_COMPUTE: return 3;
default:
assert(!"invalid/unhandled shader type");
return 0;
}
}

/* nv50_context.c */
struct pipe_context *nv50_create(struct pipe_screen *, void *);

+ 2
- 5
src/gallium/drivers/nv50/nv50_screen.c View File

@@ -196,7 +196,7 @@ nv50_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader,
case PIPE_SHADER_CAP_MAX_CONSTS:
return 65536 / 16;
case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
return 14;
return NV50_MAX_PIPE_CONSTBUFS;
case PIPE_SHADER_CAP_MAX_ADDRS:
return 1;
case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
@@ -437,10 +437,7 @@ nv50_screen_init_hwctx(struct nv50_screen *screen, unsigned tls_space)
PUSH_DATA (push, screen->uniforms->offset + (3 << 16));
PUSH_DATA (push, (NV50_CB_AUX << 16) | 0x0200);

BEGIN_NI04(push, NV50_3D(SET_PROGRAM_CB), 6);
PUSH_DATA (push, (NV50_CB_PVP << 12) | 0x001);
PUSH_DATA (push, (NV50_CB_PGP << 12) | 0x021);
PUSH_DATA (push, (NV50_CB_PFP << 12) | 0x031);
BEGIN_NI04(push, NV50_3D(SET_PROGRAM_CB), 3);
PUSH_DATA (push, (NV50_CB_AUX << 12) | 0xf01);
PUSH_DATA (push, (NV50_CB_AUX << 12) | 0xf21);
PUSH_DATA (push, (NV50_CB_AUX << 12) | 0xf31);

+ 3
- 0
src/gallium/drivers/nv50/nv50_screen.h View File

@@ -12,6 +12,9 @@
#define NV50_TIC_MAX_ENTRIES 2048
#define NV50_TSC_MAX_ENTRIES 2048

/* doesn't count reserved slots (for auxiliary constants, immediates, etc.) */
#define NV50_MAX_PIPE_CONSTBUFS 14

struct nv50_context;

#define NV50_CODE_BO_SIZE_LOG2 19

+ 51
- 58
src/gallium/drivers/nv50/nv50_shader_state.c View File

@@ -35,9 +35,7 @@ nv50_constbufs_validate(struct nv50_context *nv50)
unsigned s;

for (s = 0; s < 3; ++s) {
struct nv04_resource *res;
int i;
unsigned p, b;
unsigned p;

if (s == PIPE_SHADER_FRAGMENT)
p = NV50_3D_SET_PROGRAM_CB_PROGRAM_FRAGMENT;
@@ -48,68 +46,63 @@ nv50_constbufs_validate(struct nv50_context *nv50)
p = NV50_3D_SET_PROGRAM_CB_PROGRAM_VERTEX;

while (nv50->constbuf_dirty[s]) {
struct nouveau_bo *bo;
unsigned start = 0;
unsigned words = 0;

i = ffs(nv50->constbuf_dirty[s]) - 1;
const int i = ffs(nv50->constbuf_dirty[s]) - 1;
nv50->constbuf_dirty[s] &= ~(1 << i);

res = nv04_resource(nv50->constbuf[s][i]);
if (!res) {
if (i != 0) {
if (nv50->constbuf[s][i].user) {
const unsigned b = NV50_CB_PVP + s;
unsigned start = 0;
unsigned words = nv50->constbuf[s][0].size / 4;
if (i) {
NOUVEAU_ERR("user constbufs only supported in slot 0\n");
continue;
}
if (!nv50->state.uniform_buffer_bound[s]) {
nv50->state.uniform_buffer_bound[s] = TRUE;
BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
PUSH_DATA (push, (i << 8) | p | 0);
PUSH_DATA (push, (b << 12) | (i << 8) | p | 1);
}
while (words) {
unsigned nr;

if (!PUSH_SPACE(push, 16))
break;
nr = PUSH_AVAIL(push);
assert(nr >= 16);
nr = MIN2(MIN2(nr - 3, words), NV04_PFIFO_MAX_PACKET_LEN);

BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
PUSH_DATA (push, (start << 8) | b);
BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nr);
PUSH_DATAp(push, &nv50->constbuf[s][0].u.data[start * 4], nr);

start += nr;
words -= nr;
}
continue;
}

if (i == 0) {
b = NV50_CB_PVP + s;

/* always upload GL uniforms through CB DATA */
bo = nv50->screen->uniforms;
words = res->base.width0 / 4;
} else {
b = s * 16 + i;

assert(0);

if (!nouveau_resource_mapped_by_gpu(&res->base)) {
nouveau_buffer_migrate(&nv50->base, res, NOUVEAU_BO_VRAM);
struct nv04_resource *res =
nv04_resource(nv50->constbuf[s][i].u.buf);
if (res) {
/* TODO: allocate persistent bindings */
const unsigned b = s * 16 + i;

assert(nouveau_resource_mapped_by_gpu(&res->base));

BEGIN_NV04(push, NV50_3D(CB_DEF_ADDRESS_HIGH), 3);
PUSH_DATAh(push, res->address + nv50->constbuf[s][i].offset);
PUSH_DATA (push, res->address + nv50->constbuf[s][i].offset);
PUSH_DATA (push, (b << 16) |
(nv50->constbuf[s][i].size & 0xffff));
BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
PUSH_DATA (push, (b << 12) | (i << 8) | p | 1);

BEGIN_NV04(push, NV50_3D(CODE_CB_FLUSH), 1);
PUSH_DATA (push, 0);
BCTX_REFN(nv50->bufctx_3d, CB(s, i), res, RD);
} else {
BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
PUSH_DATA (push, (i << 8) | p | 0);
}
BEGIN_NV04(push, NV50_3D(CB_DEF_ADDRESS_HIGH), 3);
PUSH_DATAh(push, res->address);
PUSH_DATA (push, res->address);
PUSH_DATA (push, (b << 16) | (res->base.width0 & 0xffff));
BEGIN_NV04(push, NV50_3D(SET_PROGRAM_CB), 1);
PUSH_DATA (push, (b << 12) | (i << 8) | p | 1);

bo = res->bo;
}

if (bo != nv50->screen->uniforms)
BCTX_REFN(nv50->bufctx_3d, CB(s, i), res, RD);

while (words) {
unsigned nr;

if (!PUSH_SPACE(push, 16))
break;
nr = PUSH_AVAIL(push);
assert(nr >= 16);
nr = MIN2(MIN2(nr - 3, words), NV04_PFIFO_MAX_PACKET_LEN);

BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
PUSH_DATA (push, (start << 8) | b);
BEGIN_NI04(push, NV50_3D(CB_DATA(0)), nr);
PUSH_DATAp(push, &res->data[start * 4], nr);

start += nr;
words -= nr;
if (i == 0)
nv50->state.uniform_buffer_bound[s] = FALSE;
}
}
}

+ 25
- 17
src/gallium/drivers/nv50/nv50_state.c View File

@@ -751,28 +751,36 @@ nv50_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
{
struct nv50_context *nv50 = nv50_context(pipe);
struct pipe_resource *res = cb ? cb->buffer : NULL;
const unsigned s = nv50_context_shader_stage(shader);
const unsigned i = index;

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);
if (shader == PIPE_SHADER_COMPUTE)
return;

nv50->constbuf_dirty[shader] |= 1 << index;
if (res)
nv50->constbuf_valid[shader] |= 1 << index;
if (nv50->constbuf[s][i].user)
nv50->constbuf[s][i].u.buf = NULL;
else
nv50->constbuf_valid[shader] &= ~(1 << index);

nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_CB(shader, index));
if (nv50->constbuf[s][i].u.buf)
nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_CB(s, i));

pipe_resource_reference(&nv50->constbuf[s][i].u.buf, res);

nv50->constbuf[s][i].user = (cb && cb->user_buffer) ? TRUE : FALSE;
if (nv50->constbuf[s][i].user) {
nv50->constbuf[s][i].u.data = cb->user_buffer;
nv50->constbuf[s][i].size = cb->buffer_size;
nv50->constbuf_valid[s] |= 1 << i;
} else
if (res) {
nv50->constbuf[s][i].offset = cb->buffer_offset;
nv50->constbuf[s][i].size = align(cb->buffer_size, 0x100);
nv50->constbuf_valid[s] |= 1 << i;
} else {
nv50->constbuf_valid[s] &= ~(1 << i);
}
nv50->constbuf_dirty[s] |= 1 << i;

nv50->dirty |= NV50_NEW_CONSTBUF;

if (cb && cb->user_buffer) {
pipe_resource_reference(&res, NULL);
}
}

/* =============================================================================

+ 10
- 0
src/gallium/drivers/nv50/nv50_stateobj.h View File

@@ -34,6 +34,16 @@ struct nv50_zsa_stateobj {
uint32_t state[29];
};

struct nv50_constbuf {
union {
struct pipe_resource *buf;
const uint8_t *data;
} u;
uint32_t size; /* max 65536 */
uint16_t offset;
boolean user; /* should only be TRUE if u.data is valid and non-NULL */
};

struct nv50_vertex_element {
struct pipe_vertex_element pipe;
uint32_t state;

+ 3
- 2
src/gallium/drivers/nvc0/nvc0_context.c View File

@@ -72,8 +72,9 @@ nvc0_context_unreference_resources(struct nvc0_context *nvc0)
for (i = 0; i < nvc0->num_textures[s]; ++i)
pipe_sampler_view_reference(&nvc0->textures[s][i], NULL);

for (i = 0; i < 16; ++i)
pipe_resource_reference(&nvc0->constbuf[s][i], NULL);
for (i = 0; i < NVC0_MAX_PIPE_CONSTBUFS; ++i)
if (!nvc0->constbuf[s][i].user)
pipe_resource_reference(&nvc0->constbuf[s][i].u.buf, NULL);
}

for (i = 0; i < nvc0->num_tfbbufs; ++i)

+ 18
- 1
src/gallium/drivers/nvc0/nvc0_context.h View File

@@ -121,7 +121,7 @@ struct nvc0_context {
struct nvc0_program *gmtyprog;
struct nvc0_program *fragprog;

struct pipe_resource *constbuf[5][16];
struct nvc0_constbuf constbuf[5][NVC0_MAX_PIPE_CONSTBUFS];
uint16_t constbuf_dirty[5];

struct pipe_vertex_buffer vtxbuf[PIPE_MAX_ATTRIBS];
@@ -168,6 +168,23 @@ nvc0_context(struct pipe_context *pipe)
return (struct nvc0_context *)pipe;
}

static INLINE unsigned
nvc0_shader_stage(unsigned pipe)
{
switch (pipe) {
case PIPE_SHADER_VERTEX: return 0;
/* case PIPE_SHADER_TESSELLATION_CONTROL: return 1; */
/* case PIPE_SHADER_TESSELLATION_EVALUATION: return 2; */
case PIPE_SHADER_GEOMETRY: return 3;
case PIPE_SHADER_FRAGMENT: return 4;
case PIPE_SHADER_COMPUTE: return 5;
default:
assert(!"invalid PIPE_SHADER type");
return 0;
}
}


/* nvc0_context.c */
struct pipe_context *nvc0_create(struct pipe_screen *, void *);
void nvc0_bufctx_fence(struct nvc0_context *, struct nouveau_bufctx *,

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

@@ -190,7 +190,7 @@ nvc0_screen_get_shader_param(struct pipe_screen *pscreen, unsigned shader,
case PIPE_SHADER_CAP_MAX_CONSTS:
return 65536 / 16;
case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
return 14;
return NVC0_MAX_PIPE_CONSTBUFS;
case PIPE_SHADER_CAP_MAX_ADDRS:
return 1;
case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:

+ 3
- 0
src/gallium/drivers/nvc0/nvc0_screen.h View File

@@ -14,6 +14,9 @@
#define NVC0_TIC_MAX_ENTRIES 2048
#define NVC0_TSC_MAX_ENTRIES 2048

/* doesn't count reserved slots (for auxiliary constants, immediates, etc.) */
#define NVC0_MAX_PIPE_CONSTBUFS 14

struct nvc0_context;

struct nvc0_blitctx;

+ 20
- 25
src/gallium/drivers/nvc0/nvc0_state.c View File

@@ -620,38 +620,33 @@ nvc0_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
{
struct nvc0_context *nvc0 = nvc0_context(pipe);
struct pipe_resource *res = cb ? cb->buffer : NULL;
const unsigned s = nvc0_shader_stage(shader);
const unsigned i = index;

if (cb && cb->user_buffer) {
res = nouveau_user_buffer_create(pipe->screen, cb->user_buffer,
cb->buffer_size,
PIPE_BIND_CONSTANT_BUFFER);
}
if (shader == PIPE_SHADER_COMPUTE)
return;

switch (shader) {
case PIPE_SHADER_VERTEX: shader = 0; break;
/*
case PIPE_SHADER_TESSELLATION_CONTROL: shader = 1; break;
case PIPE_SHADER_TESSELLATION_EVALUATION: shader = 2; break;
*/
case PIPE_SHADER_GEOMETRY: shader = 3; break;
case PIPE_SHADER_FRAGMENT: shader = 4; break;
default:
assert(0);
break;
}
if (nvc0->constbuf[s][i].user)
nvc0->constbuf[s][i].u.buf = NULL;
else
if (nvc0->constbuf[s][i].u.buf)
nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_CB(s, i));

if (nvc0->constbuf[shader][index])
nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_CB(shader, index));
pipe_resource_reference(&nvc0->constbuf[s][i].u.buf, res);

pipe_resource_reference(&nvc0->constbuf[shader][index], res);
nvc0->constbuf[s][i].user = (cb && cb->user_buffer) ? TRUE : FALSE;
if (nvc0->constbuf[s][i].user) {
nvc0->constbuf[s][i].u.data = cb->user_buffer;
nvc0->constbuf[s][i].size = cb->buffer_size;
} else
if (cb) {
nvc0->constbuf[s][i].offset = cb->buffer_offset;
nvc0->constbuf[s][i].size = align(cb->buffer_size, 0x100);
}

nvc0->constbuf_dirty[shader] |= 1 << index;
nvc0->constbuf_dirty[s] |= 1 << i;

nvc0->dirty |= NVC0_NEW_CONSTBUF;

if (cb->user_buffer) {
pipe_resource_reference(&res, NULL);
}
}

/* =============================================================================

+ 36
- 53
src/gallium/drivers/nvc0/nvc0_state_validate.c View File

@@ -355,70 +355,53 @@ static void
nvc0_constbufs_validate(struct nvc0_context *nvc0)
{
struct nouveau_pushbuf *push = nvc0->base.pushbuf;
struct nouveau_bo *bo;
unsigned s;

for (s = 0; s < 5; ++s) {
struct nv04_resource *res;
int i;

while (nvc0->constbuf_dirty[s]) {
unsigned base = 0;
unsigned words = 0;
boolean rebind = TRUE;

i = ffs(nvc0->constbuf_dirty[s]) - 1;
int i = ffs(nvc0->constbuf_dirty[s]) - 1;
nvc0->constbuf_dirty[s] &= ~(1 << i);

res = nv04_resource(nvc0->constbuf[s][i]);
if (!res) {
BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
PUSH_DATA (push, (i << 4) | 0);
if (i == 0)
nvc0->state.uniform_buffer_bound[s] = 0;
continue;
}

if (!nouveau_resource_mapped_by_gpu(&res->base)) {
if (i == 0 && (res->status & NOUVEAU_BUFFER_STATUS_USER_MEMORY)) {
base = s << 16;
bo = nvc0->screen->uniform_bo;

if (nvc0->state.uniform_buffer_bound[s] >= res->base.width0)
rebind = FALSE;
else
nvc0->state.uniform_buffer_bound[s] =
align(res->base.width0, 0x100);

words = res->base.width0 / 4;
} else {
nouveau_buffer_migrate(&nvc0->base, res, NOUVEAU_BO_VRAM);
bo = res->bo;
base = res->offset;
if (nvc0->constbuf[s][i].user) {
struct nouveau_bo *bo = nvc0->screen->uniform_bo;
const unsigned base = s << 16;
const unsigned size = nvc0->constbuf[s][0].size;
assert(i == 0); /* we really only want OpenGL uniforms here */
assert(nvc0->constbuf[s][0].u.data);

if (nvc0->state.uniform_buffer_bound[s] < size) {
nvc0->state.uniform_buffer_bound[s] = align(size, 0x100);

BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
PUSH_DATA (push, nvc0->state.uniform_buffer_bound[s]);
PUSH_DATAh(push, bo->offset + base);
PUSH_DATA (push, bo->offset + base);
BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
PUSH_DATA (push, (0 << 4) | 1);
}
nvc0_cb_push(&nvc0->base, bo, NOUVEAU_BO_VRAM,
base, nvc0->state.uniform_buffer_bound[s],
0, (size + 3) / 4,
nvc0->constbuf[s][0].u.data);
} else {
bo = res->bo;
base = res->offset;
struct nv04_resource *res =
nv04_resource(nvc0->constbuf[s][i].u.buf);
if (res) {
BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
PUSH_DATA (push, nvc0->constbuf[s][i].size);
PUSH_DATAh(push, res->address + nvc0->constbuf[s][i].offset);
PUSH_DATA (push, res->address + nvc0->constbuf[s][i].offset);
BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
PUSH_DATA (push, (i << 4) | 1);

BCTX_REFN(nvc0->bufctx_3d, CB(s, i), res, RD);
} else {
BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
PUSH_DATA (push, (i << 4) | 0);
}
if (i == 0)
nvc0->state.uniform_buffer_bound[s] = 0;
}

if (bo != nvc0->screen->uniform_bo)
BCTX_REFN(nvc0->bufctx_3d, CB(s, i), res, RD);

if (rebind) {
BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3);
PUSH_DATA (push, align(res->base.width0, 0x100));
PUSH_DATAh(push, bo->offset + base);
PUSH_DATA (push, bo->offset + base);
BEGIN_NVC0(push, NVC0_3D(CB_BIND(s)), 1);
PUSH_DATA (push, (i << 4) | 1);
}

if (words)
nvc0_cb_push(&nvc0->base,
bo, NOUVEAU_BO_VRAM, base, res->base.width0,
0, words, (const uint32_t *)res->data);
}
}
}

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

@@ -32,6 +32,16 @@ struct nvc0_zsa_stateobj {
uint32_t state[26];
};

struct nvc0_constbuf {
union {
struct pipe_resource *buf;
const void *data;
} u;
uint32_t size;
uint16_t offset;
boolean user; /* should only be TRUE if u.data is valid and non-NULL */
};

struct nvc0_vertex_element {
struct pipe_vertex_element pipe;
uint32_t state;

Loading…
Cancel
Save