[Mesa-dev,7/9] gallium/u_tests: test a NULL texture sampler view

Submitted by Marek Olšák on Feb. 6, 2015, 7:08 p.m.

Details

Message ID CAAxE2A7cQk4qrY+eo4WCfxgpPY4prG5qZ3daydx7Ovkyj=qceA@mail.gmail.com
State New, archived
Headers show

Not browsing as part of any series.

Commit Message

Marek Olšák Feb. 6, 2015, 7:08 p.m.
The updated patch is attached. It allows both (0,0,0,0) and (0,0,0,1).

Marek

On Mon, Feb 2, 2015 at 5:19 PM, Roland Scheidegger <sroland@vmware.com> wrote:
> Actually, since ARB_robust_buffer_access_behavior, GL requires some
> specfic values, but it's - odd...
> "In all the above cases, if the context was created with robust buffer
> access enabled then instead of undefined behavior the result of the
> texel fetch is zero. For the case of a texel fetch on an incomplete
> texture the result is a texture source color of (0, 0, 0, 1)."
> So, it seems if the texture was incomplete, then 0/0/0/1 has to be
> returned, but if it was unbound, then all zeros is the right answer.
> However, this is only true for textures _fetches_, not ordinary sampling
> (it is described in the vertex shader functionality). I would assume
> this to be the case for ordinary sampling too, but there the spec only
> describes the 0/0/0/1 behavior for incomplete textures, not the behavior
> for unbound ones...
>
> Roland
>
>
>
> Am 02.02.2015 um 16:51 schrieb Roland Scheidegger:
>> I don't think this is really correct. llvmpipe will return all zeros on
>> purpose, because this is d3d10 behavior (and dummy textures cannot work
>> correctly with d3d10). Traditionally both d3d9 and gl state trackers
>> used dummy textures, though I'm unsure what values they required (if
>> any). (For d3d9 though 0/0/0/1 would be somewhat odd since it would be
>> different to what bound textures but unused channels have to return, but
>> d3d9 is sometimes odd so it's possible. Well in that way d3d10 is odd
>> too...)
>> I certainly do agree though with the "don't crash" part.
>>
>> Am 01.02.2015 um 18:15 schrieb Marek Olšák:
>>> From: Marek Olšák <marek.olsak@amd.com>
>>>
>>> It shouldn't crash the GPU and it should return (0, 0, 0, 1).
>>>
>>> This is r300 behavior, so I assume it's also DX9 behavior.
>>> Radeonsi can support this easily.
>>> ---
>>>  src/gallium/auxiliary/util/u_tests.c | 39 ++++++++++++++++++++++++++++++++++++
>>>  1 file changed, 39 insertions(+)
>>>
>>> diff --git a/src/gallium/auxiliary/util/u_tests.c b/src/gallium/auxiliary/util/u_tests.c
>>> index 89ae840..9c8514c 100644
>>> --- a/src/gallium/auxiliary/util/u_tests.c
>>> +++ b/src/gallium/auxiliary/util/u_tests.c
>>> @@ -304,6 +304,44 @@ tgsi_vs_window_space_position(struct pipe_context *ctx)
>>>     util_report_result(pass);
>>>  }
>>>
>>> +static void
>>> +null_sampler_view(struct pipe_context *ctx)
>>> +{
>>> +   struct cso_context *cso;
>>> +   struct pipe_resource *cb;
>>> +   void *fs, *vs;
>>> +   bool pass = true;
>>> +   static const float expected[] = {0, 0, 0, 1};
>>> +
>>> +   cso = cso_create_context(ctx);
>>> +   cb = util_create_texture2d(ctx->screen, 256, 256,
>>> +                              PIPE_FORMAT_R8G8B8A8_UNORM);
>>> +   util_set_common_states_and_clear(cso, ctx, cb);
>>> +
>>> +   ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, NULL);
>>> +
>>> +   /* Fragment shader. */
>>> +   fs = util_make_fragment_tex_shader(ctx, TGSI_TEXTURE_2D,
>>> +                                      TGSI_INTERPOLATE_LINEAR);
>>> +   cso_set_fragment_shader_handle(cso, fs);
>>> +
>>> +   /* Vertex shader. */
>>> +   vs = util_set_passthrough_vertex_shader(cso, ctx, false);
>>> +   util_draw_fullscreen_quad(cso);
>>> +
>>> +   /* Probe pixels. */
>>> +   pass = pass && util_probe_rect_rgba(ctx, cb, 0, 0,
>>> +                                       cb->width0, cb->height0, expected);
>>> +
>>> +   /* Cleanup. */
>>> +   cso_destroy_context(cso);
>>> +   ctx->delete_vs_state(ctx, vs);
>>> +   ctx->delete_fs_state(ctx, fs);
>>> +   pipe_resource_reference(&cb, NULL);
>>> +
>>> +   util_report_result(pass);
>>> +}
>>> +
>>>  /**
>>>   * Run all tests. This should be run with a clean context after
>>>   * context_create.
>>> @@ -314,6 +352,7 @@ util_run_tests(struct pipe_screen *screen)
>>>     struct pipe_context *ctx = screen->context_create(screen, NULL);
>>>
>>>     tgsi_vs_window_space_position(ctx);
>>> +   null_sampler_view(ctx);
>>>
>>>     ctx->destroy(ctx);
>>>
>>>
>>
>> _______________________________________________
>> mesa-dev mailing list
>> mesa-dev@lists.freedesktop.org
>> https://urldefense.proofpoint.com/v2/url?u=http-3A__lists.freedesktop.org_mailman_listinfo_mesa-2Ddev&d=AwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Vjtt0vs_iqoI31UfJxBl7yv9I2FeiaeAYgMTLKRBc_I&m=XOQSHQnIu1sXl65rM4KSLIO5-Zej5H2L9o1CVQNkXvQ&s=uBbprkG3Qul-bWCqNmg5fX-4b9csQamQpx5wWJZmWcU&e=
>>
>

Patch hide | download patch | download mbox

From fda88ae3275eb357d2cc573249501779e33ae68a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= <marek.olsak@amd.com>
Date: Sun, 1 Feb 2015 13:08:53 +0100
Subject: [PATCH] gallium/u_tests: test a NULL texture sampler view

It shouldn't crash the GPU and it should return (0, 0, 0, 1).

This is r300 behavior, so I assume it's also DX9 behavior.
Radeonsi can support this easily.

Reviewed-by: Glenn Kennard <glenn.kennard@gmail.com>
---
 src/gallium/auxiliary/util/u_tests.c | 102 +++++++++++++++++++++++++++++------
 1 file changed, 85 insertions(+), 17 deletions(-)

diff --git a/src/gallium/auxiliary/util/u_tests.c b/src/gallium/auxiliary/util/u_tests.c
index 89ae840..1011153 100644
--- a/src/gallium/auxiliary/util/u_tests.c
+++ b/src/gallium/auxiliary/util/u_tests.c
@@ -184,15 +184,24 @@  util_draw_fullscreen_quad(struct cso_context *cso)
    util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2);
 }
 
+/**
+ * Probe and test if the rectangle contains the expected color.
+ *
+ * If "num_expected_colors" > 1, at least one expected color must match
+ * the probed color. "expected" should be an array of 4*num_expected_colors
+ * floats.
+ */
 static bool
