Fix missing dependency on sparse binds
[platform/upstream/VK-GL-CTS.git] / external / vulkancts / modules / vulkan / shaderrender / vktShaderRenderLimitTests.cpp
1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2018 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Shader limit tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktShaderRenderLimitTests.hpp"
25 #include "vktShaderRender.hpp"
26 #include "tcuImageCompare.hpp"
27 #include "tcuStringTemplate.hpp"
28 #include "tcuTextureUtil.hpp"
29 #include "tcuTestLog.hpp"
30 #include "vktDrawUtil.hpp"
31 #include "deMath.h"
32
33 using namespace std;
34 using namespace tcu;
35 using namespace vk;
36 using namespace de;
37
38 namespace vkt
39 {
40 using namespace drawutil;
41
42 namespace sr
43 {
44
45 namespace
46 {
47
48 class FragmentInputComponentCaseInstance : public ShaderRenderCaseInstance
49 {
50 public:
51         FragmentInputComponentCaseInstance (Context& context);
52
53         TestStatus              iterate(void);
54         virtual void    setupDefaultInputs(void);
55
56 private:
57         const Vec4              m_constantColor;
58 };
59
60 FragmentInputComponentCaseInstance::FragmentInputComponentCaseInstance (Context& context)
61         : ShaderRenderCaseInstance (context)
62         , m_constantColor       (0.1f, 0.05f, 0.2f, 0.0f)
63 {
64 }
65
66 TestStatus FragmentInputComponentCaseInstance::iterate (void)
67 {
68         const UVec2             viewportSize    = getViewportSize();
69         const int               width                   = viewportSize.x();
70         const int               height                  = viewportSize.y();
71         const tcu::RGBA threshold               (2, 2, 2, 2);
72         Surface                 resImage                (width, height);
73         Surface                 refImage                (width, height);
74         bool                    compareOk               = false;
75
76         const deUint16  indices[12]             =
77         {
78                 0, 4, 1,
79                 0, 5, 4,
80                 1, 2, 3,
81                 1, 3, 4
82         };
83
84         setup();
85         render(6, 4, indices);
86         copy(resImage.getAccess(), getResultImage().getAccess());
87
88         // Reference image
89         for (int y = 0; y < refImage.getHeight(); y++)
90         {
91                 for (int x = 0; x < refImage.getWidth(); x++)
92                         refImage.setPixel(x, y, RGBA(0, 255, 0, 255));
93         }
94
95         compareOk = pixelThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage, resImage, threshold, COMPARE_LOG_RESULT);
96
97         if (compareOk)
98                 return TestStatus::pass("Result image matches reference");
99         else
100                 return TestStatus::fail("Image mismatch");
101 }
102
103 void FragmentInputComponentCaseInstance::setupDefaultInputs (void)
104 {
105         const float vertices[] =
106         {
107                 -1.0f, -1.0f, 0.0f, 1.0f,
108                  0.0f, -1.0f, 0.0f, 1.0f,
109                  1.0f, -1.0f, 0.0f, 1.0f,
110                  1.0f,  1.0f, 0.0f, 1.0f,
111                  0.0f,  1.0f, 0.0f, 1.0f,
112                 -1.0f,  1.0f, 0.0f, 1.0f
113         };
114
115         addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, deUint16(sizeof(float) * 4), 6, vertices);
116 }
117
118 class FragmentInputComponentCase : public TestCase
119 {
120 public:
121         FragmentInputComponentCase      (TestContext& testCtx, const string& name, const string& description, const deUint16 inputComponents);
122         virtual                                         ~FragmentInputComponentCase(void);
123
124         void                                            initPrograms(SourceCollections& dst) const;
125         TestInstance*                           createInstance(Context& context) const;
126
127 private:
128         FragmentInputComponentCase      (const FragmentInputComponentCase&);
129         const deUint16                          m_inputComponents;
130 };
131
132 FragmentInputComponentCase::FragmentInputComponentCase (TestContext& testCtx, const string& name, const string& description, const deUint16 inputComponents)
133         : TestCase                      (testCtx, name, description)
134         , m_inputComponents     (inputComponents)
135 {
136 }
137
138 FragmentInputComponentCase::~FragmentInputComponentCase (void)
139 {
140 }
141
142 void FragmentInputComponentCase::initPrograms (SourceCollections& dst) const
143 {
144         const tcu::StringTemplate       vertexCodeTemplate(
145                 "#version 450\n"
146                 "layout(location = 0) in highp vec4 a_position;\n"
147                 "${VARYING_OUT}"
148                 "void main (void)\n"
149                 "{\n"
150                 "    gl_Position = a_position;\n"
151                     "${VARYING_DECL}"
152                 "}\n");
153
154         const tcu::StringTemplate       fragmentCodeTemplate(
155                 "#version 450\n"
156                 "layout(location = 0) out highp vec4 o_color;\n"
157                 "${VARYING_IN}"
158                 "void main (void)\n"
159                 "{\n"
160                 "    int errorCount = 0;\n"
161                     "${VERIFY}"
162                 "\n"
163                 "    if (errorCount == 0)\n"
164                 "        o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
165                 "    else\n"
166                 "        o_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
167                 "}\n");
168
169         //
170         // The number of vertex output/fragment input components is *inclusive* of any built-ins being used,
171         // since gl_Position is always output by the shader, this actually means that there are n - 4 components
172         // available as user specified output data.
173         //
174         // [14.1.4. Location Assignment, para 11]
175         //
176         // "The number of input and output locations available for a shader input or output
177         //  interface are limited, and dependent on the shader stage as described in Shader
178         //  Input and Output Locations. All variables in both the built-in interface block
179         //  and the user-defined variable interface count against these limits."
180         //
181         // So, as an example, the '128' component variant of this test will specify 124 user
182         // declared outputs in addition to gl_Position.
183
184         deUint16                                        maxLocations    = (deUint16)deCeilToInt32((float)(m_inputComponents - 4) / 4u);
185         string                                          varyingType;
186         map<string, string>                     vertexParams;
187         map<string, string>                     fragmentParams;
188
189         for (deUint16 loc = 0; loc < maxLocations; loc++)
190         {
191                 if (loc == (maxLocations - 1u))
192                 {
193                         switch (m_inputComponents - loc * 4u)
194                         {
195                         case 1:
196                                 varyingType = "float";
197                                 break;
198                         case 2:
199                                 varyingType = "vec2";
200                                 break;
201                         case 3:
202                                 varyingType = "vec3";
203                                 break;
204                         default:
205                                 varyingType = "vec4";
206                         }
207                 }
208                 else
209                         varyingType = "vec4";
210
211                 vertexParams["VARYING_OUT"]             += "layout(location = "                 + de::toString(loc)     + ") out highp "        + varyingType   + " o_color"    + de::toString(loc)     + ";\n";
212                 vertexParams["VARYING_DECL"]    += "    o_color"                                + de::toString(loc)     + " = "                         + varyingType   + "("                   + de::toString(loc)     + ".0);\n";
213                 fragmentParams["VARYING_IN"]    += "layout(location = "                 + de::toString(loc)     + ") in highp "         + varyingType   + " i_color"    + de::toString(loc)     + ";\n";
214                 fragmentParams["VERIFY"]                += "    errorCount += (i_color" + de::toString(loc)     + " == "                        + varyingType   + "("                   + de::toString(loc)     + ".0)) ? 0 : 1;\n";
215         }
216
217         dst.glslSources.add("vert") << glu::VertexSource(vertexCodeTemplate.specialize(vertexParams));
218         dst.glslSources.add("frag") << glu::FragmentSource(fragmentCodeTemplate.specialize(fragmentParams));
219 }
220
221 TestInstance* FragmentInputComponentCase::createInstance (Context& context) const
222 {
223         const InstanceInterface&                vki                                                     = context.getInstanceInterface();
224         const VkPhysicalDevice                  physDevice                                      = context.getPhysicalDevice();
225         const VkPhysicalDeviceLimits    limits                                          = getPhysicalDeviceProperties(vki, physDevice).limits;
226         const deUint16                                  maxFragmentInputComponents      = (deUint16)limits.maxFragmentInputComponents;
227         const deUint16                                  maxVertexOutputComponents       = (deUint16)limits.maxVertexOutputComponents;
228
229         if (m_inputComponents > maxFragmentInputComponents)
230         {
231                 const std::string notSupportedStr = "Unsupported number of fragment input components (" +
232                                                                                         de::toString(m_inputComponents) +
233                                                                                         ") maxFragmentInputComponents=" + de::toString(maxFragmentInputComponents);
234                 TCU_THROW(NotSupportedError, notSupportedStr.c_str());
235         }
236
237         // gl_Position counts as an output component as well, so outputComponents = inputComponents + 4
238         if (m_inputComponents + 4 > maxVertexOutputComponents)
239         {
240                 const std::string notSupportedStr = "Unsupported number of user specified vertex output components (" +
241                                                                                         de::toString(m_inputComponents + 4) +
242                                                                                         ") maxVertexOutputComponents=" + de::toString(maxVertexOutputComponents);
243                 TCU_THROW(NotSupportedError, notSupportedStr.c_str());
244         }
245
246         return new FragmentInputComponentCaseInstance(context);
247 }
248 } // anonymous
249
250 TestCaseGroup* createLimitTests (TestContext& testCtx)
251 {
252         de::MovePtr<TestCaseGroup> limitGroup                   (new TestCaseGroup(testCtx,     "limits",                       "Shader device limit tests"));
253         de::MovePtr<TestCaseGroup> nearGroup                    (new TestCaseGroup(testCtx, "near_max",                 "Shaders near maximum values"));
254
255         de::MovePtr<TestCaseGroup> inputComponentsGroup (new TestCaseGroup(testCtx,     "fragment_input",       "Fragment input component variations"));
256
257         // Fragment input component case
258         deUint16 fragmentComponentMaxLimits [] = { 64u, 128u, 256u };
259
260         for (deUint16 limitNdx = 0; limitNdx < DE_LENGTH_OF_ARRAY(fragmentComponentMaxLimits); limitNdx++)
261         {
262                 for (deInt16 cases = 5; cases > 0; cases--)
263                         inputComponentsGroup->addChild(new FragmentInputComponentCase(testCtx, "components_" + de::toString(fragmentComponentMaxLimits[limitNdx] - cases), "Input component count", (deUint16)(fragmentComponentMaxLimits[limitNdx] - cases)));
264         }
265
266         nearGroup->addChild(inputComponentsGroup.release());
267         limitGroup->addChild(nearGroup.release());
268         return limitGroup.release();
269 }
270
271 } // sr
272 } // vkt