1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2020 The Khronos Group Inc.
6 * Copyright (c) 2020 Valve Corporation
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief VK_AMD_shader_explicit_vertex_parameter tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawExplicitVertexParameterTests.hpp"
26
27 #include "vktDrawBaseClass.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
32
33 #include "vkObjUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkTypeUtil.hpp"
36
37 #include "deDefs.h"
38 #include "deRandom.hpp"
39 #include "deString.h"
40 #include "deMath.h"
41
42 #include "tcuTestCase.hpp"
43 #include "tcuRGBA.hpp"
44 #include "tcuTextureUtil.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuStringTemplate.hpp"
47
48 #include "rrRenderer.hpp"
49
50 #include <string>
51 #include <sstream>
52
53 namespace vkt
54 {
55 namespace Draw
56 {
57 namespace
58 {
59 using namespace vk;
60 using namespace std;
61
62 enum Interpolation
63 {
64 SMOOTH = 0,
65 NOPERSPECTIVE = 1,
66 };
67
68 enum AuxiliaryQualifier
69 {
70 AUX_NONE = 0,
71 AUX_CENTROID = 1,
72 AUX_SAMPLE = 2,
73 };
74
75
76 enum
77 {
78 WIDTH = 16,
79 HEIGHT = 16
80 };
81
82 struct PositionValueVertex {
PositionValueVertexvkt::Draw::__anon0fca8ed40111::PositionValueVertex83 PositionValueVertex(tcu::Vec4 pos, float val)
84 : position(pos)
85 , value(val)
86 {}
87 public:
88 tcu::Vec4 position;
89 float value;
90 };
91
92 struct DrawParams
93 {
94 Interpolation interpolation;
95 vk::VkSampleCountFlagBits samples;
96 AuxiliaryQualifier auxiliaryStorage;
97 const SharedGroupParams groupParams;
98 };
99
interpolationToString(Interpolation interpolation)100 const char* interpolationToString (Interpolation interpolation)
101 {
102 switch (interpolation)
103 {
104 case SMOOTH:
105 return "smooth";
106 case NOPERSPECTIVE:
107 return "noperspective";
108 default:
109 DE_FATAL("Invalid interpolation enum");
110 }
111
112 return "";
113 }
114
barycentricVariableString(Interpolation interpolation,AuxiliaryQualifier aux)115 std::string barycentricVariableString (Interpolation interpolation, AuxiliaryQualifier aux)
116 {
117 std::ostringstream name;
118 name << "gl_BaryCoord";
119 switch (interpolation)
120 {
121 case SMOOTH:
122 name << "Smooth";
123 break;
124 case NOPERSPECTIVE:
125 name << "NoPersp";
126 break;
127 default:
128 DE_FATAL("Invalid interpolation enum");
129 }
130
131 switch (aux)
132 {
133 case AUX_CENTROID:
134 name << "Centroid";
135 break;
136 case AUX_SAMPLE:
137 name << "Sample";
138 break;
139 case AUX_NONE:
140 name << "";
141 break;
142 default:
143 DE_FATAL("Invalid auxiliary storage qualifier enum");
144 }
145 name << "AMD";
146 return name.str();
147 }
148
auxiliaryQualifierToString(AuxiliaryQualifier aux)149 const char* auxiliaryQualifierToString (AuxiliaryQualifier aux)
150 {
151 switch (aux)
152 {
153 case AUX_CENTROID:
154 return "centroid";
155 case AUX_SAMPLE:
156 return "sample";
157 case AUX_NONE:
158 return "";
159 default:
160 DE_FATAL("Invalid auxiliary storage qualifier enum");
161 }
162
163 return "";
164 }
165
getTestName(DrawParams params)166 std::string getTestName (DrawParams params)
167 {
168 std::ostringstream name;
169
170 name << interpolationToString(params.interpolation) << "_";
171
172 if (params.auxiliaryStorage != AUX_NONE)
173 name << auxiliaryQualifierToString(params.auxiliaryStorage) << "_";
174
175 name << "samples_" << de::toString(params.samples);
176
177 return name.str();
178 }
179
180 class DrawTestInstance : public TestInstance
181 {
182 public:
183 DrawTestInstance (Context& context, const DrawParams& data);
184 ~DrawTestInstance (void);
185 tcu::TestStatus iterate (void);
186
187 protected:
188 void preRenderCommands (VkCommandBuffer cmdBuffer, VkImage colorTargetImage) const;
189 void beginRenderPass (VkCommandBuffer cmdBuffer, VkRect2D renderArea,
190 const VkClearValue* pClearValues, deUint32 clearValueCount) const;
191 void drawCommands (VkCommandBuffer cmdBuffer, VkBuffer vertexBuffer) const;
192
193 #ifndef CTS_USES_VULKANSC
194 void beginSecondaryCmdBuffer (VkCommandBuffer cmdBuffer, VkFormat colorFormat,
195 VkRenderingFlagsKHR renderingFlags = 0u) const;
196 void beginDynamicRender (VkCommandBuffer cmdBuffer, VkRect2D renderArea,
197 const VkClearValue* pClearValues, VkRenderingFlagsKHR renderingFlags = 0u) const;
198 #endif // CTS_USES_VULKANSC
199
200 private:
201 DrawParams m_data;
202 Move<VkRenderPass> m_renderPass;
203 Move<VkImageView> m_colorTargetView;
204 Move<VkImageView> m_multisampleTargetView;
205 Move<VkFramebuffer> m_framebuffer;
206 Move<VkPipeline> m_pipeline;
207 Move<VkPipelineLayout> m_pipelineLayout;
208 Move<VkDescriptorPool> m_descriptorPool;
209 Move<VkDescriptorSet> m_descriptorSet;
210 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
211 };
212
DrawTestInstance(Context & context,const DrawParams & data)213 DrawTestInstance::DrawTestInstance (Context& context, const DrawParams& data)
214 : vkt::TestInstance (context)
215 , m_data (data)
216 {
217 }
218
~DrawTestInstance(void)219 DrawTestInstance::~DrawTestInstance (void)
220 {
221 }
222
223 class DrawTestCase : public TestCase
224 {
225 public:
226 DrawTestCase (tcu::TestContext& context, const char* name, const DrawParams data);
227 ~DrawTestCase (void);
228 virtual void initPrograms (SourceCollections& programCollection) const;
229 virtual TestInstance* createInstance (Context& context) const;
230 virtual void checkSupport (Context& context) const;
231
232 private:
233 DrawParams m_data;
234 };
235
DrawTestCase(tcu::TestContext & context,const char * name,const DrawParams data)236 DrawTestCase::DrawTestCase (tcu::TestContext& context, const char* name, const DrawParams data)
237 : vkt::TestCase (context, name)
238 , m_data (data)
239 {
240 }
241
~DrawTestCase(void)242 DrawTestCase::~DrawTestCase (void)
243 {
244 }
245
checkSupport(Context & context) const246 void DrawTestCase::checkSupport(Context &context) const
247 {
248 context.requireDeviceFunctionality("VK_AMD_shader_explicit_vertex_parameter");
249
250 if ((context.getDeviceProperties().limits.framebufferColorSampleCounts & m_data.samples) == 0)
251 TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
252
253 if (m_data.groupParams->useDynamicRendering)
254 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
255 }
256
initPrograms(SourceCollections & programCollection) const257 void DrawTestCase::initPrograms (SourceCollections& programCollection) const
258 {
259 const deUint32 numValues = WIDTH * HEIGHT * m_data.samples;
260
261 const tcu::StringTemplate vertShader (string(
262 "#version 450\n"
263 "#extension GL_AMD_shader_explicit_vertex_parameter : require\n"
264 "\n"
265 "layout(location = 0) in vec4 in_position;\n"
266 "layout(location = 1) in float in_data;\n"
267 "layout(location = 0) __explicitInterpAMD out float out_data_explicit;\n"
268 "layout(location = 1) ${auxqualifier} ${qualifier} out float out_data_${qualifier};\n"
269 "\n"
270 "out gl_PerVertex {\n"
271 " vec4 gl_Position;\n"
272 " float gl_PointSize;\n"
273 "};\n"
274 "\n"
275 "void main() {\n"
276 " gl_PointSize = 1.0;\n"
277 " gl_Position = in_position;\n"
278 " out_data_explicit = in_data;\n"
279 " out_data_${qualifier} = in_data;\n"
280 "}\n"));
281
282 const tcu::StringTemplate fragShader (string(
283 "#version 450\n"
284 "#extension GL_AMD_shader_explicit_vertex_parameter : require\n"
285 "\n"
286 "layout(location = 0) __explicitInterpAMD in float in_data_explicit;\n"
287 "layout(location = 1) ${auxqualifier} ${qualifier} in float in_data_${qualifier};\n"
288 "layout(location = 0) out vec4 out_color;\n"
289 "layout (binding = 0, std140) writeonly buffer Output {\n"
290 " vec4 values [${numValues}];\n"
291 "} sb_out;\n"
292 "\n"
293 "void main()\n"
294 "{\n"
295 " uint index = (uint(gl_FragCoord.y) * ${width} * ${samples}) + uint(gl_FragCoord.x) * ${samples} + gl_SampleID;\n"
296 " // Barycentric coodinates (I, J, K)\n"
297 " vec3 bary_coord = vec3(${barycoord}.x, ${barycoord}.y, 1.0f - ${barycoord}.x - ${barycoord}.y);\n"
298 "\n"
299 " // Vertex 0 -> (I = 0, J = 0, K = 1)\n"
300 " float data0 = interpolateAtVertexAMD(in_data_explicit, 0);\n"
301 " // Vertex 1 -> (I = 1, J = 0, K = 0)\n"
302 " float data1 = interpolateAtVertexAMD(in_data_explicit, 1);\n"
303 " // Vertex 1 -> (I = 0, J = 1, K = 0)\n"
304 " float data2 = interpolateAtVertexAMD(in_data_explicit, 2);\n"
305 " // Match data component with barycentric coordinate\n"
306 " vec3 data = vec3(data1, data2, data0);\n"
307 "\n"
308 " float res = (bary_coord.x * data.x) + (bary_coord.y * data.y) + (bary_coord.z * data.z);\n"
309 " float expected = in_data_${qualifier};\n"
310 "\n"
311 " sb_out.values[ index ] = vec4(expected, res, 0u, 0u);\n"
312 "\n"
313 " const float threshold = 0.0005f;\n"
314 " if (abs(res - expected) < threshold)\n"
315 " out_color = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
316 " else\n"
317 " out_color = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
318 "}\n"));
319
320 map<string, string> attributes;
321 attributes["width"] = de::toString(WIDTH);
322 attributes["numValues"] = de::toString(numValues * m_data.samples);
323 attributes["qualifier"] = interpolationToString(m_data.interpolation);
324 attributes["auxqualifier"] = auxiliaryQualifierToString(m_data.auxiliaryStorage);
325 attributes["barycoord"] = barycentricVariableString(m_data.interpolation, m_data.auxiliaryStorage);
326 attributes["samples"] = de::toString(m_data.samples);
327
328 programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(attributes));
329 programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(attributes));
330 }
331
createInstance(Context & context) const332 TestInstance* DrawTestCase::createInstance (Context& context) const
333 {
334 return new DrawTestInstance(context, m_data);
335 }
336
iterate(void)337 tcu::TestStatus DrawTestInstance::iterate (void)
338 {
339 de::SharedPtr<Image> colorTargetImage;
340 de::SharedPtr<Image> multisampleTargetImage;
341 tcu::TestLog &log = m_context.getTestContext().getLog();
342
343 // Run two iterations with shaders that have different interpolation decorations. Images should still match.
344 const DeviceInterface& vk = m_context.getDeviceInterface();
345 const VkDevice device = m_context.getDevice();
346 const CmdPoolCreateInfo cmdPoolCreateInfo (m_context.getUniversalQueueFamilyIndex());
347 Move<VkCommandPool> cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
348 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
349 Move<VkCommandBuffer> secCmdBuffer;
350 const Unique<VkShaderModule> vs (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
351 const Unique<VkShaderModule> fs (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
352 de::SharedPtr<Buffer> vertexBuffer;
353 de::SharedPtr<Buffer> ssboBuffer;
354
355 vk::VkFormat imageFormat = VK_FORMAT_R8G8B8A8_UNORM;
356 const deUint32 numValues = WIDTH * HEIGHT * m_data.samples;
357 const deBool useMultisampling = m_data.samples != VK_SAMPLE_COUNT_1_BIT;
358
359 // Create color buffer images.
360 {
361 const VkExtent3D targetImageExtent = { WIDTH, HEIGHT, 1 };
362 const ImageCreateInfo targetImageCreateInfo (VK_IMAGE_TYPE_2D, imageFormat, targetImageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT,
363 VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
364 colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
365
366 if (useMultisampling)
367 {
368 const ImageCreateInfo multisampleTargetImageCreateInfo (VK_IMAGE_TYPE_2D, imageFormat, targetImageExtent, 1, 1, m_data.samples,
369 VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
370 multisampleTargetImage = Image::createAndAlloc(vk, device, multisampleTargetImageCreateInfo, m_context.getDefaultAllocator(), m_context.getUniversalQueueFamilyIndex());
371 }
372 }
373
374 const ImageViewCreateInfo colorTargetViewInfo(colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, imageFormat);
375 m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
376
377 if (useMultisampling)
378 {
379 const ImageViewCreateInfo multisamplingTargetViewInfo(multisampleTargetImage->object(), vk::VK_IMAGE_VIEW_TYPE_2D, imageFormat);
380 m_multisampleTargetView = createImageView(vk, device, &multisamplingTargetViewInfo);
381 }
382
383 // Create render pass
384 if (!m_data.groupParams->useDynamicRendering)
385 {
386 RenderPassCreateInfo renderPassCreateInfo;
387 renderPassCreateInfo.addAttachment(AttachmentDescription(imageFormat,
388 VK_SAMPLE_COUNT_1_BIT,
389 VK_ATTACHMENT_LOAD_OP_CLEAR,
390 VK_ATTACHMENT_STORE_OP_STORE,
391 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
392 VK_ATTACHMENT_STORE_OP_STORE,
393 VK_IMAGE_LAYOUT_UNDEFINED,
394 VK_IMAGE_LAYOUT_GENERAL));
395
396 const VkAttachmentReference colorAttachmentRef = { 0u, VK_IMAGE_LAYOUT_GENERAL };
397 const VkAttachmentReference multisampleAttachmentRef = { 1u, VK_IMAGE_LAYOUT_GENERAL };
398
399 if (useMultisampling)
400 {
401 renderPassCreateInfo.addAttachment(AttachmentDescription(imageFormat,
402 m_data.samples,
403 vk::VK_ATTACHMENT_LOAD_OP_CLEAR,
404 vk::VK_ATTACHMENT_STORE_OP_STORE,
405 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
406 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
407 vk::VK_IMAGE_LAYOUT_UNDEFINED,
408 vk::VK_IMAGE_LAYOUT_GENERAL));
409 }
410
411 renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
412 0,
413 0,
414 DE_NULL,
415 1u,
416 useMultisampling ? &multisampleAttachmentRef : &colorAttachmentRef,
417 useMultisampling ? &colorAttachmentRef : DE_NULL,
418 AttachmentReference(),
419 0,
420 DE_NULL));
421
422 m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
423
424 // Create framebuffer
425 vector<VkImageView> colorAttachments { *m_colorTargetView };
426 if (useMultisampling)
427 colorAttachments.push_back(*m_multisampleTargetView);
428
429 const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
430 m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
431 }
432
433 // Create vertex buffer.
434 {
435 const PositionValueVertex vertices[] =
436 {
437 PositionValueVertex(
438 tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f), // Coord
439 float(1.0f)), // Value
440
441 PositionValueVertex(
442 tcu::Vec4(-1.0f, -1.0f, 0.25f, 0.75f), // Coord
443 float(0.0f)), // Value
444 PositionValueVertex(
445 tcu::Vec4( 1.0f, 1.0f, 0.0f, 2.0f), // Coord
446 float(0.5f)), // Value
447 PositionValueVertex(
448 tcu::Vec4( 1.0f, -1.0f, 1.0f, 0.5f), // Coord
449 float(1.0f)), // Value
450 };
451
452 const VkDeviceSize dataSize = DE_LENGTH_OF_ARRAY(vertices) * sizeof(PositionValueVertex);
453 vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
454 deUint8* ptr = reinterpret_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
455
456 deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
457 flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
458 }
459
460 // Create SSBO buffer
461 {
462 const VkDeviceSize dataSize = sizeof(tcu::Vec4) * numValues;
463 ssboBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
464 deUint8* ptr = reinterpret_cast<deUint8*>(ssboBuffer->getBoundMemory().getHostPtr());
465
466 deMemset(ptr, 0, static_cast<size_t>(dataSize));
467 flushMappedMemoryRange(vk, device, ssboBuffer->getBoundMemory().getMemory(), ssboBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
468 }
469
470 // Create Descriptor Set layout
471 {
472 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
473 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
474 .build(vk, device);
475 }
476
477 // Create Descriptor Set
478 {
479 m_descriptorPool = DescriptorPoolBuilder()
480 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
481 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
482
483 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
484
485 const VkDescriptorBufferInfo bufferInfo =
486 {
487 ssboBuffer->object(), // VkBuffer buffer;
488 0u, // VkDeviceSize offset;
489 VK_WHOLE_SIZE // VkDeviceSize range;
490 };
491
492 DescriptorSetUpdateBuilder()
493 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo)
494 .update(vk, device);
495 }
496
497 // Create pipeline
498 {
499 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
500
501 VkViewport viewport = makeViewport(WIDTH, HEIGHT);
502 VkRect2D scissor = makeRect2D(WIDTH, HEIGHT);
503
504 const VkVertexInputBindingDescription vertexInputBindingDescription = { 0, (deUint32)(sizeof(tcu::Vec4) + sizeof(float)), VK_VERTEX_INPUT_RATE_VERTEX };
505
506 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
507 {
508 { 0u, 0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
509 { 1u, 0u, vk::VK_FORMAT_R32_SFLOAT, (deUint32)(sizeof(float)* 4) }
510 };
511
512 PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
513
514 m_pipelineLayout = makePipelineLayout (vk, device, *m_descriptorSetLayout);
515
516 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
517 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
518 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
519 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
520 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP));
521 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
522 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, vector<VkViewport>(1, viewport), vector<VkRect2D>(1, scissor)));
523 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
524 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
525 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState(m_data.samples));
526
527 #ifndef CTS_USES_VULKANSC
528 VkPipelineRenderingCreateInfoKHR renderingCreateInfo
529 {
530 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
531 DE_NULL,
532 0u,
533 1u,
534 &imageFormat,
535 VK_FORMAT_UNDEFINED,
536 VK_FORMAT_UNDEFINED
537 };
538
539 if (m_data.groupParams->useDynamicRendering)
540 pipelineCreateInfo.pNext = &renderingCreateInfo;
541 #endif // CTS_USES_VULKANSC
542
543 m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
544 }
545
546 // Queue draw and read results.
547 {
548 const VkQueue queue = m_context.getUniversalQueue();
549 const ImageSubresourceRange subresourceRange (VK_IMAGE_ASPECT_COLOR_BIT);
550 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
551 const VkRect2D renderArea = makeRect2D(WIDTH, HEIGHT);
552 const VkBuffer buffer = vertexBuffer->object();
553
554 vector<VkClearValue> clearColors;
555 clearColors.push_back(makeClearValueColor(clearColor));
556 if (useMultisampling)
557 clearColors.push_back(makeClearValueColor(clearColor));
558
559 #ifndef CTS_USES_VULKANSC
560 if (m_data.groupParams->useSecondaryCmdBuffer)
561 {
562 secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
563
564 // record secondary command buffer
565 if (m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
566 {
567 beginSecondaryCmdBuffer(*secCmdBuffer, imageFormat, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
568 beginDynamicRender(*secCmdBuffer, renderArea, clearColors.data());
569 }
570 else
571 beginSecondaryCmdBuffer(*secCmdBuffer, imageFormat);
572
573 drawCommands(*secCmdBuffer, buffer);
574
575 if (m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
576 endRendering(vk, *secCmdBuffer);
577
578 endCommandBuffer(vk, *secCmdBuffer);
579
580 // record primary command buffer
581 beginCommandBuffer(vk, *cmdBuffer, 0u);
582
583 if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
584 beginDynamicRender(*cmdBuffer, renderArea, clearColors.data(), VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
585
586 vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
587
588 if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
589 endRendering(vk, *cmdBuffer);
590
591 endCommandBuffer(vk, *cmdBuffer);
592 }
593 else if (m_data.groupParams->useDynamicRendering)
594 {
595 beginCommandBuffer(vk, *cmdBuffer);
596 beginDynamicRender(*cmdBuffer, renderArea, clearColors.data());
597 drawCommands(*cmdBuffer, buffer);
598 endRendering(vk, *cmdBuffer);
599 endCommandBuffer(vk, *cmdBuffer);
600 }
601 #endif // CTS_USES_VULKANSC
602
603 if (!m_data.groupParams->useDynamicRendering)
604 {
605 beginCommandBuffer(vk, *cmdBuffer);
606 beginRenderPass(*cmdBuffer, renderArea, clearColors.data(), (deUint32)clearColors.size());
607 drawCommands(*cmdBuffer, buffer);
608 endRenderPass(vk, *cmdBuffer);
609 endCommandBuffer(vk, *cmdBuffer);
610 }
611
612 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
613 }
614
615 qpTestResult res = QP_TEST_RESULT_PASS;
616
617 {
618 const Allocation& resultAlloc = ssboBuffer->getBoundMemory();
619 invalidateAlloc(vk, device, resultAlloc);
620
621 const tcu::Vec4* ptr = reinterpret_cast<tcu::Vec4*>(resultAlloc.getHostPtr());
622 for (deUint32 valueNdx = 0u; valueNdx < numValues; valueNdx++)
623 {
624 if (deFloatAbs(ptr[valueNdx].x() - ptr[valueNdx].y()) > 0.0005f)
625 {
626 log << tcu::TestLog::Message << "Expected value " << valueNdx << " is " << ptr[valueNdx].x() << ", got " << ptr[valueNdx].y()
627 << tcu::TestLog::EndMessage;
628 res = QP_TEST_RESULT_FAIL;
629 }
630 }
631 }
632
633 return tcu::TestStatus(res, qpGetTestResultName(res));
634 }
635
beginRenderPass(VkCommandBuffer cmdBuffer,VkRect2D renderArea,const VkClearValue * pClearValues,deUint32 clearValueCount) const636 void DrawTestInstance::beginRenderPass(VkCommandBuffer cmdBuffer, VkRect2D renderArea,
637 const VkClearValue* pClearValues, deUint32 clearValueCount) const
638 {
639 const DeviceInterface& vk = m_context.getDeviceInterface();
640
641 const VkRenderPassBeginInfo renderPassBeginInfo
642 {
643 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
644 DE_NULL, // const void* pNext;
645 *m_renderPass, // VkRenderPass renderPass;
646 *m_framebuffer, // VkFramebuffer framebuffer;
647 renderArea, // VkRect2D renderArea;
648 clearValueCount, // deUint32 clearValueCount;
649 pClearValues, // const VkClearValue* pClearValues;
650 };
651
652 vk.cmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
653 }
654
drawCommands(VkCommandBuffer cmdBuffer,VkBuffer vertexBuffer) const655 void DrawTestInstance::drawCommands(VkCommandBuffer cmdBuffer, VkBuffer vertexBuffer) const
656 {
657 const DeviceInterface& vk = m_context.getDeviceInterface();
658 const VkDeviceSize vertexBufferOffset = 0;
659
660 vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
661 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
662 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet, 0u, DE_NULL);
663 vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
664 }
665
666 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,VkFormat colorFormat,VkRenderingFlagsKHR renderingFlags) const667 void DrawTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat colorFormat, VkRenderingFlagsKHR renderingFlags) const
668 {
669 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
670 {
671 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
672 DE_NULL, // const void* pNext;
673 renderingFlags, // VkRenderingFlagsKHR flags;
674 0u, // uint32_t viewMask;
675 1u, // uint32_t colorAttachmentCount;
676 &colorFormat, // const VkFormat* pColorAttachmentFormats;
677 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
678 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
679 m_data.samples, // VkSampleCountFlagBits rasterizationSamples;
680 };
681 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
682
683 VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
684 if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
685 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
686
687 const VkCommandBufferBeginInfo commandBufBeginParams
688 {
689 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
690 DE_NULL, // const void* pNext;
691 usageFlags, // VkCommandBufferUsageFlags flags;
692 &bufferInheritanceInfo
693 };
694
695 const DeviceInterface& vk = m_context.getDeviceInterface();
696 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
697 }
698
beginDynamicRender(VkCommandBuffer cmdBuffer,VkRect2D renderArea,const VkClearValue * pClearValues,VkRenderingFlagsKHR renderingFlags) const699 void DrawTestInstance::beginDynamicRender(VkCommandBuffer cmdBuffer, VkRect2D renderArea, const VkClearValue* pClearValues, VkRenderingFlagsKHR renderingFlags) const
700 {
701 const DeviceInterface& vk = m_context.getDeviceInterface();
702 const deBool useMultisampling = m_data.samples != VK_SAMPLE_COUNT_1_BIT;
703
704 VkRenderingAttachmentInfoKHR colorAttachment
705 {
706 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
707 DE_NULL, // const void* pNext;
708 useMultisampling ? *m_multisampleTargetView : *m_colorTargetView, // VkImageView imageView;
709 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout imageLayout;
710 useMultisampling ? VK_RESOLVE_MODE_AVERAGE_BIT : VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
711 useMultisampling ? *m_colorTargetView : DE_NULL, // VkImageView resolveImageView;
712 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout resolveImageLayout;
713 useMultisampling ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
714 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
715 pClearValues[0] // VkClearValue clearValue;
716 };
717
718 VkRenderingInfoKHR renderingInfo
719 {
720 VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
721 DE_NULL,
722 renderingFlags, // VkRenderingFlagsKHR flags;
723 renderArea, // VkRect2D renderArea;
724 1u, // deUint32 layerCount;
725 0u, // deUint32 viewMask;
726 1u, // deUint32 colorAttachmentCount;
727 &colorAttachment, // const VkRenderingAttachmentInfoKHR* pColorAttachments;
728 DE_NULL, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
729 DE_NULL, // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
730 };
731
732 vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
733 }
734 #endif // CTS_USES_VULKANSC
735
createTests(tcu::TestCaseGroup * testGroup,const SharedGroupParams groupParams)736 void createTests (tcu::TestCaseGroup* testGroup, const SharedGroupParams groupParams)
737 {
738 tcu::TestContext& testCtx = testGroup->getTestContext();
739
740 const VkSampleCountFlagBits samples[] =
741 {
742 VK_SAMPLE_COUNT_1_BIT,
743 VK_SAMPLE_COUNT_2_BIT,
744 VK_SAMPLE_COUNT_4_BIT,
745 VK_SAMPLE_COUNT_8_BIT,
746 VK_SAMPLE_COUNT_16_BIT,
747 VK_SAMPLE_COUNT_32_BIT,
748 VK_SAMPLE_COUNT_64_BIT,
749 };
750
751 const Interpolation interTypes[] =
752 {
753 SMOOTH,
754 NOPERSPECTIVE
755 };
756
757 const AuxiliaryQualifier auxQualifiers[] =
758 {
759 AUX_NONE,
760 AUX_SAMPLE,
761 AUX_CENTROID,
762 };
763
764 for (deUint32 sampleNdx = 0; sampleNdx < DE_LENGTH_OF_ARRAY(samples); sampleNdx++)
765 {
766 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
767 if (groupParams->useSecondaryCmdBuffer && (sampleNdx > VK_SAMPLE_COUNT_2_BIT))
768 continue;
769
770 for (deUint32 auxNdx = 0; auxNdx < DE_LENGTH_OF_ARRAY(auxQualifiers); auxNdx++)
771 for (deUint32 interNdx = 0; interNdx < DE_LENGTH_OF_ARRAY(interTypes); interNdx++)
772 {
773 if (samples[sampleNdx] == VK_SAMPLE_COUNT_1_BIT && auxQualifiers[auxNdx] != AUX_NONE)
774 continue;
775
776 const DrawParams params
777 {
778 interTypes[interNdx],
779 samples[sampleNdx],
780 auxQualifiers[auxNdx],
781 groupParams
782 };
783 testGroup->addChild(new DrawTestCase(testCtx, getTestName(params).c_str(), params));
784 }
785 }
786 }
787
788 } // anonymous
789
createExplicitVertexParameterTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)790 tcu::TestCaseGroup* createExplicitVertexParameterTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
791 {
792 // Tests for VK_AMD_shader_explicit_vertex_parameter.
793 return createTestGroup(testCtx, "explicit_vertex_parameter", createTests, groupParams);
794 }
795
796 } // Draw
797 } // vkt
798