-util_probe_rect_rgba(struct pipe_context *ctx, struct pipe_resource *tex,
-                     unsigned offx, unsigned offy, unsigned w, unsigned h,
-                     const float *expected)
+util_probe_rect_rgba_multi(struct pipe_context *ctx, struct pipe_resource *tex,
+                           unsigned offx, unsigned offy, unsigned w,
+                           unsigned h,
+                           const float *expected,
+                           unsigned num_expected_colors)
 {
    struct pipe_transfer *transfer;
    void *map;
    float *pixels = malloc(w * h * 4 * sizeof(float));
-   int x,y,c;
+   int x,y,e,c;
    bool pass = true;
 
    map = pipe_transfer_map(ctx, tex, 0, 0, PIPE_TRANSFER_READ,
@@ -200,21 +209,31 @@  util_probe_rect_rgba(struct pipe_context *ctx, struct pipe_resource *tex,
    pipe_get_tile_rgba(transfer, map, 0, 0, w, h, pixels);
    pipe_transfer_unmap(ctx, transfer);
 
-   for (y = 0; y < h; y++) {
-      for (x = 0; x < w; x++) {
-         float *probe = &pixels[(y*w + x)*4];
-
-         for (c = 0; c < 4; c++)
-            if (fabs(probe[c] - expected[c]) >= TOLERANCE) {
-               printf("Probe color at (%i,%i),  ", offx+x, offy+y);
-               printf("Expected: %.3f, %.3f, %.3f, %.3f,  ",
-                      expected[0], expected[1], expected[2], expected[3]);
-               printf("Got: %.3f, %.3f, %.3f, %.3f\n",
-                      probe[0], probe[1], probe[2], probe[2]);
-               pass = false;
-               goto done;
+   for (e = 0; e < num_expected_colors; e++) {
+      for (y = 0; y < h; y++) {
+         for (x = 0; x < w; x++) {
+            float *probe = &pixels[(y*w + x)*4];
+
+            for (c = 0; c < 4; c++) {
+               if (fabs(probe[c] - expected[e*4+c]) >= TOLERANCE) {
+                  if (e < num_expected_colors-1)
+                     goto next_color; /* test the next expected color */
+
+                  printf("Probe color at (%i,%i),  ", offx+x, offy+y);
+                  printf("Expected: %.3f, %.3f, %.3f, %.3f,  ",
+                         expected[e*4], expected[e*4+1],
+                         expected[e*4+2], expected[e*4+3]);
+                  printf("Got: %.3f, %.3f, %.3f, %.3f\n",
+                         probe[0], probe[1], probe[2], probe[2]);
+                  pass = false;
+                  goto done;
+               }
             }
+         }
       }
+      break; /* this color was successful */
+
+   next_color:;
    }
 done:
 
@@ -222,6 +241,14 @@  done:
    return pass;
 }
 
+static bool
+util_probe_rect_rgba(struct pipe_context *ctx, struct pipe_resource *tex,
+                     unsigned offx, unsigned offy, unsigned w, unsigned h,
+                     const float *expected)
+{
+   return util_probe_rect_rgba_multi(ctx, tex, offx, offy, w, h, expected, 1);
+}
+
 enum {
    SKIP = -1,
    FAIL = 0, /* also "false" */
@@ -304,6 +331,46 @@  tgsi_vs_window_space_position(struct pipe_context *ctx)
    util_report_result(pass);
 }
 
+static void
+null_sampler_view(struct pipe_context *ctx)
+{
+   struct cso_context *cso;
+   struct pipe_resource *cb;
+   void *fs, *vs;
+   bool pass = true;
+   /* 2 expected colors: */
+   static const float expected[] = {0, 0, 0, 1,
+                                    0, 0, 0, 0};
+
+   cso = cso_create_context(ctx);
+   cb = util_create_texture2d(ctx->screen, 256, 256,
+                              PIPE_FORMAT_R8G8B8A8_UNORM);
+   util_set_common_states_and_clear(cso, ctx, cb);
+
+   ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, NULL);
+
+   /* Fragment shader. */
+   fs = util_make_fragment_tex_shader(ctx, TGSI_TEXTURE_2D,
+                                      TGSI_INTERPOLATE_LINEAR);
+   cso_set_fragment_shader_handle(cso, fs);
+
+   /* Vertex shader. */
+   vs = util_set_passthrough_vertex_shader(cso, ctx, false);
+   util_draw_fullscreen_quad(cso);
+
+   /* Probe pixels. */
+   pass = pass && util_probe_rect_rgba_multi(ctx, cb, 0, 0,
+                                  cb->width0, cb->height0, expected, 2);
+
+   /* Cleanup. */
+   cso_destroy_context(cso);
+   ctx->delete_vs_state(ctx, vs);
+   ctx->delete_fs_state(ctx, fs);
+   pipe_resource_reference(&cb, NULL);
+
+   util_report_result(pass);
+}
+
 /**
  * Run all tests. This should be run with a clean context after
  * context_create.
@@ -314,6 +381,7 @@  util_run_tests(struct pipe_screen *screen)
    struct pipe_context *ctx = screen->context_create(screen, NULL);
 
    tgsi_vs_window_space_position(ctx);
+   null_sampler_view(ctx);
 
    ctx->destroy(ctx);
 
-- 
2.1.0


Comments

Looks good to me. We may need to tighten that up at some point but I
wouldn't know how yet.

Roland

Am 06.02.2015 um 20:08 schrieb Marek Olšák:
> The updated patch is attached. It allows both (0,0,0,0) and (0,0,0,1).
> 
> Marek
> 
> On Mon, Feb 2, 2015 at 5:19 PM, Roland Scheidegger <sroland@vmware.com> wrote:
>> Actually, since ARB_robust_buffer_access_behavior, GL requires some
>> specfic values, but it's - odd...
>> "In all the above cases, if the context was created with robust buffer
>> access enabled then instead of undefined behavior the result of the
>> texel fetch is zero. For the case of a texel fetch on an incomplete
>> texture the result is a texture source color of (0, 0, 0, 1)."
>> So, it seems if the texture was incomplete, then 0/0/0/1 has to be
>> returned, but if it was unbound, then all zeros is the right answer.
>> However, this is only true for textures _fetches_, not ordinary sampling
>> (it is described in the vertex shader functionality). I would assume
>> this to be the case for ordinary sampling too, but there the spec only
>> describes the 0/0/0/1 behavior for incomplete textures, not the behavior
>> for unbound ones...
>>
>> Roland
>>
>>
>>
>> Am 02.02.2015 um 16:51 schrieb Roland Scheidegger:
>>> I don't think this is really correct. llvmpipe will return all zeros on
>>> purpose, because this is d3d10 behavior (and dummy textures cannot work
>>> correctly with d3d10). Traditionally both d3d9 and gl state trackers
>>> used dummy textures, though I'm unsure what values they required (if
>>> any). (For d3d9 though 0/0/0/1 would be somewhat odd since it would be
>>> different to what bound textures but unused channels have to return, but
>>> d3d9 is sometimes odd so it's possible. Well in that way d3d10 is odd
>>> too...)
>>> I certainly do agree though with the "don't crash" part.
>>>
>>> Am 01.02.2015 um 18:15 schrieb Marek Olšák:
>>>> From: Marek Olšák <marek.olsak@amd.com>
>>>>
>>>> It shouldn't crash the GPU and it should return (0, 0, 0, 1).
>>>>
>>>> This is r300 behavior, so I assume it's also DX9 behavior.
>>>> Radeonsi can support this easily.
>>>> ---
>>>>  src/gallium/auxiliary/util/u_tests.c | 39 ++++++++++++++++++++++++++++++++++++
>>>>  1 file changed, 39 insertions(+)
>>>>
>>>> diff --git a/src/gallium/auxiliary/util/u_tests.c b/src/gallium/auxiliary/util/u_tests.c
>>>> index 89ae840..9c8514c 100644
>>>> --- a/src/gallium/auxiliary/util/u_tests.c
>>>> +++ b/src/gallium/auxiliary/util/u_tests.c
>>>> @@ -304,6 +304,44 @@ tgsi_vs_window_space_position(struct pipe_context *ctx)
>>>>     util_report_result(pass);
>>>>  }
>>>>
>>>> +static void
>>>> +null_sampler_view(struct pipe_context *ctx)
>>>> +{
>>>> +   struct cso_context *cso;
>>>> +   struct pipe_resource *cb;
>>>> +   void *fs, *vs;
>>>> +   bool pass = true;
>>>> +   static const float expected[] = {0, 0, 0, 1};
>>>> +
>>>> +   cso = cso_create_context(ctx);
>>>> +   cb = util_create_texture2d(ctx->screen, 256, 256,
>>>> +                              PIPE_FORMAT_R8G8B8A8_UNORM);
>>>> +   util_set_common_states_and_clear(cso, ctx, cb);
>>>> +
>>>> +   ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, NULL);
>>>> +
>>>> +   /* Fragment shader. */
>>>> +   fs = util_make_fragment_tex_shader(ctx, TGSI_TEXTURE_2D,
>>>> +                                      TGSI_INTERPOLATE_LINEAR);
>>>> +   cso_set_fragment_shader_handle(cso, fs);
>>>> +
>>>> +   /* Vertex shader. */
>>>> +   vs = util_set_passthrough_vertex_shader(cso, ctx, false);
>>>> +   util_draw_fullscreen_quad(cso);
>>>> +
>>>> +   /* Probe pixels. */
>>>> +   pass = pass && util_probe_rect_rgba(ctx, cb, 0, 0,
>>>> +                                       cb->width0, cb->height0, expected);
>>>> +
>>>> +   /* Cleanup. */
>>>> +   cso_destroy_context(cso);
>>>> +   ctx->delete_vs_state(ctx, vs);
>>>> +   ctx->delete_fs_state(ctx, fs);
>>>> +   pipe_resource_reference(&cb, NULL);
>>>> +
>>>> +   util_report_result(pass);
>>>> +}
>>>> +
>>>>  /**
>>>>   * Run all tests. This should be run with a clean context after
>>>>   * context_create.
>>>> @@ -314,6 +352,7 @@ util_run_tests(struct pipe_screen *screen)
>>>>     struct pipe_context *ctx = screen->context_create(screen, NULL);
>>>>
>>>>     tgsi_vs_window_space_position(ctx);
>>>> +   null_sampler_view(ctx);
>>>>
>>>>     ctx->destroy(ctx);
>>>>
>>>>
>>>
>>> _______________________________________________
>>> mesa-dev mailing list
>>> mesa-dev@lists.freedesktop.org
>>> https://urldefense.proofpoint.com/v2/url?u=http-3A__lists.freedesktop.org_mailman_listinfo_mesa-2Ddev&d=AwIGaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=Vjtt0vs_iqoI31UfJxBl7yv9I2FeiaeAYgMTLKRBc_I&m=XOQSHQnIu1sXl65rM4KSLIO5-Zej5H2L9o1CVQNkXvQ&s=uBbprkG3Qul-bWCqNmg5fX-4b9csQamQpx5wWJZmWcU&e=
>>>
>>