st/mesa: add an entirely separate codepath for setting up buffer views
authorMarek Olšák <marek.olsak@amd.com>
Sun, 11 Jun 2017 23:00:04 +0000 (01:00 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Wed, 21 Jun 2017 23:51:02 +0000 (01:51 +0200)
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)
src/mesa/state_tracker/st_atom_image.c
src/mesa/state_tracker/st_atom_texture.c
src/mesa/state_tracker/st_cb_texture.c
src/mesa/state_tracker/st_cb_texture.h
src/mesa/state_tracker/st_sampler_view.c
src/mesa/state_tracker/st_sampler_view.h

index 5b914637a2aa220915bec15046585db9890a9a0f..1c4980173f4b260bba18f46f49eba0c567a5ded1 100644 (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;
 
+      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) {
@@ -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;
    }
index 20cc859c9414bff7d420ee94291d7473d0f9dd02..b71b73506f82a07e0879f8e2d9e506d738d00da2 100644 (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 */
index 317bb5324d0f4e5e8d60ebcd7cdbceed960bbb32..9798321d4bc4d848765ab4f1797da2e18f9b50b2 100644 (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);
 }
 
index f647b16c8dcd5f2504991673375689caf403d509..ed6ed16fed896ff093a4b967cba44e1a9a9d2e8a 100644 (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);
index c78a987486e04414293dbf13c490b0ca8963b8b7..f0cf9cb929aa5115490f000963a972edcbf5e7d9 100644 (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;
+}
index 6825cebdf6d01ab1d756a207ee4d0beecaba1f45..b08ca4a70f243787b44f00d45382c4bf42fc7d9f 100644 (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 */