1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 The Khronos Group Inc.
6 * Copyright (c) 2019 Google Inc.
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 Tests for multiple interpolation decorations in a shader stage
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawMultipleInterpolationTests.hpp"
26
27 #include "tcuStringTemplate.hpp"
28 #include "vkCmdUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vktDrawBaseClass.hpp"
32 #include "vktTestGroupUtil.hpp"
33
34 namespace vkt
35 {
36 namespace Draw
37 {
38 namespace
39 {
40
41 enum Interpolation
42 {
43 SMOOTH = 0,
44 FLAT = 1,
45 NOPERSPECTIVE = 2,
46 CENTROID = 3
47 };
48
49 struct DrawParams
50 {
51 vk::VkFormat format;
52 tcu::UVec2 size;
53 vk::VkSampleCountFlagBits samples;
54 // From the SPIR-V point of view, structured test variants will allow us to test interpolation decorations on struct members
55 // instead of plain ids.
56 bool useStructure;
57 };
58
59 template<typename T>
makeSharedPtr(vk::Move<T> move)60 inline de::SharedPtr<vk::Move<T> > makeSharedPtr(vk::Move<T> move)
61 {
62 return de::SharedPtr<vk::Move<T> >(new vk::Move<T>(move));
63 }
64
interpolationToString(Interpolation interpolation)65 const char* interpolationToString (Interpolation interpolation)
66 {
67 switch (interpolation)
68 {
69 case SMOOTH:
70 return "smooth";
71 case FLAT:
72 return "flat";
73 case NOPERSPECTIVE:
74 return "noperspective";
75 case CENTROID:
76 return "centroid";
77 default:
78 DE_FATAL("Invalid interpolation enum");
79 }
80
81 return "";
82 }
83
84 class DrawTestInstance : public TestInstance
85 {
86 public:
87 DrawTestInstance (Context& context, DrawParams params);
88 void render (std::vector<de::SharedPtr<Image> >& colorTargetImages,
89 tcu::ConstPixelBufferAccess* frames,
90 const char* vsName,
91 const char* fsName);
92 bool compare (const tcu::ConstPixelBufferAccess& result,
93 const tcu::ConstPixelBufferAccess& reference);
94 tcu::TestStatus iterate (void);
95 private:
96 DrawParams m_params;
97 };
98
DrawTestInstance(Context & context,DrawParams params)99 DrawTestInstance::DrawTestInstance (Context& context, DrawParams params)
100 : TestInstance (context)
101 , m_params (params)
102 {
103 }
104
105 class DrawTestCase : public TestCase
106 {
107 public:
108 DrawTestCase (tcu::TestContext& testCtx,
109 const std::string& name,
110 const std::string& description,
111 const DrawParams params);
112 ~DrawTestCase (void);
113 virtual void initPrograms (vk::SourceCollections& programCollection) const;
114 virtual void checkSupport (Context& context) const;
115 virtual TestInstance* createInstance (Context& context) const;
116 private:
117 const DrawParams m_params;
118 };
119
DrawTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const DrawParams params)120 DrawTestCase::DrawTestCase (tcu::TestContext& testCtx,
121 const std::string& name,
122 const std::string& description,
123 const DrawParams params)
124 : TestCase (testCtx, name, description)
125 , m_params (params)
126 {
127 }
128
~DrawTestCase(void)129 DrawTestCase::~DrawTestCase (void)
130 {
131 }
132
initPrograms(vk::SourceCollections & programCollection) const133 void DrawTestCase::initPrograms (vk::SourceCollections& programCollection) const
134 {
135 const std::string blockName = "ifb";
136 const std::map<std::string, std::string> replacements =
137 {
138 std::pair<std::string, std::string>{"blockOpeningOut" , (m_params.useStructure ? "layout(location = 0) out InterfaceBlock {\n" : "")},
139 std::pair<std::string, std::string>{"blockOpeningIn" , (m_params.useStructure ? "layout(location = 0) in InterfaceBlock {\n" : "")},
140 std::pair<std::string, std::string>{"blockClosure" , (m_params.useStructure ? "} " + blockName + ";\n" : "")},
141 std::pair<std::string, std::string>{"extensions" , (m_params.useStructure ? "#extension GL_ARB_enhanced_layouts : require\n" : "")},
142 std::pair<std::string, std::string>{"accessPrefix" , (m_params.useStructure ? blockName + "." : "")},
143 std::pair<std::string, std::string>{"outQual" , (m_params.useStructure ? "" : "out ")},
144 std::pair<std::string, std::string>{"inQual" , (m_params.useStructure ? "" : "in ")},
145 std::pair<std::string, std::string>{"indent" , (m_params.useStructure ? " " : "")},
146 };
147
148 const tcu::StringTemplate vertShaderMulti
149 {
150 "#version 430\n"
151 "${extensions}"
152 "\n"
153 "layout(location = 0) in vec4 in_position;\n"
154 "layout(location = 1) in vec4 in_color;\n"
155 "\n"
156 "${blockOpeningOut}"
157 "${indent}layout(location = 0) ${outQual}vec4 out_color_smooth;\n"
158 "${indent}layout(location = 1) ${outQual}flat vec4 out_color_flat;\n"
159 "${indent}layout(location = 2) ${outQual}noperspective vec4 out_color_noperspective;\n"
160 "${indent}layout(location = 3) ${outQual}centroid vec4 out_color_centroid;\n"
161 "${blockClosure}"
162 "\n"
163 "void main()\n"
164 "{\n"
165 " ${accessPrefix}out_color_smooth = in_color;\n"
166 " ${accessPrefix}out_color_flat = in_color;\n"
167 " ${accessPrefix}out_color_noperspective = in_color;\n"
168 " ${accessPrefix}out_color_centroid = in_color;\n"
169 " gl_Position = in_position;\n"
170 "}\n"
171 };
172
173 const tcu::StringTemplate fragShaderMulti
174 {
175 "#version 430\n"
176 "${extensions}"
177 "\n"
178 "${blockOpeningIn}"
179 "${indent}layout(location = 0) ${inQual}vec4 in_color_smooth;\n"
180 "${indent}layout(location = 1) ${inQual}flat vec4 in_color_flat;\n"
181 "${indent}layout(location = 2) ${inQual}noperspective vec4 in_color_noperspective;\n"
182 "${indent}layout(location = 3) ${inQual}centroid vec4 in_color_centroid;\n"
183 "${blockClosure}"
184 "\n"
185 "layout(location = " + de::toString(SMOOTH) + ") out vec4 out_color_smooth;\n"
186 "layout(location = " + de::toString(FLAT) + ") out vec4 out_color_flat;\n"
187 "layout(location = " + de::toString(NOPERSPECTIVE) + ") out vec4 out_color_noperspective;\n"
188 "layout(location = " + de::toString(CENTROID) + ") out vec4 out_color_centroid;\n"
189 "\n"
190 "void main()\n"
191 "{\n"
192 " out_color_smooth = ${accessPrefix}in_color_smooth;\n"
193 " out_color_flat = ${accessPrefix}in_color_flat;\n"
194 " out_color_noperspective = ${accessPrefix}in_color_noperspective;\n"
195 " out_color_centroid = ${accessPrefix}in_color_centroid;\n"
196 "}\n"
197 };
198
199 const tcu::StringTemplate vertShaderSingle
200 {
201 "#version 430\n"
202 "${extensions}"
203 "\n"
204 "layout(location = 0) in vec4 in_position;\n"
205 "layout(location = 1) in vec4 in_color;\n"
206 "\n"
207 "${blockOpeningOut}"
208 "${indent}layout(location = 0) ${outQual}${qualifier:opt}vec4 out_color;\n"
209 "${blockClosure}"
210 "\n"
211 "void main()\n"
212 "{\n"
213 " ${accessPrefix}out_color = in_color;\n"
214 " gl_Position = in_position;\n"
215 "}\n"
216 };
217
218 const tcu::StringTemplate fragShaderSingle
219 {
220 "#version 430\n"
221 "${extensions}"
222 "\n"
223 "${blockOpeningIn}"
224 "${indent}layout(location = 0) ${inQual}${qualifier:opt}vec4 in_color;\n"
225 "${blockClosure}"
226 "\n"
227 "layout(location = 0) out vec4 out_color;\n"
228 "\n"
229 "void main()\n"
230 "{\n"
231 " out_color = ${accessPrefix}in_color;\n"
232 "}\n"
233 };
234
235 std::map<std::string, std::string> smooth = replacements;
236 std::map<std::string, std::string> flat = replacements;
237 std::map<std::string, std::string> noperspective = replacements;
238 std::map<std::string, std::string> centroid = replacements;
239
240 flat["qualifier"] = "flat ";
241 noperspective["qualifier"] = "noperspective ";
242 centroid["qualifier"] = "centroid ";
243
244 programCollection.glslSources.add("vert_multi") << glu::VertexSource(vertShaderMulti.specialize(replacements));
245 programCollection.glslSources.add("frag_multi") << glu::FragmentSource(fragShaderMulti.specialize(replacements));
246 programCollection.glslSources.add("vert_smooth") << glu::VertexSource(vertShaderSingle.specialize(smooth));
247 programCollection.glslSources.add("frag_smooth") << glu::FragmentSource(fragShaderSingle.specialize(smooth));
248 programCollection.glslSources.add("vert_flat") << glu::VertexSource(vertShaderSingle.specialize(flat));
249 programCollection.glslSources.add("frag_flat") << glu::FragmentSource(fragShaderSingle.specialize(flat));
250 programCollection.glslSources.add("vert_noperspective") << glu::VertexSource(vertShaderSingle.specialize(noperspective));
251 programCollection.glslSources.add("frag_noperspective") << glu::FragmentSource(fragShaderSingle.specialize(noperspective));
252 programCollection.glslSources.add("vert_centroid") << glu::VertexSource(vertShaderSingle.specialize(centroid));
253 programCollection.glslSources.add("frag_centroid") << glu::FragmentSource(fragShaderSingle.specialize(centroid));
254 }
255
checkSupport(Context & context) const256 void DrawTestCase::checkSupport (Context& context) const
257 {
258 if (!(m_params.samples & context.getDeviceProperties().limits.framebufferColorSampleCounts))
259 throw tcu::NotSupportedError("Multisampling with " + de::toString(m_params.samples) + " samples not supported");
260 }
261
createInstance(Context & context) const262 TestInstance* DrawTestCase::createInstance (Context& context) const
263 {
264 return new DrawTestInstance(context, m_params);
265 }
266
render(std::vector<de::SharedPtr<Image>> & colorTargetImages,tcu::ConstPixelBufferAccess * frames,const char * vsName,const char * fsName)267 void DrawTestInstance::render (std::vector<de::SharedPtr<Image> >& colorTargetImages,
268 tcu::ConstPixelBufferAccess* frames,
269 const char* vsName,
270 const char* fsName)
271 {
272 const bool useMultisampling = (m_params.samples != vk::VK_SAMPLE_COUNT_1_BIT);
273 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
274 const vk::VkDevice device = m_context.getDevice();
275 const vk::Unique<vk::VkShaderModule> vs (createShaderModule(vk, device, m_context.getBinaryCollection().get(vsName), 0));
276 const vk::Unique<vk::VkShaderModule> fs (createShaderModule(vk, device, m_context.getBinaryCollection().get(fsName), 0));
277 const CmdPoolCreateInfo cmdPoolCreateInfo = m_context.getUniversalQueueFamilyIndex();
278 vk::Move<vk::VkCommandPool> cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
279 vk::Move<vk::VkCommandBuffer> cmdBuffer = vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
280 std::vector<de::SharedPtr<Image> > multisampleImages;
281 std::vector<de::SharedPtr<vk::Move<vk::VkImageView> > > colorTargetViews;
282 std::vector<de::SharedPtr<vk::Move<vk::VkImageView> > > multisampleViews;
283 de::SharedPtr<Buffer> vertexBuffer;
284 vk::Move<vk::VkRenderPass> renderPass;
285 vk::Move<vk::VkFramebuffer> framebuffer;
286 vk::Move<vk::VkPipeline> pipeline;
287
288 // Create color buffer images
289 for (deUint32 frameNdx = 0; frameNdx < colorTargetImages.size(); frameNdx++)
290 {
291 const vk::VkExtent3D targetImageExtent = { m_params.size.x(), m_params.size.y(), 1 };
292 const vk::VkImageUsageFlags usage = vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;
293 const ImageCreateInfo targetImageCreateInfo (vk::VK_IMAGE_TYPE_2D,
294 m_params.format,
295 targetImageExtent,
296 1,
297 1,
298 vk::VK_SAMPLE_COUNT_1_BIT,
299 vk::VK_IMAGE_TILING_OPTIMAL,
300 usage);
301
302 colorTargetImages[frameNdx] = Image::createAndAlloc(vk, device, targetImageCreateInfo,
303 m_context.getDefaultAllocator(),
304 m_context.getUniversalQueueFamilyIndex());
305
306 if (useMultisampling)
307 {
308 const ImageCreateInfo multisampleImageCreateInfo (vk::VK_IMAGE_TYPE_2D,
309 m_params.format,
310 targetImageExtent,
311 1,
312 1,
313 m_params.samples,
314 vk::VK_IMAGE_TILING_OPTIMAL,
315 usage);
316
317 multisampleImages.push_back(Image::createAndAlloc(vk, device, multisampleImageCreateInfo,
318 m_context.getDefaultAllocator(),
319 m_context.getUniversalQueueFamilyIndex()));
320 }
321 }
322
323 // Create render pass and framebuffer
324 {
325 RenderPassCreateInfo renderPassCreateInfo;
326 std::vector<vk::VkImageView> attachments;
327 std::vector<vk::VkAttachmentReference> colorAttachmentRefs;
328 std::vector<vk::VkAttachmentReference> multisampleAttachmentRefs;
329 deUint32 attachmentNdx = 0;
330
331 for (deUint32 frameNdx = 0; frameNdx < colorTargetImages.size(); frameNdx++)
332 {
333 const ImageViewCreateInfo colorTargetViewInfo (colorTargetImages[frameNdx]->object(),
334 vk::VK_IMAGE_VIEW_TYPE_2D,
335 m_params.format);
336
337 const vk::VkAttachmentReference colorAttachmentReference =
338 {
339 attachmentNdx++,
340 vk::VK_IMAGE_LAYOUT_GENERAL
341 };
342
343 colorTargetViews.push_back(makeSharedPtr(createImageView(vk, device, &colorTargetViewInfo)));
344 colorAttachmentRefs.push_back(colorAttachmentReference);
345
346 renderPassCreateInfo.addAttachment(AttachmentDescription(m_params.format,
347 vk::VK_SAMPLE_COUNT_1_BIT,
348 vk::VK_ATTACHMENT_LOAD_OP_CLEAR,
349 vk::VK_ATTACHMENT_STORE_OP_STORE,
350 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
351 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
352 vk::VK_IMAGE_LAYOUT_UNDEFINED,
353 vk::VK_IMAGE_LAYOUT_GENERAL));
354
355 if (useMultisampling)
356 {
357 const ImageViewCreateInfo multisamplingTargetViewInfo (multisampleImages[frameNdx]->object(),
358 vk::VK_IMAGE_VIEW_TYPE_2D,
359 m_params.format);
360
361 const vk::VkAttachmentReference multiSampleAttachmentReference =
362 {
363 attachmentNdx++,
364 vk::VK_IMAGE_LAYOUT_GENERAL
365 };
366
367 multisampleViews.push_back(makeSharedPtr(createImageView(vk, device, &multisamplingTargetViewInfo)));
368 multisampleAttachmentRefs.push_back(multiSampleAttachmentReference);
369
370 renderPassCreateInfo.addAttachment(AttachmentDescription(m_params.format,
371 m_params.samples,
372 vk::VK_ATTACHMENT_LOAD_OP_CLEAR,
373 vk::VK_ATTACHMENT_STORE_OP_STORE,
374 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,
375 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,
376 vk::VK_IMAGE_LAYOUT_UNDEFINED,
377 vk::VK_IMAGE_LAYOUT_GENERAL));
378 }
379 }
380
381 renderPassCreateInfo.addSubpass(SubpassDescription(vk::VK_PIPELINE_BIND_POINT_GRAPHICS,
382 0,
383 0,
384 DE_NULL,
385 (deUint32)colorAttachmentRefs.size(),
386 useMultisampling ? &multisampleAttachmentRefs[0] : &colorAttachmentRefs[0],
387 useMultisampling ? &colorAttachmentRefs[0] : DE_NULL,
388 AttachmentReference(),
389 0,
390 DE_NULL));
391
392 renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
393
394 for (deUint32 frameNdx = 0; frameNdx < colorTargetViews.size(); frameNdx++)
395 {
396 attachments.push_back(**colorTargetViews[frameNdx]);
397
398 if (useMultisampling)
399 attachments.push_back(**multisampleViews[frameNdx]);
400 }
401
402 const vk::VkFramebufferCreateInfo framebufferCreateInfo =
403 {
404 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
405 DE_NULL,
406 0u,
407 *renderPass,
408 (deUint32)attachments.size(),
409 &attachments[0],
410 m_params.size.x(),
411 m_params.size.y(),
412 1
413 };
414
415 framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
416 }
417
418 // Create vertex buffer.
419 {
420 const PositionColorVertex vertices[] =
421 {
422 PositionColorVertex(
423 tcu::Vec4(-1.5f, -0.4f, 1.0f, 2.0f), // Coord
424 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)), // Color
425
426 PositionColorVertex(
427 tcu::Vec4(0.4f, -0.4f, 0.5f, 0.5f), // Coord
428 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)), // Color
429
430 PositionColorVertex(
431 tcu::Vec4(0.3f, 0.8f, 0.0f, 1.0f), // Coord
432 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f)) // Color
433 };
434
435 const vk::VkDeviceSize dataSize = DE_LENGTH_OF_ARRAY(vertices) * sizeof(PositionColorVertex);
436 vertexBuffer = Buffer::createAndAlloc(vk,
437 device,
438 BufferCreateInfo(dataSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
439 m_context.getDefaultAllocator(),
440 vk::MemoryRequirement::HostVisible);
441 deUint8* ptr = reinterpret_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
442
443 deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
444 flushMappedMemoryRange(vk,
445 device,
446 vertexBuffer->getBoundMemory().getMemory(),
447 vertexBuffer->getBoundMemory().getOffset(),
448 VK_WHOLE_SIZE);
449 }
450
451 // Create pipeline
452 {
453 const vk::VkViewport viewport = vk::makeViewport(m_params.size.x(), m_params.size.y());
454 const vk::VkRect2D scissor = vk::makeRect2D(m_params.size.x(), m_params.size.y());
455 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
456 const vk::Move<vk::VkPipelineLayout> pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
457 PipelineCreateInfo pipelineCreateInfo (*pipelineLayout, *renderPass, 0, 0);
458
459 const vk::VkVertexInputBindingDescription vertexInputBindingDescription =
460 {
461 0,
462 (deUint32)sizeof(tcu::Vec4) * 2,
463 vk::VK_VERTEX_INPUT_RATE_VERTEX
464 };
465
466 const vk::VkVertexInputAttributeDescription vertexInputAttributeDescriptions[2] =
467 {
468 { 0u, 0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
469 { 1u, 0u, vk::VK_FORMAT_R32G32B32A32_SFLOAT, (deUint32)(sizeof(float) * 4) }
470 };
471
472 std::vector<PipelineCreateInfo::ColorBlendState::Attachment> vkCbAttachmentStates (colorTargetImages.size());
473 PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1,
474 &vertexInputBindingDescription,
475 2,
476 vertexInputAttributeDescriptions);
477
478 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", vk::VK_SHADER_STAGE_VERTEX_BIT));
479 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", vk::VK_SHADER_STAGE_FRAGMENT_BIT));
480 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
481 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
482 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState((deUint32)vkCbAttachmentStates.size(), &vkCbAttachmentStates[0]));
483 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<vk::VkViewport>(1, viewport), std::vector<vk::VkRect2D>(1, scissor)));
484 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
485 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
486 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState(m_params.samples));
487
488 pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
489 }
490
491 // Queue draw and read results.
492 {
493 const vk::VkQueue queue = m_context.getUniversalQueue();
494 const vk::VkRect2D renderArea = vk::makeRect2D(m_params.size.x(), m_params.size.y());
495 const vk::VkDeviceSize vertexBufferOffset = 0;
496 const vk::VkBuffer buffer = vertexBuffer->object();
497 const vk::VkOffset3D zeroOffset = { 0, 0, 0 };
498 std::vector<vk::VkClearValue> clearValues;
499
500 for (deUint32 i = 0; i < colorTargetImages.size() + multisampleImages.size(); i++)
501 clearValues.push_back(vk::makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
502
503 beginCommandBuffer(vk, *cmdBuffer, 0u);
504 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, (deUint32)clearValues.size(), &clearValues[0]);
505 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &vertexBufferOffset);
506 vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
507 vk.cmdDraw(*cmdBuffer, 3u, 1u, 0u, 0u);
508 endRenderPass(vk, *cmdBuffer);
509
510 endCommandBuffer(vk, *cmdBuffer);
511 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
512
513 for (deUint32 frameNdx = 0; frameNdx < colorTargetImages.size(); frameNdx++)
514 {
515 frames[frameNdx] = colorTargetImages[frameNdx]->readSurface(queue,
516 m_context.getDefaultAllocator(),
517 vk::VK_IMAGE_LAYOUT_GENERAL,
518 zeroOffset,
519 (int)m_params.size.x(),
520 (int)m_params.size.y(),
521 vk::VK_IMAGE_ASPECT_COLOR_BIT);
522 }
523 }
524 }
525
compare(const tcu::ConstPixelBufferAccess & result,const tcu::ConstPixelBufferAccess & reference)526 bool DrawTestInstance::compare (const tcu::ConstPixelBufferAccess& result, const tcu::ConstPixelBufferAccess& reference)
527 {
528 DE_ASSERT(result.getSize() == reference.getSize());
529
530 const size_t size = result.getWidth() * result.getHeight() * vk::mapVkFormat(m_params.format).getPixelSize();
531 const int res = deMemCmp(result.getDataPtr(), reference.getDataPtr(), size);
532
533 return (res == 0);
534 }
535
iterate(void)536 tcu::TestStatus DrawTestInstance::iterate (void)
537 {
538 tcu::TestLog& log = m_context.getTestContext().getLog();
539 const bool useMultisampling = (m_params.samples != vk::VK_SAMPLE_COUNT_1_BIT);
540 const deUint32 frameCount = 4;
541 std::vector<de::SharedPtr<Image> > resImages (frameCount);
542 std::vector<de::SharedPtr<Image> > smoothImage (1);
543 std::vector<de::SharedPtr<Image> > flatImage (1);
544 std::vector<de::SharedPtr<Image> > noperspectiveImage (1);
545 std::vector<de::SharedPtr<Image> > centroidImage (1);
546 tcu::ConstPixelBufferAccess resFrames[frameCount];
547 tcu::ConstPixelBufferAccess refFrames[frameCount];
548
549 render(resImages, resFrames, "vert_multi", "frag_multi");
550 render(smoothImage, &refFrames[SMOOTH], "vert_smooth", "frag_smooth");
551 render(flatImage, &refFrames[FLAT], "vert_flat", "frag_flat");
552 render(noperspectiveImage, &refFrames[NOPERSPECTIVE], "vert_noperspective", "frag_noperspective");
553 render(centroidImage, &refFrames[CENTROID], "vert_centroid", "frag_centroid");
554
555 for (deUint32 resNdx = 0; resNdx < frameCount; resNdx++)
556 {
557 const std::string resName = interpolationToString((Interpolation)resNdx);
558
559 log << tcu::TestLog::ImageSet(resName, resName)
560 << tcu::TestLog::Image("Result", "Result", resFrames[resNdx])
561 << tcu::TestLog::Image("Reference", "Reference", refFrames[resNdx])
562 << tcu::TestLog::EndImageSet;
563
564 for (deUint32 refNdx = 0; refNdx < frameCount; refNdx++)
565 {
566 const std::string refName = interpolationToString((Interpolation)refNdx);
567
568 if (resNdx == refNdx)
569 {
570 if (!compare(resFrames[resNdx], refFrames[refNdx]))
571 return tcu::TestStatus::fail(resName + " produced different results");
572 }
573 else if (!useMultisampling && ((resNdx == SMOOTH && refNdx == CENTROID) || (resNdx == CENTROID && refNdx == SMOOTH)))
574 {
575 if (!compare(resFrames[resNdx], refFrames[refNdx]))
576 return tcu::TestStatus::fail(resName + " and " + refName + " produced different results without multisampling");
577 }
578 else
579 {
580 if (compare(resFrames[resNdx], refFrames[refNdx]))
581 return tcu::TestStatus::fail(resName + " and " + refName + " produced same result");
582 }
583 }
584 }
585
586 return tcu::TestStatus::pass("Results differ and references match");
587 }
588
createTests(tcu::TestCaseGroup * testGroup)589 void createTests (tcu::TestCaseGroup* testGroup)
590 {
591 tcu::TestContext& testCtx = testGroup->getTestContext();
592 const vk::VkFormat format = vk::VK_FORMAT_R8G8B8A8_UNORM;
593 const tcu::UVec2 size (128, 128);
594
595 struct TestVariant
596 {
597 const std::string name;
598 const std::string desc;
599 const vk::VkSampleCountFlagBits samples;
600 };
601
602 static const std::vector<TestVariant> testVariants =
603 {
604 { "1_sample", "Without multisampling", vk::VK_SAMPLE_COUNT_1_BIT },
605 { "2_samples", "2 samples", vk::VK_SAMPLE_COUNT_2_BIT },
606 { "4_samples", "4 samples", vk::VK_SAMPLE_COUNT_4_BIT },
607 { "8_samples", "8 samples", vk::VK_SAMPLE_COUNT_8_BIT },
608 { "16_samples", "16 samples", vk::VK_SAMPLE_COUNT_16_BIT },
609 { "32_samples", "32 samples", vk::VK_SAMPLE_COUNT_32_BIT },
610 { "64_samples", "64 samples", vk::VK_SAMPLE_COUNT_64_BIT },
611 };
612
613 struct GroupVariant
614 {
615 const bool useStructure;
616 const std::string groupName;
617 };
618
619 static const std::vector<GroupVariant> groupVariants =
620 {
621 { false, "separate" },
622 { true, "structured" },
623 };
624
625 for (const auto& grpVariant : groupVariants)
626 {
627 de::MovePtr<tcu::TestCaseGroup> group {new tcu::TestCaseGroup{testCtx, grpVariant.groupName.c_str(), ""}};
628
629 for (const auto& testVariant : testVariants)
630 {
631 const DrawParams params {format, size, testVariant.samples, grpVariant.useStructure};
632 group->addChild(new DrawTestCase(testCtx, testVariant.name, testVariant.desc, params));
633 }
634
635 testGroup->addChild(group.release());
636 }
637 }
638
639 } // anonymous
640
createMultipleInterpolationTests(tcu::TestContext & testCtx)641 tcu::TestCaseGroup* createMultipleInterpolationTests (tcu::TestContext& testCtx)
642 {
643 return createTestGroup(testCtx,
644 "multiple_interpolation",
645 "Tests for multiple interpolation decorations in a shader stage.",
646 createTests);
647 }
648
649 } // Draw
650 } // vkt
651