st/mesa: add an entirely separate codepath for setting up buffer views

Remove handling of buffers from all texture paths.
This simplifies things for both buffers and textures.

get_sampler_view_format is also cleaned up not to call
util_format_is_depth_and_stencil.

v2: also update st_NewTextureHandle

Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com> (v1)
This commit is contained in:
Marek Olšák 2017-06-12 01:00:04 +02:00
parent fbd9cc6169
commit f0ecd36ef8
6 changed files with 135 additions and 101 deletions

View File

@ -36,6 +36,7 @@
#include "util/u_surface.h"
#include "cso_cache/cso_context.h"
#include "st_cb_bufferobjects.h"
#include "st_cb_texture.h"
#include "st_debug.h"
#include "st_texture.h"
@ -53,7 +54,6 @@ st_convert_image(const struct st_context *st, const struct gl_image_unit *u,
{
struct st_texture_object *stObj = st_texture_object(u->TexObj);
img->resource = stObj->pt;
img->format = st_mesa_format_to_pipe_format(st, u->_ActualFormat);
switch (u->Access) {
@ -70,16 +70,32 @@ st_convert_image(const struct st_context *st, const struct gl_image_unit *u,
unreachable("bad gl_image_unit::Access");
}
if (stObj->pt->target == PIPE_BUFFER) {
if (stObj->base.Target == GL_TEXTURE_BUFFER) {
struct st_buffer_object *stbuf =
st_buffer_object(stObj->base.BufferObject);
unsigned base, size;
base = stObj->base.BufferOffset;
assert(base < stObj->pt->width0);
size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize);
if (!stbuf || !stbuf->buffer) {
memset(img, 0, sizeof(*img));
return;
}
struct pipe_resource *buf = stbuf->buffer;
base = stObj->base.BufferOffset;
assert(base < buf->width0);
size = MIN2(buf->width0 - base, (unsigned)stObj->base.BufferSize);
img->resource = stbuf->buffer;
img->u.buf.offset = base;
img->u.buf.size = size;
} else {
if (!st_finalize_texture(st->ctx, st->pipe, u->TexObj, 0) ||
!stObj->pt) {
memset(img, 0, sizeof(*img));
return;
}
img->resource = stObj->pt;
img->u.tex.level = u->Level + stObj->base.MinLevel;
if (stObj->pt->target == PIPE_TEXTURE_3D) {
if (u->Layered) {
@ -111,11 +127,8 @@ st_convert_image_from_unit(const struct st_context *st,
GLuint imgUnit)
{
struct gl_image_unit *u = &st->ctx->ImageUnits[imgUnit];
struct st_texture_object *stObj = st_texture_object(u->TexObj);
if (!_mesa_is_image_unit_valid(st->ctx, u) ||
!st_finalize_texture(st->ctx, st->pipe, u->TexObj, 0) ||
!stObj->pt) {
if (!_mesa_is_image_unit_valid(st->ctx, u)) {
memset(img, 0, sizeof(*img));
return;
}

View File

@ -73,6 +73,11 @@ st_update_single_texture(struct st_context *st,
stObj = st_texture_object(texObj);
if (unlikely(texObj->Target == GL_TEXTURE_BUFFER)) {
*sampler_view = st_get_buffer_sampler_view_from_stobj(st, stObj);
return;
}
retval = st_finalize_texture(ctx, st->pipe, texObj, 0);
if (!retval) {
/* out of mem */

View File

@ -2469,23 +2469,6 @@ st_finalize_texture(struct gl_context *ctx,
stObj->lastLevel = stObj->base._MaxLevel;
}
if (tObj->Target == GL_TEXTURE_BUFFER) {
struct st_buffer_object *st_obj = st_buffer_object(tObj->BufferObject);
if (!st_obj) {
pipe_resource_reference(&stObj->pt, NULL);
st_texture_release_all_sampler_views(st, stObj);
return GL_TRUE;
}
if (st_obj->buffer != stObj->pt) {
pipe_resource_reference(&stObj->pt, st_obj->buffer);
st_texture_release_all_sampler_views(st, stObj);
}
return GL_TRUE;
}
firstImage = st_texture_image_const(stObj->base.Image[cubeMapFace][stObj->base.BaseLevel]);
assert(firstImage);
@ -2923,10 +2906,11 @@ st_NewTextureHandle(struct gl_context *ctx, struct gl_texture_object *texObj,
return 0;
st_convert_sampler(st, texObj, sampObj, &sampler);
view = st_get_texture_sampler_view_from_stobj(st, stObj, sampObj, 0);
} else {
view = st_get_buffer_sampler_view_from_stobj(st, stObj);
}
view = st_get_texture_sampler_view_from_stobj(st, stObj, sampObj, 0);
return pipe->create_texture_handle(pipe, view, &sampler);
}

View File

@ -37,6 +37,7 @@ struct gl_context;
struct gl_texture_object;
struct pipe_context;
struct st_context;
struct st_texture_object;
extern enum pipe_texture_target
gl_target_to_pipe(GLenum target);

View File

@ -38,6 +38,7 @@
#include "st_sampler_view.h"
#include "st_texture.h"
#include "st_format.h"
#include "st_cb_bufferobjects.h"
#include "st_cb_texture.h"
@ -362,43 +363,31 @@ get_sampler_view_format(struct st_context *st,
{
enum pipe_format format;
if (stObj->base.Target == GL_TEXTURE_BUFFER) {
format =
st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat);
}
else {
format =
stObj->surface_based ? stObj->surface_format : stObj->pt->format;
GLenum baseFormat = _mesa_base_tex_image(&stObj->base)->_BaseFormat;
format = stObj->surface_based ? stObj->surface_format : stObj->pt->format;
if (util_format_is_depth_and_stencil(format)) {
if (stObj->base.StencilSampling) {
format = util_format_stencil_only(format);
}
else {
GLenum baseFormat = _mesa_texture_base_format(&stObj->base);
if (baseFormat == GL_STENCIL_INDEX) {
format = util_format_stencil_only(format);
}
}
}
else {
/* If sRGB decoding is off, use the linear format */
if (samp->sRGBDecode == GL_SKIP_DECODE_EXT) {
format = util_format_linear(format);
}
if (baseFormat == GL_DEPTH_COMPONENT ||
baseFormat == GL_DEPTH_STENCIL ||
baseFormat == GL_STENCIL_INDEX) {
if (stObj->base.StencilSampling || baseFormat == GL_STENCIL_INDEX)
format = util_format_stencil_only(format);
/* Use R8_UNORM for video formats */
switch (format) {
case PIPE_FORMAT_NV12:
case PIPE_FORMAT_IYUV:
format = PIPE_FORMAT_R8_UNORM;
break;
default:
break;
}
}
return format;
}
/* If sRGB decoding is off, use the linear format */
if (samp->sRGBDecode == GL_SKIP_DECODE_EXT)
format = util_format_linear(format);
/* Use R8_UNORM for video formats */
switch (format) {
case PIPE_FORMAT_NV12:
case PIPE_FORMAT_IYUV:
format = PIPE_FORMAT_R8_UNORM;
break;
default:
break;
}
return format;
}
@ -414,31 +403,17 @@ st_create_texture_sampler_view_from_stobj(struct st_context *st,
u_sampler_view_default_template(&templ, stObj->pt, format);
if (stObj->pt->target == PIPE_BUFFER) {
unsigned base, size;
base = stObj->base.BufferOffset;
if (base >= stObj->pt->width0)
return NULL;
size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize);
if (!size)
return NULL;
templ.u.buf.offset = base;
templ.u.buf.size = size;
templ.u.tex.first_level = stObj->base.MinLevel + stObj->base.BaseLevel;
templ.u.tex.last_level = last_level(stObj);
assert(templ.u.tex.first_level <= templ.u.tex.last_level);
if (stObj->layer_override) {
templ.u.tex.first_layer = templ.u.tex.last_layer = stObj->layer_override;
} else {
templ.u.tex.first_level = stObj->base.MinLevel + stObj->base.BaseLevel;
templ.u.tex.last_level = last_level(stObj);
assert(templ.u.tex.first_level <= templ.u.tex.last_level);
if (stObj->layer_override) {
templ.u.tex.first_layer = templ.u.tex.last_layer = stObj->layer_override;
} else {
templ.u.tex.first_layer = stObj->base.MinLayer;
templ.u.tex.last_layer = last_layer(stObj);
}
assert(templ.u.tex.first_layer <= templ.u.tex.last_layer);
templ.target = gl_target_to_pipe(stObj->base.Target);
templ.u.tex.first_layer = stObj->base.MinLayer;
templ.u.tex.last_layer = last_layer(stObj);
}
assert(templ.u.tex.first_layer <= templ.u.tex.last_layer);
templ.target = gl_target_to_pipe(stObj->base.Target);
templ.swizzle_r = GET_SWZ(swizzle, 0);
templ.swizzle_g = GET_SWZ(swizzle, 1);
@ -468,26 +443,18 @@ st_get_texture_sampler_view_from_stobj(struct st_context *st,
* what they're supposed to be.
*/
MAYBE_UNUSED struct pipe_sampler_view *view = *sv;
assert(stObj->pt == view->texture);
assert(!check_sampler_swizzle(st, stObj, view, glsl_version));
assert(get_sampler_view_format(st, stObj, samp) == view->format);
assert(gl_target_to_pipe(stObj->base.Target) == view->target);
if (stObj->base.Target == GL_TEXTURE_BUFFER) {
unsigned base = stObj->base.BufferOffset;
MAYBE_UNUSED unsigned size = MIN2(stObj->pt->width0 - base,
(unsigned) stObj->base.BufferSize);
assert(view->u.buf.offset == base);
assert(view->u.buf.size == size);
}
else {
assert(stObj->base.MinLevel + stObj->base.BaseLevel ==
view->u.tex.first_level);
assert(last_level(stObj) == view->u.tex.last_level);
assert(stObj->layer_override || stObj->base.MinLayer == view->u.tex.first_layer);
assert(stObj->layer_override || last_layer(stObj) == view->u.tex.last_layer);
assert(!stObj->layer_override ||
(stObj->layer_override == view->u.tex.first_layer &&
stObj->layer_override == view->u.tex.last_layer));
}
assert(stObj->base.MinLevel + stObj->base.BaseLevel ==
view->u.tex.first_level);
assert(last_level(stObj) == view->u.tex.last_level);
assert(stObj->layer_override || stObj->base.MinLayer == view->u.tex.first_layer);
assert(stObj->layer_override || last_layer(stObj) == view->u.tex.last_layer);
assert(!stObj->layer_override ||
(stObj->layer_override == view->u.tex.first_layer &&
stObj->layer_override == view->u.tex.last_layer));
}
else {
/* create new sampler view */
@ -500,3 +467,64 @@ st_get_texture_sampler_view_from_stobj(struct st_context *st,
return *sv;
}
struct pipe_sampler_view *
st_get_buffer_sampler_view_from_stobj(struct st_context *st,
struct st_texture_object *stObj)
{
struct pipe_sampler_view **sv;
struct st_buffer_object *stBuf =
st_buffer_object(stObj->base.BufferObject);
if (!stBuf || !stBuf->buffer)
return NULL;
sv = st_texture_get_sampler_view(st, stObj);
struct pipe_resource *buf = stBuf->buffer;
struct pipe_sampler_view *view = *sv;
if (view && view->texture == buf) {
/* Debug check: make sure that the sampler view's parameters are
* what they're supposed to be.
*/
assert(st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat)
== view->format);
assert(view->target == PIPE_BUFFER);
unsigned base = stObj->base.BufferOffset;
MAYBE_UNUSED unsigned size = MIN2(buf->width0 - base,
(unsigned) stObj->base.BufferSize);
assert(view->u.buf.offset == base);
assert(view->u.buf.size == size);
} else {
unsigned base = stObj->base.BufferOffset;
if (base >= buf->width0)
return NULL;
unsigned size = buf->width0 - base;
size = MIN2(size, (unsigned)stObj->base.BufferSize);
if (!size)
return NULL;
/* Create a new sampler view. There is no need to clear the entire
* structure (consider CPU overhead).
*/
struct pipe_sampler_view templ;
templ.format =
st_mesa_format_to_pipe_format(st, stObj->base._BufferObjectFormat);
templ.target = PIPE_BUFFER;
templ.swizzle_r = PIPE_SWIZZLE_X;
templ.swizzle_g = PIPE_SWIZZLE_Y;
templ.swizzle_b = PIPE_SWIZZLE_Z;
templ.swizzle_a = PIPE_SWIZZLE_W;
templ.u.buf.offset = base;
templ.u.buf.size = size;
pipe_sampler_view_reference(sv, NULL);
*sv = st->pipe->create_sampler_view(st->pipe, buf, &templ);
}
return *sv;
}

View File

@ -75,5 +75,8 @@ st_get_texture_sampler_view_from_stobj(struct st_context *st,
const struct gl_sampler_object *samp,
unsigned glsl_version);
struct pipe_sampler_view *
st_get_buffer_sampler_view_from_stobj(struct st_context *st,
struct st_texture_object *stObj);
#endif /* ST_SAMPLER_VIEW_H */