1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2022 The Khronos Group Inc.
6 * Copyright (c) 2022 Google Inc.
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
12 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \file vktDrawMultisampleLinearInterpolationTests.cpp
22 * \brief InterpolateAt tests with linear interpolation
23 *//*--------------------------------------------------------------------*/
25 #include "vktDrawMultisampleLinearInterpolationTests.hpp"
27 #include "vktDrawBaseClass.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkTypeUtil.hpp"
31 #include "vktTestGroupUtil.hpp"
41 class MultisampleLinearInterpolationTestInstance : public TestInstance
44 MultisampleLinearInterpolationTestInstance (Context& context,
45 const tcu::IVec2 renderSize,
46 const float interpolationRange,
47 const VkSampleCountFlagBits sampleCountFlagBits,
48 const bool useDynamicRendering)
49 : vkt::TestInstance (context)
50 , m_renderSize (renderSize)
51 , m_interpolationRange (interpolationRange)
52 , m_sampleCountFlagBits (sampleCountFlagBits)
53 , m_useDynamicRendering (useDynamicRendering)
56 ~MultisampleLinearInterpolationTestInstance (void)
59 tcu::TestStatus iterate (void);
62 const tcu::IVec2 m_renderSize;
63 const float m_interpolationRange;
64 const VkSampleCountFlagBits m_sampleCountFlagBits;
65 const bool m_useDynamicRendering;
68 tcu::TestStatus MultisampleLinearInterpolationTestInstance::iterate (void)
70 const DeviceInterface& vk = m_context.getDeviceInterface();
71 const VkDevice device = m_context.getDevice();
73 tcu::ConstPixelBufferAccess resultPixelBufferAccesses[2];
74 de::SharedPtr<Image> colorTargetImages[2];
75 de::SharedPtr<Image> multisampleImages[2];
77 const VkFormat imageColorFormat = VK_FORMAT_R8G8B8A8_UNORM;
79 const std::string vertShadernames[2] = { "vertRef", "vertNoPer" };
80 const std::string fragShadernames[2] = { "fragRef", "fragNoPer" };
82 tcu::TestLog& log = m_context.getTestContext().getLog();
84 const bool useMultisampling = m_sampleCountFlagBits == VK_SAMPLE_COUNT_1_BIT ? false : true;
86 for (int draw = 0; draw < 2; draw++)
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));
91 de::SharedPtr<Buffer> vertexBuffer;
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);
97 Move<VkRenderPass> renderPass;
99 std::vector<Move<VkImageView>> colorTargetViews;
100 std::vector<Move<VkImageView>> multisampleViews;
102 Move<VkFramebuffer> framebuffer;
104 Move<VkPipeline> pipeline;
105 const PipelineLayoutCreateInfo pipelineLayoutCreateInfo;
106 Move<VkPipelineLayout> pipelineLayout = createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
108 const VkVertexInputAttributeDescription vertInAttrDescs[2] =
110 { 0u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, 0u },
111 { 1u, 0u, VK_FORMAT_R32G32B32A32_SFLOAT, static_cast<deUint32>(sizeof(float) * 4) }
114 // Create color buffer images
116 const VkExtent3D targetImageExtent = { static_cast<deUint32>(m_renderSize.x()), static_cast<deUint32>(m_renderSize.y()), 1u };
117 const VkImageUsageFlags usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
118 const ImageCreateInfo targetImageCreateInfo (VK_IMAGE_TYPE_2D,
123 VK_SAMPLE_COUNT_1_BIT,
124 VK_IMAGE_TILING_OPTIMAL,
127 colorTargetImages[draw] = Image::createAndAlloc(vk, device, targetImageCreateInfo,
128 m_context.getDefaultAllocator(),
129 m_context.getUniversalQueueFamilyIndex());
131 if (useMultisampling)
133 const ImageCreateInfo multisampleImageCreateInfo (VK_IMAGE_TYPE_2D,
138 m_sampleCountFlagBits,
139 VK_IMAGE_TILING_OPTIMAL,
142 multisampleImages[draw] = Image::createAndAlloc(vk, device, multisampleImageCreateInfo,
143 m_context.getDefaultAllocator(),
144 m_context.getUniversalQueueFamilyIndex());
149 const ImageViewCreateInfo colorTargetViewInfo(colorTargetImages[draw]->object(),
150 VK_IMAGE_VIEW_TYPE_2D,
153 colorTargetViews.push_back(createImageView(vk, device, &colorTargetViewInfo));
155 if (useMultisampling)
157 const ImageViewCreateInfo multisamplingTargetViewInfo(multisampleImages[draw]->object(),
158 VK_IMAGE_VIEW_TYPE_2D,
161 multisampleViews.push_back(createImageView(vk, device, &multisamplingTargetViewInfo));
165 // Create render pass and frame buffer.
166 if (!m_useDynamicRendering)
168 RenderPassCreateInfo renderPassCreateInfo;
169 std::vector<VkImageView> attachments;
170 std::vector<VkAttachmentReference> colorAttachmentRefs;
171 std::vector<VkAttachmentReference> multisampleAttachmentRefs;
172 deUint32 attachmentNdx = 0;
175 const VkAttachmentReference colorAttachmentReference =
177 attachmentNdx++, // uint32_t attachment;
178 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
181 colorAttachmentRefs.push_back(colorAttachmentReference);
183 renderPassCreateInfo.addAttachment(AttachmentDescription(imageColorFormat,
184 VK_SAMPLE_COUNT_1_BIT,
185 VK_ATTACHMENT_LOAD_OP_CLEAR,
186 VK_ATTACHMENT_STORE_OP_STORE,
187 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
188 VK_ATTACHMENT_STORE_OP_DONT_CARE,
189 VK_IMAGE_LAYOUT_UNDEFINED,
190 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL));
192 if (useMultisampling)
194 const VkAttachmentReference multiSampleAttachmentReference =
196 attachmentNdx++, // uint32_t attachment;
197 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
200 multisampleAttachmentRefs.push_back(multiSampleAttachmentReference);
202 renderPassCreateInfo.addAttachment(AttachmentDescription(imageColorFormat,
203 m_sampleCountFlagBits,
204 VK_ATTACHMENT_LOAD_OP_CLEAR,
205 VK_ATTACHMENT_STORE_OP_DONT_CARE,
206 VK_ATTACHMENT_LOAD_OP_DONT_CARE,
207 VK_ATTACHMENT_STORE_OP_DONT_CARE,
208 VK_IMAGE_LAYOUT_UNDEFINED,
209 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));
213 renderPassCreateInfo.addSubpass(SubpassDescription(VK_PIPELINE_BIND_POINT_GRAPHICS,
217 (deUint32)colorAttachmentRefs.size(),
218 useMultisampling ? &multisampleAttachmentRefs[0] : &colorAttachmentRefs[0],
219 useMultisampling ? &colorAttachmentRefs[0] : DE_NULL,
220 AttachmentReference(),
224 renderPass = createRenderPass(vk, device, &renderPassCreateInfo);
226 for (deUint32 frameNdx = 0; frameNdx < colorTargetViews.size(); frameNdx++)
228 attachments.push_back(*colorTargetViews[frameNdx]);
230 if (useMultisampling)
231 attachments.push_back(*multisampleViews[frameNdx]);
234 const VkFramebufferCreateInfo framebufferCreateInfo =
236 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
237 DE_NULL, // const void* pNext;
238 0u, // VkFramebufferCreateFlags flags;
239 *renderPass, // VkRenderPass renderPass;
240 static_cast<deUint32>(attachments.size()), // uint32_t attachmentCount;
241 &attachments[0], // const VkImageView* pAttachments;
242 static_cast<deUint32>(m_renderSize.x()), // uint32_t width;
243 static_cast<deUint32>(m_renderSize.y()), // uint32_t height;
244 1u // uint32_t layers;
247 framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
250 // Create vertex buffer.
252 const PositionColorVertex vertices[] =
254 // The first draw is for reference image.
261 /* result reference */
263 // In result shape the bottom vertices are deeper. When the drawn result image is a perfect square,
264 // and color comparison with reference image is easy to make.
265 PositionColorVertex(tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f), tcu::Vec4(0.0f, m_interpolationRange, 0.0f, m_interpolationRange)), // Top Right
266 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
267 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
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.0f, 0.0f, m_interpolationRange)), // Bottom Left
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.5f, m_interpolationRange * 0.5f, 0.0f, m_interpolationRange)), // Bottom Right
270 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
273 const VkDeviceSize dataSize = sizeof(vertices);
274 vertexBuffer = Buffer::createAndAlloc(vk, device, BufferCreateInfo(dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
275 deUint8* ptr = static_cast<deUint8*>(vertexBuffer->getBoundMemory().getHostPtr());
277 deMemcpy(ptr, vertices, static_cast<size_t>(dataSize));
278 flushMappedMemoryRange(vk, device, vertexBuffer->getBoundMemory().getMemory(), vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
283 const PipelineCreateInfo::ColorBlendState::Attachment vkCbAttachmentState;
285 VkViewport viewport = makeViewport(m_renderSize.x(), m_renderSize.y());
286 VkRect2D scissor = makeRect2D(m_renderSize.x(), m_renderSize.y());
288 const std::vector<deUint32> sampleMask = { 0xfffffff, 0xfffffff };
290 const VkVertexInputBindingDescription vertexInputBindingDescription = { 0, (deUint32)sizeof(tcu::Vec4) * 2, VK_VERTEX_INPUT_RATE_VERTEX };
291 PipelineCreateInfo::VertexInputState vertexInputState = PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription, 2, vertInAttrDescs);
293 PipelineCreateInfo pipelineCreateInfo(*pipelineLayout, *renderPass, 0, 0);
295 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vs, "main", VK_SHADER_STAGE_VERTEX_BIT));
296 pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fs, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
297 pipelineCreateInfo.addState(PipelineCreateInfo::VertexInputState(vertexInputState));
298 pipelineCreateInfo.addState(PipelineCreateInfo::InputAssemblerState(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST));
299 pipelineCreateInfo.addState(PipelineCreateInfo::ColorBlendState(1, &vkCbAttachmentState));
300 pipelineCreateInfo.addState(PipelineCreateInfo::ViewportState(1, std::vector<VkViewport>(1, viewport), std::vector<VkRect2D>(1, scissor)));
301 pipelineCreateInfo.addState(PipelineCreateInfo::DepthStencilState());
302 pipelineCreateInfo.addState(PipelineCreateInfo::RasterizerState());
303 pipelineCreateInfo.addState(PipelineCreateInfo::MultiSampleState(m_sampleCountFlagBits, false, 0.0f, sampleMask));
305 #ifndef CTS_USES_VULKANSC
306 VkPipelineRenderingCreateInfo renderingCreateInfo
308 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
317 if (m_useDynamicRendering)
318 pipelineCreateInfo.pNext = &renderingCreateInfo;
319 #endif // CTS_USES_VULKANSC
321 pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
324 // Draw quad and read results.
326 const VkQueue queue = m_context.getUniversalQueue();
327 const VkClearValue clearColor = { { { 0.0f, 0.0f, 0.0f, 1.0f } } };
328 const ImageSubresourceRange subresourceRange (VK_IMAGE_ASPECT_COLOR_BIT);
329 const VkRect2D renderArea = makeRect2D(m_renderSize.x(), m_renderSize.y());
330 const VkDeviceSize vertexBufferOffset = 0;
331 const VkBuffer buffer = vertexBuffer->object();
332 const VkOffset3D zeroOffset = { 0, 0, 0 };
334 std::vector<VkClearValue> clearValues (2, clearColor);
336 clearColorImage(vk, device, queue, m_context.getUniversalQueueFamilyIndex(),
337 colorTargetImages[draw]->object(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
338 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
339 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 1u);
341 beginCommandBuffer(vk, *cmdBuffer, 0u);
343 #ifndef CTS_USES_VULKANSC
344 if (m_useDynamicRendering)
346 const deUint32 imagesCount = static_cast<deUint32>(colorTargetViews.size());
348 std::vector<VkRenderingAttachmentInfo> colorAttachments(imagesCount,
350 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
351 DE_NULL, // const void* pNext;
352 DE_NULL, // VkImageView imageView;
353 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
354 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
355 DE_NULL, // VkImageView resolveImageView;
356 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout resolveImageLayout;
357 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
358 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
359 clearColor // VkClearValue clearValue;
362 for (deUint32 i = 0; i < imagesCount; ++i)
364 if (useMultisampling)
366 colorAttachments[i].imageView = *multisampleViews[i];
367 colorAttachments[i].resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
368 colorAttachments[i].resolveImageView = *colorTargetViews[i];
372 colorAttachments[i].imageView = *colorTargetViews[i];
376 VkRenderingInfo renderingInfo
378 VK_STRUCTURE_TYPE_RENDERING_INFO, // VkStructureType sType;
379 DE_NULL, // const void* pNext;
380 0, // VkRenderingFlagsKHR flags;
381 renderArea, // VkRect2D renderArea;
382 1u, // deUint32 layerCount;
383 0u, // deUint32 viewMask;
384 imagesCount, // deUint32 colorAttachmentCount;
385 colorAttachments.data(), // const VkRenderingAttachmentInfoKHR* pColorAttachments;
386 DE_NULL, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
387 DE_NULL, // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
391 initialTransitionColor2DImage(vk, *cmdBuffer, colorTargetImages[draw]->object(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
392 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
394 if (useMultisampling)
396 initialTransitionColor2DImage(vk, *cmdBuffer, multisampleImages[draw]->object(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
397 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
400 vk.cmdBeginRendering(*cmdBuffer, &renderingInfo);
403 #endif // CTS_USES_VULKANSC
405 const deUint32 imagesCount = static_cast<deUint32>(colorTargetViews.size() + multisampleViews.size());
406 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, imagesCount, &clearValues[0]);
409 vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &buffer, &vertexBufferOffset);
410 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
411 vk.cmdDraw(*cmdBuffer, 6u, 1u, 0u, 0u);
413 #ifndef CTS_USES_VULKANSC
414 if (m_useDynamicRendering)
415 endRendering(vk, *cmdBuffer);
417 #endif // CTS_USES_VULKANSC
418 endRenderPass(vk, *cmdBuffer);
420 endCommandBuffer(vk, *cmdBuffer);
422 submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
424 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);
428 if (!tcu::floatThresholdCompare(log, "Result", "Image comparison result", resultPixelBufferAccesses[0], resultPixelBufferAccesses[1], tcu::Vec4(0.005f), tcu::COMPARE_LOG_RESULT))
429 return tcu::TestStatus::fail("Rendered color image is not correct");
431 return tcu::TestStatus::pass("Success");
434 class MultisampleLinearInterpolationTestCase : public TestCase
437 MultisampleLinearInterpolationTestCase (tcu::TestContext& context,
440 const tcu::IVec2 renderSize,
441 const float interpolationRange,
442 const tcu::Vec2 offset,
443 const VkSampleCountFlagBits sampleCountFlagBits,
444 const bool useDynamicRendering)
445 : vkt::TestCase(context, name, desc)
446 , m_renderSize (renderSize)
447 , m_interpolationRange (interpolationRange)
449 , m_sampleCountFlagBits (sampleCountFlagBits)
450 , m_useDynamicRendering (useDynamicRendering)
453 ~MultisampleLinearInterpolationTestCase (void)
456 virtual void initPrograms (SourceCollections& programCollection) const;
457 virtual void checkSupport (Context& context) const;
458 virtual TestInstance* createInstance (Context& context) const;
461 const tcu::IVec2 m_renderSize;
462 const float m_interpolationRange;
463 const tcu::Vec2 m_offset;
464 const VkSampleCountFlagBits m_sampleCountFlagBits;
465 const bool m_useDynamicRendering;
468 void MultisampleLinearInterpolationTestCase::initPrograms (SourceCollections& programCollection) const
470 // Reference vertex shader.
472 std::ostringstream vrt;
474 vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
476 << "layout(location = 0) in vec4 in_position;\n"
477 << "layout(location = 1) in vec4 in_color;\n"
478 << "layout(location = 0) out vec4 out_color;\n"
482 << " gl_PointSize = 1.0;\n"
483 << " gl_Position = in_position;\n"
484 << " out_color = in_color;\n"
487 programCollection.glslSources.add("vertRef") << glu::VertexSource(vrt.str());
490 // Noperspective vertex shader.
492 std::ostringstream vrt;
494 vrt << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
496 << "layout(location = 0) in vec4 in_position;\n"
497 << "layout(location = 1) in vec4 in_color;\n"
498 << "layout(location = 0) noperspective out vec4 out_color;\n"
502 << " gl_PointSize = 1.0;\n"
503 << " gl_Position = in_position;\n"
504 << " out_color = in_color;\n"
507 programCollection.glslSources.add("vertNoPer") << glu::VertexSource(vrt.str());
510 // Reference fragment shader.
512 std::ostringstream frg;
514 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
515 << "layout(location = 0) in vec4 in_color;\n"
516 << "layout(location = 0) out vec4 out_color;\n"
519 << " 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"
520 << " 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"
521 << " out_color = 0.5 * (out_color_y + out_color_x);\n"
524 programCollection.glslSources.add("fragRef") << glu::FragmentSource(frg.str());
527 // Noperspective fragment shader.
529 std::ostringstream frg;
531 frg << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
532 << "layout(location = 0) noperspective in vec4 in_color;\n"
533 << "layout(location = 0) out vec4 out_color;\n"
536 << " vec4 out_color_offset = interpolateAtOffset(in_color, vec2(" << m_offset.x() << ", " << m_offset.y() << "));\n"
537 << " vec4 out_color_sample = interpolateAtSample(in_color, gl_SampleID);\n"
538 << " out_color = (0.5 * (out_color_offset + out_color_sample));\n"
539 << " out_color /= " << m_interpolationRange << ";\n";
541 // Run additional sample comparison test. If it fails, we write 1.0 to blue color channel.
542 frg << " if (out_color_sample != interpolateAtOffset(in_color, gl_SamplePosition - vec2(0.5)))\n"
544 << " out_color.z = 1.0;\n"
549 programCollection.glslSources.add("fragNoPer") << glu::FragmentSource(frg.str());
553 void MultisampleLinearInterpolationTestCase::checkSupport (Context& context) const
555 if (!(m_sampleCountFlagBits & context.getDeviceProperties().limits.framebufferColorSampleCounts))
556 TCU_THROW(NotSupportedError, "Multisampling with " + de::toString(m_sampleCountFlagBits) + " samples not supported");
557 #ifndef CTS_USES_VULKANSC
558 if (m_useDynamicRendering)
559 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
561 if (context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
562 !context.getPortabilitySubsetFeatures().shaderSampleRateInterpolationFunctions)
564 TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Shader sample rate interpolation functions are not supported by this implementation");
566 #endif // CTS_USES_VULKANSC
569 TestInstance* MultisampleLinearInterpolationTestCase::createInstance (Context& context) const
571 return new MultisampleLinearInterpolationTestInstance(context, m_renderSize, m_interpolationRange, m_sampleCountFlagBits, m_useDynamicRendering);
574 void createTests (tcu::TestCaseGroup* testGroup, bool useDynamicRendering)
576 tcu::TestContext& testCtx = testGroup->getTestContext();
580 const std::string name;
581 const tcu::Vec2 value;
584 { "no_offset", tcu::Vec2(0.0f, 0.0f) },
585 { "offset_min", tcu::Vec2(-0.5f, -0.5f) },
586 { "offset_max", tcu::Vec2(0.4375f, 0.4375f) }
591 const std::string name;
592 VkSampleCountFlagBits value;
595 { "1_sample", VK_SAMPLE_COUNT_1_BIT },
596 { "2_samples", VK_SAMPLE_COUNT_2_BIT },
597 { "4_samples", VK_SAMPLE_COUNT_4_BIT },
598 { "8_samples", VK_SAMPLE_COUNT_8_BIT },
599 { "16_samples", VK_SAMPLE_COUNT_16_BIT },
600 { "32_samples", VK_SAMPLE_COUNT_32_BIT },
601 { "64_samples", VK_SAMPLE_COUNT_64_BIT }
604 for (const auto& offset : offsets)
606 for (const auto& flagBit : flagBits)
608 testGroup->addChild(new MultisampleLinearInterpolationTestCase(testCtx, (offset.name + "_" + flagBit.name).c_str(), ".", tcu::IVec2(16, 16), 1.0f, offset.value, flagBit.value, useDynamicRendering));
615 tcu::TestCaseGroup* createMultisampleLinearInterpolationTests (tcu::TestContext& testCtx, bool useDynamicRendering)
617 return createTestGroup(testCtx, "linear_interpolation", "Tests for linear interpolation decorations.", createTests, useDynamicRendering);