[Mesa-dev] [PATCH] nv50: implement multisample textures
Bryan Cain
bryancain3 at gmail.com
Tue Oct 22 00:23:30 CEST 2013
This is a port of 4da54c91d24da ("nvc0: implement multisample textures") to
nv50.
When coupled with the patch to only report 16 texture samplers (to fix
crashes), all of the Piglit tests in spec/arb_texture_multisample pass.
---
.../nouveau/codegen/nv50_ir_lowering_nv50.cpp | 5 ++-
src/gallium/drivers/nouveau/nv50/nv50_context.c | 46 ++++++++++++++++++++
src/gallium/drivers/nouveau/nv50/nv50_miptree.c | 2 +
src/gallium/drivers/nouveau/nv50/nv50_screen.c | 3 +-
src/gallium/drivers/nouveau/nv50/nv50_tex.c | 20 +++++++--
5 files changed, 70 insertions(+), 6 deletions(-)
diff --git a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nv50.cpp b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nv50.cpp
index caaf09f..d5d1f1e 100644
--- a/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nv50.cpp
+++ b/src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nv50.cpp
@@ -569,6 +569,7 @@ NV50LoweringPreSSA::handleTEX(TexInstruction *i)
const int arg = i->tex.target.getArgCount();
const int dref = arg;
const int lod = i->tex.target.isShadow() ? (arg + 1) : arg;
+ const int lyr = arg - (i->tex.target.isMS() ? 2 : 1);
// dref comes before bias/lod
if (i->tex.target.isShadow())
@@ -577,11 +578,11 @@ NV50LoweringPreSSA::handleTEX(TexInstruction *i)
// array index must be converted to u32
if (i->tex.target.isArray()) {
- Value *layer = i->getSrc(arg - 1);
+ Value *layer = i->getSrc(lyr);
LValue *src = new_LValue(func, FILE_GPR);
bld.mkCvt(OP_CVT, TYPE_U32, src, TYPE_F32, layer);
bld.mkOp2(OP_MIN, TYPE_U32, src, src, bld.loadImm(NULL, 511));
- i->setSrc(arg - 1, src);
+ i->setSrc(lyr, src);
if (i->tex.target.isCube()) {
std::vector<Value *> acube, a2d;
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.c b/src/gallium/drivers/nouveau/nv50/nv50_context.c
index b6bdf79..45e3f5d 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_context.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_context.c
@@ -194,6 +194,10 @@ nv50_invalidate_resource_storage(struct nouveau_context *ctx,
return ref;
}
+static void
+nv50_context_get_sample_position(struct pipe_context *, unsigned, unsigned,
+ float *);
+
struct pipe_context *
nv50_create(struct pipe_screen *pscreen, void *priv)
{
@@ -237,6 +241,7 @@ nv50_create(struct pipe_screen *pscreen, void *priv)
pipe->flush = nv50_flush;
pipe->texture_barrier = nv50_texture_barrier;
+ pipe->get_sample_position = nv50_context_get_sample_position;
if (!screen->cur_ctx) {
screen->cur_ctx = nv50;
@@ -315,3 +320,44 @@ nv50_bufctx_fence(struct nouveau_bufctx *bufctx, boolean on_flush)
nv50_resource_validate(res, (unsigned)ref->priv_data);
}
}
+
+static void
+nv50_context_get_sample_position(struct pipe_context *pipe,
+ unsigned sample_count, unsigned sample_index,
+ float *xy)
+{
+ static const uint8_t ms1[1][2] = { { 0x8, 0x8 } };
+ static const uint8_t ms2[2][2] = {
+ { 0x4, 0x4 }, { 0xc, 0xc } }; /* surface coords (0,0), (1,0) */
+ static const uint8_t ms4[4][2] = {
+ { 0x6, 0x2 }, { 0xe, 0x6 }, /* (0,0), (1,0) */
+ { 0x2, 0xa }, { 0xa, 0xe } }; /* (0,1), (1,1) */
+ static const uint8_t ms8[8][2] = {
+ { 0x1, 0x7 }, { 0x5, 0x3 }, /* (0,0), (1,0) */
+ { 0x3, 0xd }, { 0x7, 0xb }, /* (0,1), (1,1) */
+ { 0x9, 0x5 }, { 0xf, 0x1 }, /* (2,0), (3,0) */
+ { 0xb, 0xf }, { 0xd, 0x9 } }; /* (2,1), (3,1) */
+#if 0
+ /* NOTE: NVA3+ has alternative modes for MS2 and MS8, currently not used */
+ static const uint8_t ms8_alt[8][2] = {
+ { 0x9, 0x5 }, { 0x7, 0xb }, /* (2,0), (1,1) */
+ { 0xd, 0x9 }, { 0x5, 0x3 }, /* (3,1), (1,0) */
+ { 0x3, 0xd }, { 0x1, 0x7 }, /* (0,1), (0,0) */
+ { 0xb, 0xf }, { 0xf, 0x1 } }; /* (2,1), (3,0) */
+#endif
+
+ const uint8_t (*ptr)[2];
+
+ switch (sample_count) {
+ case 0:
+ case 1: ptr = ms1; break;
+ case 2: ptr = ms2; break;
+ case 4: ptr = ms4; break;
+ case 8: ptr = ms8; break;
+ default:
+ assert(0);
+ return; /* bad sample count -> undefined locations */
+ }
+ xy[0] = ptr[sample_index][0] * 0.0625f;
+ xy[1] = ptr[sample_index][1] * 0.0625f;
+}
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_miptree.c b/src/gallium/drivers/nouveau/nv50/nv50_miptree.c
index 513d8f9..1963a4a 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_miptree.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_miptree.c
@@ -277,6 +277,8 @@ nv50_miptree_init_layout_tiled(struct nv50_miptree *mt)
*/
d = mt->layout_3d ? pt->depth0 : 1;
+ assert(!mt->ms_mode || !pt->last_level);
+
for (l = 0; l <= pt->last_level; ++l) {
struct nv50_miptree_level *lvl = &mt->level[l];
unsigned tsx, tsy, tsz;
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
index f454ec7..47cf1a1 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
@@ -183,8 +183,9 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_TGSI_TEXCOORD:
- case PIPE_CAP_TEXTURE_MULTISAMPLE:
return 0;
+ case PIPE_CAP_TEXTURE_MULTISAMPLE:
+ return 1;
case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
return 1;
case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_tex.c b/src/gallium/drivers/nouveau/nv50/nv50_tex.c
index 9e51292..40af224 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_tex.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_tex.c
@@ -75,6 +75,7 @@ nv50_create_texture_view(struct pipe_context *pipe,
uint64_t addr;
uint32_t *tic;
uint32_t swz[4];
+ uint32_t width, height;
uint32_t depth;
struct nv50_tic_entry *view;
struct nv50_miptree *mt = nv50_miptree(texture);
@@ -197,15 +198,28 @@ nv50_create_texture_view(struct pipe_context *pipe,
tic[3] = (flags & NV50_TEXVIEW_FILTER_MSAA8) ? 0x20000000 : 0x00300000;
- tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x);
+ if (flags & NV50_TEXVIEW_ACCESS_RESOLVE) {
+ width = mt->base.base.width0 << mt->ms_x;
+ height = mt->base.base.height0 << mt->ms_y;
+ } else {
+ width = mt->base.base.width0;
+ height = mt->base.base.height0;
+ }
+
+ tic[4] = (1 << 31) | width;
- tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff;
+ tic[5] = height & 0xffff;
tic[5] |= depth << 16;
tic[5] |= mt->base.base.last_level << NV50_TIC_5_LAST_LEVEL__SHIFT;
- tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */
+ /* sampling points: (?) */
+ if (flags & NV50_TEXVIEW_ACCESS_RESOLVE)
+ tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000;
+ else
+ tic[6] = 0x03000000;
tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level;
+ tic[7] |= mt->ms_mode << 12;
if (unlikely(!(tic[2] & NV50_TIC_2_NORMALIZED_COORDS)))
if (mt->base.base.last_level)
--
1.7.9.5
More information about the mesa-dev
mailing list