nv50,nvc0: implement blit

This commit is contained in:
Christoph Bumiller 2012-09-26 23:06:40 +02:00
parent de80660c2b
commit 36ea744f58
16 changed files with 1403 additions and 720 deletions

View File

@ -0,0 +1,182 @@
#ifndef __NV50_BLIT_H__
#define __NV50_BLIT_H__
#include "util/u_inlines.h"
#include "util/u_format.h"
void *
nv50_blitter_make_fp(struct pipe_context *,
unsigned mode,
enum pipe_texture_target);
unsigned
nv50_blit_select_mode(const struct pipe_blit_info *);
/* Converted to a pipe->blit. */
void
nv50_resource_resolve(struct pipe_context *, const struct pipe_resolve_info *);
#define NV50_BLIT_MODE_PASS 0 /* pass through TEX $t0/$s0 output */
#define NV50_BLIT_MODE_Z24S8 1 /* encode ZS values for RGBA unorm8 */
#define NV50_BLIT_MODE_S8Z24 2
#define NV50_BLIT_MODE_X24S8 3
#define NV50_BLIT_MODE_S8X24 4
#define NV50_BLIT_MODE_Z24X8 5
#define NV50_BLIT_MODE_X8Z24 6
#define NV50_BLIT_MODE_ZS 7 /* put $t0/$s0 into R, $t1/$s1 into G */
#define NV50_BLIT_MODE_XS 8 /* put $t1/$s1 into G */
#define NV50_BLIT_MODES 9
/* CUBE and RECT textures are reinterpreted as 2D(_ARRAY) */
#define NV50_BLIT_TEXTURE_BUFFER 0
#define NV50_BLIT_TEXTURE_1D 1
#define NV50_BLIT_TEXTURE_2D 2
#define NV50_BLIT_TEXTURE_3D 3
#define NV50_BLIT_TEXTURE_1D_ARRAY 4
#define NV50_BLIT_TEXTURE_2D_ARRAY 5
#define NV50_BLIT_MAX_TEXTURE_TYPES 6
static INLINE unsigned
nv50_blit_texture_type(enum pipe_texture_target target)
{
switch (target) {
case PIPE_TEXTURE_1D: return NV50_BLIT_TEXTURE_1D;
case PIPE_TEXTURE_2D: return NV50_BLIT_TEXTURE_2D;
case PIPE_TEXTURE_3D: return NV50_BLIT_TEXTURE_3D;
case PIPE_TEXTURE_1D_ARRAY: return NV50_BLIT_TEXTURE_1D_ARRAY;
case PIPE_TEXTURE_2D_ARRAY: return NV50_BLIT_TEXTURE_2D_ARRAY;
default:
assert(target == PIPE_BUFFER);
return NV50_BLIT_TEXTURE_BUFFER;
}
}
static INLINE unsigned
nv50_blit_get_tgsi_texture_target(enum pipe_texture_target target)
{
switch (target) {
case PIPE_TEXTURE_1D: return TGSI_TEXTURE_1D;
case PIPE_TEXTURE_2D: return TGSI_TEXTURE_2D;
case PIPE_TEXTURE_3D: return TGSI_TEXTURE_3D;
case PIPE_TEXTURE_1D_ARRAY: return TGSI_TEXTURE_1D_ARRAY;
case PIPE_TEXTURE_2D_ARRAY: return TGSI_TEXTURE_2D_ARRAY;
default:
assert(target == PIPE_BUFFER);
return TGSI_TEXTURE_BUFFER;
}
}
static INLINE enum pipe_texture_target
nv50_blit_reinterpret_pipe_texture_target(enum pipe_texture_target target)
{
switch (target) {
case PIPE_TEXTURE_CUBE:
return PIPE_TEXTURE_2D_ARRAY;
case PIPE_TEXTURE_RECT:
return PIPE_TEXTURE_2D;
default:
return target;
}
}
static INLINE unsigned
nv50_blit_get_filter(const struct pipe_blit_info *info)
{
if (info->dst.resource->nr_samples < info->src.resource->nr_samples)
return util_format_is_depth_or_stencil(info->src.format) ? 0 : 1;
if (info->filter != PIPE_TEX_FILTER_LINEAR)
return 0;
if ((info->dst.box.width == info->src.box.width ||
info->dst.box.width == -info->src.box.width) &&
(info->dst.box.height == info->src.box.height ||
info->dst.box.height == -info->src.box.height))
return 0;
return 1;
}
/* Since shaders cannot export stencil, we cannot copy stencil values when
* rendering to ZETA, so we attach the ZS surface to a colour render target.
*/
static INLINE enum pipe_format
nv50_blit_zeta_to_colour_format(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_Z16_UNORM:
return PIPE_FORMAT_R16_UNORM;
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
case PIPE_FORMAT_Z24X8_UNORM:
return PIPE_FORMAT_R8G8B8A8_UNORM;
case PIPE_FORMAT_Z32_FLOAT:
return PIPE_FORMAT_R32_FLOAT;
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
return PIPE_FORMAT_R32G32_FLOAT;
default:
assert(0);
return PIPE_FORMAT_NONE;
}
}
static INLINE uint16_t
nv50_blit_derive_color_mask(const struct pipe_blit_info *info)
{
const unsigned mask = info->mask;
uint16_t color_mask = 0;
switch (info->dst.format) {
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
if (mask & PIPE_MASK_S)
color_mask |= 0x1000;
/* fall through */
case PIPE_FORMAT_Z24X8_UNORM:
if (mask & PIPE_MASK_Z)
color_mask |= 0x0111;
break;
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
if (mask & PIPE_MASK_Z)
color_mask |= 0x1110;
if (mask & PIPE_MASK_S)
color_mask |= 0x0001;
break;
default:
if (mask & (PIPE_MASK_R | PIPE_MASK_Z)) color_mask |= 0x0001;
if (mask & (PIPE_MASK_G | PIPE_MASK_S)) color_mask |= 0x0010;
if (mask & PIPE_MASK_B) color_mask |= 0x0100;
if (mask & PIPE_MASK_A) color_mask |= 0x1000;
break;
}
return color_mask;
}
static INLINE uint32_t
nv50_blit_eng2d_get_mask(const struct pipe_blit_info *info)
{
uint32_t mask = 0;
switch (info->dst.format) {
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
if (info->mask & PIPE_MASK_Z) mask |= 0x00ffffff;
if (info->mask & PIPE_MASK_S) mask |= 0xff000000;
break;
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
if (info->mask & PIPE_MASK_Z) mask |= 0xffffff00;
if (info->mask & PIPE_MASK_S) mask |= 0x000000ff;
break;
case PIPE_FORMAT_X8Z24_UNORM:
if (info->mask & PIPE_MASK_Z) mask = 0x00ffffff;
break;
default:
mask = 0xffffffff;
break;
}
return mask;
}
#endif /* __NV50_BLIT_H__ */

