1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2016 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Shader builtin variable tests.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktShaderRenderBuiltinVarTests.hpp"
27 
28 #include "tcuFloat.hpp"
29 #include "deUniquePtr.hpp"
30 #include "vkDefs.hpp"
31 #include "vktShaderRender.hpp"
32 #include "gluShaderUtil.hpp"
33 #include "tcuImageCompare.hpp"
34 #include "tcuStringTemplate.hpp"
35 #include "tcuTextureUtil.hpp"
36 #include "tcuTestLog.hpp"
37 #include "vktDrawUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkTypeUtil.hpp"
40 #include "vkMemUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 
43 #include "deMath.h"
44 #include "deRandom.hpp"
45 
46 #include <map>
47 
48 using namespace std;
49 using namespace tcu;
50 using namespace vk;
51 using namespace de;
52 
53 namespace vkt
54 {
55 using namespace drawutil;
56 
57 namespace sr
58 {
59 
60 namespace
61 {
62 
63 enum
64 {
65     FRONTFACE_RENDERWIDTH  = 16,
66     FRONTFACE_RENDERHEIGHT = 16
67 };
68 
69 class FrontFacingVertexShader : public rr::VertexShader
70 {
71 public:
FrontFacingVertexShader(void)72     FrontFacingVertexShader(void) : rr::VertexShader(1, 0)
73     {
74         m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
75     }
76 
~FrontFacingVertexShader()77     virtual ~FrontFacingVertexShader()
78     {
79     }
80 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const81     void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const
82     {
83         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
84         {
85             packets[packetNdx]->position =
86                 rr::readVertexAttribFloat(inputs[0], packets[packetNdx]->instanceNdx, packets[packetNdx]->vertexNdx);
87         }
88     }
89 };
90 
91 class FrontFacingFragmentShader : public rr::FragmentShader
92 {
93 public:
FrontFacingFragmentShader(void)94     FrontFacingFragmentShader(void) : rr::FragmentShader(0, 1)
95     {
96         m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
97     }
98 
~FrontFacingFragmentShader()99     virtual ~FrontFacingFragmentShader()
100     {
101     }
102 
shadeFragments(rr::FragmentPacket *,const int numPackets,const rr::FragmentShadingContext & context) const103     void shadeFragments(rr::FragmentPacket *, const int numPackets, const rr::FragmentShadingContext &context) const
104     {
105         tcu::Vec4 color;
106         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
107         {
108             for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
109             {
110                 if (context.visibleFace == rr::FACETYPE_FRONT)
111                     color = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
112                 else
113                     color = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
114                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
115             }
116         }
117     }
118 };
119 
120 class BuiltinGlFrontFacingCaseInstance : public ShaderRenderCaseInstance
121 {
122 public:
123     BuiltinGlFrontFacingCaseInstance(Context &context, VkPrimitiveTopology topology);
124 
125     TestStatus iterate(void);
126 
127 private:
128     const VkPrimitiveTopology m_topology;
129 };
130 
BuiltinGlFrontFacingCaseInstance(Context & context,VkPrimitiveTopology topology)131 BuiltinGlFrontFacingCaseInstance::BuiltinGlFrontFacingCaseInstance(Context &context, VkPrimitiveTopology topology)
132     : ShaderRenderCaseInstance(context)
133     , m_topology(topology)
134 {
135 }
136 
iterate(void)137 TestStatus BuiltinGlFrontFacingCaseInstance::iterate(void)
138 {
139     TestLog &log = m_context.getTestContext().getLog();
140     std::vector<Vec4> vertices;
141     std::vector<VulkanShader> shaders;
142     std::shared_ptr<rr::VertexShader> vertexShader     = std::make_shared<FrontFacingVertexShader>();
143     std::shared_ptr<rr::FragmentShader> fragmentShader = std::make_shared<FrontFacingFragmentShader>();
144     std::string testDesc;
145 
146     vertices.push_back(Vec4(-0.75f, -0.75f, 0.0f, 1.0f));
147     vertices.push_back(Vec4(0.0f, -0.75f, 0.0f, 1.0f));
148     vertices.push_back(Vec4(-0.37f, 0.75f, 0.0f, 1.0f));
149     vertices.push_back(Vec4(0.37f, 0.75f, 0.0f, 1.0f));
150     vertices.push_back(Vec4(0.75f, -0.75f, 0.0f, 1.0f));
151     vertices.push_back(Vec4(0.0f, -0.75f, 0.0f, 1.0f));
152 
153     shaders.push_back(VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("vert")));
154     shaders.push_back(VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("frag")));
155 
156     testDesc = "gl_FrontFacing " + getPrimitiveTopologyShortName(m_topology) + " ";
157 
158     FrameBufferState frameBufferState(FRONTFACE_RENDERWIDTH, FRONTFACE_RENDERHEIGHT);
159     PipelineState pipelineState(m_context.getDeviceProperties().limits.subPixelPrecisionBits);
160     DrawCallData drawCallData(m_topology, vertices);
161     VulkanProgram vulkanProgram(shaders);
162     VulkanDrawContext dc(m_context, frameBufferState);
163     dc.registerDrawObject(pipelineState, vulkanProgram, drawCallData);
164     dc.draw();
165 
166     ReferenceDrawContext refDrawContext(frameBufferState);
167     refDrawContext.registerDrawObject(pipelineState, vertexShader, fragmentShader, drawCallData);
168     refDrawContext.draw();
169 
170     log << TestLog::Image("reference", "reference",
171                           tcu::ConstPixelBufferAccess(tcu::TextureFormat(refDrawContext.getColorPixels().getFormat()),
172                                                       refDrawContext.getColorPixels().getWidth(),
173                                                       refDrawContext.getColorPixels().getHeight(), 1,
174                                                       refDrawContext.getColorPixels().getDataPtr()));
175 
176     log << TestLog::Image("result", "result",
177                           tcu::ConstPixelBufferAccess(tcu::TextureFormat(dc.getColorPixels().getFormat()),
178                                                       dc.getColorPixels().getWidth(), dc.getColorPixels().getHeight(),
179                                                       1, dc.getColorPixels().getDataPtr()));
180 
181     if (tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(), "ComparisonResult",
182                                                   "Image comparison result", refDrawContext.getColorPixels(),
183                                                   dc.getColorPixels(), UVec4(0u), IVec3(1, 1, 0), false,
184                                                   tcu::COMPARE_LOG_RESULT))
185     {
186         testDesc += "passed";
187         return tcu::TestStatus::pass(testDesc.c_str());
188     }
189     else
190     {
191         testDesc += "failed";
192         return tcu::TestStatus::fail(testDesc.c_str());
193     }
194 }
195 
196 class BuiltinGlFrontFacingCase : public TestCase
197 {
198 public:
199     BuiltinGlFrontFacingCase(TestContext &testCtx, VkPrimitiveTopology topology, const char *name);
200     virtual ~BuiltinGlFrontFacingCase(void);
201 
202     void initPrograms(SourceCollections &dst) const;
203     void checkSupport(Context &context) const;
204     TestInstance *createInstance(Context &context) const;
205 
206 private:
207     BuiltinGlFrontFacingCase(const BuiltinGlFrontFacingCase &);            // not allowed!
208     BuiltinGlFrontFacingCase &operator=(const BuiltinGlFrontFacingCase &); // not allowed!
209 
210     const VkPrimitiveTopology m_topology;
211 };
212 
BuiltinGlFrontFacingCase(TestContext & testCtx,VkPrimitiveTopology topology,const char * name)213 BuiltinGlFrontFacingCase::BuiltinGlFrontFacingCase(TestContext &testCtx, VkPrimitiveTopology topology, const char *name)
214     : TestCase(testCtx, name)
215     , m_topology(topology)
216 {
217 }
218 
~BuiltinGlFrontFacingCase(void)219 BuiltinGlFrontFacingCase::~BuiltinGlFrontFacingCase(void)
220 {
221 }
222 
initPrograms(SourceCollections & programCollection) const223 void BuiltinGlFrontFacingCase::initPrograms(SourceCollections &programCollection) const
224 {
225     {
226         std::ostringstream vertexSource;
227         vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
228                      << "\n"
229                      << "layout(location = 0) in highp vec4 position;\n"
230                      << "void main()\n"
231                      << "{\n"
232                      << "gl_Position = position;\n"
233                      << "gl_PointSize = 1.0;\n"
234                      << "}\n";
235         programCollection.glslSources.add("vert") << glu::VertexSource(vertexSource.str());
236     }
237 
238     {
239         std::ostringstream fragmentSource;
240         fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES) << "\n"
241                        << "\n"
242                        << "layout(location = 0) out mediump vec4 color;\n"
243                        << "void main()\n"
244                        << "{\n"
245                        << "if (gl_FrontFacing)\n"
246                        << "    color = vec4(1.0, 0.0, 0.0, 1.0);\n"
247                        << "else\n"
248                        << "    color = vec4(0.0, 1.0, 0.0, 1.0);\n"
249                        << "}\n";
250         programCollection.glslSources.add("frag") << glu::FragmentSource(fragmentSource.str());
251     }
252 }
253 
checkSupport(Context & context) const254 void BuiltinGlFrontFacingCase::checkSupport(Context &context) const
255 {
256 #ifndef CTS_USES_VULKANSC
257     if (m_topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
258         context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
259         !context.getPortabilitySubsetFeatures().triangleFans)
260     {
261         TCU_THROW(NotSupportedError,
262                   "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
263     }
264 #else
265     DE_UNREF(context);
266 #endif // CTS_USES_VULKANSC
267 }
268 
createInstance(Context & context) const269 TestInstance *BuiltinGlFrontFacingCase::createInstance(Context &context) const
270 {
271     return new BuiltinGlFrontFacingCaseInstance(context, m_topology);
272 }
273 
274 class BuiltinFragDepthCaseInstance : public TestInstance
275 {
276 public:
277     enum
278     {
279         RENDERWIDTH  = 16,
280         RENDERHEIGHT = 16
281     };
282     BuiltinFragDepthCaseInstance(Context &context, VkPrimitiveTopology topology, VkFormat format, bool largeDepthEnable,
283                                  float defaultDepth, bool depthClampEnable, const VkSampleCountFlagBits samples);
284     TestStatus iterate(void);
285 
286     bool validateDepthBuffer(const tcu::ConstPixelBufferAccess &validationBuffer,
287                              const tcu::ConstPixelBufferAccess &markerBuffer, const float tolerance) const;
288 
289 private:
290     const VkPrimitiveTopology m_topology;
291     const VkFormat m_format;
292     const bool m_largeDepthEnable;
293     const float m_defaultDepthValue;
294     const bool m_depthClampEnable;
295     const VkSampleCountFlagBits m_samples;
296     const tcu::UVec2 m_renderSize;
297     const float m_largeDepthBase;
298 };
299 
BuiltinFragDepthCaseInstance(Context & context,VkPrimitiveTopology topology,VkFormat format,bool largeDepthEnable,float defaultDepth,bool depthClampEnable,const VkSampleCountFlagBits samples)300 BuiltinFragDepthCaseInstance::BuiltinFragDepthCaseInstance(Context &context, VkPrimitiveTopology topology,
301                                                            VkFormat format, bool largeDepthEnable, float defaultDepth,
302                                                            bool depthClampEnable, const VkSampleCountFlagBits samples)
303     : TestInstance(context)
304     , m_topology(topology)
305     , m_format(format)
306     , m_largeDepthEnable(largeDepthEnable)
307     , m_defaultDepthValue(defaultDepth)
308     , m_depthClampEnable(depthClampEnable)
309     , m_samples(samples)
310     , m_renderSize(RENDERWIDTH, RENDERHEIGHT)
311     , m_largeDepthBase(20.0f)
312 {
313     const InstanceInterface &vki          = m_context.getInstanceInterface();
314     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
315 
316     try
317     {
318         VkImageFormatProperties imageFormatProperties;
319         VkFormatProperties formatProperties;
320 
321         if (m_context.getDeviceFeatures().fragmentStoresAndAtomics == VK_FALSE)
322             throw tcu::NotSupportedError("fragmentStoresAndAtomics not supported");
323 
324         if (m_context.getDeviceFeatures().sampleRateShading == VK_FALSE)
325             throw tcu::NotSupportedError("sampleRateShading not supported");
326 
327         imageFormatProperties = getPhysicalDeviceImageFormatProperties(
328             vki, physicalDevice, m_format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
329             VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, (VkImageCreateFlags)0);
330 
331         if ((imageFormatProperties.sampleCounts & m_samples) == 0)
332             throw tcu::NotSupportedError("Image format and sample count not supported");
333 
334         formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, VK_FORMAT_R8G8B8A8_UINT);
335 
336         if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
337             throw tcu::NotSupportedError("MarkerImage format not supported as storage image");
338 
339         if (m_largeDepthEnable && !de::contains(context.getDeviceExtensions().begin(),
340                                                 context.getDeviceExtensions().end(), "VK_EXT_depth_range_unrestricted"))
341             throw tcu::NotSupportedError(
342                 "large_depth test variants require the VK_EXT_depth_range_unrestricted extension");
343 
344         if (m_context.getDeviceFeatures().depthClamp == VK_FALSE && m_depthClampEnable)
345             throw tcu::NotSupportedError("Depthclamp is not supported.");
346     }
347     catch (const vk::Error &e)
348     {
349         if (e.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
350             throw tcu::NotSupportedError("Image format not supported");
351         else
352             throw;
353     }
354 }
355 
iterate(void)356 TestStatus BuiltinFragDepthCaseInstance::iterate(void)
357 {
358     const VkDevice device           = m_context.getDevice();
359     const DeviceInterface &vk       = m_context.getDeviceInterface();
360     const VkQueue queue             = m_context.getUniversalQueue();
361     Allocator &allocator            = m_context.getDefaultAllocator();
362     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
363     TestLog &log                    = m_context.getTestContext().getLog();
364     const uint32_t scale            = 4; // To account for std140 stride
365     const VkDeviceSize pixelCount   = m_renderSize.x() * m_renderSize.y();
366     std::string testDesc;
367     Move<VkImage> depthResolveImage;
368     Move<VkImageView> depthResolveImageView;
369     MovePtr<Allocation> depthResolveAllocation;
370     Move<VkImage> depthImage;
371     Move<VkImageView> depthImageView;
372     MovePtr<Allocation> depthImageAllocation;
373     Move<VkBuffer> controlBuffer;
374     MovePtr<Allocation> controlBufferAllocation;
375     Move<VkImage> markerImage;
376     Move<VkImageView> markerImageView;
377     MovePtr<Allocation> markerImageAllocation;
378     Move<VkBuffer> markerBuffer;
379     MovePtr<Allocation> markerBufferAllocation;
380     Move<VkBuffer> validationBuffer;
381     MovePtr<Allocation> validationAlloc;
382     MovePtr<Allocation> depthInitAllocation;
383     Move<VkCommandPool> cmdPool;
384     Move<VkCommandBuffer> transferCmdBuffer;
385     Move<VkSampler> depthSampler;
386 
387     // Create Buffer/Image for validation
388     {
389         VkFormat resolvedBufferFormat                       = VK_FORMAT_R32_SFLOAT;
390         const VkBufferCreateInfo validationBufferCreateInfo = {
391             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                                     // VkStructureType        sType
392             DE_NULL,                                                                  // const void*            pNext
393             (VkBufferCreateFlags)0,                                                   // VkBufferCreateFlags    flags
394             m_samples * pixelCount * getPixelSize(mapVkFormat(resolvedBufferFormat)), // VkDeviceSize            size
395             VK_BUFFER_USAGE_TRANSFER_DST_BIT,                                         // VkBufferUsageFlags    usage
396             VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode        sharingMode
397             0u,                        // uint32_t                queueFamilyIndexCount,
398             DE_NULL                    // const uint32_t*        pQueueFamilyIndices
399         };
400 
401         validationBuffer = createBuffer(vk, device, &validationBufferCreateInfo);
402         validationAlloc  = allocator.allocate(getBufferMemoryRequirements(vk, device, *validationBuffer),
403                                               MemoryRequirement::HostVisible);
404         VK_CHECK(
405             vk.bindBufferMemory(device, *validationBuffer, validationAlloc->getMemory(), validationAlloc->getOffset()));
406 
407         const VkImageCreateInfo depthResolveImageCreateInfo = {
408             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                              // VkStructureType            sType
409             DE_NULL,                                                          // const void*                pNext
410             (VkImageCreateFlags)0,                                            // VkImageCreateFlags        flags
411             VK_IMAGE_TYPE_2D,                                                 // VkIMageType                imageType
412             resolvedBufferFormat,                                             // VkFormat                    format
413             makeExtent3D(m_samples * m_renderSize.x(), m_renderSize.y(), 1u), // VkExtent3D                extent
414             1u,                                                               // uint32_t                    mipLevels
415             1u,                                                               // uint32_t                    arrayLayers
416             VK_SAMPLE_COUNT_1_BIT,                                            // VkSampleCountFlagsBits    samples
417             VK_IMAGE_TILING_OPTIMAL,                                          // VkImageTiling            tiling
418             VK_IMAGE_USAGE_TRANSFER_SRC_BIT |                                 // VkImageUsageFlags        usage
419                 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
420             VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode            sharingMode
421             0u,                        // uint32_t                    queueFamilyIndexCount
422             DE_NULL,                   // const uint32_t            pQueueFamilyIndices
423             VK_IMAGE_LAYOUT_UNDEFINED  // VkImageLayout            initialLayout
424         };
425 
426         depthResolveImage = createImage(vk, device, &depthResolveImageCreateInfo, DE_NULL);
427         depthResolveAllocation =
428             allocator.allocate(getImageMemoryRequirements(vk, device, *depthResolveImage), MemoryRequirement::Any);
429         VK_CHECK(vk.bindImageMemory(device, *depthResolveImage, depthResolveAllocation->getMemory(),
430                                     depthResolveAllocation->getOffset()));
431 
432         const VkImageViewCreateInfo depthResolveImageViewCreateInfo = {
433             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType            sType
434             DE_NULL,                                  // const void*                pNext
435             (VkImageViewCreateFlags)0,                // VkImageViewCreateFlags    flags
436             *depthResolveImage,                       // VkImage                    image
437             VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType            type
438             resolvedBufferFormat,                     // VkFormat                    format
439             makeComponentMappingRGBA(),               // VkComponentMapping        componentMapping
440             makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u,
441                                       1u) // VkImageSUbresourceRange    subresourceRange
442         };
443 
444         depthResolveImageView = createImageView(vk, device, &depthResolveImageViewCreateInfo, DE_NULL);
445     }
446 
447     // Marker Buffer
448     {
449         const VkDeviceSize size =
450             m_samples * m_renderSize.x() * m_renderSize.y() * getPixelSize(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT));
451 
452         const VkBufferCreateInfo markerBufferCreateInfo = {
453             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType            sType
454             DE_NULL,                              // const void*                pNext
455             (VkBufferCreateFlags)0,               // VkBufferCreateFlags        flags
456             size,                                 // VkDeviceSize                size
457             VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // VkBufferUsageFlags        usage
458             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode            sharingMode
459             0u,                                   // uint32_t                    queueFamilyIndexCount
460             DE_NULL                               // const uint32_t*            pQueueFamilyIndices
461         };
462 
463         markerBuffer = createBuffer(vk, device, &markerBufferCreateInfo, DE_NULL);
464         markerBufferAllocation =
465             allocator.allocate(getBufferMemoryRequirements(vk, device, *markerBuffer), MemoryRequirement::HostVisible);
466         VK_CHECK(vk.bindBufferMemory(device, *markerBuffer, markerBufferAllocation->getMemory(),
467                                      markerBufferAllocation->getOffset()));
468 
469         const VkImageCreateInfo markerImageCreateInfo = {
470             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                             // VkStructureType            sType
471             DE_NULL,                                                         // const void*                pNext
472             (VkImageCreateFlags)0,                                           // VkImageCreateFlags        flags
473             VK_IMAGE_TYPE_2D,                                                // VkImageType                imageType
474             VK_FORMAT_R8G8B8A8_UINT,                                         // VkFormat                    format
475             makeExtent3D(m_samples * m_renderSize.x(), m_renderSize.y(), 1), // VkExtent3D                extent
476             1u,                                                              // uint32_t                    mipLevels
477             1u,                                                              // uint32_t                    arrayLayers
478             VK_SAMPLE_COUNT_1_BIT,                                           // VkSampleCountFlagsBit    smaples
479             VK_IMAGE_TILING_OPTIMAL,                                         // VkImageTiling            tiling
480             VK_IMAGE_USAGE_STORAGE_BIT |                                     // VkImageUsageFlags        usage
481                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT,
482             VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode            sharing
483             0u,                        // uint32_t                    queueFamilyIndexCount
484             DE_NULL,                   // const uint32_t*            pQueueFamilyIndices
485             VK_IMAGE_LAYOUT_UNDEFINED  // VkImageLayout            initialLayout
486         };
487 
488         markerImage = createImage(vk, device, &markerImageCreateInfo, DE_NULL);
489         markerImageAllocation =
490             allocator.allocate(getImageMemoryRequirements(vk, device, *markerImage), MemoryRequirement::Any);
491         VK_CHECK(vk.bindImageMemory(device, *markerImage, markerImageAllocation->getMemory(),
492                                     markerImageAllocation->getOffset()));
493 
494         const VkImageViewCreateInfo markerViewCreateInfo = {
495             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType            sType
496             DE_NULL,                                  // const void*                pNext
497             (VkImageViewCreateFlags)0,                // VkImageViewCreateFlags    flags
498             *markerImage,                             // VkImage                    image
499             VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType            viewType
500             VK_FORMAT_R8G8B8A8_UINT,                  // VkFormat                    format
501             makeComponentMappingRGBA(),               // VkComponentMapping        components
502             makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u)};
503 
504         markerImageView = createImageView(vk, device, &markerViewCreateInfo, DE_NULL);
505     }
506 
507     // Control Buffer
508     {
509         const VkBufferCreateInfo controlBufferCreateInfo = {
510             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType        sType
511             DE_NULL,                              // const void*            pNext
512             (VkBufferCreateFlags)0,               // VkBufferCreateFlags    flags
513             pixelCount * sizeof(float) * scale,   // VkDeviceSize            size
514             VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,   // VkBufferUsageFlags    usage
515             VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode        sharingMode
516             0u,                                   // uint32_t                queueFamilyIndexCount
517 
518             DE_NULL // pQueueFamilyIndices
519         };
520 
521         controlBuffer = createBuffer(vk, device, &controlBufferCreateInfo, DE_NULL);
522         controlBufferAllocation =
523             allocator.allocate(getBufferMemoryRequirements(vk, device, *controlBuffer), MemoryRequirement::HostVisible);
524         VK_CHECK(vk.bindBufferMemory(device, *controlBuffer, controlBufferAllocation->getMemory(),
525                                      controlBufferAllocation->getOffset()));
526 
527         {
528             float *bufferData = (float *)(controlBufferAllocation->getHostPtr());
529             float sign        = m_depthClampEnable ? -1.0f : 1.0f;
530             for (uint32_t ndx = 0; ndx < m_renderSize.x() * m_renderSize.y(); ndx++)
531             {
532                 bufferData[ndx * scale] = (float)ndx / 256.0f * sign;
533                 if (m_largeDepthEnable)
534                     bufferData[ndx * scale] += m_largeDepthBase;
535             }
536 
537             const VkMappedMemoryRange range = {VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE, DE_NULL,
538                                                controlBufferAllocation->getMemory(), 0u, VK_WHOLE_SIZE};
539 
540             VK_CHECK(vk.flushMappedMemoryRanges(device, 1u, &range));
541         }
542     }
543 
544     // Depth Buffer
545     {
546         VkImageSubresourceRange depthSubresourceRange =
547             makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
548         const VkImageCreateInfo depthImageCreateInfo = {
549             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,                  // VkStructureType            sType
550             DE_NULL,                                              // const void*                pNext
551             (VkImageCreateFlags)0,                                // VkImageCreateFlags        flags
552             VK_IMAGE_TYPE_2D,                                     // VkImageType                imageType
553             m_format,                                             // VkFormat                    format
554             makeExtent3D(m_renderSize.x(), m_renderSize.y(), 1u), // VkExtent3D                extent
555             1u,                                                   // uint32_t                    mipLevels
556             1u,                                                   // uint32_t                    arrayLayers
557             m_samples,                                            // VkSampleCountFlagsBits    samples
558             VK_IMAGE_TILING_OPTIMAL,                              // VkImageTiling            tiling
559             VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
560                 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, // VkImageUsageFlags        usage
561             VK_SHARING_MODE_EXCLUSIVE,                       // VkShaderingMode            sharingMode
562             0u,                                              // uint32_t                    queueFamilyIndexCount
563             DE_NULL,                                         // const uint32_t*            pQueueFamilyIndices
564             VK_IMAGE_LAYOUT_UNDEFINED                        // VkImageLayout            initialLayout
565         };
566 
567         depthImage = createImage(vk, device, &depthImageCreateInfo, DE_NULL);
568         depthImageAllocation =
569             allocator.allocate(getImageMemoryRequirements(vk, device, *depthImage), MemoryRequirement::Any);
570         VK_CHECK(vk.bindImageMemory(device, *depthImage, depthImageAllocation->getMemory(),
571                                     depthImageAllocation->getOffset()));
572 
573         const VkImageViewCreateInfo imageViewParams = {
574             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
575             DE_NULL,                                  // const void* pNext;
576             (VkImageViewCreateFlags)0,                // VkImageViewCreateFlags flags;
577             *depthImage,                              // VkImage image;
578             VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType viewType;
579             m_format,                                 // VkFormat format;
580             makeComponentMappingRGBA(),               // VkComponentMapping components;
581             depthSubresourceRange,                    // VkImageSubresourceRange subresourceRange;
582         };
583         depthImageView = createImageView(vk, device, &imageViewParams);
584 
585         const VkSamplerCreateInfo depthSamplerCreateInfo = {
586             VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,   // VkStructureType            sType
587             DE_NULL,                                 // const void*                pNext
588             (VkSamplerCreateFlags)0,                 // VkSamplerCreateFlags        flags
589             VK_FILTER_NEAREST,                       // VkFilter                    minFilter
590             VK_FILTER_NEAREST,                       // VkFilter                    magFilter
591             VK_SAMPLER_MIPMAP_MODE_NEAREST,          // VkSamplerMipMapMode        mipMapMode
592             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode        addressModeU
593             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode        addressModeV
594             VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,   // VkSamplerAddressMode        addressmodeW
595             0.0f,                                    // float                    mipLodBias
596             VK_FALSE,                                // VkBool32                    anisotropyEnable
597             0.0f,                                    // float                    maxAnisotropy
598             VK_FALSE,                                // VkBool32                    compareEnable
599             VK_COMPARE_OP_NEVER,                     // VkCompareOp                compareOp
600             0.0f,                                    // float                    minLod
601             0.0f,                                    // float                    maxLod
602             VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // VkBorderColor            borderColor
603             VK_FALSE                                 // VkBool32                    unnormalizedCoordinates
604         };
605 
606         depthSampler = createSampler(vk, device, &depthSamplerCreateInfo, DE_NULL);
607     }
608 
609     // Command Pool
610     {
611         const VkCommandPoolCreateInfo cmdPoolCreateInfo = {
612             VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType            sType
613             DE_NULL,                                         // const void*                pNext
614             VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags    flags
615             queueFamilyIndex                                 // uint32_t                    queueFamilyIndex
616         };
617 
618         cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
619     }
620 
621     // Command buffer for data transfers
622     {
623         const VkCommandBufferAllocateInfo cmdBufferAllocInfo = {
624             VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType        sType,
625             DE_NULL,                                        // const void*            pNext
626             *cmdPool,                                       // VkCommandPool        commandPool
627             VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel    level
628             1u                                              // uint32_t                bufferCount
629         };
630 
631         transferCmdBuffer = allocateCommandBuffer(vk, device, &cmdBufferAllocInfo);
632     }
633 
634     // Initialize Marker Buffer
635     {
636         const VkImageMemoryBarrier imageBarrier[] = {
637             {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType        sType
638              DE_NULL,                                // const void*            pNext
639              0,                                      // VkAccessMask            srcAccessMask
640              VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessMask            dstAccessMask
641              VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout        oldLayout
642              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout        newLayout
643              VK_QUEUE_FAMILY_IGNORED,                // uint32_t                srcQueueFamilyIndex
644              VK_QUEUE_FAMILY_IGNORED,                // uint32_t                dstQueueFamilyIndex
645              *markerImage,                           // VkImage                image
646              {
647                  VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
648                  0u,                        // uint32_t                baseMipLevel
649                  1u,                        // uint32_t                mipLevels
650                  0u,                        // uint32_t                baseArray
651                  1u                         // uint32_t                arraySize
652              }},
653         };
654 
655         const VkImageMemoryBarrier imagePostBarrier[] = {
656             {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType        sType
657              DE_NULL,                                // const void*            pNext
658              VK_ACCESS_TRANSFER_WRITE_BIT,           // VkAccessFlagBits        srcAccessMask
659              VK_ACCESS_SHADER_WRITE_BIT,             // VkAccessFlagBits        dstAccessMask
660              VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,   // VkImageLayout        oldLayout
661              VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout        newLayout
662              VK_QUEUE_FAMILY_IGNORED,                // uint32_t                srcQueueFamilyIndex
663              VK_QUEUE_FAMILY_IGNORED,                // uint32_t                dstQueueFamilyIndex
664              *markerImage,                           // VkImage                image
665              {
666                  VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
667                  0u,                        // uint32_t                baseMipLevel
668                  1u,                        // uint32_t                mipLevels
669                  0u,                        // uint32_t                baseArray
670                  1u                         // uint32_t                arraySize
671              }},
672         };
673 
674         beginCommandBuffer(vk, *transferCmdBuffer);
675         vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
676                               (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
677                               (const VkBufferMemoryBarrier *)DE_NULL, DE_LENGTH_OF_ARRAY(imageBarrier), imageBarrier);
678 
679         const VkClearValue colorClearValue = makeClearValueColor(Vec4(0.0f, 0.0f, 0.0f, 0.0f));
680         const VkImageSubresourceRange colorClearRange =
681             makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
682 
683         vk.cmdClearColorImage(*transferCmdBuffer, *markerImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
684                               &colorClearValue.color, 1u, &colorClearRange);
685 
686         vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
687                               (VkDependencyFlags)0, 0, (const VkMemoryBarrier *)DE_NULL, 0,
688                               (const VkBufferMemoryBarrier *)DE_NULL, DE_LENGTH_OF_ARRAY(imagePostBarrier),
689                               imagePostBarrier);
690 
691         endCommandBuffer(vk, *transferCmdBuffer);
692 
693         submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
694         m_context.resetCommandPoolForVKSC(device, *cmdPool);
695     }
696 
697     // Perform Draw
698     {
699         std::vector<Vec4> vertices;
700         std::vector<VulkanShader> shaders;
701         Move<VkDescriptorSetLayout> descriptorSetLayout;
702         Move<VkDescriptorPool> descriptorPool;
703         Move<VkDescriptorSet> descriptorSet;
704 
705         // Descriptors
706         {
707             DescriptorSetLayoutBuilder layoutBuilder;
708             layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT);
709             layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
710             descriptorSetLayout = layoutBuilder.build(vk, device);
711             descriptorPool      = DescriptorPoolBuilder()
712                                  .addType(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER)
713                                  .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
714                                  .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
715 
716             const VkDescriptorSetAllocateInfo descriptorSetAllocInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
717                                                                         DE_NULL, *descriptorPool, 1u,
718                                                                         &descriptorSetLayout.get()};
719 
720             descriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);
721 
722             const VkDescriptorBufferInfo bufferInfo = {*controlBuffer, 0u, VK_WHOLE_SIZE};
723 
724             const VkDescriptorImageInfo imageInfo = {(VkSampler)DE_NULL, *markerImageView, VK_IMAGE_LAYOUT_GENERAL};
725 
726             DescriptorSetUpdateBuilder()
727                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
728                              VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &bufferInfo)
729                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
730                              VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo)
731                 .update(vk, device);
732         }
733 
734         vertices.push_back(Vec4(-0.70f, 0.5f, 0.0f, 1.0f));
735         vertices.push_back(Vec4(0.45f, -0.75f, 0.0f, 1.0f));
736         vertices.push_back(Vec4(0.78f, 0.0f, 0.0f, 1.0f));
737         vertices.push_back(Vec4(-0.1f, 0.6f, 0.0f, 1.0f));
738 
739         shaders.push_back(
740             VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("FragDepthVert")));
741         shaders.push_back(
742             VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("FragDepthFrag")));
743 
744         FrameBufferState frameBufferState(m_renderSize.x(), m_renderSize.y());
745         PipelineState pipelineState(m_context.getDeviceProperties().limits.subPixelPrecisionBits);
746         DrawCallData drawCallData(m_topology, vertices);
747         VulkanProgram vulkanProgram(shaders);
748 
749         frameBufferState.depthFormat      = m_format;
750         frameBufferState.numSamples       = m_samples;
751         frameBufferState.depthImageView   = *depthImageView;
752         pipelineState.depthClampEnable    = m_depthClampEnable;
753         pipelineState.compareOp           = rr::TESTFUNC_ALWAYS;
754         pipelineState.depthTestEnable     = true;
755         pipelineState.depthWriteEnable    = true;
756         pipelineState.sampleShadingEnable = true;
757         vulkanProgram.descriptorSetLayout = *descriptorSetLayout;
758         vulkanProgram.descriptorSet       = *descriptorSet;
759 
760         VulkanDrawContext vulkanDrawContext(m_context, frameBufferState);
761         vulkanDrawContext.registerDrawObject(pipelineState, vulkanProgram, drawCallData);
762         vulkanDrawContext.draw();
763 
764         log << TestLog::Image(
765             "resultColor", "Result Color Buffer",
766             tcu::ConstPixelBufferAccess(tcu::TextureFormat(vulkanDrawContext.getColorPixels().getFormat()),
767                                         vulkanDrawContext.getColorPixels().getWidth(),
768                                         vulkanDrawContext.getColorPixels().getHeight(), 1,
769                                         vulkanDrawContext.getColorPixels().getDataPtr()));
770     }
771 
772     // Barrier to transition between first and second pass
773     {
774         const VkImageMemoryBarrier imageBarrier[] = {
775             {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,           // VkStructureType        sType
776              DE_NULL,                                          // const void*            pNext
777              VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,     // VkAccessFlags        srcAccessMask
778              VK_ACCESS_SHADER_READ_BIT,                        // VkAccessFlags        dstAccessMask
779              VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout        oldLayout
780              VK_IMAGE_LAYOUT_GENERAL,                          // VkImageLayout        newLayout
781              0u,                                               // uint32_t                srcQueueFamilyIndex
782              0u,                                               // uint32_t                dstQueueFamilyIndex
783              *depthImage,                                      // VkImage                image
784              {
785                  VK_IMAGE_ASPECT_DEPTH_BIT, // VkImageAspectFlags        aspectMask
786                  0u,                        // uint32_t                    baseMipLevel
787                  1u,                        // uint32_t                    levelCount
788                  0u,                        // uint32_t                    baseArrayLayer
789                  1u                         // uint32_t                    layerCount
790              }},
791             {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType        sType
792              DE_NULL,                                // const void*            pNext
793              0u,                                     // VkAccessFlags        srcAccessMask
794              VK_ACCESS_HOST_READ_BIT,                // VkAccessFlags        dstAccessMask
795              VK_IMAGE_LAYOUT_UNDEFINED,              // VkImageLayout        oldLayout
796              VK_IMAGE_LAYOUT_GENERAL,                // VkImageLayout        newLayout
797              0u,                                     // uint32_t                srcQueueFamilyIndex
798              0u,                                     // uint32_t                dstQueueFamilyIndex
799              *depthResolveImage,                     // VkImage                image
800              {
801                  VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags        aspectMask
802                  0u,                        // uint32_t                    baseMipLevel
803                  1u,                        // uint32_t                    levelCount
804                  0u,                        // uint32_t                    baseArrayLayer
805                  1u,                        // uint32_t                    layerCount
806 
807              }}};
808 
809         beginCommandBuffer(vk, *transferCmdBuffer);
810         vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
811                               VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0,
812                               (const VkMemoryBarrier *)DE_NULL, 0, (const VkBufferMemoryBarrier *)DE_NULL,
813                               DE_LENGTH_OF_ARRAY(imageBarrier), imageBarrier);
814         endCommandBuffer(vk, *transferCmdBuffer);
815 
816         submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
817         m_context.resetCommandPoolForVKSC(device, *cmdPool);
818     }
819 
820     // Resolve Depth Buffer
821     {
822         std::vector<Vec4> vertices;
823         std::vector<VulkanShader> shaders;
824         Move<VkDescriptorSetLayout> descriptorSetLayout;
825         Move<VkDescriptorPool> descriptorPool;
826         Move<VkDescriptorSet> descriptorSet;
827 
828         // Descriptors
829         {
830             DescriptorSetLayoutBuilder layoutBuilder;
831             layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT);
832             layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
833             descriptorSetLayout = layoutBuilder.build(vk, device);
834             descriptorPool      = DescriptorPoolBuilder()
835                                  .addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
836                                  .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
837                                  .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
838 
839             const VkDescriptorSetAllocateInfo descriptorSetAllocInfo = {VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
840                                                                         DE_NULL, *descriptorPool, 1u,
841                                                                         &descriptorSetLayout.get()};
842 
843             descriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);
844 
845             const VkDescriptorImageInfo depthImageInfo = {*depthSampler, *depthImageView, VK_IMAGE_LAYOUT_GENERAL};
846 
847             const VkDescriptorImageInfo imageInfo = {(VkSampler)DE_NULL, *depthResolveImageView,
848                                                      VK_IMAGE_LAYOUT_GENERAL};
849 
850             DescriptorSetUpdateBuilder()
851                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
852                              VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &depthImageInfo)
853                 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(1u),
854                              VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo)
855                 .update(vk, device);
856         }
857 
858         vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
859         vertices.push_back(Vec4(-1.0f, 1.0f, 0.0f, 1.0f));
860         vertices.push_back(Vec4(1.0f, -1.0f, 0.0f, 1.0f));
861         vertices.push_back(Vec4(1.0f, 1.0f, 0.0f, 1.0f));
862 
863         shaders.push_back(
864             VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("FragDepthVertPass2")));
865         shaders.push_back(
866             VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("FragDepthFragPass2")));
867 
868         FrameBufferState frameBufferState(m_renderSize.x(), m_renderSize.y());
869         PipelineState pipelineState(m_context.getDeviceProperties().limits.subPixelPrecisionBits);
870         DrawCallData drawCallData(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, vertices);
871         VulkanProgram vulkanProgram(shaders);
872 
873         frameBufferState.numSamples       = m_samples;
874         pipelineState.sampleShadingEnable = true;
875         vulkanProgram.descriptorSetLayout = *descriptorSetLayout;
876         vulkanProgram.descriptorSet       = *descriptorSet;
877 
878         VulkanDrawContext vulkanDrawContext(m_context, frameBufferState);
879         vulkanDrawContext.registerDrawObject(pipelineState, vulkanProgram, drawCallData);
880         vulkanDrawContext.draw();
881     }
882 
883     // Transfer marker buffer
884     {
885         beginCommandBuffer(vk, *transferCmdBuffer);
886         copyImageToBuffer(vk, *transferCmdBuffer, *markerImage, *markerBuffer,
887                           tcu::IVec2(m_renderSize.x() * m_samples, m_renderSize.y()), VK_ACCESS_SHADER_WRITE_BIT,
888                           VK_IMAGE_LAYOUT_GENERAL);
889         endCommandBuffer(vk, *transferCmdBuffer);
890 
891         submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
892         m_context.resetCommandPoolForVKSC(device, *cmdPool);
893     }
894 
895     // Verify depth buffer
896     {
897         bool status;
898 
899         beginCommandBuffer(vk, *transferCmdBuffer, 0u);
900         copyImageToBuffer(vk, *transferCmdBuffer, *depthResolveImage, *validationBuffer,
901                           tcu::IVec2(m_renderSize.x() * m_samples, m_renderSize.y()), VK_ACCESS_SHADER_WRITE_BIT,
902                           VK_IMAGE_LAYOUT_GENERAL);
903         endCommandBuffer(vk, *transferCmdBuffer);
904 
905         submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
906         m_context.resetCommandPoolForVKSC(device, *cmdPool);
907 
908         invalidateMappedMemoryRange(vk, device, validationAlloc->getMemory(), validationAlloc->getOffset(),
909                                     VK_WHOLE_SIZE);
910         invalidateMappedMemoryRange(vk, device, markerBufferAllocation->getMemory(),
911                                     markerBufferAllocation->getOffset(), VK_WHOLE_SIZE);
912 
913         tcu::ConstPixelBufferAccess resultPixelBuffer(mapVkFormat(VK_FORMAT_R32_SFLOAT), m_renderSize.x() * m_samples,
914                                                       m_renderSize.y(), 1u, validationAlloc->getHostPtr());
915         tcu::ConstPixelBufferAccess markerPixelBuffer(mapVkFormat(VK_FORMAT_R8G8B8A8_UINT),
916                                                       m_renderSize.x() * m_samples, m_renderSize.y(), 1u,
917                                                       markerBufferAllocation->getHostPtr());
918         status   = validateDepthBuffer(resultPixelBuffer, markerPixelBuffer, 0.001f);
919         testDesc = "gl_FragDepth " + getPrimitiveTopologyShortName(m_topology) + " ";
920         if (status)
921         {
922             testDesc += "passed";
923             return tcu::TestStatus::pass(testDesc.c_str());
924         }
925         else
926         {
927             log << TestLog::Image("resultDepth", "Result Depth Buffer", resultPixelBuffer);
928             testDesc += "failed";
929             return tcu::TestStatus::fail(testDesc.c_str());
930         }
931     }
932 }
933 
validateDepthBuffer(const tcu::ConstPixelBufferAccess & validationBuffer,const tcu::ConstPixelBufferAccess & markerBuffer,const float tolerance) const934 bool BuiltinFragDepthCaseInstance::validateDepthBuffer(const tcu::ConstPixelBufferAccess &validationBuffer,
935                                                        const tcu::ConstPixelBufferAccess &markerBuffer,
936                                                        const float tolerance) const
937 {
938     TestLog &log = m_context.getTestContext().getLog();
939 
940     for (uint32_t rowNdx = 0; rowNdx < m_renderSize.y(); rowNdx++)
941     {
942         for (uint32_t colNdx = 0; colNdx < m_renderSize.x(); colNdx++)
943         {
944             const float multiplier = m_depthClampEnable ? 0.0f : 1.0f;
945             float expectedValue    = (float)(rowNdx * m_renderSize.x() + colNdx) / 256.0f * multiplier;
946 
947             if (m_largeDepthEnable)
948                 expectedValue += m_largeDepthBase;
949 
950             for (uint32_t sampleNdx = 0; sampleNdx < (uint32_t)m_samples; sampleNdx++)
951             {
952                 const float actualValue = validationBuffer.getPixel(sampleNdx + m_samples * colNdx, rowNdx).x();
953                 const float markerValue = markerBuffer.getPixel(sampleNdx + m_samples * colNdx, rowNdx).x();
954 
955                 if (markerValue != 0)
956                 {
957                     if (de::abs(expectedValue - actualValue) > tolerance)
958                     {
959                         log << TestLog::Message << "Mismatch at pixel (" << colNdx << "," << rowNdx << "," << sampleNdx
960                             << "): expected " << expectedValue << " but got " << actualValue << TestLog::EndMessage;
961                         return false;
962                     }
963                 }
964                 else
965                 {
966                     if (de::abs(actualValue - m_defaultDepthValue) > tolerance)
967                     {
968                         log << TestLog::Message << "Mismatch at pixel (" << colNdx << "," << rowNdx << "," << sampleNdx
969                             << "): expected " << expectedValue << " but got " << actualValue << TestLog::EndMessage;
970                         return false;
971                     }
972                 }
973             }
974         }
975     }
976 
977     return true;
978 }
979 
980 class BuiltinFragCoordMsaaCaseInstance : public TestInstance
981 {
982 public:
983     enum
984     {
985         RENDERWIDTH  = 16,
986         RENDERHEIGHT = 16
987     };
988     BuiltinFragCoordMsaaCaseInstance(Context &context, VkSampleCountFlagBits sampleCount, bool sampleShading,
989                                      std::vector<uint32_t> sampleMaskArray, bool useEnable);
990     TestStatus iterate(void);
991 
992 private:
993     bool validateSampleLocations(const ConstPixelBufferAccess &sampleLocationBuffer) const;
994 
995     const tcu::UVec2 m_renderSize;
996     const VkSampleCountFlagBits m_sampleCount;
997     const bool m_sampleShading;
998     const std::vector<uint32_t> m_sampleMaskArray;
999     const bool m_useEnable;
1000 };
1001 
BuiltinFragCoordMsaaCaseInstance(Context & context,VkSampleCountFlagBits sampleCount,bool sampleShading,std::vector<uint32_t> sampleMaskArray,bool useEnable)1002 BuiltinFragCoordMsaaCaseInstance::BuiltinFragCoordMsaaCaseInstance(Context &context, VkSampleCountFlagBits sampleCount,
1003                                                                    bool sampleShading,
1004                                                                    std::vector<uint32_t> sampleMaskArray,
1005                                                                    bool useEnable)
1006     : TestInstance(context)
1007     , m_renderSize(RENDERWIDTH, RENDERHEIGHT)
1008     , m_sampleCount(sampleCount)
1009     , m_sampleShading(sampleShading)
1010     , m_sampleMaskArray(sampleMaskArray)
1011     , m_useEnable(useEnable)
1012 {
1013     const InstanceInterface &vki          = m_context.getInstanceInterface();
1014     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1015 
1016     if (!context.getDeviceFeatures().sampleRateShading)
1017         TCU_THROW(NotSupportedError, "sampleRateShading not supported");
1018 
1019     try
1020     {
1021         VkImageFormatProperties imageFormatProperties;
1022         VkFormatProperties formatProperties;
1023 
1024         if (m_context.getDeviceFeatures().fragmentStoresAndAtomics == VK_FALSE)
1025             throw tcu::NotSupportedError("fragmentStoresAndAtomics not supported");
1026 
1027         if (m_context.getDeviceFeatures().sampleRateShading == VK_FALSE)
1028             throw tcu::NotSupportedError("sampleRateShading not supported");
1029 
1030         imageFormatProperties = getPhysicalDeviceImageFormatProperties(
1031             vki, physicalDevice, VK_FORMAT_R32G32B32A32_SFLOAT, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
1032             VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, (VkImageCreateFlags)0);
1033 
1034         if ((imageFormatProperties.sampleCounts & m_sampleCount) == 0)
1035             throw tcu::NotSupportedError("Image format and sample count not supported");
1036 
1037         formatProperties = getPhysicalDeviceFormatProperties(vki, physicalDevice, VK_FORMAT_R32G32B32A32_SFLOAT);
1038 
1039         if ((formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) == 0)
1040             throw tcu::NotSupportedError("Output format not supported as storage image");
1041     }
1042     catch (const vk::Error &e)
1043     {
1044         if (e.getError() == VK_ERROR_FORMAT_NOT_SUPPORTED)
1045             throw tcu::NotSupportedError("Image format not supported");
1046         else
1047             throw;
1048     }
1049 }
1050 
iterate(void)1051 TestStatus BuiltinFragCoordMsaaCaseInstance::iterate(void)
1052 {
1053     const VkDevice device           = m_context.getDevice();
1054     const DeviceInterface &vk       = m_context.getDeviceInterface();
1055     const VkQueue queue             = m_context.getUniversalQueue();
1056     Allocator &allocator            = m_context.getDefaultAllocator();
1057     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1058     TestLog &log                    = m_context.getTestContext().getLog();
1059     Move<VkImage> outputImage;
1060     Move<VkImageView> outputImageView;
1061     MovePtr<Allocation> outputImageAllocation;
1062     Move<VkDescriptorSetLayout> descriptorSetLayout;
1063     Move<VkDescriptorPool> descriptorPool;
1064     Move<VkDescriptorSet> descriptorSet;
1065     Move<VkBuffer> sampleLocationBuffer;
1066     MovePtr<Allocation> sampleLocationBufferAllocation;
1067     Move<VkCommandPool> cmdPool;
1068     Move<VkCommandBuffer> transferCmdBuffer;
1069 
1070     // Coordinate result image
1071     {
1072         const VkImageCreateInfo outputImageCreateInfo = {
1073             VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
1074             DE_NULL,                             // const void*                pNext
1075             (VkImageCreateFlags)0,               // VkImageCreateFlags        flags
1076             VK_IMAGE_TYPE_2D,                    // VkImageType                imageType
1077             VK_FORMAT_R32G32B32A32_SFLOAT,       // VkFormat                    format
1078             makeExtent3D(m_sampleCount * m_renderSize.x(), m_renderSize.y(), 1u), // VkExtent3D                extent3d
1079             1u,                          // uint32_t                    mipLevels
1080             1u,                          // uint32_t                    arrayLayers
1081             VK_SAMPLE_COUNT_1_BIT,       // VkSampleCountFlagBits    samples
1082             VK_IMAGE_TILING_OPTIMAL,     // VkImageTiling            tiling
1083             VK_IMAGE_USAGE_STORAGE_BIT | // VkImageUsageFlags        usage
1084                 VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
1085             VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode            sharingMode
1086             0u,                        // uint32_t                    queueFamilyIndexCount
1087             DE_NULL,                   // const uint32_t*            pQueueFamilyIndices
1088             VK_IMAGE_LAYOUT_UNDEFINED  // VkImageLayout            initialLayout
1089         };
1090 
1091         outputImage = createImage(vk, device, &outputImageCreateInfo, DE_NULL);
1092         outputImageAllocation =
1093             allocator.allocate(getImageMemoryRequirements(vk, device, *outputImage), MemoryRequirement::Any);
1094         vk.bindImageMemory(device, *outputImage, outputImageAllocation->getMemory(),
1095                            outputImageAllocation->getOffset());
1096 
1097         VkImageSubresourceRange imageSubresourceRange =
1098             makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1099         const VkImageViewCreateInfo outputImageViewCreateInfo = {
1100             VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType            sType
1101             DE_NULL,                                  // const void*                pNext
1102             (VkImageViewCreateFlags)0,                // VkImageViewCreateFlags    flags
1103             *outputImage,                             // VkImage                    image
1104             VK_IMAGE_VIEW_TYPE_2D,                    // VkImageViewType            viewType
1105             VK_FORMAT_R32G32B32A32_SFLOAT,            // VkFormat                    format,
1106             makeComponentMappingRGBA(),               // VkComponentMapping        components
1107             imageSubresourceRange                     // VkImageSubresourceRange    imageSubresourceRange
1108         };
1109 
1110         outputImageView = createImageView(vk, device, &outputImageViewCreateInfo);
1111     }
1112 
1113     // Validation buffer
1114     {
1115         VkDeviceSize pixelSize = getPixelSize(mapVkFormat(VK_FORMAT_R32G32B32A32_SFLOAT));
1116         const VkBufferCreateInfo sampleLocationBufferCreateInfo = {
1117             VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,                            // VkStructureType        sType
1118             DE_NULL,                                                         // const void*            pNext
1119             (VkBufferCreateFlags)0,                                          // VkBufferCreateFlags    flags
1120             m_sampleCount * m_renderSize.x() * m_renderSize.y() * pixelSize, // VkDeviceSize            size
1121             VK_BUFFER_USAGE_TRANSFER_DST_BIT,                                // VkBufferUsageFlags    usage
1122             VK_SHARING_MODE_EXCLUSIVE,                                       // VkSharingMode        mode
1123             0u,     // uint32_t                queueFamilyIndexCount
1124             DE_NULL // const uint32_t*        pQueueFamilyIndices
1125         };
1126 
1127         sampleLocationBuffer           = createBuffer(vk, device, &sampleLocationBufferCreateInfo, DE_NULL);
1128         sampleLocationBufferAllocation = allocator.allocate(
1129             getBufferMemoryRequirements(vk, device, *sampleLocationBuffer), MemoryRequirement::HostVisible);
1130         vk.bindBufferMemory(device, *sampleLocationBuffer, sampleLocationBufferAllocation->getMemory(),
1131                             sampleLocationBufferAllocation->getOffset());
1132     }
1133 
1134     // Descriptors
1135     {
1136         DescriptorSetLayoutBuilder layoutBuilder;
1137         layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
1138         descriptorSetLayout = layoutBuilder.build(vk, device);
1139         descriptorPool      = DescriptorPoolBuilder()
1140                              .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
1141                              .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
1142 
1143         const VkDescriptorSetAllocateInfo descriptorSetAllocInfo = {
1144             VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, DE_NULL, *descriptorPool, 1u, &*descriptorSetLayout};
1145 
1146         descriptorSet = allocateDescriptorSet(vk, device, &descriptorSetAllocInfo);
1147 
1148         const VkDescriptorImageInfo imageInfo = {(VkSampler)DE_NULL, *outputImageView, VK_IMAGE_LAYOUT_GENERAL};
1149 
1150         DescriptorSetUpdateBuilder()
1151             .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u),
1152                          VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &imageInfo)
1153             .update(vk, device);
1154     }
1155 
1156     // Command Pool
1157     {
1158         const VkCommandPoolCreateInfo cmdPoolCreateInfo = {
1159             VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,      // VkStructureType            sType
1160             DE_NULL,                                         // const void*                pNext
1161             VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // VkCommandPoolCreateFlags    flags
1162             queueFamilyIndex                                 // uint32_t                    queueFamilyIndex
1163         };
1164 
1165         cmdPool = createCommandPool(vk, device, &cmdPoolCreateInfo);
1166     }
1167 
1168     // Command buffer for data transfers
1169     {
1170         const VkCommandBufferAllocateInfo cmdBufferAllocInfo = {
1171             VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // VkStructureType        sType,
1172             DE_NULL,                                        // const void*            pNext
1173             *cmdPool,                                       // VkCommandPool        commandPool
1174             VK_COMMAND_BUFFER_LEVEL_PRIMARY,                // VkCommandBufferLevel    level
1175             1u                                              // uint32_t                bufferCount
1176         };
1177 
1178         transferCmdBuffer = allocateCommandBuffer(vk, device, &cmdBufferAllocInfo);
1179     }
1180 
1181     // Transition the output image to LAYOUT_GENERAL
1182     {
1183         const VkImageMemoryBarrier barrier = {VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType        sType
1184                                               DE_NULL,                                // const void*            pNext
1185                                               0u,                         // VkAccessFlags        srcAccessMask
1186                                               VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags        dstAccessMask
1187                                               VK_IMAGE_LAYOUT_UNDEFINED,  // VkImageLayout        oldLayout
1188                                               VK_IMAGE_LAYOUT_GENERAL,    // VkImageLayout        newLayout
1189                                               VK_QUEUE_FAMILY_IGNORED,    // uint32_t                srcQueueFamilyIndex
1190                                               VK_QUEUE_FAMILY_IGNORED,    // uint32_t                dstQueueFamilyIndex
1191                                               *outputImage,               // VkImage                image
1192                                               {
1193                                                   VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags    aspectMask
1194                                                   0u,                        // uint32_t                baseMipLevel
1195                                                   1u,                        // uint32_t                mipLevels
1196                                                   0u,                        // uint32_t                baseArray
1197                                                   1u                         // uint32_t                arraySize
1198                                               }};
1199 
1200         beginCommandBuffer(vk, *transferCmdBuffer);
1201         vk.cmdPipelineBarrier(*transferCmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1202                               VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 0,
1203                               (const VkMemoryBarrier *)DE_NULL, 0, (const VkBufferMemoryBarrier *)DE_NULL, 1, &barrier);
1204 
1205         endCommandBuffer(vk, *transferCmdBuffer);
1206 
1207         submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
1208         m_context.resetCommandPoolForVKSC(device, *cmdPool);
1209     }
1210 
1211     // Perform draw
1212     {
1213         std::vector<Vec4> vertices;
1214         std::vector<VulkanShader> shaders;
1215 
1216         vertices.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
1217         vertices.push_back(Vec4(-1.0f, 1.0f, 0.0f, 1.0f));
1218         vertices.push_back(Vec4(1.0f, -1.0f, 0.0f, 1.0f));
1219         vertices.push_back(Vec4(1.0f, 1.0f, 0.0f, 1.0f));
1220 
1221         shaders.push_back(
1222             VulkanShader(VK_SHADER_STAGE_VERTEX_BIT, m_context.getBinaryCollection().get("FragCoordMsaaVert")));
1223         shaders.push_back(
1224             VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_context.getBinaryCollection().get("FragCoordMsaaFrag")));
1225 
1226         FrameBufferState frameBufferState(m_renderSize.x(), m_renderSize.y());
1227         PipelineState pipelineState(m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1228         DrawCallData drawCallData(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, vertices);
1229         VulkanProgram vulkanProgram(shaders);
1230 
1231         frameBufferState.numSamples = m_sampleCount;
1232         pipelineState.sampleShadingEnable =
1233             m_useEnable; // When m_useEnable is false, we rely on the gl_SampleID input to enable sample shading
1234         pipelineState.sampleMasks         = m_sampleMaskArray;
1235         vulkanProgram.descriptorSetLayout = *descriptorSetLayout;
1236         vulkanProgram.descriptorSet       = *descriptorSet;
1237 
1238         VulkanDrawContext vulkanDrawContext(m_context, frameBufferState);
1239         vulkanDrawContext.registerDrawObject(pipelineState, vulkanProgram, drawCallData);
1240         vulkanDrawContext.draw();
1241 
1242         log << TestLog::Image(
1243             "result", "result",
1244             tcu::ConstPixelBufferAccess(tcu::TextureFormat(vulkanDrawContext.getColorPixels().getFormat()),
1245                                         vulkanDrawContext.getColorPixels().getWidth(),
1246                                         vulkanDrawContext.getColorPixels().getHeight(), 1,
1247                                         vulkanDrawContext.getColorPixels().getDataPtr()));
1248     }
1249 
1250     // Transfer location image to buffer
1251     {
1252         beginCommandBuffer(vk, *transferCmdBuffer);
1253         copyImageToBuffer(vk, *transferCmdBuffer, *outputImage, *sampleLocationBuffer,
1254                           tcu::IVec2(m_renderSize.x() * m_sampleCount, m_renderSize.y()), VK_ACCESS_SHADER_WRITE_BIT,
1255                           VK_IMAGE_LAYOUT_GENERAL);
1256         endCommandBuffer(vk, *transferCmdBuffer);
1257 
1258         submitCommandsAndWait(vk, device, queue, transferCmdBuffer.get());
1259         m_context.resetCommandPoolForVKSC(device, *cmdPool);
1260 
1261         invalidateAlloc(vk, device, *sampleLocationBufferAllocation);
1262     }
1263 
1264     // Validate result
1265     {
1266         bool status;
1267 
1268         ConstPixelBufferAccess sampleLocationPixelBuffer(mapVkFormat(VK_FORMAT_R32G32B32A32_SFLOAT),
1269                                                          m_sampleCount * m_renderSize.x(), m_renderSize.y(), 1u,
1270                                                          sampleLocationBufferAllocation->getHostPtr());
1271 
1272         status = validateSampleLocations(sampleLocationPixelBuffer);
1273         if (status)
1274             return TestStatus::pass("FragCoordMsaa passed");
1275         else
1276             return TestStatus::fail("FragCoordMsaa failed");
1277     }
1278 }
1279 
pixelOffsetCompare(const Vec2 & a,const Vec2 & b)1280 static bool pixelOffsetCompare(const Vec2 &a, const Vec2 &b)
1281 {
1282     return a.x() < b.x();
1283 }
1284 
validateSampleLocations(const ConstPixelBufferAccess & sampleLocationBuffer) const1285 bool BuiltinFragCoordMsaaCaseInstance::validateSampleLocations(const ConstPixelBufferAccess &sampleLocationBuffer) const
1286 {
1287     const InstanceInterface &vki          = m_context.getInstanceInterface();
1288     TestLog &log                          = m_context.getTestContext().getLog();
1289     const VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
1290     uint32_t logSampleCount               = deLog2Floor32(m_sampleCount);
1291     VkPhysicalDeviceProperties physicalDeviceProperties;
1292 
1293     static const Vec2 sampleCount1Bit[] = {Vec2(0.5f, 0.5f)};
1294 
1295     static const Vec2 sampleCount2Bit[] = {Vec2(0.25f, 0.25f), Vec2(0.75f, 0.75f)};
1296 
1297     static const Vec2 sampleCount4Bit[] = {Vec2(0.375f, 0.125f), Vec2(0.875f, 0.375f), Vec2(0.125f, 0.625f),
1298                                            Vec2(0.625f, 0.875f)};
1299 
1300     static const Vec2 sampleCount8Bit[] = {Vec2(0.5625f, 0.3125f), Vec2(0.4375f, 0.6875f), Vec2(0.8125f, 0.5625f),
1301                                            Vec2(0.3125f, 0.1875f), Vec2(0.1875f, 0.8125f), Vec2(0.0625f, 0.4375f),
1302                                            Vec2(0.6875f, 0.9375f), Vec2(0.9375f, 0.0625f)};
1303 
1304     static const Vec2 sampleCount16Bit[] = {
1305         Vec2(0.5625f, 0.5625f), Vec2(0.4375f, 0.3125f), Vec2(0.3125f, 0.6250f), Vec2(0.7500f, 0.4375f),
1306         Vec2(0.1875f, 0.3750f), Vec2(0.6250f, 0.8125f), Vec2(0.8125f, 0.6875f), Vec2(0.6875f, 0.1875f),
1307         Vec2(0.3750f, 0.8750f), Vec2(0.5000f, 0.0625f), Vec2(0.2500f, 0.1250f), Vec2(0.1250f, 0.7500f),
1308         Vec2(0.0000f, 0.5000f), Vec2(0.9375f, 0.2500f), Vec2(0.8750f, 0.9375f), Vec2(0.0625f, 0.0000f)};
1309 
1310     static const Vec2 *standardSampleLocationTable[] = {sampleCount1Bit, sampleCount2Bit, sampleCount4Bit,
1311                                                         sampleCount8Bit, sampleCount16Bit};
1312 
1313     vki.getPhysicalDeviceProperties(physicalDevice, &physicalDeviceProperties);
1314 
1315     for (int32_t rowNdx = 0; rowNdx < (int32_t)m_renderSize.y(); rowNdx++)
1316     {
1317         for (int32_t colNdx = 0; colNdx < (int32_t)m_renderSize.x(); colNdx++)
1318         {
1319             // Check standard sample locations
1320             if (m_sampleShading == true)
1321             {
1322                 std::vector<Vec2> locations;
1323 
1324                 for (uint32_t sampleNdx = 0; sampleNdx < (uint32_t)m_sampleCount; sampleNdx++)
1325                 {
1326                     const UVec2 pixelAddress = UVec2(sampleNdx + m_sampleCount * colNdx, rowNdx);
1327                     const Vec4 pixelData     = sampleLocationBuffer.getPixel(pixelAddress.x(), pixelAddress.y());
1328 
1329                     if (pixelData.z() != 0.0f)
1330                     {
1331                         log << TestLog::Message << "Pixel (" << colNdx << "," << rowNdx
1332                             << "): has unexpected .z component, expected: 0.0, got: " << pixelData.z()
1333                             << TestLog::EndMessage;
1334                         return false;
1335                     }
1336 
1337                     if (pixelData.w() != 1.0f)
1338                     {
1339                         log << TestLog::Message << "Pixel (" << colNdx << "," << rowNdx
1340                             << "): has unexpected .w component, expected: 1.0, got: " << pixelData.w()
1341                             << TestLog::EndMessage;
1342                         return false;
1343                     }
1344 
1345                     locations.push_back(Vec2(pixelData.x(), pixelData.y()));
1346                 }
1347                 std::sort(locations.begin(), locations.end(), pixelOffsetCompare);
1348                 for (std::vector<Vec2>::const_iterator sampleIt = locations.begin(); sampleIt != locations.end();
1349                      sampleIt++)
1350                 {
1351                     IVec2 sampleFloor(deFloorFloatToInt32((*sampleIt).x()), deFloorFloatToInt32((*sampleIt).y()));
1352                     IVec2 sampleCeil(deCeilFloatToInt32((*sampleIt).x()), deCeilFloatToInt32((*sampleIt).y()));
1353 
1354                     if ((sampleFloor.x() < colNdx) || (sampleCeil.x() > colNdx + 1) || (sampleFloor.y() < rowNdx) ||
1355                         (sampleCeil.y() > rowNdx + 1))
1356                     {
1357                         log << TestLog::Message << "Pixel (" << colNdx << "," << rowNdx << "): " << *sampleIt
1358                             << TestLog::EndMessage;
1359                         return false;
1360                     }
1361                 }
1362 
1363                 std::vector<Vec2>::iterator last = std::unique(locations.begin(), locations.end());
1364                 if (last != locations.end())
1365                 {
1366                     log << TestLog::Message << "Fail: Sample locations contains non-unique entry"
1367                         << TestLog::EndMessage;
1368                     return false;
1369                 }
1370 
1371                 if (logSampleCount < DE_LENGTH_OF_ARRAY(standardSampleLocationTable))
1372                 {
1373                     if (physicalDeviceProperties.limits.standardSampleLocations)
1374                     {
1375                         for (uint32_t sampleNdx = 0; sampleNdx < (uint32_t)m_sampleCount; sampleNdx++)
1376                         {
1377                             if (!de::contains(locations.begin(), locations.end(),
1378                                               standardSampleLocationTable[logSampleCount][sampleNdx] +
1379                                                   Vec2(float(colNdx), float(rowNdx))))
1380                             {
1381                                 log << TestLog::Message << "Didn't match sample locations "
1382                                     << standardSampleLocationTable[logSampleCount][sampleNdx] << TestLog::EndMessage;
1383                                 return false;
1384                             }
1385                         }
1386                     }
1387                 }
1388             }
1389             else
1390             {
1391                 // Check the sample location is at the pixel center when sample shading is disabled.
1392                 const Vec4 pixelData = sampleLocationBuffer.getPixel(colNdx, rowNdx);
1393 
1394                 if (pixelData.z() != 0.0f)
1395                 {
1396                     log << TestLog::Message << "Pixel (" << colNdx << "," << rowNdx
1397                         << "): has unexpected .z component, expected: 0.0, got: " << pixelData.z()
1398                         << TestLog::EndMessage;
1399                     return false;
1400                 }
1401 
1402                 if (pixelData.w() != 1.0f)
1403                 {
1404                     log << TestLog::Message << "Pixel (" << colNdx << "," << rowNdx
1405                         << "): has unexpected .w component, expected: 1.0, got: " << pixelData.w()
1406                         << TestLog::EndMessage;
1407                     return false;
1408                 }
1409 
1410                 if (!(deFloatFrac(pixelData.x()) == 0.5f && deFloatFrac(pixelData.y()) == 0.5f))
1411                 {
1412                     log << TestLog::Message << "Didn't match sample locations (" << pixelData.x() << ", "
1413                         << pixelData.y() << "): " << Vec2(float(colNdx) + 0.5f, float(rowNdx) + 0.5f)
1414                         << TestLog::EndMessage;
1415                     return false;
1416                 }
1417             }
1418         }
1419     }
1420 
1421     return true;
1422 }
1423 
1424 class BuiltinFragCoordMsaaTestCase : public TestCase
1425 {
1426 public:
1427     BuiltinFragCoordMsaaTestCase(TestContext &testCtx, const char *name, VkSampleCountFlagBits sampleCount,
1428                                  bool sampleShading, std::vector<uint32_t> sampleMaskArray, bool useCentroid,
1429                                  bool useEnable);
1430     virtual ~BuiltinFragCoordMsaaTestCase(void);
1431     void initPrograms(SourceCollections &sourceCollections) const;
1432     TestInstance *createInstance(Context &context) const;
1433 
1434 private:
1435     const VkSampleCountFlagBits m_sampleCount;
1436     const bool m_sampleShading; // Enable or disable Sample Shading.
1437     const std::vector<uint32_t> m_sampleMaskArray;
1438     const bool m_useCentroid; // Use Centroid interpolation decoration.
1439     const bool m_useEnable;
1440 };
1441 
BuiltinFragCoordMsaaTestCase(TestContext & testCtx,const char * name,VkSampleCountFlagBits sampleCount,bool sampleShading,std::vector<uint32_t> sampleMaskArray,bool useCentroid,bool useEnable)1442 BuiltinFragCoordMsaaTestCase::BuiltinFragCoordMsaaTestCase(TestContext &testCtx, const char *name,
1443                                                            VkSampleCountFlagBits sampleCount, bool sampleShading,
1444                                                            std::vector<uint32_t> sampleMaskArray, bool useCentroid,
1445                                                            bool useEnable)
1446     : TestCase(testCtx, name)
1447     , m_sampleCount(sampleCount)
1448     , m_sampleShading(sampleShading)
1449     , m_sampleMaskArray(sampleMaskArray)
1450     , m_useCentroid(useCentroid)
1451     , m_useEnable(useEnable)
1452 {
1453 }
1454 
~BuiltinFragCoordMsaaTestCase(void)1455 BuiltinFragCoordMsaaTestCase::~BuiltinFragCoordMsaaTestCase(void)
1456 {
1457 }
1458 
initPrograms(SourceCollections & programCollection) const1459 void BuiltinFragCoordMsaaTestCase::initPrograms(SourceCollections &programCollection) const
1460 {
1461     {
1462         std::ostringstream vertexSource;
1463         vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1464                      << "\n"
1465                      << "layout (location = 0) in vec4 position;\n"
1466                      << "void main()\n"
1467                      << "{\n"
1468                      << "    gl_Position = position;\n"
1469                      << "}\n";
1470         programCollection.glslSources.add("FragCoordMsaaVert") << glu::VertexSource(vertexSource.str());
1471     }
1472 
1473     if (m_sampleShading == true)
1474     {
1475         std::ostringstream fragmentSource;
1476         fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1477                        << "\n"
1478                        << "layout(location = 0) out mediump vec4 color;\n"
1479                        << "layout (set = 0, binding = 0, rgba32f) writeonly uniform image2D storageImage;\n"
1480                        << "void main()\n"
1481                        << "{\n"
1482                        << "    const int sampleNdx = int(gl_SampleID);\n"
1483                        << "    ivec2 imageCoord = ivec2(sampleNdx + int(gl_FragCoord.x) * " << m_sampleCount
1484                        << ", int(gl_FragCoord.y));\n"
1485                        << "    imageStore(storageImage, imageCoord, gl_FragCoord);\n"
1486                        << "    color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1487                        << "}\n";
1488         programCollection.glslSources.add("FragCoordMsaaFrag") << glu::FragmentSource(fragmentSource.str());
1489     }
1490     else
1491     {
1492         if (m_useCentroid == false)
1493         {
1494             std::ostringstream src;
1495 
1496             src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1497                 << "\n"
1498                 << "layout (location = 0) out mediump vec4 color;\n"
1499                 << "layout (set = 0, binding = 0, rgba32f) writeonly uniform image2D storageImage;\n"
1500                 << "void main()\n"
1501                 << "{\n"
1502                 << "    ivec2 imageCoord = ivec2(int(gl_FragCoord.x), int(gl_FragCoord.y));\n"
1503                 << "    imageStore(storageImage, imageCoord, gl_FragCoord);\n"
1504                 << "    color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1505                 << "}\n";
1506 
1507             programCollection.glslSources.add("FragCoordMsaaFrag") << glu::FragmentSource(src.str());
1508         }
1509         else
1510         {
1511             // This SPIR-V shader is identical to GLSL shader above but with the exception of that added cendroid decoration line.
1512             std::ostringstream src;
1513             src << "; SPIR - V\n"
1514                 << "; Version: 1.0\n"
1515                 << "; Generator: Khronos Glslang Reference Front End; 10\n"
1516                 << "; Bound: 36\n"
1517                 << "; Schema: 0\n"
1518                 << "OpCapability Shader\n"
1519                 << "%1 = OpExtInstImport \"GLSL.std.450\"\n"
1520                 << "OpMemoryModel Logical GLSL450\n"
1521                 << "OpEntryPoint Fragment %main \"main\" %gl_FragCoord %color\n"
1522                 << "OpExecutionMode %main OriginUpperLeft\n"
1523                 << "OpSource GLSL 450\n"
1524                 << "OpName %main \"main\"\n"
1525                 << "OpName %imageCoord \"imageCoord\"\n"
1526                 << "OpName %gl_FragCoord \"gl_FragCoord\"\n"
1527                 << "OpName %storageImage \"storageImage\"\n"
1528                 << "OpName %color \"color\"\n"
1529                 << "OpDecorate %gl_FragCoord BuiltIn FragCoord\n"
1530                 << "OpDecorate %gl_FragCoord Centroid\n"
1531                 << "OpDecorate %storageImage DescriptorSet 0\n"
1532                 << "OpDecorate %storageImage Binding 0\n"
1533                 << "OpDecorate %storageImage NonReadable\n"
1534                 << "OpDecorate %color RelaxedPrecision\n"
1535                 << "OpDecorate %color Location 0\n"
1536                 << "%void = OpTypeVoid\n"
1537                 << "%3 = OpTypeFunction %void\n"
1538                 << "%int = OpTypeInt 32 1\n"
1539                 << "%v2int = OpTypeVector %int 2\n"
1540                 << "%_ptr_Function_v2int = OpTypePointer Function %v2int\n"
1541                 << "%float = OpTypeFloat 32\n"
1542                 << "%v4float = OpTypeVector %float 4\n"
1543                 << "%_ptr_Input_v4float = OpTypePointer Input %v4float\n"
1544                 << "%gl_FragCoord = OpVariable %_ptr_Input_v4float Input\n"
1545                 << "%uint = OpTypeInt 32 0\n"
1546                 << "%uint_0 = OpConstant %uint 0\n"
1547                 << "%_ptr_Input_float = OpTypePointer Input %float\n"
1548                 << "%uint_1 = OpConstant %uint 1\n"
1549                 << "%25 = OpTypeImage %float 2D 0 0 0 2 Rgba32f\n"
1550                 << "%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25\n"
1551                 << "%storageImage = OpVariable %_ptr_UniformConstant_25 UniformConstant\n"
1552                 << "%_ptr_Output_v4float = OpTypePointer Output %v4float\n"
1553                 << "%color = OpVariable %_ptr_Output_v4float Output\n"
1554                 << "%float_1 = OpConstant %float 1\n"
1555                 << "%float_0 = OpConstant %float 0\n"
1556                 << "%35 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1\n"
1557                 << "%main = OpFunction %void None %3\n"
1558                 << "%5 = OpLabel\n"
1559                 << "%imageCoord = OpVariable %_ptr_Function_v2int Function\n"
1560                 << "%17 = OpAccessChain %_ptr_Input_float %gl_FragCoord %uint_0\n"
1561                 << "%18 = OpLoad %float %17\n"
1562                 << "%19 = OpConvertFToS %int %18\n"
1563                 << "%21 = OpAccessChain %_ptr_Input_float %gl_FragCoord %uint_1\n"
1564                 << "%22 = OpLoad %float %21\n"
1565                 << "%23 = OpConvertFToS %int %22\n"
1566                 << "%24 = OpCompositeConstruct %v2int %19 %23\n"
1567                 << "OpStore %imageCoord %24\n"
1568                 << "%28 = OpLoad %25 %storageImage\n"
1569                 << "%29 = OpLoad %v2int %imageCoord\n"
1570                 << "%30 = OpLoad %v4float %gl_FragCoord\n"
1571                 << "OpImageWrite %28 %29 %30\n"
1572                 << "OpStore %color %35\n"
1573                 << "OpReturn\n"
1574                 << "OpFunctionEnd\n";
1575 
1576             programCollection.spirvAsmSources.add("FragCoordMsaaFrag") << src.str();
1577         }
1578     }
1579 }
1580 
createInstance(Context & context) const1581 TestInstance *BuiltinFragCoordMsaaTestCase::createInstance(Context &context) const
1582 {
1583     return new BuiltinFragCoordMsaaCaseInstance(context, m_sampleCount, m_sampleShading, m_sampleMaskArray,
1584                                                 m_useEnable);
1585 }
1586 
1587 class BuiltinFragDepthCase : public TestCase
1588 {
1589 public:
1590     BuiltinFragDepthCase(TestContext &testCtx, const char *name, VkPrimitiveTopology topology, VkFormat format,
1591                          bool largeDepthEnable, bool depthClampEnable, const VkSampleCountFlagBits samples);
1592     virtual ~BuiltinFragDepthCase(void);
1593 
1594     void initPrograms(SourceCollections &dst) const;
1595     TestInstance *createInstance(Context &context) const;
1596 
1597 private:
1598     const VkPrimitiveTopology m_topology;
1599     const VkFormat m_format;
1600     const bool m_largeDepthEnable;
1601     const float m_defaultDepth;
1602     const bool m_depthClampEnable;
1603     const VkSampleCountFlagBits m_samples;
1604 };
1605 
BuiltinFragDepthCase(TestContext & testCtx,const char * name,VkPrimitiveTopology topology,VkFormat format,bool largeDepthEnable,bool depthClampEnable,const VkSampleCountFlagBits samples)1606 BuiltinFragDepthCase::BuiltinFragDepthCase(TestContext &testCtx, const char *name, VkPrimitiveTopology topology,
1607                                            VkFormat format, bool largeDepthEnable, bool depthClampEnable,
1608                                            const VkSampleCountFlagBits samples)
1609     : TestCase(testCtx, name)
1610     , m_topology(topology)
1611     , m_format(format)
1612     , m_largeDepthEnable(largeDepthEnable)
1613     , m_defaultDepth(0.0f)
1614     , m_depthClampEnable(depthClampEnable)
1615     , m_samples(samples)
1616 {
1617 }
1618 
~BuiltinFragDepthCase(void)1619 BuiltinFragDepthCase::~BuiltinFragDepthCase(void)
1620 {
1621 }
1622 
initPrograms(SourceCollections & programCollection) const1623 void BuiltinFragDepthCase::initPrograms(SourceCollections &programCollection) const
1624 {
1625     // Vertex
1626     {// Pass 1
1627      {std::ostringstream vertexSource;
1628     vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1629                  << "\n"
1630                  << "layout (location = 0) in vec4 position;\n"
1631                  << "void main()\n"
1632                  << "{\n"
1633                  << "    gl_Position = position;\n"
1634                  << "    gl_PointSize = 1.0;\n"
1635                  << "}\n";
1636     programCollection.glslSources.add("FragDepthVert") << glu::VertexSource(vertexSource.str());
1637 }
1638 
1639 // Pass 2
1640 {
1641     std::ostringstream vertexSource;
1642     vertexSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1643                  << "\n"
1644                  << "layout (location = 0) in vec4 position;\n"
1645                  << "layout (location = 1) out vec2 texCoord;\n"
1646                  << "void main()\n"
1647                  << "{\n"
1648                  << "    gl_Position = position;\n"
1649                  << "    gl_PointSize = 1.0;\n"
1650                  << "    texCoord = position.xy/2 + vec2(0.5);\n"
1651                  << "}\n";
1652     programCollection.glslSources.add("FragDepthVertPass2") << glu::VertexSource(vertexSource.str());
1653 }
1654 } // namespace
1655 
1656 // Fragment
1657 {
1658     // Pass 1
1659     {
1660         std::ostringstream fragmentSource;
1661         fragmentSource << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1662                        << "\n"
1663                        << "layout(location = 0) out mediump vec4 color;\n"
1664                        << "layout (std140, set = 0, binding = 0) uniform control_buffer_t\n"
1665                        << "{\n"
1666                        << "    float data[256];\n"
1667                        << "} control_buffer;\n"
1668                        << "layout (set = 0, binding = 1, rgba8ui) writeonly uniform uimage2D storageImage;\n"
1669                        << "float controlDepthValue;\n"
1670                        << "void recheck(float controlDepthValue)\n"
1671                        << "{\n"
1672                        << "    if (gl_FragDepth != controlDepthValue)\n"
1673                        << "        gl_FragDepth = 1.0;\n"
1674                        << "}\n"
1675                        << "void main()\n"
1676                        << "{\n"
1677                        << "    const int numSamples = " << m_samples << ";\n"
1678                        << "    if (int(gl_FragCoord.x) == " << BuiltinFragDepthCaseInstance::RENDERWIDTH / 4 << ")\n"
1679                        << "        discard;\n"
1680                        << "    highp int index =int(gl_FragCoord.y) * " << BuiltinFragDepthCaseInstance::RENDERHEIGHT
1681                        << " + int(gl_FragCoord.x);\n"
1682                        << "    controlDepthValue = control_buffer.data[index];\n"
1683                        << "    gl_FragDepth = controlDepthValue;\n"
1684                        << "    const int sampleNdx = int(gl_SampleID);\n"
1685                        << "    ivec2 imageCoord = ivec2(sampleNdx + int(gl_FragCoord.x) * " << m_samples
1686                        << ", int(gl_FragCoord.y));\n"
1687                        << "    imageStore(storageImage, imageCoord, uvec4(1));\n"
1688                        << "    recheck(controlDepthValue);\n"
1689                        << "    color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1690                        << "}\n";
1691         programCollection.glslSources.add("FragDepthFrag") << glu::FragmentSource(fragmentSource.str());
1692     }
1693 
1694     // Pass 2
1695     {
1696         const char *multisampleDecoration = m_samples != VK_SAMPLE_COUNT_1_BIT ? "MS" : "";
1697         std::ostringstream fragmentSource;
1698         fragmentSource
1699             << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1700             << "\n"
1701             << "layout (location = 0) out mediump vec4 color;\n"
1702             << "layout (location = 1) in vec2 texCoord;\n"
1703             << "layout (binding = 0, set = 0) uniform sampler2D" << multisampleDecoration << " u_depthTex;\n"
1704             << "layout (binding = 1, set = 0, r32f) writeonly uniform image2D u_outImage;\n"
1705             << "void main (void)\n"
1706             << "{\n"
1707             << "    const int numSamples = " << m_samples << ";\n"
1708             << "    const int sampleNdx = int(gl_SampleID);\n"
1709             << "    ivec2 renderSize = ivec2(" << BuiltinFragDepthCaseInstance::RENDERWIDTH << ","
1710             << BuiltinFragDepthCaseInstance::RENDERHEIGHT << ");\n"
1711             << "    ivec2 imageCoord = ivec2(int(texCoord.x * renderSize.x), int(texCoord.y * renderSize.y));\n"
1712             << "    vec4 depthVal = texelFetch(u_depthTex, imageCoord, sampleNdx);\n"
1713             << "    imageStore(u_outImage, ivec2(sampleNdx + int(texCoord.x * renderSize.x) * numSamples, "
1714                "int(texCoord.y * renderSize.y)), depthVal);\n"
1715             << "    color = vec4(1.0, 0.0, 0.0, 1.0);\n"
1716             << "}\n";
1717         programCollection.glslSources.add("FragDepthFragPass2") << glu::FragmentSource(fragmentSource.str());
1718     }
1719 }
1720 } // namespace sr
1721 
createInstance(Context & context) const1722 TestInstance *BuiltinFragDepthCase::createInstance(Context &context) const
1723 {
1724     return new BuiltinFragDepthCaseInstance(context, m_topology, m_format, m_largeDepthEnable, m_defaultDepth,
1725                                             m_depthClampEnable, m_samples);
1726 }
1727 
1728 class BuiltinGlFragCoordXYZCaseInstance : public ShaderRenderCaseInstance
1729 {
1730 public:
1731     BuiltinGlFragCoordXYZCaseInstance(Context &context);
1732 
1733     TestStatus iterate(void);
1734     virtual void setupDefaultInputs(void);
1735 };
1736 
BuiltinGlFragCoordXYZCaseInstance(Context & context)1737 BuiltinGlFragCoordXYZCaseInstance::BuiltinGlFragCoordXYZCaseInstance(Context &context)
1738     : ShaderRenderCaseInstance(context)
1739 {
1740     m_colorFormat = VK_FORMAT_R16G16B16A16_UNORM;
1741 }
1742 
iterate(void)1743 TestStatus BuiltinGlFragCoordXYZCaseInstance::iterate(void)
1744 {
1745     const UVec2 viewportSize = getViewportSize();
1746     const int width          = viewportSize.x();
1747     const int height         = viewportSize.y();
1748     const tcu::Vec3 scale(1.0f / float(width), 1.0f / float(height), 1.0f);
1749     const float precision     = 0.00001f;
1750     const uint16_t indices[6] = {
1751         2, 1, 3, 0, 1, 2,
1752     };
1753 
1754     setup();
1755     addUniform(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, scale);
1756 
1757     render(4, 2, indices);
1758 
1759     // Reference image
1760     for (int y = 0; y < height; y++)
1761     {
1762         for (int x = 0; x < width; x++)
1763         {
1764             const float xf = (float(x) + .5f) / float(width);
1765             const float yf = (float(height - y - 1) + .5f) / float(height);
1766             const float z  = (xf + yf) / 2.0f;
1767             const Vec3 fragCoord(float(x) + .5f, float(y) + .5f, z);
1768             const Vec3 scaledFC = fragCoord * scale;
1769             const Vec4 color(scaledFC.x(), scaledFC.y(), scaledFC.z(), 1.0f);
1770             const Vec4 resultColor = getResultImage().getAccess().getPixel(x, y);
1771 
1772             if (de::abs(color.x() - resultColor.x()) > precision || de::abs(color.y() - resultColor.y()) > precision ||
1773                 de::abs(color.z() - resultColor.z()) > precision)
1774                 return TestStatus::fail("Image mismatch");
1775         }
1776     }
1777 
1778     return TestStatus::pass("Result image matches reference");
1779 }
1780 
setupDefaultInputs(void)1781 void BuiltinGlFragCoordXYZCaseInstance::setupDefaultInputs(void)
1782 {
1783     const float vertices[] = {
1784         -1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.5f, 1.0f, 1.0f, 1.0f, 0.5f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
1785     };
1786 
1787     addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, uint32_t(sizeof(float) * 4), 4, vertices);
1788 }
1789 
1790 class BuiltinGlFragCoordXYZCase : public TestCase
1791 {
1792 public:
1793     BuiltinGlFragCoordXYZCase(TestContext &testCtx, const string &name);
1794     virtual ~BuiltinGlFragCoordXYZCase(void);
1795 
1796     void initPrograms(SourceCollections &dst) const;
1797     TestInstance *createInstance(Context &context) const;
1798 
1799 private:
1800     BuiltinGlFragCoordXYZCase(const BuiltinGlFragCoordXYZCase &);            // not allowed!
1801     BuiltinGlFragCoordXYZCase &operator=(const BuiltinGlFragCoordXYZCase &); // not allowed!
1802 };
1803 
BuiltinGlFragCoordXYZCase(TestContext & testCtx,const string & name)1804 BuiltinGlFragCoordXYZCase::BuiltinGlFragCoordXYZCase(TestContext &testCtx, const string &name) : TestCase(testCtx, name)
1805 {
1806 }
1807 
~BuiltinGlFragCoordXYZCase(void)1808 BuiltinGlFragCoordXYZCase::~BuiltinGlFragCoordXYZCase(void)
1809 {
1810 }
1811 
initPrograms(SourceCollections & dst) const1812 void BuiltinGlFragCoordXYZCase::initPrograms(SourceCollections &dst) const
1813 {
1814     dst.glslSources.add("vert") << glu::VertexSource("#version 310 es\n"
1815                                                      "layout(location = 0) in highp vec4 a_position;\n"
1816                                                      "void main (void)\n"
1817                                                      "{\n"
1818                                                      "       gl_Position = a_position;\n"
1819                                                      "}\n");
1820 
1821     dst.glslSources.add("frag") << glu::FragmentSource(
1822         "#version 310 es\n"
1823         "layout(set=0, binding=0) uniform Scale { highp vec3 u_scale; };\n"
1824         "layout(location = 0) out highp vec4 o_color;\n"
1825         "void main (void)\n"
1826         "{\n"
1827         "       o_color = vec4(gl_FragCoord.xyz * u_scale, 1.0);\n"
1828         "}\n");
1829 }
1830 
createInstance(Context & context) const1831 TestInstance *BuiltinGlFragCoordXYZCase::createInstance(Context &context) const
1832 {
1833     return new BuiltinGlFragCoordXYZCaseInstance(context);
1834 }
1835 
projectedTriInterpolate(const Vec3 & s,const Vec3 & w,float nx,float ny)1836 inline float projectedTriInterpolate(const Vec3 &s, const Vec3 &w, float nx, float ny)
1837 {
1838     return (s[0] * (1.0f - nx - ny) / w[0] + s[1] * ny / w[1] + s[2] * nx / w[2]) /
1839            ((1.0f - nx - ny) / w[0] + ny / w[1] + nx / w[2]);
1840 }
1841 
1842 class BuiltinGlFragCoordWCaseInstance : public ShaderRenderCaseInstance
1843 {
1844 public:
1845     BuiltinGlFragCoordWCaseInstance(Context &context);
1846 
1847     TestStatus iterate(void);
1848     virtual void setupDefaultInputs(void);
1849 
1850 private:
1851     const Vec4 m_w;
1852 };
1853 
BuiltinGlFragCoordWCaseInstance(Context & context)1854 BuiltinGlFragCoordWCaseInstance::BuiltinGlFragCoordWCaseInstance(Context &context)
1855     : ShaderRenderCaseInstance(context)
1856     , m_w(1.7f, 2.0f, 1.2f, 1.0f)
1857 {
1858     m_colorFormat = VK_FORMAT_R16G16B16A16_UNORM;
1859 }
1860 
iterate(void)1861 TestStatus BuiltinGlFragCoordWCaseInstance::iterate(void)
1862 {
1863     const UVec2 viewportSize  = getViewportSize();
1864     const int width           = viewportSize.x();
1865     const int height          = viewportSize.y();
1866     const float precision     = 0.00001f;
1867     const uint16_t indices[6] = {
1868         2, 1, 3, 0, 1, 2,
1869     };
1870 
1871     setup();
1872     render(4, 2, indices);
1873 
1874     // Reference image
1875     for (int y = 0; y < height; y++)
1876     {
1877         for (int x = 0; x < width; x++)
1878         {
1879             const float xf = (float(x) + .5f) / float(width);
1880             const float yf = (float(height - y - 1) + .5f) / float(height);
1881             const float oow =
1882                 ((xf + yf) < 1.0f) ?
1883                     projectedTriInterpolate(Vec3(m_w[0], m_w[1], m_w[2]), Vec3(m_w[0], m_w[1], m_w[2]), xf, yf) :
1884                     projectedTriInterpolate(Vec3(m_w[3], m_w[2], m_w[1]), Vec3(m_w[3], m_w[2], m_w[1]), 1.0f - xf,
1885                                             1.0f - yf);
1886             const Vec4 color(0.0f, oow - 1.0f, 0.0f, 1.0f);
1887             const Vec4 resultColor = getResultImage().getAccess().getPixel(x, y);
1888 
1889             if (de::abs(color.x() - resultColor.x()) > precision || de::abs(color.y() - resultColor.y()) > precision ||
1890                 de::abs(color.z() - resultColor.z()) > precision)
1891                 return TestStatus::fail("Image mismatch");
1892         }
1893     }
1894 
1895     return TestStatus::pass("Result image matches reference");
1896 }
1897 
setupDefaultInputs(void)1898 void BuiltinGlFragCoordWCaseInstance::setupDefaultInputs(void)
1899 {
1900     const float vertices[] = {-m_w[0], m_w[0], 0.0f, m_w[0], -m_w[1], -m_w[1], 0.0f, m_w[1],
1901                               m_w[2],  m_w[2], 0.0f, m_w[2], m_w[3],  -m_w[3], 0.0f, m_w[3]};
1902 
1903     addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, uint32_t(sizeof(float) * 4), 4, vertices);
1904 }
1905 
1906 class BuiltinGlFragCoordWCase : public TestCase
1907 {
1908 public:
1909     BuiltinGlFragCoordWCase(TestContext &testCtx, const string &name);
1910     virtual ~BuiltinGlFragCoordWCase(void);
1911 
1912     void initPrograms(SourceCollections &dst) const;
1913     TestInstance *createInstance(Context &context) const;
1914 
1915 private:
1916     BuiltinGlFragCoordWCase(const BuiltinGlFragCoordWCase &);            // not allowed!
1917     BuiltinGlFragCoordWCase &operator=(const BuiltinGlFragCoordWCase &); // not allowed!
1918 };
1919 
BuiltinGlFragCoordWCase(TestContext & testCtx,const string & name)1920 BuiltinGlFragCoordWCase::BuiltinGlFragCoordWCase(TestContext &testCtx, const string &name) : TestCase(testCtx, name)
1921 {
1922 }
1923 
~BuiltinGlFragCoordWCase(void)1924 BuiltinGlFragCoordWCase::~BuiltinGlFragCoordWCase(void)
1925 {
1926 }
1927 
initPrograms(SourceCollections & dst) const1928 void BuiltinGlFragCoordWCase::initPrograms(SourceCollections &dst) const
1929 {
1930     dst.glslSources.add("vert") << glu::VertexSource("#version 310 es\n"
1931                                                      "layout(location = 0) in highp vec4 a_position;\n"
1932                                                      "void main (void)\n"
1933                                                      "{\n"
1934                                                      "       gl_Position = a_position;\n"
1935                                                      "}\n");
1936 
1937     dst.glslSources.add("frag") << glu::FragmentSource(
1938         "#version 310 es\n"
1939         "layout(location = 0) out highp vec4 o_color;\n"
1940         "void main (void)\n"
1941         "{\n"
1942         "       o_color = vec4(0.0, 1.0 / gl_FragCoord.w - 1.0, 0.0, 1.0);\n"
1943         "}\n");
1944 }
1945 
createInstance(Context & context) const1946 TestInstance *BuiltinGlFragCoordWCase::createInstance(Context &context) const
1947 {
1948     return new BuiltinGlFragCoordWCaseInstance(context);
1949 }
1950 
1951 enum
1952 {
1953     POINTCOORD_VARIANT_DEFAULT,
1954     POINTCOORD_VARIANT_UNIFORM_VERTEX,
1955     POINTCOORD_VARIANT_UNIFORM_FRAGMENT
1956 };
1957 
1958 class BuiltinGlPointCoordCaseInstance : public ShaderRenderCaseInstance
1959 {
1960 public:
1961     BuiltinGlPointCoordCaseInstance(Context &context, int testVariant);
1962 
1963     TestStatus iterate(void);
1964     virtual void setupDefaultInputs(void);
1965 
1966 private:
1967     int variant;
1968 };
1969 
BuiltinGlPointCoordCaseInstance(Context & context,int testVariant)1970 BuiltinGlPointCoordCaseInstance::BuiltinGlPointCoordCaseInstance(Context &context, int testVariant)
1971     : ShaderRenderCaseInstance(context)
1972     , variant(testVariant)
1973 {
1974 }
1975 
iterate(void)1976 TestStatus BuiltinGlPointCoordCaseInstance::iterate(void)
1977 {
1978     const UVec2 viewportSize = getViewportSize();
1979     const int width          = viewportSize.x();
1980     const int height         = viewportSize.y();
1981     const float threshold    = 0.02f;
1982     const int numPoints      = 16;
1983     vector<Vec3> coords(numPoints);
1984     de::Random rnd(0x145fa);
1985     Surface resImage(width, height);
1986     Surface refImage(width, height);
1987     bool compareOk = false;
1988     const tcu::Vec3 scale(1.0f / float(width), 1.0f / float(height), 1.0f);
1989 
1990     // Compute coordinates.
1991     {
1992         const VkPhysicalDeviceLimits &limits = m_context.getDeviceProperties().limits;
1993         const float minPointSize             = limits.pointSizeRange[0];
1994         const float maxPointSize             = limits.pointSizeRange[1];
1995         const int pointSizeDeltaMultiples =
1996             de::max(1, deCeilFloatToInt32((maxPointSize - minPointSize) / limits.pointSizeGranularity));
1997 
1998         TCU_CHECK(minPointSize <= maxPointSize);
1999 
2000         for (vector<Vec3>::iterator coord = coords.begin(); coord != coords.end(); ++coord)
2001         {
2002             coord->x() = rnd.getFloat(-0.9f, 0.9f);
2003             coord->y() = rnd.getFloat(-0.9f, 0.9f);
2004             coord->z() = de::min(maxPointSize, minPointSize + float(rnd.getInt(0, pointSizeDeltaMultiples)) *
2005                                                                   limits.pointSizeGranularity);
2006         }
2007     }
2008 
2009     setup();
2010 
2011     if (variant == POINTCOORD_VARIANT_UNIFORM_VERTEX || variant == POINTCOORD_VARIANT_UNIFORM_FRAGMENT)
2012         addUniform(0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, scale);
2013 
2014     addAttribute(0u, VK_FORMAT_R32G32B32_SFLOAT, uint32_t(sizeof(Vec3)), numPoints, &coords[0]);
2015     render(numPoints, 0, DE_NULL, VK_PRIMITIVE_TOPOLOGY_POINT_LIST);
2016     copy(resImage.getAccess(), getResultImage().getAccess());
2017 
2018     // Draw reference
2019     clear(refImage.getAccess(), m_clearColor);
2020 
2021     for (vector<Vec3>::const_iterator pointIter = coords.begin(); pointIter != coords.end(); ++pointIter)
2022     {
2023         float x = pointIter->x();
2024         float y = pointIter->y();
2025         if (variant == POINTCOORD_VARIANT_UNIFORM_VERTEX)
2026         {
2027             x *= scale.m_data[0];
2028             y *= scale.m_data[1];
2029         }
2030         const float centerX = float(width) * (x * 0.5f + 0.5f);
2031         const float centerY = float(height) * (y * 0.5f + 0.5f);
2032         const float size    = pointIter->z();
2033         const int x0        = deRoundFloatToInt32(centerX - size * 0.5f);
2034         const int y0        = deRoundFloatToInt32(centerY - size * 0.5f);
2035         const int x1        = deRoundFloatToInt32(centerX + size * 0.5f);
2036         const int y1        = deRoundFloatToInt32(centerY + size * 0.5f);
2037         const int w         = x1 - x0;
2038         const int h         = y1 - y0;
2039 
2040         for (int yo = 0; yo < h; yo++)
2041         {
2042             for (int xo = 0; xo < w; xo++)
2043             {
2044                 const int dx      = x0 + xo;
2045                 const int dy      = y0 + yo;
2046                 const float fragX = float(dx) + 0.5f;
2047                 const float fragY = float(dy) + 0.5f;
2048                 const float s     = 0.5f + (fragX - centerX) / size;
2049                 const float t     = 0.5f + (fragY - centerY) / size;
2050                 Vec4 color(s, t, 0.0f, 1.0f);
2051 
2052                 if (variant == POINTCOORD_VARIANT_UNIFORM_FRAGMENT)
2053                 {
2054                     color.m_data[0] *= scale.m_data[0];
2055                     color.m_data[1] *= scale.m_data[1];
2056                     color.m_data[2] *= scale.m_data[2];
2057                 }
2058 
2059                 if (de::inBounds(dx, 0, refImage.getWidth()) && de::inBounds(dy, 0, refImage.getHeight()))
2060                     refImage.setPixel(dx, dy, RGBA(color));
2061             }
2062         }
2063     }
2064 
2065     compareOk = fuzzyCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result", refImage,
2066                              resImage, threshold, COMPARE_LOG_RESULT);
2067 
2068     if (compareOk)
2069         return TestStatus::pass("Result image matches reference");
2070     else
2071         return TestStatus::fail("Image mismatch");
2072 }
2073 
setupDefaultInputs(void)2074 void BuiltinGlPointCoordCaseInstance::setupDefaultInputs(void)
2075 {
2076 }
2077 
2078 class BuiltinGlPointCoordCase : public TestCase
2079 {
2080 public:
2081     BuiltinGlPointCoordCase(TestContext &testCtx, const string &name, int testVariant);
2082     virtual ~BuiltinGlPointCoordCase(void);
2083 
2084     void initPrograms(SourceCollections &dst) const;
2085     TestInstance *createInstance(Context &context) const;
2086 
2087 private:
2088     int variant;
2089     BuiltinGlPointCoordCase(const BuiltinGlPointCoordCase &);            // not allowed!
2090     BuiltinGlPointCoordCase &operator=(const BuiltinGlPointCoordCase &); // not allowed!
2091 };
2092 
BuiltinGlPointCoordCase(TestContext & testCtx,const string & name,int testVariant)2093 BuiltinGlPointCoordCase::BuiltinGlPointCoordCase(TestContext &testCtx, const string &name, int testVariant)
2094     : TestCase(testCtx, name)
2095     , variant(testVariant)
2096 {
2097 }
2098 
~BuiltinGlPointCoordCase(void)2099 BuiltinGlPointCoordCase::~BuiltinGlPointCoordCase(void)
2100 {
2101 }
2102 
initPrograms(SourceCollections & dst) const2103 void BuiltinGlPointCoordCase::initPrograms(SourceCollections &dst) const
2104 {
2105     switch (variant)
2106     {
2107     case POINTCOORD_VARIANT_UNIFORM_FRAGMENT:
2108         dst.glslSources.add("vert") << glu::VertexSource("#version 310 es\n"
2109                                                          "layout(location = 0) in highp vec3 a_position;\n"
2110                                                          "void main (void)\n"
2111                                                          "{\n"
2112                                                          "    gl_Position = vec4(a_position.xy, 0.0, 1.0);\n"
2113                                                          "    gl_PointSize = a_position.z;\n"
2114                                                          "}\n");
2115 
2116         dst.glslSources.add("frag") << glu::FragmentSource(
2117             "#version 310 es\n"
2118             "layout(set=0, binding=0) uniform Scale { highp vec3 u_scale; };\n"
2119             "layout(location = 0) out lowp vec4 o_color;\n"
2120             "void main (void)\n"
2121             "{\n"
2122             "    o_color = vec4(gl_PointCoord, 0.0, 1.0) * vec4(u_scale, 1.0);\n"
2123             "}\n");
2124         break;
2125     case POINTCOORD_VARIANT_UNIFORM_VERTEX:
2126         dst.glslSources.add("vert") << glu::VertexSource(
2127             "#version 310 es\n"
2128             "layout(set=0, binding=0) uniform Scale { highp vec3 u_scale; };\n"
2129             "layout(location = 0) in highp vec3 a_position;\n"
2130             "void main (void)\n"
2131             "{\n"
2132             "    gl_Position = vec4(a_position.xy, 0.0, 1.0) * vec4(u_scale, 1.0);\n"
2133             "    gl_PointSize = a_position.z;\n"
2134             "}\n");
2135 
2136         dst.glslSources.add("frag") << glu::FragmentSource("#version 310 es\n"
2137                                                            "layout(location = 0) out lowp vec4 o_color;\n"
2138                                                            "void main (void)\n"
2139                                                            "{\n"
2140                                                            "    o_color = vec4(gl_PointCoord, 0.0, 1.0);\n"
2141                                                            "}\n");
2142         break;
2143     default: // POINTCOORD_VARIANT_DEFAULT
2144         dst.glslSources.add("vert") << glu::VertexSource("#version 310 es\n"
2145                                                          "layout(location = 0) in highp vec3 a_position;\n"
2146                                                          "void main (void)\n"
2147                                                          "{\n"
2148                                                          "    gl_Position = vec4(a_position.xy, 0.0, 1.0);\n"
2149                                                          "    gl_PointSize = a_position.z;\n"
2150                                                          "}\n");
2151 
2152         dst.glslSources.add("frag") << glu::FragmentSource("#version 310 es\n"
2153                                                            "layout(location = 0) out lowp vec4 o_color;\n"
2154                                                            "void main (void)\n"
2155                                                            "{\n"
2156                                                            "    o_color = vec4(gl_PointCoord, 0.0, 1.0);\n"
2157                                                            "}\n");
2158     }
2159 }
2160 
createInstance(Context & context) const2161 TestInstance *BuiltinGlPointCoordCase::createInstance(Context &context) const
2162 {
2163     return new BuiltinGlPointCoordCaseInstance(context, variant);
2164 }
2165 
2166 enum ShaderInputTypeBits
2167 {
2168     SHADER_INPUT_BUILTIN_BIT  = 0x01,
2169     SHADER_INPUT_VARYING_BIT  = 0x02,
2170     SHADER_INPUT_CONSTANT_BIT = 0x04
2171 };
2172 
2173 typedef uint16_t ShaderInputTypes;
2174 
shaderInputTypeToString(ShaderInputTypes type)2175 string shaderInputTypeToString(ShaderInputTypes type)
2176 {
2177     string typeString = "input";
2178 
2179     if (type == 0)
2180         return "input_none";
2181 
2182     if (type & SHADER_INPUT_BUILTIN_BIT)
2183         typeString += "_builtin";
2184 
2185     if (type & SHADER_INPUT_VARYING_BIT)
2186         typeString += "_varying";
2187 
2188     if (type & SHADER_INPUT_CONSTANT_BIT)
2189         typeString += "_constant";
2190 
2191     return typeString;
2192 }
2193 
2194 class BuiltinInputVariationsCaseInstance : public ShaderRenderCaseInstance
2195 {
2196 public:
2197     BuiltinInputVariationsCaseInstance(Context &context, const ShaderInputTypes shaderInputTypes);
2198 
2199     TestStatus iterate(void);
2200     virtual void setupDefaultInputs(void);
2201     virtual void updatePushConstants(vk::VkCommandBuffer commandBuffer, vk::VkPipelineLayout pipelineLayout);
2202 
2203 private:
2204     const ShaderInputTypes m_shaderInputTypes;
2205     const Vec4 m_constantColor;
2206 };
2207 
BuiltinInputVariationsCaseInstance(Context & context,const ShaderInputTypes shaderInputTypes)2208 BuiltinInputVariationsCaseInstance::BuiltinInputVariationsCaseInstance(Context &context,
2209                                                                        const ShaderInputTypes shaderInputTypes)
2210     : ShaderRenderCaseInstance(context)
2211     , m_shaderInputTypes(shaderInputTypes)
2212     , m_constantColor(0.1f, 0.05f, 0.2f, 0.0f)
2213 {
2214 }
2215 
iterate(void)2216 TestStatus BuiltinInputVariationsCaseInstance::iterate(void)
2217 {
2218     const UVec2 viewportSize = getViewportSize();
2219     const int width          = viewportSize.x();
2220     const int height         = viewportSize.y();
2221     const tcu::RGBA threshold(2, 2, 2, 2);
2222     Surface resImage(width, height);
2223     Surface refImage(width, height);
2224     bool compareOk                     = false;
2225     const VkPushConstantRange pcRanges = {
2226         VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
2227         0u,                           // uint32_t offset;
2228         sizeof(Vec4)                  // uint32_t size;
2229     };
2230     const uint16_t indices[12] = {0, 4, 1, 0, 5, 4, 1, 2, 3, 1, 3, 4};
2231 
2232     setup();
2233 
2234     if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
2235         setPushConstantRanges(1, &pcRanges);
2236 
2237     render(6, 4, indices);
2238     copy(resImage.getAccess(), getResultImage().getAccess());
2239 
2240     // Reference image
2241     for (int y = 0; y < refImage.getHeight(); y++)
2242     {
2243         for (int x = 0; x < refImage.getWidth(); x++)
2244         {
2245             Vec4 color(0.1f, 0.2f, 0.3f, 1.0f);
2246 
2247             if (((m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT) && (x < refImage.getWidth() / 2)) ||
2248                 !(m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT))
2249             {
2250                 if (m_shaderInputTypes & SHADER_INPUT_VARYING_BIT)
2251                 {
2252                     const float xf = (float(x) + .5f) / float(refImage.getWidth());
2253                     color += Vec4(0.6f * (1 - xf), 0.6f * xf, 0.0f, 0.0f);
2254                 }
2255                 else
2256                     color += Vec4(0.3f, 0.2f, 0.1f, 0.0f);
2257             }
2258 
2259             if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
2260                 color += m_constantColor;
2261 
2262             refImage.setPixel(x, y, RGBA(color));
2263         }
2264     }
2265 
2266     compareOk = pixelThresholdCompare(m_context.getTestContext().getLog(), "Result", "Image comparison result",
2267                                       refImage, resImage, threshold, COMPARE_LOG_RESULT);
2268 
2269     if (compareOk)
2270         return TestStatus::pass("Result image matches reference");
2271     else
2272         return TestStatus::fail("Image mismatch");
2273 }
2274 
setupDefaultInputs(void)2275 void BuiltinInputVariationsCaseInstance::setupDefaultInputs(void)
2276 {
2277     const float vertices[] = {-1.0f, -1.0f, 0.0f, 1.0f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f,  -1.0f, 0.0f, 1.0f,
2278                               1.0f,  1.0f,  0.0f, 1.0f, 0.0f, 1.0f,  0.0f, 1.0f, -1.0f, 1.0f,  0.0f, 1.0f};
2279 
2280     addAttribute(0u, VK_FORMAT_R32G32B32A32_SFLOAT, uint32_t(sizeof(float) * 4), 6, vertices);
2281 
2282     if (m_shaderInputTypes & SHADER_INPUT_VARYING_BIT)
2283     {
2284         const float colors[] = {0.6f, 0.0f, 0.0f, 1.0f, 0.3f, 0.3f, 0.0f, 1.0f, 0.0f, 0.6f, 0.0f, 1.0f,
2285                                 0.0f, 0.6f, 0.0f, 1.0f, 0.3f, 0.3f, 0.0f, 1.0f, 0.6f, 0.0f, 0.0f, 1.0f};
2286         addAttribute(1u, VK_FORMAT_R32G32B32A32_SFLOAT, uint32_t(sizeof(float) * 4), 6, colors);
2287     }
2288 }
2289 
updatePushConstants(vk::VkCommandBuffer commandBuffer,vk::VkPipelineLayout pipelineLayout)2290 void BuiltinInputVariationsCaseInstance::updatePushConstants(vk::VkCommandBuffer commandBuffer,
2291                                                              vk::VkPipelineLayout pipelineLayout)
2292 {
2293     if (m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT)
2294     {
2295         const DeviceInterface &vk = m_context.getDeviceInterface();
2296         vk.cmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(Vec4),
2297                             &m_constantColor);
2298     }
2299 }
2300 
2301 class BuiltinInputVariationsCase : public TestCase
2302 {
2303 public:
2304     BuiltinInputVariationsCase(TestContext &testCtx, const string &name, const ShaderInputTypes shaderInputTypes);
2305     virtual ~BuiltinInputVariationsCase(void);
2306 
2307     void initPrograms(SourceCollections &dst) const;
2308     TestInstance *createInstance(Context &context) const;
2309 
2310 private:
2311     BuiltinInputVariationsCase(const BuiltinInputVariationsCase &);            // not allowed!
2312     BuiltinInputVariationsCase &operator=(const BuiltinInputVariationsCase &); // not allowed!
2313     const ShaderInputTypes m_shaderInputTypes;
2314 };
2315 
BuiltinInputVariationsCase(TestContext & testCtx,const string & name,ShaderInputTypes shaderInputTypes)2316 BuiltinInputVariationsCase::BuiltinInputVariationsCase(TestContext &testCtx, const string &name,
2317                                                        ShaderInputTypes shaderInputTypes)
2318     : TestCase(testCtx, name)
2319     , m_shaderInputTypes(shaderInputTypes)
2320 {
2321 }
2322 
~BuiltinInputVariationsCase(void)2323 BuiltinInputVariationsCase::~BuiltinInputVariationsCase(void)
2324 {
2325 }
2326 
initPrograms(SourceCollections & dst) const2327 void BuiltinInputVariationsCase::initPrograms(SourceCollections &dst) const
2328 {
2329     map<string, string> vertexParams;
2330     map<string, string> fragmentParams;
2331     const tcu::StringTemplate vertexCodeTemplate("#version 450\n"
2332                                                  "layout(location = 0) in highp vec4 a_position;\n"
2333                                                  "out gl_PerVertex {\n"
2334                                                  "    vec4 gl_Position;\n"
2335                                                  "};\n"
2336                                                  "${VARYING_DECL}"
2337                                                  "void main (void)\n"
2338                                                  "{\n"
2339                                                  "    gl_Position = a_position;\n"
2340                                                  "    ${VARYING_USAGE}"
2341                                                  "}\n");
2342 
2343     const tcu::StringTemplate fragmentCodeTemplate("#version 450\n"
2344                                                    "${VARYING_DECL}"
2345                                                    "${CONSTANT_DECL}"
2346                                                    "layout(location = 0) out highp vec4 o_color;\n"
2347                                                    "void main (void)\n"
2348                                                    "{\n"
2349                                                    "    o_color = vec4(0.1, 0.2, 0.3, 1.0);\n"
2350                                                    "    ${BUILTIN_USAGE}"
2351                                                    "    ${VARYING_USAGE}"
2352                                                    "    ${CONSTANT_USAGE}"
2353                                                    "}\n");
2354 
2355     vertexParams["VARYING_DECL"] = m_shaderInputTypes & SHADER_INPUT_VARYING_BIT ?
2356                                        "layout(location = 1) in highp vec4 a_color;\n"
2357                                        "layout(location = 0) out highp vec4 v_color;\n" :
2358                                        "";
2359 
2360     vertexParams["VARYING_USAGE"] = m_shaderInputTypes & SHADER_INPUT_VARYING_BIT ? "v_color = a_color;\n" : "";
2361 
2362     fragmentParams["VARYING_DECL"] =
2363         m_shaderInputTypes & SHADER_INPUT_VARYING_BIT ? "layout(location = 0) in highp vec4 a_color;\n" : "";
2364 
2365     fragmentParams["CONSTANT_DECL"] = m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT ?
2366                                           "layout(push_constant) uniform PCBlock {\n"
2367                                           "  vec4 color;\n"
2368                                           "} pc;\n" :
2369                                           "";
2370 
2371     fragmentParams["BUILTIN_USAGE"] = m_shaderInputTypes & SHADER_INPUT_BUILTIN_BIT ? "if (gl_FrontFacing)\n" : "";
2372 
2373     fragmentParams["VARYING_USAGE"] = m_shaderInputTypes & SHADER_INPUT_VARYING_BIT ?
2374                                           "o_color += vec4(a_color.xyz, 0.0);\n" :
2375                                           "o_color += vec4(0.3, 0.2, 0.1, 0.0);\n";
2376 
2377     fragmentParams["CONSTANT_USAGE"] = m_shaderInputTypes & SHADER_INPUT_CONSTANT_BIT ? "o_color += pc.color;\n" : "";
2378 
2379     dst.glslSources.add("vert") << glu::VertexSource(vertexCodeTemplate.specialize(vertexParams));
2380     dst.glslSources.add("frag") << glu::FragmentSource(fragmentCodeTemplate.specialize(fragmentParams));
2381 }
2382 
createInstance(Context & context) const2383 TestInstance *BuiltinInputVariationsCase::createInstance(Context &context) const
2384 {
2385     return new BuiltinInputVariationsCaseInstance(context, m_shaderInputTypes);
2386 }
2387 
2388 } // namespace vkt
2389 
createBuiltinVarTests(TestContext & testCtx)2390 TestCaseGroup *createBuiltinVarTests(TestContext &testCtx)
2391 {
2392     de::MovePtr<TestCaseGroup> builtinGroup(new TestCaseGroup(testCtx, "builtin_var"));
2393     de::MovePtr<TestCaseGroup> simpleGroup(new TestCaseGroup(testCtx, "simple"));
2394     de::MovePtr<TestCaseGroup> inputVariationsGroup(new TestCaseGroup(testCtx, "input_variations"));
2395     de::MovePtr<TestCaseGroup> frontFacingGroup(new TestCaseGroup(testCtx, "frontfacing"));
2396     de::MovePtr<TestCaseGroup> fragDepthGroup(new TestCaseGroup(testCtx, "fragdepth"));
2397     de::MovePtr<TestCaseGroup> fragCoordMsaaGroup(new TestCaseGroup(testCtx, "fragcoord_msaa"));
2398     de::MovePtr<TestCaseGroup> fragCoordMsaaInputGroup(new TestCaseGroup(testCtx, "fragcoord_msaa_input"));
2399 
2400     // FragCoord xyz test
2401     simpleGroup->addChild(new BuiltinGlFragCoordXYZCase(testCtx, "fragcoord_xyz"));
2402     // FragCoord w test
2403     simpleGroup->addChild(new BuiltinGlFragCoordWCase(testCtx, "fragcoord_w"));
2404     // PointCoord test
2405     simpleGroup->addChild(new BuiltinGlPointCoordCase(testCtx, "pointcoord", POINTCOORD_VARIANT_DEFAULT));
2406     // PointCoord test with fragment uniform
2407     simpleGroup->addChild(
2408         new BuiltinGlPointCoordCase(testCtx, "pointcoord_uniform_frag", POINTCOORD_VARIANT_UNIFORM_FRAGMENT));
2409     // PointCoord test with vertex uniform
2410     simpleGroup->addChild(
2411         new BuiltinGlPointCoordCase(testCtx, "pointcoord_uniform_vert", POINTCOORD_VARIANT_UNIFORM_VERTEX));
2412 
2413     // FragCoord_msaa
2414     {
2415         static const struct FragCoordMsaaCaseList
2416         {
2417             const char *name;
2418             VkSampleCountFlagBits sampleCount;
2419         } fragCoordMsaaCaseList[] = {
2420             {"1_bit", VK_SAMPLE_COUNT_1_BIT},   {"2_bit", VK_SAMPLE_COUNT_2_BIT},   {"4_bit", VK_SAMPLE_COUNT_4_BIT},
2421             {"8_bit", VK_SAMPLE_COUNT_8_BIT},   {"16_bit", VK_SAMPLE_COUNT_16_BIT}, {"32_bit", VK_SAMPLE_COUNT_32_BIT},
2422             {"64_bit", VK_SAMPLE_COUNT_64_BIT},
2423         };
2424 
2425         // Standard sample tests
2426         std::vector<uint32_t> sampleMaskArray;
2427 
2428         for (uint32_t caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(fragCoordMsaaCaseList); caseNdx++)
2429         {
2430             fragCoordMsaaGroup->addChild(new BuiltinFragCoordMsaaTestCase(testCtx, fragCoordMsaaCaseList[caseNdx].name,
2431                                                                           fragCoordMsaaCaseList[caseNdx].sampleCount,
2432                                                                           true, sampleMaskArray, false, true));
2433             fragCoordMsaaInputGroup->addChild(new BuiltinFragCoordMsaaTestCase(
2434                 testCtx, fragCoordMsaaCaseList[caseNdx].name, fragCoordMsaaCaseList[caseNdx].sampleCount, true,
2435                 sampleMaskArray, false, false));
2436         }
2437 
2438         sampleMaskArray.push_back(1u);
2439 
2440         // No sample shading tests
2441         for (uint32_t caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(fragCoordMsaaCaseList); caseNdx++)
2442         {
2443             fragCoordMsaaInputGroup->addChild(new BuiltinFragCoordMsaaTestCase(
2444                 testCtx, (std::string(fragCoordMsaaCaseList[caseNdx].name) + "_no_sample_shading").c_str(),
2445                 fragCoordMsaaCaseList[caseNdx].sampleCount, false, sampleMaskArray, false, false));
2446         }
2447 
2448         // No sample shading tests with centroid interpolation decoration
2449         for (uint32_t caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(fragCoordMsaaCaseList); caseNdx++)
2450         {
2451             fragCoordMsaaInputGroup->addChild(new BuiltinFragCoordMsaaTestCase(
2452                 testCtx,
2453                 (std::string(fragCoordMsaaCaseList[caseNdx].name) + "_no_sample_shading_centroid_interpolation")
2454                     .c_str(),
2455                 fragCoordMsaaCaseList[caseNdx].sampleCount, false, sampleMaskArray, true, false));
2456         }
2457     }
2458 
2459     // gl_FrontFacing tests
2460     {
2461         static const struct PrimitiveTable
2462         {
2463             const char *name;
2464             VkPrimitiveTopology primitive;
2465         } frontfacingCases[] = {
2466             // Test that points are frontfacing
2467             {"point_list", VK_PRIMITIVE_TOPOLOGY_POINT_LIST},
2468             // Test that lines are frontfacing
2469             {"line_list", VK_PRIMITIVE_TOPOLOGY_LINE_LIST},
2470             // Test that triangles can be frontfacing or backfacing
2471             {"triangle_list", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST},
2472             // Test that traiangle strips can be front or back facing
2473             {"triangle_strip", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP},
2474             // Test that triangle fans can be front or back facing
2475             {"triangle_fan", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN},
2476         };
2477 
2478         for (uint32_t ndx = 0; ndx < DE_LENGTH_OF_ARRAY(frontfacingCases); ndx++)
2479             frontFacingGroup->addChild(
2480                 new BuiltinGlFrontFacingCase(testCtx, frontfacingCases[ndx].primitive, frontfacingCases[ndx].name));
2481     }
2482 
2483     // gl_FragDepth
2484     {
2485         static const struct PrimitiveTopologyTable
2486         {
2487             std::string name;
2488             VkPrimitiveTopology prim;
2489         } primitiveTopologyTable[] = {
2490             // test that points respect gl_fragdepth
2491             {"point_list", VK_PRIMITIVE_TOPOLOGY_POINT_LIST},
2492             // test taht lines respect gl_fragdepth
2493             {"line_list", VK_PRIMITIVE_TOPOLOGY_LINE_LIST},
2494             // test that triangles respect gl_fragdepth
2495             {"triangle_list", VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP},
2496         };
2497 
2498         static const struct TestCaseTable
2499         {
2500             VkFormat format;
2501             std::string name;
2502             bool largeDepthEnable;
2503             bool depthClampEnable;
2504             VkSampleCountFlagBits samples;
2505         } testCaseTable[] = {
2506             {VK_FORMAT_D16_UNORM, "d16_unorm_no_depth_clamp", false, false, VK_SAMPLE_COUNT_1_BIT},
2507             {VK_FORMAT_X8_D24_UNORM_PACK32, "x8_d24_unorm_pack32_no_depth_clamp", false, false, VK_SAMPLE_COUNT_1_BIT},
2508             {VK_FORMAT_D32_SFLOAT, "d32_sfloat_no_depth_clamp", false, false, VK_SAMPLE_COUNT_1_BIT},
2509             {VK_FORMAT_D16_UNORM_S8_UINT, "d16_unorm_s8_uint_no_depth_clamp", false, false, VK_SAMPLE_COUNT_1_BIT},
2510             {VK_FORMAT_D24_UNORM_S8_UINT, "d24_unorm_s8_uint_no_depth_clamp", false, false, VK_SAMPLE_COUNT_1_BIT},
2511             {VK_FORMAT_D32_SFLOAT_S8_UINT, "d32_sfloat_s8_uint_no_depth_clamp", false, false, VK_SAMPLE_COUNT_1_BIT},
2512             {VK_FORMAT_D32_SFLOAT, "d32_sfloat_large_depth", true, false, VK_SAMPLE_COUNT_1_BIT},
2513             {VK_FORMAT_D32_SFLOAT, "d32_sfloat", false, true, VK_SAMPLE_COUNT_1_BIT},
2514             {VK_FORMAT_D32_SFLOAT_S8_UINT, "d32_sfloat_s8_uint", false, true, VK_SAMPLE_COUNT_1_BIT},
2515             {VK_FORMAT_D32_SFLOAT, "d32_sfloat_multisample_2", false, false, VK_SAMPLE_COUNT_2_BIT},
2516             {VK_FORMAT_D32_SFLOAT, "d32_sfloat_multisample_4", false, false, VK_SAMPLE_COUNT_4_BIT},
2517             {VK_FORMAT_D32_SFLOAT, "d32_sfloat_multisample_8", false, false, VK_SAMPLE_COUNT_8_BIT},
2518             {VK_FORMAT_D32_SFLOAT, "d32_sfloat_multisample_16", false, false, VK_SAMPLE_COUNT_16_BIT},
2519             {VK_FORMAT_D32_SFLOAT, "d32_sfloat_multisample_32", false, false, VK_SAMPLE_COUNT_32_BIT},
2520             {VK_FORMAT_D32_SFLOAT, "d32_sfloat_multisample_64", false, false, VK_SAMPLE_COUNT_64_BIT},
2521         };
2522 
2523         for (uint32_t primNdx = 0; primNdx < DE_LENGTH_OF_ARRAY(primitiveTopologyTable); primNdx++)
2524         {
2525             for (uint32_t caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(testCaseTable); caseNdx++)
2526                 fragDepthGroup->addChild(new BuiltinFragDepthCase(
2527                     testCtx, (primitiveTopologyTable[primNdx].name + "_" + testCaseTable[caseNdx].name).c_str(),
2528                     primitiveTopologyTable[primNdx].prim, testCaseTable[caseNdx].format,
2529                     testCaseTable[caseNdx].largeDepthEnable, testCaseTable[caseNdx].depthClampEnable,
2530                     testCaseTable[caseNdx].samples));
2531         }
2532     }
2533 
2534     builtinGroup->addChild(frontFacingGroup.release());
2535     builtinGroup->addChild(fragDepthGroup.release());
2536     builtinGroup->addChild(fragCoordMsaaGroup.release());
2537     builtinGroup->addChild(fragCoordMsaaInputGroup.release());
2538     builtinGroup->addChild(simpleGroup.release());
2539 
2540     for (uint16_t shaderType = 0;
2541          shaderType <= (SHADER_INPUT_BUILTIN_BIT | SHADER_INPUT_VARYING_BIT | SHADER_INPUT_CONSTANT_BIT); ++shaderType)
2542     {
2543         inputVariationsGroup->addChild(
2544             new BuiltinInputVariationsCase(testCtx, shaderInputTypeToString(shaderType), shaderType));
2545     }
2546 
2547     builtinGroup->addChild(inputVariationsGroup.release());
2548     return builtinGroup.release();
2549 }
2550 
2551 } // sr
2552 } // vkt
2553