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