Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2013 Intel Corporation
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21.  * DEALINGS IN THE SOFTWARE.
  22.  */
  23. #include <gtest/gtest.h>
  24. #include "main/compiler.h"
  25. #include "main/mtypes.h"
  26. #include "main/macros.h"
  27. #include "util/ralloc.h"
  28. #include "ir.h"
  29. #include "program/hash_table.h"
  30.  
  31. /**
  32.  * \file varyings_test.cpp
  33.  *
  34.  * Test various aspects of linking shader stage inputs and outputs.
  35.  */
  36.  
  37. namespace linker {
  38. bool
  39. populate_consumer_input_sets(void *mem_ctx, exec_list *ir,
  40.                              hash_table *consumer_inputs,
  41.                              hash_table *consumer_interface_inputs,
  42.                              ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX]);
  43.  
  44. ir_variable *
  45. get_matching_input(void *mem_ctx,
  46.                    const ir_variable *output_var,
  47.                    hash_table *consumer_inputs,
  48.                    hash_table *consumer_interface_inputs,
  49.                    ir_variable *consumer_inputs_with_locations[VARYING_SLOT_MAX]);
  50. }
  51.  
  52. class link_varyings : public ::testing::Test {
  53. public:
  54.    link_varyings();
  55.  
  56.    virtual void SetUp();
  57.    virtual void TearDown();
  58.  
  59.    char *interface_field_name(const glsl_type *iface, unsigned field = 0)
  60.    {
  61.       return ralloc_asprintf(mem_ctx,
  62.                              "%s.%s",
  63.                              iface->name,
  64.                              iface->fields.structure[field].name);
  65.    }
  66.  
  67.    void *mem_ctx;
  68.    exec_list ir;
  69.    hash_table *consumer_inputs;
  70.    hash_table *consumer_interface_inputs;
  71.  
  72.    const glsl_type *simple_interface;
  73.    ir_variable *junk[VARYING_SLOT_MAX];
  74. };
  75.  
  76. link_varyings::link_varyings()
  77. {
  78.    static const glsl_struct_field f[] = {
  79.       {
  80.          glsl_type::vec(4),
  81.          "v",
  82.          false,
  83.          0,
  84.          0,
  85.          0,
  86.          0
  87.       }
  88.    };
  89.  
  90.    this->simple_interface =
  91.       glsl_type::get_interface_instance(f,
  92.                                         ARRAY_SIZE(f),
  93.                                         GLSL_INTERFACE_PACKING_STD140,
  94.                                         "simple_interface");
  95. }
  96.  
  97. void
  98. link_varyings::SetUp()
  99. {
  100.    this->mem_ctx = ralloc_context(NULL);
  101.    this->ir.make_empty();
  102.  
  103.    this->consumer_inputs
  104.       = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
  105.  
  106.    this->consumer_interface_inputs
  107.       = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
  108. }
  109.  
  110. void
  111. link_varyings::TearDown()
  112. {
  113.    ralloc_free(this->mem_ctx);
  114.    this->mem_ctx = NULL;
  115.  
  116.    hash_table_dtor(this->consumer_inputs);
  117.    this->consumer_inputs = NULL;
  118.    hash_table_dtor(this->consumer_interface_inputs);
  119.    this->consumer_interface_inputs = NULL;
  120. }
  121.  
  122. /**
  123.  * Hash table callback function that counts the elements in the table
  124.  *
  125.  * \sa num_elements
  126.  */
  127. static void
  128. ht_count_callback(const void *, void *, void *closure)
  129. {
  130.    unsigned int *counter = (unsigned int *) closure;
  131.  
  132.    (*counter)++;
  133. }
  134.  
  135. /**
  136.  * Helper function to count the number of elements in a hash table.
  137.  */
  138. static unsigned
  139. num_elements(hash_table *ht)
  140. {
  141.    unsigned int counter = 0;
  142.  
  143.    hash_table_call_foreach(ht, ht_count_callback, (void *) &counter);
  144.  
  145.    return counter;
  146. }
  147.  
  148. /**
  149.  * Helper function to determine whether a hash table is empty.
  150.  */
  151. static bool
  152. is_empty(hash_table *ht)
  153. {
  154.    return num_elements(ht) == 0;
  155. }
  156.  
  157. TEST_F(link_varyings, single_simple_input)
  158. {
  159.    ir_variable *const v =
  160.       new(mem_ctx) ir_variable(glsl_type::vec(4),
  161.                                "a",
  162.                                ir_var_shader_in);
  163.  
  164.  
  165.    ir.push_tail(v);
  166.  
  167.    ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
  168.                                                     &ir,
  169.                                                     consumer_inputs,
  170.                                                     consumer_interface_inputs,
  171.                                                     junk));
  172.  
  173.    EXPECT_EQ((void *) v, hash_table_find(consumer_inputs, "a"));
  174.    EXPECT_EQ(1u, num_elements(consumer_inputs));
  175.    EXPECT_TRUE(is_empty(consumer_interface_inputs));
  176. }
  177.  
  178. TEST_F(link_varyings, gl_ClipDistance)
  179. {
  180.    const glsl_type *const array_8_of_float =
  181.       glsl_type::get_array_instance(glsl_type::vec(1), 8);
  182.  
  183.    ir_variable *const clipdistance =
  184.       new(mem_ctx) ir_variable(array_8_of_float,
  185.                                "gl_ClipDistance",
  186.                                ir_var_shader_in);
  187.  
  188.    clipdistance->data.explicit_location = true;
  189.    clipdistance->data.location = VARYING_SLOT_CLIP_DIST0;
  190.    clipdistance->data.explicit_index = 0;
  191.  
  192.    ir.push_tail(clipdistance);
  193.  
  194.    ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
  195.                                                     &ir,
  196.                                                     consumer_inputs,
  197.                                                     consumer_interface_inputs,
  198.                                                     junk));
  199.  
  200.    EXPECT_EQ(clipdistance, junk[VARYING_SLOT_CLIP_DIST0]);
  201.    EXPECT_TRUE(is_empty(consumer_inputs));
  202.    EXPECT_TRUE(is_empty(consumer_interface_inputs));
  203. }
  204.  
  205. TEST_F(link_varyings, single_interface_input)
  206. {
  207.    ir_variable *const v =
  208.       new(mem_ctx) ir_variable(simple_interface->fields.structure[0].type,
  209.                                simple_interface->fields.structure[0].name,
  210.                                ir_var_shader_in);
  211.  
  212.    v->init_interface_type(simple_interface);
  213.  
  214.    ir.push_tail(v);
  215.  
  216.    ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
  217.                                                     &ir,
  218.                                                     consumer_inputs,
  219.                                                     consumer_interface_inputs,
  220.                                                     junk));
  221.    char *const full_name = interface_field_name(simple_interface);
  222.  
  223.    EXPECT_EQ((void *) v, hash_table_find(consumer_interface_inputs, full_name));
  224.    EXPECT_EQ(1u, num_elements(consumer_interface_inputs));
  225.    EXPECT_TRUE(is_empty(consumer_inputs));
  226. }
  227.  
  228. TEST_F(link_varyings, one_interface_and_one_simple_input)
  229. {
  230.    ir_variable *const v =
  231.       new(mem_ctx) ir_variable(glsl_type::vec(4),
  232.                                "a",
  233.                                ir_var_shader_in);
  234.  
  235.  
  236.    ir.push_tail(v);
  237.  
  238.    ir_variable *const iface =
  239.       new(mem_ctx) ir_variable(simple_interface->fields.structure[0].type,
  240.                                simple_interface->fields.structure[0].name,
  241.                                ir_var_shader_in);
  242.  
  243.    iface->init_interface_type(simple_interface);
  244.  
  245.    ir.push_tail(iface);
  246.  
  247.    ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
  248.                                                     &ir,
  249.                                                     consumer_inputs,
  250.                                                     consumer_interface_inputs,
  251.                                                     junk));
  252.  
  253.    char *const iface_field_name = interface_field_name(simple_interface);
  254.  
  255.    EXPECT_EQ((void *) iface, hash_table_find(consumer_interface_inputs,
  256.                                              iface_field_name));
  257.    EXPECT_EQ(1u, num_elements(consumer_interface_inputs));
  258.  
  259.    EXPECT_EQ((void *) v, hash_table_find(consumer_inputs, "a"));
  260.    EXPECT_EQ(1u, num_elements(consumer_inputs));
  261. }
  262.  
  263. TEST_F(link_varyings, invalid_interface_input)
  264. {
  265.    ir_variable *const v =
  266.       new(mem_ctx) ir_variable(simple_interface,
  267.                                "named_interface",
  268.                                ir_var_shader_in);
  269.  
  270.    ASSERT_EQ(simple_interface, v->get_interface_type());
  271.  
  272.    ir.push_tail(v);
  273.  
  274.    EXPECT_FALSE(linker::populate_consumer_input_sets(mem_ctx,
  275.                                                     &ir,
  276.                                                     consumer_inputs,
  277.                                                      consumer_interface_inputs,
  278.                                                      junk));
  279. }
  280.  
  281. TEST_F(link_varyings, interface_field_doesnt_match_noninterface)
  282. {
  283.    char *const iface_field_name = interface_field_name(simple_interface);
  284.  
  285.    /* The input shader has a single input variable name "a.v"
  286.     */
  287.    ir_variable *const in_v =
  288.       new(mem_ctx) ir_variable(glsl_type::vec(4),
  289.                                iface_field_name,
  290.                                ir_var_shader_in);
  291.  
  292.    ir.push_tail(in_v);
  293.  
  294.    ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
  295.                                                     &ir,
  296.                                                     consumer_inputs,
  297.                                                     consumer_interface_inputs,
  298.                                                     junk));
  299.  
  300.    /* Create an output variable, "v", that is part of an interface block named
  301.     * "a".  They should not match.
  302.     */
  303.    ir_variable *const out_v =
  304.       new(mem_ctx) ir_variable(simple_interface->fields.structure[0].type,
  305.                                simple_interface->fields.structure[0].name,
  306.                                ir_var_shader_in);
  307.  
  308.    out_v->init_interface_type(simple_interface);
  309.  
  310.    ir_variable *const match =
  311.       linker::get_matching_input(mem_ctx,
  312.                                  out_v,
  313.                                  consumer_inputs,
  314.                                  consumer_interface_inputs,
  315.                                  junk);
  316.  
  317.    EXPECT_EQ(NULL, match);
  318. }
  319.  
  320. TEST_F(link_varyings, interface_field_doesnt_match_noninterface_vice_versa)
  321. {
  322.    char *const iface_field_name = interface_field_name(simple_interface);
  323.  
  324.    /* In input shader has a single variable, "v", that is part of an interface
  325.     * block named "a".
  326.     */
  327.    ir_variable *const in_v =
  328.       new(mem_ctx) ir_variable(simple_interface->fields.structure[0].type,
  329.                                simple_interface->fields.structure[0].name,
  330.                                ir_var_shader_in);
  331.  
  332.    in_v->init_interface_type(simple_interface);
  333.  
  334.    ir.push_tail(in_v);
  335.  
  336.    ASSERT_TRUE(linker::populate_consumer_input_sets(mem_ctx,
  337.                                                     &ir,
  338.                                                     consumer_inputs,
  339.                                                     consumer_interface_inputs,
  340.                                                     junk));
  341.  
  342.    /* Create an output variable "a.v".  They should not match.
  343.     */
  344.    ir_variable *const out_v =
  345.       new(mem_ctx) ir_variable(glsl_type::vec(4),
  346.                                iface_field_name,
  347.                                ir_var_shader_out);
  348.  
  349.    ir_variable *const match =
  350.       linker::get_matching_input(mem_ctx,
  351.                                  out_v,
  352.                                  consumer_inputs,
  353.                                  consumer_interface_inputs,
  354.                                  junk);
  355.  
  356.    EXPECT_EQ(NULL, match);
  357. }
  358.