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