From: Christoph Bumiller Date: Mon, 11 Jul 2011 16:02:27 +0000 (+0200) Subject: nv50,nvc0: add support for multi-sample resources X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b2dcf880e8bcd61be59602f5a2d18c77a5fc60c1;p=mesa.git nv50,nvc0: add support for multi-sample resources --- diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index 4e141a6c1e5..c1226d5eb26 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -18,6 +18,7 @@ #include "nv50_screen.h" #include "nv50_program.h" #include "nv50_resource.h" +#include "nv50_transfer.h" #include "nouveau/nouveau_context.h" #include "nouveau/nv_object.xml.h" @@ -188,6 +189,11 @@ nv50_create_sampler_view(struct pipe_context *, /* nv50_transfer.c */ void +nv50_m2mf_transfer_rect(struct pipe_screen *pscreen, + const struct nv50_m2mf_rect *dst, + const struct nv50_m2mf_rect *src, + uint32_t nblocksx, uint32_t nblocksy); +void nv50_sifc_linear_u8(struct nouveau_context *pipe, struct nouveau_bo *dst, unsigned offset, unsigned domain, unsigned size, void *data); diff --git a/src/gallium/drivers/nv50/nv50_miptree.c b/src/gallium/drivers/nv50/nv50_miptree.c index fcb9ca3e7ac..115a98dcda4 100644 --- a/src/gallium/drivers/nv50/nv50_miptree.c +++ b/src/gallium/drivers/nv50/nv50_miptree.c @@ -27,7 +27,6 @@ #include "nv50_context.h" #include "nv50_resource.h" -#include "nv50_transfer.h" static INLINE uint32_t nv50_tex_choose_tile_dims(unsigned nx, unsigned ny, unsigned nz) diff --git a/src/gallium/drivers/nv50/nv50_resource.h b/src/gallium/drivers/nv50/nv50_resource.h index a771edf4095..66d21209be2 100644 --- a/src/gallium/drivers/nv50/nv50_resource.h +++ b/src/gallium/drivers/nv50/nv50_resource.h @@ -107,6 +107,22 @@ nv50_miptree_surface_new(struct pipe_context *, struct pipe_resource *, const struct pipe_surface *templ); +struct pipe_transfer * +nv50_miptree_transfer_new(struct pipe_context *pcontext, + struct pipe_resource *pt, + unsigned level, + unsigned usage, + const struct pipe_box *box); +void +nv50_miptree_transfer_del(struct pipe_context *pcontext, + struct pipe_transfer *ptx); +void * +nv50_miptree_transfer_map(struct pipe_context *pcontext, + struct pipe_transfer *ptx); +void +nv50_miptree_transfer_unmap(struct pipe_context *pcontext, + struct pipe_transfer *ptx); + #endif /* __NVC0_RESOURCE_H__ */ struct nv50_surface * diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c index 4cda303c44a..a697ff5ecf7 100644 --- a/src/gallium/drivers/nv50/nv50_screen.c +++ b/src/gallium/drivers/nv50/nv50_screen.c @@ -43,7 +43,9 @@ nv50_screen_is_format_supported(struct pipe_screen *pscreen, unsigned sample_count, unsigned bindings) { - if (sample_count > 1) + if (sample_count > 2 && sample_count != 4 && sample_count != 8) + return FALSE; + if (sample_count == 8 && util_format_get_blocksizebits(format) >= 128) return FALSE; if (!util_format_is_supported(format, bindings)) diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c index fb125f3a8d8..49ea646c77c 100644 --- a/src/gallium/drivers/nv50/nv50_state.c +++ b/src/gallium/drivers/nv50/nv50_state.c @@ -119,6 +119,7 @@ nv50_blend_state_create(struct pipe_context *pipe, struct nv50_blend_stateobj *so = CALLOC_STRUCT(nv50_blend_stateobj); int i; boolean emit_common_func = cso->rt[0].blend_enable; + uint32_t ms; if (nv50_context(pipe)->screen->tesla->grclass >= NVA3_3D) { SB_BEGIN_3D(so, BLEND_INDEPENDENT, 1); @@ -190,6 +191,15 @@ nv50_blend_state_create(struct pipe_context *pipe, SB_DATA (so, nv50_colormask(cso->rt[0].colormask)); } + ms = 0; + if (cso->alpha_to_coverage) + ms |= NV50_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE; + if (cso->alpha_to_one) + ms |= NV50_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE; + + SB_BEGIN_3D(so, MULTISAMPLE_CTRL, 1); + SB_DATA (so, ms); + assert(so->size <= (sizeof(so->state) / sizeof(so->state[0]))); return so; } @@ -237,6 +247,9 @@ nv50_rasterizer_state_create(struct pipe_context *pipe, SB_BEGIN_3D(so, FRAG_COLOR_CLAMP_EN, 1); SB_DATA (so, cso->clamp_fragment_color ? 0x11111111 : 0x00000000); + SB_BEGIN_3D(so, MULTISAMPLE_ENABLE, 1); + SB_DATA (so, cso->multisample); + SB_BEGIN_3D(so, LINE_WIDTH, 1); SB_DATA (so, fui(cso->line_width)); SB_BEGIN_3D(so, LINE_SMOOTH_ENABLE, 1); diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c index d29c1e9723f..8b0b08f8e93 100644 --- a/src/gallium/drivers/nv50/nv50_state_validate.c +++ b/src/gallium/drivers/nv50/nv50_state_validate.c @@ -8,6 +8,7 @@ nv50_validate_fb(struct nv50_context *nv50) struct nouveau_channel *chan = nv50->screen->base.channel; struct pipe_framebuffer_state *fb = &nv50->framebuffer; unsigned i; + unsigned ms_mode = NV50_3D_MULTISAMPLE_MODE_MS1; boolean serialize = FALSE; nv50_bufctx_reset(nv50, NV50_BUFCTX_FRAME); @@ -38,6 +39,8 @@ nv50_validate_fb(struct nv50_context *nv50) BEGIN_RING(chan, RING_3D(RT_ARRAY_MODE), 1); OUT_RING (chan, sf->depth); + ms_mode = mt->ms_mode; + if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING) serialize = TRUE; mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; @@ -69,6 +72,8 @@ nv50_validate_fb(struct nv50_context *nv50) OUT_RING (chan, sf->height); OUT_RING (chan, (unk << 16) | sf->depth); + ms_mode = mt->ms_mode; + if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING) serialize = TRUE; mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; @@ -81,6 +86,9 @@ nv50_validate_fb(struct nv50_context *nv50) OUT_RING (chan, 0); } + BEGIN_RING(chan, RING_3D(MULTISAMPLE_MODE), 1); + OUT_RING (chan, ms_mode); + BEGIN_RING(chan, RING_3D(VIEWPORT_HORIZ(0)), 2); OUT_RING (chan, fb->width << 16); OUT_RING (chan, fb->height << 16); @@ -257,6 +265,26 @@ nv50_validate_rasterizer(struct nv50_context *nv50) OUT_RINGp(chan, nv50->rast->state, nv50->rast->size); } +static void +nv50_validate_sample_mask(struct nv50_context *nv50) +{ + struct nouveau_channel *chan = nv50->screen->base.channel; + + unsigned mask[4] = + { + nv50->sample_mask & 0xffff, + nv50->sample_mask & 0xffff, + nv50->sample_mask & 0xffff, + nv50->sample_mask & 0xffff + }; + + BEGIN_RING(chan, RING_3D(MSAA_MASK(0)), 4); + OUT_RING (chan, mask[0]); + OUT_RING (chan, mask[1]); + OUT_RING (chan, mask[2]); + OUT_RING (chan, mask[3]); +} + static void nv50_switch_pipe_context(struct nv50_context *ctx_to) { @@ -292,6 +320,7 @@ static struct state_validate { { nv50_validate_fb, NV50_NEW_FRAMEBUFFER }, { nv50_validate_blend, NV50_NEW_BLEND }, { nv50_validate_zsa, NV50_NEW_ZSA }, + { nv50_validate_sample_mask, NV50_NEW_SAMPLE_MASK }, { nv50_validate_rasterizer, NV50_NEW_RASTERIZER }, { nv50_validate_blend_colour, NV50_NEW_BLEND_COLOUR }, { nv50_validate_stencil_ref, NV50_NEW_STENCIL_REF }, diff --git a/src/gallium/drivers/nv50/nv50_stateobj.h b/src/gallium/drivers/nv50/nv50_stateobj.h index 4c98c7e46fc..d367a064d61 100644 --- a/src/gallium/drivers/nv50/nv50_stateobj.h +++ b/src/gallium/drivers/nv50/nv50_stateobj.h @@ -21,13 +21,13 @@ struct nv50_blend_stateobj { struct pipe_blend_state pipe; int size; - uint32_t state[82]; // TODO: allocate less if !independent_blend_enable + uint32_t state[84]; // TODO: allocate less if !independent_blend_enable }; struct nv50_rasterizer_stateobj { struct pipe_rasterizer_state pipe; int size; - uint32_t state[42]; + uint32_t state[44]; }; struct nv50_zsa_stateobj { diff --git a/src/gallium/drivers/nv50/nv50_surface.c b/src/gallium/drivers/nv50/nv50_surface.c index fb51db84ac6..ebacbb4a449 100644 --- a/src/gallium/drivers/nv50/nv50_surface.c +++ b/src/gallium/drivers/nv50/nv50_surface.c @@ -87,8 +87,8 @@ nv50_2d_texture_set(struct nouveau_channel *chan, int dst, return 1; } - width = u_minify(mt->base.base.width0, level); - height = u_minify(mt->base.base.height0, level); + width = u_minify(mt->base.base.width0, level) << mt->ms_x; + height = u_minify(mt->base.base.height0, level) << mt->ms_y; offset = mt->level[level].offset; if (!mt->layout_3d) { @@ -143,7 +143,13 @@ nv50_2d_texture_do_copy(struct nouveau_channel *chan, unsigned sx, unsigned sy, unsigned sz, unsigned w, unsigned h) { + static const uint32_t duvdxy[5] = + { + 0x40000000, 0x80000000, 0x00000001, 0x00000002, 0x00000004 + }; + int ret; + uint32_t ctrl; ret = MARK_RING(chan, 2 * 16 + 32, 4); if (ret) @@ -157,24 +163,28 @@ nv50_2d_texture_do_copy(struct nouveau_channel *chan, if (ret) return ret; - /* 0/1 = CENTER/CORNER, 10/00 = POINT/BILINEAR */ + /* NOTE: 2D engine doesn't work for MS8 */ + if (src->ms_x) + ctrl = 0x11; + + /* 0/1 = CENTER/CORNER, 00/10 = POINT/BILINEAR */ BEGIN_RING(chan, RING_2D(BLIT_CONTROL), 1); - OUT_RING (chan, 0); + OUT_RING (chan, ctrl); BEGIN_RING(chan, RING_2D(BLIT_DST_X), 4); - OUT_RING (chan, dx); - OUT_RING (chan, dy); - OUT_RING (chan, w); - OUT_RING (chan, h); + OUT_RING (chan, dx << dst->ms_x); + OUT_RING (chan, dy << dst->ms_y); + OUT_RING (chan, w << dst->ms_x); + OUT_RING (chan, h << dst->ms_y); BEGIN_RING(chan, RING_2D(BLIT_DU_DX_FRACT), 4); - OUT_RING (chan, 0); - OUT_RING (chan, 1); - OUT_RING (chan, 0); - OUT_RING (chan, 1); + OUT_RING (chan, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0xf0000000); + OUT_RING (chan, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0x0000000f); + OUT_RING (chan, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0xf0000000); + OUT_RING (chan, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0x0000000f); BEGIN_RING(chan, RING_2D(BLIT_SRC_X_FRACT), 4); OUT_RING (chan, 0); - OUT_RING (chan, sx); + OUT_RING (chan, sx << src->ms_x); OUT_RING (chan, 0); - OUT_RING (chan, sy); + OUT_RING (chan, sy << src->ms_y); return 0; } @@ -197,6 +207,34 @@ nv50_resource_copy_region(struct pipe_context *pipe, return; } + nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; + + if (src->format == dst->format && src->nr_samples == dst->nr_samples) { + struct nv50_m2mf_rect drect, srect; + unsigned i; + unsigned nx = util_format_get_nblocksx(src->format, src_box->width); + unsigned ny = util_format_get_nblocksy(src->format, src_box->height); + + nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz); + nv50_m2mf_rect_setup(&srect, src, src_level, + src_box->x, src_box->y, src_box->z); + + for (i = 0; i < src_box->depth; ++i) { + nv50_m2mf_transfer_rect(&screen->base.base, &drect, &srect, nx, ny); + + if (nv50_miptree(dst)->layout_3d) + drect.z++; + else + drect.base += nv50_miptree(dst)->layer_stride; + + if (nv50_miptree(src)->layout_3d) + srect.z++; + else + srect.base += nv50_miptree(src)->layer_stride; + } + return; + } + assert((src->format == dst->format) || (nv50_2d_format_faithful(src->format) && nv50_2d_format_faithful(dst->format))); diff --git a/src/gallium/drivers/nv50/nv50_tex.c b/src/gallium/drivers/nv50/nv50_tex.c index 9192d2e2590..73db9ca4fd1 100644 --- a/src/gallium/drivers/nv50/nv50_tex.c +++ b/src/gallium/drivers/nv50/nv50_tex.c @@ -159,13 +159,13 @@ nv50_create_sampler_view(struct pipe_context *pipe, else tic[3] = 0x00300000; - tic[4] = (1 << 31) | mt->base.base.width0; + tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x); - tic[5] = mt->base.base.height0 & 0xffff; + tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff; tic[5] |= depth << 16; tic[5] |= mt->base.base.last_level << 28; - tic[6] = 0x03000000; + tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */ tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level; diff --git a/src/gallium/drivers/nv50/nv50_transfer.c b/src/gallium/drivers/nv50/nv50_transfer.c index d9fb22aa673..0ff79eb908a 100644 --- a/src/gallium/drivers/nv50/nv50_transfer.c +++ b/src/gallium/drivers/nv50/nv50_transfer.c @@ -2,7 +2,6 @@ #include "util/u_format.h" #include "nv50_context.h" -#include "nv50_transfer.h" #include "nv50_defs.xml.h" @@ -13,7 +12,44 @@ struct nv50_transfer { uint32_t nblocksy; }; -static void +void +nv50_m2mf_rect_setup(struct nv50_m2mf_rect *rect, + struct pipe_resource *restrict res, unsigned l, + unsigned x, unsigned y, unsigned z) +{ + struct nv50_miptree *mt = nv50_miptree(res); + const unsigned w = u_minify(res->width0, l); + const unsigned h = u_minify(res->height0, l); + + rect->bo = mt->base.bo; + rect->domain = mt->base.domain; + rect->base = mt->level[l].offset; + rect->pitch = mt->level[l].pitch; + if (util_format_is_plain(res->format)) { + rect->width = w << mt->ms_x; + rect->height = h << mt->ms_y; + rect->x = x << mt->ms_x; + rect->y = y << mt->ms_y; + } else { + rect->width = util_format_get_nblocksx(res->format, w); + rect->height = util_format_get_nblocksy(res->format, h); + rect->x = util_format_get_nblocksx(res->format, x); + rect->y = util_format_get_nblocksy(res->format, y); + } + rect->tile_mode = mt->level[l].tile_mode; + rect->cpp = util_format_get_blocksize(res->format); + + if (mt->layout_3d) { + rect->z = z; + rect->depth = u_minify(res->depth0, l); + } else { + rect->base += z * mt->layer_stride; + rect->z = 0; + rect->depth = 1; + } +} + +void nv50_m2mf_transfer_rect(struct pipe_screen *pscreen, const struct nv50_m2mf_rect *dst, const struct nv50_m2mf_rect *src, @@ -202,26 +238,14 @@ nv50_miptree_transfer_new(struct pipe_context *pctx, struct nv50_context *nv50 = nv50_context(pctx); struct pipe_screen *pscreen = pctx->screen; struct nouveau_device *dev = nv50->screen->base.device; - struct nv50_miptree *mt = nv50_miptree(res); - struct nv50_miptree_level *lvl = &mt->level[level]; + const struct nv50_miptree *mt = nv50_miptree(res); struct nv50_transfer *tx; uint32_t size; - uint32_t w, h, d, z, layer; int ret; if (usage & PIPE_TRANSFER_MAP_DIRECTLY) return NULL; - if (mt->layout_3d) { - z = box->z; - d = u_minify(res->depth0, level); - layer = 0; - } else { - z = 0; - d = 1; - layer = box->z; - } - tx = CALLOC_STRUCT(nv50_transfer); if (!tx) return NULL; @@ -232,28 +256,18 @@ nv50_miptree_transfer_new(struct pipe_context *pctx, tx->base.usage = usage; tx->base.box = *box; - tx->nblocksx = util_format_get_nblocksx(res->format, box->width); - tx->nblocksy = util_format_get_nblocksy(res->format, box->height); + if (util_format_is_plain(res->format)) { + tx->nblocksx = box->width << mt->ms_x; + tx->nblocksy = box->height << mt->ms_x; + } else { + tx->nblocksx = util_format_get_nblocksx(res->format, box->width); + tx->nblocksy = util_format_get_nblocksy(res->format, box->height); + } tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format); tx->base.layer_stride = tx->nblocksy * tx->base.stride; - w = u_minify(res->width0, level); - h = u_minify(res->height0, level); - - tx->rect[0].cpp = tx->rect[1].cpp = util_format_get_blocksize(res->format); - - tx->rect[0].bo = mt->base.bo; - tx->rect[0].base = lvl->offset + layer * mt->layer_stride; - tx->rect[0].tile_mode = lvl->tile_mode; - tx->rect[0].x = util_format_get_nblocksx(res->format, box->x); - tx->rect[0].y = util_format_get_nblocksy(res->format, box->y); - tx->rect[0].z = z; - tx->rect[0].width = util_format_get_nblocksx(res->format, w); - tx->rect[0].height = util_format_get_nblocksy(res->format, h); - tx->rect[0].depth = d; - tx->rect[0].pitch = lvl->pitch; - tx->rect[0].domain = NOUVEAU_BO_VRAM; + nv50_m2mf_rect_setup(&tx->rect[0], res, level, box->x, box->y, box->z); size = tx->base.layer_stride; @@ -264,6 +278,7 @@ nv50_miptree_transfer_new(struct pipe_context *pctx, return NULL; } + tx->rect[1].cpp = tx->rect[0].cpp; tx->rect[1].width = tx->nblocksx; tx->rect[1].height = tx->nblocksy; tx->rect[1].depth = 1; @@ -272,6 +287,7 @@ nv50_miptree_transfer_new(struct pipe_context *pctx, if (usage & PIPE_TRANSFER_READ) { unsigned base = tx->rect[0].base; + unsigned z = tx->rect[0].z; unsigned i; for (i = 0; i < box->depth; ++i) { nv50_m2mf_transfer_rect(pscreen, &tx->rect[1], &tx->rect[0], diff --git a/src/gallium/drivers/nv50/nv50_transfer.h b/src/gallium/drivers/nv50/nv50_transfer.h index d3259ef4a5d..c58cb0008df 100644 --- a/src/gallium/drivers/nv50/nv50_transfer.h +++ b/src/gallium/drivers/nv50/nv50_transfer.h @@ -4,22 +4,6 @@ #include "pipe/p_state.h" -struct pipe_transfer * -nv50_miptree_transfer_new(struct pipe_context *pcontext, - struct pipe_resource *pt, - unsigned level, - unsigned usage, - const struct pipe_box *box); -void -nv50_miptree_transfer_del(struct pipe_context *pcontext, - struct pipe_transfer *ptx); -void * -nv50_miptree_transfer_map(struct pipe_context *pcontext, - struct pipe_transfer *ptx); -void -nv50_miptree_transfer_unmap(struct pipe_context *pcontext, - struct pipe_transfer *ptx); - struct nv50_m2mf_rect { struct nouveau_bo *bo; uint32_t base; @@ -35,4 +19,9 @@ struct nv50_m2mf_rect { uint16_t cpp; }; +void +nv50_m2mf_rect_setup(struct nv50_m2mf_rect *rect, + struct pipe_resource *restrict res, unsigned l, + unsigned x, unsigned y, unsigned z); + #endif diff --git a/src/gallium/drivers/nvc0/nvc0_3d.xml.h b/src/gallium/drivers/nvc0/nvc0_3d.xml.h index 6fba20cd2db..ba7d28bd47e 100644 --- a/src/gallium/drivers/nvc0/nvc0_3d.xml.h +++ b/src/gallium/drivers/nvc0/nvc0_3d.xml.h @@ -146,6 +146,11 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define NVC0_3D_TFB_ENABLE 0x00000744 +#define NVC0_3D_SAMPLE_SHADING 0x00000754 +#define NVC0_3D_SAMPLE_SHADING_MIN_SAMPLES__MASK 0x0000000f +#define NVC0_3D_SAMPLE_SHADING_MIN_SAMPLES__SHIFT 0 +#define NVC0_3D_SAMPLE_SHADING_ENABLE 0x00000010 + #define NVC0_3D_LOCAL_BASE 0x0000077c #define NVC0_3D_LOCAL_ADDRESS_HIGH 0x00000790 diff --git a/src/gallium/drivers/nvc0/nvc0_context.h b/src/gallium/drivers/nvc0/nvc0_context.h index e59209176e0..bf891649a57 100644 --- a/src/gallium/drivers/nvc0/nvc0_context.h +++ b/src/gallium/drivers/nvc0/nvc0_context.h @@ -19,6 +19,8 @@ #include "nvc0_program.h" #include "nvc0_resource.h" +#include "nv50/nv50_transfer.h" + #include "nouveau/nouveau_context.h" #include "nvc0_3ddefs.xml.h" @@ -195,6 +197,11 @@ nvc0_create_sampler_view(struct pipe_context *, /* nvc0_transfer.c */ void +nvc0_m2mf_transfer_rect(struct pipe_screen *pscreen, + const struct nv50_m2mf_rect *dst, + const struct nv50_m2mf_rect *src, + uint32_t nblocksx, uint32_t nblocksy); +void nvc0_m2mf_push_linear(struct nouveau_context *nv, struct nouveau_bo *dst, unsigned offset, unsigned domain, unsigned size, void *data); diff --git a/src/gallium/drivers/nvc0/nvc0_miptree.c b/src/gallium/drivers/nvc0/nvc0_miptree.c index 8b8e2cfc780..a72ddf306cd 100644 --- a/src/gallium/drivers/nvc0/nvc0_miptree.c +++ b/src/gallium/drivers/nvc0/nvc0_miptree.c @@ -27,7 +27,6 @@ #include "nvc0_context.h" #include "nvc0_resource.h" -#include "nvc0_transfer.h" uint32_t nvc0_tex_choose_tile_dims(unsigned nx, unsigned ny, unsigned nz) diff --git a/src/gallium/drivers/nvc0/nvc0_resource.h b/src/gallium/drivers/nvc0/nvc0_resource.h index d699895729d..6d946c83834 100644 --- a/src/gallium/drivers/nvc0/nvc0_resource.h +++ b/src/gallium/drivers/nvc0/nvc0_resource.h @@ -42,4 +42,20 @@ nvc0_miptree_surface_new(struct pipe_context *, unsigned nvc0_mt_zslice_offset(const struct nv50_miptree *, unsigned l, unsigned z); +struct pipe_transfer * +nvc0_miptree_transfer_new(struct pipe_context *pcontext, + struct pipe_resource *pt, + unsigned level, + unsigned usage, + const struct pipe_box *box); +void +nvc0_miptree_transfer_del(struct pipe_context *pcontext, + struct pipe_transfer *ptx); +void * +nvc0_miptree_transfer_map(struct pipe_context *pcontext, + struct pipe_transfer *ptx); +void +nvc0_miptree_transfer_unmap(struct pipe_context *pcontext, + struct pipe_transfer *ptx); + #endif diff --git a/src/gallium/drivers/nvc0/nvc0_screen.c b/src/gallium/drivers/nvc0/nvc0_screen.c index a2e45b16745..605a0b04018 100644 --- a/src/gallium/drivers/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nvc0/nvc0_screen.c @@ -37,7 +37,7 @@ nvc0_screen_is_format_supported(struct pipe_screen *pscreen, unsigned sample_count, unsigned bindings) { - if (sample_count > 1) + if (sample_count > 2 && sample_count != 4 && sample_count != 8) return FALSE; if (!util_format_is_supported(format, bindings)) diff --git a/src/gallium/drivers/nvc0/nvc0_state.c b/src/gallium/drivers/nvc0/nvc0_state.c index b0b2065167e..9f9921cc09e 100644 --- a/src/gallium/drivers/nvc0/nvc0_state.c +++ b/src/gallium/drivers/nvc0/nvc0_state.c @@ -88,6 +88,7 @@ nvc0_blend_state_create(struct pipe_context *pipe, { struct nvc0_blend_stateobj *so = CALLOC_STRUCT(nvc0_blend_stateobj); int i; + uint32_t ms; so->pipe = *cso; @@ -144,6 +145,15 @@ nvc0_blend_state_create(struct pipe_context *pipe, SB_DATA(so, nvc0_colormask(cso->rt[i].colormask)); } + ms = 0; + if (cso->alpha_to_coverage) + ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_COVERAGE; + if (cso->alpha_to_one) + ms |= NVC0_3D_MULTISAMPLE_CTRL_ALPHA_TO_ONE; + + SB_BEGIN_3D(so, MULTISAMPLE_CTRL, 1); + SB_DATA (so, ms); + assert(so->size <= (sizeof(so->state) / sizeof(so->state[0]))); return so; } @@ -190,6 +200,8 @@ nvc0_rasterizer_state_create(struct pipe_context *pipe, SB_BEGIN_3D(so, FRAG_COLOR_CLAMP_EN, 1); SB_DATA (so, cso->clamp_fragment_color ? 0x11111111 : 0x00000000); + SB_IMMED_3D(so, MULTISAMPLE_ENABLE, cso->multisample); + SB_IMMED_3D(so, LINE_SMOOTH_ENABLE, cso->line_smooth); if (cso->line_smooth) SB_BEGIN_3D(so, LINE_WIDTH_SMOOTH, 1); diff --git a/src/gallium/drivers/nvc0/nvc0_state_validate.c b/src/gallium/drivers/nvc0/nvc0_state_validate.c index bd40a231cde..968d7a7bd49 100644 --- a/src/gallium/drivers/nvc0/nvc0_state_validate.c +++ b/src/gallium/drivers/nvc0/nvc0_state_validate.c @@ -59,6 +59,7 @@ nvc0_validate_fb(struct nvc0_context *nvc0) struct nouveau_channel *chan = nvc0->screen->base.channel; struct pipe_framebuffer_state *fb = &nvc0->framebuffer; unsigned i; + unsigned ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS1; boolean serialize = FALSE; nvc0_bufctx_reset(nvc0, NVC0_BUFCTX_FRAME); @@ -89,6 +90,8 @@ nvc0_validate_fb(struct nvc0_context *nvc0) OUT_RING (chan, mt->layer_stride >> 2); OUT_RING (chan, sf->base.u.tex.first_layer); + ms_mode = mt->ms_mode; + if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING) serialize = TRUE; mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; @@ -123,6 +126,8 @@ nvc0_validate_fb(struct nvc0_context *nvc0) BEGIN_RING(chan, RING_3D(ZETA_BASE_LAYER), 1); OUT_RING (chan, sf->base.u.tex.first_layer); + ms_mode = mt->ms_mode; + if (mt->base.status & NOUVEAU_BUFFER_STATUS_GPU_READING) serialize = TRUE; mt->base.status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; @@ -135,6 +140,8 @@ nvc0_validate_fb(struct nvc0_context *nvc0) OUT_RING (chan, 0); } + IMMED_RING(chan, RING_3D(MULTISAMPLE_MODE), ms_mode); + if (serialize) { BEGIN_RING(chan, RING_3D(SERIALIZE), 1); OUT_RING (chan, 0); @@ -389,6 +396,28 @@ nvc0_constbufs_validate(struct nvc0_context *nvc0) } } +static void +nvc0_validate_sample_mask(struct nvc0_context *nvc0) +{ + struct nouveau_channel *chan = nvc0->screen->base.channel; + + unsigned mask[4] = + { + nvc0->sample_mask & 0xffff, + nvc0->sample_mask & 0xffff, + nvc0->sample_mask & 0xffff, + nvc0->sample_mask & 0xffff + }; + + BEGIN_RING(chan, RING_3D(MSAA_MASK(0)), 4); + OUT_RING (chan, mask[0]); + OUT_RING (chan, mask[1]); + OUT_RING (chan, mask[2]); + OUT_RING (chan, mask[3]); + BEGIN_RING(chan, RING_3D(SAMPLE_SHADING), 1); + OUT_RING (chan, 0x01); +} + static void nvc0_validate_derived_1(struct nvc0_context *nvc0) { @@ -438,6 +467,7 @@ static struct state_validate { { nvc0_validate_fb, NVC0_NEW_FRAMEBUFFER }, { nvc0_validate_blend, NVC0_NEW_BLEND }, { nvc0_validate_zsa, NVC0_NEW_ZSA }, + { nvc0_validate_sample_mask, NVC0_NEW_SAMPLE_MASK }, { nvc0_validate_rasterizer, NVC0_NEW_RASTERIZER }, { nvc0_validate_blend_colour, NVC0_NEW_BLEND_COLOUR }, { nvc0_validate_stencil_ref, NVC0_NEW_STENCIL_REF }, diff --git a/src/gallium/drivers/nvc0/nvc0_stateobj.h b/src/gallium/drivers/nvc0/nvc0_stateobj.h index e0fe9df25d7..0686c52fd0c 100644 --- a/src/gallium/drivers/nvc0/nvc0_stateobj.h +++ b/src/gallium/drivers/nvc0/nvc0_stateobj.h @@ -19,13 +19,13 @@ struct nvc0_blend_stateobj { struct pipe_blend_state pipe; int size; - uint32_t state[70]; + uint32_t state[72]; }; struct nvc0_rasterizer_stateobj { struct pipe_rasterizer_state pipe; int size; - uint32_t state[38]; + uint32_t state[39]; }; struct nvc0_zsa_stateobj { diff --git a/src/gallium/drivers/nvc0/nvc0_surface.c b/src/gallium/drivers/nvc0/nvc0_surface.c index e1e4c303b12..4484a9f8b76 100644 --- a/src/gallium/drivers/nvc0/nvc0_surface.c +++ b/src/gallium/drivers/nvc0/nvc0_surface.c @@ -31,7 +31,6 @@ #include "nvc0_context.h" #include "nvc0_resource.h" -#include "nvc0_transfer.h" #include "nv50/nv50_defs.xml.h" @@ -91,8 +90,8 @@ nvc0_2d_texture_set(struct nouveau_channel *chan, int dst, return 1; } - width = u_minify(mt->base.base.width0, level); - height = u_minify(mt->base.base.height0, level); + width = u_minify(mt->base.base.width0, level) << mt->ms_x; + height = u_minify(mt->base.base.height0, level) << mt->ms_y; depth = u_minify(mt->base.base.depth0, level); /* layer has to be < depth, and depth > tile depth / 2 */ @@ -151,7 +150,13 @@ nvc0_2d_texture_do_copy(struct nouveau_channel *chan, unsigned sx, unsigned sy, unsigned sz, unsigned w, unsigned h) { + static const uint32_t duvdxy[5] = + { + 0x40000000, 0x80000000, 0x00000001, 0x00000002, 0x00000004 + }; + int ret; + uint32_t ctrl = 0x00; ret = MARK_RING(chan, 2 * 16 + 32, 4); if (ret) @@ -165,65 +170,32 @@ nvc0_2d_texture_do_copy(struct nouveau_channel *chan, if (ret) return ret; - /* 0/1 = CENTER/CORNER, 10/00 = POINT/BILINEAR */ + /* NOTE: 2D engine doesn't work for MS8 */ + if (src->ms_x) + ctrl = 0x11; + + /* 0/1 = CENTER/CORNER, 00/10 = POINT/BILINEAR */ BEGIN_RING(chan, RING_2D(BLIT_CONTROL), 1); - OUT_RING (chan, 0); + OUT_RING (chan, ctrl); BEGIN_RING(chan, RING_2D(BLIT_DST_X), 4); - OUT_RING (chan, dx); - OUT_RING (chan, dy); - OUT_RING (chan, w); - OUT_RING (chan, h); + OUT_RING (chan, dx << dst->ms_x); + OUT_RING (chan, dy << dst->ms_y); + OUT_RING (chan, w << dst->ms_x); + OUT_RING (chan, h << dst->ms_y); BEGIN_RING(chan, RING_2D(BLIT_DU_DX_FRACT), 4); - OUT_RING (chan, 0); - OUT_RING (chan, 1); - OUT_RING (chan, 0); - OUT_RING (chan, 1); + OUT_RING (chan, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0xf0000000); + OUT_RING (chan, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0x0000000f); + OUT_RING (chan, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0xf0000000); + OUT_RING (chan, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0x0000000f); BEGIN_RING(chan, RING_2D(BLIT_SRC_X_FRACT), 4); OUT_RING (chan, 0); - OUT_RING (chan, sx); + OUT_RING (chan, sx << src->ms_x); OUT_RING (chan, 0); - OUT_RING (chan, sy); + OUT_RING (chan, sy << src->ms_x); return 0; } -static void -nvc0_setup_m2mf_rect(struct nvc0_m2mf_rect *rect, - struct pipe_resource *restrict res, unsigned l, - unsigned x, unsigned y, unsigned z) -{ - struct nv50_miptree *mt = nv50_miptree(res); - const unsigned w = u_minify(res->width0, l); - const unsigned h = u_minify(res->height0, l); - - rect->bo = mt->base.bo; - rect->domain = mt->base.domain; - rect->base = mt->level[l].offset; - rect->pitch = mt->level[l].pitch; - if (util_format_is_plain(res->format)) { - rect->width = w; - rect->height = h; - rect->x = x; - rect->y = y; - } else { - rect->width = util_format_get_nblocksx(res->format, w); - rect->height = util_format_get_nblocksy(res->format, h); - rect->x = util_format_get_nblocksx(res->format, x); - rect->y = util_format_get_nblocksy(res->format, y); - } - rect->tile_mode = mt->level[l].tile_mode; - rect->cpp = util_format_get_blocksize(res->format); - - if (mt->layout_3d) { - rect->z = z; - rect->depth = u_minify(res->depth0, l); - } else { - rect->base += z * mt->layer_stride; - rect->z = 0; - rect->depth = 1; - } -} - static void nvc0_resource_copy_region(struct pipe_context *pipe, struct pipe_resource *dst, unsigned dst_level, @@ -244,14 +216,14 @@ nvc0_resource_copy_region(struct pipe_context *pipe, nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING; - if (src->format == dst->format) { - struct nvc0_m2mf_rect drect, srect; + if (src->format == dst->format && src->nr_samples == dst->nr_samples) { + struct nv50_m2mf_rect drect, srect; unsigned i; unsigned nx = util_format_get_nblocksx(src->format, src_box->width); unsigned ny = util_format_get_nblocksy(src->format, src_box->height); - nvc0_setup_m2mf_rect(&drect, dst, dst_level, dstx, dsty, dstz); - nvc0_setup_m2mf_rect(&srect, src, src_level, + nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz); + nv50_m2mf_rect_setup(&srect, src, src_level, src_box->x, src_box->y, src_box->z); for (i = 0; i < src_box->depth; ++i) { diff --git a/src/gallium/drivers/nvc0/nvc0_tex.c b/src/gallium/drivers/nvc0/nvc0_tex.c index 4b82fdf05f9..0cbb4b33b59 100644 --- a/src/gallium/drivers/nvc0/nvc0_tex.c +++ b/src/gallium/drivers/nvc0/nvc0_tex.c @@ -114,6 +114,7 @@ nvc0_create_sampler_view(struct pipe_context *pipe, depth = MAX2(mt->base.base.array_size, mt->base.base.depth0); if (mt->base.base.target == PIPE_TEXTURE_1D_ARRAY || + /* mt->base.base.target == PIPE_TEXTURE_2D_ARRAY_MS || */ mt->base.base.target == PIPE_TEXTURE_2D_ARRAY) { /* there doesn't seem to be a base layer field in TIC */ tic[1] = view->pipe.u.tex.first_layer * mt->layer_stride; @@ -124,6 +125,7 @@ nvc0_create_sampler_view(struct pipe_context *pipe, case PIPE_TEXTURE_1D: tic[2] |= NV50_TIC_2_TARGET_1D; break; +/* case PIPE_TEXTURE_2D_MS: */ case PIPE_TEXTURE_2D: tic[2] |= NV50_TIC_2_TARGET_2D; break; @@ -143,6 +145,7 @@ nvc0_create_sampler_view(struct pipe_context *pipe, case PIPE_TEXTURE_1D_ARRAY: tic[2] |= NV50_TIC_2_TARGET_1D_ARRAY; break; +/* case PIPE_TEXTURE_2D_ARRAY_MS: */ case PIPE_TEXTURE_2D_ARRAY: tic[2] |= NV50_TIC_2_TARGET_2D_ARRAY; break; @@ -159,16 +162,22 @@ nvc0_create_sampler_view(struct pipe_context *pipe, else tic[3] = 0x00300000; - tic[4] = (1 << 31) | mt->base.base.width0; + tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x); - tic[5] = mt->base.base.height0 & 0xffff; + tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff; tic[5] |= depth << 16; tic[5] |= mt->base.base.last_level << 28; - tic[6] = 0x03000000; + tic[6] = (mt->ms_x > 1) ? 0x88000000 : 0x03000000; /* sampling points */ tic[7] = (view->pipe.u.tex.last_level << 4) | view->pipe.u.tex.first_level; + /* + if (mt->base.base.target == PIPE_TEXTURE_2D_MS || + mt->base.base.target == PIPE_TEXTURE_2D_ARRAY_MS) + tic[7] |= mt->ms_mode << 12; + */ + return &view->pipe; } diff --git a/src/gallium/drivers/nvc0/nvc0_transfer.c b/src/gallium/drivers/nvc0/nvc0_transfer.c index 1170f12da13..ecc9e213250 100644 --- a/src/gallium/drivers/nvc0/nvc0_transfer.c +++ b/src/gallium/drivers/nvc0/nvc0_transfer.c @@ -2,13 +2,12 @@ #include "util/u_format.h" #include "nvc0_context.h" -#include "nvc0_transfer.h" #include "nv50/nv50_defs.xml.h" struct nvc0_transfer { struct pipe_transfer base; - struct nvc0_m2mf_rect rect[2]; + struct nv50_m2mf_rect rect[2]; uint32_t nblocksx; uint16_t nblocksy; uint16_t nlayers; @@ -16,8 +15,8 @@ struct nvc0_transfer { void nvc0_m2mf_transfer_rect(struct pipe_screen *pscreen, - const struct nvc0_m2mf_rect *dst, - const struct nvc0_m2mf_rect *src, + const struct nv50_m2mf_rect *dst, + const struct nv50_m2mf_rect *src, uint32_t nblocksx, uint32_t nblocksy) { struct nouveau_channel *chan = nouveau_screen(pscreen)->channel; @@ -174,9 +173,10 @@ nvc0_m2mf_copy_linear(struct nouveau_context *nv, } } +#if 0 static void nvc0_m2mf_push_rect(struct pipe_screen *pscreen, - const struct nvc0_m2mf_rect *dst, + const struct nv50_m2mf_rect *dst, const void *data, unsigned nblocksx, unsigned nblocksy) { @@ -228,6 +228,7 @@ nvc0_m2mf_push_rect(struct pipe_screen *pscreen, nblocksy -= line_count; } } +#endif struct pipe_transfer * nvc0_miptree_transfer_new(struct pipe_context *pctx, @@ -240,10 +241,8 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, struct pipe_screen *pscreen = pctx->screen; struct nouveau_device *dev = nvc0->screen->base.device; struct nv50_miptree *mt = nv50_miptree(res); - struct nv50_miptree_level *lvl = &mt->level[level]; struct nvc0_transfer *tx; uint32_t size; - uint32_t w, h, d, z, layer; int ret; if (usage & PIPE_TRANSFER_MAP_DIRECTLY) @@ -253,45 +252,25 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, if (!tx) return NULL; - if (mt->layout_3d) { - z = box->z; - d = u_minify(res->depth0, level); - layer = 0; - } else { - z = 0; - d = 1; - layer = box->z; - } - tx->nlayers = box->depth; - pipe_resource_reference(&tx->base.resource, res); tx->base.level = level; tx->base.usage = usage; tx->base.box = *box; - tx->nblocksx = util_format_get_nblocksx(res->format, box->width); - tx->nblocksy = util_format_get_nblocksy(res->format, box->height); + if (util_format_is_plain(res->format)) { + tx->nblocksx = box->width << mt->ms_x; + tx->nblocksy = box->height << mt->ms_y; + } else { + tx->nblocksx = util_format_get_nblocksx(res->format, box->width); + tx->nblocksy = util_format_get_nblocksy(res->format, box->height); + } + tx->nlayers = box->depth; tx->base.stride = tx->nblocksx * util_format_get_blocksize(res->format); tx->base.layer_stride = tx->nblocksy * tx->base.stride; - w = u_minify(res->width0, level); - h = u_minify(res->height0, level); - - tx->rect[0].cpp = tx->rect[1].cpp = util_format_get_blocksize(res->format); - - tx->rect[0].bo = mt->base.bo; - tx->rect[0].base = lvl->offset + layer * mt->layer_stride; - tx->rect[0].tile_mode = lvl->tile_mode; - tx->rect[0].x = util_format_get_nblocksx(res->format, box->x); - tx->rect[0].y = util_format_get_nblocksy(res->format, box->y); - tx->rect[0].z = z; - tx->rect[0].width = util_format_get_nblocksx(res->format, w); - tx->rect[0].height = util_format_get_nblocksy(res->format, h); - tx->rect[0].depth = d; - tx->rect[0].pitch = lvl->pitch; - tx->rect[0].domain = NOUVEAU_BO_VRAM; + nv50_m2mf_rect_setup(&tx->rect[0], res, level, box->x, box->y, box->z); size = tx->base.layer_stride; @@ -302,6 +281,7 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, return NULL; } + tx->rect[1].cpp = tx->rect[0].cpp; tx->rect[1].width = tx->nblocksx; tx->rect[1].height = tx->nblocksy; tx->rect[1].depth = 1; @@ -310,6 +290,7 @@ nvc0_miptree_transfer_new(struct pipe_context *pctx, if (usage & PIPE_TRANSFER_READ) { unsigned base = tx->rect[0].base; + unsigned z = tx->rect[0].z; unsigned i; for (i = 0; i < tx->nlayers; ++i) { nvc0_m2mf_transfer_rect(pscreen, &tx->rect[1], &tx->rect[0], diff --git a/src/gallium/drivers/nvc0/nvc0_transfer.h b/src/gallium/drivers/nvc0/nvc0_transfer.h deleted file mode 100644 index 803ee3463ec..00000000000 --- a/src/gallium/drivers/nvc0/nvc0_transfer.h +++ /dev/null @@ -1,44 +0,0 @@ - -#ifndef __NVC0_TRANSFER_H__ -#define __NVC0_TRANSFER_H__ - -#include "pipe/p_state.h" - -struct pipe_transfer * -nvc0_miptree_transfer_new(struct pipe_context *pcontext, - struct pipe_resource *pt, - unsigned level, - unsigned usage, - const struct pipe_box *box); -void -nvc0_miptree_transfer_del(struct pipe_context *pcontext, - struct pipe_transfer *ptx); -void * -nvc0_miptree_transfer_map(struct pipe_context *pcontext, - struct pipe_transfer *ptx); -void -nvc0_miptree_transfer_unmap(struct pipe_context *pcontext, - struct pipe_transfer *ptx); - -struct nvc0_m2mf_rect { - struct nouveau_bo *bo; - uint32_t base; - unsigned domain; - uint32_t pitch; - uint32_t width; - uint32_t x; - uint32_t height; - uint32_t y; - uint16_t depth; - uint16_t z; - uint16_t tile_mode; - uint16_t cpp; -}; - -void -nvc0_m2mf_transfer_rect(struct pipe_screen *pscreen, - const struct nvc0_m2mf_rect *dst, - const struct nvc0_m2mf_rect *src, - uint32_t nblocksx, uint32_t nblocksy); - -#endif