View File

@ -128,6 +128,9 @@ nv50_create(struct pipe_screen *pscreen, void *priv)
return NULL;
pipe = &nv50->base.pipe;
if (!nv50_blitctx_create(nv50))
goto out_err;
nv50->base.pushbuf = screen->base.pushbuf;
ret = nouveau_bufctx_new(screen->base.client, NV50_BIND_COUNT,
@ -195,6 +198,8 @@ out_err:
nouveau_bufctx_del(&nv50->bufctx_3d);
if (nv50->bufctx)
nouveau_bufctx_del(&nv50->bufctx);
if (nv50->blit)
FREE(nv50->blit);
FREE(nv50);
}
return NULL;

View File

@ -73,6 +73,10 @@
#define NV50_CB_AUX 127
struct nv50_blitctx;
boolean nv50_blitctx_create(struct nv50_context *);
struct nv50_context {
struct nouveau_context base;
@ -151,6 +155,11 @@ struct nv50_context {
boolean vbo_push_hint;
struct pipe_query *cond_query;
uint cond_mode;
struct nv50_blitctx *blit;
#ifdef NV50_WITH_DRAW_MODULE
struct draw_context *draw;
#endif
@ -232,6 +241,12 @@ extern void nv50_init_surface_functions(struct nv50_context *);
void nv50_validate_textures(struct nv50_context *);
void nv50_validate_samplers(struct nv50_context *);
struct pipe_sampler_view *
nv50_create_texture_view(struct pipe_context *,
struct pipe_resource *,
const struct pipe_sampler_view *,
uint32_t flags,
enum pipe_texture_target);
struct pipe_sampler_view *
nv50_create_sampler_view(struct pipe_context *,
struct pipe_resource *,

View File

@ -327,6 +327,9 @@ nv50_render_condition(struct pipe_context *pipe,
struct nouveau_pushbuf *push = nv50->base.pushbuf;
struct nv50_query *q;
nv50->cond_query = pq;
nv50->cond_mode = mode;
PUSH_SPACE(push, 6);
if (!pq) {

View File

@ -60,6 +60,11 @@ nv50_miptree(struct pipe_resource *pt)
return (struct nv50_miptree *)pt;
}
#define NV50_TEXVIEW_SCALED_COORDS (1 << 0)
#define NV50_TEXVIEW_FILTER_MSAA8 (1 << 1)
/* Internal functions:
*/
boolean

View File

@ -268,7 +268,8 @@ nv50_screen_destroy(struct pipe_screen *pscreen)
if (screen->base.pushbuf)
screen->base.pushbuf->user_priv = NULL;
FREE(screen->blitctx);
if (screen->blitter)
nv50_blitter_destroy(screen);
nouveau_bo_ref(NULL, &screen->code);
nouveau_bo_ref(NULL, &screen->tls_bo);
@ -750,7 +751,7 @@ nv50_screen_create(struct nouveau_device *dev)
screen->tic.entries = CALLOC(4096, sizeof(void *));
screen->tsc.entries = screen->tic.entries + 2048;
if (!nv50_blitctx_create(screen))
if (!nv50_blitter_create(screen))
goto fail;
nv50_screen_init_hwctx(screen);

View File

@ -21,7 +21,7 @@ struct nv50_context;
#define NV50_SCREEN_RESIDENT_BO_COUNT 5
struct nv50_blitctx;
struct nv50_blitter;
struct nv50_screen {
struct nouveau_screen base;
@ -43,7 +43,7 @@ struct nv50_screen {
struct nouveau_heap *gp_code_heap;
struct nouveau_heap *fp_code_heap;
struct nv50_blitctx *blitctx;
struct nv50_blitter *blitter;
struct {
void **entries;
@ -75,7 +75,8 @@ nv50_screen(struct pipe_screen *screen)
return (struct nv50_screen *)screen;
}
boolean nv50_blitctx_create(struct nv50_screen *);
boolean nv50_blitter_create(struct nv50_screen *);
void nv50_blitter_destroy(struct nv50_screen *);
int nv50_screen_tic_alloc(struct nv50_screen *, void *);
int nv50_screen_tsc_alloc(struct nv50_screen *, void *);

File diff suppressed because it is too large Load Diff

View File

@ -71,8 +71,23 @@ nv50_init_tic_entry_linear(uint32_t *tic, struct pipe_resource *res)
struct pipe_sampler_view *
nv50_create_sampler_view(struct pipe_context *pipe,
struct pipe_resource *texture,
struct pipe_resource *res,
const struct pipe_sampler_view *templ)
{
uint32_t flags = 0;
if (res->target == PIPE_TEXTURE_RECT)
flags |= NV50_TEXVIEW_SCALED_COORDS;
return nv50_create_texture_view(pipe, res, templ, flags, res->target);
}
struct pipe_sampler_view *
nv50_create_texture_view(struct pipe_context *pipe,
struct pipe_resource *texture,
const struct pipe_sampler_view *templ,
uint32_t flags,
enum pipe_texture_target target)
{
const struct util_format_description *desc;
uint64_t addr;
@ -139,14 +154,14 @@ nv50_create_sampler_view(struct pipe_context *pipe,
return &view->pipe;
}
if (mt->base.base.target != PIPE_TEXTURE_RECT)
if (!(flags & NV50_TEXVIEW_SCALED_COORDS))
tic[2] |= NV50_TIC_2_NORMALIZED_COORDS;
tic[2] |=
((mt->level[0].tile_mode & 0x0f0) << (22 - 4)) |
((mt->level[0].tile_mode & 0xf00) << (25 - 8));
switch (mt->base.base.target) {
switch (target) {
case PIPE_TEXTURE_1D:
tic[2] |= NV50_TIC_2_TARGET_1D;
break;
@ -181,18 +196,22 @@ nv50_create_sampler_view(struct pipe_context *pipe,
return FALSE;
}
tic[3] = 0x00300000;
tic[3] = (flags & NV50_TEXVIEW_FILTER_MSAA8) ? 0x20000000 : 0x00300000;
tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x);
tic[5] = (mt->base.base.height0 << mt->ms_y) & 0xffff;
tic[5] |= depth << 16;
tic[5] |= mt->base.base.last_level << 28;
tic[5] |= mt->base.base.last_level << NV50_TIC_5_LAST_LEVEL__SHIFT;
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 (unlikely(!(tic[2] & NV50_TIC_2_NORMALIZED_COORDS)))
if (mt->base.base.last_level)
tic[5] &= ~NV50_TIC_5_LAST_LEVEL__MASK;
return &view->pipe;
}

View File

@ -129,6 +129,9 @@ nvc0_create(struct pipe_screen *pscreen, void *priv)
return NULL;
pipe = &nvc0->base.pipe;
if (!nvc0_blitctx_create(nvc0))
goto out_err;
nvc0->base.pushbuf = screen->base.pushbuf;
ret = nouveau_bufctx_new(screen->base.client, NVC0_BIND_COUNT,
@ -199,6 +202,8 @@ out_err:
nouveau_bufctx_del(&nvc0->bufctx_3d);
if (nvc0->bufctx)
nouveau_bufctx_del(&nvc0->bufctx);
if (nvc0->blit)
FREE(nvc0->blit);
FREE(nvc0);
}
return NULL;

View File

@ -71,6 +71,11 @@
#define NVC0_BIND_M2MF 0
#define NVC0_BIND_FENCE 1
struct nvc0_blitctx;
boolean nvc0_blitctx_create(struct nvc0_context *);
struct nvc0_context {
struct nouveau_context base;
@ -159,6 +164,11 @@ struct nvc0_context {
struct pipe_stream_output_target *tfbbuf[4];
unsigned num_tfbbufs;
struct pipe_query *cond_query;
uint cond_mode;
struct nvc0_blitctx *blit;
#ifdef NVC0_WITH_DRAW_MODULE
struct draw_context *draw;
#endif
@ -240,6 +250,12 @@ void nvc0_validate_textures(struct nvc0_context *);
void nvc0_validate_samplers(struct nvc0_context *);
void nve4_set_tex_handles(struct nvc0_context *);
struct pipe_sampler_view *
nvc0_create_texture_view(struct pipe_context *,
struct pipe_resource *,
const struct pipe_sampler_view *,
uint32_t flags,
enum pipe_texture_target);
struct pipe_sampler_view *
nvc0_create_sampler_view(struct pipe_context *,
struct pipe_resource *,

View File

@ -436,6 +436,9 @@ nvc0_render_condition(struct pipe_context *pipe,
mode != PIPE_RENDER_COND_NO_WAIT &&
mode != PIPE_RENDER_COND_BY_REGION_NO_WAIT;
nvc0->cond_query = pq;
nvc0->cond_mode = mode;
if (!pq) {
PUSH_SPACE(push, 1);
IMMED_NVC0(push, NVC0_3D(COND_MODE), NVC0_3D_COND_MODE_ALWAYS);

View File

@ -257,7 +257,8 @@ nvc0_screen_destroy(struct pipe_screen *pscreen)
if (screen->base.pushbuf)
screen->base.pushbuf->user_priv = NULL;
FREE(screen->blitctx);
if (screen->blitter)
nvc0_blitter_destroy(screen);
nouveau_bo_ref(NULL, &screen->text);
nouveau_bo_ref(NULL, &screen->uniform_bo);
@ -746,7 +747,7 @@ nvc0_screen_create(struct nouveau_device *dev)
mm_config.nvc0.memtype = 0xfe0;
screen->mm_VRAM_fe0 = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, &mm_config);
if (!nvc0_blitctx_create(screen))
if (!nvc0_blitter_create(screen))
goto fail;
nouveau_fence_new(&screen->base, &screen->base.fence.current, FALSE);

View File

@ -19,7 +19,7 @@
struct nvc0_context;
struct nvc0_blitctx;
struct nvc0_blitter;
struct nvc0_screen {
struct nouveau_screen base;
@ -39,7 +39,7 @@ struct nvc0_screen {
struct nouveau_heap *text_heap;
struct nouveau_heap *lib_code; /* allocated from text_heap */
struct nvc0_blitctx *blitctx;
struct nvc0_blitter *blitter;
struct {
void **entries;
@ -72,7 +72,8 @@ nvc0_screen(struct pipe_screen *screen)
return (struct nvc0_screen *)screen;
}
boolean nvc0_blitctx_create(struct nvc0_screen *);
boolean nvc0_blitter_create(struct nvc0_screen *);
void nvc0_blitter_destroy(struct nvc0_screen *);
void nvc0_screen_make_buffers_resident(struct nvc0_screen *);

File diff suppressed because it is too large Load Diff

View File

@ -55,8 +55,23 @@ nv50_tic_swizzle(uint32_t tc, unsigned swz, boolean tex_int)
struct pipe_sampler_view *
nvc0_create_sampler_view(struct pipe_context *pipe,
struct pipe_resource *texture,
struct pipe_resource *res,
const struct pipe_sampler_view *templ)
{
uint32_t flags = 0;
if (res->target == PIPE_TEXTURE_RECT)
flags |= NV50_TEXVIEW_SCALED_COORDS;
return nvc0_create_texture_view(pipe, res, templ, flags, res->target);
}
struct pipe_sampler_view *
nvc0_create_texture_view(struct pipe_context *pipe,
struct pipe_resource *texture,
const struct pipe_sampler_view *templ,
uint32_t flags,
enum pipe_texture_target target)
{
const struct util_format_description *desc;
uint64_t address;
@ -132,7 +147,7 @@ nvc0_create_sampler_view(struct pipe_context *pipe,
return &view->pipe;
}
if (mt->base.base.target != PIPE_TEXTURE_RECT)
if (!(flags & NV50_TEXVIEW_SCALED_COORDS))
tic[2] |= NV50_TIC_2_NORMALIZED_COORDS;
tic[2] |=
@ -149,7 +164,7 @@ nvc0_create_sampler_view(struct pipe_context *pipe,
tic[1] = address;
tic[2] |= address >> 32;
switch (mt->base.base.target) {
switch (target) {
case PIPE_TEXTURE_1D:
tic[2] |= NV50_TIC_2_TARGET_1D;
break;
@ -185,7 +200,7 @@ nvc0_create_sampler_view(struct pipe_context *pipe,
if (mt->base.base.target == PIPE_BUFFER)
tic[3] = mt->base.base.width0;
else
tic[3] = 0x00300000;
tic[3] = (flags & NV50_TEXVIEW_FILTER_MSAA8) ? 0x20000000 : 0x00300000;
tic[4] = (1 << 31) | (mt->base.base.width0 << mt->ms_x);