[Mesa-dev] [PATCH 19/24] st/mesa: add an entirely separate codepath for setting up buffer views
Marek Olšák
maraeo at gmail.com
Mon Jun 12 18:18:50 UTC 2017
From: Marek Olšák <marek.olsak at amd.com>
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.
---
src/mesa/state_tracker/st_atom_image.c | 29 ++++--
src/mesa/state_tracker/st_atom_texture.c | 5 +
src/mesa/state_tracker/st_cb_texture.c | 17 ---
src/mesa/state_tracker/st_cb_texture.h | 1 +
src/mesa/state_tracker/st_sampler_view.c | 174 ++++++++++++++++++-------------
src/mesa/state_tracker/st_sampler_view.h | 3 +
6 files changed, 131 insertions(+), 98 deletions(-)
diff --git a/src/mesa/state_tracker/st_atom_image.c b/src/mesa/state_tracker/st_atom_image.c
index 381eca1..eb873a6 100644
--- a/src/mesa/state_tracker/st_atom_image.c
+++ b/src/mesa/state_tracker/st_atom_image.c
@@ -29,64 +29,80 @@
#include "program/prog_parameter.h"
#include "program/prog_print.h"
#include "compiler/glsl/ir_uniform.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#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"
#include "st_context.h"
#include "st_atom.h"
#include "st_program.h"
#include "st_format.h"
/**
* Convert a gl_image_unit object to a pipe_image_view object.
*/
void
st_convert_image(const struct st_context *st, const struct gl_image_unit *u,
struct pipe_image_view *img)
{
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) {
case GL_READ_ONLY:
img->access = PIPE_IMAGE_ACCESS_READ;
break;
case GL_WRITE_ONLY:
img->access = PIPE_IMAGE_ACCESS_WRITE;
break;
case GL_READ_WRITE:
img->access = PIPE_IMAGE_ACCESS_READ_WRITE;
break;
default:
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;
+ if (!stbuf || !stbuf->buffer) {
+ memset(img, 0, sizeof(*img));
+ return;
+ }
+ struct pipe_resource *buf = stbuf->buffer;
+
base = stObj->base.BufferOffset;
- assert(base < stObj->pt->width0);
- size = MIN2(stObj->pt->width0 - base, (unsigned)stObj->base.BufferSize);
+ 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) {
img->u.tex.first_layer = 0;
img->u.tex.last_layer = u_minify(stObj->pt->depth0, img->u.tex.level) - 1;
} else {
img->u.tex.first_layer = u->_Layer;
img->u.tex.last_layer = u->_Layer;
}
} else {
@@ -111,26 +127,23 @@ st_bind_images(struct st_context *st, struct gl_program *prog,
struct gl_program_constants *c;
if (!prog || !st->pipe->set_shader_images)
return;
c = &st->ctx->Const.Program[prog->info.stage];
for (i = 0; i < prog->info.num_images; i++) {
struct gl_image_unit *u =
&st->ctx->ImageUnits[prog->sh.ImageUnits[i]];
- struct st_texture_object *stObj = st_texture_object(u->TexObj);
struct pipe_image_view *img = &images[i];
- 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));
continue;
}
st_convert_image(st, u, img);
}
cso_set_shader_images(st->cso_context, shader_type, 0,
prog->info.num_images, images);
/* clear out any stale shader images */
if (prog->info.num_images < c->MaxImageUniforms)
diff --git a/src/mesa/state_tracker/st_atom_texture.c b/src/mesa/state_tracker/st_atom_texture.c
index ddde445..f696f0e 100644
--- a/src/mesa/state_tracker/st_atom_texture.c
+++ b/src/mesa/state_tracker/st_atom_texture.c
@@ -63,20 +63,25 @@ update_single_texture(struct st_context *st,
struct st_texture_object *stObj;
GLboolean retval;
samp = _mesa_get_samplerobj(ctx, texUnit);
texObj = ctx->Texture.Unit[texUnit]._Current;
assert(texObj);
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 */
*sampler_view = NULL;
return;
}
/* Check a few pieces of state outside the texture object to see if we
* need to force revalidation.
*/
diff --git a/src/mesa/state_tracker/st_cb_texture.c b/src/mesa/state_tracker/st_cb_texture.c
index 443bb7b..540519f 100644
--- a/src/mesa/state_tracker/st_cb_texture.c
+++ b/src/mesa/state_tracker/st_cb_texture.c
@@ -2462,37 +2462,20 @@ st_finalize_texture(struct gl_context *ctx,
* incomplete. In that case, we'll have set stObj->lastLevel before
* we get here.
*/
if (stObj->base.Sampler.MinFilter == GL_LINEAR ||
stObj->base.Sampler.MinFilter == GL_NEAREST)
stObj->lastLevel = stObj->base.BaseLevel;
else
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);
/* Skip the loop over images in the common case of no images having
* changed. But if the GL_BASE_LEVEL or GL_MAX_LEVEL change to something we
* haven't looked at, then we do need to look at those new images.
*/
if (!stObj->needs_validation &&
stObj->base.BaseLevel >= stObj->validated_first_level &&
stObj->lastLevel <= stObj->validated_last_level) {
diff --git a/src/mesa/state_tracker/st_cb_texture.h b/src/mesa/state_tracker/st_cb_texture.h
index f647b16..ed6ed16 100644
--- a/src/mesa/state_tracker/st_cb_texture.h
+++ b/src/mesa/state_tracker/st_cb_texture.h
@@ -30,20 +30,21 @@
#define ST_CB_TEXTURE_H
#include "main/glheader.h"
struct dd_function_table;
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);
unsigned
st_get_blit_mask(GLenum srcFormat, GLenum dstFormat);
extern GLboolean
st_finalize_texture(struct gl_context *ctx,
struct pipe_context *pipe,
diff --git a/src/mesa/state_tracker/st_sampler_view.c b/src/mesa/state_tracker/st_sampler_view.c
index c78a987..f0cf9cb 100644
--- a/src/mesa/state_tracker/st_sampler_view.c
+++ b/src/mesa/state_tracker/st_sampler_view.c
@@ -31,20 +31,21 @@
#include "main/macros.h"
#include "main/mtypes.h"
#include "main/teximage.h"
#include "main/texobj.h"
#include "program/prog_instruction.h"
#include "st_context.h"
#include "st_sampler_view.h"
#include "st_texture.h"
#include "st_format.h"
+#include "st_cb_bufferobjects.h"
#include "st_cb_texture.h"
/**
* Try to find a matching sampler view for the given context.
* If none is found an empty slot is initialized with a
* template and returned instead.
*/
static struct pipe_sampler_view **
st_texture_get_sampler_view(struct st_context *st,
@@ -355,97 +356,71 @@ last_layer(const struct st_texture_object *stObj)
/**
* Determine the format for the texture sampler view.
*/
static enum pipe_format
get_sampler_view_format(struct st_context *st,
const struct st_texture_object *stObj,
const struct gl_sampler_object *samp)
{
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;
}
static struct pipe_sampler_view *
st_create_texture_sampler_view_from_stobj(struct st_context *st,
struct st_texture_object *stObj,
enum pipe_format format,
unsigned glsl_version)
{
struct pipe_sampler_view templ;
unsigned swizzle = get_texture_format_swizzle(st, stObj, glsl_version);
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);
templ.swizzle_b = GET_SWZ(swizzle, 2);
templ.swizzle_a = GET_SWZ(swizzle, 3);
return st->pipe->create_sampler_view(st->pipe, stObj->pt, &templ);
}
@@ -461,42 +436,95 @@ st_get_texture_sampler_view_from_stobj(struct st_context *st,
return NULL;
}
sv = st_texture_get_sampler_view(st, stObj);
if (*sv) {
/* Debug check: make sure that the sampler view's parameters are
* 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 */
enum pipe_format format = get_sampler_view_format(st, stObj, samp);
*sv = st_create_texture_sampler_view_from_stobj(st, stObj,
format, glsl_version);
}
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;
+}
diff --git a/src/mesa/state_tracker/st_sampler_view.h b/src/mesa/state_tracker/st_sampler_view.h
index 6825ceb..b08ca4a 100644
--- a/src/mesa/state_tracker/st_sampler_view.h
+++ b/src/mesa/state_tracker/st_sampler_view.h
@@ -68,12 +68,15 @@ st_texture_release_all_sampler_views(struct st_context *st,
void
st_texture_free_sampler_views(struct st_texture_object *stObj);
struct pipe_sampler_view *
st_get_texture_sampler_view_from_stobj(struct st_context *st,
struct st_texture_object *stObj,
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 */
--
2.7.4
More information about the mesa-dev
mailing list