1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2022 The Khronos Group Inc.
6 * Copyright (c) 2022 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 vktDrawMultisampleLinearInterpolationTests.cpp
22 * \brief InterpolateAt tests with linear interpolation
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktDrawMultisampleLinearInterpolationTests.hpp"
26
27 #include "vktDrawBaseClass.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
32
33 namespace vkt
34 {
35 namespace Draw
36 {
37 namespace
38 {
39 using namespace vk;
40
41 class MultisampleLinearInterpolationTestInstance : public TestInstance
42 {
43 public:
MultisampleLinearInterpolationTestInstance(Context & context,const tcu::IVec2 renderSize,const float interpolationRange,const VkSampleCountFlagBits sampleCountFlagBits,const SharedGroupParams groupParams)44 MultisampleLinearInterpolationTestInstance (Context& context,
45 const tcu::IVec2 renderSize,
46 const float interpolationRange,
47 const VkSampleCountFlagBits sampleCountFlagBits,
48 const SharedGroupParams groupParams)
49 : vkt::TestInstance (context)
50 , m_renderSize (renderSize)
51 , m_interpolationRange (interpolationRange)
52 , m_sampleCountFlagBits (sampleCountFlagBits)
53 , m_groupParams (groupParams)
54 {}
55
~MultisampleLinearInterpolationTestInstance(void)56 ~MultisampleLinearInterpolationTestInstance (void)
57 {}
58
59 tcu::TestStatus iterate (void);
60
61 private:
62 const tcu::IVec2 m_renderSize;
63 const float m_interpolationRange;
64 const VkSampleCountFlagBits m_sampleCountFlagBits;
65 const SharedGroupParams m_groupParams;
66 };
67
iterate(void)68 tcu::TestStatus MultisampleLinearInterpolationTestInstance::iterate (void)
69 {
70 const DeviceInterface& vk = m_context.getDeviceInterface();
71 const VkDevice device = m_context.getDevice();
72
73 tcu::ConstPixelBufferAccess resultPixelBufferAccesses[2];
74 de::SharedPtr<Image> colorTargetImages[2];
75 de::SharedPtr<Image> multisampleImages[2];
76
77 const VkFormat imageColorFormat = VK_FORMAT_R8G8B8A8_UNORM;
78
79 const std::string vertShadernames[2] = { "vertRef", "vertNoPer" };
80 const std::string fragShadernames[2] = { "fragRef", "fragNoPer" };
81
82 tcu::TestLog& log = m_context.getTestContext().getLog();
83
84 const bool useMultisampling = m_sampleCountFlagBits == VK_SAMPLE_COUNT_1_BIT ? false : true;
85
86 for (int draw = 0; draw < 2; draw++)
87 {
88 const Unique<VkShaderModule> vs (createShaderModule(vk, device, m_context.getBinaryCollection().get(vertShadernames[draw].c_str()), 0));
89 const Unique<VkShaderModule> fs (createShaderModule(vk, device, m_context.getBinaryCollection().get(fragShadernames[draw].c_str()), 0));
90
91 de::SharedPtr<Buffer> vertexBuffer;
92
93 const CmdPoolCreateInfo cmdPoolCreateInfo (m_context.getUniversalQueueFamilyIndex());
94 Move<VkCommandPool> cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
95 Move<VkCommandBuffer> cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
96 Move<VkCommandBuffer> secCmdBuffer;
97
98 Move<VkRenderPass> renderPass;
99
100 std::vector<Move<VkImageView>> colorTargetViews;
101 std::vector<Move<VkImageView>> multisampleViews;
102
103 Move<VkFramebuffer> framebuffer;
104
105 Move<VkPipeline> pipeline;
106 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
107 Move<VkPipelineLayout> pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
108
109 const VkVertexInputAttributeDescription vertInAttrDescs[2] =
110 {
111 { 0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
112 { 1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<deUint32>(sizeof(float) * 4) }
113 };
114
115 // Create color buffer images
116 {
117 const VkExtent3D targetImageExtent = { static_cast<deUint32>(m_renderSize.x()), static_cast<deUint32>(m_renderSize.y()), 1u };
118 const VkImageUsageFlags usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
119 const ImageCreateInfo targetImageCreateInfo (VK_IMAGE_TYPE_2D,
120 imageColorFormat,
121 targetImageExtent,
122 1u,
123 1u,
124 VK_SAMPLE_COUNT_1_BIT,
125 VK_IMAGE_TILING_OPTIMAL,
126 usage);
127
128 colorTargetImages[draw] = Image::createAndAlloc(vk, device, targetImageCreateInfo,
129 m_context.getDefaultAllocator(),
130 m_context.getUniversalQueueFamilyIndex());
131
132 if (useMultisampling)
133 {
134 const ImageCreateInfo multisampleImageCreateInfo (VK_IMAGE_TYPE_2D,
135 imageColorFormat,
136 targetImageExtent,
137 1u,
138 1u,
139 m_sampleCountFlagBits,
140 VK_IMAGE_TILING_OPTIMAL,
141 usage);
142
143 multisampleImages[draw] = Image::createAndAlloc(vk, device, multisampleImageCreateInfo,
144 m_context.getDefaultAllocator(),
145 m_context.getUniversalQueueFamilyIndex());
146 }
147 }
148
149 {
150 const ImageViewCreateInfo colorTargetViewInfo(colorTargetImages[draw]->object(),
151 VK_IMAGE_VIEW_TYPE_2D,
152 imageColorFormat);
153
154 colorTargetViews.push_back(createImageView(vk, device, &colorTargetViewInfo));
155
156 if (useMultisampling)
157 {
158 const ImageViewCreateInfo multisamplingTargetViewInfo(multisampleImages[draw]->object(),
159 VK_IMAGE_VIEW_TYPE_2D,
160 imageColorFormat);
161
162 multisampleViews.push_back(createImageView(vk, device, &multisamplingTargetViewInfo));
163 }
164 }
165
166 // Create render pass and frame buffer.
167 if (!m_groupParams->useDynamicRendering)
168 {
169 RenderPassCreateInfo renderPassCreateInfo;
170 std::vector<VkImageView> attachments;
171 std::vector<VkAttachmentReference> colorAttachmentRefs;
172 std::vector<VkAttachmentReference> multisampleAttachmentRefs;
173 deUint32 attachmentNdx = 0;
174
175 {
176 const VkAttachmentReference colorAttachmentReference =
177 {
178 attachmentNdx++, // uint32_t attachment;
179 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
180 };
181
182 colorAttachmentRefs.push_back(colorAttachmentReference);
183
184 renderPassCreateInfo.addAttachment(AttachmentDescription(imageColorFormat,
185 VK_SAMPLE_COUNT_1_BIT,
186 VK_ATTACHMENT_LOAD_OP_CLEAR,
187 VK_ATTACHMENT_STORE_OP_STORE,
188 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
189 VK_ATTACHMENT_STORE_OP_DONT_CARE,
190 VK_IMAGE_LAYOUT_UNDEFINED,
191 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL));
192
193 if (useMultisampling)
194 {
195 const VkAttachmentReference multiSampleAttachmentReference =
196 {
197 attachmentNdx++, // uint32_t attachment;
198 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
199 };
200
201 multisampleAttachmentRefs.push_back(multiSampleAttachmentReference);
202
203 renderPassCreateInfo.addAttachment(AttachmentDescription(imageColorFormat,
204 m_sampleCountFlagBits,
205 VK_ATTACHMENT_LOAD_OP_CLEAR,
206 VK_ATTACHMENT_STORE_OP_DONT_CARE,
207 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
208 VK_ATTACHMENT_STORE_OP_DONT_CARE,
209 VK_IMAGE_LAYOUT_UNDEFINED,
210 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
211 }
212 }
213
214 renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
215 0,
216 0,
217 DE_NULL,
218 (deUint32)colorAttachmentRefs.size(),
219 useMultisampling ? &multisampleAttachmentRefs[0] : &colorAttachmentRefs[0],
220 useMultisampling ? &colorAttachmentRefs[0] : DE_NULL,
221 AttachmentReference(),
222 0,
223 DE_NULL));
224
225 renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
226
227 for (deUint32 frameNdx = 0; frameNdx < colorTargetViews.size(); frameNdx++)
228 {
229 attachments.push_back(*colorTargetViews[frameNdx]);
230
231 if (useMultisampling)
232 attachments.push_back(*multisampleViews[frameNdx]);
233 }
234
235 const VkFramebufferCreateInfo framebufferCreateInfo =
236 {
237 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
238 DE_NULL, // const void* pNext;
239 0u, // VkFramebufferCreateFlags flags;
240 *renderPass, // VkRenderPass renderPass;
241 static_cast<deUint32>(attachments.size()), // uint32_t attachmentCount;
242 &attachments[0], // const VkImageView* pAttachments;
243 static_cast<deUint32>(m_renderSize.x()), // uint32_t width;
244 static_cast<deUint32>(m_renderSize.y()), // uint32_t height;
245 1u // uint32_t layers;
246 };
247
248 framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
249 }
250
251 // Create vertex buffer.
252 {
253 const PositionColorVertex vertices[] =
254 {
255 // The first draw is for reference image.
256 /* ____ ____ */
257 /* / \ | | */
258 /* / \ |____| */
259 /* / \ */
260 /* /__________\ */
261 /* */
262 /* result reference */
263 /* */
264 // In result shape the bottom vertices are deeper. When the drawn result image is a perfect square,
265 // and color comparison with reference image is easy to make.
266 PositionColorVertex(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, m_interpolationRange, 0.0f, m_interpolationRange)), // Top Right
267 PositionColorVertex(tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec4(m_interpolationRange * 0.5f, m_interpolationRange * 0.5f, 0.0f, m_interpolationRange)), // Top Left
268 PositionColorVertex(tcu::Vec4( draw == 0 ? 1.0f : 2.0f, draw == 0 ? 1.0f : 2.0f, 0.0f, draw == 0 ? 1.0f : 2.0f), tcu::Vec4(m_interpolationRange * 0.5f, m_interpolationRange * 0.5f, 0.0f, m_interpolationRange)), // Bottom Right
269 PositionColorVertex(tcu::Vec4( draw == 0 ? -1.0f : -2.0f, draw == 0 ? 1.0f : 2.0f, 0.0f, draw == 0 ? 1.0f : 2.0f), tcu::Vec4(m_interpolationRange, 0.0f, 0.0f, m_interpolationRange)), // Bottom Left
270 PositionColorVertex(tcu::Vec4( draw == 0 ? 1.0f : 2.0f, draw == 0 ? 1.0f : 2.0f, 0.0f, draw == 0 ? 1.0f : 2.0f), tcu::Vec4(m_interpolationRange * 0.5f, m_interpolationRange * 0.5f, 0.0f, m_interpolationRange)), // Bottom Right
271 PositionColorVertex(tcu::Vec4( -1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec4(m_interpolationRange * 0.5f, m_interpolationRange * 0.5f, 0.0f, m_interpolationRange)) // Top Left
272 };
273
274 const VkDeviceSize dataSize = sizeof(vertices);
275 vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
276 deUint8* ptr = static_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
277
278 deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
279 flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
280 }
281
282 // Create pipeline.
283 {
284 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
285
286 VkViewport viewport = makeViewport(m_renderSize.x(), m_renderSize.y());
287 VkRect2D scissor = makeRect2D(m_renderSize.x(), m_renderSize.y());
288
289 const std::vector<deUint32> sampleMask = { 0xfffffff, 0xfffffff };
290
291 const VkVertexInputBindingDescription vertexInputBindingDescription = { 0, (deUint32)sizeof(tcu::Vec4) * 2, VK_VERTEX_INPUT_RATE_VERTEX };
292 PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertInAttrDescs);
293
294 PipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0);
295
296 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
297 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
298 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
299 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
300 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
301 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<VkViewport>(1, viewport), std::vector<VkRect2D>(1, scissor)));
302 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
303 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
304 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState(m_sampleCountFlagBits, false, 0.0f, sampleMask));
305
306 #ifndef CTS_USES_VULKANSC
307 VkPipelineRenderingCreateInfo renderingCreateInfo
308 {
309 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
310 DE_NULL,
311 0u,
312 1u,
313 &imageColorFormat,
314 VK_FORMAT_UNDEFINED,
315 VK_FORMAT_UNDEFINED
316 };
317
318 if (m_groupParams->useDynamicRendering)
319 pipelineCreateInfo.pNext = &renderingCreateInfo;
320 #endif // CTS_USES_VULKANSC
321
322 pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
323 }
324
325 // Draw quad and read results.
326 {
327 const VkQueue queue = m_context.getUniversalQueue();
328 const VkClearValue clearColor = { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
329 const ImageSubresourceRange subresourceRange (VK_IMAGE_ASPECT_COLOR_BIT);
330 const VkRect2D renderArea = makeRect2D(m_renderSize.x(), m_renderSize.y());
331 const VkBuffer buffer = vertexBuffer->object();
332 const VkOffset3D zeroOffset = { 0, 0, 0 };
333
334 std::vector<VkClearValue> clearValues (2, clearColor);
335
336 auto drawCommands = [&](VkCommandBuffer cmdBuff)
337 {
338 const VkDeviceSize vertexBufferOffset = 0;
339 vk.cmdBindVertexBuffers(cmdBuff, 0, 1, &buffer, &vertexBufferOffset);
340 vk.cmdBindPipeline(cmdBuff, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
341 vk.cmdDraw(cmdBuff, 6u, 1u, 0u, 0u);
342 };
343
344 clearColorImage(vk, device, queue, m_context.getUniversalQueueFamilyIndex(),
345 colorTargetImages[draw]->object(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
346 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
347 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 1u);
348
349 #ifndef CTS_USES_VULKANSC
350 auto preRenderBarriers = [&]()
351 {
352 // Transition Images
353 initialTransitionColor2DImage(vk, *cmdBuffer, colorTargetImages[draw]->object(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
354 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
355
356 if (useMultisampling)
357 {
358 initialTransitionColor2DImage(vk, *cmdBuffer, multisampleImages[draw]->object(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
359 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
360 }
361 };
362
363 if (m_groupParams->useDynamicRendering)
364 {
365 const deUint32 imagesCount = static_cast<deUint32>(colorTargetViews.size());
366
367 std::vector<VkRenderingAttachmentInfo> colorAttachments(imagesCount,
368 {
369 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
370 DE_NULL, // const void* pNext;
371 DE_NULL, // VkImageView imageView;
372 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
373 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
374 DE_NULL, // VkImageView resolveImageView;
375 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout resolveImageLayout;
376 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
377 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
378 clearColor // VkClearValue clearValue;
379 });
380
381 for (deUint32 i = 0; i < imagesCount; ++i)
382 {
383 if (useMultisampling)
384 {
385 colorAttachments[i].imageView = *multisampleViews[i];
386 colorAttachments[i].resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
387 colorAttachments[i].resolveImageView = *colorTargetViews[i];
388 }
389 else
390 {
391 colorAttachments[i].imageView = *colorTargetViews[i];
392 }
393 }
394
395 VkRenderingInfo renderingInfo
396 {
397 VK_STRUCTURE_TYPE_RENDERING_INFO, // VkStructureType sType;
398 DE_NULL, // const void* pNext;
399 0, // VkRenderingFlagsKHR flags;
400 renderArea, // VkRect2D renderArea;
401 1u, // deUint32 layerCount;
402 0u, // deUint32 viewMask;
403 imagesCount, // deUint32 colorAttachmentCount;
404 colorAttachments.data(), // const VkRenderingAttachmentInfoKHR* pColorAttachments;
405 DE_NULL, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
406 DE_NULL, // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
407 };
408
409 if (m_groupParams->useSecondaryCmdBuffer)
410 {
411 VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
412 {
413 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR, // VkStructureType sType;
414 DE_NULL, // const void* pNext;
415 0u, // VkRenderingFlagsKHR flags;
416 0u, // uint32_t viewMask;
417 1u, // uint32_t colorAttachmentCount;
418 &imageColorFormat, // const VkFormat* pColorAttachmentFormats;
419 VK_FORMAT_UNDEFINED, // VkFormat depthAttachmentFormat;
420 VK_FORMAT_UNDEFINED, // VkFormat stencilAttachmentFormat;
421 m_sampleCountFlagBits // VkSampleCountFlagBits rasterizationSamples;
422 };
423
424 const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
425 VkCommandBufferBeginInfo commandBufBeginParams
426 {
427 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
428 DE_NULL, // const void* pNext;
429 VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, // VkCommandBufferUsageFlags flags;
430 &bufferInheritanceInfo
431 };
432
433 secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
434
435 // record secondary command buffer
436 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
437 {
438 inheritanceRenderingInfo.flags = VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT;
439 VK_CHECK(vk.beginCommandBuffer(*secCmdBuffer, &commandBufBeginParams));
440 vk.cmdBeginRendering(*secCmdBuffer, &renderingInfo);
441 }
442 else
443 {
444 commandBufBeginParams.flags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
445 VK_CHECK(vk.beginCommandBuffer(*secCmdBuffer, &commandBufBeginParams));
446 }
447
448 drawCommands(*secCmdBuffer);
449
450 if (m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
451 endRendering(vk, *secCmdBuffer);
452
453 endCommandBuffer(vk, *secCmdBuffer);
454
455 // record primary command buffer
456 beginCommandBuffer(vk, *cmdBuffer, 0u);
457
458 preRenderBarriers();
459
460 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
461 {
462 renderingInfo.flags = VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS;
463 vk.cmdBeginRendering(*cmdBuffer, &renderingInfo);
464 }
465 vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
466
467 if (!m_groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
468 endRendering(vk, *cmdBuffer);
469 endCommandBuffer(vk, *cmdBuffer);
470 }
471 else
472 {
473 beginCommandBuffer(vk, *cmdBuffer, 0u);
474 preRenderBarriers();
475
476 vk.cmdBeginRendering(*cmdBuffer, &renderingInfo);
477 drawCommands(*cmdBuffer);
478 endRendering(vk, *cmdBuffer);
479
480 endCommandBuffer(vk, *cmdBuffer);
481 }
482 }
483 else
484 #endif // CTS_USES_VULKANSC
485 {
486 beginCommandBuffer(vk, *cmdBuffer, 0u);
487
488 const deUint32 imagesCount = static_cast<deUint32>(colorTargetViews.size() + multisampleViews.size());
489
490 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, imagesCount, &clearValues[0]);
491 drawCommands(*cmdBuffer);
492 endRenderPass(vk, *cmdBuffer);
493
494 endCommandBuffer(vk, *cmdBuffer);
495 }
496
497 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
498
499 resultPixelBufferAccesses[draw] = colorTargetImages[draw]->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, zeroOffset, m_renderSize.x(), m_renderSize.y(), VK_IMAGE_ASPECT_COLOR_BIT);
500 }
501 }
502
503 if (!tcu::floatThresholdCompare(log, "Result", "Image comparison result", resultPixelBufferAccesses[0], resultPixelBufferAccesses[1], tcu::Vec4(0.005f), tcu::COMPARE_LOG_RESULT))
504 return tcu::TestStatus::fail("Rendered color image is not correct");
505
506 return tcu::TestStatus::pass("Success");
507 }
508
509 class MultisampleLinearInterpolationTestCase : public TestCase
510 {
511 public:
MultisampleLinearInterpolationTestCase(tcu::TestContext & context,const char * name,const char * desc,const tcu::IVec2 renderSize,const float interpolationRange,const tcu::Vec2 offset,const VkSampleCountFlagBits sampleCountFlagBits,const SharedGroupParams groupParams)512 MultisampleLinearInterpolationTestCase (tcu::TestContext& context,
513 const char* name,
514 const char* desc,
515 const tcu::IVec2 renderSize,
516 const float interpolationRange,
517 const tcu::Vec2 offset,
518 const VkSampleCountFlagBits sampleCountFlagBits,
519 const SharedGroupParams groupParams)
520 : vkt::TestCase(context, name, desc)
521 , m_renderSize (renderSize)
522 , m_interpolationRange (interpolationRange)
523 , m_offset (offset)
524 , m_sampleCountFlagBits (sampleCountFlagBits)
525 , m_groupParams (groupParams)
526 {}
527
~MultisampleLinearInterpolationTestCase(void)528 ~MultisampleLinearInterpolationTestCase (void)
529 {}
530
531 virtual void initPrograms (SourceCollections& programCollection) const;
532 virtual void checkSupport (Context& context) const;
533 virtual TestInstance* createInstance (Context& context) const;
534
535 private:
536 const tcu::IVec2 m_renderSize;
537 const float m_interpolationRange;
538 const tcu::Vec2 m_offset;
539 const VkSampleCountFlagBits m_sampleCountFlagBits;
540 const SharedGroupParams m_groupParams;
541 };
542
initPrograms(SourceCollections & programCollection) const543 void MultisampleLinearInterpolationTestCase::initPrograms (SourceCollections& programCollection) const
544 {
545 // Reference vertex shader.
546 {
547 std::ostringstream vrt;
548
549 vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
550 << "\n"
551 << "layout(location = 0) in vec4 in_position;\n"
552 << "layout(location = 1) in vec4 in_color;\n"
553 << "layout(location = 0) out vec4 out_color;\n"
554 << "\n"
555 << "void main()\n"
556 << "{\n"
557 << " gl_PointSize = 1.0;\n"
558 << " gl_Position = in_position;\n"
559 << " out_color = in_color;\n"
560 << "}\n";
561
562 programCollection.glslSources.add("vertRef") << glu::VertexSource(vrt.str());
563 }
564
565 // Noperspective vertex shader.
566 {
567 std::ostringstream vrt;
568
569 vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
570 << "\n"
571 << "layout(location = 0) in vec4 in_position;\n"
572 << "layout(location = 1) in vec4 in_color;\n"
573 << "layout(location = 0) noperspective out vec4 out_color;\n"
574 << "\n"
575 << "void main()\n"
576 << "{\n"
577 << " gl_PointSize = 1.0;\n"
578 << " gl_Position = in_position;\n"
579 << " out_color = in_color;\n"
580 << "}\n";
581
582 programCollection.glslSources.add("vertNoPer") << glu::VertexSource(vrt.str());
583 }
584
585 // Reference fragment shader.
586 {
587 std::ostringstream frg;
588
589 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
590 << "layout(location = 0) in vec4 in_color;\n"
591 << "layout(location = 0) out vec4 out_color;\n"
592 << "void main()\n"
593 << "{\n"
594 << " vec4 out_color_y = mix(vec4(0.0, 1.0, 0.0, 1.0), vec4(1.0, 0.0, 0.0, 1.0), gl_FragCoord.y / " << static_cast<float>(m_renderSize.y()) << " + " << m_offset.y() / static_cast<float>(m_renderSize.y()) << ");\n"
595 << " vec4 out_color_x = mix(vec4(1.0, 0.0, 0.0, 1.0), vec4(0.0, 1.0, 0.0, 1.0), gl_FragCoord.x / " << static_cast<float>(m_renderSize.x()) << " + " << m_offset.x() / static_cast<float>(m_renderSize.x()) << ");\n"
596 << " out_color = 0.5 * (out_color_y + out_color_x);\n"
597 << "}\n";
598
599 programCollection.glslSources.add("fragRef") << glu::FragmentSource(frg.str());
600 }
601
602 // Noperspective fragment shader.
603 {
604 std::ostringstream frg;
605
606 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
607 << "layout(location = 0) noperspective in vec4 in_color;\n"
608 << "layout(location = 0) out vec4 out_color;\n"
609 << "void main()\n"
610 << "{\n"
611 << " vec4 out_color_offset = interpolateAtOffset(in_color, vec2(" << m_offset.x() << ", " << m_offset.y() << "));\n"
612 << " vec4 out_color_sample = interpolateAtSample(in_color, gl_SampleID);\n"
613 << " out_color = (0.5 * (out_color_offset + out_color_sample));\n"
614 << " out_color /= " << m_interpolationRange << ";\n";
615
616 // Run additional sample comparison test. If it fails, we write 1.0 to blue color channel.
617 frg << " vec4 diff = out_color_sample - interpolateAtOffset(in_color, gl_SamplePosition - vec2(0.5));"
618 << " float min_precision = 0.000001;\n"
619 << " if (diff.x > min_precision && diff.y > min_precision && diff.z > min_precision && diff.w > min_precision)\n"
620 << " {\n"
621 << " out_color.z = 1.0;\n"
622 << " }\n";
623
624 frg << "}\n";
625
626 programCollection.glslSources.add("fragNoPer") << glu::FragmentSource(frg.str());
627 }
628 }
629
checkSupport(Context & context) const630 void MultisampleLinearInterpolationTestCase::checkSupport (Context& context) const
631 {
632 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING);
633
634 if (!(m_sampleCountFlagBits & context.getDeviceProperties().limits.framebufferColorSampleCounts))
635 TCU_THROW(NotSupportedError, "Multisampling with " + de::toString(m_sampleCountFlagBits) + " samples not supported");
636
637 #ifndef CTS_USES_VULKANSC
638 if (m_groupParams->useDynamicRendering)
639 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
640
641 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
642 !context.getPortabilitySubsetFeatures().shaderSampleRateInterpolationFunctions)
643 {
644 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Shader sample rate interpolation functions are not supported by this implementation");
645 }
646 #endif // CTS_USES_VULKANSC
647 }
648
createInstance(Context & context) const649 TestInstance* MultisampleLinearInterpolationTestCase::createInstance (Context& context) const
650 {
651 return new MultisampleLinearInterpolationTestInstance(context, m_renderSize, m_interpolationRange, m_sampleCountFlagBits, m_groupParams);
652 }
653
createTests(tcu::TestCaseGroup * testGroup,const SharedGroupParams groupParams)654 void createTests (tcu::TestCaseGroup* testGroup, const SharedGroupParams groupParams)
655 {
656 tcu::TestContext& testCtx = testGroup->getTestContext();
657
658 struct
659 {
660 const std::string name;
661 const tcu::Vec2 value;
662 } offsets[] =
663 {
664 { "no_offset", tcu::Vec2(0.0f, 0.0f) },
665 { "offset_min", tcu::Vec2(-0.5f, -0.5f) },
666 { "offset_max", tcu::Vec2(0.4375f, 0.4375f) }
667 };
668
669 struct
670 {
671 const std::string name;
672 VkSampleCountFlagBits value;
673 } flagBits[] =
674 {
675 { "1_sample", VK_SAMPLE_COUNT_1_BIT },
676 { "2_samples", VK_SAMPLE_COUNT_2_BIT },
677 { "4_samples", VK_SAMPLE_COUNT_4_BIT },
678 { "8_samples", VK_SAMPLE_COUNT_8_BIT },
679 { "16_samples", VK_SAMPLE_COUNT_16_BIT },
680 { "32_samples", VK_SAMPLE_COUNT_32_BIT },
681 { "64_samples", VK_SAMPLE_COUNT_64_BIT }
682 };
683
684 for (const auto& offset : offsets)
685 {
686 for (const auto& flagBit : flagBits)
687 {
688 // reduce number of tests for dynamic rendering cases where secondary command buffer is used
689 if (groupParams->useSecondaryCmdBuffer && (flagBit.value > VK_SAMPLE_COUNT_4_BIT))
690 break;
691
692 testGroup->addChild(new MultisampleLinearInterpolationTestCase(testCtx, (offset.name + "_" + flagBit.name).c_str(), ".", tcu::IVec2(16, 16), 1.0f, offset.value, flagBit.value, groupParams));
693 }
694 }
695 }
696
697 } // anonymous
698
createMultisampleLinearInterpolationTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)699 tcu::TestCaseGroup* createMultisampleLinearInterpolationTests (tcu::TestContext& testCtx, const SharedGroupParams groupParams)
700 {
701 return createTestGroup(testCtx, "linear_interpolation", "Tests for linear interpolation decorations.", createTests, groupParams);
702 }
703
704 } // Draw
705 } // vkt
706