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 enum
76 {
77 WIDTH = 16,
78 HEIGHT = 16
79 };
80
81 struct PositionValueVertex
82 {
PositionValueVertexvkt::Draw::__anon06b78bc90111::PositionValueVertex83 PositionValueVertex(tcu::Vec4 pos, float val) : position(pos), value(val)
84 {
85 }
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, const VkClearValue *pClearValues,
190 uint32_t 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, const VkClearValue *pClearValues,
197 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) : vkt::TestInstance(context), m_data(data)
214 {
215 }
216
~DrawTestInstance(void)217 DrawTestInstance::~DrawTestInstance(void)
218 {
219 }
220
221 class DrawTestCase : public TestCase
222 {
223 public:
224 DrawTestCase(tcu::TestContext &context, const char *name, const DrawParams data);
225 ~DrawTestCase(void);
226 virtual void initPrograms(SourceCollections &programCollection) const;
227 virtual TestInstance *createInstance(Context &context) const;
228 virtual void checkSupport(Context &context) const;
229
230 private:
231 DrawParams m_data;
232 };
233
DrawTestCase(tcu::TestContext & context,const char * name,const DrawParams data)234 DrawTestCase::DrawTestCase(tcu::TestContext &context, const char *name, const DrawParams data)
235 : vkt::TestCase(context, name)
236 , m_data(data)
237 {
238 }
239
~DrawTestCase(void)240 DrawTestCase::~DrawTestCase(void)
241 {
242 }
243
checkSupport(Context & context) const244 void DrawTestCase::checkSupport(Context &context) const
245 {
246 context.requireDeviceFunctionality("VK_AMD_shader_explicit_vertex_parameter");
247
248 if ((context.getDeviceProperties().limits.framebufferColorSampleCounts & m_data.samples) == 0)
249 TCU_THROW(NotSupportedError, "framebufferColorSampleCounts: sample count not supported");
250
251 if (m_data.groupParams->useDynamicRendering)
252 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
253
254 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
255 }
256
initPrograms(SourceCollections & programCollection) const257 void DrawTestCase::initPrograms(SourceCollections &programCollection) const
258 {
259 const uint32_t numValues = WIDTH * HEIGHT * m_data.samples;
260
261 const tcu::StringTemplate vertShader(
262 string("#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(
283 string("#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} + "
296 "gl_SampleID;\n"
297 " // Barycentric coodinates (I, J, K)\n"
298 " vec3 bary_coord = vec3(${barycoord}.x, ${barycoord}.y, 1.0f - ${barycoord}.x - ${barycoord}.y);\n"
299 "\n"
300 " // Vertex 0 -> (I = 0, J = 0, K = 1)\n"
301 " float data0 = interpolateAtVertexAMD(in_data_explicit, 0);\n"
302 " // Vertex 1 -> (I = 1, J = 0, K = 0)\n"
303 " float data1 = interpolateAtVertexAMD(in_data_explicit, 1);\n"
304 " // Vertex 1 -> (I = 0, J = 1, K = 0)\n"
305 " float data2 = interpolateAtVertexAMD(in_data_explicit, 2);\n"
306 " // Match data component with barycentric coordinate\n"
307 " vec3 data = vec3(data1, data2, data0);\n"
308 "\n"
309 " float res = (bary_coord.x * data.x) + (bary_coord.y * data.y) + (bary_coord.z * data.z);\n"
310 " float expected = in_data_${qualifier};\n"
311 "\n"
312 " sb_out.values[ index ] = vec4(expected, res, 0u, 0u);\n"
313 "\n"
314 " const float threshold = 0.0005f;\n"
315 " if (abs(res - expected) < threshold)\n"
316 " out_color = vec4(0.0f, 1.0f, 0.0f, 1.0f);\n"
317 " else\n"
318 " out_color = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n"
319 "}\n"));
320
321 map<string, string> attributes;
322 attributes["width"] = de::toString(WIDTH);
323 attributes["numValues"] = de::toString(numValues * m_data.samples);
324 attributes["qualifier"] = interpolationToString(m_data.interpolation);
325 attributes["auxqualifier"] = auxiliaryQualifierToString(m_data.auxiliaryStorage);
326 attributes["barycoord"] = barycentricVariableString(m_data.interpolation, m_data.auxiliaryStorage);
327 attributes["samples"] = de::toString(m_data.samples);
328
329 programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(attributes));
330 programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(attributes));
331 }
332
createInstance(Context & context) const333 TestInstance *DrawTestCase::createInstance(Context &context) const
334 {
335 return new DrawTestInstance(context, m_data);
336 }
337
iterate(void)338 tcu::TestStatus DrawTestInstance::iterate(void)
339 {
340 de::SharedPtr<Image> colorTargetImage;
341 de::SharedPtr<Image> multisampleTargetImage;
342 tcu::TestLog &log = m_context.getTestContext().getLog();
343
344 // Run two iterations with shaders that have different interpolation decorations. Images should still match.
345 const DeviceInterface &vk = m_context.getDeviceInterface();
346 const VkDevice device = m_context.getDevice();
347 const CmdPoolCreateInfo cmdPoolCreateInfo(m_context.getUniversalQueueFamilyIndex());
348 Move<VkCommandPool> cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
349 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
350 Move<VkCommandBuffer> secCmdBuffer;
351 const Unique<VkShaderModule> vs(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
352 const Unique<VkShaderModule> fs(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
353 de::SharedPtr<Buffer> vertexBuffer;
354 de::SharedPtr<Buffer> ssboBuffer;
355
356 vk::VkFormat imageFormat = VK_FORMAT_R8G8B8A8_UNORM;
357 const uint32_t numValues = WIDTH * HEIGHT * m_data.samples;
358 const bool useMultisampling = m_data.samples != VK_SAMPLE_COUNT_1_BIT;
359
360 // Create color buffer images.
361 {
362 const VkExtent3D targetImageExtent = {WIDTH, HEIGHT, 1};
363 const ImageCreateInfo targetImageCreateInfo(
364 VK_IMAGE_TYPE_2D, imageFormat, targetImageExtent, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL,
365 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
366 colorTargetImage = Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(),
367 m_context.getUniversalQueueFamilyIndex());
368
369 if (useMultisampling)
370 {
371 const ImageCreateInfo multisampleTargetImageCreateInfo(
372 VK_IMAGE_TYPE_2D, imageFormat, targetImageExtent, 1, 1, m_data.samples, VK_IMAGE_TILING_OPTIMAL,
373 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
374 VK_IMAGE_USAGE_TRANSFER_DST_BIT);
375 multisampleTargetImage =
376 Image::createAndAlloc(vk, device, multisampleTargetImageCreateInfo, m_context.getDefaultAllocator(),
377 m_context.getUniversalQueueFamilyIndex());
378 }
379 }
380
381 const ImageViewCreateInfo colorTargetViewInfo(colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, imageFormat);
382 m_colorTargetView = createImageView(vk, device, &colorTargetViewInfo);
383
384 if (useMultisampling)
385 {
386 const ImageViewCreateInfo multisamplingTargetViewInfo(multisampleTargetImage->object(),
387 vk::VK_IMAGE_VIEW_TYPE_2D, imageFormat);
388 m_multisampleTargetView = createImageView(vk, device, &multisamplingTargetViewInfo);
389 }
390
391 // Create render pass
392 if (!m_data.groupParams->useDynamicRendering)
393 {
394 RenderPassCreateInfo renderPassCreateInfo;
395 renderPassCreateInfo.addAttachment(
396 AttachmentDescription(imageFormat, VK_SAMPLE_COUNT_1_BIT, VK_ATTACHMENT_LOAD_OP_CLEAR,
397 VK_ATTACHMENT_STORE_OP_STORE, VK_ATTACHMENT_LOAD_OP_DONT_CARE,
398 VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL));
399
400 const VkAttachmentReference colorAttachmentRef = {0u, VK_IMAGE_LAYOUT_GENERAL};
401 const VkAttachmentReference multisampleAttachmentRef = {1u, VK_IMAGE_LAYOUT_GENERAL};
402
403 if (useMultisampling)
404 {
405 renderPassCreateInfo.addAttachment(AttachmentDescription(
406 imageFormat, m_data.samples, vk::VK_ATTACHMENT_LOAD_OP_CLEAR, vk::VK_ATTACHMENT_STORE_OP_STORE,
407 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
408 vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_GENERAL));
409 }
410
411 renderPassCreateInfo.addSubpass(
412 SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS, 0, 0, DE_NULL, 1u,
413 useMultisampling ? &multisampleAttachmentRef : &colorAttachmentRef,
414 useMultisampling ? &colorAttachmentRef : DE_NULL, AttachmentReference(), 0, DE_NULL));
415
416 m_renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
417
418 // Create framebuffer
419 vector<VkImageView> colorAttachments{*m_colorTargetView};
420 if (useMultisampling)
421 colorAttachments.push_back(*m_multisampleTargetView);
422
423 const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, colorAttachments, WIDTH, HEIGHT, 1);
424 m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
425 }
426
427 // Create vertex buffer.
428 {
429 const PositionValueVertex vertices[] = {
430 PositionValueVertex(tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f), // Coord
431 float(1.0f)), // Value
432
433 PositionValueVertex(tcu::Vec4(-1.0f, -1.0f, 0.25f, 0.75f), // Coord
434 float(0.0f)), // Value
435 PositionValueVertex(tcu::Vec4(1.0f, 1.0f, 0.0f, 2.0f), // Coord
436 float(0.5f)), // Value
437 PositionValueVertex(tcu::Vec4(1.0f, -1.0f, 1.0f, 0.5f), // Coord
438 float(1.0f)), // Value
439 };
440
441 const VkDeviceSize dataSize = DE_LENGTH_OF_ARRAY(vertices) * sizeof(PositionValueVertex);
442 vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
443 m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
444 uint8_t *ptr = reinterpret_cast<uint8_t *>(vertexBuffer->getBoundMemory().getHostPtr());
445
446 deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
447 flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(),
448 vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
449 }
450
451 // Create SSBO buffer
452 {
453 const VkDeviceSize dataSize = sizeof(tcu::Vec4) * numValues;
454 ssboBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT),
455 m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
456 uint8_t *ptr = reinterpret_cast<uint8_t *>(ssboBuffer->getBoundMemory().getHostPtr());
457
458 deMemset(ptr, 0, static_cast<size_t>(dataSize));
459 flushMappedMemoryRange(vk, device, ssboBuffer->getBoundMemory().getMemory(),
460 ssboBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
461 }
462
463 // Create Descriptor Set layout
464 {
465 m_descriptorSetLayout = DescriptorSetLayoutBuilder()
466 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
467 .build(vk, device);
468 }
469
470 // Create Descriptor Set
471 {
472 m_descriptorPool = DescriptorPoolBuilder()
473 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
474 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
475
476 m_descriptorSet = makeDescriptorSet(vk, device, *m_descriptorPool, *m_descriptorSetLayout);
477
478 const VkDescriptorBufferInfo bufferInfo = {
479 ssboBuffer->object(), // VkBuffer buffer;
480 0u, // VkDeviceSize offset;
481 VK_WHOLE_SIZE // VkDeviceSize range;
482 };
483
484 DescriptorSetUpdateBuilder()
485 .writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
486 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo)
487 .update(vk, device);
488 }
489
490 // Create pipeline
491 {
492 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
493
494 VkViewport viewport = makeViewport(WIDTH, HEIGHT);
495 VkRect2D scissor = makeRect2D(WIDTH, HEIGHT);
496
497 const VkVertexInputBindingDescription vertexInputBindingDescription = {
498 0, (uint32_t)(sizeof(tcu::Vec4) + sizeof(float)), VK_VERTEX_INPUT_RATE_VERTEX};
499
500 const VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] = {
501 {0u, 0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u},
502 {1u, 0u, vk::VK_FORMAT_R32_SFLOAT, (uint32_t)(sizeof(float) * 4)}};
503
504 PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(
505 1, &vertexInputBindingDescription, 2, vertexInputAttributeDescriptions);
506
507 m_pipelineLayout = makePipelineLayout(vk, device, *m_descriptorSetLayout);
508
509 PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, 0);
510 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
511 pipelineCreateInfo.addShader(
512 PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
513 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
514 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP));
515 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
516 pipelineCreateInfo.addState(
517 PipelineCreateInfo::ViewportState(1, vector<VkViewport>(1, viewport), vector<VkRect2D>(1, scissor)));
518 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
519 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
520 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState(m_data.samples));
521
522 #ifndef CTS_USES_VULKANSC
523 VkPipelineRenderingCreateInfoKHR renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
524 DE_NULL,
525 0u,
526 1u,
527 &imageFormat,
528 VK_FORMAT_UNDEFINED,
529 VK_FORMAT_UNDEFINED};
530
531 if (m_data.groupParams->useDynamicRendering)
532 pipelineCreateInfo.pNext = &renderingCreateInfo;
533 #endif // CTS_USES_VULKANSC
534
535 m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
536 }
537
538 // Queue draw and read results.
539 {
540 const VkQueue queue = m_context.getUniversalQueue();
541 const ImageSubresourceRange subresourceRange(VK_IMAGE_ASPECT_COLOR_BIT);
542 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
543 const VkRect2D renderArea = makeRect2D(WIDTH, HEIGHT);
544 const VkBuffer buffer = vertexBuffer->object();
545
546 vector<VkClearValue> clearColors;
547 clearColors.push_back(makeClearValueColor(clearColor));
548 if (useMultisampling)
549 clearColors.push_back(makeClearValueColor(clearColor));
550
551 #ifndef CTS_USES_VULKANSC
552 if (m_data.groupParams->useSecondaryCmdBuffer)
553 {
554 secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
555
556 // record secondary command buffer
557 if (m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
558 {
559 beginSecondaryCmdBuffer(*secCmdBuffer, imageFormat,
560 VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
561 beginDynamicRender(*secCmdBuffer, renderArea, clearColors.data());
562 }
563 else
564 beginSecondaryCmdBuffer(*secCmdBuffer, imageFormat);
565
566 drawCommands(*secCmdBuffer, buffer);
567
568 if (m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
569 endRendering(vk, *secCmdBuffer);
570
571 endCommandBuffer(vk, *secCmdBuffer);
572
573 // record primary command buffer
574 beginCommandBuffer(vk, *cmdBuffer, 0u);
575
576 if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
577 beginDynamicRender(*cmdBuffer, renderArea, clearColors.data(),
578 VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
579
580 vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
581
582 if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
583 endRendering(vk, *cmdBuffer);
584
585 endCommandBuffer(vk, *cmdBuffer);
586 }
587 else if (m_data.groupParams->useDynamicRendering)
588 {
589 beginCommandBuffer(vk, *cmdBuffer);
590 beginDynamicRender(*cmdBuffer, renderArea, clearColors.data());
591 drawCommands(*cmdBuffer, buffer);
592 endRendering(vk, *cmdBuffer);
593 endCommandBuffer(vk, *cmdBuffer);
594 }
595 #endif // CTS_USES_VULKANSC
596
597 if (!m_data.groupParams->useDynamicRendering)
598 {
599 beginCommandBuffer(vk, *cmdBuffer);
600 beginRenderPass(*cmdBuffer, renderArea, clearColors.data(), (uint32_t)clearColors.size());
601 drawCommands(*cmdBuffer, buffer);
602 endRenderPass(vk, *cmdBuffer);
603 endCommandBuffer(vk, *cmdBuffer);
604 }
605
606 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
607 }
608
609 qpTestResult res = QP_TEST_RESULT_PASS;
610
611 {
612 const Allocation &resultAlloc = ssboBuffer->getBoundMemory();
613 invalidateAlloc(vk, device, resultAlloc);
614
615 const tcu::Vec4 *ptr = reinterpret_cast<tcu::Vec4 *>(resultAlloc.getHostPtr());
616 for (uint32_t valueNdx = 0u; valueNdx < numValues; valueNdx++)
617 {
618 if (deFloatAbs(ptr[valueNdx].x() - ptr[valueNdx].y()) > 0.0005f)
619 {
620 log << tcu::TestLog::Message << "Expected value " << valueNdx << " is " << ptr[valueNdx].x() << ", got "
621 << ptr[valueNdx].y() << tcu::TestLog::EndMessage;
622 res = QP_TEST_RESULT_FAIL;
623 }
624 }
625 }
626
627 return tcu::TestStatus(res, qpGetTestResultName(res));
628 }
629
beginRenderPass(VkCommandBuffer cmdBuffer,VkRect2D renderArea,const VkClearValue * pClearValues,uint32_t clearValueCount) const630 void DrawTestInstance::beginRenderPass(VkCommandBuffer cmdBuffer, VkRect2D renderArea, const VkClearValue *pClearValues,
631 uint32_t clearValueCount) const
632 {
633 const DeviceInterface &vk = m_context.getDeviceInterface();
634
635 const VkRenderPassBeginInfo renderPassBeginInfo{
636 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
637 DE_NULL, // const void* pNext;
638 *m_renderPass, // VkRenderPass renderPass;
639 *m_framebuffer, // VkFramebuffer framebuffer;
640 renderArea, // VkRect2D renderArea;
641 clearValueCount, // uint32_t clearValueCount;
642 pClearValues, // const VkClearValue* pClearValues;
643 };
644
645 vk.cmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
646 }
647
drawCommands(VkCommandBuffer cmdBuffer,VkBuffer vertexBuffer) const648 void DrawTestInstance::drawCommands(VkCommandBuffer cmdBuffer, VkBuffer vertexBuffer) const
649 {
650 const DeviceInterface &vk = m_context.getDeviceInterface();
651 const VkDeviceSize vertexBufferOffset = 0;
652
653 vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vertexBuffer, &vertexBufferOffset);
654 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
655 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &*m_descriptorSet,
656 0u, DE_NULL);
657 vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
658 }
659
660 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,VkFormat colorFormat,VkRenderingFlagsKHR renderingFlags) const661 void DrawTestInstance::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkFormat colorFormat,
662 VkRenderingFlagsKHR renderingFlags) const
663 {
664 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo{
665 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
666 DE_NULL, // const void* pNext;
667 renderingFlags, // VkRenderingFlagsKHR flags;
668 0u, // uint32_t viewMask;
669 1u, // uint32_t colorAttachmentCount;
670 &colorFormat, // const VkFormat* pColorAttachmentFormats;
671 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
672 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
673 m_data.samples, // VkSampleCountFlagBits rasterizationSamples;
674 };
675 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
676
677 VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
678 if (!m_data.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
679 usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
680
681 const VkCommandBufferBeginInfo commandBufBeginParams{
682 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
683 DE_NULL, // const void* pNext;
684 usageFlags, // VkCommandBufferUsageFlags flags;
685 &bufferInheritanceInfo};
686
687 const DeviceInterface &vk = m_context.getDeviceInterface();
688 VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
689 }
690
beginDynamicRender(VkCommandBuffer cmdBuffer,VkRect2D renderArea,const VkClearValue * pClearValues,VkRenderingFlagsKHR renderingFlags) const691 void DrawTestInstance::beginDynamicRender(VkCommandBuffer cmdBuffer, VkRect2D renderArea,
692 const VkClearValue *pClearValues, VkRenderingFlagsKHR renderingFlags) const
693 {
694 const DeviceInterface &vk = m_context.getDeviceInterface();
695 const bool useMultisampling = m_data.samples != VK_SAMPLE_COUNT_1_BIT;
696
697 VkRenderingAttachmentInfoKHR colorAttachment{
698 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
699 DE_NULL, // const void* pNext;
700 useMultisampling ? *m_multisampleTargetView : *m_colorTargetView, // VkImageView imageView;
701 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout imageLayout;
702 useMultisampling ? VK_RESOLVE_MODE_AVERAGE_BIT : VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
703 useMultisampling ? *m_colorTargetView : DE_NULL, // VkImageView resolveImageView;
704 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout resolveImageLayout;
705 useMultisampling ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
706 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
707 pClearValues[0] // VkClearValue clearValue;
708 };
709
710 VkRenderingInfoKHR renderingInfo{
711 VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
712 DE_NULL,
713 renderingFlags, // VkRenderingFlagsKHR flags;
714 renderArea, // VkRect2D renderArea;
715 1u, // uint32_t layerCount;
716 0u, // uint32_t viewMask;
717 1u, // uint32_t colorAttachmentCount;
718 &colorAttachment, // const VkRenderingAttachmentInfoKHR* pColorAttachments;
719 DE_NULL, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
720 DE_NULL, // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
721 };
722
723 vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
724 }
725 #endif // CTS_USES_VULKANSC
726
createTests(tcu::TestCaseGroup * testGroup,const SharedGroupParams groupParams)727 void createTests(tcu::TestCaseGroup *testGroup, const SharedGroupParams groupParams)
728 {
729 tcu::TestContext &testCtx = testGroup->getTestContext();
730
731 const VkSampleCountFlagBits samples[] = {
732 VK_SAMPLE_COUNT_1_BIT, VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT,
733 VK_SAMPLE_COUNT_16_BIT, VK_SAMPLE_COUNT_32_BIT, VK_SAMPLE_COUNT_64_BIT,
734 };
735
736 const Interpolation interTypes[] = {SMOOTH, NOPERSPECTIVE};
737
738 const AuxiliaryQualifier auxQualifiers[] = {
739 AUX_NONE,
740 AUX_SAMPLE,
741 AUX_CENTROID,
742 };
743
744 for (uint32_t sampleNdx = 0; sampleNdx < DE_LENGTH_OF_ARRAY(samples); sampleNdx++)
745 {
746 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
747 if (groupParams->useSecondaryCmdBuffer && (sampleNdx > VK_SAMPLE_COUNT_2_BIT))
748 continue;
749
750 for (uint32_t auxNdx = 0; auxNdx < DE_LENGTH_OF_ARRAY(auxQualifiers); auxNdx++)
751 for (uint32_t interNdx = 0; interNdx < DE_LENGTH_OF_ARRAY(interTypes); interNdx++)
752 {
753 if (samples[sampleNdx] == VK_SAMPLE_COUNT_1_BIT && auxQualifiers[auxNdx] != AUX_NONE)
754 continue;
755
756 const DrawParams params{interTypes[interNdx], samples[sampleNdx], auxQualifiers[auxNdx], groupParams};
757 testGroup->addChild(new DrawTestCase(testCtx, getTestName(params).c_str(), params));
758 }
759 }
760 }
761
762 } // namespace
763
createExplicitVertexParameterTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)764 tcu::TestCaseGroup *createExplicitVertexParameterTests(tcu::TestContext &testCtx, const SharedGroupParams groupParams)
765 {
766 // Tests for VK_AMD_shader_explicit_vertex_parameter.
767 return createTestGroup(testCtx, "explicit_vertex_parameter", createTests, groupParams);
768 }
769
770 } // namespace Draw
771 } // namespace vkt
772