diff options
Diffstat (limited to 'src/gallium/drivers/svga/svga_surface.c')
-rw-r--r-- | src/gallium/drivers/svga/svga_surface.c | 419 |
1 files changed, 353 insertions, 66 deletions
diff --git a/src/gallium/drivers/svga/svga_surface.c b/src/gallium/drivers/svga/svga_surface.c index 85d01546007..79981dcf5ff 100644 --- a/src/gallium/drivers/svga/svga_surface.c +++ b/src/gallium/drivers/svga/svga_surface.c @@ -29,6 +29,7 @@ #include "pipe/p_defines.h" #include "util/u_inlines.h" #include "os/os_thread.h" +#include "util/u_bitmask.h" #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -36,19 +37,21 @@ #include "svga_format.h" #include "svga_screen.h" #include "svga_context.h" +#include "svga_sampler_view.h" #include "svga_resource_texture.h" #include "svga_surface.h" #include "svga_debug.h" +static void svga_mark_surface_dirty(struct pipe_surface *surf); void svga_texture_copy_handle(struct svga_context *svga, struct svga_winsys_surface *src_handle, unsigned src_x, unsigned src_y, unsigned src_z, - unsigned src_level, unsigned src_face, + unsigned src_level, unsigned src_layer, struct svga_winsys_surface *dst_handle, unsigned dst_x, unsigned dst_y, unsigned dst_z, - unsigned dst_level, unsigned dst_face, + unsigned dst_level, unsigned dst_layer, unsigned width, unsigned height, unsigned depth) { struct svga_surface dst, src; @@ -59,12 +62,12 @@ svga_texture_copy_handle(struct svga_context *svga, src.handle = src_handle; src.real_level = src_level; - src.real_face = src_face; + src.real_layer = src_layer; src.real_zslice = 0; dst.handle = dst_handle; dst.real_level = dst_level; - dst.real_face = dst_face; + dst.real_layer = dst_layer; dst.real_zslice = 0; box.x = dst_x; @@ -103,11 +106,13 @@ svga_texture_copy_handle(struct svga_context *svga, struct svga_winsys_surface * svga_texture_view_surface(struct svga_context *svga, struct svga_texture *tex, + unsigned bind_flags, SVGA3dSurfaceFlags flags, SVGA3dSurfaceFormat format, unsigned start_mip, unsigned num_mip, - int face_pick, + int layer_pick, + unsigned num_layers, int zslice_pick, struct svga_host_surface_cache_key *key) /* OUT */ { @@ -117,8 +122,8 @@ svga_texture_view_surface(struct svga_context *svga, unsigned z_offset = 0; SVGA_DBG(DEBUG_PERF, - "svga: Create surface view: face %d zslice %d mips %d..%d\n", - face_pick, zslice_pick, start_mip, start_mip+num_mip-1); + "svga: Create surface view: layer %d zslice %d mips %d..%d\n", + layer_pick, zslice_pick, start_mip, start_mip+num_mip-1); key->flags = flags; key->format = format; @@ -127,12 +132,20 @@ svga_texture_view_surface(struct svga_context *svga, key->size.height = u_minify(tex->b.b.height0, start_mip); key->size.depth = zslice_pick < 0 ? u_minify(tex->b.b.depth0, start_mip) : 1; key->cachable = 1; + key->arraySize = 1; + key->numFaces = 1; + key->sampleCount = tex->b.b.nr_samples; + + if (key->sampleCount > 1) { + key->flags |= SVGA3D_SURFACE_MASKABLE_ANTIALIAS; + } - if (tex->b.b.target == PIPE_TEXTURE_CUBE && face_pick < 0) { + if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) { key->flags |= SVGA3D_SURFACE_CUBEMAP; key->numFaces = 6; - } else { - key->numFaces = 1; + } else if (tex->b.b.target == PIPE_TEXTURE_1D_ARRAY || + tex->b.b.target == PIPE_TEXTURE_2D_ARRAY) { + key->arraySize = num_layers; } if (key->format == SVGA3D_FORMAT_INVALID) { @@ -141,7 +154,7 @@ svga_texture_view_surface(struct svga_context *svga, } SVGA_DBG(DEBUG_DMA, "surface_create for texture view\n"); - handle = svga_screen_surface_create(ss, key); + handle = svga_screen_surface_create(ss, bind_flags, PIPE_USAGE_DEFAULT, key); if (!handle) { key->cachable = 0; return NULL; @@ -149,15 +162,15 @@ svga_texture_view_surface(struct svga_context *svga, SVGA_DBG(DEBUG_DMA, " --> got sid %p (texture view)\n", handle); - if (face_pick < 0) - face_pick = 0; + if (layer_pick < 0) + layer_pick = 0; if (zslice_pick >= 0) z_offset = zslice_pick; for (i = 0; i < key->numMipLevels; i++) { - for (j = 0; j < key->numFaces; j++) { - if (svga_is_texture_level_defined(tex, j + face_pick, i + start_mip)) { + for (j = 0; j < key->numFaces * key->arraySize; j++) { + if (svga_is_texture_level_defined(tex, j + layer_pick, i + start_mip)) { unsigned depth = (zslice_pick < 0 ? u_minify(tex->b.b.depth0, i + start_mip) : 1); @@ -166,7 +179,7 @@ svga_texture_view_surface(struct svga_context *svga, tex->handle, 0, 0, z_offset, i + start_mip, - j + face_pick, + j + layer_pick, handle, 0, 0, 0, i, j, u_minify(tex->b.b.width0, i + start_mip), u_minify(tex->b.b.height0, i + start_mip), @@ -179,33 +192,43 @@ svga_texture_view_surface(struct svga_context *svga, } +/** + * A helper function to create a surface view. + * The view boolean flag specifies whether svga_texture_view_surface() + * will be called to create a cloned surface and resource for the view. + */ static struct pipe_surface * -svga_create_surface(struct pipe_context *pipe, - struct pipe_resource *pt, - const struct pipe_surface *surf_tmpl) +svga_create_surface_view(struct pipe_context *pipe, + struct pipe_resource *pt, + const struct pipe_surface *surf_tmpl, + boolean view) { struct svga_context *svga = svga_context(pipe); struct svga_texture *tex = svga_texture(pt); struct pipe_screen *screen = pipe->screen; struct svga_screen *ss = svga_screen(screen); struct svga_surface *s; - unsigned face, zslice; - boolean view = FALSE; - SVGA3dSurfaceFlags flags; + unsigned layer, zslice, bind; + unsigned nlayers = 1; + SVGA3dSurfaceFlags flags = 0; SVGA3dSurfaceFormat format; - assert(surf_tmpl->u.tex.first_layer == surf_tmpl->u.tex.last_layer); - s = CALLOC_STRUCT(svga_surface); if (!s) return NULL; if (pt->target == PIPE_TEXTURE_CUBE) { - face = surf_tmpl->u.tex.first_layer; + layer = surf_tmpl->u.tex.first_layer; zslice = 0; } + else if (pt->target == PIPE_TEXTURE_1D_ARRAY || + pt->target == PIPE_TEXTURE_2D_ARRAY) { + layer = surf_tmpl->u.tex.first_layer; + zslice = 0; + nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1; + } else { - face = 0; + layer = 0; zslice = surf_tmpl->u.tex.first_layer; } @@ -218,25 +241,93 @@ svga_create_surface(struct pipe_context *pipe, s->base.u.tex.level = surf_tmpl->u.tex.level; s->base.u.tex.first_layer = surf_tmpl->u.tex.first_layer; s->base.u.tex.last_layer = surf_tmpl->u.tex.last_layer; + s->view_id = SVGA3D_INVALID_ID; + + s->backed = NULL; if (util_format_is_depth_or_stencil(surf_tmpl->format)) { - flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL; + flags = SVGA3D_SURFACE_HINT_DEPTHSTENCIL | + SVGA3D_SURFACE_BIND_DEPTH_STENCIL; + bind = PIPE_BIND_DEPTH_STENCIL; } else { - flags = SVGA3D_SURFACE_HINT_RENDERTARGET; + flags = SVGA3D_SURFACE_HINT_RENDERTARGET | + SVGA3D_SURFACE_BIND_RENDER_TARGET; + bind = PIPE_BIND_RENDER_TARGET; } - format = svga_translate_format(ss, surf_tmpl->format, 0); + if (tex->imported) + format = tex->key.format; + else + format = svga_translate_format(ss, surf_tmpl->format, bind); + assert(format != SVGA3D_FORMAT_INVALID); - if (svga_screen(screen)->debug.force_surface_view) - view = TRUE; + if (view) { + SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u layer %u z %u, %p\n", + pt, surf_tmpl->u.tex.level, layer, zslice, s); + + if (svga_have_vgpu10(svga)) { + switch (pt->target) { + case PIPE_TEXTURE_1D: + flags |= SVGA3D_SURFACE_1D; + break; + case PIPE_TEXTURE_1D_ARRAY: + flags |= SVGA3D_SURFACE_1D | SVGA3D_SURFACE_ARRAY; + break; + case PIPE_TEXTURE_2D_ARRAY: + flags |= SVGA3D_SURFACE_ARRAY; + break; + case PIPE_TEXTURE_3D: + flags |= SVGA3D_SURFACE_VOLUME; + break; + case PIPE_TEXTURE_CUBE: + if (nlayers == 6) + flags |= SVGA3D_SURFACE_CUBEMAP; + break; + default: + break; + } + } - /* Currently only used for compressed textures */ - if (format != svga_translate_format(ss, surf_tmpl->format, 0)) { - view = TRUE; + /* When we clone the surface view resource, use the format used in + * the creation of the original resource. + */ + s->handle = svga_texture_view_surface(svga, tex, bind, flags, tex->key.format, + surf_tmpl->u.tex.level, 1, + layer, nlayers, zslice, &s->key); + s->key.format = format; + s->real_layer = 0; + s->real_level = 0; + s->real_zslice = 0; + } else { + SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: no %p, level %u, layer %u, z %u, %p\n", + pt, surf_tmpl->u.tex.level, layer, zslice, s); + + memset(&s->key, 0, sizeof s->key); + s->key.format = format; + s->handle = tex->handle; + s->real_layer = layer; + s->real_zslice = zslice; + s->real_level = surf_tmpl->u.tex.level; } + return &s->base; +} + + +static struct pipe_surface * +svga_create_surface(struct pipe_context *pipe, + struct pipe_resource *pt, + const struct pipe_surface *surf_tmpl) +{ + struct svga_context *svga = svga_context(pipe); + struct pipe_screen *screen = pipe->screen; + boolean view = FALSE; + + if (svga_screen(screen)->debug.force_surface_view) + view = TRUE; + if (surf_tmpl->u.tex.level != 0 && svga_screen(screen)->debug.force_level_surface_view) view = TRUE; @@ -244,47 +335,170 @@ svga_create_surface(struct pipe_context *pipe, if (pt->target == PIPE_TEXTURE_3D) view = TRUE; - if (svga_screen(screen)->debug.no_surface_view) + if (svga_have_vgpu10(svga) || svga_screen(screen)->debug.no_surface_view) view = FALSE; - if (view) { - SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: yes %p, level %u face %u z %u, %p\n", - pt, surf_tmpl->u.tex.level, face, zslice, s); + return svga_create_surface_view(pipe, pt, surf_tmpl, view); +} - s->handle = svga_texture_view_surface(svga, tex, flags, format, - surf_tmpl->u.tex.level, - 1, face, zslice, &s->key); - s->real_face = 0; - s->real_level = 0; - s->real_zslice = 0; - } else { - SVGA_DBG(DEBUG_VIEWS, "svga: Surface view: no %p, level %u, face %u, z %u, %p\n", - pt, surf_tmpl->u.tex.level, face, zslice, s); - memset(&s->key, 0, sizeof s->key); - s->handle = tex->handle; - s->real_face = face; - s->real_zslice = zslice; - s->real_level = surf_tmpl->u.tex.level; +/** + * Clone the surface view and its associated resource. + */ +static struct svga_surface * +create_backed_surface_view(struct svga_context *svga, struct svga_surface *s) +{ + struct svga_surface *bs = s->backed; + + if (bs == NULL) { + struct svga_texture *tex = svga_texture(s->base.texture); + struct pipe_surface *backed_view; + + backed_view = svga_create_surface_view(&svga->pipe, + &tex->b.b, + &s->base, + TRUE); + + bs = svga_surface(backed_view); + s->backed = bs; } + svga_mark_surface_dirty(&bs->base); + + return bs; +} + +/** + * Create a DX RenderTarget/DepthStencil View for the given surface, + * if needed. + */ +struct pipe_surface * +svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s) +{ + enum pipe_error ret = PIPE_OK; + int try; + + assert(svga_have_vgpu10(svga)); + + /** + * DX spec explicitly specifies that no resource can be bound to a render + * target view and a shader resource view simultanously. + * So first check if the resource bound to this surface view collides with + * a sampler view. If so, then we will clone this surface view and its + * associated resource. We will then use the cloned surface view for + * render target. + */ + if (svga_check_sampler_view_resource_collision(svga, s->handle)) { + SVGA_DBG(DEBUG_VIEWS, + "same resource used in shaderResource and renderTarget 0x%x\n", + s->handle); + s = create_backed_surface_view(svga, s); + } + + if (s->view_id == SVGA3D_INVALID_ID) { + SVGA3dResourceType resType; + SVGA3dRenderTargetViewDesc desc; + + desc.tex.mipSlice = s->real_level; + desc.tex.firstArraySlice = s->real_layer + s->real_zslice; + desc.tex.arraySize = + s->base.u.tex.last_layer - s->base.u.tex.first_layer + 1; + + s->view_id = util_bitmask_add(svga->surface_view_id_bm); + + switch (s->base.texture->target) { + case PIPE_TEXTURE_1D: + case PIPE_TEXTURE_1D_ARRAY: + resType = SVGA3D_RESOURCE_TEXTURE1D; + break; + case PIPE_TEXTURE_RECT: + case PIPE_TEXTURE_2D: + case PIPE_TEXTURE_2D_ARRAY: + case PIPE_TEXTURE_CUBE: + /* drawing to cube map is treated as drawing to 2D array */ + resType = SVGA3D_RESOURCE_TEXTURE2D; + break; + case PIPE_TEXTURE_3D: + resType = SVGA3D_RESOURCE_TEXTURE3D; + break; + default: + assert(!"Unexpected texture target"); + resType = SVGA3D_RESOURCE_TEXTURE2D; + } + + for (try = 0; try < 2; try++) { + if (util_format_is_depth_or_stencil(s->base.format)) { + ret = SVGA3D_vgpu10_DefineDepthStencilView(svga->swc, + s->view_id, + s->handle, + s->key.format, + resType, + &desc); + } + else { + ret = SVGA3D_vgpu10_DefineRenderTargetView(svga->swc, + s->view_id, + s->handle, + s->key.format, + resType, + &desc); + } + if (ret == PIPE_OK) + break; + svga_context_flush(svga, NULL); + } + + assert(ret == PIPE_OK); + if (ret != PIPE_OK) { + util_bitmask_clear(svga->surface_view_id_bm, s->view_id); + s->view_id = SVGA3D_INVALID_ID; + } + } return &s->base; } + static void svga_surface_destroy(struct pipe_context *pipe, struct pipe_surface *surf) { + struct svga_context *svga = svga_context(pipe); struct svga_surface *s = svga_surface(surf); struct svga_texture *t = svga_texture(surf->texture); struct svga_screen *ss = svga_screen(surf->texture->screen); + enum pipe_error ret = PIPE_OK; + + /* Destroy the backed view surface if it exists */ + if (s->backed) { + svga_surface_destroy(pipe, &s->backed->base); + s->backed = NULL; + } if (s->handle != t->handle) { SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle); svga_screen_surface_destroy(ss, &s->key, &s->handle); } + if (s->view_id != SVGA3D_INVALID_ID) { + unsigned try; + + assert(svga_have_vgpu10(svga)); + for (try = 0; try < 2; try++) { + if (util_format_is_depth_or_stencil(s->base.format)) { + ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id); + } + else { + ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id); + } + if (ret == PIPE_OK) + break; + svga_context_flush(svga, NULL); + } + assert(ret == PIPE_OK); + util_bitmask_clear(svga->surface_view_id_bm, s->view_id); + } + pipe_resource_reference(&surf->texture, NULL); FREE(surf); } @@ -302,11 +516,8 @@ svga_mark_surface_dirty(struct pipe_surface *surf) if (s->handle == tex->handle) { /* hmm so 3d textures always have all their slices marked ? */ - if (surf->texture->target == PIPE_TEXTURE_CUBE) - svga_define_texture_level(tex, surf->u.tex.first_layer, - surf->u.tex.level); - else - svga_define_texture_level(tex, 0, surf->u.tex.level); + svga_define_texture_level(tex, surf->u.tex.first_layer, + surf->u.tex.level); } else { /* this will happen later in svga_propagate_surface */ @@ -345,18 +556,26 @@ svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf) struct svga_surface *s = svga_surface(surf); struct svga_texture *tex = svga_texture(surf->texture); struct svga_screen *ss = svga_screen(surf->texture->screen); - unsigned zslice, face; + unsigned zslice, layer; + unsigned nlayers = 1; + unsigned i; if (!s->dirty) return; if (surf->texture->target == PIPE_TEXTURE_CUBE) { zslice = 0; - face = surf->u.tex.first_layer; + layer = surf->u.tex.first_layer; + } + else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY || + surf->texture->target == PIPE_TEXTURE_2D_ARRAY) { + zslice = 0; + layer = surf->u.tex.first_layer; + nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1; } else { zslice = surf->u.tex.first_layer; - face = 0; + layer = 0; } s->dirty = FALSE; @@ -367,12 +586,14 @@ svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf) SVGA_DBG(DEBUG_VIEWS, "svga: Surface propagate: tex %p, level %u, from %p\n", tex, surf->u.tex.level, surf); - svga_texture_copy_handle(svga, - s->handle, 0, 0, 0, s->real_level, s->real_face, - tex->handle, 0, 0, zslice, surf->u.tex.level, face, - u_minify(tex->b.b.width0, surf->u.tex.level), - u_minify(tex->b.b.height0, surf->u.tex.level), 1); - svga_define_texture_level(tex, face, surf->u.tex.level); + for (i = 0; i < nlayers; i++) { + svga_texture_copy_handle(svga, + s->handle, 0, 0, 0, s->real_level, s->real_layer + i, + tex->handle, 0, 0, zslice, surf->u.tex.level, layer + i, + u_minify(tex->b.b.width0, surf->u.tex.level), + u_minify(tex->b.b.height0, surf->u.tex.level), 1); + svga_define_texture_level(tex, layer + i, surf->u.tex.level); + } } } @@ -390,10 +611,76 @@ svga_surface_needs_propagation(const struct pipe_surface *surf) } +static void +svga_get_sample_position(struct pipe_context *context, + unsigned sample_count, unsigned sample_index, + float *pos_out) +{ + /* We can't actually query the device to learn the sample positions. + * These were grabbed from nvidia's driver. + */ + static const float pos1[1][2] = { + { 0.5, 0.5 } + }; + static const float pos4[4][2] = { + { 0.375000, 0.125000 }, + { 0.875000, 0.375000 }, + { 0.125000, 0.625000 }, + { 0.625000, 0.875000 } + }; + static const float pos8[8][2] = { + { 0.562500, 0.312500 }, + { 0.437500, 0.687500 }, + { 0.812500, 0.562500 }, + { 0.312500, 0.187500 }, + { 0.187500, 0.812500 }, + { 0.062500, 0.437500 }, + { 0.687500, 0.937500 }, + { 0.937500, 0.062500 } + }; + static const float pos16[16][2] = { + { 0.187500, 0.062500 }, + { 0.437500, 0.187500 }, + { 0.062500, 0.312500 }, + { 0.312500, 0.437500 }, + { 0.687500, 0.062500 }, + { 0.937500, 0.187500 }, + { 0.562500, 0.312500 }, + { 0.812500, 0.437500 }, + { 0.187500, 0.562500 }, + { 0.437500, 0.687500 }, + { 0.062500, 0.812500 }, + { 0.312500, 0.937500 }, + { 0.687500, 0.562500 }, + { 0.937500, 0.687500 }, + { 0.562500, 0.812500 }, + { 0.812500, 0.937500 } + }; + const float (*positions)[2]; + + switch (sample_count) { + case 4: + positions = pos4; + break; + case 8: + positions = pos8; + break; + case 16: + positions = pos16; + break; + default: + positions = pos1; + } + + pos_out[0] = positions[sample_index][0]; + pos_out[1] = positions[sample_index][1]; +} + void svga_init_surface_functions(struct svga_context *svga) { svga->pipe.create_surface = svga_create_surface; svga->pipe.surface_destroy = svga_surface_destroy; + svga->pipe.get_sample_position = svga_get_sample_position; } |