Fix attribute mapping in enhanced layouts tests for input arrays
authorIago Toral Quiroga <itoral@igalia.com>
Mon, 2 Oct 2017 11:10:20 +0000 (13:10 +0200)
committerAlexander Galazin <Alexander.Galazin@arm.com>
Tue, 31 Oct 2017 09:12:53 +0000 (05:12 -0400)
Some tests in KHR-GL45.enhanced_layouts.varying_* (specifically
KHR-GL45.enhanced_layouts.varying_array_{locations,components})
use input arrays on the vertex shader, however, the code
that uploads vertex data for these (and other test cases) doesn't
account for arrays at all.

Also, the tests in this category that call
TextureTestBase::prepareAttributes to do the VAO setup seem to
provide inconsistent values for variable.m_descriptor.m_offset,
which also leads to incorrect vertex attribute mappings.
Specifically, in the 'component' variants of these tests
(such as varying_array_components), two different input variables
have m_offset = 0, which has the consequence that we end up
computing a vertex buffer with a size that's only big enough to
fit one of the inputs and we overwrite the data for the first
input with the data for the second input when we setup the VAO,
however, the 'location' variants (such as varying_array_locations),
see different offsets for different input variables, which leads to
a different VAO setup.

Components: OpenGL
VK-GL-CTS issue: 739

Affects:
KHR-GL45.enhanced_layouts.varying_*
KHR-GL46.enhanced_layouts.varying_*

Change-Id: Icec238a970e2cd67d6109a25fba980f756abb71b

external/openglcts/modules/gl/gl4cEnhancedLayoutsTests.cpp

index 547ea44..f221203 100644 (file)
@@ -5509,7 +5509,6 @@ bool TestBase::test()
 
        for (GLuint test_case = 0; test_case < n_test_cases; ++test_case)
        {
-
 #endif /* DEBUG_REPEAT_TEST_CASE */
 
                bool case_result = true;
@@ -6731,23 +6730,52 @@ void TextureTestBase::prepareAttributes(GLuint test_case_index, Utils::ProgramIn
                return;
        }
 
+       const Functions& gl = m_context.getRenderContext().getFunctions();
+
        /* Calculate vertex stride and check */
-       GLint vertex_stride = 0;
+       GLint max_inputs;
+       gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_inputs);
+       GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
+
+       /* dvec3/4 vertex inputs use a single location but require 2x16B slots */
+       GLint max_slots = max_inputs * 2;
 
+       /* Compute used slots */
+       std::vector<GLint> slot_sizes;
+       slot_sizes.resize(max_slots);
+       std::fill(slot_sizes.begin(), slot_sizes.end(), 0);
        for (GLuint i = 0; i < si.m_inputs.size(); ++i)
        {
                Utils::Variable& variable = *si.m_inputs[i];
 
                GLint variable_size = static_cast<GLuint>(variable.m_data_size);
 
-               GLint ends_at = variable_size + variable.m_descriptor.m_offset;
+               GLint base_slot = variable.m_descriptor.m_expected_location + variable.m_descriptor.m_offset / 16;
+               GLint ends_at = variable.m_descriptor.m_offset % 16 + variable_size;
 
-               vertex_stride = std::max(vertex_stride, ends_at);
+               GLint array_length = std::max(1u, variable.m_descriptor.m_n_array_elements);
+               for (GLint loc = 0; loc < array_length; loc++) {
+                       GLint slot = base_slot + loc;
+                       slot_sizes[slot] = std::max(slot_sizes[slot], ends_at);
+               }
+       }
+
+       /* Compute the offsets where we need to put vertex buffer data for each slot */
+       std::vector<GLint> slot_offsets;
+       slot_offsets.resize(max_slots);
+       std::fill(slot_offsets.begin(), slot_offsets.end(), -1);
+       GLint buffer_size = 0;
+       for (GLint i = 0; i < max_slots; i++)
+       {
+               if (slot_sizes[i] == 0)
+                       continue;
+               slot_offsets[i] = buffer_size;
+               buffer_size += slot_sizes[i];
        }
 
        /* Prepare buffer data and set up vao */
        std::vector<GLubyte> buffer_data;
-       buffer_data.resize(vertex_stride);
+       buffer_data.resize(buffer_size);
 
        GLubyte* ptr = &buffer_data[0];
 
@@ -6755,13 +6783,19 @@ void TextureTestBase::prepareAttributes(GLuint test_case_index, Utils::ProgramIn
        {
                Utils::Variable& variable = *si.m_inputs[i];
 
-               memcpy(ptr + variable.m_descriptor.m_offset, variable.m_data, variable.m_data_size);
+               GLint base_slot = variable.m_descriptor.m_expected_location + variable.m_descriptor.m_offset / 16;
+               GLint variable_offset = variable.m_descriptor.m_offset % 16;
+               GLint array_length = std::max(1u, variable.m_descriptor.m_n_array_elements);
+               for (GLint loc = 0; loc < array_length; loc++) {
+                       GLint slot = base_slot + loc;
+                       memcpy(ptr + slot_offsets[slot] + variable_offset, variable.m_data, variable.m_data_size);
+               }
 
                if (false == use_component_qualifier)
                {
                        vao.Attribute(variable.m_descriptor.m_expected_location, variable.m_descriptor.m_builtin,
                                                  variable.m_descriptor.m_n_array_elements, variable.m_descriptor.m_normalized,
-                                                 variable.GetStride(), (GLvoid*)(intptr_t)variable.m_descriptor.m_offset);
+                                                 variable.GetStride(), (GLvoid*)(intptr_t)(slot_offsets[base_slot] + variable_offset));
                }
                else if (0 == variable.m_descriptor.m_expected_component)
                {
@@ -6772,12 +6806,12 @@ void TextureTestBase::prepareAttributes(GLuint test_case_index, Utils::ProgramIn
 
                        vao.Attribute(variable.m_descriptor.m_expected_location, type, variable.m_descriptor.m_n_array_elements,
                                                  variable.m_descriptor.m_normalized, variable.GetStride(),
-                                                 (GLvoid*)(intptr_t)variable.m_descriptor.m_offset);
+                                                 (GLvoid*)(intptr_t)(slot_offsets[base_slot] + variable_offset));
                }
        }
 
        /* Update buffer */
-       buffer.Data(Utils::Buffer::StaticDraw, vertex_stride, ptr);
+       buffer.Data(Utils::Buffer::StaticDraw, buffer_size, ptr);
 }
 
 /** Get locations for all outputs with automatic_location