Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2014 Advanced Micro Devices, Inc.
  4.  * All Rights Reserved.
  5.  *
  6.  * Permission is hereby granted, free of charge, to any person obtaining a
  7.  * copy of this software and associated documentation files (the
  8.  * "Software"), to deal in the Software without restriction, including
  9.  * without limitation the rights to use, copy, modify, merge, publish,
  10.  * distribute, sub license, and/or sell copies of the Software, and to
  11.  * permit persons to whom the Software is furnished to do so, subject to
  12.  * the following conditions:
  13.  *
  14.  * The above copyright notice and this permission notice (including the
  15.  * next paragraph) shall be included in all copies or substantial portions
  16.  * of the Software.
  17.  *
  18.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  19.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
  21.  * IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR
  22.  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  23.  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  24.  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25.  *
  26.  **************************************************************************/
  27.  
  28. #include "util/u_tests.h"
  29.  
  30. #include "util/u_draw_quad.h"
  31. #include "util/u_format.h"
  32. #include "util/u_inlines.h"
  33. #include "util/u_memory.h"
  34. #include "util/u_simple_shaders.h"
  35. #include "util/u_surface.h"
  36. #include "util/u_string.h"
  37. #include "util/u_tile.h"
  38. #include "tgsi/tgsi_strings.h"
  39. #include "tgsi/tgsi_text.h"
  40. #include "cso_cache/cso_context.h"
  41. #include <stdio.h>
  42.  
  43. #define TOLERANCE 0.01
  44.  
  45. static struct pipe_resource *
  46. util_create_texture2d(struct pipe_screen *screen, unsigned width,
  47.                       unsigned height, enum pipe_format format)
  48. {
  49.    struct pipe_resource templ = {{0}};
  50.  
  51.    templ.target = PIPE_TEXTURE_2D;
  52.    templ.width0 = width;
  53.    templ.height0 = height;
  54.    templ.depth0 = 1;
  55.    templ.array_size = 1;
  56.    templ.format = format;
  57.    templ.usage = PIPE_USAGE_DEFAULT;
  58.    templ.bind = PIPE_BIND_SAMPLER_VIEW |
  59.                 (util_format_is_depth_or_stencil(format) ?
  60.                     PIPE_BIND_DEPTH_STENCIL : PIPE_BIND_RENDER_TARGET);
  61.  
  62.    return screen->resource_create(screen, &templ);
  63. }
  64.  
  65. static void
  66. util_set_framebuffer_cb0(struct cso_context *cso, struct pipe_context *ctx,
  67.                          struct pipe_resource *tex)
  68. {
  69.    struct pipe_surface templ = {{0}}, *surf;
  70.    struct pipe_framebuffer_state fb = {0};
  71.  
  72.    templ.format = tex->format;
  73.    surf = ctx->create_surface(ctx, tex, &templ);
  74.  
  75.    fb.width = tex->width0;
  76.    fb.height = tex->height0;
  77.    fb.cbufs[0] = surf;
  78.    fb.nr_cbufs = 1;
  79.  
  80.    cso_set_framebuffer(cso, &fb);
  81.    pipe_surface_reference(&surf, NULL);
  82. }
  83.  
  84. static void
  85. util_set_blend_normal(struct cso_context *cso)
  86. {
  87.    struct pipe_blend_state blend = {0};
  88.  
  89.    blend.rt[0].colormask = PIPE_MASK_RGBA;
  90.    cso_set_blend(cso, &blend);
  91. }
  92.  
  93. static void
  94. util_set_dsa_disable(struct cso_context *cso)
  95. {
  96.    struct pipe_depth_stencil_alpha_state dsa = {{0}};
  97.  
  98.    cso_set_depth_stencil_alpha(cso, &dsa);
  99. }
  100.  
  101. static void
  102. util_set_rasterizer_normal(struct cso_context *cso)
  103. {
  104.    struct pipe_rasterizer_state rs = {0};
  105.  
  106.    rs.half_pixel_center = 1;
  107.    rs.bottom_edge_rule = 1;
  108.    rs.depth_clip = 1;
  109.  
  110.    cso_set_rasterizer(cso, &rs);
  111. }
  112.  
  113. static void
  114. util_set_max_viewport(struct cso_context *cso, struct pipe_resource *tex)
  115. {
  116.    struct pipe_viewport_state viewport;
  117.  
  118.    viewport.scale[0] = 0.5f * tex->width0;
  119.    viewport.scale[1] = 0.5f * tex->height0;
  120.    viewport.scale[2] = 1.0f;
  121.    viewport.translate[0] = 0.5f * tex->width0;
  122.    viewport.translate[1] = 0.5f * tex->height0;
  123.    viewport.translate[2] = 0.0f;
  124.  
  125.    cso_set_viewport(cso, &viewport);
  126. }
  127.  
  128. static void
  129. util_set_interleaved_vertex_elements(struct cso_context *cso,
  130.                                      unsigned num_elements)
  131. {
  132.    int i;
  133.    struct pipe_vertex_element *velem =
  134.       calloc(1, num_elements * sizeof(struct pipe_vertex_element));
  135.  
  136.    for (i = 0; i < num_elements; i++) {
  137.       velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
  138.       velem[i].src_offset = i * 16;
  139.    }
  140.  
  141.    cso_set_vertex_elements(cso, num_elements, velem);
  142.    free(velem);
  143. }
  144.  
  145. static void *
  146. util_set_passthrough_vertex_shader(struct cso_context *cso,
  147.                                    struct pipe_context *ctx,
  148.                                    bool window_space)
  149. {
  150.    static const uint vs_attribs[] = {
  151.       TGSI_SEMANTIC_POSITION,
  152.       TGSI_SEMANTIC_GENERIC
  153.    };
  154.    static const uint vs_indices[] = {0, 0};
  155.    void *vs;
  156.  
  157.    vs = util_make_vertex_passthrough_shader(ctx, 2, vs_attribs, vs_indices,
  158.                                             window_space);
  159.    cso_set_vertex_shader_handle(cso, vs);
  160.    return vs;
  161. }
  162.  
  163. static void
  164. util_set_common_states_and_clear(struct cso_context *cso, struct pipe_context *ctx,
  165.                                  struct pipe_resource *cb)
  166. {
  167.    static const float clear_color[] = {0.1, 0.1, 0.1, 0.1};
  168.  
  169.    util_set_framebuffer_cb0(cso, ctx, cb);
  170.    util_set_blend_normal(cso);
  171.    util_set_dsa_disable(cso);
  172.    util_set_rasterizer_normal(cso);
  173.    util_set_max_viewport(cso, cb);
  174.  
  175.    ctx->clear(ctx, PIPE_CLEAR_COLOR0, (void*)clear_color, 0, 0);
  176. }
  177.  
  178. static void
  179. util_draw_fullscreen_quad(struct cso_context *cso)
  180. {
  181.    static float vertices[] = {
  182.      -1, -1, 0, 1,   0, 0, 0, 0,
  183.      -1,  1, 0, 1,   0, 1, 0, 0,
  184.       1,  1, 0, 1,   1, 1, 0, 0,
  185.       1, -1, 0, 1,   1, 0, 0, 0
  186.    };
  187.    util_set_interleaved_vertex_elements(cso, 2);
  188.    util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2);
  189. }
  190.  
  191. /**
  192.  * Probe and test if the rectangle contains the expected color.
  193.  *
  194.  * If "num_expected_colors" > 1, at least one expected color must match
  195.  * the probed color. "expected" should be an array of 4*num_expected_colors
  196.  * floats.
  197.  */
  198. static bool
  199. util_probe_rect_rgba_multi(struct pipe_context *ctx, struct pipe_resource *tex,
  200.                            unsigned offx, unsigned offy, unsigned w,
  201.                            unsigned h,
  202.                            const float *expected,
  203.                            unsigned num_expected_colors)
  204. {
  205.    struct pipe_transfer *transfer;
  206.    void *map;
  207.    float *pixels = malloc(w * h * 4 * sizeof(float));
  208.    int x,y,e,c;
  209.    bool pass = true;
  210.  
  211.    map = pipe_transfer_map(ctx, tex, 0, 0, PIPE_TRANSFER_READ,
  212.                            offx, offy, w, h, &transfer);
  213.    pipe_get_tile_rgba(transfer, map, 0, 0, w, h, pixels);
  214.    pipe_transfer_unmap(ctx, transfer);
  215.  
  216.    for (e = 0; e < num_expected_colors; e++) {
  217.       for (y = 0; y < h; y++) {
  218.          for (x = 0; x < w; x++) {
  219.             float *probe = &pixels[(y*w + x)*4];
  220.  
  221.             for (c = 0; c < 4; c++) {
  222.                if (fabs(probe[c] - expected[e*4+c]) >= TOLERANCE) {
  223.                   if (e < num_expected_colors-1)
  224.                      goto next_color; /* test the next expected color */
  225.  
  226.                   printf("Probe color at (%i,%i),  ", offx+x, offy+y);
  227.                   printf("Expected: %.3f, %.3f, %.3f, %.3f,  ",
  228.                          expected[e*4], expected[e*4+1],
  229.                          expected[e*4+2], expected[e*4+3]);
  230.                   printf("Got: %.3f, %.3f, %.3f, %.3f\n",
  231.                          probe[0], probe[1], probe[2], probe[2]);
  232.                   pass = false;
  233.                   goto done;
  234.                }
  235.             }
  236.          }
  237.       }
  238.       break; /* this color was successful */
  239.  
  240.    next_color:;
  241.    }
  242. done:
  243.  
  244.    free(pixels);
  245.    return pass;
  246. }
  247.  
  248. static bool
  249. util_probe_rect_rgba(struct pipe_context *ctx, struct pipe_resource *tex,
  250.                      unsigned offx, unsigned offy, unsigned w, unsigned h,
  251.                      const float *expected)
  252. {
  253.    return util_probe_rect_rgba_multi(ctx, tex, offx, offy, w, h, expected, 1);
  254. }
  255.  
  256. enum {
  257.    SKIP = -1,
  258.    FAIL = 0, /* also "false" */
  259.    PASS = 1 /* also "true" */
  260. };
  261.  
  262. static void
  263. util_report_result_helper(int status, const char *name, ...)
  264. {
  265.    char buf[256];
  266.    va_list ap;
  267.  
  268.    va_start(ap, name);
  269.    util_vsnprintf(buf, sizeof(buf), name, ap);
  270.    va_end(ap);
  271.  
  272.    printf("Test(%s) = %s\n", buf,
  273.           status == SKIP ? "skip" :
  274.           status == PASS ? "pass" : "fail");
  275. }
  276.  
  277. #define util_report_result(status) util_report_result_helper(status, __func__)
  278.  
  279. /**
  280.  * Test TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION.
  281.  *
  282.  * The viewport state is set as usual, but it should have no effect.
  283.  * Clipping should also be disabled.
  284.  *
  285.  * POSITION.xyz should already be multiplied by 1/w and POSITION.w should
  286.  * contain 1/w. By setting w=0, we can test that POSITION.xyz isn't
  287.  * multiplied by 1/w (otherwise nothing would be rendered).
  288.  *
  289.  * TODO: Whether the value of POSITION.w is correctly interpreted as 1/w
  290.  *       during perspective interpolation is not tested.
  291.  */
  292. static void
  293. tgsi_vs_window_space_position(struct pipe_context *ctx)
  294. {
  295.    struct cso_context *cso;
  296.    struct pipe_resource *cb;
  297.    void *fs, *vs;
  298.    bool pass = true;
  299.    static const float red[] = {1, 0, 0, 1};
  300.  
  301.    if (!ctx->screen->get_param(ctx->screen,
  302.                                PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION)) {
  303.       util_report_result(SKIP);
  304.       return;
  305.    }
  306.  
  307.    cso = cso_create_context(ctx);
  308.    cb = util_create_texture2d(ctx->screen, 256, 256,
  309.                               PIPE_FORMAT_R8G8B8A8_UNORM);
  310.    util_set_common_states_and_clear(cso, ctx, cb);
  311.  
  312.    /* Fragment shader. */
  313.    fs = util_make_fragment_passthrough_shader(ctx, TGSI_SEMANTIC_GENERIC,
  314.                                        TGSI_INTERPOLATE_LINEAR, TRUE);
  315.    cso_set_fragment_shader_handle(cso, fs);
  316.  
  317.    /* Vertex shader. */
  318.    vs = util_set_passthrough_vertex_shader(cso, ctx, true);
  319.  
  320.    /* Draw. */
  321.    {
  322.       static float vertices[] = {
  323.           0,   0, 0, 0,   1,  0, 0, 1,
  324.           0, 256, 0, 0,   1,  0, 0, 1,
  325.         256, 256, 0, 0,   1,  0, 0, 1,
  326.         256,   0, 0, 0,   1,  0, 0, 1,
  327.       };
  328.       util_set_interleaved_vertex_elements(cso, 2);
  329.       util_draw_user_vertex_buffer(cso, vertices, PIPE_PRIM_QUADS, 4, 2);
  330.    }
  331.  
  332.    /* Probe pixels. */
  333.    pass = pass && util_probe_rect_rgba(ctx, cb, 0, 0,
  334.                                        cb->width0, cb->height0, red);
  335.  
  336.    /* Cleanup. */
  337.    cso_destroy_context(cso);
  338.    ctx->delete_vs_state(ctx, vs);
  339.    ctx->delete_fs_state(ctx, fs);
  340.    pipe_resource_reference(&cb, NULL);
  341.  
  342.    util_report_result(pass);
  343. }
  344.  
  345. static void
  346. null_sampler_view(struct pipe_context *ctx, unsigned tgsi_tex_target)
  347. {
  348.    struct cso_context *cso;
  349.    struct pipe_resource *cb;
  350.    void *fs, *vs;
  351.    bool pass = true;
  352.    /* 2 expected colors: */
  353.    static const float expected_tex[] = {0, 0, 0, 1,
  354.                                         0, 0, 0, 0};
  355.    static const float expected_buf[] = {0, 0, 0, 0};
  356.    const float *expected = tgsi_tex_target == TGSI_TEXTURE_BUFFER ?
  357.                               expected_buf : expected_tex;
  358.    unsigned num_expected = tgsi_tex_target == TGSI_TEXTURE_BUFFER ? 1 : 2;
  359.  
  360.    if (tgsi_tex_target == TGSI_TEXTURE_BUFFER &&
  361.        !ctx->screen->get_param(ctx->screen, PIPE_CAP_TEXTURE_BUFFER_OBJECTS)) {
  362.       util_report_result_helper(SKIP, "%s: %s", __func__,
  363.                                 tgsi_texture_names[tgsi_tex_target]);
  364.       return;
  365.    }
  366.  
  367.    cso = cso_create_context(ctx);
  368.    cb = util_create_texture2d(ctx->screen, 256, 256,
  369.                               PIPE_FORMAT_R8G8B8A8_UNORM);
  370.    util_set_common_states_and_clear(cso, ctx, cb);
  371.  
  372.    ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, NULL);
  373.  
  374.    /* Fragment shader. */
  375.    fs = util_make_fragment_tex_shader(ctx, tgsi_tex_target,
  376.                                       TGSI_INTERPOLATE_LINEAR);
  377.    cso_set_fragment_shader_handle(cso, fs);
  378.  
  379.    /* Vertex shader. */
  380.    vs = util_set_passthrough_vertex_shader(cso, ctx, false);
  381.    util_draw_fullscreen_quad(cso);
  382.  
  383.    /* Probe pixels. */
  384.    pass = pass && util_probe_rect_rgba_multi(ctx, cb, 0, 0,
  385.                                   cb->width0, cb->height0, expected,
  386.                                   num_expected);
  387.  
  388.    /* Cleanup. */
  389.    cso_destroy_context(cso);
  390.    ctx->delete_vs_state(ctx, vs);
  391.    ctx->delete_fs_state(ctx, fs);
  392.    pipe_resource_reference(&cb, NULL);
  393.  
  394.    util_report_result_helper(pass, "%s: %s", __func__,
  395.                              tgsi_texture_names[tgsi_tex_target]);
  396. }
  397.  
  398. static void
  399. null_constant_buffer(struct pipe_context *ctx)
  400. {
  401.    struct cso_context *cso;
  402.    struct pipe_resource *cb;
  403.    void *fs, *vs;
  404.    bool pass = true;
  405.    static const float zero[] = {0, 0, 0, 0};
  406.  
  407.    cso = cso_create_context(ctx);
  408.    cb = util_create_texture2d(ctx->screen, 256, 256,
  409.                               PIPE_FORMAT_R8G8B8A8_UNORM);
  410.    util_set_common_states_and_clear(cso, ctx, cb);
  411.  
  412.    ctx->set_constant_buffer(ctx, PIPE_SHADER_FRAGMENT, 0, NULL);
  413.  
  414.    /* Fragment shader. */
  415.    {
  416.       static const char *text = /* I don't like ureg... */
  417.             "FRAG\n"
  418.             "DCL CONST[0]\n"
  419.             "DCL OUT[0], COLOR\n"
  420.  
  421.             "MOV OUT[0], CONST[0]\n"
  422.             "END\n";
  423.       struct tgsi_token tokens[1000];
  424.       struct pipe_shader_state state = {tokens};
  425.  
  426.       if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
  427.          puts("Can't compile a fragment shader.");
  428.          util_report_result(FAIL);
  429.          return;
  430.       }
  431.       fs = ctx->create_fs_state(ctx, &state);
  432.       cso_set_fragment_shader_handle(cso, fs);
  433.    }
  434.  
  435.    /* Vertex shader. */
  436.    vs = util_set_passthrough_vertex_shader(cso, ctx, false);
  437.    util_draw_fullscreen_quad(cso);
  438.  
  439.    /* Probe pixels. */
  440.    pass = pass && util_probe_rect_rgba(ctx, cb, 0, 0, cb->width0,
  441.                                        cb->height0, zero);
  442.  
  443.    /* Cleanup. */
  444.    cso_destroy_context(cso);
  445.    ctx->delete_vs_state(ctx, vs);
  446.    ctx->delete_fs_state(ctx, fs);
  447.    pipe_resource_reference(&cb, NULL);
  448.  
  449.    util_report_result(pass);
  450. }
  451.  
  452. /**
  453.  * Run all tests. This should be run with a clean context after
  454.  * context_create.
  455.  */
  456. void
  457. util_run_tests(struct pipe_screen *screen)
  458. {
  459.    struct pipe_context *ctx = screen->context_create(screen, NULL);
  460.  
  461.    tgsi_vs_window_space_position(ctx);
  462.    null_sampler_view(ctx, TGSI_TEXTURE_2D);
  463.    null_sampler_view(ctx, TGSI_TEXTURE_BUFFER);
  464.    null_constant_buffer(ctx);
  465.  
  466.    ctx->destroy(ctx);
  467.  
  468.    puts("Done. Exiting..");
  469.    exit(0);
  470. }
  471.