1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*
20 * \file vktPipelineMultisampleInterpolationTests.cpp
21 * \brief Multisample Interpolation Tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktPipelineMultisampleInterpolationTests.hpp"
25 #include "vktPipelineMultisampleTestsUtil.hpp"
26 #include "vktPipelineMakeUtil.hpp"
27 #include "vkQueryUtil.hpp"
28
29 #include <set>
30
31 namespace vkt
32 {
33 namespace pipeline
34 {
35 namespace multisample
36 {
37
38 using namespace vk;
39
40 struct ImageMSParams
41 {
ImageMSParamsvkt::pipeline::multisample::ImageMSParams42 ImageMSParams(const VkSampleCountFlagBits samples, const tcu::UVec3& size) : numSamples(samples), imageSize(size) {}
43
44 VkSampleCountFlagBits numSamples;
45 tcu::UVec3 imageSize;
46 };
47
48 class MSInterpolationCaseBase : public TestCase
49 {
50 public:
MSInterpolationCaseBase(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)51 MSInterpolationCaseBase (tcu::TestContext& testCtx,
52 const std::string& name,
53 const ImageMSParams& imageMSParams)
54 : TestCase(testCtx, name, "")
55 , m_imageMSParams(imageMSParams)
56 {}
57
58 protected:
59 const ImageMSParams m_imageMSParams;
60 };
61
62 typedef MSInterpolationCaseBase* (*MSInterpolationCaseFuncPtr)(tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams);
63
64 class MSInterpolationInstanceBase : public TestInstance
65 {
66 public:
MSInterpolationInstanceBase(Context & context,const ImageMSParams & imageMSParams)67 MSInterpolationInstanceBase (Context& context,
68 const ImageMSParams& imageMSParams)
69 : TestInstance (context)
70 , m_imageMSParams (imageMSParams)
71 , m_imageType (IMAGE_TYPE_2D)
72 , m_imageFormat (tcu::TextureFormat(tcu::TextureFormat::RG, tcu::TextureFormat::UNORM_INT8))
73 {}
74
75 tcu::TestStatus iterate (void);
76
77 protected:
78
79 typedef std::vector<VkVertexInputAttributeDescription> VertexAttribDescVec;
80
81 struct VertexDataDesc
82 {
83 VkPrimitiveTopology primitiveTopology;
84 deUint32 verticesCount;
85 deUint32 dataStride;
86 VkDeviceSize dataSize;
87 VertexAttribDescVec vertexAttribDescVec;
88 };
89
90 void validateImageSize (const InstanceInterface& instance,
91 const VkPhysicalDevice physicalDevice,
92 const ImageType imageType,
93 const tcu::UVec3& imageSize) const;
94
95 void validateImageFeatureFlags (const InstanceInterface& instance,
96 const VkPhysicalDevice physicalDevice,
97 const VkFormat format,
98 const VkFormatFeatureFlags featureFlags) const;
99
100 void validateImageInfo (const InstanceInterface& instance,
101 const VkPhysicalDevice physicalDevice,
102 const VkImageCreateInfo& imageInfo) const;
103
104 virtual VertexDataDesc getVertexDataDescripton (void) const = 0;
105
106 virtual void uploadVertexData (const Allocation& vertexBufferAllocation,
107 const VertexDataDesc& vertexDataDescripton) const = 0;
108
109 virtual tcu::TestStatus verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const = 0;
110 protected:
111 const ImageMSParams m_imageMSParams;
112 const ImageType m_imageType;
113 const tcu::TextureFormat m_imageFormat;
114 };
115
validateImageSize(const InstanceInterface & instance,const VkPhysicalDevice physicalDevice,const ImageType imageType,const tcu::UVec3 & imageSize) const116 void MSInterpolationInstanceBase::validateImageSize (const InstanceInterface& instance,
117 const VkPhysicalDevice physicalDevice,
118 const ImageType imageType,
119 const tcu::UVec3& imageSize) const
120 {
121 const VkPhysicalDeviceProperties deviceProperties = getPhysicalDeviceProperties(instance, physicalDevice);
122
123 bool isImageSizeValid = true;
124
125 switch (imageType)
126 {
127 case IMAGE_TYPE_1D:
128 isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension1D;
129 break;
130 case IMAGE_TYPE_1D_ARRAY:
131 isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension1D &&
132 imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
133 break;
134 case IMAGE_TYPE_2D:
135 isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
136 imageSize.y() <= deviceProperties.limits.maxImageDimension2D;
137 break;
138 case IMAGE_TYPE_2D_ARRAY:
139 isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension2D &&
140 imageSize.y() <= deviceProperties.limits.maxImageDimension2D &&
141 imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
142 break;
143 case IMAGE_TYPE_CUBE:
144 isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
145 imageSize.y() <= deviceProperties.limits.maxImageDimensionCube;
146 break;
147 case IMAGE_TYPE_CUBE_ARRAY:
148 isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimensionCube &&
149 imageSize.y() <= deviceProperties.limits.maxImageDimensionCube &&
150 imageSize.z() <= deviceProperties.limits.maxImageArrayLayers;
151 break;
152 case IMAGE_TYPE_3D:
153 isImageSizeValid = imageSize.x() <= deviceProperties.limits.maxImageDimension3D &&
154 imageSize.y() <= deviceProperties.limits.maxImageDimension3D &&
155 imageSize.z() <= deviceProperties.limits.maxImageDimension3D;
156 break;
157 default:
158 DE_FATAL("Unknown image type");
159 }
160
161 if (!isImageSizeValid)
162 {
163 std::ostringstream notSupportedStream;
164
165 notSupportedStream << "Image type (" << getImageTypeName(imageType) << ") with size (" << imageSize.x() << ", " << imageSize.y() << ", " << imageSize.z() << ") not supported by device" << std::endl;
166
167 const std::string notSupportedString = notSupportedStream.str();
168
169 TCU_THROW(NotSupportedError, notSupportedString.c_str());
170 }
171 }
172
validateImageFeatureFlags(const InstanceInterface & instance,const VkPhysicalDevice physicalDevice,const VkFormat format,const VkFormatFeatureFlags featureFlags) const173 void MSInterpolationInstanceBase::validateImageFeatureFlags (const InstanceInterface& instance,
174 const VkPhysicalDevice physicalDevice,
175 const VkFormat format,
176 const VkFormatFeatureFlags featureFlags) const
177 {
178 const VkFormatProperties formatProperties = getPhysicalDeviceFormatProperties(instance, physicalDevice, format);
179
180 if ((formatProperties.optimalTilingFeatures & featureFlags) != featureFlags)
181 {
182 std::ostringstream notSupportedStream;
183
184 notSupportedStream << "Device does not support image format " << format << " for feature flags " << featureFlags << std::endl;
185
186 const std::string notSupportedString = notSupportedStream.str();
187
188 TCU_THROW(NotSupportedError, notSupportedString.c_str());
189 }
190 }
191
validateImageInfo(const InstanceInterface & instance,const VkPhysicalDevice physicalDevice,const VkImageCreateInfo & imageInfo) const192 void MSInterpolationInstanceBase::validateImageInfo (const InstanceInterface& instance,
193 const VkPhysicalDevice physicalDevice,
194 const VkImageCreateInfo& imageInfo) const
195 {
196 VkImageFormatProperties imageFormatProps;
197 instance.getPhysicalDeviceImageFormatProperties(physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &imageFormatProps);
198
199 if (imageFormatProps.maxExtent.width < imageInfo.extent.width ||
200 imageFormatProps.maxExtent.height < imageInfo.extent.height ||
201 imageFormatProps.maxExtent.depth < imageInfo.extent.depth)
202 {
203 std::ostringstream notSupportedStream;
204
205 notSupportedStream << "Image extent ("
206 << imageInfo.extent.width << ", "
207 << imageInfo.extent.height << ", "
208 << imageInfo.extent.depth
209 << ") exceeds allowed maximum ("
210 << imageFormatProps.maxExtent.width << ", "
211 << imageFormatProps.maxExtent.height << ", "
212 << imageFormatProps.maxExtent.depth
213 << ")"
214 << std::endl;
215
216 const std::string notSupportedString = notSupportedStream.str();
217
218 TCU_THROW(NotSupportedError, notSupportedString.c_str());
219 }
220
221 if (imageFormatProps.maxArrayLayers < imageInfo.arrayLayers)
222 {
223 std::ostringstream notSupportedStream;
224
225 notSupportedStream << "Image layers count of " << imageInfo.arrayLayers << " exceeds allowed maximum which is " << imageFormatProps.maxArrayLayers << std::endl;
226
227 const std::string notSupportedString = notSupportedStream.str();
228
229 TCU_THROW(NotSupportedError, notSupportedString.c_str());
230 }
231
232 if (!(imageFormatProps.sampleCounts & imageInfo.samples))
233 {
234 std::ostringstream notSupportedStream;
235
236 notSupportedStream << "Samples count of " << imageInfo.samples << " not supported for image" << std::endl;
237
238 const std::string notSupportedString = notSupportedStream.str();
239
240 TCU_THROW(NotSupportedError, notSupportedString.c_str());
241 }
242 }
243
iterate(void)244 tcu::TestStatus MSInterpolationInstanceBase::iterate (void)
245 {
246 const InstanceInterface& instance = m_context.getInstanceInterface();
247 const DeviceInterface& deviceInterface = m_context.getDeviceInterface();
248 const VkDevice device = m_context.getDevice();
249 const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
250 Allocator& allocator = m_context.getDefaultAllocator();
251 const VkQueue queue = m_context.getUniversalQueue();
252 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
253
254 VkImageCreateInfo imageMSInfo;
255 VkImageCreateInfo imageRSInfo;
256
257 // Check if image size does not exceed device limits
258 validateImageSize(instance, physicalDevice, m_imageType, m_imageMSParams.imageSize);
259
260 // Check if device supports image format as color attachment
261 validateImageFeatureFlags(instance, physicalDevice, mapTextureFormat(m_imageFormat), VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT);
262
263 imageMSInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
264 imageMSInfo.pNext = DE_NULL;
265 imageMSInfo.flags = 0u;
266 imageMSInfo.imageType = mapImageType(m_imageType);
267 imageMSInfo.format = mapTextureFormat(m_imageFormat);
268 imageMSInfo.extent = makeExtent3D(getLayerSize(m_imageType, m_imageMSParams.imageSize));
269 imageMSInfo.arrayLayers = getNumLayers(m_imageType, m_imageMSParams.imageSize);
270 imageMSInfo.mipLevels = 1u;
271 imageMSInfo.samples = m_imageMSParams.numSamples;
272 imageMSInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
273 imageMSInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
274 imageMSInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
275 imageMSInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
276 imageMSInfo.queueFamilyIndexCount = 0u;
277 imageMSInfo.pQueueFamilyIndices = DE_NULL;
278
279 if (m_imageType == IMAGE_TYPE_CUBE || m_imageType == IMAGE_TYPE_CUBE_ARRAY)
280 {
281 imageMSInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
282 }
283
284 validateImageInfo(instance, physicalDevice, imageMSInfo);
285
286 const de::UniquePtr<Image> imageMS(new Image(deviceInterface, device, allocator, imageMSInfo, MemoryRequirement::Any));
287
288 imageRSInfo = imageMSInfo;
289 imageRSInfo.samples = VK_SAMPLE_COUNT_1_BIT;
290
291 validateImageInfo(instance, physicalDevice, imageRSInfo);
292
293 const de::UniquePtr<Image> imageRS(new Image(deviceInterface, device, allocator, imageRSInfo, MemoryRequirement::Any));
294
295 // Create render pass
296 const VkAttachmentDescription attachmentMSDesc =
297 {
298 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
299 imageMSInfo.format, // VkFormat format;
300 imageMSInfo.samples, // VkSampleCountFlagBits samples;
301 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
302 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
303 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
304 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
305 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
306 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
307 };
308
309 const VkAttachmentDescription attachmentRSDesc =
310 {
311 (VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags;
312 imageRSInfo.format, // VkFormat format;
313 imageRSInfo.samples, // VkSampleCountFlagBits samples;
314 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
315 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
316 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp;
317 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp;
318 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout;
319 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout;
320 };
321
322 const VkAttachmentDescription attachments[] = { attachmentMSDesc, attachmentRSDesc };
323
324 const VkAttachmentReference attachmentMSRef =
325 {
326 0u, // deUint32 attachment;
327 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
328 };
329
330 const VkAttachmentReference attachmentRSRef =
331 {
332 1u, // deUint32 attachment;
333 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout;
334 };
335
336 const VkAttachmentReference* resolveAttachment = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? DE_NULL : &attachmentRSRef;
337
338 const VkSubpassDescription subpassDescription =
339 {
340 (VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags;
341 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint;
342 0u, // deUint32 inputAttachmentCount;
343 DE_NULL, // const VkAttachmentReference* pInputAttachments;
344 1u, // deUint32 colorAttachmentCount;
345 &attachmentMSRef, // const VkAttachmentReference* pColorAttachments;
346 resolveAttachment, // const VkAttachmentReference* pResolveAttachments;
347 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment;
348 0u, // deUint32 preserveAttachmentCount;
349 DE_NULL // const deUint32* pPreserveAttachments;
350 };
351
352 const VkRenderPassCreateInfo renderPassInfo =
353 {
354 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType;
355 DE_NULL, // const void* pNext;
356 (VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags;
357 2u, // deUint32 attachmentCount;
358 attachments, // const VkAttachmentDescription* pAttachments;
359 1u, // deUint32 subpassCount;
360 &subpassDescription, // const VkSubpassDescription* pSubpasses;
361 0u, // deUint32 dependencyCount;
362 DE_NULL // const VkSubpassDependency* pDependencies;
363 };
364
365 const Unique<VkRenderPass> renderPass(createRenderPass(deviceInterface, device, &renderPassInfo));
366
367 const VkImageSubresourceRange fullImageRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, imageMSInfo.mipLevels, 0u, imageMSInfo.arrayLayers);
368
369 // Create color attachments image views
370 const Unique<VkImageView> imageMSView(makeImageView(deviceInterface, device, **imageMS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
371 const Unique<VkImageView> imageRSView(makeImageView(deviceInterface, device, **imageRS, mapImageViewType(m_imageType), imageMSInfo.format, fullImageRange));
372
373 const VkImageView attachmentsViews[] = { *imageMSView, *imageRSView };
374
375 // Create framebuffer
376 const VkFramebufferCreateInfo framebufferInfo =
377 {
378 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
379 DE_NULL, // const void* pNext;
380 (VkFramebufferCreateFlags)0u, // VkFramebufferCreateFlags flags;
381 *renderPass, // VkRenderPass renderPass;
382 2u, // uint32_t attachmentCount;
383 attachmentsViews, // const VkImageView* pAttachments;
384 imageMSInfo.extent.width, // uint32_t width;
385 imageMSInfo.extent.height, // uint32_t height;
386 imageMSInfo.arrayLayers, // uint32_t layers;
387 };
388
389 const Unique<VkFramebuffer> framebuffer(createFramebuffer(deviceInterface, device, &framebufferInfo));
390
391 // Create pipeline layout
392 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
393 {
394 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
395 DE_NULL, // const void* pNext;
396 (VkPipelineLayoutCreateFlags)0u, // VkPipelineLayoutCreateFlags flags;
397 0u, // deUint32 setLayoutCount;
398 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
399 0u, // deUint32 pushConstantRangeCount;
400 DE_NULL, // const VkPushConstantRange* pPushConstantRanges;
401 };
402
403 const Unique<VkPipelineLayout> pipelineLayout(createPipelineLayout(deviceInterface, device, &pipelineLayoutParams));
404
405 // Create vertex attributes data
406 const VertexDataDesc vertexDataDesc = getVertexDataDescripton();
407
408 de::SharedPtr<Buffer> vertexBuffer = de::SharedPtr<Buffer>(new Buffer(deviceInterface, device, allocator, makeBufferCreateInfo(vertexDataDesc.dataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT), MemoryRequirement::HostVisible));
409 const Allocation& vertexBufferAllocation = vertexBuffer->getAllocation();
410
411 uploadVertexData(vertexBufferAllocation, vertexDataDesc);
412
413 flushMappedMemoryRange(deviceInterface, device, vertexBufferAllocation.getMemory(), vertexBufferAllocation.getOffset(), vertexDataDesc.dataSize);
414
415 const VkVertexInputBindingDescription vertexBinding =
416 {
417 0u, // deUint32 binding;
418 vertexDataDesc.dataStride, // deUint32 stride;
419 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputRate inputRate;
420 };
421
422 const VkPipelineVertexInputStateCreateInfo vertexInputStateInfo =
423 {
424 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
425 DE_NULL, // const void* pNext;
426 (VkPipelineVertexInputStateCreateFlags)0u, // VkPipelineVertexInputStateCreateFlags flags;
427 1u, // uint32_t vertexBindingDescriptionCount;
428 &vertexBinding, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
429 static_cast<deUint32>(vertexDataDesc.vertexAttribDescVec.size()), // uint32_t vertexAttributeDescriptionCount;
430 dataPointer(vertexDataDesc.vertexAttribDescVec), // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
431 };
432
433 const VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateInfo =
434 {
435 VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, // VkStructureType sType;
436 DE_NULL, // const void* pNext;
437 (VkPipelineInputAssemblyStateCreateFlags)0u, // VkPipelineInputAssemblyStateCreateFlags flags;
438 vertexDataDesc.primitiveTopology, // VkPrimitiveTopology topology;
439 VK_FALSE, // VkBool32 primitiveRestartEnable;
440 };
441
442 const VkViewport viewport =
443 {
444 0.0f, 0.0f,
445 static_cast<float>(imageMSInfo.extent.width), static_cast<float>(imageMSInfo.extent.height),
446 0.0f, 1.0f
447 };
448
449 const VkRect2D scissor =
450 {
451 makeOffset2D(0, 0),
452 makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height),
453 };
454
455 const VkPipelineViewportStateCreateInfo viewportStateInfo =
456 {
457 VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, // VkStructureType sType;
458 DE_NULL, // const void* pNext;
459 (VkPipelineViewportStateCreateFlags)0u, // VkPipelineViewportStateCreateFlags flags;
460 1u, // uint32_t viewportCount;
461 &viewport, // const VkViewport* pViewports;
462 1u, // uint32_t scissorCount;
463 &scissor, // const VkRect2D* pScissors;
464 };
465
466 const VkPipelineRasterizationStateCreateInfo rasterizationStateInfo =
467 {
468 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // VkStructureType sType;
469 DE_NULL, // const void* pNext;
470 (VkPipelineRasterizationStateCreateFlags)0u, // VkPipelineRasterizationStateCreateFlags flags;
471 VK_FALSE, // VkBool32 depthClampEnable;
472 VK_FALSE, // VkBool32 rasterizerDiscardEnable;
473 VK_POLYGON_MODE_FILL, // VkPolygonMode polygonMode;
474 VK_CULL_MODE_NONE, // VkCullModeFlags cullMode;
475 VK_FRONT_FACE_COUNTER_CLOCKWISE, // VkFrontFace frontFace;
476 VK_FALSE, // VkBool32 depthBiasEnable;
477 0.0f, // float depthBiasConstantFactor;
478 0.0f, // float depthBiasClamp;
479 0.0f, // float depthBiasSlopeFactor;
480 1.0f, // float lineWidth;
481 };
482
483 const VkPipelineMultisampleStateCreateInfo multisampleStateInfo =
484 {
485 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType;
486 DE_NULL, // const void* pNext;
487 (VkPipelineMultisampleStateCreateFlags)0u, // VkPipelineMultisampleStateCreateFlags flags;
488 imageMSInfo.samples, // VkSampleCountFlagBits rasterizationSamples;
489 VK_TRUE, // VkBool32 sampleShadingEnable;
490 1.0f, // float minSampleShading;
491 DE_NULL, // const VkSampleMask* pSampleMask;
492 VK_FALSE, // VkBool32 alphaToCoverageEnable;
493 VK_FALSE, // VkBool32 alphaToOneEnable;
494 };
495
496 const VkStencilOpState stencilOpState = makeStencilOpState
497 (
498 VK_STENCIL_OP_KEEP, // stencil fail
499 VK_STENCIL_OP_KEEP, // depth & stencil pass
500 VK_STENCIL_OP_KEEP, // depth only fail
501 VK_COMPARE_OP_ALWAYS, // compare op
502 0u, // compare mask
503 0u, // write mask
504 0u // reference
505 );
506
507 const VkPipelineDepthStencilStateCreateInfo depthStencilStateInfo =
508 {
509 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
510 DE_NULL, // const void* pNext;
511 (VkPipelineDepthStencilStateCreateFlags)0u, // VkPipelineDepthStencilStateCreateFlags flags;
512 VK_FALSE, // VkBool32 depthTestEnable;
513 VK_FALSE, // VkBool32 depthWriteEnable;
514 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp;
515 VK_FALSE, // VkBool32 depthBoundsTestEnable;
516 VK_FALSE, // VkBool32 stencilTestEnable;
517 stencilOpState, // VkStencilOpState front;
518 stencilOpState, // VkStencilOpState back;
519 0.0f, // float minDepthBounds;
520 1.0f, // float maxDepthBounds;
521 };
522
523 const VkColorComponentFlags colorComponentsAll = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
524
525 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState =
526 {
527 VK_FALSE, // VkBool32 blendEnable;
528 VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcColorBlendFactor;
529 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstColorBlendFactor;
530 VK_BLEND_OP_ADD, // VkBlendOp colorBlendOp;
531 VK_BLEND_FACTOR_SRC_ALPHA, // VkBlendFactor srcAlphaBlendFactor;
532 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, // VkBlendFactor dstAlphaBlendFactor;
533 VK_BLEND_OP_ADD, // VkBlendOp alphaBlendOp;
534 colorComponentsAll, // VkColorComponentFlags colorWriteMask;
535 };
536
537 const VkPipelineColorBlendStateCreateInfo colorBlendStateInfo =
538 {
539 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
540 DE_NULL, // const void* pNext;
541 (VkPipelineColorBlendStateCreateFlags)0u, // VkPipelineColorBlendStateCreateFlags flags;
542 VK_FALSE, // VkBool32 logicOpEnable;
543 VK_LOGIC_OP_COPY, // VkLogicOp logicOp;
544 1u, // deUint32 attachmentCount;
545 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments;
546 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
547 };
548
549 const Unique<VkShaderModule> vsModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("vertex_shader"), (VkShaderModuleCreateFlags)0));
550
551 const VkPipelineShaderStageCreateInfo vsShaderStageInfo =
552 {
553 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
554 DE_NULL, // const void* pNext;
555 (VkPipelineShaderStageCreateFlags)0u, // VkPipelineShaderStageCreateFlags flags;
556 VK_SHADER_STAGE_VERTEX_BIT, // VkShaderStageFlagBits stage;
557 *vsModule, // VkShaderModule module;
558 "main", // const char* pName;
559 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
560 };
561
562 const Unique<VkShaderModule> fsModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get("fragment_shader"), (VkShaderModuleCreateFlags)0));
563
564 const VkPipelineShaderStageCreateInfo fsShaderStageInfo =
565 {
566 VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, // VkStructureType sType;
567 DE_NULL, // const void* pNext;
568 (VkPipelineShaderStageCreateFlags)0u, // VkPipelineShaderStageCreateFlags flags;
569 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlagBits stage;
570 *fsModule, // VkShaderModule module;
571 "main", // const char* pName;
572 DE_NULL, // const VkSpecializationInfo* pSpecializationInfo;
573 };
574
575 const VkPipelineShaderStageCreateInfo shaderStageInfos[] = { vsShaderStageInfo, fsShaderStageInfo };
576
577 const VkGraphicsPipelineCreateInfo graphicsPipelineInfo =
578 {
579 VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, // VkStructureType sType;
580 DE_NULL, // const void* pNext;
581 (VkPipelineCreateFlags)0, // VkPipelineCreateFlags flags;
582 2u, // deUint32 stageCount;
583 shaderStageInfos, // const VkPipelineShaderStageCreateInfo* pStages;
584 &vertexInputStateInfo, // const VkPipelineVertexInputStateCreateInfo* pVertexInputState;
585 &inputAssemblyStateInfo, // const VkPipelineInputAssemblyStateCreateInfo* pInputAssemblyState;
586 DE_NULL, // const VkPipelineTessellationStateCreateInfo* pTessellationState;
587 &viewportStateInfo, // const VkPipelineViewportStateCreateInfo* pViewportState;
588 &rasterizationStateInfo, // const VkPipelineRasterizationStateCreateInfo* pRasterizationState;
589 &multisampleStateInfo, // const VkPipelineMultisampleStateCreateInfo* pMultisampleState;
590 &depthStencilStateInfo, // const VkPipelineDepthStencilStateCreateInfo* pDepthStencilState;
591 &colorBlendStateInfo, // const VkPipelineColorBlendStateCreateInfo* pColorBlendState;
592 DE_NULL, // const VkPipelineDynamicStateCreateInfo* pDynamicState;
593 *pipelineLayout, // VkPipelineLayout layout;
594 *renderPass, // VkRenderPass renderPass;
595 0u, // deUint32 subpass;
596 DE_NULL, // VkPipeline basePipelineHandle;
597 0u, // deInt32 basePipelineIndex;
598 };
599
600 // Create graphics pipeline
601 const Unique<VkPipeline> graphicsPipeline(createGraphicsPipeline(deviceInterface, device, DE_NULL, &graphicsPipelineInfo));
602
603 // Create command buffer for compute and transfer oparations
604 const Unique<VkCommandPool> commandPool(makeCommandPool(deviceInterface, device, queueFamilyIndex));
605 const Unique<VkCommandBuffer> commandBuffer(makeCommandBuffer(deviceInterface, device, *commandPool));
606
607 // Start recording commands
608 beginCommandBuffer(deviceInterface, *commandBuffer);
609
610 {
611 VkImageMemoryBarrier imageOutputAttachmentBarriers[2];
612
613 imageOutputAttachmentBarriers[0] = makeImageMemoryBarrier
614 (
615 0u,
616 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
617 VK_IMAGE_LAYOUT_UNDEFINED,
618 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
619 **imageMS,
620 fullImageRange
621 );
622
623 imageOutputAttachmentBarriers[1] = makeImageMemoryBarrier
624 (
625 0u,
626 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
627 VK_IMAGE_LAYOUT_UNDEFINED,
628 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
629 **imageRS,
630 fullImageRange
631 );
632
633 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 2u, imageOutputAttachmentBarriers);
634 }
635
636 {
637 const VkDeviceSize vertexStartOffset = 0u;
638
639 std::vector<VkClearValue> clearValues;
640 clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
641 clearValues.push_back(makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)));
642
643 const vk::VkRect2D renderArea =
644 {
645 makeOffset2D(0u, 0u),
646 makeExtent2D(imageMSInfo.extent.width, imageMSInfo.extent.height),
647 };
648
649 // Begin render pass
650 const VkRenderPassBeginInfo renderPassBeginInfo =
651 {
652 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
653 DE_NULL, // const void* pNext;
654 *renderPass, // VkRenderPass renderPass;
655 *framebuffer, // VkFramebuffer framebuffer;
656 renderArea, // VkRect2D renderArea;
657 static_cast<deUint32>(clearValues.size()), // deUint32 clearValueCount;
658 &clearValues[0], // const VkClearValue* pClearValues;
659 };
660
661 deviceInterface.cmdBeginRenderPass(*commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
662
663 // Bind graphics pipeline
664 deviceInterface.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
665
666 // Bind vertex buffer
667 deviceInterface.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &vertexStartOffset);
668
669 // Draw full screen quad
670 deviceInterface.cmdDraw(*commandBuffer, vertexDataDesc.verticesCount, 1u, 0u, 0u);
671
672 // End render pass
673 deviceInterface.cmdEndRenderPass(*commandBuffer);
674 }
675
676 const VkImage sourceImage = m_imageMSParams.numSamples == VK_SAMPLE_COUNT_1_BIT ? **imageMS : **imageRS;
677
678 {
679 const VkImageMemoryBarrier imageTransferSrcBarrier = makeImageMemoryBarrier
680 (
681 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
682 VK_ACCESS_TRANSFER_READ_BIT,
683 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
684 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
685 sourceImage,
686 fullImageRange
687 );
688
689 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageTransferSrcBarrier);
690 }
691
692 // Copy data from resolve image to buffer
693 const deUint32 imageRSSizeInBytes = getImageSizeInBytes(imageRSInfo.extent, imageRSInfo.arrayLayers, m_imageFormat, imageRSInfo.mipLevels);
694
695 const VkBufferCreateInfo bufferRSInfo = makeBufferCreateInfo(imageRSSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
696 const de::UniquePtr<Buffer> bufferRS(new Buffer(deviceInterface, device, allocator, bufferRSInfo, MemoryRequirement::HostVisible));
697
698 {
699 const VkBufferImageCopy bufferImageCopy =
700 {
701 0u, // VkDeviceSize bufferOffset;
702 0u, // deUint32 bufferRowLength;
703 0u, // deUint32 bufferImageHeight;
704 makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, imageRSInfo.arrayLayers), // VkImageSubresourceLayers imageSubresource;
705 makeOffset3D(0, 0, 0), // VkOffset3D imageOffset;
706 imageRSInfo.extent, // VkExtent3D imageExtent;
707 };
708
709 deviceInterface.cmdCopyImageToBuffer(*commandBuffer, sourceImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, bufferRS->get(), 1u, &bufferImageCopy);
710 }
711
712 {
713 const VkBufferMemoryBarrier bufferRSHostReadBarrier = makeBufferMemoryBarrier
714 (
715 VK_ACCESS_TRANSFER_WRITE_BIT,
716 VK_ACCESS_HOST_READ_BIT,
717 bufferRS->get(),
718 0u,
719 imageRSSizeInBytes
720 );
721
722 deviceInterface.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferRSHostReadBarrier, 0u, DE_NULL);
723 }
724
725 // End recording commands
726 VK_CHECK(deviceInterface.endCommandBuffer(*commandBuffer));
727
728 // Submit commands for execution and wait for completion
729 submitCommandsAndWait(deviceInterface, device, queue, *commandBuffer);
730
731 // Retrieve data from buffer to host memory
732 const Allocation& bufferRSAllocation = bufferRS->getAllocation();
733
734 invalidateMappedMemoryRange(deviceInterface, device, bufferRSAllocation.getMemory(), bufferRSAllocation.getOffset(), imageRSSizeInBytes);
735
736 const tcu::ConstPixelBufferAccess bufferRSData (m_imageFormat,
737 imageRSInfo.extent.width,
738 imageRSInfo.extent.height,
739 imageRSInfo.extent.depth * imageRSInfo.arrayLayers,
740 bufferRSAllocation.getHostPtr());
741
742 std::stringstream imageName;
743 imageName << getImageTypeName(m_imageType) << "_" << bufferRSData.getWidth() << "_" << bufferRSData.getHeight() << "_" << bufferRSData.getDepth() << std::endl;
744
745 m_context.getTestContext().getLog()
746 << tcu::TestLog::Section(imageName.str(), imageName.str())
747 << tcu::LogImage("image", "", bufferRSData)
748 << tcu::TestLog::EndSection;
749
750 return verifyResolvedImage(bufferRSData);
751 }
752
753 class MSInstanceDistinctValues : public MSInterpolationInstanceBase
754 {
755 public:
MSInstanceDistinctValues(Context & context,const ImageMSParams & imageMSParams)756 MSInstanceDistinctValues(Context& context,
757 const ImageMSParams& imageMSParams)
758 : MSInterpolationInstanceBase(context, imageMSParams) {}
759
760 VertexDataDesc getVertexDataDescripton (void) const;
761 void uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const;
762 tcu::TestStatus verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const;
763
764 protected:
765 struct VertexData
766 {
VertexDatavkt::pipeline::multisample::MSInstanceDistinctValues::VertexData767 VertexData(const tcu::Vec4& posNdc) : positionNdc(posNdc) {}
768
769 tcu::Vec4 positionNdc;
770 };
771 };
772
getVertexDataDescripton(void) const773 MSInterpolationInstanceBase::VertexDataDesc MSInstanceDistinctValues::getVertexDataDescripton (void) const
774 {
775 VertexDataDesc vertexDataDesc;
776
777 vertexDataDesc.verticesCount = 3u;
778 vertexDataDesc.dataStride = sizeof(VertexData);
779 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
780 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
781
782 const VkVertexInputAttributeDescription vertexAttribPositionNdc =
783 {
784 0u, // deUint32 location;
785 0u, // deUint32 binding;
786 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
787 DE_OFFSET_OF(VertexData, positionNdc), // deUint32 offset;
788 };
789
790 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
791
792 return vertexDataDesc;
793 }
794
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const795 void MSInstanceDistinctValues::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
796 {
797 std::vector<VertexData> vertices;
798
799 vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f)));
800 vertices.push_back(VertexData(tcu::Vec4(-1.0f, 4.0f, 0.0f, 1.0f)));
801 vertices.push_back(VertexData(tcu::Vec4( 4.0f,-1.0f, 0.0f, 1.0f)));
802
803 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
804 }
805
verifyResolvedImage(const tcu::ConstPixelBufferAccess & imageData) const806 tcu::TestStatus MSInstanceDistinctValues::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const
807 {
808 const deUint32 distinctValuesExpected = static_cast<deUint32>(m_imageMSParams.numSamples) + 1u;
809
810 std::vector<tcu::IVec4> distinctValues;
811
812 for (deInt32 z = 0u; z < imageData.getDepth(); ++z)
813 for (deInt32 y = 0u; y < imageData.getHeight(); ++y)
814 for (deInt32 x = 0u; x < imageData.getWidth(); ++x)
815 {
816 const tcu::IVec4 pixel = imageData.getPixelInt(x, y, z);
817
818 if (std::find(distinctValues.begin(), distinctValues.end(), pixel) == distinctValues.end())
819 distinctValues.push_back(pixel);
820 }
821
822 if (distinctValues.size() >= distinctValuesExpected)
823 return tcu::TestStatus::pass("Passed");
824 else
825 return tcu::TestStatus::fail("Failed");
826 }
827
828 class MSCaseSampleQualifierDistinctValues : public MSInterpolationCaseBase
829 {
830 public:
MSCaseSampleQualifierDistinctValues(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)831 MSCaseSampleQualifierDistinctValues (tcu::TestContext& testCtx,
832 const std::string& name,
833 const ImageMSParams& imageMSParams)
834 : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
835
836 void init (void);
837 void initPrograms (vk::SourceCollections& programCollection) const;
838 TestInstance* createInstance (Context& context) const;
839 };
840
createMSCaseSampleQualifierDistinctValues(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)841 MSInterpolationCaseBase* createMSCaseSampleQualifierDistinctValues (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
842 {
843 return new MSCaseSampleQualifierDistinctValues(testCtx, name, imageMSParams);
844 }
845
init(void)846 void MSCaseSampleQualifierDistinctValues::init (void)
847 {
848 m_testCtx.getLog()
849 << tcu::TestLog::Message
850 << "Verifying that a sample qualified varying is given different values for different samples.\n"
851 << " Render full screen traingle with quadratic function defining red/green color pattern division.\n"
852 << " => Resulting image should contain n+1 different colors, where n = sample count.\n"
853 << tcu::TestLog::EndMessage;
854
855 MSInterpolationCaseBase::init();
856 }
857
initPrograms(vk::SourceCollections & programCollection) const858 void MSCaseSampleQualifierDistinctValues::initPrograms (vk::SourceCollections& programCollection) const
859 {
860 // Create vertex shader
861 std::ostringstream vs;
862
863 vs << "#version 440\n"
864 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
865 << "\n"
866 << "layout(location = 0) out vec4 vs_out_position_ndc;\n"
867 << "\n"
868 << "out gl_PerVertex {\n"
869 << " vec4 gl_Position;\n"
870 << "};\n"
871 << "void main (void)\n"
872 << "{\n"
873 << " gl_Position = vs_in_position_ndc;\n"
874 << " vs_out_position_ndc = vs_in_position_ndc;\n"
875 << "}\n";
876
877 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
878
879 // Create fragment shader
880 std::ostringstream fs;
881
882 fs << "#version 440\n"
883 << "layout(location = 0) sample in vec4 fs_in_position_ndc;\n"
884 << "\n"
885 << "layout(location = 0) out vec2 fs_out_color;\n"
886 << "\n"
887 << "void main (void)\n"
888 << "{\n"
889 << " if(fs_in_position_ndc.y < -2.0*pow(0.5*(fs_in_position_ndc.x + 1.0), 2.0) + 1.0)\n"
890 << " fs_out_color = vec2(1.0, 0.0);\n"
891 << " else\n"
892 << " fs_out_color = vec2(0.0, 1.0);\n"
893 << "}\n";
894
895 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
896 }
897
createInstance(Context & context) const898 TestInstance* MSCaseSampleQualifierDistinctValues::createInstance (Context& context) const
899 {
900 return new MSInstanceDistinctValues(context, m_imageMSParams);
901 }
902
903 class MSCaseInterpolateAtSampleDistinctValues : public MSInterpolationCaseBase
904 {
905 public:
MSCaseInterpolateAtSampleDistinctValues(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)906 MSCaseInterpolateAtSampleDistinctValues (tcu::TestContext& testCtx,
907 const std::string& name,
908 const ImageMSParams& imageMSParams)
909 : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
910
911 void init (void);
912 void initPrograms (vk::SourceCollections& programCollection) const;
913 TestInstance* createInstance (Context& context) const;
914 };
915
createMSCaseInterpolateAtSampleDistinctValues(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)916 MSInterpolationCaseBase* createMSCaseInterpolateAtSampleDistinctValues (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
917 {
918 return new MSCaseInterpolateAtSampleDistinctValues(testCtx, name, imageMSParams);
919 }
920
init(void)921 void MSCaseInterpolateAtSampleDistinctValues::init (void)
922 {
923 m_testCtx.getLog()
924 << tcu::TestLog::Message
925 << "Verifying that a interpolateAtSample returns different values for different samples.\n"
926 << " Render full screen traingle with quadratic function defining red/green color pattern division.\n"
927 << " => Resulting image should contain n+1 different colors, where n = sample count.\n"
928 << tcu::TestLog::EndMessage;
929
930 MSInterpolationCaseBase::init();
931 }
932
initPrograms(vk::SourceCollections & programCollection) const933 void MSCaseInterpolateAtSampleDistinctValues::initPrograms (vk::SourceCollections& programCollection) const
934 {
935 // Create vertex shader
936 std::ostringstream vs;
937
938 vs << "#version 440\n"
939 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
940 << "\n"
941 << "layout(location = 0) out vec4 vs_out_position_ndc;\n"
942 << "\n"
943 << "out gl_PerVertex {\n"
944 << " vec4 gl_Position;\n"
945 << "};\n"
946 << "void main (void)\n"
947 << "{\n"
948 << " gl_Position = vs_in_position_ndc;\n"
949 << " vs_out_position_ndc = vs_in_position_ndc;\n"
950 << "}\n";
951
952 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
953
954 // Create fragment shader
955 std::ostringstream fs;
956
957 fs << "#version 440\n"
958 << "layout(location = 0) in vec4 fs_in_position_ndc;\n"
959 << "\n"
960 << "layout(location = 0) out vec2 fs_out_color;\n"
961 << "\n"
962 << "void main (void)\n"
963 << "{\n"
964 << " const vec4 position_ndc_at_sample = interpolateAtSample(fs_in_position_ndc, gl_SampleID);\n"
965 << " if(position_ndc_at_sample.y < -2.0*pow(0.5*(position_ndc_at_sample.x + 1.0), 2.0) + 1.0)\n"
966 << " fs_out_color = vec2(0.0, 1.0);\n"
967 << " else\n"
968 << " fs_out_color = vec2(1.0, 0.0);\n"
969 << "}\n";
970
971 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
972 }
973
createInstance(Context & context) const974 TestInstance* MSCaseInterpolateAtSampleDistinctValues::createInstance (Context& context) const
975 {
976 return new MSInstanceDistinctValues(context, m_imageMSParams);
977 }
978
979 class MSInstanceInterpolateScreenPosition : public MSInterpolationInstanceBase
980 {
981 public:
MSInstanceInterpolateScreenPosition(Context & context,const ImageMSParams & imageMSParams)982 MSInstanceInterpolateScreenPosition (Context& context,
983 const ImageMSParams& imageMSParams)
984 : MSInterpolationInstanceBase(context, imageMSParams) {}
985
986 VertexDataDesc getVertexDataDescripton (void) const;
987 void uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const;
988 tcu::TestStatus verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const;
989
990 protected:
991 struct VertexData
992 {
VertexDatavkt::pipeline::multisample::MSInstanceInterpolateScreenPosition::VertexData993 VertexData(const tcu::Vec4& posNdc, const tcu::Vec2& posScreen) : positionNdc(posNdc), positionScreen(posScreen) {}
994
995 tcu::Vec4 positionNdc;
996 tcu::Vec2 positionScreen;
997 };
998 };
999
getVertexDataDescripton(void) const1000 MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateScreenPosition::getVertexDataDescripton (void) const
1001 {
1002 VertexDataDesc vertexDataDesc;
1003
1004 vertexDataDesc.verticesCount = 4u;
1005 vertexDataDesc.dataStride = sizeof(VertexData);
1006 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
1007 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1008
1009 const VkVertexInputAttributeDescription vertexAttribPositionNdc =
1010 {
1011 0u, // deUint32 location;
1012 0u, // deUint32 binding;
1013 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1014 DE_OFFSET_OF(VertexData, positionNdc), // deUint32 offset;
1015 };
1016
1017 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
1018
1019 const VkVertexInputAttributeDescription vertexAttribPositionScreen =
1020 {
1021 1u, // deUint32 location;
1022 0u, // deUint32 binding;
1023 VK_FORMAT_R32G32_SFLOAT, // VkFormat format;
1024 DE_OFFSET_OF(VertexData, positionScreen), // deUint32 offset;
1025 };
1026
1027 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionScreen);
1028
1029 return vertexDataDesc;
1030 }
1031
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const1032 void MSInstanceInterpolateScreenPosition::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
1033 {
1034 const tcu::UVec3 layerSize = getLayerSize(IMAGE_TYPE_2D, m_imageMSParams.imageSize);
1035 const float screenSizeX = static_cast<float>(layerSize.x());
1036 const float screenSizeY = static_cast<float>(layerSize.y());
1037
1038 std::vector<VertexData> vertices;
1039
1040 vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, 0.0f)));
1041 vertices.push_back(VertexData(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, 0.0f)));
1042 vertices.push_back(VertexData(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(0.0f, screenSizeY)));
1043 vertices.push_back(VertexData(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec2(screenSizeX, screenSizeY)));
1044
1045 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
1046 }
1047
verifyResolvedImage(const tcu::ConstPixelBufferAccess & imageData) const1048 tcu::TestStatus MSInstanceInterpolateScreenPosition::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const
1049 {
1050 for (deInt32 z = 0u; z < imageData.getDepth(); ++z)
1051 for (deInt32 y = 0u; y < imageData.getHeight(); ++y)
1052 for (deInt32 x = 0u; x < imageData.getWidth(); ++x)
1053 {
1054 const deInt32 firstComponent = imageData.getPixelInt(x, y, z).x();
1055
1056 if (firstComponent > 0)
1057 return tcu::TestStatus::fail("Failed");
1058 }
1059 return tcu::TestStatus::pass("Passed");
1060 }
1061
1062 class MSCaseInterpolateAtSampleSingleSample : public MSInterpolationCaseBase
1063 {
1064 public:
MSCaseInterpolateAtSampleSingleSample(tcu::TestContext & testCtx,const std::string & name,tcu::UVec3 imageSize)1065 MSCaseInterpolateAtSampleSingleSample (tcu::TestContext& testCtx,
1066 const std::string& name,
1067 tcu::UVec3 imageSize)
1068 : MSInterpolationCaseBase(testCtx, name, ImageMSParams(VK_SAMPLE_COUNT_1_BIT, imageSize)) {}
1069
1070 void init (void);
1071 void initPrograms (vk::SourceCollections& programCollection) const;
1072 TestInstance* createInstance (Context& context) const;
1073 };
1074
init(void)1075 void MSCaseInterpolateAtSampleSingleSample::init (void)
1076 {
1077 m_testCtx.getLog()
1078 << tcu::TestLog::Message
1079 << "Verifying that using interpolateAtSample with multisample buffers not available returns sample evaluated at the center of the pixel.\n"
1080 << " Interpolate varying containing screen space location.\n"
1081 << " => fract(screen space location) should be (about) (0.5, 0.5)\n"
1082 << tcu::TestLog::EndMessage;
1083
1084 MSInterpolationCaseBase::init();
1085 }
1086
initPrograms(vk::SourceCollections & programCollection) const1087 void MSCaseInterpolateAtSampleSingleSample::initPrograms (vk::SourceCollections& programCollection) const
1088 {
1089 // Create vertex shader
1090 std::ostringstream vs;
1091
1092 vs << "#version 440\n"
1093 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1094 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1095 << "\n"
1096 << "layout(location = 0) out vec2 vs_out_position_screen;\n"
1097 << "\n"
1098 << "out gl_PerVertex {\n"
1099 << " vec4 gl_Position;\n"
1100 << "};\n"
1101 << "void main (void)\n"
1102 << "{\n"
1103 << " gl_Position = vs_in_position_ndc;\n"
1104 << " vs_out_position_screen = vs_in_position_screen;\n"
1105 << "}\n";
1106
1107 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1108
1109 // Create fragment shader
1110 std::ostringstream fs;
1111
1112 fs << "#version 440\n"
1113 << "layout(location = 0) in vec2 fs_in_position_screen;\n"
1114 << "\n"
1115 << "layout(location = 0) out vec2 fs_out_color;\n"
1116 << "\n"
1117 << "void main (void)\n"
1118 << "{\n"
1119 << " const float threshold = 0.15625;\n"
1120 << " const vec2 position_screen_at_sample = interpolateAtSample(fs_in_position_screen, 0);\n"
1121 << " const vec2 position_inside_pixel = fract(position_screen_at_sample);\n"
1122 << "\n"
1123 << " if (abs(position_inside_pixel.x - 0.5) <= threshold && abs(position_inside_pixel.y - 0.5) <= threshold)\n"
1124 << " fs_out_color = vec2(0.0, 1.0);\n"
1125 << " else\n"
1126 << " fs_out_color = vec2(1.0, 0.0);\n"
1127 << "}\n";
1128
1129 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1130 }
1131
createInstance(Context & context) const1132 TestInstance* MSCaseInterpolateAtSampleSingleSample::createInstance (Context& context) const
1133 {
1134 return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1135 }
1136
1137 class MSCaseInterpolateAtSampleIgnoresCentroid : public MSInterpolationCaseBase
1138 {
1139 public:
MSCaseInterpolateAtSampleIgnoresCentroid(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1140 MSCaseInterpolateAtSampleIgnoresCentroid(tcu::TestContext& testCtx,
1141 const std::string& name,
1142 const ImageMSParams& imageMSParams)
1143 : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1144
1145 void init (void);
1146 void initPrograms (vk::SourceCollections& programCollection) const;
1147 TestInstance* createInstance (Context& context) const;
1148 };
1149
createMSCaseInterpolateAtSampleIgnoresCentroid(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1150 MSInterpolationCaseBase* createMSCaseInterpolateAtSampleIgnoresCentroid (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1151 {
1152 return new MSCaseInterpolateAtSampleIgnoresCentroid(testCtx, name, imageMSParams);
1153 }
1154
init(void)1155 void MSCaseInterpolateAtSampleIgnoresCentroid::init (void)
1156 {
1157 m_testCtx.getLog()
1158 << tcu::TestLog::Message
1159 << "Verifying that interpolateAtSample ignores centroid qualifier.\n"
1160 << " Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
1161 << " => interpolateAtSample(screenSample, n) ~= interpolateAtSample(screenCentroid, n)\n"
1162 << tcu::TestLog::EndMessage;
1163
1164 MSInterpolationCaseBase::init();
1165 }
1166
initPrograms(vk::SourceCollections & programCollection) const1167 void MSCaseInterpolateAtSampleIgnoresCentroid::initPrograms (vk::SourceCollections& programCollection) const
1168 {
1169 // Create vertex shader
1170 std::ostringstream vs;
1171
1172 vs << "#version 440\n"
1173 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1174 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1175 << "\n"
1176 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
1177 << "layout(location = 1) out vec2 vs_out_pos_screen_fragment;\n"
1178 << "\n"
1179 << "out gl_PerVertex {\n"
1180 << " vec4 gl_Position;\n"
1181 << "};\n"
1182 << "void main (void)\n"
1183 << "{\n"
1184 << " gl_Position = vs_in_position_ndc;\n"
1185 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n"
1186 << " vs_out_pos_screen_fragment = vs_in_position_screen;\n"
1187 << "}\n";
1188
1189 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1190
1191 // Create fragment shader
1192 std::ostringstream fs;
1193
1194 fs << "#version 440\n"
1195 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
1196 << "layout(location = 1) in vec2 fs_in_pos_screen_fragment;\n"
1197 << "\n"
1198 << "layout(location = 0) out vec2 fs_out_color;\n"
1199 << "\n"
1200 << "void main (void)\n"
1201 << "{\n"
1202 << " const float threshold = 0.0005;\n"
1203 << "\n"
1204 << " const vec2 position_a = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
1205 << " const vec2 position_b = interpolateAtSample(fs_in_pos_screen_fragment, gl_SampleID);\n"
1206 << " const bool valuesEqual = all(lessThan(abs(position_a - position_b), vec2(threshold)));\n"
1207 << "\n"
1208 << " if (valuesEqual)\n"
1209 << " fs_out_color = vec2(0.0, 1.0);\n"
1210 << " else\n"
1211 << " fs_out_color = vec2(1.0, 0.0);\n"
1212 << "}\n";
1213
1214 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1215 }
1216
createInstance(Context & context) const1217 TestInstance* MSCaseInterpolateAtSampleIgnoresCentroid::createInstance (Context& context) const
1218 {
1219 return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1220 }
1221
1222 class MSCaseInterpolateAtSampleConsistency : public MSInterpolationCaseBase
1223 {
1224 public:
MSCaseInterpolateAtSampleConsistency(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1225 MSCaseInterpolateAtSampleConsistency (tcu::TestContext& testCtx,
1226 const std::string& name,
1227 const ImageMSParams& imageMSParams)
1228 : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1229
1230 void init (void);
1231 void initPrograms (vk::SourceCollections& programCollection) const;
1232 TestInstance* createInstance (Context& context) const;
1233 };
1234
createMSCaseInterpolateAtSampleConsistency(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1235 MSInterpolationCaseBase* createMSCaseInterpolateAtSampleConsistency (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1236 {
1237 return new MSCaseInterpolateAtSampleConsistency(testCtx, name, imageMSParams);
1238 }
1239
init(void)1240 void MSCaseInterpolateAtSampleConsistency::init (void)
1241 {
1242 m_testCtx.getLog()
1243 << tcu::TestLog::Message
1244 << "Verifying that interpolateAtSample with the sample set to the current sampleID returns consistent values.\n"
1245 << " Interpolate varying containing screen space location with centroid and sample qualifiers.\n"
1246 << " => interpolateAtSample(screenCentroid, sampleID) = screenSample\n"
1247 << tcu::TestLog::EndMessage;
1248
1249 MSInterpolationCaseBase::init();
1250 }
1251
initPrograms(vk::SourceCollections & programCollection) const1252 void MSCaseInterpolateAtSampleConsistency::initPrograms (vk::SourceCollections& programCollection) const
1253 {
1254 // Create vertex shader
1255 std::ostringstream vs;
1256
1257 vs << "#version 440\n"
1258 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1259 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1260 << "\n"
1261 << "layout(location = 0) out vec2 vs_out_pos_screen_centroid;\n"
1262 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
1263 << "\n"
1264 << "out gl_PerVertex {\n"
1265 << " vec4 gl_Position;\n"
1266 << "};\n"
1267 << "void main (void)\n"
1268 << "{\n"
1269 << " gl_Position = vs_in_position_ndc;\n"
1270 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n"
1271 << " vs_out_pos_screen_sample = vs_in_position_screen;\n"
1272 << "}\n";
1273
1274 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1275
1276 // Create fragment shader
1277 std::ostringstream fs;
1278
1279 fs << "#version 440\n"
1280 << "layout(location = 0) centroid in vec2 fs_in_pos_screen_centroid;\n"
1281 << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n"
1282 << "\n"
1283 << "layout(location = 0) out vec2 fs_out_color;\n"
1284 << "\n"
1285 << "void main (void)\n"
1286 << "{\n"
1287 << " const float threshold = 0.15625;\n"
1288 << "\n"
1289 << " const vec2 pos_interpolated_at_sample = interpolateAtSample(fs_in_pos_screen_centroid, gl_SampleID);\n"
1290 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_sample - fs_in_pos_screen_sample), vec2(threshold)));\n"
1291 << "\n"
1292 << " if (valuesEqual)\n"
1293 << " fs_out_color = vec2(0.0, 1.0);\n"
1294 << " else\n"
1295 << " fs_out_color = vec2(1.0, 0.0);\n"
1296 << "}\n";
1297
1298 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1299 }
1300
createInstance(Context & context) const1301 TestInstance* MSCaseInterpolateAtSampleConsistency::createInstance (Context& context) const
1302 {
1303 return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1304 }
1305
1306 class MSCaseInterpolateAtCentroidConsistency : public MSInterpolationCaseBase
1307 {
1308 public:
MSCaseInterpolateAtCentroidConsistency(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1309 MSCaseInterpolateAtCentroidConsistency (tcu::TestContext& testCtx,
1310 const std::string& name,
1311 const ImageMSParams& imageMSParams)
1312 : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1313
1314 void init (void);
1315 void initPrograms (vk::SourceCollections& programCollection) const;
1316 TestInstance* createInstance (Context& context) const;
1317 };
1318
createMSCaseInterpolateAtCentroidConsistency(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1319 MSInterpolationCaseBase* createMSCaseInterpolateAtCentroidConsistency (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1320 {
1321 return new MSCaseInterpolateAtCentroidConsistency(testCtx, name, imageMSParams);
1322 }
1323
init(void)1324 void MSCaseInterpolateAtCentroidConsistency::init (void)
1325 {
1326 m_testCtx.getLog()
1327 << tcu::TestLog::Message
1328 << "Verifying that interpolateAtCentroid does not return different values than a corresponding centroid qualified varying.\n"
1329 << " Interpolate varying containing screen space location with sample and centroid qualifiers.\n"
1330 << " => interpolateAtCentroid(screenSample) = screenCentroid\n"
1331 << tcu::TestLog::EndMessage;
1332
1333 MSInterpolationCaseBase::init();
1334 }
1335
initPrograms(vk::SourceCollections & programCollection) const1336 void MSCaseInterpolateAtCentroidConsistency::initPrograms (vk::SourceCollections& programCollection) const
1337 {
1338 // Create vertex shader
1339 std::ostringstream vs;
1340
1341 vs << "#version 440\n"
1342 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1343 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1344 << "\n"
1345 << "layout(location = 0) out vec2 vs_out_pos_screen_sample;\n"
1346 << "layout(location = 1) out vec2 vs_out_pos_screen_centroid;\n"
1347 << "\n"
1348 << "out gl_PerVertex {\n"
1349 << " vec4 gl_Position;\n"
1350 << "};\n"
1351 << "void main (void)\n"
1352 << "{\n"
1353 << " gl_Position = vs_in_position_ndc;\n"
1354 << " vs_out_pos_screen_sample = vs_in_position_screen;\n"
1355 << " vs_out_pos_screen_centroid = vs_in_position_screen;\n"
1356 << "}\n";
1357
1358 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1359
1360 // Create fragment shader
1361 std::ostringstream fs;
1362
1363 fs << "#version 440\n"
1364 << "layout(location = 0) sample in vec2 fs_in_pos_screen_sample;\n"
1365 << "layout(location = 1) centroid in vec2 fs_in_pos_screen_centroid;\n"
1366 << "\n"
1367 << "layout(location = 0) out vec2 fs_out_color;\n"
1368 << "\n"
1369 << "void main (void)\n"
1370 << "{\n"
1371 << " const float threshold = 0.0005;\n"
1372 << "\n"
1373 << " const vec2 pos_interpolated_at_centroid = interpolateAtCentroid(fs_in_pos_screen_sample);\n"
1374 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_centroid - fs_in_pos_screen_centroid), vec2(threshold)));\n"
1375 << "\n"
1376 << " if (valuesEqual)\n"
1377 << " fs_out_color = vec2(0.0, 1.0);\n"
1378 << " else\n"
1379 << " fs_out_color = vec2(1.0, 0.0);\n"
1380 << "}\n";
1381
1382 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1383 }
1384
createInstance(Context & context) const1385 TestInstance* MSCaseInterpolateAtCentroidConsistency::createInstance (Context& context) const
1386 {
1387 return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1388 }
1389
1390 class MSCaseInterpolateAtOffsetPixelCenter : public MSInterpolationCaseBase
1391 {
1392 public:
MSCaseInterpolateAtOffsetPixelCenter(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1393 MSCaseInterpolateAtOffsetPixelCenter(tcu::TestContext& testCtx,
1394 const std::string& name,
1395 const ImageMSParams& imageMSParams)
1396 : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1397
1398 void init (void);
1399 void initPrograms (vk::SourceCollections& programCollection) const;
1400 TestInstance* createInstance (Context& context) const;
1401 };
1402
createMSCaseInterpolateAtOffsetPixelCenter(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1403 MSInterpolationCaseBase* createMSCaseInterpolateAtOffsetPixelCenter (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1404 {
1405 return new MSCaseInterpolateAtOffsetPixelCenter(testCtx, name, imageMSParams);
1406 }
1407
init(void)1408 void MSCaseInterpolateAtOffsetPixelCenter::init (void)
1409 {
1410 m_testCtx.getLog()
1411 << tcu::TestLog::Message
1412 << "Verifying that interpolateAtOffset returns value sampled at an offset from the center of the pixel.\n"
1413 << " Interpolate varying containing screen space location.\n"
1414 << " => interpolateAtOffset(screen, offset) should be \"varying value at the pixel center\" + offset"
1415 << tcu::TestLog::EndMessage;
1416
1417 MSInterpolationCaseBase::init();
1418 }
1419
initPrograms(vk::SourceCollections & programCollection) const1420 void MSCaseInterpolateAtOffsetPixelCenter::initPrograms (vk::SourceCollections& programCollection) const
1421 {
1422 // Create vertex shader
1423 std::ostringstream vs;
1424
1425 vs << "#version 440\n"
1426 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1427 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1428 << "\n"
1429 << "layout(location = 0) out vec2 vs_out_pos_screen;\n"
1430 << "layout(location = 1) out vec2 vs_out_offset;\n"
1431 << "\n"
1432 << "out gl_PerVertex {\n"
1433 << " vec4 gl_Position;\n"
1434 << "};\n"
1435 << "void main (void)\n"
1436 << "{\n"
1437 << " gl_Position = vs_in_position_ndc;\n"
1438 << " vs_out_pos_screen = vs_in_position_screen;\n"
1439 << " vs_out_offset = vs_in_position_ndc.xy * 0.5;\n"
1440 << "}\n";
1441
1442 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1443
1444 // Create fragment shader
1445 std::ostringstream fs;
1446
1447 fs << "#version 440\n"
1448 << "layout(location = 0) in vec2 fs_in_pos_screen;\n"
1449 << "layout(location = 1) in vec2 fs_in_offset;\n"
1450 << "\n"
1451 << "layout(location = 0) out vec2 fs_out_color;\n"
1452 << "\n"
1453 << "void main (void)\n"
1454 << "{\n"
1455 << " const vec2 frag_center = interpolateAtOffset(fs_in_pos_screen, vec2(0.0));\n"
1456 << " const vec2 center_diff = abs(frag_center - fs_in_pos_screen);\n"
1457 << " const float threshold = 0.125;\n"
1458 << " bool valuesEqual = false;\n"
1459 << "\n"
1460 << " if (all(lessThan(center_diff, vec2(0.5 + threshold)))) {\n"
1461 << " const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen, fs_in_offset);\n"
1462 << " const vec2 reference_value = frag_center + fs_in_offset;\n"
1463 << "\n"
1464 << " valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - reference_value), vec2(threshold)));\n"
1465 << " }\n"
1466 << "\n"
1467 << " if (valuesEqual)\n"
1468 << " fs_out_color = vec2(0.0, 1.0);\n"
1469 << " else\n"
1470 << " fs_out_color = vec2(1.0, 0.0);\n"
1471 << "}\n";
1472
1473 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1474 }
1475
createInstance(Context & context) const1476 TestInstance* MSCaseInterpolateAtOffsetPixelCenter::createInstance (Context& context) const
1477 {
1478 return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1479 }
1480
1481 class MSCaseInterpolateAtOffsetSamplePosition : public MSInterpolationCaseBase
1482 {
1483 public:
MSCaseInterpolateAtOffsetSamplePosition(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1484 MSCaseInterpolateAtOffsetSamplePosition (tcu::TestContext& testCtx,
1485 const std::string& name,
1486 const ImageMSParams& imageMSParams)
1487 : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1488
1489 void init (void);
1490 void initPrograms (vk::SourceCollections& programCollection) const;
1491 TestInstance* createInstance (Context& context) const;
1492 };
1493
createMSCaseInterpolateAtOffsetSamplePosition(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1494 MSInterpolationCaseBase* createMSCaseInterpolateAtOffsetSamplePosition (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1495 {
1496 return new MSCaseInterpolateAtOffsetSamplePosition(testCtx, name, imageMSParams);
1497 }
1498
init(void)1499 void MSCaseInterpolateAtOffsetSamplePosition::init (void)
1500 {
1501 m_testCtx.getLog()
1502 << tcu::TestLog::Message
1503 << "Verifying that interpolateAtOffset of screen position with the offset of current sample position returns value "
1504 << "similar to screen position interpolated at sample.\n"
1505 << " Interpolate varying containing screen space location with and without sample qualifier.\n"
1506 << " => interpolateAtOffset(screenFragment, samplePosition - (0.5,0.5)) = screenSample"
1507 << tcu::TestLog::EndMessage;
1508
1509 MSInterpolationCaseBase::init();
1510 }
1511
initPrograms(vk::SourceCollections & programCollection) const1512 void MSCaseInterpolateAtOffsetSamplePosition::initPrograms (vk::SourceCollections& programCollection) const
1513 {
1514 // Create vertex shader
1515 std::ostringstream vs;
1516
1517 vs << "#version 440\n"
1518 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1519 << "layout(location = 1) in vec2 vs_in_position_screen;\n"
1520 << "\n"
1521 << "layout(location = 0) out vec2 vs_out_pos_screen_fragment;\n"
1522 << "layout(location = 1) out vec2 vs_out_pos_screen_sample;\n"
1523 << "\n"
1524 << "out gl_PerVertex {\n"
1525 << " vec4 gl_Position;\n"
1526 << "};\n"
1527 << "void main (void)\n"
1528 << "{\n"
1529 << " gl_Position = vs_in_position_ndc;\n"
1530 << " vs_out_pos_screen_fragment = vs_in_position_screen;\n"
1531 << " vs_out_pos_screen_sample = vs_in_position_screen;\n"
1532 << "}\n";
1533
1534 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1535
1536 // Create fragment shader
1537 std::ostringstream fs;
1538
1539 fs << "#version 440\n"
1540 << "layout(location = 0) in vec2 fs_in_pos_screen_fragment;\n"
1541 << "layout(location = 1) sample in vec2 fs_in_pos_screen_sample;\n"
1542 << "\n"
1543 << "layout(location = 0) out vec2 fs_out_color;\n"
1544 << "\n"
1545 << "void main (void)\n"
1546 << "{\n"
1547 << " const float threshold = 0.15625;\n"
1548 << "\n"
1549 << " const vec2 offset = gl_SamplePosition - vec2(0.5, 0.5);\n"
1550 << " const vec2 pos_interpolated_at_offset = interpolateAtOffset(fs_in_pos_screen_fragment, offset);\n"
1551 << " const bool valuesEqual = all(lessThan(abs(pos_interpolated_at_offset - fs_in_pos_screen_sample), vec2(threshold)));\n"
1552 << "\n"
1553 << " if (valuesEqual)\n"
1554 << " fs_out_color = vec2(0.0, 1.0);\n"
1555 << " else\n"
1556 << " fs_out_color = vec2(1.0, 0.0);\n"
1557 << "}\n";
1558
1559 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1560 }
1561
createInstance(Context & context) const1562 TestInstance* MSCaseInterpolateAtOffsetSamplePosition::createInstance (Context& context) const
1563 {
1564 return new MSInstanceInterpolateScreenPosition(context, m_imageMSParams);
1565 }
1566
1567 class MSInstanceInterpolateBarycentricCoordinates : public MSInterpolationInstanceBase
1568 {
1569 public:
MSInstanceInterpolateBarycentricCoordinates(Context & context,const ImageMSParams & imageMSParams)1570 MSInstanceInterpolateBarycentricCoordinates (Context& context,
1571 const ImageMSParams& imageMSParams)
1572 : MSInterpolationInstanceBase(context, imageMSParams) {}
1573
1574 VertexDataDesc getVertexDataDescripton (void) const;
1575 void uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const;
1576 tcu::TestStatus verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const;
1577
1578 protected:
1579 struct VertexData
1580 {
VertexDatavkt::pipeline::multisample::MSInstanceInterpolateBarycentricCoordinates::VertexData1581 VertexData(const tcu::Vec4& posNdc, const tcu::Vec3& barCoord) : positionNdc(posNdc), barycentricCoord(barCoord) {}
1582
1583 tcu::Vec4 positionNdc;
1584 tcu::Vec3 barycentricCoord;
1585 };
1586 };
1587
getVertexDataDescripton(void) const1588 MSInterpolationInstanceBase::VertexDataDesc MSInstanceInterpolateBarycentricCoordinates::getVertexDataDescripton (void) const
1589 {
1590 VertexDataDesc vertexDataDesc;
1591
1592 vertexDataDesc.verticesCount = 3u;
1593 vertexDataDesc.dataStride = sizeof(VertexData);
1594 vertexDataDesc.dataSize = vertexDataDesc.verticesCount * vertexDataDesc.dataStride;
1595 vertexDataDesc.primitiveTopology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1596
1597 const VkVertexInputAttributeDescription vertexAttribPositionNdc =
1598 {
1599 0u, // deUint32 location;
1600 0u, // deUint32 binding;
1601 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
1602 DE_OFFSET_OF(VertexData, positionNdc), // deUint32 offset;
1603 };
1604
1605 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttribPositionNdc);
1606
1607 const VkVertexInputAttributeDescription vertexAttrBarCoord =
1608 {
1609 1u, // deUint32 location;
1610 0u, // deUint32 binding;
1611 VK_FORMAT_R32G32B32_SFLOAT, // VkFormat format;
1612 DE_OFFSET_OF(VertexData, barycentricCoord), // deUint32 offset;
1613 };
1614
1615 vertexDataDesc.vertexAttribDescVec.push_back(vertexAttrBarCoord);
1616
1617 return vertexDataDesc;
1618 }
1619
uploadVertexData(const Allocation & vertexBufferAllocation,const VertexDataDesc & vertexDataDescripton) const1620 void MSInstanceInterpolateBarycentricCoordinates::uploadVertexData (const Allocation& vertexBufferAllocation, const VertexDataDesc& vertexDataDescripton) const
1621 {
1622 // Create buffer storing vertex data
1623 std::vector<VertexData> vertices;
1624
1625 vertices.push_back(VertexData(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 0.0f, 1.0f)));
1626 vertices.push_back(VertexData(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f), tcu::Vec3(1.0f, 0.0f, 0.0f)));
1627 vertices.push_back(VertexData(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f), tcu::Vec3(0.0f, 1.0f, 0.0f)));
1628
1629 deMemcpy(vertexBufferAllocation.getHostPtr(), dataPointer(vertices), static_cast<std::size_t>(vertexDataDescripton.dataSize));
1630 }
1631
verifyResolvedImage(const tcu::ConstPixelBufferAccess & imageData) const1632 tcu::TestStatus MSInstanceInterpolateBarycentricCoordinates::verifyResolvedImage (const tcu::ConstPixelBufferAccess& imageData) const
1633 {
1634 for (deInt32 z = 0u; z < imageData.getDepth(); ++z)
1635 for (deInt32 y = 0u; y < imageData.getHeight(); ++y)
1636 for (deInt32 x = 0u; x < imageData.getWidth(); ++x)
1637 {
1638 const deInt32 firstComponent = imageData.getPixelInt(x, y, z).x();
1639
1640 if (firstComponent > 0)
1641 return tcu::TestStatus::fail("Failed");
1642 }
1643
1644 return tcu::TestStatus::pass("Passed");
1645 }
1646
1647 class MSCaseCentroidQualifierInsidePrimitive : public MSInterpolationCaseBase
1648 {
1649 public:
MSCaseCentroidQualifierInsidePrimitive(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1650 MSCaseCentroidQualifierInsidePrimitive (tcu::TestContext& testCtx,
1651 const std::string& name,
1652 const ImageMSParams& imageMSParams)
1653 : MSInterpolationCaseBase(testCtx, name, imageMSParams) {}
1654
1655 void init (void);
1656 void initPrograms (vk::SourceCollections& programCollection) const;
1657 TestInstance* createInstance (Context& context) const;
1658 };
1659
createMSCaseCentroidQualifierInsidePrimitive(tcu::TestContext & testCtx,const std::string & name,const ImageMSParams & imageMSParams)1660 MSInterpolationCaseBase* createMSCaseCentroidQualifierInsidePrimitive (tcu::TestContext& testCtx, const std::string& name, const ImageMSParams& imageMSParams)
1661 {
1662 return new MSCaseCentroidQualifierInsidePrimitive(testCtx, name, imageMSParams);
1663 }
1664
init(void)1665 void MSCaseCentroidQualifierInsidePrimitive::init (void)
1666 {
1667 m_testCtx.getLog()
1668 << tcu::TestLog::Message
1669 << "Verifying that varying qualified with centroid is interpolated at location inside both the pixel and the primitive being processed.\n"
1670 << " Interpolate triangle's barycentric coordinates with centroid qualifier.\n"
1671 << " => After interpolation we expect barycentric.xyz >= 0.0 && barycentric.xyz <= 1.0\n"
1672 << tcu::TestLog::EndMessage;
1673
1674 MSInterpolationCaseBase::init();
1675 }
1676
initPrograms(vk::SourceCollections & programCollection) const1677 void MSCaseCentroidQualifierInsidePrimitive::initPrograms (vk::SourceCollections& programCollection) const
1678 {
1679 // Create vertex shader
1680 std::ostringstream vs;
1681
1682 vs << "#version 440\n"
1683 << "layout(location = 0) in vec4 vs_in_position_ndc;\n"
1684 << "layout(location = 1) in vec3 vs_in_barCoord;\n"
1685 << "\n"
1686 << "layout(location = 0) out vec3 vs_out_barCoord;\n"
1687 << "\n"
1688 << "out gl_PerVertex {\n"
1689 << " vec4 gl_Position;\n"
1690 << "};\n"
1691 << "void main (void)\n"
1692 << "{\n"
1693 << " gl_Position = vs_in_position_ndc;\n"
1694 << " vs_out_barCoord = vs_in_barCoord;\n"
1695 << "}\n";
1696
1697 programCollection.glslSources.add("vertex_shader") << glu::VertexSource(vs.str());
1698
1699 // Create fragment shader
1700 std::ostringstream fs;
1701
1702 fs << "#version 440\n"
1703 << "layout(location = 0) centroid in vec3 fs_in_barCoord;\n"
1704 << "\n"
1705 << "layout(location = 0) out vec2 fs_out_color;\n"
1706 << "\n"
1707 << "void main (void)\n"
1708 << "{\n"
1709 << " if( all(greaterThanEqual(fs_in_barCoord, vec3(0.0))) && all(lessThanEqual(fs_in_barCoord, vec3(1.0))) )\n"
1710 << " fs_out_color = vec2(0.0, 1.0);\n"
1711 << " else\n"
1712 << " fs_out_color = vec2(1.0, 0.0);\n"
1713 << "}\n";
1714
1715 programCollection.glslSources.add("fragment_shader") << glu::FragmentSource(fs.str());
1716 }
1717
createInstance(Context & context) const1718 TestInstance* MSCaseCentroidQualifierInsidePrimitive::createInstance (Context& context) const
1719 {
1720 return new MSInstanceInterpolateBarycentricCoordinates(context, m_imageMSParams);
1721 }
1722
1723 } // multisample
1724
makeGroup(multisample::MSInterpolationCaseFuncPtr createCaseFuncPtr,tcu::TestContext & testCtx,const std::string groupName,const tcu::UVec3 imageSizes[],const deUint32 imageSizesElemCount,const vk::VkSampleCountFlagBits imageSamples[],const deUint32 imageSamplesElemCount)1725 tcu::TestCaseGroup* makeGroup( multisample::MSInterpolationCaseFuncPtr createCaseFuncPtr,
1726 tcu::TestContext& testCtx,
1727 const std::string groupName,
1728 const tcu::UVec3 imageSizes[],
1729 const deUint32 imageSizesElemCount,
1730 const vk::VkSampleCountFlagBits imageSamples[],
1731 const deUint32 imageSamplesElemCount)
1732 {
1733 de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, groupName.c_str(), ""));
1734
1735 for (deUint32 imageSizeNdx = 0u; imageSizeNdx < imageSizesElemCount; ++imageSizeNdx)
1736 {
1737 const tcu::UVec3 imageSize = imageSizes[imageSizeNdx];
1738 std::ostringstream imageSizeStream;
1739
1740 imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
1741
1742 de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), ""));
1743
1744 for (deUint32 imageSamplesNdx = 0u; imageSamplesNdx < imageSamplesElemCount; ++imageSamplesNdx)
1745 {
1746 const vk::VkSampleCountFlagBits samples = imageSamples[imageSamplesNdx];
1747 const multisample::ImageMSParams imageMSParams = multisample::ImageMSParams(samples, imageSize);
1748
1749 sizeGroup->addChild(createCaseFuncPtr(testCtx, "samples_" + de::toString(samples), imageMSParams));
1750 }
1751
1752 caseGroup->addChild(sizeGroup.release());
1753 }
1754 return caseGroup.release();
1755 }
1756
createMultisampleInterpolationTests(tcu::TestContext & testCtx)1757 tcu::TestCaseGroup* createMultisampleInterpolationTests (tcu::TestContext& testCtx)
1758 {
1759 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "multisample_interpolation", "Multisample Interpolation"));
1760
1761 const tcu::UVec3 imageSizes[] =
1762 {
1763 tcu::UVec3(128u, 128u, 1u),
1764 tcu::UVec3(137u, 191u, 1u),
1765 };
1766
1767 const deUint32 sizesElemCount = static_cast<deUint32>(sizeof(imageSizes) / sizeof(tcu::UVec3));
1768
1769 const vk::VkSampleCountFlagBits imageSamples[] =
1770 {
1771 vk::VK_SAMPLE_COUNT_2_BIT,
1772 vk::VK_SAMPLE_COUNT_4_BIT,
1773 vk::VK_SAMPLE_COUNT_8_BIT,
1774 vk::VK_SAMPLE_COUNT_16_BIT,
1775 vk::VK_SAMPLE_COUNT_32_BIT,
1776 vk::VK_SAMPLE_COUNT_64_BIT,
1777 };
1778
1779 const deUint32 samplesElemCount = static_cast<deUint32>(sizeof(imageSamples) / sizeof(vk::VkSampleCountFlagBits));
1780
1781 de::MovePtr<tcu::TestCaseGroup> caseGroup(new tcu::TestCaseGroup(testCtx, "sample_interpolate_at_single_sample_", ""));
1782
1783 for (deUint32 imageSizeNdx = 0u; imageSizeNdx < sizesElemCount; ++imageSizeNdx)
1784 {
1785 const tcu::UVec3 imageSize = imageSizes[imageSizeNdx];
1786 std::ostringstream imageSizeStream;
1787
1788 imageSizeStream << imageSize.x() << "_" << imageSize.y() << "_" << imageSize.z();
1789
1790 de::MovePtr<tcu::TestCaseGroup> sizeGroup(new tcu::TestCaseGroup(testCtx, imageSizeStream.str().c_str(), ""));
1791
1792 sizeGroup->addChild(new multisample::MSCaseInterpolateAtSampleSingleSample(testCtx, "samples_" + de::toString(1), imageSize));
1793
1794 caseGroup->addChild(sizeGroup.release());
1795 }
1796
1797 testGroup->addChild(caseGroup.release());
1798
1799 testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleDistinctValues, testCtx, "sample_interpolate_at_distinct_values", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1800 testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleIgnoresCentroid, testCtx, "sample_interpolate_at_ignores_centroid", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1801 testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtSampleConsistency, testCtx, "sample_interpolate_at_consistency", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1802 testGroup->addChild(makeGroup(multisample::createMSCaseSampleQualifierDistinctValues, testCtx, "sample_qualifier_distinct_values", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1803 testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtCentroidConsistency, testCtx, "centroid_interpolate_at_consistency", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1804 testGroup->addChild(makeGroup(multisample::createMSCaseCentroidQualifierInsidePrimitive, testCtx, "centroid_qualifier_inside_primitive", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1805 testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtOffsetPixelCenter, testCtx, "offset_interpolate_at_pixel_center", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1806 testGroup->addChild(makeGroup(multisample::createMSCaseInterpolateAtOffsetSamplePosition, testCtx, "offset_interpolate_at_sample_position", imageSizes, sizesElemCount, imageSamples, samplesElemCount));
1807
1808 return testGroup.release();
1809 }
1810
1811 } // pipeline
1812 } // vkt
1813