1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2021 The Khronos Group 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 Fragment Shading Barycentric extention tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktFragmentShadingBarycentricTests.hpp"
25
26 #include "deDefs.h"
27 #include "vkDefs.hpp"
28 #include "vktTestCase.hpp"
29 #include "vktTestGroupUtil.hpp"
30 #include "vkCmdUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkBuilderUtil.hpp"
33 #include "vkBarrierUtil.hpp"
34 #include "vkBufferWithMemory.hpp"
35 #include "vkImageWithMemory.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkPipelineConstructionUtil.hpp"
39
40 #include "tcuTestLog.hpp"
41 #include "tcuStringTemplate.hpp"
42 #include "tcuImageCompare.hpp"
43 #include "tcuVectorUtil.hpp"
44
45 #include <cstdint>
46 #include <ostream>
47 #include <string>
48 #include <vector>
49 #include <map>
50
51 namespace vkt
52 {
53 namespace FragmentShadingBarycentric
54 {
55 namespace
56 {
57 using namespace vk;
58 using namespace vkt;
59
60 using de::MovePtr;
61 using std::map;
62 using std::string;
63 using std::vector;
64 using tcu::mix;
65
66 enum TestType
67 {
68 TEST_TYPE_DATA = 0,
69 TEST_TYPE_WEIGHTS,
70 };
71
72 enum TestSubtype
73 {
74 TEST_SUBTYPE_DEFAULT = 0,
75 TEST_SUBTYPE_MSAA_INTERPOLATE_AT_CENTROID,
76 TEST_SUBTYPE_MSAA_INTERPOLATE_AT_SAMPLE,
77 TEST_SUBTYPE_MSAA_INTERPOLATE_AT_OFFSET,
78 TEST_SUBTYPE_MSAA_CENTROID_QUALIFIER,
79 TEST_SUBTYPE_MSAA_SAMPLE_QUALIFIER,
80 TEST_SUBTYPE_PERVERTEX_CORRECTNESS,
81 TEST_SUBTYPE_TESS_SHADER,
82 TEST_SUBTYPE_GEOMETRY_SHADER,
83 TEST_SUBTYPE_TESSGEOM_SHADER,
84 };
85
getShaderComboName(uint32_t testSubType)86 const char *getShaderComboName(uint32_t testSubType)
87 {
88 uint32_t idx = testSubType - TEST_SUBTYPE_TESS_SHADER;
89
90 DE_ASSERT(idx < 3);
91
92 static const char *sc_names[] = {
93 "with_tess_shader",
94 "with_geom_shader",
95 "with_tess_geom_shader",
96 };
97
98 return sc_names[idx];
99 }
100
101 const size_t DATA_TEST_WIDTH = 8u;
102 const size_t DATA_TEST_HEIGHT = 8u;
103 const size_t WEIGHT_TEST_WIDTH = 128u;
104 const size_t WEIGHT_TEST_HEIGHT = 128u;
105 const float WEIGHT_TEST_SLOPE = 16.0f;
106
107 struct TestParams
108 {
109 const PipelineConstructionType pipelineConstructionType;
110 TestType testType;
111 TestSubtype testSubtype;
112 VkPrimitiveTopology topology;
113 bool dynamicIndexing;
114 size_t aggregate; // 0: value itself, 1:struct, 2+:Array
115 glu::DataType dataType;
116 size_t width;
117 size_t height;
118 bool perspective;
119 bool provokingVertexLast;
120 uint32_t rotation;
121 bool dynamicTopologyInPipeline;
122 VkSampleCountFlagBits sampleCount;
123 bool testWithInterpolation;
124 bool testWithFlatInterpolation;
125 bool clipVertices;
126 bool useMeshShader;
127 };
128
getComponentCount(const TestParams & testParams)129 size_t getComponentCount(const TestParams &testParams)
130 {
131 const size_t scalarSize = static_cast<size_t>(getDataTypeScalarSize(testParams.dataType));
132 const size_t aggregateSize = (testParams.aggregate > 0) ? testParams.aggregate : 1;
133 const size_t topologySize =
134 3; // Test always check three items in array: "Reads of per-vertex values for missing vertices, such as the third vertex of a line primitive, will return zero."
135 const size_t result = scalarSize * aggregateSize * topologySize;
136
137 return result;
138 }
139
makeImageCreateInfo(const VkFormat format,const uint32_t width,uint32_t height,VkSampleCountFlagBits samples)140 static VkImageCreateInfo makeImageCreateInfo(const VkFormat format, const uint32_t width, uint32_t height,
141 VkSampleCountFlagBits samples)
142 {
143 const VkImageUsageFlags usage =
144 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
145 const VkImageCreateInfo imageCreateInfo = {
146 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
147 nullptr, // const void* pNext;
148 0u, // VkImageCreateFlags flags;
149 VK_IMAGE_TYPE_2D, // VkImageType imageType;
150 format, // VkFormat format;
151 makeExtent3D(width, height, 1u), // VkExtent3D extent;
152 1u, // uint32_t mipLevels;
153 1u, // uint32_t arrayLayers;
154 samples, // VkSampleCountFlagBits samples;
155 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
156 usage, // VkImageUsageFlags usage;
157 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
158 0u, // uint32_t queueFamilyIndexCount;
159 nullptr, // const uint32_t* pQueueFamilyIndices;
160 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
161 };
162
163 return imageCreateInfo;
164 }
165
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat format,VkSampleCountFlagBits samples)166 static Move<VkRenderPass> makeRenderPass(const DeviceInterface &vk, const VkDevice device, const VkFormat format,
167 VkSampleCountFlagBits samples)
168 {
169 const VkAttachmentDescription attachmentSingleSampleDesc{
170 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
171 format, // VkFormat format;
172 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
173 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
174 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
175 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
176 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
177 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
178 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
179 };
180
181 const VkAttachmentDescription attachmentMultiSampleDesc{
182 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
183 format, // VkFormat format;
184 samples, // VkSampleCountFlagBits samples;
185 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
186 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
187 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
188 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
189 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
190 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
191 };
192
193 const VkAttachmentDescription attachments[] = {attachmentSingleSampleDesc, attachmentMultiSampleDesc};
194
195 const VkAttachmentReference attachmentSingleSampleRef{
196 0u, // uint32_t attachment;
197 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
198 };
199
200 const VkAttachmentReference attachmentMultiSampleRef{
201 1u, // uint32_t attachment;
202 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
203 };
204
205 const bool useMultisampling = (samples > VK_SAMPLE_COUNT_1_BIT);
206 const VkAttachmentReference *colorAttachment =
207 useMultisampling ? &attachmentMultiSampleRef : &attachmentSingleSampleRef;
208 const VkAttachmentReference *resolveAttachment = useMultisampling ? &attachmentSingleSampleRef : nullptr;
209
210 const VkSubpassDescription subpassDescription{
211 (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags;
212 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
213 0u, // uint32_t inputAttachmentCount;
214 nullptr, // const VkAttachmentReference* pInputAttachments;
215 1u, // uint32_t colorAttachmentCount;
216 colorAttachment, // const VkAttachmentReference* pColorAttachments;
217 resolveAttachment, // const VkAttachmentReference* pResolveAttachments;
218 nullptr, // const VkAttachmentReference* pDepthStencilAttachment;
219 0u, // uint32_t preserveAttachmentCount;
220 nullptr // const uint32_t* pPreserveAttachments;
221 };
222
223 const VkRenderPassCreateInfo renderPassInfo{
224 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
225 nullptr, // const void* pNext;
226 (VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags;
227 1u + useMultisampling, // uint32_t attachmentCount;
228 attachments, // const VkAttachmentDescription* pAttachments;
229 1u, // uint32_t subpassCount;
230 &subpassDescription, // const VkSubpassDescription* pSubpasses;
231 0u, // uint32_t dependencyCount;
232 nullptr // const VkSubpassDependency* pDependencies;
233 };
234
235 return createRenderPass(vk, device, &renderPassInfo, nullptr);
236 }
237
238 using GraphicsPipelinePtr = std::unique_ptr<GraphicsPipelineWrapper>;
239
makeGraphicsVertexShaderPipeline(PipelineConstructionType pipelineConstructionType,const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice physicalDevice,const VkDevice device,const std::vector<std::string> & deviceExtensions,const PipelineLayoutWrapper & pipelineLayout,const VkRenderPass renderPass,const ShaderWrapper vertShaderModule,const ShaderWrapper fragShaderModule,const uint32_t width,const uint32_t height,const VkPrimitiveTopology topology,const VkSampleCountFlagBits rasterizationSamples,const bool withColor=false,const bool provokingVertexLast=false,const bool dynamicTopology=false,const ShaderWrapper tessCtrlShaderModule=ShaderWrapper (),const ShaderWrapper tessEvalShaderModule=ShaderWrapper (),const ShaderWrapper geometryShaderModule=ShaderWrapper ())240 static GraphicsPipelinePtr makeGraphicsVertexShaderPipeline(
241 PipelineConstructionType pipelineConstructionType, const InstanceInterface &vki, const DeviceInterface &vkd,
242 const VkPhysicalDevice physicalDevice, const VkDevice device, const std::vector<std::string> &deviceExtensions,
243 const PipelineLayoutWrapper &pipelineLayout, const VkRenderPass renderPass, const ShaderWrapper vertShaderModule,
244 const ShaderWrapper fragShaderModule, const uint32_t width, const uint32_t height,
245 const VkPrimitiveTopology topology, const VkSampleCountFlagBits rasterizationSamples, const bool withColor = false,
246 const bool provokingVertexLast = false, const bool dynamicTopology = false,
247 const ShaderWrapper tessCtrlShaderModule = ShaderWrapper(),
248 const ShaderWrapper tessEvalShaderModule = ShaderWrapper(),
249 const ShaderWrapper geometryShaderModule = ShaderWrapper())
250 {
251 const std::vector<VkViewport> viewports(1, makeViewport(width, height));
252 const std::vector<VkRect2D> scissors(1, makeRect2D(width, height));
253 const VkVertexInputBindingDescription vertexInputBindingDescription = {
254 0u, // uint32_t binding;
255 2 * sizeof(tcu::Vec4), // uint32_t stride;
256 VK_VERTEX_INPUT_RATE_VERTEX, // VkVertexInputRate inputRate;
257 };
258 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[] = {
259 {
260 0u, // uint32_t location;
261 0u, // uint32_t binding;
262 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
263 0u // uint32_t offset;
264 },
265 {
266 1u, // uint32_t location;
267 0u, // uint32_t binding;
268 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
269 sizeof(tcu::Vec4) // uint32_t offset;
270 },
271 };
272 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo = {
273 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
274 nullptr, // const void* pNext;
275 (VkPipelineVertexInputStateCreateFlags)0, // VkPipelineVertexInputStateCreateFlags flags;
276 1u, // uint32_t vertexBindingDescriptionCount;
277 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
278 DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions), // uint32_t vertexAttributeDescriptionCount;
279 vertexInputAttributeDescriptions, // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
280 };
281 const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT provokingVertexStateCreateInfoEXT = {
282 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT, // VkStructureType sType;
283 nullptr, // const void* pNext;
284 VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, // VkProvokingVertexModeEXT provokingVertexMode;
285 };
286 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
287 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
288 provokingVertexLast ? &provokingVertexStateCreateInfoEXT : nullptr, // const void* pNext;
289 0u, // VkPipelineRasterizationStateCreateFlags flags;
290 VK_FALSE, // VkBool32 depthClampEnable;
291 false, // VkBool32 rasterizerDiscardEnable;
292 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
293 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
294 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
295 VK_FALSE, // VkBool32 depthBiasEnable;
296 0.0f, // float depthBiasConstantFactor;
297 0.0f, // float depthBiasClamp;
298 0.0f, // float depthBiasSlopeFactor;
299 1.0f // float lineWidth;
300 };
301 const bool isMultiSample = (rasterizationSamples > VK_SAMPLE_COUNT_1_BIT);
302 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo{
303 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
304 nullptr, // const void* pNext;
305 0u, // VkPipelineMultisampleStateCreateFlags flags;
306 rasterizationSamples, // VkSampleCountFlagBits rasterizationSamples;
307 (isMultiSample ? VK_TRUE : VK_FALSE), // VkBool32 sampleShadingEnable;
308 1.0f, // float minSampleShading;
309 nullptr, // const VkSampleMask* pSampleMask;
310 VK_FALSE, // VkBool32 alphaToCoverageEnable;
311 VK_FALSE, // VkBool32 alphaToOneEnable;
312 };
313 const VkDynamicState dynamicStates[] = {
314 VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY,
315 };
316 const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
317 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
318 nullptr, // const void* pNext;
319 0u, // VkPipelineDynamicStateCreateFlags flags;
320 DE_LENGTH_OF_ARRAY(dynamicStates), // uint32_t dynamicStateCount;
321 dynamicStates, // const VkDynamicState* pDynamicStates;
322 };
323 const VkPipelineDynamicStateCreateInfo *pDynamicStateCreateInfo =
324 dynamicTopology ? &dynamicStateCreateInfo : nullptr;
325 const auto pVertexInputStateCreateInfo = (withColor ? &vertexInputStateInfo : nullptr);
326
327 GraphicsPipelinePtr pipelineWrapperPtr(
328 new GraphicsPipelineWrapper(vki, vkd, physicalDevice, device, deviceExtensions, pipelineConstructionType));
329 auto &pipelineWrapper = *pipelineWrapperPtr.get();
330
331 pipelineWrapper.setMonolithicPipelineLayout(pipelineLayout)
332 .setDefaultDepthStencilState()
333 .setDefaultColorBlendState()
334 .setDefaultTopology(topology)
335 .setDynamicState(pDynamicStateCreateInfo)
336 .setupVertexInputState(pVertexInputStateCreateInfo)
337 .setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, renderPass, 0u, vertShaderModule,
338 &rasterizationStateCreateInfo, tessCtrlShaderModule, tessEvalShaderModule,
339 geometryShaderModule)
340 .setupFragmentShaderState(pipelineLayout, renderPass, 0u, fragShaderModule, nullptr,
341 isMultiSample ? &multisampleStateInfo : nullptr)
342 .setupFragmentOutputState(renderPass, 0u, nullptr, &multisampleStateInfo)
343 .buildPipeline();
344
345 return pipelineWrapperPtr;
346 }
347
makeGraphicsMeshShaderPipeline(PipelineConstructionType pipelineConstructionType,const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice physicalDevice,const VkDevice device,const std::vector<std::string> & deviceExtensions,const PipelineLayoutWrapper & pipelineLayout,const VkRenderPass renderPass,const ShaderWrapper meshShaderModule,const ShaderWrapper fragShaderModule,const uint32_t width,const uint32_t height,const VkPrimitiveTopology topology,const VkSampleCountFlagBits rasterizationSamples,const bool provokingVertexLast=false,const bool dynamicTopology=false)348 static GraphicsPipelinePtr makeGraphicsMeshShaderPipeline(
349 PipelineConstructionType pipelineConstructionType, const InstanceInterface &vki, const DeviceInterface &vkd,
350 const VkPhysicalDevice physicalDevice, const VkDevice device, const std::vector<std::string> &deviceExtensions,
351 const PipelineLayoutWrapper &pipelineLayout, const VkRenderPass renderPass, const ShaderWrapper meshShaderModule,
352 const ShaderWrapper fragShaderModule, const uint32_t width, const uint32_t height,
353 const VkPrimitiveTopology topology, const VkSampleCountFlagBits rasterizationSamples,
354 const bool provokingVertexLast = false, const bool dynamicTopology = false)
355 {
356 const std::vector<VkViewport> viewports(1, makeViewport(width, height));
357 const std::vector<VkRect2D> scissors(1, makeRect2D(width, height));
358
359 const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT provokingVertexStateCreateInfoEXT = {
360 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT, // VkStructureType sType;
361 nullptr, // const void* pNext;
362 VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT, // VkProvokingVertexModeEXT provokingVertexMode;
363 };
364 const VkPipelineRasterizationStateCreateInfo rasterizationStateCreateInfo = {
365 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
366 provokingVertexLast ? &provokingVertexStateCreateInfoEXT : nullptr, // const void* pNext;
367 0u, // VkPipelineRasterizationStateCreateFlags flags;
368 VK_FALSE, // VkBool32 depthClampEnable;
369 false, // VkBool32 rasterizerDiscardEnable;
370 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
371 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
372 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
373 VK_FALSE, // VkBool32 depthBiasEnable;
374 0.0f, // float depthBiasConstantFactor;
375 0.0f, // float depthBiasClamp;
376 0.0f, // float depthBiasSlopeFactor;
377 1.0f // float lineWidth;
378 };
379 const bool isMultiSample = (rasterizationSamples > VK_SAMPLE_COUNT_1_BIT);
380 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo{
381 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
382 nullptr, // const void* pNext;
383 0u, // VkPipelineMultisampleStateCreateFlags flags;
384 rasterizationSamples, // VkSampleCountFlagBits rasterizationSamples;
385 (isMultiSample ? VK_TRUE : VK_FALSE), // VkBool32 sampleShadingEnable;
386 1.0f, // float minSampleShading;
387 nullptr, // const VkSampleMask* pSampleMask;
388 VK_FALSE, // VkBool32 alphaToCoverageEnable;
389 VK_FALSE, // VkBool32 alphaToOneEnable;
390 };
391 const VkDynamicState dynamicStates[] = {
392 VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY,
393 };
394 const VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo = {
395 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
396 nullptr, // const void* pNext;
397 0u, // VkPipelineDynamicStateCreateFlags flags;
398 DE_LENGTH_OF_ARRAY(dynamicStates), // uint32_t dynamicStateCount;
399 dynamicStates, // const VkDynamicState* pDynamicStates;
400 };
401 const VkPipelineDynamicStateCreateInfo *pDynamicStateCreateInfo =
402 dynamicTopology ? &dynamicStateCreateInfo : nullptr;
403
404 GraphicsPipelinePtr pipelineWrapperPtr(
405 new GraphicsPipelineWrapper(vki, vkd, physicalDevice, device, deviceExtensions, pipelineConstructionType));
406 auto &pipelineWrapper = *pipelineWrapperPtr.get();
407
408 pipelineWrapper.setMonolithicPipelineLayout(pipelineLayout)
409 .setDefaultDepthStencilState()
410 .setDefaultColorBlendState()
411 .setDefaultTopology(topology)
412 .setDynamicState(pDynamicStateCreateInfo)
413 .setupPreRasterizationMeshShaderState(viewports, scissors, pipelineLayout, renderPass, 0u, vk::ShaderWrapper(),
414 meshShaderModule, &rasterizationStateCreateInfo)
415 .setupFragmentShaderState(pipelineLayout, renderPass, 0u, fragShaderModule)
416 .setupFragmentOutputState(renderPass, 0u, nullptr, &multisampleStateInfo)
417 .buildPipeline();
418
419 return pipelineWrapperPtr;
420 }
421
makeGraphicsPipeline(bool useMeshShader,PipelineConstructionType pipelineConstructionType,const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice physicalDevice,const VkDevice device,const std::vector<std::string> & deviceExtensions,const PipelineLayoutWrapper & pipelineLayout,const VkRenderPass renderPass,const ShaderWrapper vertOrMeshShaderModule,const ShaderWrapper fragShaderModule,const uint32_t width,const uint32_t height,const VkPrimitiveTopology topology,const VkSampleCountFlagBits rasterizationSamples,const bool withColor=false,const bool provokingVertexLast=false,const bool dynamicTopology=false,const ShaderWrapper tessCtrlShaderModule=ShaderWrapper (),const ShaderWrapper tessEvalShaderModule=ShaderWrapper (),const ShaderWrapper geometryShaderModule=ShaderWrapper ())422 static GraphicsPipelinePtr makeGraphicsPipeline(
423 bool useMeshShader, PipelineConstructionType pipelineConstructionType, const InstanceInterface &vki,
424 const DeviceInterface &vkd, const VkPhysicalDevice physicalDevice, const VkDevice device,
425 const std::vector<std::string> &deviceExtensions, const PipelineLayoutWrapper &pipelineLayout,
426 const VkRenderPass renderPass, const ShaderWrapper vertOrMeshShaderModule, const ShaderWrapper fragShaderModule,
427 const uint32_t width, const uint32_t height, const VkPrimitiveTopology topology,
428 const VkSampleCountFlagBits rasterizationSamples, const bool withColor = false,
429 const bool provokingVertexLast = false, const bool dynamicTopology = false,
430 const ShaderWrapper tessCtrlShaderModule = ShaderWrapper(),
431 const ShaderWrapper tessEvalShaderModule = ShaderWrapper(),
432 const ShaderWrapper geometryShaderModule = ShaderWrapper())
433 {
434 if (useMeshShader)
435 {
436 DE_ASSERT(!tessCtrlShaderModule.isSet());
437 DE_ASSERT(!tessEvalShaderModule.isSet());
438 DE_ASSERT(!geometryShaderModule.isSet());
439
440 return makeGraphicsMeshShaderPipeline(pipelineConstructionType, vki, vkd, physicalDevice, device,
441 deviceExtensions, pipelineLayout, renderPass, vertOrMeshShaderModule,
442 fragShaderModule, width, height, topology, rasterizationSamples,
443 provokingVertexLast, dynamicTopology);
444 }
445 else
446 {
447 return makeGraphicsVertexShaderPipeline(
448 pipelineConstructionType, vki, vkd, physicalDevice, device, deviceExtensions, pipelineLayout, renderPass,
449 vertOrMeshShaderModule, fragShaderModule, width, height, topology, rasterizationSamples, withColor,
450 provokingVertexLast, dynamicTopology, tessCtrlShaderModule, tessEvalShaderModule, geometryShaderModule);
451 }
452 }
453
454 // Function replacing all occurrences of substring with string passed in last parameter.
replace(const std::string & str,const std::string & from,const std::string & to)455 static inline std::string replace(const std::string &str, const std::string &from, const std::string &to)
456 {
457 std::string result(str);
458
459 size_t start_pos = 0;
460 while ((start_pos = result.find(from, start_pos)) != std::string::npos)
461 {
462 result.replace(start_pos, from.length(), to);
463 start_pos += to.length();
464 }
465
466 return result;
467 }
468
469 class FragmentShadingBarycentricDataTestInstance : public TestInstance
470 {
471 public:
472 FragmentShadingBarycentricDataTestInstance(Context &context, const TestParams &testParams);
473 virtual ~FragmentShadingBarycentricDataTestInstance();
474 virtual tcu::TestStatus iterate(void);
475
476 protected:
477 vector<tcu::Vec4> generateVertexBuffer(void);
478 MovePtr<BufferWithMemory> createVertexBuffer(const vector<tcu::Vec4> &vertices);
479 bool verify(BufferWithMemory *resultBuffer);
480 bool getProvokingVertexLast(void);
481
482 TestParams m_testParams;
483 };
484
FragmentShadingBarycentricDataTestInstance(Context & context,const TestParams & testParams)485 FragmentShadingBarycentricDataTestInstance::FragmentShadingBarycentricDataTestInstance(Context &context,
486 const TestParams &testParams)
487 : TestInstance(context)
488 , m_testParams(testParams)
489 {
490 }
491
~FragmentShadingBarycentricDataTestInstance()492 FragmentShadingBarycentricDataTestInstance::~FragmentShadingBarycentricDataTestInstance()
493 {
494 }
495
generateVertexBuffer(void)496 vector<tcu::Vec4> FragmentShadingBarycentricDataTestInstance::generateVertexBuffer(void)
497 {
498 size_t verticesCount = static_cast<size_t>(~0ull);
499 vector<tcu::Vec4> result;
500
501 DE_ASSERT(!m_testParams.clipVertices || m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
502
503 switch (m_testParams.topology)
504 {
505 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
506 {
507 verticesCount = m_testParams.width * m_testParams.height;
508
509 result.reserve(verticesCount);
510
511 for (size_t y = 0; y < m_testParams.height; y++)
512 {
513 const float yy = -1.0f + 2.0f * ((0.5f + float(y)) / float(m_testParams.height));
514
515 for (size_t x = 0; x < m_testParams.width; x++)
516 {
517 const float xx = -1.0f + 2.0f * ((0.5f + float(x)) / float(m_testParams.width));
518
519 result.push_back(tcu::Vec4(xx, yy, 0.0f, 1.0f));
520 }
521 }
522
523 break;
524 }
525
526 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
527 {
528 verticesCount = 2 * m_testParams.height;
529
530 result.reserve(verticesCount);
531
532 for (size_t y = 0; y < m_testParams.height; y++)
533 {
534 const float yy = -1.0f + 2.0f * ((0.5f + float(y)) / float(m_testParams.height));
535
536 result.push_back(tcu::Vec4(-1.0f, yy, 0.0f, 1.0f));
537 result.push_back(tcu::Vec4(1.0f, yy, 0.0f, 1.0f));
538 }
539
540 break;
541 }
542
543 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
544 {
545 verticesCount = 2 * m_testParams.height;
546
547 result.reserve(verticesCount);
548
549 for (size_t y = 0; y < m_testParams.height; y++)
550 {
551 const float yy = -1.0f + 2.0f * (0.5f + float(y)) / float(m_testParams.height);
552 ;
553
554 if (y % 2 == 0)
555 {
556 result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
557 result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
558 }
559 else
560 {
561 result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
562 result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
563 }
564 }
565
566 break;
567 }
568
569 case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
570 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
571 {
572 verticesCount = 6;
573
574 result.reserve(verticesCount);
575
576 result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
577 result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
578 result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
579
580 result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
581 result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
582 result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
583
584 break;
585 }
586
587 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
588 {
589 verticesCount = 4;
590
591 result.reserve(verticesCount);
592
593 result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
594 result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
595 result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
596 result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
597
598 break;
599 }
600
601 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
602 {
603 verticesCount = 4;
604
605 result.reserve(verticesCount);
606
607 result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
608 result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
609 result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
610 result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
611
612 break;
613 }
614
615 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
616 {
617 verticesCount = 4 * m_testParams.height;
618
619 result.reserve(verticesCount);
620
621 for (size_t y = 0; y < m_testParams.height; y++)
622 {
623 const float yy = -1.0f + 2.0f * ((0.5f + float(y)) / float(m_testParams.height));
624
625 result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
626 result.push_back(tcu::Vec4(-1.0f, yy, 0.0f, 1.0f));
627 result.push_back(tcu::Vec4(1.0f, yy, 0.0f, 1.0f));
628 result.push_back(tcu::Vec4(2.0f, yy, 0.0f, 1.0f));
629 }
630
631 break;
632 }
633
634 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
635 {
636 verticesCount = 2 * m_testParams.height + 2;
637
638 result.reserve(verticesCount);
639
640 result.push_back(tcu::Vec4(-10.0f, -10.0f, 0.0f, 1.0f));
641
642 for (size_t y = 0; y < m_testParams.height; y++)
643 {
644 const float ky = (0.5f + float(y)) / float(m_testParams.height);
645 const float yy = -1.0f + 2.0f * ky;
646
647 if (y % 2 == 0)
648 {
649 result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
650 result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
651 }
652 else
653 {
654 result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
655 result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
656 }
657 }
658
659 result.push_back(tcu::Vec4(+10.0f, +10.0f, 0.0f, 1.0f));
660
661 break;
662 }
663
664 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
665 {
666 verticesCount = 12;
667
668 result.reserve(verticesCount);
669
670 result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
671 result.push_back(tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f));
672 result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
673 result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
674 result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
675 result.push_back(tcu::Vec4(-3.0f, -1.0f, 0.0f, 1.0f));
676
677 result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
678 result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
679 result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
680 result.push_back(tcu::Vec4(+3.0f, +1.0f, 0.0f, 1.0f));
681 result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
682 result.push_back(tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f));
683
684 break;
685 }
686
687 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
688 {
689 verticesCount = 8;
690
691 result.reserve(verticesCount);
692
693 result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
694 result.push_back(tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f));
695 result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
696 result.push_back(tcu::Vec4(-3.0f, -1.0f, 0.0f, 1.0f));
697 result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
698 result.push_back(tcu::Vec4(+3.0f, +1.0f, 0.0f, 1.0f));
699 result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
700 result.push_back(tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f));
701
702 break;
703 }
704
705 default:
706 TCU_THROW(InternalError, "Unknown topology");
707 }
708
709 DE_ASSERT(result.size() == verticesCount);
710
711 if (m_testParams.clipVertices)
712 {
713 for (size_t i = 0; i < result.size(); ++i)
714 {
715 result[i][1] *= 2.0f;
716 }
717 }
718
719 return result;
720 }
721
verify(BufferWithMemory * resultBuffer)722 bool FragmentShadingBarycentricDataTestInstance::verify(BufferWithMemory *resultBuffer)
723 {
724 const size_t components = getComponentCount(m_testParams);
725 const uint32_t expectedPerVertex = static_cast<uint32_t>(1 << components) - 1;
726 const uint32_t expectedInterpolated = (static_cast<uint32_t>(1 << components / 3) - 1);
727 const uint32_t expectedFlat = (static_cast<uint32_t>(1 << components / 3) - 1);
728 const tcu::UVec4 expected =
729 m_testParams.testSubtype == TEST_SUBTYPE_PERVERTEX_CORRECTNESS ?
730 tcu::UVec4(10u) :
731 tcu::UVec4(expectedPerVertex, m_testParams.testWithInterpolation ? expectedInterpolated : 0u,
732 m_testParams.testWithFlatInterpolation ? expectedFlat : 0u, 0u);
733 const tcu::UVec4 *retrieved = (tcu::UVec4 *)resultBuffer->getAllocation().getHostPtr();
734 size_t failures = 0;
735
736 {
737 size_t n = 0;
738
739 for (size_t y = 0; y < m_testParams.height; y++)
740 for (size_t x = 0; x < m_testParams.width; x++)
741 {
742 if (retrieved[n] != expected)
743 failures++;
744
745 n++;
746 }
747 }
748
749 if (failures)
750 {
751 const uint8_t places = static_cast<uint8_t>(components / 4);
752 tcu::TestLog &log = m_context.getTestContext().getLog();
753 size_t n = 0;
754 std::ostringstream s;
755
756 s << "Expected mask:" << std::setfill('0') << std::hex << std::setw(places) << expected << std::endl;
757
758 for (size_t y = 0; y < m_testParams.height; y++)
759 {
760 for (size_t x = 0; x < m_testParams.width; x++)
761 {
762 s << std::setw(places) << retrieved[n] << ' ';
763
764 n++;
765 }
766
767 s << std::endl;
768 }
769
770 log << tcu::TestLog::Message << s.str() << tcu::TestLog::EndMessage;
771 }
772
773 return failures == 0;
774 }
775
createVertexBuffer(const vector<tcu::Vec4> & vertices)776 MovePtr<BufferWithMemory> FragmentShadingBarycentricDataTestInstance::createVertexBuffer(
777 const vector<tcu::Vec4> &vertices)
778 {
779 const DeviceInterface &vkd = m_context.getDeviceInterface();
780 const VkDevice device = m_context.getDevice();
781 Allocator &allocator = m_context.getDefaultAllocator();
782 const VkDeviceSize vertexBufferSize = vertices.size() * sizeof(vertices[0]);
783 const VkBufferCreateInfo vertexBufferCreateInfo =
784 makeBufferCreateInfo(vertexBufferSize, m_testParams.useMeshShader ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT :
785 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
786 MovePtr<BufferWithMemory> vertexBuffer = MovePtr<BufferWithMemory>(
787 new BufferWithMemory(vkd, device, allocator, vertexBufferCreateInfo, MemoryRequirement::HostVisible));
788 Allocation &vertexBufferAlloc = vertexBuffer->getAllocation();
789
790 // Initialize vertex data
791 deMemcpy(vertexBufferAlloc.getHostPtr(), vertices.data(), (size_t)vertexBufferSize);
792 flushAlloc(vkd, device, vertexBufferAlloc);
793
794 return vertexBuffer;
795 }
796
getProvokingVertexLast(void)797 bool FragmentShadingBarycentricDataTestInstance::getProvokingVertexLast(void)
798 {
799 if (m_testParams.provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
800 {
801 const VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR &fragmentShaderBarycentricProperties =
802 m_context.getFragmentShaderBarycentricProperties();
803
804 if (fragmentShaderBarycentricProperties.triStripVertexOrderIndependentOfProvokingVertex)
805 return false;
806 }
807
808 return m_testParams.provokingVertexLast;
809 }
810
iterate(void)811 tcu::TestStatus FragmentShadingBarycentricDataTestInstance::iterate(void)
812 {
813 const InstanceInterface &vki = m_context.getInstanceInterface();
814 const DeviceInterface &vkd = m_context.getDeviceInterface();
815 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
816 const VkDevice device = m_context.getDevice();
817 const auto &deviceExtensions = m_context.getDeviceExtensions();
818 const VkQueue queue = m_context.getUniversalQueue();
819 Allocator &allocator = m_context.getDefaultAllocator();
820 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
821
822 const VkDeviceSize offsetZero = 0ull;
823 const VkFormat format = VK_FORMAT_R32G32B32A32_UINT;
824 const uint32_t pixelSize = mapVkFormat(format).getPixelSize();
825 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
826 const uint32_t width = static_cast<uint32_t>(m_testParams.width);
827 const uint32_t height = static_cast<uint32_t>(m_testParams.height);
828 const VkPrimitiveTopology topology = m_testParams.topology;
829 const bool withColor = false;
830 const bool provokingVertexLast = getProvokingVertexLast();
831
832 const vector<tcu::Vec4> vertices = generateVertexBuffer();
833 const uint32_t vertexCount = static_cast<uint32_t>(vertices.size());
834 MovePtr<BufferWithMemory> vertexBuffer = createVertexBuffer(vertices);
835
836 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(format, width, height, VK_SAMPLE_COUNT_1_BIT);
837 const VkImageSubresourceRange imageSubresourceRange =
838 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
839 const MovePtr<ImageWithMemory> image =
840 MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
841 const Move<VkImageView> imageView =
842 makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
843
844 bool useMeshShader = m_testParams.useMeshShader;
845
846 const VkBufferCreateInfo resultBufferCreateInfo =
847 makeBufferCreateInfo(width * height * pixelSize,
848 (useMeshShader ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT :
849 VK_BUFFER_USAGE_TRANSFER_DST_BIT));
850 MovePtr<BufferWithMemory> resultBuffer = MovePtr<BufferWithMemory>(
851 new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
852
853 const string shaderSuffix = (provokingVertexLast == m_testParams.provokingVertexLast) ? "" : "-forced";
854 const ShaderWrapper module = ShaderWrapper(
855 vkd, device, m_context.getBinaryCollection().get(useMeshShader ? "mesh" + shaderSuffix : "vert" + shaderSuffix),
856 0u);
857
858 const ShaderWrapper tessCtrlShaderModule =
859 ((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
860 (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
861 ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("tess_ctrl" + shaderSuffix), 0u) :
862 ShaderWrapper();
863 const ShaderWrapper tessEvalShaderModule =
864 ((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
865 (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
866 ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("tess_eval" + shaderSuffix), 0u) :
867 ShaderWrapper();
868 const ShaderWrapper geometryShaderModule =
869 ((m_testParams.testSubtype == TEST_SUBTYPE_GEOMETRY_SHADER) ||
870 (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
871 ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("geom" + shaderSuffix), 0u) :
872 ShaderWrapper();
873 const ShaderWrapper fragModule =
874 ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag" + shaderSuffix), 0u);
875 RenderPassWrapper renderPass = RenderPassWrapper(m_testParams.pipelineConstructionType, vkd, device, format);
876 renderPass.createFramebuffer(vkd, device, **image, *imageView, width, height);
877 const uint32_t pushConstants[] = {0, 1, 2};
878 const VkPushConstantRange pushConstantRange =
879 makePushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(pushConstants));
880 const VkPushConstantRange *pushConstantRangePtr = m_testParams.dynamicIndexing ? &pushConstantRange : nullptr;
881 const uint32_t pushConstantRangeCount = m_testParams.dynamicIndexing ? 1 : 0;
882 const Move<VkCommandPool> commandPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
883 const Move<VkCommandBuffer> commandBuffer =
884 allocateCommandBuffer(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
885 Move<VkDescriptorSetLayout> descriptorSetLayout;
886 Move<VkDescriptorPool> descriptorPool;
887 Move<VkDescriptorSet> descriptorSet;
888
889 if (useMeshShader)
890 {
891 DescriptorSetLayoutBuilder layoutBuilder;
892 layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_MESH_BIT_EXT);
893 descriptorSetLayout = layoutBuilder.build(vkd, device);
894
895 DescriptorPoolBuilder poolBuilder;
896 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
897 descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
898
899 descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), *descriptorSetLayout);
900 }
901
902 // Pipeline layout
903 const PipelineLayoutWrapper pipelineLayout(m_testParams.pipelineConstructionType, vkd, device,
904 useMeshShader ? 1 : 0, useMeshShader ? &*descriptorSetLayout : nullptr,
905 pushConstantRangeCount, pushConstantRangePtr);
906 const auto pipelineWrapper =
907 makeGraphicsPipeline(m_testParams.useMeshShader, m_testParams.pipelineConstructionType, vki, vkd,
908 physicalDevice, device, deviceExtensions, pipelineLayout, *renderPass, module, fragModule,
909 width, height, topology, VK_SAMPLE_COUNT_1_BIT, withColor, provokingVertexLast, false,
910 tessCtrlShaderModule, tessEvalShaderModule, geometryShaderModule);
911
912 // Update descriptor set.
913 if (useMeshShader)
914 {
915 DescriptorSetUpdateBuilder updateBuilder;
916
917 const auto vertexBufferSize = static_cast<VkDeviceSize>(de::dataSize(vertices));
918 const auto vertexBufferDescInfo = makeDescriptorBufferInfo(vertexBuffer->get(), 0ull, vertexBufferSize);
919 updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
920 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &vertexBufferDescInfo);
921 updateBuilder.update(vkd, device);
922 }
923
924 const tcu::IVec3 groupCount =
925 (topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST) ? tcu::IVec3(4u, 4u, 4u) : tcu::IVec3(1u, 1u, 1u);
926
927 beginCommandBuffer(vkd, *commandBuffer);
928 {
929 renderPass.begin(vkd, *commandBuffer, makeRect2D(width, height), clearColor);
930
931 pipelineWrapper->bind(*commandBuffer);
932
933 if (useMeshShader)
934 vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
935 &descriptorSet.get(), 0u, nullptr);
936 else
937 vkd.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &offsetZero);
938
939 if (m_testParams.dynamicIndexing)
940 vkd.cmdPushConstants(*commandBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u,
941 sizeof(pushConstants), &pushConstants);
942
943 if (useMeshShader)
944 vkd.cmdDrawMeshTasksEXT(*commandBuffer, groupCount.x(), groupCount.y(), groupCount.z());
945 else
946 vkd.cmdDraw(*commandBuffer, vertexCount, 1u, 0u, 0u);
947
948 renderPass.end(vkd, *commandBuffer);
949
950 copyImageToBuffer(vkd, *commandBuffer, image->get(), resultBuffer->get(), tcu::IVec2(width, height));
951 }
952
953 endCommandBuffer(vkd, *commandBuffer);
954 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
955
956 invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(),
957 resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
958
959 DE_ASSERT(8 * pixelSize >= 3 * getComponentCount(m_testParams));
960
961 if (verify(resultBuffer.get()))
962 return tcu::TestStatus::pass("Pass");
963 else
964 return tcu::TestStatus::fail("Fail");
965 }
966
967 class FragmentShadingBarycentricWeightTestInstance : public TestInstance
968 {
969 public:
970 FragmentShadingBarycentricWeightTestInstance(Context &context, const TestParams &testParams);
971 virtual ~FragmentShadingBarycentricWeightTestInstance();
972 virtual tcu::TestStatus iterate(void);
973
974 protected:
975 void addVertexWithColor(vector<tcu::Vec4> &vertices, const tcu::Vec4 &vertex, const tcu::Vec4 &color);
976 vector<tcu::Vec4> generateVertexBuffer(void);
977 MovePtr<BufferWithMemory> createVertexBuffer(const vector<tcu::Vec4> &vertices);
978 bool verify(VkFormat format, BufferWithMemory *referenceBuffer, BufferWithMemory *resultBuffer);
979
980 TestParams m_testParams;
981 };
982
FragmentShadingBarycentricWeightTestInstance(Context & context,const TestParams & testParams)983 FragmentShadingBarycentricWeightTestInstance::FragmentShadingBarycentricWeightTestInstance(Context &context,
984 const TestParams &testParams)
985 : TestInstance(context)
986 , m_testParams(testParams)
987 {
988 }
989
~FragmentShadingBarycentricWeightTestInstance()990 FragmentShadingBarycentricWeightTestInstance::~FragmentShadingBarycentricWeightTestInstance()
991 {
992 }
993
addVertexWithColor(vector<tcu::Vec4> & vertices,const tcu::Vec4 & vertex,const tcu::Vec4 & color)994 void FragmentShadingBarycentricWeightTestInstance::addVertexWithColor(vector<tcu::Vec4> &vertices,
995 const tcu::Vec4 &vertex, const tcu::Vec4 &color)
996 {
997 vertices.push_back(vertex);
998 vertices.push_back(color);
999 }
1000
generateVertexBuffer(void)1001 vector<tcu::Vec4> FragmentShadingBarycentricWeightTestInstance::generateVertexBuffer(void)
1002 {
1003 const float slope = WEIGHT_TEST_SLOPE;
1004 const tcu::Vec4 leftBotColor = tcu::Vec4(0.00f, 0.00f, 0.00f, 1.0f);
1005 const tcu::Vec4 leftTopColor = tcu::Vec4(1.00f, 0.00f, 0.00f, 1.0f);
1006 const tcu::Vec4 rightTopColor = tcu::Vec4(0.00f, 1.00f, 0.00f, 1.0f);
1007 const tcu::Vec4 rightBotColor = tcu::Vec4(0.00f, 0.00f, 1.00f, 1.0f);
1008 const tcu::Vec4 noneColor = tcu::Vec4(0.25f, 0.50f, 0.75f, 1.0f);
1009 size_t vertexCount = static_cast<size_t>(~0ull);
1010 vector<tcu::Vec4> result;
1011
1012 DE_ASSERT(slope >= 1.0f);
1013
1014 switch (m_testParams.topology)
1015 {
1016 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
1017 {
1018 vertexCount = m_testParams.width * m_testParams.height;
1019
1020 result.reserve(2 * vertexCount);
1021
1022 for (size_t y = 0; y < m_testParams.height; y++)
1023 {
1024 const float ky = (0.5f + float(y)) / float(m_testParams.height);
1025 const float yy = -1.0f + 2.0f * ky;
1026 const tcu::Vec4 leftColor = mix(leftTopColor, leftBotColor, ky);
1027 const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
1028
1029 for (size_t x = 0; x < m_testParams.width; x++)
1030 {
1031 const float kx = (0.5f + float(x)) / float(m_testParams.width);
1032 const float xx = -1.0f + 2.0f * kx;
1033 const float pointSlope = 1.0f + kx * (slope - 1.0f);
1034 const tcu::Vec4 point = tcu::Vec4(xx, yy, 0.0f, 1.0f) * pointSlope;
1035 const tcu::Vec4 color = mix(leftColor, rightColor, kx);
1036
1037 addVertexWithColor(result, point, color);
1038 }
1039 }
1040
1041 break;
1042 }
1043
1044 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
1045 {
1046 vertexCount = 2 * m_testParams.height;
1047
1048 result.reserve(2 * vertexCount);
1049
1050 for (size_t y = 0; y < m_testParams.height; y++)
1051 {
1052 const float ky = (0.5f + float(y)) / float(m_testParams.height);
1053 const float yy = -1.0f + 2.0f * ky;
1054 const tcu::Vec4 leftColor = mix(leftTopColor, leftBotColor, ky);
1055 const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
1056 const tcu::Vec4 left = tcu::Vec4(-1.0f, yy, 0.0f, 1.0f);
1057 const tcu::Vec4 right = tcu::Vec4(1.0f, yy, 0.0f, 1.0f) * slope;
1058
1059 addVertexWithColor(result, left, leftColor);
1060 addVertexWithColor(result, right, rightColor);
1061 }
1062
1063 break;
1064 }
1065
1066 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
1067 {
1068 vertexCount = 2 * m_testParams.height;
1069
1070 result.reserve(2 * vertexCount);
1071
1072 for (size_t y = 0; y < m_testParams.height; y++)
1073 {
1074 const float ky = (0.5f + float(y)) / float(m_testParams.height);
1075 const float yy = -1.0f + 2.0f * ky;
1076 const tcu::Vec4 leftColor = mix(leftTopColor, leftBotColor, ky);
1077 const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
1078 const tcu::Vec4 left = tcu::Vec4(-2.0f, yy, 0.0f, 1.0f);
1079 const tcu::Vec4 right = tcu::Vec4(2.0f, yy, 0.0f, 1.0f) * slope;
1080
1081 if (y % 2 == 0)
1082 {
1083 addVertexWithColor(result, left, leftColor);
1084 addVertexWithColor(result, right, rightColor);
1085 }
1086 else
1087 {
1088 addVertexWithColor(result, right, rightColor);
1089 addVertexWithColor(result, left, leftColor);
1090 }
1091 }
1092
1093 break;
1094 }
1095
1096 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
1097 {
1098 vertexCount = 6;
1099
1100 result.reserve(2 * vertexCount);
1101
1102 addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1103 addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
1104 addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1105
1106 addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1107 addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
1108 addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1109
1110 break;
1111 }
1112
1113 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
1114 {
1115 vertexCount = 4;
1116
1117 result.reserve(2 * vertexCount);
1118
1119 addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
1120 addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1121 addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1122 addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
1123
1124 break;
1125 }
1126
1127 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
1128 {
1129 vertexCount = 4;
1130
1131 result.reserve(2 * vertexCount);
1132
1133 addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1134 addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
1135 addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1136 addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
1137
1138 break;
1139 }
1140
1141 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
1142 {
1143 vertexCount = 4 * m_testParams.height;
1144
1145 result.reserve(2 * vertexCount);
1146
1147 for (size_t y = 0; y < m_testParams.height; y++)
1148 {
1149 const float ky = (0.5f + float(y)) / float(m_testParams.height);
1150 const float yy = -1.0f + 2.0f * ky;
1151 const tcu::Vec4 leftColor = mix(leftTopColor, leftBotColor, ky);
1152 const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
1153 const tcu::Vec4 preLeft = tcu::Vec4(-2.0f, yy, 0.0f, 1.0f);
1154 const tcu::Vec4 left = tcu::Vec4(-1.0f, yy, 0.0f, 1.0f);
1155 const tcu::Vec4 right = tcu::Vec4(1.0f, yy, 0.0f, 1.0f) * slope;
1156 const tcu::Vec4 afterRight = tcu::Vec4(2.0f, yy, 0.0f, 1.0f) * slope;
1157
1158 addVertexWithColor(result, preLeft, noneColor);
1159 addVertexWithColor(result, left, leftColor);
1160 addVertexWithColor(result, right, rightColor);
1161 addVertexWithColor(result, afterRight, noneColor);
1162 }
1163
1164 break;
1165 }
1166
1167 case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
1168 {
1169 vertexCount = 2 * m_testParams.height + 2;
1170
1171 result.reserve(2 * vertexCount);
1172
1173 addVertexWithColor(result, tcu::Vec4(-10.0f, -10.0f, 0.0f, 1.0f), noneColor);
1174
1175 for (size_t y = 0; y < m_testParams.height; y++)
1176 {
1177 const float ky = (0.5f + float(y)) / float(m_testParams.height);
1178 const float yy = -1.0f + 2.0f * ky;
1179 const tcu::Vec4 leftColor = mix(leftTopColor, leftBotColor, ky);
1180 const tcu::Vec4 rightColor = mix(rightTopColor, rightBotColor, ky);
1181 const tcu::Vec4 left = tcu::Vec4(-2.0f, yy, 0.0f, 1.0f);
1182 const tcu::Vec4 right = tcu::Vec4(2.0f, yy, 0.0f, 1.0f) * slope;
1183
1184 if (y % 2 == 0)
1185 {
1186 addVertexWithColor(result, left, leftColor);
1187 addVertexWithColor(result, right, rightColor);
1188 }
1189 else
1190 {
1191 addVertexWithColor(result, right, rightColor);
1192 addVertexWithColor(result, left, leftColor);
1193 }
1194 }
1195
1196 addVertexWithColor(result, tcu::Vec4(+10.0f, +10.0f, 0.0f, 1.0f), noneColor);
1197
1198 break;
1199 }
1200
1201 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
1202 {
1203 vertexCount = 12;
1204
1205 result.reserve(2 * vertexCount);
1206
1207 addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
1208 addVertexWithColor(result, tcu::Vec4(-3.0f, +1.0f, 0.0f, 1.0f), noneColor);
1209 addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1210 addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, noneColor);
1211 addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1212 addVertexWithColor(result, tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f) * slope, noneColor);
1213
1214 addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1215 addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), noneColor);
1216 addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1217 addVertexWithColor(result, tcu::Vec4(+3.0f, +1.0f, 0.0f, 1.0f) * slope, noneColor);
1218 addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
1219 addVertexWithColor(result, tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f), leftTopColor);
1220
1221 break;
1222 }
1223
1224 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
1225 {
1226 vertexCount = 8;
1227
1228 result.reserve(2 * vertexCount);
1229
1230 addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f), leftBotColor);
1231 addVertexWithColor(result, tcu::Vec4(-3.0f, -1.0f, 0.0f, 1.0f), noneColor);
1232 addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f), leftTopColor);
1233 addVertexWithColor(result, tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f) * slope, noneColor);
1234 addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope, rightBotColor);
1235 addVertexWithColor(result, tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f), noneColor);
1236 addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope, rightTopColor);
1237 addVertexWithColor(result, tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f) * slope, noneColor);
1238
1239 break;
1240 }
1241
1242 default:
1243 TCU_THROW(InternalError, "Unknown topology");
1244 }
1245
1246 DE_ASSERT(result.size() == 2 * vertexCount);
1247
1248 return result;
1249 }
1250
verify(VkFormat format,BufferWithMemory * referenceBuffer,BufferWithMemory * resultBuffer)1251 bool FragmentShadingBarycentricWeightTestInstance::verify(VkFormat format, BufferWithMemory *referenceBuffer,
1252 BufferWithMemory *resultBuffer)
1253 {
1254 const uint32_t *refernceData = (uint32_t *)referenceBuffer->getAllocation().getHostPtr();
1255 const uint32_t *resultData = (uint32_t *)resultBuffer->getAllocation().getHostPtr();
1256 tcu::TestLog &log = m_context.getTestContext().getLog();
1257 const tcu::ConstPixelBufferAccess refImage(mapVkFormat(format), (int)m_testParams.width, (int)m_testParams.height,
1258 1u, refernceData);
1259 const tcu::ConstPixelBufferAccess resultImage(mapVkFormat(format), (int)m_testParams.width,
1260 (int)m_testParams.height, 1u, resultData);
1261 const tcu::UVec4 threshold(1, 1, 1, 1);
1262 bool result = tcu::intThresholdCompare(log, "ComparisonResult", "Image comparison result", refImage, resultImage,
1263 threshold, tcu::COMPARE_LOG_ON_ERROR);
1264
1265 return result;
1266 }
1267
createVertexBuffer(const vector<tcu::Vec4> & vertices)1268 MovePtr<BufferWithMemory> FragmentShadingBarycentricWeightTestInstance::createVertexBuffer(
1269 const vector<tcu::Vec4> &vertices)
1270 {
1271 const DeviceInterface &vkd = m_context.getDeviceInterface();
1272 const VkDevice device = m_context.getDevice();
1273 Allocator &allocator = m_context.getDefaultAllocator();
1274 const VkDeviceSize vertexBufferSize = vertices.size() * sizeof(vertices[0]);
1275 const VkBufferCreateInfo vertexBufferCreateInfo =
1276 makeBufferCreateInfo(vertexBufferSize, m_testParams.useMeshShader ? VK_BUFFER_USAGE_STORAGE_BUFFER_BIT :
1277 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1278 MovePtr<BufferWithMemory> vertexBuffer = MovePtr<BufferWithMemory>(
1279 new BufferWithMemory(vkd, device, allocator, vertexBufferCreateInfo, MemoryRequirement::HostVisible));
1280 Allocation &vertexBufferAlloc = vertexBuffer->getAllocation();
1281
1282 // Initialize vertex data
1283 deMemcpy(vertexBufferAlloc.getHostPtr(), vertices.data(), (size_t)vertexBufferSize);
1284 flushAlloc(vkd, device, vertexBufferAlloc);
1285
1286 return vertexBuffer;
1287 }
1288
iterate(void)1289 tcu::TestStatus FragmentShadingBarycentricWeightTestInstance::iterate(void)
1290 {
1291 const InstanceInterface &vki = m_context.getInstanceInterface();
1292 const DeviceInterface &vkd = m_context.getDeviceInterface();
1293 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1294 const VkDevice device = m_context.getDevice();
1295 const auto &deviceExtensions = m_context.getDeviceExtensions();
1296 const VkQueue queue = m_context.getUniversalQueue();
1297 Allocator &allocator = m_context.getDefaultAllocator();
1298 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1299
1300 const VkDeviceSize offsetZero = 0ull;
1301 const VkFormat format = VK_FORMAT_R8G8B8A8_UNORM;
1302 const uint32_t pixelSize = mapVkFormat(format).getPixelSize();
1303 const uint32_t width = static_cast<uint32_t>(m_testParams.width);
1304 const uint32_t height = static_cast<uint32_t>(m_testParams.height);
1305 const bool dynamicStateTopology = m_testParams.dynamicTopologyInPipeline;
1306 const VkPrimitiveTopology pipelineTopology =
1307 dynamicStateTopology ? primitiveTopologyCastToList(m_testParams.topology) : m_testParams.topology;
1308 const bool withColor = true;
1309 const bool provokingVertexLast = m_testParams.provokingVertexLast;
1310 const bool useMultisampling = m_testParams.sampleCount > VK_SAMPLE_COUNT_1_BIT;
1311 const float teta = deFloatRadians(-float(m_testParams.rotation));
1312 const float mvp[4 * 4] = {cos(teta), -sin(teta), 0.0f, 0.0f, sin(teta), cos(teta), 0.0f, 0.0f,
1313 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f};
1314 bool useMeshShader = m_testParams.useMeshShader;
1315
1316 const vector<tcu::Vec4> vertices = generateVertexBuffer();
1317 const uint32_t vertexCount = static_cast<uint32_t>(vertices.size() / 2);
1318 MovePtr<BufferWithMemory> vertexBuffer = createVertexBuffer(vertices);
1319
1320 const VkBufferCreateInfo bufferCreateInfo =
1321 makeBufferCreateInfo(width * height * pixelSize,
1322 useMeshShader ? VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT :
1323 VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1324 MovePtr<BufferWithMemory> resultBuffer = MovePtr<BufferWithMemory>(
1325 new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
1326 MovePtr<BufferWithMemory> referenceBuffer = MovePtr<BufferWithMemory>(
1327 new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
1328 const Move<VkRenderPass> renderPass = makeRenderPass(vkd, device, format, m_testParams.sampleCount);
1329 const Move<VkCommandPool> commandPool = createCommandPool(vkd, device, 0, queueFamilyIndex);
1330 const ShaderWrapper shaderModule =
1331 ShaderWrapper(vkd, device, m_context.getBinaryCollection().get(useMeshShader ? "mesh" : "vert"), 0u);
1332
1333 const VkImageCreateInfo imageCreateInfo = makeImageCreateInfo(format, width, height, VK_SAMPLE_COUNT_1_BIT);
1334 const VkImageSubresourceRange imageSubresourceRange =
1335 makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1336 const VkImageCreateInfo msImageCreateInfo = makeImageCreateInfo(format, width, height, m_testParams.sampleCount);
1337 const std::vector<VkClearValue> clearValues(2u, makeClearValueColorU32(0u, 0u, 0u, 0u));
1338
1339 Move<VkDescriptorSetLayout> descriptorSetLayout;
1340 Move<VkDescriptorPool> descriptorPool;
1341 Move<VkDescriptorSet> descriptorSet;
1342
1343 if (useMeshShader)
1344 {
1345 DescriptorSetLayoutBuilder layoutBuilder;
1346 layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_MESH_BIT_EXT);
1347 descriptorSetLayout = layoutBuilder.build(vkd, device);
1348
1349 DescriptorPoolBuilder poolBuilder;
1350 poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
1351 descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1352
1353 descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), *descriptorSetLayout);
1354
1355 DescriptorSetUpdateBuilder updateBuilder;
1356
1357 const auto vertexBufferSize = static_cast<VkDeviceSize>(de::dataSize(vertices));
1358 const auto vertexBufferDescInfo = makeDescriptorBufferInfo(vertexBuffer->get(), 0ull, vertexBufferSize);
1359 updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u),
1360 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &vertexBufferDescInfo);
1361 updateBuilder.update(vkd, device);
1362 }
1363
1364 std::vector<VkImageMemoryBarrier> initialImageBarriers(
1365 2, makeImageMemoryBarrier(
1366 VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1367 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, VK_NULL_HANDLE, imageSubresourceRange));
1368
1369 for (size_t ndx = 0; ndx < 2; ndx++)
1370 {
1371 const MovePtr<ImageWithMemory> image = MovePtr<ImageWithMemory>(
1372 new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1373 const Move<VkImageView> imageView =
1374 makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
1375 MovePtr<ImageWithMemory> msImage;
1376 Move<VkImageView> msImageView;
1377
1378 initialImageBarriers[0].image = **image;
1379
1380 if (useMultisampling)
1381 {
1382 msImage = MovePtr<ImageWithMemory>(
1383 new ImageWithMemory(vkd, device, allocator, msImageCreateInfo, MemoryRequirement::Any));
1384 msImageView = makeImageView(vkd, device, **msImage, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
1385 initialImageBarriers[1].image = **msImage;
1386 }
1387
1388 const std::vector<VkImageView> imageViewVect = {*imageView, *msImageView};
1389 const Move<VkFramebuffer> framebuffer =
1390 makeFramebuffer(vkd, device, *renderPass, 1u + useMultisampling, imageViewVect.data(), width, height);
1391 const Move<VkCommandBuffer> commandBuffer =
1392 allocateCommandBuffer(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1393 const BufferWithMemory *buffer = (ndx == 0) ? resultBuffer.get() : referenceBuffer.get();
1394 const string fragModuleName = (ndx == 0) ? "frag_test" : "frag_reference";
1395 const ShaderWrapper fragModule =
1396 ShaderWrapper(vkd, device, m_context.getBinaryCollection().get(fragModuleName), 0u);
1397 const VkPushConstantRange pushConstantRange = makePushConstantRange(
1398 useMeshShader ? VK_SHADER_STAGE_MESH_BIT_EXT : VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(mvp));
1399 const PipelineLayoutWrapper pipelineLayout(
1400 m_testParams.pipelineConstructionType, vkd, device, useMeshShader ? 1 : 0,
1401 useMeshShader ? &*descriptorSetLayout : nullptr, 1, &pushConstantRange);
1402 const auto pipelineWrapper = makeGraphicsPipeline(
1403 useMeshShader, m_testParams.pipelineConstructionType, vki, vkd, physicalDevice, device, deviceExtensions,
1404 pipelineLayout, *renderPass, shaderModule, fragModule, width, height, pipelineTopology,
1405 m_testParams.sampleCount, withColor, provokingVertexLast, dynamicStateTopology);
1406 const VkPipeline pipeline = pipelineWrapper->getPipeline();
1407
1408 beginCommandBuffer(vkd, *commandBuffer);
1409 {
1410 cmdPipelineImageMemoryBarrier(vkd, *commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT,
1411 VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, initialImageBarriers.data(),
1412 1u + useMultisampling);
1413
1414 if (dynamicStateTopology)
1415 vkd.cmdSetPrimitiveTopology(*commandBuffer, m_testParams.topology);
1416
1417 beginRenderPass(vkd, *commandBuffer, *renderPass, *framebuffer, makeRect2D(width, height),
1418 1u + useMultisampling, clearValues.data());
1419 {
1420 vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
1421
1422 if (useMeshShader)
1423 vkd.cmdBindDescriptorSets(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u,
1424 1u, &descriptorSet.get(), 0u, nullptr);
1425 else
1426 vkd.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &offsetZero);
1427
1428 vkd.cmdPushConstants(*commandBuffer, *pipelineLayout,
1429 useMeshShader ? VK_SHADER_STAGE_MESH_BIT_EXT : VK_SHADER_STAGE_VERTEX_BIT, 0u,
1430 sizeof(mvp), &mvp);
1431
1432 if (useMeshShader)
1433 {
1434 const tcu::IVec3 groupCount = (m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST) ?
1435 tcu::IVec3(256u, 8u, 8u) :
1436 tcu::IVec3(1u, 1u, 1u);
1437 vkd.cmdDrawMeshTasksEXT(*commandBuffer, groupCount.x(), groupCount.y(), groupCount.z());
1438 }
1439 else
1440 vkd.cmdDraw(*commandBuffer, vertexCount, 1u, 0u, 0u);
1441 }
1442 endRenderPass(vkd, *commandBuffer);
1443
1444 copyImageToBuffer(vkd, *commandBuffer, image->get(), buffer->get(), tcu::IVec2(width, height));
1445 }
1446 endCommandBuffer(vkd, *commandBuffer);
1447 submitCommandsAndWait(vkd, device, queue, *commandBuffer);
1448
1449 invalidateMappedMemoryRange(vkd, device, buffer->getAllocation().getMemory(),
1450 buffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
1451 }
1452
1453 if (verify(format, referenceBuffer.get(), resultBuffer.get()))
1454 return tcu::TestStatus::pass("Pass");
1455 else
1456 return tcu::TestStatus::fail("Fail");
1457 }
1458
1459 class FragmentShadingBarycentricTestCase : public TestCase
1460 {
1461 public:
1462 FragmentShadingBarycentricTestCase(tcu::TestContext &context, const char *name, const TestParams testParams);
1463 ~FragmentShadingBarycentricTestCase(void);
1464
1465 virtual void checkSupport(Context &context) const;
1466 virtual void initPrograms(SourceCollections &programCollection) const;
1467 virtual TestInstance *createInstance(Context &context) const;
1468
1469 private:
1470 void initDataPrograms(SourceCollections &programCollection) const;
1471 void initMiscDataPrograms(SourceCollections &programCollection) const;
1472 void initMiscDataTessPrograms(SourceCollections &programCollection, map<string, string> &attributes) const;
1473 void initMiscDataGeomPrograms(SourceCollections &programCollection, map<string, string> &attributes) const;
1474 void initWeightPrograms(SourceCollections &programCollection) const;
1475 string generateDataMeshShader(void) const;
1476 string generateWeightMeshShader(void) const;
1477 string getDataPrimitiveFormula(void) const;
1478 string getDataVertexFormula(const uint32_t vertex, const bool *provokingVertexLastPtr = nullptr) const;
1479 string getDataProvokingVertexFormula(const bool *provokingVertexLastPtr = nullptr) const;
1480 TestParams m_testParams;
1481 };
1482
FragmentShadingBarycentricTestCase(tcu::TestContext & context,const char * name,const TestParams testParams)1483 FragmentShadingBarycentricTestCase::FragmentShadingBarycentricTestCase(tcu::TestContext &context, const char *name,
1484 const TestParams testParams)
1485 : vkt::TestCase(context, name)
1486 , m_testParams(testParams)
1487 {
1488 }
1489
~FragmentShadingBarycentricTestCase(void)1490 FragmentShadingBarycentricTestCase::~FragmentShadingBarycentricTestCase(void)
1491 {
1492 }
1493
checkSupport(Context & context) const1494 void FragmentShadingBarycentricTestCase::checkSupport(Context &context) const
1495 {
1496 const auto &vki = context.getInstanceInterface();
1497 const auto physicalDevice = context.getPhysicalDevice();
1498
1499 context.requireDeviceFunctionality("VK_KHR_fragment_shader_barycentric");
1500
1501 const VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR &fragmentShaderBarycentricFeatures =
1502 context.getFragmentShaderBarycentricFeatures();
1503
1504 if (!fragmentShaderBarycentricFeatures.fragmentShaderBarycentric)
1505 TCU_THROW(NotSupportedError,
1506 "Requires VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR.fragmentShaderBarycentric");
1507
1508 checkPipelineConstructionRequirements(vki, physicalDevice, m_testParams.pipelineConstructionType);
1509
1510 if (m_testParams.provokingVertexLast)
1511 {
1512 context.requireDeviceFunctionality("VK_EXT_provoking_vertex");
1513
1514 const VkPhysicalDeviceProvokingVertexFeaturesEXT &provokingVertexFeaturesEXT =
1515 context.getProvokingVertexFeaturesEXT();
1516
1517 if (!provokingVertexFeaturesEXT.provokingVertexLast)
1518 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceProvokingVertexFeaturesEXT.provokingVertexLast");
1519 }
1520
1521 if (m_testParams.dynamicTopologyInPipeline)
1522 {
1523 context.requireDeviceFunctionality("VK_EXT_extended_dynamic_state");
1524
1525 const VkPhysicalDeviceExtendedDynamicStateFeaturesEXT &extendedDynamicStateFeaturesEXT =
1526 context.getExtendedDynamicStateFeaturesEXT();
1527
1528 if (!extendedDynamicStateFeaturesEXT.extendedDynamicState)
1529 TCU_THROW(NotSupportedError,
1530 "Requires VkPhysicalDeviceExtendedDynamicStateFeaturesEXT.extendedDynamicState");
1531 }
1532
1533 if (m_testParams.useMeshShader)
1534 {
1535 context.requireDeviceFunctionality("VK_EXT_mesh_shader");
1536
1537 const VkPhysicalDeviceMeshShaderFeaturesEXT &meshShaderFeaturesEXT = context.getMeshShaderFeaturesEXT();
1538
1539 if (!meshShaderFeaturesEXT.meshShader)
1540 TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceMeshShaderFeaturesEXT.meshShader");
1541 }
1542
1543 if ((m_testParams.dataType == glu::TYPE_DOUBLE) || (m_testParams.dataType == glu::TYPE_DOUBLE_VEC2) ||
1544 (m_testParams.dataType == glu::TYPE_DOUBLE_VEC3) || (m_testParams.dataType == glu::TYPE_DOUBLE_VEC4))
1545 {
1546 VkPhysicalDeviceFeatures2 features2;
1547 deMemset(&features2, 0, sizeof(features2));
1548 features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
1549 features2.pNext = nullptr;
1550 vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
1551 if (features2.features.shaderFloat64 != VK_TRUE)
1552 {
1553 TCU_THROW(NotSupportedError, "shaderFloat64 not supported");
1554 }
1555 }
1556
1557 if ((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
1558 (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER))
1559 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1560
1561 if ((m_testParams.testSubtype == TEST_SUBTYPE_GEOMETRY_SHADER) ||
1562 (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER))
1563 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
1564
1565 if ((m_testParams.testSubtype == TEST_SUBTYPE_MSAA_INTERPOLATE_AT_SAMPLE) ||
1566 (m_testParams.testSubtype == TEST_SUBTYPE_MSAA_INTERPOLATE_AT_OFFSET))
1567 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
1568 }
1569
createInstance(Context & context) const1570 TestInstance *FragmentShadingBarycentricTestCase::createInstance(Context &context) const
1571 {
1572 switch (m_testParams.testType)
1573 {
1574 case TEST_TYPE_DATA:
1575 return new FragmentShadingBarycentricDataTestInstance(context, m_testParams);
1576 case TEST_TYPE_WEIGHTS:
1577 return new FragmentShadingBarycentricWeightTestInstance(context, m_testParams);
1578 default:
1579 TCU_THROW(InternalError, "Unknown testType");
1580 }
1581 }
1582
initPrograms(SourceCollections & programCollection) const1583 void FragmentShadingBarycentricTestCase::initPrograms(SourceCollections &programCollection) const
1584 {
1585 switch (m_testParams.testType)
1586 {
1587 case TEST_TYPE_DATA:
1588 if (m_testParams.testSubtype == TEST_SUBTYPE_PERVERTEX_CORRECTNESS)
1589 initMiscDataPrograms(programCollection);
1590 else
1591 initDataPrograms(programCollection);
1592 break;
1593 case TEST_TYPE_WEIGHTS:
1594 initWeightPrograms(programCollection);
1595 break;
1596 default:
1597 TCU_THROW(InternalError, "Unknown testType");
1598 }
1599 }
1600
getDataPrimitiveFormula(void) const1601 string FragmentShadingBarycentricTestCase::getDataPrimitiveFormula(void) const
1602 {
1603 if (m_testParams.clipVertices)
1604 {
1605 DE_ASSERT(m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST);
1606 return "((x - 2) * 2 < y) ? 0 : 1";
1607 }
1608 const char *primitiveFormulas[] = {
1609 "w * y + x", // VK_PRIMITIVE_TOPOLOGY_POINT_LIST
1610 "y", // VK_PRIMITIVE_TOPOLOGY_LINE_LIST
1611 "2*y", // VK_PRIMITIVE_TOPOLOGY_LINE_STRIP
1612 "(x < y) ? 0 : 1", // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
1613 "(x < y) ? 0 : 1", // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
1614 "(x < y) ? 0 : 1", // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
1615 "y", // VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY
1616 "2*y", // VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY
1617 "(x < y) ? 0 : 1", // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY
1618 "(x < y) ? 0 : 1", // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1619 "(x < y) ? 0 : 1", // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
1620 };
1621
1622 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(primitiveFormulas) == vk::VK_PRIMITIVE_TOPOLOGY_LAST);
1623 DE_ASSERT(m_testParams.topology < DE_LENGTH_OF_ARRAY(primitiveFormulas));
1624
1625 return primitiveFormulas[m_testParams.topology];
1626 }
1627
getDataVertexFormula(const uint32_t vertex,const bool * provokingVertexLastPtr) const1628 string FragmentShadingBarycentricTestCase::getDataVertexFormula(const uint32_t vertex,
1629 const bool *provokingVertexLastPtr) const
1630 {
1631 typedef const char *TriVertexFormula[3];
1632
1633 // Accoriding "Barycentric Interpolation" section
1634 const TriVertexFormula topologyVertexFormulas[] = {
1635 {"p", "p", "p"}, // VK_PRIMITIVE_TOPOLOGY_POINT_LIST
1636 {"2*p", "2*p+1", "2*p+1"}, // VK_PRIMITIVE_TOPOLOGY_LINE_LIST
1637 {"p", "p+1", "p+1"}, // VK_PRIMITIVE_TOPOLOGY_LINE_STRIP
1638 {"3*p", "3*p+1", "3*p+2"}, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
1639 {"p", "even?p+1:p+2", "even?p+2:p+1"}, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
1640 {"p+1", "p+2", "0"}, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
1641 {"4*p+1", "4*p+2", "4*p+2"}, // VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY
1642 {"p+1", "p+2", "p+2"}, // VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY
1643 {"6*p", "6*p+2", "6*p+4"}, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY
1644 {"2*p", "even?2*p+2:2*p+4", "even?2*p+4:2*p+2"}, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1645 {"3*p", "3*p+1", "3*p+2"}, // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
1646 };
1647 const TriVertexFormula topologyVertexFormulasLast[] = {
1648 {"even?p:p+1", "even?p+1:p", "p+2"}, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
1649 {"0", "p+1", "p+2"}, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
1650 {"even?2*p:2*p+2", "even?2*p+2:2*p", "2*p+4"}, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1651 };
1652 const bool provokingVertexLast =
1653 provokingVertexLastPtr ? (*provokingVertexLastPtr) : m_testParams.provokingVertexLast;
1654 const bool provokingLastTriangleStrip =
1655 provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1656 const bool provokingLastTriangleFan =
1657 provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
1658 const bool provokingLastTriangleStripAdj =
1659 provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
1660 const TriVertexFormula *triVertexFormula =
1661 provokingLastTriangleStrip ? &topologyVertexFormulasLast[0] :
1662 provokingLastTriangleFan ? &topologyVertexFormulasLast[1] :
1663 provokingLastTriangleStripAdj ? &topologyVertexFormulasLast[2] :
1664 &topologyVertexFormulas[static_cast<size_t>(m_testParams.topology)];
1665
1666 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(topologyVertexFormulas) == vk::VK_PRIMITIVE_TOPOLOGY_LAST);
1667 DE_ASSERT(vertex < DE_LENGTH_OF_ARRAY(triVertexFormula[0]));
1668
1669 return "(" + string(triVertexFormula[0][vertex]) + ")";
1670 }
1671
getDataProvokingVertexFormula(const bool * provokingVertexLastPtr) const1672 string FragmentShadingBarycentricTestCase::getDataProvokingVertexFormula(const bool *provokingVertexLastPtr) const
1673 {
1674 typedef const char *ProvokingVertexFormula[2];
1675
1676 const ProvokingVertexFormula provokingVertexFormulas[] = {
1677 {"p", "p"}, // VK_PRIMITIVE_TOPOLOGY_POINT_LIST
1678 {"2*p", "2*p+1"}, // VK_PRIMITIVE_TOPOLOGY_LINE_LIST
1679 {"p", "p+1"}, // VK_PRIMITIVE_TOPOLOGY_LINE_STRIP
1680 {"3*p", "3*p+2"}, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
1681 {"p", "p+2"}, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
1682 {
1683 "p+1",
1684 "p+2",
1685 }, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
1686 {"4*p+1", "4*p+2"}, // VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY
1687 {"p+1", "p+2"}, // VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY
1688 {"6*p", "6*p+4"}, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY
1689 {"2*p", "2*p+4"}, // VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1690 {
1691 "",
1692 "",
1693 }, // VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
1694 };
1695
1696 const bool provokingVertexLast =
1697 provokingVertexLastPtr ? (*provokingVertexLastPtr) : m_testParams.provokingVertexLast;
1698 const ProvokingVertexFormula &provokingVertexFormula =
1699 provokingVertexFormulas[static_cast<size_t>(m_testParams.topology)];
1700
1701 return "(" + string(provokingVertexFormula[provokingVertexLast ? 1 : 0]) + ")";
1702 }
1703
generateDataMeshShader() const1704 string FragmentShadingBarycentricTestCase::generateDataMeshShader() const
1705 {
1706
1707 string meshShader;
1708
1709 switch (m_testParams.topology)
1710 {
1711 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
1712 {
1713 meshShader = "#version 450\n"
1714 "#extension GL_EXT_mesh_shader : enable\n"
1715 "\n"
1716 "${dataStruct}\n"
1717 "layout(local_size_x = 8, local_size_y = 4, local_size_z = 1) in;\n"
1718 "layout(triangles) out;\n"
1719 "layout(max_vertices=6, max_primitives=6) out;\n"
1720 "\n"
1721 "layout(set = 0, binding = 0) buffer PerVertexData{ \n"
1722 " vec4 vertexBuffer[6];\n"
1723 "} pvd;\n"
1724 "layout (location=0) out ${typePrefix} data[]${typeSuffix};\n" +
1725 string(m_testParams.testWithInterpolation ?
1726 "layout(location = ${locInterp}) out ${typePrefix} dataInterp[]${typeSuffix};\n" :
1727 "") +
1728 string(m_testParams.testWithFlatInterpolation ?
1729 "layout(location = ${locFlat}) out ${typePrefix} dataFlat[]${typeSuffix};\n" :
1730 "") +
1731 "\n"
1732 "out gl_MeshPerVertexEXT \n"
1733 "{\n"
1734 " vec4 gl_Position;\n"
1735 " float gl_PointSize;\n"
1736 "} gl_MeshVerticesEXT[];\n"
1737 "\n"
1738 "void main()\n"
1739 "{\n"
1740 " uint maxVertex = 6;\n"
1741 " uint maxPrimitive = 2;\n"
1742 " SetMeshOutputsEXT(maxVertex, maxPrimitive);\n"
1743 " const uint vertex = gl_LocalInvocationIndex;\n"
1744 " const uint primitive = gl_LocalInvocationIndex;\n"
1745 " const uvec3 indices[2] = uvec3[](\n"
1746 " uvec3(0, 1, 2),\n"
1747 " uvec3(3, 4, 5)\n"
1748 " );\n"
1749 " if (vertex < maxVertex)\n"
1750 " {\n"
1751 " gl_MeshVerticesEXT[vertex].gl_Position = pvd.vertexBuffer[vertex];\n"
1752 " gl_MeshVerticesEXT[vertex].gl_PointSize = 1.0;\n"
1753 " uint n = vertex + 1;\n"
1754 " data[vertex] = ${value};\n" +
1755 string(m_testParams.testWithInterpolation ? " dataInterp[vertex] = ${value};\n" : "") +
1756 string(m_testParams.testWithFlatInterpolation ? " dataFlat[vertex] = ${value};\n" : "") +
1757 " }\n"
1758 " if(primitive < maxPrimitive){\n"
1759 " gl_PrimitiveTriangleIndicesEXT[primitive] = indices[primitive];\n"
1760 " }\n"
1761 "}\n";
1762
1763 return meshShader;
1764 }
1765 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
1766 {
1767 meshShader = "#version 450\n"
1768 "#extension GL_EXT_mesh_shader : enable\n"
1769 "\n"
1770 "${dataStruct}\n"
1771 "layout(local_size_x = 8, local_size_y = 4, local_size_z = 1) in;\n"
1772 "layout(lines) out;\n"
1773 "layout(max_vertices=16, max_primitives=16) out;\n"
1774 "\n"
1775 "layout(set = 0, binding = 0) buffer PerVertexData{ \n"
1776 " vec4 vertexBuffer[16];\n"
1777 "} pvd;\n"
1778 "layout (location=0) out ${typePrefix} data[]${typeSuffix};\n" +
1779 string(m_testParams.testWithInterpolation ?
1780 "layout(location = ${locInterp}) out ${typePrefix} dataInterp[]${typeSuffix};\n" :
1781 "") +
1782 string(m_testParams.testWithFlatInterpolation ?
1783 "layout(location = ${locFlat}) out ${typePrefix} dataFlat[]${typeSuffix};\n" :
1784 "") +
1785 "\n"
1786 "out gl_MeshPerVertexEXT \n"
1787 "{\n"
1788 " vec4 gl_Position;\n"
1789 " float gl_PointSize;\n"
1790 "} gl_MeshVerticesEXT[];\n"
1791 "\n"
1792 "void main()\n"
1793 "{\n"
1794 " uint maxVertex = 16;\n"
1795 " uint maxPrimitive = 8;\n"
1796 " SetMeshOutputsEXT(maxVertex, maxPrimitive);\n"
1797 " const uint vertex = gl_LocalInvocationIndex;\n"
1798 " const uint primitive = gl_LocalInvocationIndex;\n"
1799 " if (vertex < maxVertex)\n"
1800 " {\n"
1801 " gl_MeshVerticesEXT[vertex].gl_Position = pvd.vertexBuffer[vertex];\n"
1802 " gl_MeshVerticesEXT[vertex].gl_PointSize = 1.0;\n"
1803 " uint n = vertex + 1;\n"
1804 " data[vertex] = ${value};\n" +
1805 string(m_testParams.testWithInterpolation ? " dataInterp[vertex] = ${value};\n" : "") +
1806 string(m_testParams.testWithFlatInterpolation ? " dataFlat[vertex] = ${value};\n" : "") +
1807 " }\n"
1808 " if(primitive < maxPrimitive){\n"
1809 " gl_PrimitiveLineIndicesEXT[vertex] = uvec2(vertex * 2, vertex * 2 + 1u);\n"
1810 " }\n"
1811 "}\n";
1812
1813 return meshShader;
1814 }
1815 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
1816 {
1817 meshShader = "#version 450\n"
1818 "#extension GL_EXT_mesh_shader : enable\n"
1819 "\n"
1820 "${dataStruct}\n"
1821 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
1822 "layout(points) out;\n"
1823 "layout(max_vertices=1, max_primitives = 1) out;\n"
1824 "layout(set = 0, binding = 0) buffer PerVertexData{ \n"
1825 " vec4 vertexBuffer[64];\n"
1826 "} pvd;\n"
1827 "layout (location=0) out ${typePrefix} data[]${typeSuffix};\n" +
1828 string(m_testParams.testWithInterpolation ?
1829 "layout(location = ${locInterp}) out ${typePrefix} dataInterp[]${typeSuffix};\n" :
1830 "") +
1831 string(m_testParams.testWithFlatInterpolation ?
1832 "layout(location = ${locFlat}) out ${typePrefix} dataFlat[]${typeSuffix};\n" :
1833 "") +
1834 "\n"
1835 "out gl_MeshPerVertexEXT \n"
1836 "{\n"
1837 " vec4 gl_Position;\n"
1838 " float gl_PointSize;\n"
1839 "} gl_MeshVerticesEXT[];\n"
1840 "\n"
1841 "void main()\n"
1842 "{\n"
1843 " SetMeshOutputsEXT(1u, 1u);\n"
1844 " const uint vertex = gl_LocalInvocationIndex;\n"
1845 " const uint workGroupIndex = gl_NumWorkGroups.x * gl_NumWorkGroups.y * gl_WorkGroupID.z + "
1846 "gl_NumWorkGroups.x * gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
1847 " uint jobId = workGroupIndex + gl_LocalInvocationIndex;\n"
1848 " gl_MeshVerticesEXT[vertex].gl_Position = pvd.vertexBuffer[jobId];\n"
1849 " gl_MeshVerticesEXT[vertex].gl_PointSize = 1.0;\n"
1850 " gl_PrimitivePointIndicesEXT[vertex] = vertex;\n"
1851 " uint n = jobId + 1;\n"
1852 " data[vertex] = ${value};\n" +
1853 string(m_testParams.testWithInterpolation ? " dataInterp[vertex] = ${value};\n" : "") +
1854 string(m_testParams.testWithFlatInterpolation ? " dataFlat[vertex] = ${value};\n" : "") +
1855 "}\n";
1856
1857 return meshShader;
1858 }
1859 default:
1860 TCU_THROW(InternalError, "Unknown topology");
1861 }
1862 }
1863
initDataPrograms(SourceCollections & programCollection) const1864 void FragmentShadingBarycentricTestCase::initDataPrograms(SourceCollections &programCollection) const
1865 {
1866 map<string, string> attributes;
1867 const string primitiveType = string(getDataTypeName(m_testParams.dataType));
1868 const string dataStructType = m_testParams.aggregate == 1 ? "struct DataStruct {" + primitiveType + " q;};" : "";
1869 const string typePrefix = m_testParams.aggregate == 0 ? primitiveType :
1870 m_testParams.aggregate == 1 ? "DataStruct" :
1871 primitiveType;
1872 const string typeSuffix = m_testParams.aggregate == 0 ? "" :
1873 m_testParams.aggregate == 1 ? "" :
1874 "[" + de::toString(m_testParams.aggregate) + "]";
1875 const int scalarSize = getDataTypeScalarSize(m_testParams.dataType);
1876 const string scalarName = getDataTypeName(getDataTypeScalarType(m_testParams.dataType));
1877 const string vectoredInit = (scalarSize == 1) ? primitiveType + "(n)" :
1878 (scalarSize == 2) ? primitiveType + "(" + scalarName + "(n), " + scalarName + "(2*n))" :
1879 (scalarSize == 3) ? primitiveType + "(" + scalarName + "(n), " + scalarName +
1880 "(2*n), " + scalarName + "(4*n))" :
1881 (scalarSize == 4) ? primitiveType + "(" + scalarName + "(n), " + scalarName +
1882 "(2*n), " + scalarName + "(4*n), " + scalarName + "(8*n))" :
1883 "NOT IMPLEMENTED";
1884 const string value = m_testParams.aggregate == 0 ? vectoredInit :
1885 m_testParams.aggregate == 1 ? "DataStruct(" + vectoredInit + ")" :
1886 m_testParams.aggregate == 2 ? primitiveType + "[2](" + vectoredInit + ", " + scalarName +
1887 "(3)*" + vectoredInit + ")" :
1888 "NOT IMPLEMENTED";
1889 const size_t componentCount = getComponentCount(m_testParams);
1890 const string scalarized = (scalarSize == 1) ? "e${R}," :
1891 (scalarSize == 2) ? "e${R}.x,e${R}.y," :
1892 (scalarSize == 3) ? "e${R}.x,e${R}.y,e${R}.z," :
1893 (scalarSize == 4) ? "e${R}.x,e${R}.y,e${R}.z,e${R}.w," :
1894 "NOT IMPLEMENTED";
1895 const string deaggregated =
1896 m_testParams.aggregate == 0 ? replace(scalarized, "${R}", "${S}") :
1897 m_testParams.aggregate == 1 ? replace(scalarized, "${R}", "${S}.q") :
1898 m_testParams.aggregate == 2 ? replace(scalarized, "${R}", "${S}[0]") + replace(scalarized, "${R}", "${S}[1]") :
1899 "NOT IMPLEMENTED";
1900 const string unwrap =
1901 replace(deaggregated, "${S}", "A") + replace(deaggregated, "${S}", "B") + replace(deaggregated, "${S}", "C");
1902 const string expected = unwrap.substr(0, unwrap.size() - 1);
1903 const string arrived = replace(expected, "e", "v");
1904
1905 const string unwrapFlat = replace(deaggregated, "${S}", "FlatV");
1906 const string expectedFlat = unwrapFlat.substr(0, unwrapFlat.size() - 1);
1907 const string arrivedFlat = replace(expectedFlat, "e", "v");
1908
1909 const string unwraIntrp = replace(deaggregated, "${S}", "IntrpV");
1910 const string expectedIntrp = unwraIntrp.substr(0, unwraIntrp.size() - 1);
1911 const string arrivedIntrp = replace(expectedIntrp, "e", "v");
1912
1913 const string dynamicIndexing =
1914 m_testParams.dynamicIndexing ? "layout(push_constant) uniform PushConstant { uint n[3]; } pc;\n" : "";
1915 const string i0 = m_testParams.dynamicIndexing ? "pc.n[0]" : "0";
1916 const string i1 = m_testParams.dynamicIndexing ? "pc.n[1]" : "1";
1917 const string i2 = m_testParams.dynamicIndexing ? "pc.n[2]" : "2";
1918 const string primitiveId = getDataPrimitiveFormula();
1919 const string vertexFormula[] = {getDataVertexFormula(0), getDataVertexFormula(1), getDataVertexFormula(2)};
1920 string intrpFormula;
1921 for (size_t i = 0; i < std::max(static_cast<size_t>(1), m_testParams.aggregate); ++i)
1922 {
1923 string acc = m_testParams.aggregate > 1 ? "[" + de::toString(i) + "]" : "";
1924 if (m_testParams.aggregate == 1)
1925 acc += ".q";
1926 intrpFormula +=
1927 "eA" + acc + " * gl_BaryCoordEXT.x + eB" + acc + " * gl_BaryCoordEXT.y + eC" + acc + " * gl_BaryCoordEXT.z";
1928 if (i + 1 < m_testParams.aggregate)
1929 {
1930 intrpFormula += ", ";
1931 }
1932 }
1933
1934 const ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, SPIRV_VERSION_1_4, 0u);
1935
1936 const tcu::StringTemplate meshShader(m_testParams.useMeshShader ? generateDataMeshShader() : "");
1937
1938 const tcu::StringTemplate vertShader(
1939 string("#version 450\n"
1940 "#extension GL_EXT_fragment_shader_barycentric : require\n"
1941 "\n"
1942 "${dataStruct}\n"
1943 "\n"
1944 "layout(location = 0) in vec4 in_position;\n"
1945 "layout(location = 0) out ${typePrefix} data${typeSuffix};\n" +
1946 string(m_testParams.testWithInterpolation ?
1947 "layout(location = ${locInterp}) out ${typePrefix} dataInterp${typeSuffix};\n" :
1948 "") +
1949 string(m_testParams.testWithFlatInterpolation ?
1950 "layout(location = ${locFlat}) out ${typePrefix} dataFlat${typeSuffix};\n" :
1951 "") +
1952 "\n"
1953 "out gl_PerVertex\n"
1954 "{\n"
1955 " vec4 gl_Position;\n"
1956 " float gl_PointSize;\n"
1957 "};\n"
1958 "\n"
1959 "void main()\n"
1960 "{\n"
1961 " const int n = gl_VertexIndex + 1;\n"
1962 " data = ${value};\n" +
1963 string(m_testParams.testWithInterpolation ? " dataInterp = ${value};\n" : "") +
1964 string(m_testParams.testWithFlatInterpolation ? " dataFlat = ${value};\n" : "") +
1965 " gl_PointSize = 1.0;\n"
1966 " gl_Position = in_position;\n"
1967 "}\n"));
1968 const tcu::StringTemplate fragShader(
1969 string("#version 450\n") +
1970 "#extension GL_EXT_fragment_shader_barycentric : require\n"
1971 "\n"
1972 "${dataStruct}\n"
1973 "\n"
1974 "${dynamicIndexing}\n" +
1975 string(m_testParams.testWithInterpolation ?
1976 "layout(location = ${locInterp}) in ${typePrefix} dataIntrp${typeSuffix};\n" :
1977 "") +
1978 string(m_testParams.testWithFlatInterpolation ?
1979 "layout(location = ${locFlat}) flat in ${typePrefix} dataFlat${typeSuffix};\n" :
1980 "") +
1981 "layout(location = 0) out uvec4 out_color;\n"
1982 "\n" +
1983 string(((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
1984 (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
1985 "struct InDataStruct {uint idx; ${typePrefix} data${typeSuffix};};\n"
1986 "layout(location = 0) pervertexEXT in InDataStruct inParam[];\n"
1987 "void getData(uint i, out ${typePrefix} ds${typeSuffix})\n"
1988 "{\n"
1989 " for(uint k = 0; k < 3; k++)\n"
1990 " {\n"
1991 " if (inParam[k].idx == i)\n"
1992 " ds = " +
1993 string(m_testParams.aggregate == 2 ?
1994 "${typePrefix}${typeSuffix}(inParam[k].data[0],inParam[k].data[1])" :
1995 "inParam[k].data") +
1996 ";\n"
1997 " }\n"
1998 "}\n" :
1999 "layout(location = 0) pervertexEXT in ${typePrefix} data[]${typeSuffix};\n") +
2000 "void main()\n"
2001 "{\n"
2002 " const int w = " +
2003 de::toString(m_testParams.width) +
2004 ";\n"
2005 " const int h = " +
2006 de::toString(m_testParams.height) +
2007 ";\n"
2008 " const int x = int(gl_FragCoord.x - 0.5f);\n"
2009 " const int y = int(gl_FragCoord.y - 0.5f);\n"
2010 " const int p = ${primitiveId};\n"
2011 " const bool even = (p%2 == 0);\n"
2012 "\n"
2013 " ${typePrefix} eA${typeSuffix}; { const int n = 1 + ${vertexFormula0}; eA = ${value}; }\n"
2014 " ${typePrefix} eB${typeSuffix}; { const int n = 1 + ${vertexFormula1}; eB = ${value}; }\n"
2015 " ${typePrefix} eC${typeSuffix}; { const int n = 1 + ${vertexFormula2}; eC = ${value}; }\n" +
2016 "\n"
2017 " ${scalarName} e[${componentCount}] = { ${expected} };\n" +
2018 string(
2019 m_testParams.testWithInterpolation ?
2020 " ${typePrefix} eIntrpV${typeSuffix}; {eIntrpV = ${typePrefix}${typeSuffix}(${intrpFormula}); }\n" :
2021 "") +
2022 string(m_testParams.testWithInterpolation ?
2023 " ${scalarName} eIntrp[${componentCount} / 3] = { ${expectedIntrp} };\n" :
2024 "") +
2025 string(m_testParams.testWithFlatInterpolation ? " ${typePrefix} eFlatV${typeSuffix}; { const int n = 1 + "
2026 "${vertexFormulaFlat}; eFlatV = ${value}; }\n" :
2027 "") +
2028 string(m_testParams.testWithFlatInterpolation ?
2029 " ${scalarName} eFlat[${componentCount} / 3] = { ${expectedFlat} };\n" :
2030 "") +
2031 "\n" +
2032 string(
2033 ((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
2034 (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
2035 " ${typePrefix} vA${typeSuffix}; { getData(${i0}, vA); }\n"
2036 " ${typePrefix} vB${typeSuffix}; { getData(${i1}, vB); }\n"
2037 " ${typePrefix} vC${typeSuffix}; { getData(${i2}, vC); }\n" :
2038 " ${typePrefix} vA${typeSuffix}; { vA = " +
2039 string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(data[${i0}][0],data[${i0}][1])" :
2040 "data[${i0}]") +
2041 "; }\n"
2042 " ${typePrefix} vB${typeSuffix}; { vB = " +
2043 string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(data[${i1}][0],data[${i1}][1])" :
2044 "data[${i1}]") +
2045 "; }\n"
2046 " ${typePrefix} vC${typeSuffix}; { vC = " +
2047 string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(data[${i2}][0],data[${i2}][1])" :
2048 "data[${i2}]") +
2049 "; }\n" +
2050 string(m_testParams.testWithInterpolation ?
2051 " ${typePrefix} vIntrpV${typeSuffix}; { vIntrpV = " +
2052 string(m_testParams.aggregate == 2 ?
2053 "${typePrefix}${typeSuffix}(dataIntrp[0],dataIntrp[1])" :
2054 "dataIntrp") +
2055 "; }\n" :
2056 "") +
2057 string(m_testParams.testWithInterpolation ?
2058 " ${scalarName} vIntrp[${componentCount} / 3] = { ${arrivedIntrp} };\n" :
2059 "") +
2060 string(m_testParams.testWithFlatInterpolation ?
2061 " ${typePrefix} vFlatV${typeSuffix}; { vFlatV = " +
2062 string(m_testParams.aggregate == 2 ?
2063 "${typePrefix}${typeSuffix}(dataFlat[0],dataFlat[1])" :
2064 "dataFlat") +
2065 "; }\n" :
2066 "") +
2067 string(m_testParams.testWithFlatInterpolation ?
2068 " ${scalarName} vFlat[${componentCount} / 3] = { ${arrivedFlat}};\n" :
2069 "")) +
2070 "\n"
2071 " ${scalarName} v[${componentCount}] = { ${arrived} };\n" +
2072 " uvec4 mask = uvec4(0);\n"
2073 "\n"
2074 " for (int i = 0; i<${componentCount}; i++)\n"
2075 " if (e[i] == v[i])\n"
2076 " mask.x = mask.x | (1<<i);\n" +
2077 string(m_testParams.testWithInterpolation ? " for (int i = 0; i<${componentCount} / 3; i++)\n" : "") +
2078 string(m_testParams.testWithInterpolation ? " if (abs(eIntrp[i] - vIntrp[i]) < 0.001)\n" : "") +
2079 string(m_testParams.testWithInterpolation ? " mask.y = mask.y | (1<<i);\n" : "") +
2080 string(m_testParams.testWithFlatInterpolation ? " for (int i = 0; i<${componentCount} / 3; i++)\n" : "") +
2081 string(m_testParams.testWithFlatInterpolation ? " if (eFlat[i] == vFlat[i])\n" : "") +
2082 string(m_testParams.testWithFlatInterpolation ? " mask.z = mask.z | (1<<i);\n" : "") +
2083 " out_color = mask;\n"
2084 "}\n");
2085
2086 attributes["typePrefix"] = typePrefix;
2087 attributes["typeSuffix"] = typeSuffix;
2088 attributes["value"] = value;
2089 attributes["componentCount"] = de::toString(componentCount);
2090 attributes["expected"] = expected;
2091 attributes["arrived"] = arrived;
2092 attributes["expectedIntrp"] = expectedIntrp;
2093 attributes["arrivedIntrp"] = arrivedIntrp;
2094 attributes["expectedFlat"] = expectedFlat;
2095 attributes["arrivedFlat"] = arrivedFlat;
2096 attributes["scalarName"] = scalarName;
2097 attributes["dataStruct"] = dataStructType;
2098 attributes["dynamicIndexing"] = dynamicIndexing;
2099 attributes["primitiveId"] = primitiveId;
2100 attributes["i0"] = i0;
2101 attributes["i1"] = i1;
2102 attributes["i2"] = i2;
2103 attributes["vertexFormula0"] = vertexFormula[0];
2104 attributes["vertexFormula1"] = vertexFormula[1];
2105 attributes["vertexFormula2"] = vertexFormula[2];
2106 attributes["intrpFormula"] = intrpFormula;
2107
2108 {
2109 size_t locationsPerInput = (m_testParams.aggregate > 0u ? m_testParams.aggregate : 1u);
2110
2111 if (glu::isDataTypeDoubleOrDVec(m_testParams.dataType))
2112 {
2113 locationsPerInput *= 2;
2114 }
2115
2116 size_t usedLocations = 0u;
2117 if (m_testParams.testWithInterpolation)
2118 {
2119 usedLocations += locationsPerInput;
2120 attributes["locInterp"] = de::toString(usedLocations);
2121 }
2122 if (m_testParams.testWithFlatInterpolation)
2123 {
2124 usedLocations += locationsPerInput;
2125 attributes["locFlat"] = de::toString(usedLocations);
2126 }
2127 }
2128
2129 if (m_testParams.testWithFlatInterpolation)
2130 {
2131 attributes["vertexFormulaFlat"] = getDataProvokingVertexFormula();
2132 }
2133
2134 if (isPrimitiveTopologyLine(m_testParams.topology))
2135 {
2136 DE_ASSERT(vertexFormula[2] == vertexFormula[1]);
2137 }
2138 else if (isPrimitiveTopologyPoint(m_testParams.topology))
2139 {
2140 DE_ASSERT(vertexFormula[2] == vertexFormula[1] && vertexFormula[1] == vertexFormula[0]);
2141 }
2142
2143 if (m_testParams.useMeshShader)
2144 programCollection.glslSources.add("mesh") << glu::MeshSource(meshShader.specialize(attributes)) << buildOptions;
2145 else
2146 programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(attributes));
2147
2148 programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(attributes));
2149
2150 if (m_testParams.provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
2151 {
2152 const bool provokingVertexLast = false;
2153
2154 attributes["vertexFormula0"] = getDataVertexFormula(0, &provokingVertexLast);
2155 attributes["vertexFormula1"] = getDataVertexFormula(1, &provokingVertexLast);
2156 attributes["vertexFormula2"] = getDataVertexFormula(2, &provokingVertexLast);
2157
2158 if (m_testParams.useMeshShader)
2159 programCollection.glslSources.add("mesh-forced")
2160 << glu::VertexSource(meshShader.specialize(attributes)) << buildOptions;
2161 else
2162 programCollection.glslSources.add("vert-forced") << glu::VertexSource(vertShader.specialize(attributes));
2163
2164 programCollection.glslSources.add("frag-forced") << glu::FragmentSource(fragShader.specialize(attributes));
2165 }
2166
2167 if (m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER)
2168 initMiscDataTessPrograms(programCollection, attributes);
2169 else if (m_testParams.testSubtype == TEST_SUBTYPE_GEOMETRY_SHADER)
2170 initMiscDataGeomPrograms(programCollection, attributes);
2171 else if (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)
2172 {
2173 initMiscDataTessPrograms(programCollection, attributes);
2174 initMiscDataGeomPrograms(programCollection, attributes);
2175 }
2176 }
2177
initMiscDataPrograms(SourceCollections & programCollection) const2178 void FragmentShadingBarycentricTestCase::initMiscDataPrograms(SourceCollections &programCollection) const
2179 {
2180 const std::string vertShader("#version 450\n"
2181 "#extension GL_EXT_fragment_shader_barycentric : require\n"
2182 "\n"
2183 "layout(location = 0) in vec4 in_position;\n"
2184 "layout(location = 0) out uvec2 dataA;\n"
2185 "layout(location = 1) out uvec2 dataB;\n"
2186 "void main()\n"
2187 "{\n"
2188 // we will draw two triangles and we need to convert dataA for
2189 // second triangle to 0-2 range to simplify verification
2190 " dataA = uvec2(mod(gl_VertexIndex, 3));\n"
2191 " dataB = uvec2(7);\n"
2192 " gl_Position = in_position;\n"
2193 "}\n");
2194 const std::string fragShader("#version 450\n"
2195 "#extension GL_EXT_fragment_shader_barycentric : require\n"
2196 "layout(location = 0) pervertexEXT in uvec2 dataA[];\n"
2197 "layout(location = 1) flat in uvec2 dataB;\n"
2198 "layout(location = 0) out uvec4 out_color;\n"
2199 "void main()\n"
2200 "{\n"
2201 // make sure that PerVertex decoration is only applied to location 0
2202 // and that the location 1 isn't compacted/remapped to location 0
2203 // by adding all values and making sure the result is 10
2204 " out_color = uvec4(dataA[0].y + dataA[1].x + dataA[2].y + dataB.x);\n"
2205 "}\n");
2206
2207 programCollection.glslSources.add("vert") << glu::VertexSource(vertShader);
2208 programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader);
2209 }
2210
initMiscDataTessPrograms(SourceCollections & programCollection,map<string,string> & attributes) const2211 void FragmentShadingBarycentricTestCase::initMiscDataTessPrograms(SourceCollections &programCollection,
2212 map<string, string> &attributes) const
2213 {
2214 // Tessellation control
2215 const tcu::StringTemplate tesc(
2216 string("#version 450\n"
2217 "#extension GL_EXT_tessellation_shader : require\n"
2218 "layout (vertices=6) out;\n"
2219 "in gl_PerVertex\n"
2220 "{\n"
2221 " vec4 gl_Position;\n"
2222 " float gl_PointSize;\n"
2223 "} gl_in[];\n"
2224 "out gl_PerVertex\n"
2225 "{\n"
2226 " vec4 gl_Position;\n"
2227 " float gl_PointSize;\n"
2228 "} gl_out[];\n"
2229 "\n"
2230 "${dataStruct}\n"
2231 "\n"
2232 "layout (location=0) in ${typePrefix} inData[]${typeSuffix};\n"
2233 "layout (location=0) out ${typePrefix} outData[]${typeSuffix};\n"
2234 "\n"
2235 "void main (void)\n"
2236 "{\n"
2237 " if (gl_InvocationID == 0)\n"
2238 " {\n"
2239 " gl_TessLevelInner[0] = 1.0;\n"
2240 " gl_TessLevelInner[1] = 1.0;\n"
2241 " gl_TessLevelOuter[0] = 1.0;\n"
2242 " gl_TessLevelOuter[1] = 1.0;\n"
2243 " gl_TessLevelOuter[2] = 1.0;\n"
2244 " gl_TessLevelOuter[3] = 1.0;\n"
2245 " }\n"
2246 " outData[gl_InvocationID] = inData[gl_InvocationID];\n"
2247 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
2248 "}\n"));
2249 programCollection.glslSources.add("tess_ctrl") << glu::TessellationControlSource(tesc.specialize(attributes));
2250
2251 // Tessellation evaluation shader
2252 const tcu::StringTemplate tese(
2253 string("#version 450\n"
2254 "#extension GL_EXT_tessellation_shader : require\n"
2255 "layout (triangles) in;\n"
2256 "in gl_PerVertex\n"
2257 "{\n"
2258 " vec4 gl_Position;\n"
2259 " float gl_PointSize;\n"
2260 "} gl_in[];\n"
2261 "out gl_PerVertex\n"
2262 "{\n"
2263 " vec4 gl_Position;\n"
2264 " float gl_PointSize;\n"
2265 "};\n"
2266 "\n"
2267 "${dataStruct}\n"
2268 "\n"
2269 "layout (location=0) in ${typePrefix} inData[]${typeSuffix};\n"
2270 "struct OutDataStruct {uint idx; ${typePrefix} data${typeSuffix};};\n"
2271 "layout (location=0) flat out OutDataStruct outParam;\n"
2272 "\n"
2273 "void main (void)\n"
2274 "{\n"
2275 " gl_Position = (gl_TessCoord.x * gl_in[0].gl_Position) +\n"
2276 " (gl_TessCoord.y * gl_in[1].gl_Position) +\n"
2277 " (gl_TessCoord.z * gl_in[2].gl_Position);\n"
2278 " if (gl_TessCoord.xyz == vec3(0.0,1.0,0.0)) {outParam.idx = ${i2}; outParam.data = " +
2279 string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(inData[${i2}][0],inData[${i2}][1])" :
2280 "inData[${i2}]") +
2281 "; }\n"
2282 " else if (gl_TessCoord.xyz == vec3(1.0,0.0,0.0)) {outParam.idx = ${i0}; outParam.data = " +
2283 string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(inData[${i0}][0],inData[${i0}][1])" :
2284 "inData[${i0}]") +
2285 "; }\n"
2286 " else if (gl_TessCoord.xyz == vec3(0.0,0.0,1.0)) {outParam.idx = ${i1}; outParam.data = " +
2287 string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(inData[${i1}][0],inData[${i1}][1])" :
2288 "inData[${i1}]") +
2289 "; }\n"
2290 "}\n"));
2291 programCollection.glslSources.add("tess_eval") << glu::TessellationEvaluationSource(tese.specialize(attributes));
2292 }
2293
initMiscDataGeomPrograms(SourceCollections & programCollection,map<string,string> & attributes) const2294 void FragmentShadingBarycentricTestCase::initMiscDataGeomPrograms(SourceCollections &programCollection,
2295 map<string, string> &attributes) const
2296 {
2297 // Geometry shader
2298 const tcu::StringTemplate geom(string("#version 460\n"
2299 "\n"
2300 "layout (triangles) in;\n"
2301 "layout (triangle_strip, max_vertices=3) out;\n"
2302 "in gl_PerVertex\n"
2303 "{\n"
2304 " vec4 gl_Position;\n"
2305 " float gl_PointSize;\n"
2306 "} gl_in[3];\n"
2307 "out gl_PerVertex\n"
2308 "{\n"
2309 " vec4 gl_Position;\n"
2310 " float gl_PointSize;\n"
2311 "};\n"
2312 "\n"
2313 "${dataStruct}\n"
2314 "\n") +
2315 string(((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
2316 (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
2317 "struct InOutDataStruct {uint idx; ${typePrefix} data${typeSuffix};};\n"
2318 "layout(location = 0) in InOutDataStruct inParam[];\n" :
2319 "layout (location=0) in ${typePrefix} inData[]${typeSuffix};\n") +
2320 string(((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
2321 (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
2322 "layout (location=0) flat out InOutDataStruct outParam;\n" :
2323 "layout (location=0) out ${typePrefix} outData${typeSuffix};\n") +
2324 string("\n"
2325 "void main ()\n"
2326 "{\n"
2327 " gl_Position = gl_in[0].gl_Position;\n") +
2328 string(((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
2329 (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
2330 " outParam = inParam[${i0}];\n" :
2331 " outData = inData[${i0}];\n") +
2332 string(" EmitVertex();\n"
2333
2334 " gl_Position = gl_in[1].gl_Position;\n") +
2335 string(((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
2336 (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
2337 " outParam = inParam[${i1}];\n" :
2338 " outData = inData[${i1}];\n") +
2339 string(" EmitVertex();\n"
2340
2341 " gl_Position = gl_in[2].gl_Position;\n") +
2342 string(((m_testParams.testSubtype == TEST_SUBTYPE_TESS_SHADER) ||
2343 (m_testParams.testSubtype == TEST_SUBTYPE_TESSGEOM_SHADER)) ?
2344 " outParam = inParam[${i2}];\n" :
2345 " outData = inData[${i2}];\n") +
2346 string(" EmitVertex();\n"
2347 "}\n"));
2348 programCollection.glslSources.add("geom") << glu::GeometrySource(geom.specialize(attributes));
2349 }
2350
generateWeightMeshShader(void) const2351 string FragmentShadingBarycentricTestCase::generateWeightMeshShader(void) const
2352 {
2353
2354 string meshShader;
2355
2356 switch (m_testParams.topology)
2357 {
2358 case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2359 {
2360 meshShader =
2361 "#version 450\n"
2362 "#extension GL_EXT_mesh_shader : enable\n"
2363 "\n"
2364 "layout(local_size_x = 8, local_size_y = 4, local_size_z = 1) in;\n"
2365 "layout(triangles) out;\n"
2366 "layout(max_vertices=256, max_primitives=256) out;\n"
2367 "layout(push_constant) uniform PushConstant { mat4 mvp; } pc;\n"
2368 "\n"
2369 "layout(set = 0, binding = 0) buffer PerVertexData{ \n"
2370 " vec4 vertexBuffer[12];\n"
2371 "} pvd;\n"
2372 "layout (location=0) out vec3 outColor[];\n"
2373 "\n"
2374 "void main ()\n"
2375 "{\n"
2376 " uint maxVertex = 6;\n"
2377 " uint maxPrimitive = 2;\n"
2378 " SetMeshOutputsEXT(maxVertex, maxPrimitive);\n"
2379 " const uint vertex = gl_LocalInvocationIndex;\n"
2380 " const uint primitive = gl_LocalInvocationIndex;\n"
2381 " const uvec3 indices[2] = uvec3[](\n"
2382 " uvec3(0, 1, 2),\n"
2383 " uvec3(3, 4, 5)\n"
2384 " );\n"
2385 " if (vertex < maxVertex)\n"
2386 " {\n"
2387 " gl_MeshVerticesEXT[vertex].gl_Position = transpose(pc.mvp) * pvd.vertexBuffer[vertex*2];\n"
2388 " outColor[vertex] = pvd.vertexBuffer[vertex*2+1].xyz;\n"
2389 " }\n"
2390 " if(primitive < maxPrimitive){\n"
2391 " gl_PrimitiveTriangleIndicesEXT[primitive] = indices[primitive];\n"
2392 " }\n"
2393 "}\n";
2394
2395 return meshShader;
2396 }
2397 case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
2398 {
2399 meshShader =
2400 "#version 450\n"
2401 "#extension GL_EXT_mesh_shader : enable\n"
2402 "\n"
2403 "layout(local_size_x = 8, local_size_y = 4, local_size_z = 1) in;\n"
2404 "layout(lines) out;\n"
2405 "layout(max_vertices=256, max_primitives=256) out;\n"
2406 "layout(push_constant) uniform PushConstant { mat4 mvp; } pc;\n"
2407 "\n"
2408 "layout(set = 0, binding = 0) buffer PerVertexData{ \n"
2409 " vec4 vertexBuffer[512];\n"
2410 "} pvd;\n"
2411 "layout (location=0) out vec3 outColor[];\n"
2412 "\n"
2413 "void main ()\n"
2414 "{\n"
2415 " uint maxVertex = 256;\n"
2416 " uint maxPrimitive = 128;\n"
2417 " SetMeshOutputsEXT(maxVertex, maxPrimitive);\n"
2418 " uint iterations = max(maxVertex, maxPrimitive) / (8 * 4 * 1);\n"
2419 " for (int iteration = 0; iteration < iterations; ++iteration)\n"
2420 " {\n"
2421 " const uint vertex = gl_LocalInvocationIndex * iterations + iteration;\n"
2422 " const uint primitive = gl_LocalInvocationIndex * iterations + iteration;\n"
2423 " if (vertex < maxVertex)\n"
2424 " {\n"
2425 " gl_MeshVerticesEXT[vertex].gl_Position = transpose(pc.mvp) * pvd.vertexBuffer[vertex*2];\n"
2426 " outColor[vertex] = pvd.vertexBuffer[vertex*2+1].xyz;\n"
2427 " }\n"
2428 " if(primitive < maxPrimitive){\n"
2429 " gl_PrimitiveLineIndicesEXT[primitive] = uvec2(primitive*2, primitive*2+1);\n"
2430 " }\n"
2431 " }\n"
2432 "}\n";
2433
2434 return meshShader;
2435 }
2436 case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
2437 {
2438 meshShader = "#version 450\n"
2439 "#extension GL_EXT_mesh_shader : enable\n"
2440 "\n"
2441 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
2442 "layout(points) out;\n"
2443 "layout(max_vertices=1, max_primitives = 1) out;\n"
2444 "layout(push_constant) uniform PushConstant { mat4 mvp; } pc;\n"
2445 "\n"
2446 "layout(set = 0, binding = 0) buffer PerVertexData{ \n"
2447 " vec4 vertexBuffer[32768];\n"
2448 "} pvd;\n"
2449 "layout (location=0) out vec3 outColor[];\n"
2450 "\n"
2451 "void main ()\n"
2452 "{\n"
2453 " uint maxVertex = 1;\n"
2454 " uint maxPrimitive = 1;\n"
2455 " SetMeshOutputsEXT(maxVertex, maxPrimitive);\n"
2456 " const uint vertex = gl_LocalInvocationIndex;\n"
2457 " const uint primitive = gl_LocalInvocationIndex;\n"
2458 " const uint workGroupIndex = gl_NumWorkGroups.x * gl_NumWorkGroups.y * gl_WorkGroupID.z + "
2459 "gl_NumWorkGroups.x * gl_WorkGroupID.y + gl_WorkGroupID.x;\n"
2460 " uint jobId = workGroupIndex + gl_LocalInvocationIndex;\n"
2461 " gl_MeshVerticesEXT[vertex].gl_Position = transpose(pc.mvp) * pvd.vertexBuffer[jobId*2];\n"
2462 " outColor[vertex] = pvd.vertexBuffer[jobId*2+1].xyz;\n"
2463 " gl_PrimitivePointIndicesEXT[primitive] = primitive;\n"
2464 "}\n";
2465
2466 return meshShader;
2467 }
2468 default:
2469 TCU_THROW(InternalError, "Unknown topology");
2470 }
2471 }
2472
initWeightPrograms(SourceCollections & programCollection) const2473 void FragmentShadingBarycentricTestCase::initWeightPrograms(SourceCollections &programCollection) const
2474 {
2475 const string baryCoordVariable = m_testParams.perspective ? "BaryCoord" : "BaryCoordNoPersp";
2476 const string declspecRef = m_testParams.perspective ? "smooth" : "noperspective";
2477 const ShaderBuildOptions buildOptions(programCollection.usedVulkanVersion, SPIRV_VERSION_1_4, 0u);
2478
2479 string meshShader;
2480
2481 if (m_testParams.useMeshShader)
2482 meshShader = generateWeightMeshShader();
2483
2484 const string vertShader = "#version 450\n"
2485 "\n"
2486 "layout(location = 0) in vec4 in_position;\n"
2487 "layout(location = 1) in vec4 in_color;\n"
2488 "layout(location = 0) out vec3 color;\n"
2489 "layout(push_constant) uniform PushConstant { mat4 mvp; } pc;\n"
2490 "\n"
2491 "void main()\n"
2492 "{\n"
2493 " color = in_color.xyz;\n"
2494 " gl_Position = transpose(pc.mvp) * in_position;\n"
2495 " gl_PointSize = 1.0;\n"
2496 "}\n";
2497 const tcu::StringTemplate fragShaderReference("#version 450\n"
2498 "\n"
2499 "layout(location = 0) ${glslDeclspecRef} in vec3 in_color;\n"
2500 "layout(location = 0) out vec4 out_color;\n"
2501 "\n"
2502 "void main()\n"
2503 "{\n"
2504 " out_color = vec4(in_color, 1.0f);\n"
2505 "}\n");
2506 const tcu::StringTemplate fragShaderTestGLSL(
2507 "#version 450\n"
2508 "#extension GL_EXT_fragment_shader_barycentric : require\n"
2509 "\n"
2510 "layout(location = 0) pervertexEXT in vec3 in_color[];\n"
2511 "layout(location = 0) out vec4 out_color;\n"
2512 "\n"
2513 "void main()\n"
2514 "{\n"
2515 " vec3 bc = ${glslFormulaeTest};\n"
2516 " out_color = vec4(in_color[0] * bc.x + in_color[1] * bc.y + in_color[2] * bc.z, 1.0f);\n"
2517 "}\n");
2518
2519 // it is not possible to add centroid/sample qualifiers to gl_BaryCoordEXT/gl_BaryCoordNoPerspEXT
2520 // but it is possible to do this with SPIR-V - code below is a slightly modified version of fragShaderTestGLSL
2521 const tcu::StringTemplate fragShaderTestSPIRV("OpCapability Shader\n"
2522 "OpCapability FragmentBarycentricKHR\n"
2523 "${spirvAdditionalCapabilities}"
2524 "OpExtension \"SPV_KHR_fragment_shader_barycentric\"\n"
2525 "%1 = OpExtInstImport \"GLSL.std.450\"\n"
2526 "OpMemoryModel Logical GLSL450\n"
2527 "OpEntryPoint Fragment %4 \"main\" %var_BaryCoord %15 %20\n"
2528 "OpExecutionMode %4 OriginUpperLeft\n"
2529 "OpDecorate %var_BaryCoord BuiltIn ${spirvBaryCoordVariable}\n"
2530 "OpDecorate %var_BaryCoord ${spirvBaryCoordDecoration}\n"
2531 "OpDecorate %15 Location 0\n"
2532 "OpDecorate %20 Location 0\n"
2533 "OpDecorate %20 PerVertexKHR\n"
2534 "%2 = OpTypeVoid\n"
2535 "%3 = OpTypeFunction %2\n"
2536 "%6 = OpTypeFloat 32\n"
2537 "%7 = OpTypeVector %6 3\n"
2538 "%8 = OpTypePointer Function %7\n"
2539 "%10 = OpTypePointer Input %7\n"
2540 "%var_BaryCoord = OpVariable %10 Input\n"
2541 "%13 = OpTypeVector %6 4\n"
2542 "%14 = OpTypePointer Output %13\n"
2543 "%15 = OpVariable %14 Output\n"
2544 "%16 = OpTypeInt 32 0\n"
2545 "%17 = OpConstant %16 3\n"
2546 "%18 = OpTypeArray %7 %17\n"
2547 "%19 = OpTypePointer Input %18\n"
2548 "%20 = OpVariable %19 Input\n"
2549 "%21 = OpTypeInt 32 1\n"
2550 "%22 = OpConstant %21 0\n"
2551 "%25 = OpConstant %16 0\n"
2552 "%26 = OpTypePointer Function %6\n"
2553 "%30 = OpConstant %21 1\n"
2554 "%33 = OpConstant %16 1\n"
2555 "%38 = OpConstant %21 2\n"
2556 "%41 = OpConstant %16 2\n"
2557 "%46 = OpConstant %6 1\n"
2558 "%4 = OpFunction %2 None %3\n"
2559 "%5 = OpLabel\n"
2560 "%9 = OpVariable %8 Function\n"
2561 "%12 = OpLoad %7 %var_BaryCoord\n"
2562 "OpStore %9 %12\n"
2563 "%23 = OpAccessChain %10 %20 %22\n"
2564 "%24 = OpLoad %7 %23\n"
2565 "%27 = OpAccessChain %26 %9 %25\n"
2566 "%28 = OpLoad %6 %27\n"
2567 "%29 = OpVectorTimesScalar %7 %24 %28\n"
2568 "%31 = OpAccessChain %10 %20 %30\n"
2569 "%32 = OpLoad %7 %31\n"
2570 "%34 = OpAccessChain %26 %9 %33\n"
2571 "%35 = OpLoad %6 %34\n"
2572 "%36 = OpVectorTimesScalar %7 %32 %35\n"
2573 "%37 = OpFAdd %7 %29 %36\n"
2574 "%39 = OpAccessChain %10 %20 %38\n"
2575 "%40 = OpLoad %7 %39\n"
2576 "%42 = OpAccessChain %26 %9 %41\n"
2577 "%43 = OpLoad %6 %42\n"
2578 "%44 = OpVectorTimesScalar %7 %40 %43\n"
2579 "%45 = OpFAdd %7 %37 %44\n"
2580 "%47 = OpCompositeExtract %6 %45 0\n"
2581 "%48 = OpCompositeExtract %6 %45 1\n"
2582 "%49 = OpCompositeExtract %6 %45 2\n"
2583 "%50 = OpCompositeConstruct %13 %47 %48 %49 %46\n"
2584 "OpStore %15 %50\n"
2585 "OpReturn\n"
2586 "OpFunctionEnd\n");
2587
2588 // use single specialization map for test and reference fragment shaders
2589 // as well as for spirv version of test shader
2590 map<string, string> attributes{{"glslDeclspecRef", declspecRef}};
2591
2592 switch (m_testParams.testSubtype)
2593 {
2594 case TEST_SUBTYPE_MSAA_INTERPOLATE_AT_CENTROID:
2595 attributes["glslFormulaeTest"] = std::string("interpolateAtCentroid(gl_") + baryCoordVariable + "EXT)";
2596 attributes["glslDeclspecRef"] += " centroid";
2597 break;
2598 case TEST_SUBTYPE_MSAA_INTERPOLATE_AT_SAMPLE:
2599 attributes["glslFormulaeTest"] =
2600 std::string("interpolateAtSample(gl_") + baryCoordVariable + "EXT, gl_SampleID)";
2601 attributes["glslDeclspecRef"] += " sample";
2602 break;
2603 case TEST_SUBTYPE_MSAA_INTERPOLATE_AT_OFFSET:
2604 attributes["glslFormulaeTest"] =
2605 std::string("interpolateAtOffset(gl_") + baryCoordVariable + "EXT, vec2(gl_SamplePosition - vec2(0.5)))";
2606 attributes["glslDeclspecRef"] += " sample";
2607 break;
2608 case TEST_SUBTYPE_MSAA_CENTROID_QUALIFIER:
2609 attributes["spirvBaryCoordVariable"] = baryCoordVariable + "KHR";
2610 attributes["spirvBaryCoordDecoration"] = "Centroid";
2611 attributes["spirvAdditionalCapabilities"] = "";
2612 attributes["glslDeclspecRef"] += " centroid";
2613 break;
2614 case TEST_SUBTYPE_MSAA_SAMPLE_QUALIFIER:
2615 attributes["spirvBaryCoordVariable"] = baryCoordVariable + "KHR";
2616 attributes["spirvBaryCoordDecoration"] = "Sample";
2617 attributes["spirvAdditionalCapabilities"] = "OpCapability SampleRateShading\n";
2618 attributes["glslDeclspecRef"] += " sample";
2619 break;
2620 default:
2621 attributes["glslFormulaeTest"] = std::string("gl_") + baryCoordVariable + "EXT";
2622 break;
2623 }
2624
2625 if (m_testParams.useMeshShader)
2626 programCollection.glslSources.add("mesh") << glu::MeshSource(meshShader) << buildOptions;
2627 else
2628 programCollection.glslSources.add("vert") << glu::VertexSource(vertShader);
2629
2630 programCollection.glslSources.add("frag_reference")
2631 << glu::FragmentSource(fragShaderReference.specialize(attributes));
2632
2633 // use "spirvBaryCoordVariable" key to determine if we should use glsl or spir-v version of test shader
2634 if (attributes.count("spirvBaryCoordVariable"))
2635 programCollection.spirvAsmSources.add("frag_test") << fragShaderTestSPIRV.specialize(attributes);
2636 else
2637 programCollection.glslSources.add("frag_test")
2638 << glu::FragmentSource(fragShaderTestGLSL.specialize(attributes));
2639 }
2640 } // namespace
2641
createTests(tcu::TestContext & testCtx,const std::string & name)2642 tcu::TestCaseGroup *createTests(tcu::TestContext &testCtx, const std::string &name)
2643 {
2644 const bool notused = false;
2645 MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, name.c_str()));
2646 // Tests using graphics pipeline libraries
2647 MovePtr<tcu::TestCaseGroup> libGroup(new tcu::TestCaseGroup(testCtx, "pipeline_library"));
2648 // Tests using graphics pipeline libraries with fast linking
2649 MovePtr<tcu::TestCaseGroup> fastLinkGroup(new tcu::TestCaseGroup(testCtx, "fast_linked_library"));
2650
2651 const struct
2652 {
2653 PipelineConstructionType constructionType;
2654 tcu::TestCaseGroup *testGroup;
2655 } constructionTypeCases[] = {
2656 {PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC, group.get()},
2657 {PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY, libGroup.get()},
2658 {PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY, fastLinkGroup.get()},
2659 };
2660
2661 const struct PrimitiveTestSpec
2662 {
2663 VkPrimitiveTopology topology;
2664 const char *name;
2665 } topologies[] = {
2666 {VK_PRIMITIVE_TOPOLOGY_POINT_LIST, "point_list"},
2667 {VK_PRIMITIVE_TOPOLOGY_LINE_LIST, "line_list"},
2668 {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP, "line_strip"},
2669 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangle_list"},
2670 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip"},
2671 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, "triangle_fan"},
2672 {VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, "line_list_with_adjacency"},
2673 {VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, "line_strip_with_adjacency"},
2674 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, "triangle_list_with_adjacency"},
2675 {VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, "triangle_strip_with_adjacency"},
2676 };
2677 const struct ClipVerticesTestSpec
2678 {
2679 bool clip;
2680 const char *name;
2681 } clipVerticesSpecs[] = {
2682 {false, "no_clip"},
2683 {true, "clip"},
2684 };
2685 const struct useMeshShaderTestSpec
2686 {
2687 bool meshShader;
2688 const char *name;
2689 } useMeshShaderSpecs[] = {
2690 {true, "mesh_shader"},
2691 {false, "vertex_shader"},
2692 };
2693 const glu::DataType dataTypes[] = {
2694 glu::TYPE_FLOAT, glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT_VEC4,
2695 glu::TYPE_DOUBLE, glu::TYPE_DOUBLE_VEC2, glu::TYPE_DOUBLE_VEC3, glu::TYPE_DOUBLE_VEC4,
2696 glu::TYPE_INT, glu::TYPE_INT_VEC2, glu::TYPE_INT_VEC3, glu::TYPE_INT_VEC4,
2697 glu::TYPE_UINT, glu::TYPE_UINT_VEC2, glu::TYPE_UINT_VEC3, glu::TYPE_UINT_VEC4,
2698 };
2699 const struct Perspective
2700 {
2701 const char *name;
2702 bool value;
2703 } perspectives[] = {
2704 {"perspective", true},
2705 {"noperspective", false},
2706 };
2707 const struct DynamicIndexing
2708 {
2709 const char *name;
2710 bool value;
2711 } dynamicIndexings[] = {
2712 {"static", false},
2713 {"dynamic", true},
2714 };
2715 const struct ProvokingVertex
2716 {
2717 const char *name;
2718 bool value;
2719 } provokingVertices[] = {
2720 {"provoking_first", false},
2721 {"provoking_last", true},
2722 };
2723 const uint32_t rotations[] = {0, 85, 95};
2724 const struct TopologyInPipeline
2725 {
2726 const char *name;
2727 bool value;
2728 } topologiesInPipeline[] = {
2729 {"pipeline_topology_static", false},
2730 {"pipeline_topology_dynamic", true},
2731 };
2732 const struct InterpolationTypes
2733 {
2734 const char *name;
2735 bool testWithInterpolation;
2736 bool testWithFlatInterpolation;
2737 } interpolationTypes[] = {
2738 {"per_vertex", false, false}, {"per_vertex_interp", true, false}, {"per_vertex_flat", false, true}};
2739
2740 for (const auto &constructionTypeCase : constructionTypeCases)
2741 {
2742 MovePtr<tcu::TestCaseGroup> testTypeGroup(new tcu::TestCaseGroup(testCtx, "data"));
2743 const TestType testType = TEST_TYPE_DATA;
2744
2745 for (size_t provokingVertexNdx = 0; provokingVertexNdx < DE_LENGTH_OF_ARRAY(provokingVertices);
2746 ++provokingVertexNdx)
2747 {
2748 MovePtr<tcu::TestCaseGroup> provokingVertexGroup(
2749 new tcu::TestCaseGroup(testCtx, provokingVertices[provokingVertexNdx].name));
2750 const bool provokingVertexLast = provokingVertices[provokingVertexNdx].value;
2751
2752 for (size_t dynamicNdx = 0; dynamicNdx < DE_LENGTH_OF_ARRAY(dynamicIndexings); ++dynamicNdx)
2753 {
2754 MovePtr<tcu::TestCaseGroup> dynamicIndexingGroup(
2755 new tcu::TestCaseGroup(testCtx, dynamicIndexings[dynamicNdx].name));
2756 const bool dynamicIndexing = dynamicIndexings[dynamicNdx].value;
2757
2758 for (size_t topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); ++topologyNdx)
2759 {
2760 MovePtr<tcu::TestCaseGroup> topologyGroup(
2761 new tcu::TestCaseGroup(testCtx, topologies[topologyNdx].name));
2762 const VkPrimitiveTopology topology = topologies[topologyNdx].topology;
2763
2764 for (size_t clipVerticesSpecNdx = 0; clipVerticesSpecNdx < DE_LENGTH_OF_ARRAY(clipVerticesSpecs);
2765 ++clipVerticesSpecNdx)
2766 {
2767 MovePtr<tcu::TestCaseGroup> clipVerticesGroup(
2768 new tcu::TestCaseGroup(testCtx, clipVerticesSpecs[clipVerticesSpecNdx].name, ""));
2769 const bool clipVertices = clipVerticesSpecs[clipVerticesSpecNdx].clip;
2770
2771 if (clipVertices && topology != VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
2772 // no implemented
2773 continue;
2774
2775 for (size_t aggregateNdx = 0; aggregateNdx < 3; ++aggregateNdx)
2776 {
2777 const string aggregateName = aggregateNdx == 0 ? "type" :
2778 aggregateNdx == 1 ? "struct" :
2779 "array" + de::toString(aggregateNdx);
2780 MovePtr<tcu::TestCaseGroup> aggregateGroup(
2781 new tcu::TestCaseGroup(testCtx, aggregateName.c_str()));
2782
2783 for (size_t dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(dataTypes); ++dataTypeNdx)
2784 {
2785 const glu::DataType dataType = dataTypes[dataTypeNdx];
2786
2787 MovePtr<tcu::TestCaseGroup> dataTypeGroup(
2788 new tcu::TestCaseGroup(testCtx, getDataTypeName(dataType), ""));
2789
2790 for (size_t interpolationTypeNdx = 0;
2791 interpolationTypeNdx < DE_LENGTH_OF_ARRAY(interpolationTypes);
2792 ++interpolationTypeNdx)
2793 {
2794 MovePtr<tcu::TestCaseGroup> interpolationTypeGroup(new tcu::TestCaseGroup(
2795 testCtx, interpolationTypes[interpolationTypeNdx].name, ""));
2796
2797 if (interpolationTypes[interpolationTypeNdx].testWithInterpolation &&
2798 (glu::isDataTypeIntOrIVec(dataType) || glu::isDataTypeUintOrUVec(dataType) ||
2799 glu::isDataTypeDoubleOrDVec(dataType)))
2800 {
2801 // integer and double inputs must be qualified as flat, cannot be interpolated
2802 continue;
2803 }
2804
2805 for (size_t useMeshShaderSpecNdx = 0;
2806 useMeshShaderSpecNdx < DE_LENGTH_OF_ARRAY(useMeshShaderSpecs);
2807 ++useMeshShaderSpecNdx)
2808 {
2809 const bool useMeshShader = useMeshShaderSpecs[useMeshShaderSpecNdx].meshShader;
2810 const char *useMeshShaderName = useMeshShaderSpecs[useMeshShaderSpecNdx].name;
2811
2812 if (useMeshShader && !(topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST ||
2813 topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST ||
2814 topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST))
2815 // mesh shader support only for point, line or triangle list topology
2816 continue;
2817
2818 const TestParams testParams = {
2819 constructionTypeCase.constructionType,
2820 testType, // TestType testType;
2821 TEST_SUBTYPE_DEFAULT, // TestSubtype testSubtype;
2822 topology, // VkPrimitiveTopology topology;
2823 dynamicIndexing, // bool dynamicIndexing;
2824 aggregateNdx, // size_t aggregate;
2825 dataType, // glu::DataType dataType;
2826 DATA_TEST_WIDTH, // uint32_t width;
2827 DATA_TEST_HEIGHT, // uint32_t height;
2828 notused, // bool perspective;
2829 provokingVertexLast, // bool provokingVertexLast;
2830 (uint32_t)notused, // uint32_t rotation;
2831 notused, // bool dynamicTopologyInPipeline
2832 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits sampleCount;
2833 interpolationTypes[interpolationTypeNdx]
2834 .testWithInterpolation, // bool testWithInterpolation
2835 interpolationTypes[interpolationTypeNdx]
2836 .testWithFlatInterpolation, // bool testWithFlatInterpolation
2837 clipVertices, // bool clipVertices
2838 useMeshShader, // bool useMeshShader
2839 };
2840 interpolationTypeGroup->addChild(new FragmentShadingBarycentricTestCase(
2841 testCtx, useMeshShaderName, testParams));
2842 }
2843
2844 dataTypeGroup->addChild(interpolationTypeGroup.release());
2845 }
2846 aggregateGroup->addChild(dataTypeGroup.release());
2847 }
2848
2849 clipVerticesGroup->addChild(aggregateGroup.release());
2850 }
2851 topologyGroup->addChild(clipVerticesGroup.release());
2852 }
2853
2854 dynamicIndexingGroup->addChild(topologyGroup.release());
2855 }
2856
2857 provokingVertexGroup->addChild(dynamicIndexingGroup.release());
2858 }
2859
2860 testTypeGroup->addChild(provokingVertexGroup.release());
2861 }
2862
2863 {
2864 MovePtr<tcu::TestCaseGroup> miscGroup(new tcu::TestCaseGroup(testCtx, "misc"));
2865 const TestParams testParams{
2866 constructionTypeCase.constructionType,
2867 TEST_TYPE_DATA, // TestType testType;
2868 TEST_SUBTYPE_PERVERTEX_CORRECTNESS, // TestSubtype testSubtype;
2869 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // VkPrimitiveTopology topology;
2870 notused, // bool dynamicIndexing;
2871 notused, // size_t aggregate;
2872 glu::TYPE_FLOAT_VEC2, // glu::DataType dataType;
2873 DATA_TEST_WIDTH, // uint32_t width;
2874 DATA_TEST_HEIGHT, // uint32_t height;
2875 notused, // bool perspective;
2876 notused, // bool provokingVertexLast;
2877 (uint32_t)notused, // uint32_t rotation;
2878 notused, // bool dynamicTopologyInPipeline
2879 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits sampleCount;
2880 false, // bool testWithInterpolation
2881 false, // bool testWithFlatInterpolation
2882 false, // bool clipVertices
2883 false, // bool useMeshShader
2884 };
2885 miscGroup->addChild(new FragmentShadingBarycentricTestCase(testCtx, "pervertex_correctness", testParams));
2886 testTypeGroup->addChild(miscGroup.release());
2887 }
2888
2889 {
2890 MovePtr<tcu::TestCaseGroup> scGroup(new tcu::TestCaseGroup(testCtx, "shader_combos"));
2891 for (uint32_t testSubType = (uint32_t)TEST_SUBTYPE_TESS_SHADER;
2892 testSubType <= (uint32_t)TEST_SUBTYPE_TESSGEOM_SHADER; testSubType++)
2893 {
2894 VkPrimitiveTopology primitiveType = (((TestSubtype)testSubType) == TEST_SUBTYPE_GEOMETRY_SHADER) ?
2895 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST :
2896 VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
2897 const std::string shaderComboName = getShaderComboName(testSubType);
2898
2899 MovePtr<tcu::TestCaseGroup> scSubGroup(new tcu::TestCaseGroup(testCtx, shaderComboName.c_str()));
2900
2901 for (size_t aggregateNdx = 0; aggregateNdx < 3; ++aggregateNdx)
2902 {
2903 const string aggregateName = aggregateNdx == 0 ? "type" :
2904 aggregateNdx == 1 ? "struct" :
2905 "array" + de::toString(aggregateNdx);
2906 MovePtr<tcu::TestCaseGroup> aggregateGroup(new tcu::TestCaseGroup(testCtx, aggregateName.c_str()));
2907
2908 for (size_t dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(dataTypes); ++dataTypeNdx)
2909 {
2910 const glu::DataType dataType = dataTypes[dataTypeNdx];
2911 const char *dataTypeName = getDataTypeName(dataType);
2912
2913 const TestParams testParamsShaders{
2914 constructionTypeCase.constructionType,
2915 TEST_TYPE_DATA, // TestType testType;
2916 (TestSubtype)testSubType, // TestSubtype testSubtype;
2917 primitiveType, // VkPrimitiveTopology topology;
2918 notused, // bool dynamicIndexing;
2919 aggregateNdx, // size_t aggregate;
2920 dataType, // glu::DataType dataType;
2921 DATA_TEST_WIDTH, // uint32_t width;
2922 DATA_TEST_HEIGHT, // uint32_t height;
2923 notused, // bool perspective;
2924 notused, // bool provokingVertexLast;
2925 (uint32_t)notused, // uint32_t rotation;
2926 notused, // bool dynamicTopologyInPipeline
2927 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits sampleCount;
2928 false, // bool testWithInterpolation
2929 false, // bool testWithFlatInterpolation
2930 false, // bool clipVertices
2931 false, // bool useMeshShader
2932 };
2933 aggregateGroup->addChild(
2934 new FragmentShadingBarycentricTestCase(testCtx, dataTypeName, testParamsShaders));
2935 }
2936 scSubGroup->addChild(aggregateGroup.release());
2937 }
2938 scGroup->addChild(scSubGroup.release());
2939 }
2940 testTypeGroup->addChild(scGroup.release());
2941 }
2942
2943 constructionTypeCase.testGroup->addChild(testTypeGroup.release());
2944 }
2945
2946 for (const auto &constructionTypeCase : constructionTypeCases)
2947 {
2948 const struct MsaaTestCase
2949 {
2950 const char *name;
2951 VkSampleCountFlagBits samples;
2952 TestSubtype subtype;
2953 } msaaCases[] = {
2954 {"single_sample", VK_SAMPLE_COUNT_1_BIT, TEST_SUBTYPE_DEFAULT},
2955 {"msaa_interpolate_at_centroid", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_INTERPOLATE_AT_CENTROID},
2956 {"msaa_interpolate_at_sample", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_INTERPOLATE_AT_SAMPLE},
2957 {"msaa_interpolate_at_offset", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_INTERPOLATE_AT_OFFSET},
2958 {"msaa_centroid_qualifier", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_CENTROID_QUALIFIER},
2959 {"msaa_sample_qualifier", VK_SAMPLE_COUNT_4_BIT, TEST_SUBTYPE_MSAA_SAMPLE_QUALIFIER},
2960 };
2961
2962 MovePtr<tcu::TestCaseGroup> testTypeGroup(new tcu::TestCaseGroup(testCtx, "weights"));
2963 const TestType testType = TEST_TYPE_WEIGHTS;
2964
2965 for (size_t provokingVertexNdx = 0; provokingVertexNdx < DE_LENGTH_OF_ARRAY(provokingVertices);
2966 ++provokingVertexNdx)
2967 {
2968 MovePtr<tcu::TestCaseGroup> provokingVertexGroup(
2969 new tcu::TestCaseGroup(testCtx, provokingVertices[provokingVertexNdx].name, ""));
2970 const bool provokingVertexLast = provokingVertices[provokingVertexNdx].value;
2971
2972 for (size_t topologyInPipelineNdx = 0; topologyInPipelineNdx < DE_LENGTH_OF_ARRAY(topologiesInPipeline);
2973 ++topologyInPipelineNdx)
2974 {
2975 MovePtr<tcu::TestCaseGroup> topologyInPipelineGroup(
2976 new tcu::TestCaseGroup(testCtx, topologiesInPipeline[topologyInPipelineNdx].name));
2977 const bool topologyInPipeline = topologiesInPipeline[topologyInPipelineNdx].value;
2978
2979 if (topologyInPipeline)
2980 {
2981 for (size_t msaaCaseNdx = 0; msaaCaseNdx < DE_LENGTH_OF_ARRAY(msaaCases); ++msaaCaseNdx)
2982 {
2983 MovePtr<tcu::TestCaseGroup> msaaGroup(
2984 new tcu::TestCaseGroup(testCtx, msaaCases[msaaCaseNdx].name));
2985 for (size_t topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); ++topologyNdx)
2986 {
2987 MovePtr<tcu::TestCaseGroup> topologyGroup(
2988 new tcu::TestCaseGroup(testCtx, topologies[topologyNdx].name));
2989 const VkPrimitiveTopology topology = topologies[topologyNdx].topology;
2990 const bool testableTopology =
2991 isPrimitiveTopologyLine(topology) || isPrimitiveTopologyTriangle(topology);
2992
2993 if (!testableTopology)
2994 continue;
2995
2996 for (size_t perspectiveNdx = 0; perspectiveNdx < DE_LENGTH_OF_ARRAY(perspectives);
2997 ++perspectiveNdx)
2998 {
2999 MovePtr<tcu::TestCaseGroup> usePerspectiveGroup(
3000 new tcu::TestCaseGroup(testCtx, perspectives[perspectiveNdx].name, ""));
3001 const bool perspective = perspectives[perspectiveNdx].value;
3002
3003 for (size_t useMeshShaderSpecNdx = 0;
3004 useMeshShaderSpecNdx < DE_LENGTH_OF_ARRAY(useMeshShaderSpecs);
3005 ++useMeshShaderSpecNdx)
3006 {
3007 const bool useMeshShader = useMeshShaderSpecs[useMeshShaderSpecNdx].meshShader;
3008 const char *useMeshShaderName = useMeshShaderSpecs[useMeshShaderSpecNdx].name;
3009
3010 if (useMeshShader && !(topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST ||
3011 topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST ||
3012 topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST))
3013 // mesh shader support only for point, line or triangle list topology
3014 continue;
3015
3016 if (useMeshShader && topologyInPipeline)
3017 {
3018 // topology is a dynamic state, so cannot use mesh shaders
3019 // """
3020 // If the pipeline requires pre - rasterization shader state, and includes a mesh shader,
3021 // there must be no element of the pDynamicStates member of pDynamicState set to VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY,
3022 // or VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE
3023 // """
3024 continue;
3025 }
3026
3027 const TestParams testParams{
3028 constructionTypeCase.constructionType,
3029 testType, // TestType testType;
3030 msaaCases[msaaCaseNdx].subtype, // TestSubtype testSubtype;
3031 topology, // VkPrimitiveTopology topology;
3032 notused, // bool dynamicIndexing;
3033 (size_t)notused, // size_t aggregate;
3034 (glu::DataType)notused, // glu::DataType dataType;
3035 WEIGHT_TEST_WIDTH, // uint32_t width;
3036 WEIGHT_TEST_HEIGHT, // uint32_t height;
3037 perspective, // bool perspective;
3038 false, // bool provokingVertexLast;
3039 0, // uint32_t rotation;
3040 topologyInPipeline, // bool dynamicTopologyInPipeline
3041 msaaCases[msaaCaseNdx].samples, // VkSampleCountFlagBits sampleCount;
3042 false, // bool testWithInterpolation
3043 false, // bool testWithFlatInterpolation
3044 false, // bool clipVertices
3045 useMeshShader, // bool useMeshShader
3046 };
3047
3048 usePerspectiveGroup->addChild(
3049 new FragmentShadingBarycentricTestCase(testCtx, useMeshShaderName, testParams));
3050 }
3051
3052 topologyGroup->addChild(usePerspectiveGroup.release());
3053 }
3054 msaaGroup->addChild(topologyGroup.release());
3055 }
3056 topologyInPipelineGroup->addChild(msaaGroup.release());
3057 }
3058 }
3059 else
3060 {
3061 for (size_t rotationNdx = 0; rotationNdx < DE_LENGTH_OF_ARRAY(rotations); ++rotationNdx)
3062 {
3063 const uint32_t rotation = rotations[rotationNdx];
3064 MovePtr<tcu::TestCaseGroup> rotationGroup(
3065 new tcu::TestCaseGroup(testCtx, de::toString(rotation).c_str()));
3066
3067 for (size_t topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); ++topologyNdx)
3068 {
3069 const VkPrimitiveTopology topology = topologies[topologyNdx].topology;
3070 MovePtr<tcu::TestCaseGroup> topologyGroup(
3071 new tcu::TestCaseGroup(testCtx, topologies[topologyNdx].name));
3072
3073 for (size_t perspectiveNdx = 0; perspectiveNdx < DE_LENGTH_OF_ARRAY(perspectives);
3074 ++perspectiveNdx)
3075 {
3076 MovePtr<tcu::TestCaseGroup> usePerspectiveGroup(
3077 new tcu::TestCaseGroup(testCtx, perspectives[perspectiveNdx].name, ""));
3078 const bool perspective = perspectives[perspectiveNdx].value;
3079
3080 for (size_t useMeshShaderSpecNdx = 0;
3081 useMeshShaderSpecNdx < DE_LENGTH_OF_ARRAY(useMeshShaderSpecs);
3082 ++useMeshShaderSpecNdx)
3083 {
3084 const bool useMeshShader = useMeshShaderSpecs[useMeshShaderSpecNdx].meshShader;
3085 const char *useMeshShaderName = useMeshShaderSpecs[useMeshShaderSpecNdx].name;
3086
3087 if (useMeshShader && !(topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST ||
3088 topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST ||
3089 topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST))
3090 {
3091 // mesh shader support only for point, line or triangle list topology
3092 continue;
3093 }
3094
3095 if (useMeshShader && topologyInPipeline)
3096 {
3097 // topology is a dynamic state, so cannot use mesh shaders
3098 // """
3099 // If the pipeline requires pre - rasterization shader state, and includes a mesh shader,
3100 // there must be no element of the pDynamicStates member of pDynamicState set to VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY,
3101 // or VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE
3102 // """
3103 continue;
3104 }
3105
3106 const TestParams testParams{
3107 constructionTypeCase.constructionType,
3108 testType, // TestType testType;
3109 TEST_SUBTYPE_DEFAULT, // TestSubtype testSubtype;
3110 topology, // VkPrimitiveTopology topology;
3111 notused, // bool dynamicIndexing;
3112 (size_t)-1, // size_t aggregate;
3113 glu::TYPE_INVALID, // glu::DataType dataType;
3114 WEIGHT_TEST_WIDTH, // uint32_t width;
3115 WEIGHT_TEST_HEIGHT, // uint32_t height;
3116 perspective, // bool perspective;
3117 provokingVertexLast, // bool provokingVertexLast;
3118 rotation, // uint32_t rotation;
3119 topologyInPipeline, // bool dynamicTopologyInPipeline
3120 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits sampleCount;
3121 false, // bool testWithInterpolation
3122 false, // bool testWithFlatInterpolation
3123 false, // bool clipVertices
3124 useMeshShader, // bool useMeshShader
3125 };
3126
3127 usePerspectiveGroup->addChild(
3128 new FragmentShadingBarycentricTestCase(testCtx, useMeshShaderName, testParams));
3129 }
3130 topologyGroup->addChild(usePerspectiveGroup.release());
3131 }
3132 rotationGroup->addChild(topologyGroup.release());
3133 }
3134
3135 topologyInPipelineGroup->addChild(rotationGroup.release());
3136 }
3137 }
3138 provokingVertexGroup->addChild(topologyInPipelineGroup.release());
3139 }
3140 testTypeGroup->addChild(provokingVertexGroup.release());
3141 }
3142
3143 constructionTypeCase.testGroup->addChild(testTypeGroup.release());
3144 }
3145
3146 group->addChild(libGroup.release());
3147 group->addChild(fastLinkGroup.release());
3148
3149 return group.release();
3150 }
3151
3152 } // namespace FragmentShadingBarycentric
3153 } // namespace vkt
3154