1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 * Copyright (c) 2015 The Khronos Group Inc.
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Early fragment tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktFragmentOperationsEarlyFragmentTests.hpp"
26 #include "vktFragmentOperationsMakeUtil.hpp"
27 #include "vktTestCaseUtil.hpp"
28
29 #include "vkDefs.hpp"
30 #include "vkRef.hpp"
31 #include "vkRefUtil.hpp"
32 #include "vkPlatform.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkMemUtil.hpp"
35 #include "vkBuilderUtil.hpp"
36 #include "vkStrUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "vkImageUtil.hpp"
40 #include "vkBarrierUtil.hpp"
41 #include "vkCmdUtil.hpp"
42 #include "vkObjUtil.hpp"
43
44 #include "tcuTestLog.hpp"
45 #include "tcuImageCompare.hpp"
46 #include "tcuTextureUtil.hpp"
47
48 #include "deUniquePtr.hpp"
49 #include "deStringUtil.hpp"
50 #include "deMath.h"
51
52 #include <string>
53
54 namespace vkt
55 {
56 namespace FragmentOperations
57 {
58 namespace
59 {
60 using namespace vk;
61 using de::UniquePtr;
62
63 //! Basic 2D image.
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)64 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
65 {
66 const VkImageCreateInfo imageParams =
67 {
68 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
69 DE_NULL, // const void* pNext;
70 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
71 VK_IMAGE_TYPE_2D, // VkImageType imageType;
72 format, // VkFormat format;
73 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
74 1u, // deUint32 mipLevels;
75 1u, // deUint32 arrayLayers;
76 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
77 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
78 usage, // VkImageUsageFlags usage;
79 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
80 0u, // deUint32 queueFamilyIndexCount;
81 DE_NULL, // const deUint32* pQueueFamilyIndices;
82 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
83 };
84 return imageParams;
85 }
86
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const bool useDepthStencilAttachment,const VkFormat depthStencilFormat)87 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
88 const VkDevice device,
89 const VkFormat colorFormat,
90 const bool useDepthStencilAttachment,
91 const VkFormat depthStencilFormat)
92 {
93 return makeRenderPass(vk, device, colorFormat, useDepthStencilAttachment ? depthStencilFormat : VK_FORMAT_UNDEFINED);
94 }
95
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const tcu::IVec2 & renderSize,const bool enableDepthTest,const bool enableStencilTest,const VkStencilOp stencilFailOp=VK_STENCIL_OP_KEEP,const VkStencilOp stencilPassOp=VK_STENCIL_OP_KEEP)96 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
97 const VkDevice device,
98 const VkPipelineLayout pipelineLayout,
99 const VkRenderPass renderPass,
100 const VkShaderModule vertexModule,
101 const VkShaderModule fragmentModule,
102 const tcu::IVec2& renderSize,
103 const bool enableDepthTest,
104 const bool enableStencilTest,
105 const VkStencilOp stencilFailOp = VK_STENCIL_OP_KEEP,
106 const VkStencilOp stencilPassOp = VK_STENCIL_OP_KEEP)
107 {
108 const std::vector<VkViewport> viewports (1, makeViewport(renderSize));
109 const std::vector<VkRect2D> scissors (1, makeRect2D(renderSize));
110
111 const VkStencilOpState stencilOpState = makeStencilOpState(
112 stencilFailOp, // stencil fail
113 stencilPassOp, // depth & stencil pass
114 VK_STENCIL_OP_KEEP, // depth only fail
115 VK_COMPARE_OP_EQUAL, // compare op
116 0x3, // compare mask
117 0xf, // write mask
118 1u); // reference
119
120 VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
121 {
122 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
123 DE_NULL, // const void* pNext
124 0u, // VkPipelineDepthStencilStateCreateFlags flags
125 enableDepthTest ? VK_TRUE : VK_FALSE, // VkBool32 depthTestEnable
126 enableDepthTest ? VK_TRUE : VK_FALSE, // VkBool32 depthWriteEnable
127 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp
128 VK_FALSE, // VkBool32 depthBoundsTestEnable
129 enableStencilTest ? VK_TRUE : VK_FALSE, // VkBool32 stencilTestEnable
130 stencilOpState, // VkStencilOpState front
131 stencilOpState, // VkStencilOpState back
132 0.0f, // float minDepthBounds
133 1.0f // float maxDepthBounds
134 };
135
136 return vk::makeGraphicsPipeline(vk, // const DeviceInterface& vk
137 device, // const VkDevice device
138 pipelineLayout, // const VkPipelineLayout pipelineLayout
139 vertexModule, // const VkShaderModule vertexShaderModule
140 DE_NULL, // const VkShaderModule tessellationControlModule
141 DE_NULL, // const VkShaderModule tessellationEvalModule
142 DE_NULL, // const VkShaderModule geometryShaderModule
143 fragmentModule, // const VkShaderModule fragmentShaderModule
144 renderPass, // const VkRenderPass renderPass
145 viewports, // const std::vector<VkViewport>& viewports
146 scissors, // const std::vector<VkRect2D>& scissors
147 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
148 0u, // const deUint32 subpass
149 0u, // const deUint32 patchControlPoints
150 DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
151 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
152 DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
153 &depthStencilStateCreateInfo); // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
154 }
155
commandClearStencilAttachment(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkOffset2D & offset,const VkExtent2D & extent,const deUint32 clearValue)156 void commandClearStencilAttachment (const DeviceInterface& vk,
157 const VkCommandBuffer commandBuffer,
158 const VkOffset2D& offset,
159 const VkExtent2D& extent,
160 const deUint32 clearValue)
161 {
162 const VkClearAttachment stencilAttachment =
163 {
164 VK_IMAGE_ASPECT_STENCIL_BIT, // VkImageAspectFlags aspectMask;
165 0u, // uint32_t colorAttachment;
166 makeClearValueDepthStencil(0.0f, clearValue), // VkClearValue clearValue;
167 };
168
169 const VkClearRect rect =
170 {
171 { offset, extent }, // VkRect2D rect;
172 0u, // uint32_t baseArrayLayer;
173 1u, // uint32_t layerCount;
174 };
175
176 vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
177 }
178
getImageAspectFlags(const VkFormat format)179 VkImageAspectFlags getImageAspectFlags (const VkFormat format)
180 {
181 const tcu::TextureFormat tcuFormat = mapVkFormat(format);
182
183 if (tcuFormat.order == tcu::TextureFormat::DS) return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
184 else if (tcuFormat.order == tcu::TextureFormat::D) return VK_IMAGE_ASPECT_DEPTH_BIT;
185 else if (tcuFormat.order == tcu::TextureFormat::S) return VK_IMAGE_ASPECT_STENCIL_BIT;
186
187 DE_ASSERT(false);
188 return 0u;
189 }
190
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const VkFormat format)191 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format)
192 {
193 VkFormatProperties formatProps;
194 instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
195 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
196 }
197
pickSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const deUint32 numFormats,const VkFormat * pFormats)198 VkFormat pickSupportedDepthStencilFormat (const InstanceInterface& instanceInterface,
199 const VkPhysicalDevice device,
200 const deUint32 numFormats,
201 const VkFormat* pFormats)
202 {
203 for (deUint32 i = 0; i < numFormats; ++i)
204 if (isSupportedDepthStencilFormat(instanceInterface, device, pFormats[i]))
205 return pFormats[i];
206 return VK_FORMAT_UNDEFINED;
207 }
208
209 enum Flags
210 {
211 FLAG_TEST_DEPTH = 1u << 0,
212 FLAG_TEST_STENCIL = 1u << 1,
213 FLAG_DONT_USE_TEST_ATTACHMENT = 1u << 2,
214 FLAG_DONT_USE_EARLY_FRAGMENT_TESTS = 1u << 3,
215 };
216
217 class EarlyFragmentTest : public TestCase
218 {
219 public:
220 EarlyFragmentTest (tcu::TestContext& testCtx,
221 const std::string name,
222 const deUint32 flags);
223
224 void initPrograms (SourceCollections& programCollection) const;
225 TestInstance* createInstance (Context& context) const;
226 virtual void checkSupport (Context& context) const;
227
228 private:
229 const deUint32 m_flags;
230 };
231
EarlyFragmentTest(tcu::TestContext & testCtx,const std::string name,const deUint32 flags)232 EarlyFragmentTest::EarlyFragmentTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
233 : TestCase (testCtx, name, "")
234 , m_flags (flags)
235 {
236 }
237
initPrograms(SourceCollections & programCollection) const238 void EarlyFragmentTest::initPrograms (SourceCollections& programCollection) const
239 {
240 // Vertex
241 {
242 std::ostringstream src;
243 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
244 << "\n"
245 << "layout(location = 0) in highp vec4 position;\n"
246 << "\n"
247 << "out gl_PerVertex {\n"
248 << " vec4 gl_Position;\n"
249 << "};\n"
250 << "\n"
251 << "void main (void)\n"
252 << "{\n"
253 << " gl_Position = position;\n"
254 << "}\n";
255
256 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
257 }
258
259 // Fragment
260 {
261 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
262 std::ostringstream src;
263 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
264 << "\n"
265 << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
266 << "layout(location = 0) out highp vec4 fragColor;\n"
267 << "\n"
268 << "layout(binding = 0) coherent buffer Output {\n"
269 << " uint result;\n"
270 << "} sb_out;\n"
271 << "\n"
272 << "void main (void)\n"
273 << "{\n"
274 << " atomicAdd(sb_out.result, 1u);\n"
275 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
276 << "}\n";
277
278 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
279 }
280 }
281
282 class EarlyFragmentTestInstance : public TestInstance
283 {
284 public:
285 EarlyFragmentTestInstance (Context& context, const deUint32 flags);
286
287 tcu::TestStatus iterate (void);
288
289 private:
290 enum TestMode
291 {
292 MODE_INVALID,
293 MODE_DEPTH,
294 MODE_STENCIL,
295 };
296
297 const TestMode m_testMode;
298 const bool m_useTestAttachment;
299 const bool m_useEarlyTests;
300 };
301
EarlyFragmentTestInstance(Context & context,const deUint32 flags)302 EarlyFragmentTestInstance::EarlyFragmentTestInstance (Context& context, const deUint32 flags)
303 : TestInstance (context)
304 , m_testMode (flags & FLAG_TEST_DEPTH ? MODE_DEPTH :
305 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
306 , m_useTestAttachment ((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
307 , m_useEarlyTests ((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
308 {
309 DE_ASSERT(m_testMode != MODE_INVALID);
310 }
311
iterate(void)312 tcu::TestStatus EarlyFragmentTestInstance::iterate (void)
313 {
314 const DeviceInterface& vk = m_context.getDeviceInterface();
315 const InstanceInterface& vki = m_context.getInstanceInterface();
316 const VkDevice device = m_context.getDevice();
317 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
318 const VkQueue queue = m_context.getUniversalQueue();
319 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
320 Allocator& allocator = m_context.getDefaultAllocator();
321
322 // Color attachment
323
324 const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
325 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
326 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
327 const Unique<VkImage> colorImage (makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
328 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
329 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
330
331 // Test attachment (depth or stencil)
332 static const VkFormat stencilFormats[] =
333 {
334 // One of the following formats must be supported, as per spec requirement.
335 VK_FORMAT_S8_UINT,
336 VK_FORMAT_D16_UNORM_S8_UINT,
337 VK_FORMAT_D24_UNORM_S8_UINT,
338 VK_FORMAT_D32_SFLOAT_S8_UINT,
339 };
340
341 const VkFormat testFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
342 : VK_FORMAT_D16_UNORM); // spec requires this format to be supported
343 if (testFormat == VK_FORMAT_UNDEFINED)
344 return tcu::TestStatus::fail("Required depth/stencil format not supported");
345
346 if (m_useTestAttachment)
347 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage;
348
349 const VkImageSubresourceRange testSubresourceRange = makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
350 const Unique<VkImage> testImage (makeImage(vk, device, makeImageCreateInfo(renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
351 const UniquePtr<Allocation> testImageAlloc (bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
352 const Unique<VkImageView> testImageView (makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
353 const VkImageView attachmentImages[] = { *colorImageView, *testImageView };
354 const deUint32 numUsedAttachmentImages = (m_useTestAttachment ? 2u : 1u);
355
356 // Vertex buffer
357
358 const deUint32 numVertices = 6;
359 const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices;
360 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
361 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
362
363 {
364 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
365
366 pVertices[0] = tcu::Vec4( 1.0f, -1.0f, 0.5f, 1.0f);
367 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
368 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
369
370 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
371 pVertices[4] = tcu::Vec4( 1.0f, 1.0f, 1.0f, 1.0f);
372 pVertices[5] = tcu::Vec4( 1.0f, -1.0f, 0.5f, 1.0f);
373
374 flushAlloc(vk, device, *vertexBufferAlloc);
375 // No barrier needed, flushed memory is automatically visible
376 }
377
378 // Result buffer
379
380 const VkDeviceSize resultBufferSizeBytes = sizeof(deUint32);
381 const Unique<VkBuffer> resultBuffer (makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
382 const UniquePtr<Allocation> resultBufferAlloc (bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
383
384 {
385 deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
386
387 *pData = 0;
388 flushAlloc(vk, device, *resultBufferAlloc);
389 }
390
391 // Render result buffer (to retrieve color attachment contents)
392
393 const VkDeviceSize colorBufferSizeBytes = tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
394 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
395 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
396
397 // Descriptors
398
399 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
400 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
401 .build(vk, device));
402
403 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
404 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
405 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
406
407 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
408 const VkDescriptorBufferInfo resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
409
410 DescriptorSetUpdateBuilder()
411 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
412 .update(vk, device);
413
414 // Pipeline
415
416 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
417 const Unique<VkShaderModule> fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
418 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, testFormat));
419 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
420 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
421 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
422 (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL)));
423 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
424 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
425
426 // Draw commands
427
428 {
429 const VkRect2D renderArea = {
430 makeOffset2D(0, 0),
431 makeExtent2D(renderSize.x(), renderSize.y()),
432 };
433 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
434 const VkDeviceSize vertexBufferOffset = 0ull;
435
436 beginCommandBuffer(vk, *cmdBuffer);
437
438 {
439 const VkImageMemoryBarrier barriers[] = {
440 makeImageMemoryBarrier(
441 0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
442 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
443 *colorImage, colorSubresourceRange),
444 makeImageMemoryBarrier(
445 0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
446 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
447 *testImage, testSubresourceRange),
448 };
449
450 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
451 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
452 }
453
454 // Will clear the attachments with specified depth and stencil values.
455 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 0u);
456
457 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
458 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
459 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
460
461 // Mask half of the attachment image with value that will pass the stencil test.
462 if (m_useTestAttachment && m_testMode == MODE_STENCIL)
463 commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
464
465 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
466 endRenderPass(vk, *cmdBuffer);
467
468 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
469
470 endCommandBuffer(vk, *cmdBuffer);
471 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
472 }
473
474 // Log result image
475 {
476 invalidateAlloc(vk, device, *colorBufferAlloc);
477
478 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
479
480 tcu::TestLog& log = m_context.getTestContext().getLog();
481 log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
482 }
483
484 // Verify results
485 {
486 invalidateAlloc(vk, device, *resultBufferAlloc);
487
488 const int actualCounter = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
489 const bool expectPartialResult = (m_useEarlyTests && m_useTestAttachment);
490 const int expectedCounter = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
491 const int tolerance = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3 : 0;
492 const int expectedMin = de::max(0, expectedCounter - tolerance);
493 const int expectedMax = expectedCounter + tolerance;
494
495 tcu::TestLog& log = m_context.getTestContext().getLog();
496 log << tcu::TestLog::Message << "Expected value"
497 << (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
498 << tcu::TestLog::EndMessage;
499 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
500
501 if (expectedMin <= actualCounter && actualCounter <= expectedMax)
502 return tcu::TestStatus::pass("Success");
503 else
504 return tcu::TestStatus::fail("Value out of range");
505 }
506 }
507
createInstance(Context & context) const508 TestInstance* EarlyFragmentTest::createInstance (Context& context) const
509 {
510 return new EarlyFragmentTestInstance(context, m_flags);
511 }
512
checkSupport(Context & context) const513 void EarlyFragmentTest::checkSupport (Context& context) const
514 {
515 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
516 }
517
518 class EarlyFragmentDiscardTestInstance : public EarlyFragmentTestInstance
519 {
520 public:
521 EarlyFragmentDiscardTestInstance (Context& context, const deUint32 flags);
522
523 tcu::TestStatus iterate (void);
524
525 private:
526 tcu::TextureLevel generateReferenceColorImage (const tcu::TextureFormat format, const tcu::IVec2& renderSize);
527 enum TestMode
528 {
529 MODE_INVALID,
530 MODE_DEPTH,
531 MODE_STENCIL,
532 };
533
534 const TestMode m_testMode;
535 const bool m_useTestAttachment;
536 const bool m_useEarlyTests;
537 };
538
EarlyFragmentDiscardTestInstance(Context & context,const deUint32 flags)539 EarlyFragmentDiscardTestInstance::EarlyFragmentDiscardTestInstance (Context& context, const deUint32 flags)
540 : EarlyFragmentTestInstance (context, flags)
541 , m_testMode (flags & FLAG_TEST_DEPTH ? MODE_DEPTH :
542 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
543 , m_useTestAttachment ((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
544 , m_useEarlyTests ((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
545 {
546 DE_ASSERT(m_testMode != MODE_INVALID);
547 }
548
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)549 tcu::TextureLevel EarlyFragmentDiscardTestInstance::generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize)
550 {
551 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
552 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
553
554 tcu::clear(image.getAccess(), clearColor);
555
556 return image;
557 }
558
iterate(void)559 tcu::TestStatus EarlyFragmentDiscardTestInstance::iterate (void)
560 {
561 const DeviceInterface& vk = m_context.getDeviceInterface();
562 const InstanceInterface& vki = m_context.getInstanceInterface();
563 const VkDevice device = m_context.getDevice();
564 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
565 const VkQueue queue = m_context.getUniversalQueue();
566 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
567 Allocator& allocator = m_context.getDefaultAllocator();
568
569 DE_ASSERT(m_useTestAttachment);
570
571 // Color attachment
572 const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
573 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
574 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
575 const Unique<VkImage> colorImage (makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
576 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
577 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
578
579 // Test attachment (depth or stencil)
580 static const VkFormat stencilFormats[] =
581 {
582 // One of the following formats must be supported, as per spec requirement.
583 VK_FORMAT_S8_UINT,
584 VK_FORMAT_D16_UNORM_S8_UINT,
585 VK_FORMAT_D24_UNORM_S8_UINT,
586 VK_FORMAT_D32_SFLOAT_S8_UINT,
587 };
588
589 const VkFormat depthStencilFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
590 : VK_FORMAT_D16_UNORM); // spec requires this format to be supported
591
592 if (depthStencilFormat == VK_FORMAT_UNDEFINED)
593 return tcu::TestStatus::fail("Required depth/stencil format not supported");
594
595 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(depthStencilFormat) << tcu::TestLog::EndMessage;
596
597 const VkImageSubresourceRange testSubresourceRange = makeImageSubresourceRange(getImageAspectFlags(depthStencilFormat), 0u, 1u, 0u, 1u);
598 const Unique<VkImage> testImage (makeImage(vk, device, makeImageCreateInfo(renderSize, depthStencilFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
599 const UniquePtr<Allocation> testImageAlloc (bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
600 const Unique<VkImageView> testImageView (makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, testSubresourceRange));
601 const VkImageView attachmentImages[] = { *colorImageView, *testImageView };
602 const deUint32 numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
603
604 // Vertex buffer
605
606 const deUint32 numVertices = 6;
607 const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices;
608 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
609 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
610
611 {
612 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
613
614 pVertices[0] = tcu::Vec4( 1.0f, -1.0f, 0.5f, 1.0f);
615 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
616 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
617
618 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
619 pVertices[4] = tcu::Vec4( 1.0f, 1.0f, 1.0f, 1.0f);
620 pVertices[5] = tcu::Vec4( 1.0f, -1.0f, 0.5f, 1.0f);
621
622 flushAlloc(vk, device, *vertexBufferAlloc);
623 // No barrier needed, flushed memory is automatically visible
624 }
625
626 // Result buffer
627
628 const VkDeviceSize resultBufferSizeBytes = sizeof(deUint32);
629 const Unique<VkBuffer> resultBuffer (makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
630 const UniquePtr<Allocation> resultBufferAlloc (bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
631
632 {
633 deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
634
635 *pData = 0;
636 flushAlloc(vk, device, *resultBufferAlloc);
637 }
638
639 // Render result buffer (to retrieve color attachment contents)
640
641 const VkDeviceSize colorBufferSizeBytes = tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
642 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
643 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
644
645 // Depth stencil result buffer (to retrieve depth-stencil attachment contents)
646
647 const VkDeviceSize dsBufferSizeBytes = tcu::getPixelSize(mapVkFormat(depthStencilFormat)) * renderSize.x() * renderSize.y();
648 const Unique<VkBuffer> dsBuffer (makeBuffer(vk, device, dsBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
649 const UniquePtr<Allocation> dsBufferAlloc (bindBuffer(vk, device, allocator, *dsBuffer, MemoryRequirement::HostVisible));
650
651 // Descriptors
652
653 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
654 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
655 .build(vk, device));
656
657 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
658 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
659 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
660
661 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
662 const VkDescriptorBufferInfo resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
663
664 DescriptorSetUpdateBuilder()
665 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
666 .update(vk, device);
667
668 // Pipeline
669
670 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
671 const Unique<VkShaderModule> fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
672 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, colorFormat, m_useTestAttachment, depthStencilFormat));
673 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
674 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
675 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
676 (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL),
677 VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP));
678 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
679 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
680
681 // Draw commands
682 {
683 const VkRect2D renderArea = {
684 makeOffset2D(0, 0),
685 makeExtent2D(renderSize.x(), renderSize.y()),
686 };
687 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
688 const VkDeviceSize vertexBufferOffset = 0ull;
689
690 beginCommandBuffer(vk, *cmdBuffer);
691
692 {
693 const VkImageMemoryBarrier barriers[] = {
694 makeImageMemoryBarrier(
695 0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
696 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
697 *colorImage, colorSubresourceRange),
698 makeImageMemoryBarrier(
699 0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
700 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
701 *testImage, testSubresourceRange),
702 };
703
704 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
705 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
706 }
707
708 // Will clear the attachments with specified depth and stencil values.
709 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, 0.5f, 3u);
710
711 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
712 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
713 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
714
715 // Mask half of the attachment image with value that will pass the stencil test.
716 if (m_testMode == MODE_STENCIL)
717 commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
718
719 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
720 endRenderPass(vk, *cmdBuffer);
721
722 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
723 VkImageAspectFlags dsAspect = m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT;
724 VkImageLayout dsImageLayout = m_testMode == MODE_DEPTH ? VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL;
725 copyImageToBuffer(vk, *cmdBuffer, *testImage, *dsBuffer, renderSize, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, dsImageLayout, 1u, dsAspect, dsAspect);
726
727 endCommandBuffer(vk, *cmdBuffer);
728 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
729 }
730
731 // Verify color output
732 {
733 invalidateAlloc(vk, device, *colorBufferAlloc);
734
735 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
736 const tcu::TextureLevel referenceImage = generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
737 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
738 printf("Rendered color image is not correct");
739 }
740
741 // Verify depth-stencil output
742 {
743 invalidateAlloc(vk, device, *dsBufferAlloc);
744 // the buffer holds only one aspect of d/s format
745 tcu::TextureFormat format = vk::mapVkFormat(m_testMode == MODE_STENCIL ? VK_FORMAT_S8_UINT : depthStencilFormat);
746 DE_ASSERT(format.order == tcu::TextureFormat::D || format.order == tcu::TextureFormat::S);
747
748 const tcu::ConstPixelBufferAccess dsPixelAccess (format, renderSize.x(), renderSize.y(), 1, dsBufferAlloc->getHostPtr());
749
750 for(int z = 0; z < dsPixelAccess.getDepth(); z++)
751 for(int y = 0; y < dsPixelAccess.getHeight(); y++)
752 for(int x = 0; x < dsPixelAccess.getWidth(); x++)
753 {
754 float depthValue = (m_testMode == MODE_DEPTH) ? dsPixelAccess.getPixDepth(x, y, z) : 0.0f;
755 int stencilValue = (m_testMode == MODE_STENCIL) ? dsPixelAccess.getPixStencil(x, y, z) : 0;
756
757 // Depth test should write to the depth buffer even when there is a discard in the fragment shader,
758 // when early fragment tests are enabled. We allow some tolerance to account for precision error
759 // on depth writes.
760 if (m_testMode == MODE_DEPTH)
761 {
762 float tolerance = 0.0001f;
763 if (m_useEarlyTests && ((x + y) < 31) && depthValue >= 0.50 + tolerance)
764 {
765 std::ostringstream error;
766 error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " >= 0.5f";
767 TCU_FAIL(error.str().c_str());
768 }
769 // When early fragment tests are disabled, the depth test happens after the fragment shader, but as we are discarding
770 // all fragments, the stored value in the depth buffer should be the clear one (0.5f).
771 if (!m_useEarlyTests && deAbs(depthValue - 0.5f) > tolerance)
772 {
773 std::ostringstream error;
774 error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " != 0.5f";
775 TCU_FAIL(error.str().c_str());
776 }
777 }
778
779 if (m_testMode == MODE_STENCIL)
780 {
781 if (m_useEarlyTests && ((x < 16 && stencilValue != 2u) || (x >= 16 && stencilValue != 4u)))
782 {
783 std::ostringstream error;
784 error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
785 error << (x < 16 ? 2u : 4u);
786 TCU_FAIL(error.str().c_str());
787 }
788
789 if (!m_useEarlyTests && ((x < 16 && stencilValue != 1u) || (x >= 16 && stencilValue != 3u)))
790 {
791 std::ostringstream error;
792 error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
793 error << (x < 16 ? 1u : 3u);
794 TCU_FAIL(error.str().c_str());
795 }
796 }
797 }
798 }
799
800 // Verify we process all the fragments
801 {
802 invalidateAlloc(vk, device, *resultBufferAlloc);
803
804 const int actualCounter = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
805 const bool expectPartialResult = m_useEarlyTests;
806 const int expectedCounter = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
807 const int tolerance = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3 : 0;
808 const int expectedMin = de::max(0, expectedCounter - tolerance);
809 const int expectedMax = expectedCounter + tolerance;
810
811 tcu::TestLog& log = m_context.getTestContext().getLog();
812 log << tcu::TestLog::Message << "Expected value"
813 << (expectPartialResult ? " in range: [" + de::toString(expectedMin) + ", " + de::toString(expectedMax) + "]" : ": " + de::toString(expectedCounter))
814 << tcu::TestLog::EndMessage;
815 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
816
817 if (expectedMin <= actualCounter && actualCounter <= expectedMax)
818 return tcu::TestStatus::pass("Success");
819 else
820 return tcu::TestStatus::fail("Value out of range");
821 }
822 }
823
824 class EarlyFragmentDiscardTest : public EarlyFragmentTest
825 {
826 public:
827 EarlyFragmentDiscardTest (tcu::TestContext& testCtx,
828 const std::string name,
829 const deUint32 flags);
830
831 void initPrograms (SourceCollections& programCollection) const;
832 TestInstance* createInstance (Context& context) const;
833
834 private:
835 const deUint32 m_flags;
836 };
837
EarlyFragmentDiscardTest(tcu::TestContext & testCtx,const std::string name,const deUint32 flags)838 EarlyFragmentDiscardTest::EarlyFragmentDiscardTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags)
839 : EarlyFragmentTest (testCtx, name, flags)
840 , m_flags (flags)
841 {
842 }
843
createInstance(Context & context) const844 TestInstance* EarlyFragmentDiscardTest::createInstance (Context& context) const
845 {
846 return new EarlyFragmentDiscardTestInstance(context, m_flags);
847 }
848
initPrograms(SourceCollections & programCollection) const849 void EarlyFragmentDiscardTest::initPrograms(SourceCollections &programCollection) const
850 {
851 // Vertex
852 {
853 std::ostringstream src;
854 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
855 << "\n"
856 << "layout(location = 0) in highp vec4 position;\n"
857 << "\n"
858 << "out gl_PerVertex {\n"
859 << " vec4 gl_Position;\n"
860 << "};\n"
861 << "\n"
862 << "void main (void)\n"
863 << "{\n"
864 << " gl_Position = position;\n"
865 << "}\n";
866
867 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
868 }
869
870 // Fragment
871 {
872 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
873 std::ostringstream src;
874 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
875 << "\n"
876 << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
877 << "layout(location = 0) out highp vec4 fragColor;\n"
878 << "\n"
879 << "layout(binding = 0) coherent buffer Output {\n"
880 << " uint result;\n"
881 << "} sb_out;\n"
882 << "\n"
883 << "void main (void)\n"
884 << "{\n"
885 << " atomicAdd(sb_out.result, 1u);\n"
886 << " gl_FragDepth = 0.75f;\n"
887 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
888 << " discard;\n"
889 << "}\n";
890
891 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
892 }
893 }
894
895 class EarlyFragmentSampleMaskTestInstance : public EarlyFragmentTestInstance
896 {
897 public:
898 EarlyFragmentSampleMaskTestInstance (Context& context, const deUint32 flags, const deUint32 sampleCount);
899
900 tcu::TestStatus iterate (void);
901
902 private:
903 tcu::TextureLevel generateReferenceColorImage (const tcu::TextureFormat format, const tcu::IVec2& renderSize);
904 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
905 const VkDevice device,
906 const VkFormat colorFormat,
907 const VkFormat depthStencilFormat);
908 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface& vk,
909 const VkDevice device,
910 const VkPipelineLayout pipelineLayout,
911 const VkRenderPass renderPass,
912 const VkShaderModule vertexModule,
913 const VkShaderModule fragmentModule,
914 const tcu::IVec2& renderSize,
915 const bool enableDepthTest,
916 const bool enableStencilTest,
917 const VkStencilOp stencilFailOp,
918 const VkStencilOp stencilPassOp);
919 enum TestMode
920 {
921 MODE_INVALID,
922 MODE_DEPTH,
923 MODE_STENCIL,
924 };
925
926 const TestMode m_testMode;
927 const bool m_useTestAttachment;
928 const bool m_useEarlyTests;
929 const deUint32 m_sampleCount;
930 };
931
EarlyFragmentSampleMaskTestInstance(Context & context,const deUint32 flags,const deUint32 sampleCount)932 EarlyFragmentSampleMaskTestInstance::EarlyFragmentSampleMaskTestInstance (Context& context, const deUint32 flags, const deUint32 sampleCount)
933 : EarlyFragmentTestInstance (context, flags)
934 , m_testMode (flags & FLAG_TEST_DEPTH ? MODE_DEPTH :
935 flags & FLAG_TEST_STENCIL ? MODE_STENCIL : MODE_INVALID)
936 , m_useTestAttachment ((flags & FLAG_DONT_USE_TEST_ATTACHMENT) == 0)
937 , m_useEarlyTests ((flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0)
938 , m_sampleCount (sampleCount)
939 {
940 DE_ASSERT(m_testMode != MODE_INVALID);
941 }
942
generateReferenceColorImage(const tcu::TextureFormat format,const tcu::IVec2 & renderSize)943 tcu::TextureLevel EarlyFragmentSampleMaskTestInstance::generateReferenceColorImage(const tcu::TextureFormat format, const tcu::IVec2 &renderSize)
944 {
945 tcu::TextureLevel image(format, renderSize.x(), renderSize.y());
946 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
947
948 tcu::clear(image.getAccess(), clearColor);
949
950 return image;
951 }
952
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const tcu::IVec2 & renderSize,const bool enableDepthTest,const bool enableStencilTest,const VkStencilOp stencilFailOp,const VkStencilOp stencilPassOp)953 Move<VkPipeline> EarlyFragmentSampleMaskTestInstance::makeGraphicsPipeline (const DeviceInterface& vk,
954 const VkDevice device,
955 const VkPipelineLayout pipelineLayout,
956 const VkRenderPass renderPass,
957 const VkShaderModule vertexModule,
958 const VkShaderModule fragmentModule,
959 const tcu::IVec2& renderSize,
960 const bool enableDepthTest,
961 const bool enableStencilTest,
962 const VkStencilOp stencilFailOp,
963 const VkStencilOp stencilPassOp)
964 {
965 const std::vector<VkViewport> viewports (1, makeViewport(renderSize));
966 const std::vector<VkRect2D> scissors (1, makeRect2D(renderSize));
967
968 const VkStencilOpState stencilOpState = makeStencilOpState(
969 stencilFailOp, // stencil fail
970 stencilPassOp, // depth & stencil pass
971 VK_STENCIL_OP_KEEP, // depth only fail
972 VK_COMPARE_OP_EQUAL, // compare op
973 0x3, // compare mask
974 0xf, // write mask
975 1u); // reference
976
977 const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
978 {
979 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
980 DE_NULL, // const void* pNext
981 0u, // VkPipelineDepthStencilStateCreateFlags flags
982 enableDepthTest ? VK_TRUE : VK_FALSE, // VkBool32 depthTestEnable
983 enableDepthTest ? VK_TRUE : VK_FALSE, // VkBool32 depthWriteEnable
984 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp
985 VK_FALSE, // VkBool32 depthBoundsTestEnable
986 enableStencilTest ? VK_TRUE : VK_FALSE, // VkBool32 stencilTestEnable
987 stencilOpState, // VkStencilOpState front
988 stencilOpState, // VkStencilOpState back
989 0.0f, // float minDepthBounds
990 1.0f // float maxDepthBounds
991 };
992
993 // Only allow coverage on sample 0.
994 const VkSampleMask sampleMask = 0x1;
995
996 const VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo =
997 {
998 VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, // VkStructureType sType
999 DE_NULL, // const void* pNext
1000 0u, // VkPipelineMultisampleStateCreateFlags flags
1001 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits rasterizationSamples
1002 DE_TRUE, // VkBool32 sampleShadingEnable
1003 0.0f, // float minSampleShading
1004 &sampleMask, // const VkSampleMask* pSampleMask
1005 DE_FALSE, // VkBool32 alphaToCoverageEnable
1006 DE_FALSE, // VkBool32 alphaToOneEnable
1007 };
1008
1009 return vk::makeGraphicsPipeline(vk, // const DeviceInterface& vk
1010 device, // const VkDevice device
1011 pipelineLayout, // const VkPipelineLayout pipelineLayout
1012 vertexModule, // const VkShaderModule vertexShaderModule
1013 DE_NULL, // const VkShaderModule tessellationControlModule
1014 DE_NULL, // const VkShaderModule tessellationEvalModule
1015 DE_NULL, // const VkShaderModule geometryShaderModule
1016 fragmentModule, // const VkShaderModule fragmentShaderModule
1017 renderPass, // const VkRenderPass renderPass
1018 viewports, // const std::vector<VkViewport>& viewports
1019 scissors, // const std::vector<VkRect2D>& scissors
1020 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
1021 0u, // const deUint32 subpass
1022 0u, // const deUint32 patchControlPoints
1023 DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
1024 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1025 &multisampleStateCreateInfo, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
1026 &depthStencilStateCreateInfo); // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
1027 }
1028
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const VkFormat depthStencilFormat)1029 Move<VkRenderPass> EarlyFragmentSampleMaskTestInstance::makeRenderPass (const DeviceInterface& vk,
1030 const VkDevice device,
1031 const VkFormat colorFormat,
1032 const VkFormat depthStencilFormat)
1033 {
1034 const bool hasColor = colorFormat != VK_FORMAT_UNDEFINED;
1035 const bool hasDepthStencil = depthStencilFormat != VK_FORMAT_UNDEFINED;
1036
1037
1038 const VkAttachmentDescription2 colorAttachmentDescription =
1039 {
1040 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
1041 DE_NULL, // const void* pNext;
1042 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
1043 colorFormat, // VkFormat format
1044 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits samples
1045 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
1046 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
1047 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
1048 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
1049 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
1050 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
1051 };
1052
1053 const VkAttachmentDescription2 depthStencilAttachmentDescription =
1054 {
1055 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
1056 DE_NULL, // const void* pNext;
1057 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
1058 depthStencilFormat, // VkFormat format
1059 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits samples
1060 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
1061 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
1062 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp
1063 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp
1064 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
1065 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
1066 };
1067
1068 const VkAttachmentDescription2 resolveAttachmentDescription =
1069 {
1070 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
1071 DE_NULL, // const void* pNext;
1072 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
1073 colorFormat, // VkFormat format
1074 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
1075 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
1076 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
1077 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
1078 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
1079 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
1080 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
1081 };
1082
1083 const VkAttachmentDescription2 resolveDepthStencilAttachmentDescription =
1084 {
1085 VK_STRUCTURE_TYPE_ATTACHMENT_DESCRIPTION_2, // VkStructureType sType;
1086 DE_NULL, // const void* pNext;
1087 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
1088 depthStencilFormat, // VkFormat format
1089 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
1090 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
1091 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
1092 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp stencilLoadOp
1093 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp stencilStoreOp
1094 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
1095 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout
1096 };
1097
1098 std::vector<VkAttachmentDescription2> attachmentDescriptions;
1099
1100 if (hasColor)
1101 attachmentDescriptions.push_back(colorAttachmentDescription);
1102 if (hasDepthStencil)
1103 attachmentDescriptions.push_back(depthStencilAttachmentDescription);
1104 if (hasColor)
1105 attachmentDescriptions.push_back(resolveAttachmentDescription);
1106 if (hasDepthStencil)
1107 attachmentDescriptions.push_back(resolveDepthStencilAttachmentDescription);
1108
1109 const VkAttachmentReference2 colorAttachmentRef =
1110 {
1111 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
1112 DE_NULL, // const void* pNext;
1113 0u, // deUint32 attachment
1114 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout
1115 VK_IMAGE_ASPECT_COLOR_BIT // VkImageAspectFlags aspectMask;
1116 };
1117
1118 const VkAttachmentReference2 depthStencilAttachmentRef =
1119 {
1120 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
1121 DE_NULL, // const void* pNext;
1122 hasDepthStencil ? 1u : 0u, // deUint32 attachment
1123 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout layout
1124 m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT // VkImageAspectFlags aspectMask;
1125 };
1126
1127 const VkAttachmentReference2 resolveAttachmentRef =
1128 {
1129 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
1130 DE_NULL, // const void* pNext;
1131 hasColor ? 2u : 0u, // deUint32 attachment
1132 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout layout
1133 VK_IMAGE_ASPECT_COLOR_BIT // VkImageAspectFlags aspectMask;
1134 };
1135
1136 const VkAttachmentReference2 depthStencilResolveAttachmentRef =
1137 {
1138 VK_STRUCTURE_TYPE_ATTACHMENT_REFERENCE_2, // VkStructureType sType;
1139 DE_NULL, // const void* pNext;
1140 hasDepthStencil ? 3u : 0u, // deUint32 attachment
1141 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout layout
1142 m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT // VkImageAspectFlags aspectMask;
1143 };
1144
1145 // Using VK_RESOLVE_MODE_SAMPLE_ZERO_BIT as resolve mode, so no need to check its support as it is mandatory in the extension.
1146 const VkSubpassDescriptionDepthStencilResolve depthStencilResolveDescription =
1147 {
1148 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_DEPTH_STENCIL_RESOLVE, // VkStructureType sType;
1149 DE_NULL, // const void* pNext;
1150 VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, // VkResolveModeFlagBits depthResolveMode;
1151 VK_RESOLVE_MODE_SAMPLE_ZERO_BIT, // VkResolveModeFlagBits stencilResolveMode;
1152 &depthStencilResolveAttachmentRef // const VkAttachmentReference2* pDepthStencilResolveAttachment;
1153 };
1154
1155 const VkSubpassDescription2 subpassDescription =
1156 {
1157 VK_STRUCTURE_TYPE_SUBPASS_DESCRIPTION_2, // VkStructureType sType;
1158 hasDepthStencil ? &depthStencilResolveDescription : DE_NULL, // const void* pNext;
1159 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
1160 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
1161 0u, // deUint32 viewMask;
1162 0u, // deUint32 inputAttachmentCount
1163 DE_NULL, // const VkAttachmentReference2* pInputAttachments
1164 hasColor ? 1u : 0u, // deUint32 colorAttachmentCount
1165 hasColor ? &colorAttachmentRef : DE_NULL, // const VkAttachmentReference2* pColorAttachments
1166 hasColor ? &resolveAttachmentRef : DE_NULL, // const VkAttachmentReference2* pResolveAttachments
1167 hasDepthStencil ? &depthStencilAttachmentRef : DE_NULL, // const VkAttachmentReference2* pDepthStencilAttachment
1168 0u, // deUint32 preserveAttachmentCount
1169 DE_NULL // const deUint32* pPreserveAttachments
1170 };
1171
1172 const VkRenderPassCreateInfo2 renderPassInfo =
1173 {
1174 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO_2, // VkStructureType sType
1175 DE_NULL, // const void* pNext
1176 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
1177 (deUint32)attachmentDescriptions.size(), // deUint32 attachmentCount
1178 attachmentDescriptions.size() > 0 ? &attachmentDescriptions[0] : DE_NULL, // const VkAttachmentDescription2* pAttachments
1179 1u, // deUint32 subpassCount
1180 &subpassDescription, // const VkSubpassDescription2* pSubpasses
1181 0u, // deUint32 dependencyCount
1182 DE_NULL, // const VkSubpassDependency* pDependencies
1183 0u, // deUint32 correlatedViewMaskCount;
1184 DE_NULL, // const deUint32* pCorrelatedViewMasks;
1185 };
1186
1187 return createRenderPass2(vk, device, &renderPassInfo, DE_NULL);
1188 }
1189
iterate(void)1190 tcu::TestStatus EarlyFragmentSampleMaskTestInstance::iterate (void)
1191 {
1192 const DeviceInterface& vk = m_context.getDeviceInterface();
1193 const InstanceInterface& vki = m_context.getInstanceInterface();
1194 const VkDevice device = m_context.getDevice();
1195 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
1196 const VkQueue queue = m_context.getUniversalQueue();
1197 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
1198 Allocator& allocator = m_context.getDefaultAllocator();
1199 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
1200
1201 DE_ASSERT(m_useTestAttachment);
1202 DE_UNREF(m_useTestAttachment);
1203
1204 // Test attachment (depth or stencil)
1205 static const VkFormat stencilFormats[] =
1206 {
1207 // One of the following formats must be supported, as per spec requirement.
1208 VK_FORMAT_S8_UINT,
1209 VK_FORMAT_D16_UNORM_S8_UINT,
1210 VK_FORMAT_D24_UNORM_S8_UINT,
1211 VK_FORMAT_D32_SFLOAT_S8_UINT,
1212 };
1213
1214 const VkFormat depthStencilFormat = (m_testMode == MODE_STENCIL ? pickSupportedDepthStencilFormat(vki, physDevice, DE_LENGTH_OF_ARRAY(stencilFormats), stencilFormats)
1215 : VK_FORMAT_D16_UNORM); // spec requires this format to be supported
1216
1217 if (depthStencilFormat == VK_FORMAT_UNDEFINED)
1218 return tcu::TestStatus::fail("Required depth/stencil format not supported");
1219
1220 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(depthStencilFormat) << tcu::TestLog::EndMessage;
1221
1222 // Check support for MSAA image formats used in the test.
1223 VkImageFormatProperties formatProperties;
1224 vki.getPhysicalDeviceImageFormatProperties(physDevice, colorFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
1225 if ((formatProperties.sampleCounts & m_sampleCount) == 0)
1226 TCU_THROW(NotSupportedError, "Format does not support this number of samples for color format");
1227
1228 vki.getPhysicalDeviceImageFormatProperties(physDevice, depthStencilFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
1229 if ((formatProperties.sampleCounts & m_sampleCount) == 0)
1230 TCU_THROW(NotSupportedError, "Format does not support this number of samples for depth-stencil format");
1231
1232 // Color attachment
1233 const tcu::IVec2 renderSize = tcu::IVec2(32, 32);
1234 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1235
1236 const VkImageCreateInfo imageParams =
1237 {
1238 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1239 DE_NULL, // const void* pNext;
1240 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
1241 VK_IMAGE_TYPE_2D, // VkImageType imageType;
1242 colorFormat, // VkFormat format;
1243 makeExtent3D(renderSize.x(), renderSize.y(), 1), // VkExtent3D extent;
1244 1u, // deUint32 mipLevels;
1245 1u, // deUint32 arrayLayers;
1246 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits samples;
1247 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1248 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
1249 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1250 0u, // deUint32 queueFamilyIndexCount;
1251 DE_NULL, // const deUint32* pQueueFamilyIndices;
1252 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1253 };
1254 const Unique<VkImage> colorImage (makeImage(vk, device, imageParams));
1255 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1256 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
1257
1258 const Unique<VkImage> resolveColorImage (makeImage(vk, device, makeImageCreateInfo(renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1259 const UniquePtr<Allocation> resolveColorImageAlloc (bindImage(vk, device, allocator, *resolveColorImage, MemoryRequirement::Any));
1260 const Unique<VkImageView> resolveColorImageView (makeImageView(vk, device, *resolveColorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
1261
1262 // Depth-Stencil attachment
1263 const VkImageSubresourceRange depthStencilSubresourceRange = makeImageSubresourceRange(getImageAspectFlags(depthStencilFormat), 0u, 1u, 0u, 1u);
1264
1265 const VkImageCreateInfo depthStencilImageParams =
1266 {
1267 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
1268 DE_NULL, // const void* pNext;
1269 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
1270 VK_IMAGE_TYPE_2D, // VkImageType imageType;
1271 depthStencilFormat, // VkFormat format;
1272 makeExtent3D(renderSize.x(), renderSize.y(), 1), // VkExtent3D extent;
1273 1u, // deUint32 mipLevels;
1274 1u, // deUint32 arrayLayers;
1275 (VkSampleCountFlagBits)m_sampleCount, // VkSampleCountFlagBits samples;
1276 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
1277 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage;
1278 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
1279 0u, // deUint32 queueFamilyIndexCount;
1280 DE_NULL, // const deUint32* pQueueFamilyIndices;
1281 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
1282 };
1283 const Unique<VkImage> depthStencilImage (makeImage(vk, device, depthStencilImageParams));
1284 const UniquePtr<Allocation> depthStencilImageAlloc (bindImage(vk, device, allocator, *depthStencilImage, MemoryRequirement::Any));
1285 const Unique<VkImageView> depthStencilImageView (makeImageView(vk, device, *depthStencilImage, VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, depthStencilSubresourceRange));
1286
1287 const Unique<VkImage> resolveDepthStencilImage (makeImage(vk, device, makeImageCreateInfo(renderSize, depthStencilFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
1288 const UniquePtr<Allocation> resolveDepthStencilImageAlloc (bindImage(vk, device, allocator, *resolveDepthStencilImage, MemoryRequirement::Any));
1289 const Unique<VkImageView> resolveDepthStencilImageView (makeImageView(vk, device, *resolveDepthStencilImage, VK_IMAGE_VIEW_TYPE_2D, depthStencilFormat, depthStencilSubresourceRange));
1290
1291 const VkImageView attachmentImages[] = { *colorImageView, *depthStencilImageView, *resolveColorImageView, *resolveDepthStencilImageView };
1292 const deUint32 numUsedAttachmentImages = DE_LENGTH_OF_ARRAY(attachmentImages);
1293
1294 // Vertex buffer
1295
1296 const deUint32 numVertices = 6u;
1297 const VkDeviceSize vertexBufferSizeBytes = sizeof(tcu::Vec4) * numVertices;
1298 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
1299 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1300
1301 {
1302 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
1303
1304 pVertices[0] = tcu::Vec4( 1.0f, -1.0f, 0.5f, 1.0f);
1305 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
1306 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
1307
1308 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 0.5f, 1.0f);
1309 pVertices[4] = tcu::Vec4( 1.0f, 1.0f, 1.0f, 1.0f);
1310 pVertices[5] = tcu::Vec4( 1.0f, -1.0f, 0.5f, 1.0f);
1311
1312 flushAlloc(vk, device, *vertexBufferAlloc);
1313 // No barrier needed, flushed memory is automatically visible
1314 }
1315
1316 // Result buffer
1317
1318 const VkDeviceSize resultBufferSizeBytes = sizeof(deUint32);
1319 const Unique<VkBuffer> resultBuffer (makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT));
1320 const UniquePtr<Allocation> resultBufferAlloc (bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));
1321
1322 {
1323 deUint32* const pData = static_cast<deUint32*>(resultBufferAlloc->getHostPtr());
1324
1325 *pData = 0;
1326 flushAlloc(vk, device, *resultBufferAlloc);
1327 }
1328
1329 // Render result buffer (to retrieve color attachment contents)
1330
1331 const VkDeviceSize colorBufferSizeBytes = tcu::getPixelSize(mapVkFormat(colorFormat)) * renderSize.x() * renderSize.y();
1332 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1333 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1334
1335 // Depth stencil result buffer (to retrieve depth-stencil attachment contents)
1336
1337 const VkDeviceSize dsBufferSizeBytes = tcu::getPixelSize(mapVkFormat(depthStencilFormat)) * renderSize.x() * renderSize.y();
1338 const Unique<VkBuffer> dsBuffer (makeBuffer(vk, device, dsBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1339 const UniquePtr<Allocation> dsBufferAlloc (bindBuffer(vk, device, allocator, *dsBuffer, MemoryRequirement::HostVisible));
1340
1341 // Descriptors
1342
1343 const Unique<VkDescriptorSetLayout> descriptorSetLayout(DescriptorSetLayoutBuilder()
1344 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
1345 .build(vk, device));
1346
1347 const Unique<VkDescriptorPool> descriptorPool(DescriptorPoolBuilder()
1348 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER)
1349 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u));
1350
1351 const Unique<VkDescriptorSet> descriptorSet (makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout));
1352 const VkDescriptorBufferInfo resultBufferDescriptorInfo = makeDescriptorBufferInfo(resultBuffer.get(), 0ull, resultBufferSizeBytes);
1353
1354 DescriptorSetUpdateBuilder()
1355 .writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &resultBufferDescriptorInfo)
1356 .update(vk, device);
1357
1358 // Pipeline
1359
1360 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1361 const Unique<VkShaderModule> fragmentModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1362
1363 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, colorFormat, depthStencilFormat));
1364 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages, renderSize.x(), renderSize.y()));
1365 const Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(vk, device, *descriptorSetLayout));
1366 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, renderSize,
1367 (m_testMode == MODE_DEPTH), (m_testMode == MODE_STENCIL),
1368 VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_INCREMENT_AND_CLAMP));
1369 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1370 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1371
1372 // Draw commands
1373
1374 {
1375 const VkRect2D renderArea = {
1376 makeOffset2D(0, 0),
1377 makeExtent2D(renderSize.x(), renderSize.y()),
1378 };
1379 const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
1380 const VkDeviceSize vertexBufferOffset = 0ull;
1381
1382 beginCommandBuffer(vk, *cmdBuffer);
1383
1384 {
1385 const VkImageMemoryBarrier barriers[] = {
1386 makeImageMemoryBarrier(
1387 0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1388 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1389 *colorImage, colorSubresourceRange),
1390 makeImageMemoryBarrier(
1391 0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1392 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1393 *depthStencilImage, depthStencilSubresourceRange),
1394 makeImageMemoryBarrier(
1395 0u, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
1396 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
1397 *resolveColorImage, colorSubresourceRange),
1398 makeImageMemoryBarrier(
1399 0u, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
1400 VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
1401 *resolveDepthStencilImage, depthStencilSubresourceRange),
1402 };
1403
1404 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
1405 0u, DE_NULL, 0u, DE_NULL, DE_LENGTH_OF_ARRAY(barriers), barriers);
1406 }
1407
1408 // Will clear the attachments with specified depth and stencil values.
1409 {
1410 const VkClearValue clearValues[] =
1411 {
1412 makeClearValueColor(clearColor), // attachment 0
1413 makeClearValueDepthStencil(0.5f, 3u), // attachment 1
1414 makeClearValueColor(clearColor), // attachment 2
1415 makeClearValueDepthStencil(0.5f, 3u), // attachment 3
1416 };
1417
1418 const VkRenderPassBeginInfo renderPassBeginInfo =
1419 {
1420 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
1421 DE_NULL, // const void* pNext;
1422 *renderPass, // VkRenderPass renderPass;
1423 *framebuffer, // VkFramebuffer framebuffer;
1424 renderArea, // VkRect2D renderArea;
1425 DE_LENGTH_OF_ARRAY(clearValues), // deUint32 clearValueCount;
1426 clearValues, // const VkClearValue* pClearValues;
1427 };
1428
1429 vk.cmdBeginRenderPass(*cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
1430 }
1431
1432 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1433 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1434 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1435
1436 // Mask half of the attachment image with value that will pass the stencil test.
1437 if (m_testMode == MODE_STENCIL)
1438 commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(0, 0), makeExtent2D(renderSize.x()/2, renderSize.y()), 1u);
1439
1440 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
1441 endRenderPass(vk, *cmdBuffer);
1442
1443 copyImageToBuffer(vk, *cmdBuffer, *resolveColorImage, *colorBuffer, renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
1444 VkImageAspectFlags dsAspect = m_testMode == MODE_DEPTH ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_STENCIL_BIT;
1445 copyImageToBuffer(vk, *cmdBuffer, *resolveDepthStencilImage, *dsBuffer, renderSize, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, 1u, dsAspect, dsAspect);
1446
1447 endCommandBuffer(vk, *cmdBuffer);
1448 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1449 }
1450
1451 // Verify color output
1452 {
1453 invalidateAlloc(vk, device, *colorBufferAlloc);
1454
1455 const tcu::ConstPixelBufferAccess imagePixelAccess(mapVkFormat(colorFormat), renderSize.x(), renderSize.y(), 1, colorBufferAlloc->getHostPtr());
1456 const tcu::TextureLevel referenceImage = generateReferenceColorImage(mapVkFormat(colorFormat), renderSize);
1457 if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
1458 printf("Rendered color image is not correct");
1459 }
1460
1461 // Verify depth-stencil output
1462 {
1463 invalidateAlloc(vk, device, *dsBufferAlloc);
1464 tcu::TextureFormat format = mapVkFormat(depthStencilFormat);
1465 const tcu::ConstPixelBufferAccess dsPixelAccess (format, renderSize.x(), renderSize.y(), 1, dsBufferAlloc->getHostPtr());
1466
1467 for(int z = 0; z < dsPixelAccess.getDepth(); z++)
1468 for(int y = 0; y < dsPixelAccess.getHeight(); y++)
1469 for(int x = 0; x < dsPixelAccess.getWidth(); x++)
1470 {
1471 float depthValue = (m_testMode == MODE_DEPTH) ? dsPixelAccess.getPixDepth(x, y, z) : 0.0f;
1472 int stencilValue = (m_testMode == MODE_STENCIL) ? dsPixelAccess.getPixStencil(x, y, z) : 0;
1473
1474 // Depth test should write to the depth buffer even when there is a discard in the fragment shader,
1475 // when early fragment tests are enabled.
1476 if (m_testMode == MODE_DEPTH)
1477 {
1478 if (m_useEarlyTests && ((x + y) < 31) && depthValue >= 0.5f)
1479 {
1480 std::ostringstream error;
1481 error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " >= 0.5f";
1482 TCU_FAIL(error.str().c_str());
1483 }
1484 // When early fragment tests are disabled, the depth test happens after the fragment shader, but as we are discarding
1485 // all fragments, the stored value in the depth buffer should be the clear one (0.5f).
1486 if (!m_useEarlyTests && deAbs(depthValue - 0.5f) > 0.01f)
1487 {
1488 std::ostringstream error;
1489 error << "Rendered depth value [ "<< x << ", " << y << ", " << z << "] is not correct: " << depthValue << " != 0.5f";
1490 TCU_FAIL(error.str().c_str());
1491 }
1492 }
1493
1494 if (m_testMode == MODE_STENCIL)
1495 {
1496 if (m_useEarlyTests && ((x < 16 && stencilValue != 2u) || (x >= 16 && stencilValue != 4u)))
1497 {
1498 std::ostringstream error;
1499 error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
1500 error << (x < 16 ? 2u : 4u);
1501 TCU_FAIL(error.str().c_str());
1502 }
1503
1504 if (!m_useEarlyTests && ((x < 16 && stencilValue != 1u) || (x >= 16 && stencilValue != 3u)))
1505 {
1506 std::ostringstream error;
1507 error << "Rendered stencil value [ "<< x << ", " << y << ", " << z << "] is not correct: " << stencilValue << " != ";
1508 error << (x < 16 ? 1u : 3u);
1509 TCU_FAIL(error.str().c_str());
1510 }
1511 }
1512 }
1513 }
1514
1515 // Verify we process all the fragments
1516 {
1517 invalidateAlloc(vk, device, *resultBufferAlloc);
1518
1519 const int actualCounter = *static_cast<deInt32*>(resultBufferAlloc->getHostPtr());
1520 const bool expectPartialResult = m_useEarlyTests;
1521 const int expectedCounter = expectPartialResult ? renderSize.x() * renderSize.y() / 2 : renderSize.x() * renderSize.y();
1522 const int tolerance = expectPartialResult ? de::max(renderSize.x(), renderSize.y()) * 3 : 0;
1523 const int expectedMin = de::max(0, expectedCounter - tolerance);
1524
1525 tcu::TestLog& log = m_context.getTestContext().getLog();
1526 log << tcu::TestLog::Message << "Minimum expected value: " + de::toString(expectedMin) << tcu::TestLog::EndMessage;
1527 log << tcu::TestLog::Message << "Result value: " << de::toString(actualCounter) << tcu::TestLog::EndMessage;
1528
1529 if (expectedMin <= actualCounter)
1530 return tcu::TestStatus::pass("Success");
1531 else
1532 return tcu::TestStatus::fail("Value out of range");
1533 }
1534 }
1535
1536 class EarlyFragmentSampleMaskTest : public EarlyFragmentTest
1537 {
1538 public:
1539 EarlyFragmentSampleMaskTest (tcu::TestContext& testCtx,
1540 const std::string name,
1541 const deUint32 flags,
1542 const deUint32 sampleCount);
1543
1544 void initPrograms (SourceCollections& programCollection) const override;
1545 TestInstance* createInstance (Context& context) const override;
1546 void checkSupport (Context& context) const override;
1547
1548 private:
1549 const deUint32 m_flags;
1550 const deUint32 m_sampleCount;
1551 };
1552
EarlyFragmentSampleMaskTest(tcu::TestContext & testCtx,const std::string name,const deUint32 flags,const deUint32 sampleCount)1553 EarlyFragmentSampleMaskTest::EarlyFragmentSampleMaskTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags, const deUint32 sampleCount)
1554 : EarlyFragmentTest (testCtx, name, flags)
1555 , m_flags (flags)
1556 , m_sampleCount (sampleCount)
1557 {
1558 }
1559
createInstance(Context & context) const1560 TestInstance* EarlyFragmentSampleMaskTest::createInstance (Context& context) const
1561 {
1562 return new EarlyFragmentSampleMaskTestInstance(context, m_flags, m_sampleCount);
1563 }
1564
initPrograms(SourceCollections & programCollection) const1565 void EarlyFragmentSampleMaskTest::initPrograms(SourceCollections &programCollection) const
1566 {
1567 // Vertex
1568 {
1569 std::ostringstream src;
1570 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1571 << "\n"
1572 << "layout(location = 0) in highp vec4 position;\n"
1573 << "\n"
1574 << "out gl_PerVertex {\n"
1575 << " vec4 gl_Position;\n"
1576 << "};\n"
1577 << "\n"
1578 << "void main (void)\n"
1579 << "{\n"
1580 << " gl_Position = position;\n"
1581 << "}\n";
1582
1583 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1584 }
1585
1586 // Fragment
1587 {
1588 const bool useEarlyTests = (m_flags & FLAG_DONT_USE_EARLY_FRAGMENT_TESTS) == 0;
1589 std::ostringstream src;
1590 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_440) << "\n"
1591 << "\n"
1592 << (useEarlyTests ? "layout(early_fragment_tests) in;\n" : "")
1593 << "layout(location = 0) out highp vec4 fragColor;\n"
1594 << "\n"
1595 << "layout(binding = 0) coherent buffer Output {\n"
1596 << " uint result;\n"
1597 << "} sb_out;\n"
1598 << "\n"
1599 << "void main (void)\n"
1600 << "{\n"
1601 << " atomicAdd(sb_out.result, 1u);\n"
1602 << " gl_SampleMask[0] = 0x0;\n"
1603 << " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n"
1604 << " discard;\n"
1605 << "}\n";
1606
1607 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1608 }
1609 }
1610
checkSupport(Context & context) const1611 void EarlyFragmentSampleMaskTest::checkSupport(Context& context) const
1612 {
1613 EarlyFragmentTest::checkSupport(context);
1614
1615 context.requireDeviceFunctionality("VK_KHR_depth_stencil_resolve");
1616 }
1617
1618 } // anonymous ns
1619
createEarlyFragmentTests(tcu::TestContext & testCtx)1620 tcu::TestCaseGroup* createEarlyFragmentTests (tcu::TestContext& testCtx)
1621 {
1622 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "early_fragment", "early fragment test cases"));
1623
1624 {
1625 static const struct
1626 {
1627 std::string caseName;
1628 deUint32 flags;
1629 } cases[] =
1630 {
1631 { "no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS },
1632 { "no_early_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS },
1633 { "early_fragment_tests_depth", FLAG_TEST_DEPTH },
1634 { "early_fragment_tests_stencil", FLAG_TEST_STENCIL },
1635 { "no_early_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT },
1636 { "no_early_fragment_tests_stencil_no_attachment", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS | FLAG_DONT_USE_TEST_ATTACHMENT },
1637 { "early_fragment_tests_depth_no_attachment", FLAG_TEST_DEPTH | FLAG_DONT_USE_TEST_ATTACHMENT },
1638 { "early_fragment_tests_stencil_no_attachment", FLAG_TEST_STENCIL | FLAG_DONT_USE_TEST_ATTACHMENT },
1639 };
1640
1641 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
1642 testGroup->addChild(new EarlyFragmentTest(testCtx, cases[i].caseName, cases[i].flags));
1643 }
1644
1645 // Check that discard does not affect depth test writes.
1646 {
1647 static const struct
1648 {
1649 std::string caseName;
1650 deUint32 flags;
1651 } cases[] =
1652 {
1653 { "discard_no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS },
1654 { "discard_no_early_fragment_tests_stencil", FLAG_TEST_STENCIL | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS },
1655 { "discard_early_fragment_tests_depth", FLAG_TEST_DEPTH },
1656 { "discard_early_fragment_tests_stencil", FLAG_TEST_STENCIL },
1657 };
1658
1659 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
1660 testGroup->addChild(new EarlyFragmentDiscardTest(testCtx, cases[i].caseName, cases[i].flags));
1661 }
1662
1663 // Check that writing to gl_SampleMask does not affect depth test writes.
1664 {
1665 static const struct
1666 {
1667 std::string caseName;
1668 deUint32 flags;
1669 } cases[] =
1670 {
1671 { "samplemask_no_early_fragment_tests_depth", FLAG_TEST_DEPTH | FLAG_DONT_USE_EARLY_FRAGMENT_TESTS, },
1672 { "samplemask_early_fragment_tests_depth", FLAG_TEST_DEPTH, },
1673 };
1674
1675 const VkSampleCountFlags sampleCounts[] = { VK_SAMPLE_COUNT_2_BIT, VK_SAMPLE_COUNT_4_BIT, VK_SAMPLE_COUNT_8_BIT, VK_SAMPLE_COUNT_16_BIT };
1676 const std::string sampleCountsStr[] = { "samples_2", "samples_4", "samples_8", "samples_16" };
1677
1678 for (deUint32 sampleCountsNdx = 0; sampleCountsNdx < DE_LENGTH_OF_ARRAY(sampleCounts); sampleCountsNdx++)
1679 {
1680 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
1681 testGroup->addChild(new EarlyFragmentSampleMaskTest(testCtx, cases[i].caseName + "_" + sampleCountsStr[sampleCountsNdx], cases[i].flags, sampleCounts[sampleCountsNdx]));
1682 }
1683 }
1684
1685 return testGroup.release();
1686 }
1687
1688 } // FragmentOperations
1689 } // vkt
1690