1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2021 The Khronos Group Inc.
6 * Copyright (c) 2021 Google 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 Fragment Operations Occlusion Query Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktFragmentOperationsOcclusionQueryTests.hpp"
26 #include "vktTestCaseUtil.hpp"
27
28 #include "vkDefs.hpp"
29 #include "vkRef.hpp"
30 #include "vkRefUtil.hpp"
31 #include "vkPlatform.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkMemUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkStrUtil.hpp"
36 #include "vkTypeUtil.hpp"
37 #include "vkQueryUtil.hpp"
38 #include "vkImageUtil.hpp"
39 #include "vkBarrierUtil.hpp"
40 #include "vkCmdUtil.hpp"
41 #include "vkObjUtil.hpp"
42
43 #include "tcuTestLog.hpp"
44 #include "tcuImageCompare.hpp"
45 #include "tcuTextureUtil.hpp"
46
47 #include "deUniquePtr.hpp"
48 #include "deStringUtil.hpp"
49 #include "deMath.h"
50
51 #include <string>
52
53 namespace vkt
54 {
55 namespace FragmentOperations
56 {
57 namespace
58 {
59 using namespace vk;
60 using de::UniquePtr;
61
62 //! Basic 2D image.
makeImageCreateInfo(const tcu::IVec2 & size,const VkFormat format,const VkImageUsageFlags usage)63 inline VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const VkFormat format, const VkImageUsageFlags usage)
64 {
65 const VkImageCreateInfo imageParams =
66 {
67 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
68 DE_NULL, // const void* pNext;
69 (VkImageCreateFlags)0, // VkImageCreateFlags flags;
70 VK_IMAGE_TYPE_2D, // VkImageType imageType;
71 format, // VkFormat format;
72 makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
73 1u, // deUint32 mipLevels;
74 1u, // deUint32 arrayLayers;
75 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
76 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
77 usage, // VkImageUsageFlags usage;
78 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
79 0u, // deUint32 queueFamilyIndexCount;
80 DE_NULL, // const deUint32* pQueueFamilyIndices;
81 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
82 };
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 enableScissorTest,const bool enableDepthTest,const bool enableStencilTest,const bool enableStencilWrite)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 enableScissorTest,
104 const bool enableDepthTest,
105 const bool enableStencilTest,
106 const bool enableStencilWrite)
107 {
108 const std::vector<VkViewport> viewports (1, makeViewport(renderSize));
109 const std::vector<VkRect2D> scissors (1, enableScissorTest
110 ? makeRect2D(renderSize.x() / 4, renderSize.y() / 4, renderSize.x() / 4 * 2, renderSize.y() / 4 * 2)
111 : makeRect2D(renderSize));
112
113 const VkStencilOpState stencilOpState = makeStencilOpState(VK_STENCIL_OP_KEEP, // stencil fail
114 enableStencilWrite ? VK_STENCIL_OP_REPLACE : VK_STENCIL_OP_KEEP, // depth & stencil pass
115 VK_STENCIL_OP_KEEP, // depth only fail
116 enableStencilWrite ? VK_COMPARE_OP_ALWAYS : VK_COMPARE_OP_EQUAL, // compare op
117 0xff, // compare mask
118 0xff, // write mask
119 enableStencilWrite ? 0u : 1u); // reference
120
121 VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
122 {
123 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
124 DE_NULL, // const void* pNext
125 0u, // VkPipelineDepthStencilStateCreateFlags flags
126 enableDepthTest ? VK_TRUE : VK_FALSE, // VkBool32 depthTestEnable
127 enableDepthTest ? VK_TRUE : VK_FALSE, // VkBool32 depthWriteEnable
128 VK_COMPARE_OP_LESS, // VkCompareOp depthCompareOp
129 VK_FALSE, // VkBool32 depthBoundsTestEnable
130 enableStencilTest ? VK_TRUE : VK_FALSE, // VkBool32 stencilTestEnable
131 enableStencilTest ? stencilOpState : VkStencilOpState{}, // VkStencilOpState front
132 enableStencilTest ? stencilOpState : VkStencilOpState{}, // VkStencilOpState back
133 0.0f, // float minDepthBounds
134 1.0f // float maxDepthBounds
135 };
136
137 return vk::makeGraphicsPipeline(vk, // const DeviceInterface& vk
138 device, // const VkDevice device
139 pipelineLayout, // const VkPipelineLayout pipelineLayout
140 vertexModule, // const VkShaderModule vertexShaderModule
141 DE_NULL, // const VkShaderModule tessellationControlModule
142 DE_NULL, // const VkShaderModule tessellationEvalModule
143 DE_NULL, // const VkShaderModule geometryShaderModule
144 fragmentModule, // const VkShaderModule fragmentShaderModule
145 renderPass, // const VkRenderPass renderPass
146 viewports, // const std::vector<VkViewport>& viewports
147 scissors, // const std::vector<VkRect2D>& scissors
148 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
149 0u, // const deUint32 subpass
150 0u, // const deUint32 patchControlPoints
151 DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
152 DE_NULL, // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
153 DE_NULL, // const VkPipelineMultisampleStateCreateInfo* multisampleStateCreateInfo
154 &depthStencilStateCreateInfo); // const VkPipelineDepthStencilStateCreateInfo* depthStencilStateCreateInfo
155 }
156
commandClearDepthAttachment(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkOffset2D & offset,const VkExtent2D & extent,const deUint32 clearValue)157 void commandClearDepthAttachment (const DeviceInterface& vk,
158 const VkCommandBuffer commandBuffer,
159 const VkOffset2D& offset,
160 const VkExtent2D& extent,
161 const deUint32 clearValue)
162 {
163 const VkClearAttachment depthAttachment =
164 {
165 VK_IMAGE_ASPECT_DEPTH_BIT, // VkImageAspectFlags aspectMask;
166 0u, // uint32_t colorAttachment;
167 makeClearValueDepthStencil(0.0f, clearValue), // VkClearValue clearValue;
168 };
169
170 const VkClearRect rect =
171 {
172 { offset, extent }, // VkRect2D rect;
173 0u, // uint32_t baseArrayLayer;
174 1u, // uint32_t layerCount;
175 };
176
177 vk.cmdClearAttachments(commandBuffer, 1u, &depthAttachment, 1u, &rect);
178 }
179
commandClearStencilAttachment(const DeviceInterface & vk,const VkCommandBuffer commandBuffer,const VkOffset2D & offset,const VkExtent2D & extent,const deUint32 clearValue)180 void commandClearStencilAttachment (const DeviceInterface& vk,
181 const VkCommandBuffer commandBuffer,
182 const VkOffset2D& offset,
183 const VkExtent2D& extent,
184 const deUint32 clearValue)
185 {
186 const VkClearAttachment stencilAttachment =
187 {
188 VK_IMAGE_ASPECT_STENCIL_BIT, // VkImageAspectFlags aspectMask;
189 0u, // uint32_t colorAttachment;
190 makeClearValueDepthStencil(0.0f, clearValue), // VkClearValue clearValue;
191 };
192
193 const VkClearRect rect =
194 {
195 { offset, extent }, // VkRect2D rect;
196 0u, // uint32_t baseArrayLayer;
197 1u, // uint32_t layerCount;
198 };
199
200 vk.cmdClearAttachments(commandBuffer, 1u, &stencilAttachment, 1u, &rect);
201 }
202
getImageAspectFlags(const VkFormat format)203 VkImageAspectFlags getImageAspectFlags (const VkFormat format)
204 {
205 const tcu::TextureFormat tcuFormat = mapVkFormat(format);
206
207 if (tcuFormat.order == tcu::TextureFormat::DS) return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
208 else if (tcuFormat.order == tcu::TextureFormat::D) return VK_IMAGE_ASPECT_DEPTH_BIT;
209 else if (tcuFormat.order == tcu::TextureFormat::S) return VK_IMAGE_ASPECT_STENCIL_BIT;
210
211 DE_ASSERT(false);
212 return 0u;
213 }
214
isSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device,const VkFormat format)215 bool isSupportedDepthStencilFormat (const InstanceInterface& instanceInterface, const VkPhysicalDevice device, const VkFormat format)
216 {
217 VkFormatProperties formatProps;
218 instanceInterface.getPhysicalDeviceFormatProperties(device, format, &formatProps);
219 return (formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0;
220 }
221
pickSupportedDepthStencilFormat(const InstanceInterface & instanceInterface,const VkPhysicalDevice device)222 VkFormat pickSupportedDepthStencilFormat (const InstanceInterface& instanceInterface,
223 const VkPhysicalDevice device)
224 {
225 static const VkFormat dsFormats[] =
226 {
227 VK_FORMAT_D16_UNORM_S8_UINT,
228 VK_FORMAT_D24_UNORM_S8_UINT,
229 VK_FORMAT_D32_SFLOAT_S8_UINT,
230 };
231
232 for (deUint32 i = 0; i < DE_LENGTH_OF_ARRAY(dsFormats); ++i)
233 if (isSupportedDepthStencilFormat(instanceInterface, device, dsFormats[i]))
234 return dsFormats[i];
235
236 return VK_FORMAT_UNDEFINED;
237 }
238
239 enum Flags
240 {
241 TEST_NO_FLAGS = 0,
242 TEST_SCISSOR = 1u << 0,
243 TEST_DEPTH_WRITE = 1u << 1,
244 TEST_DEPTH_CLEAR = 1u << 2,
245 TEST_STENCIL_WRITE = 1u << 3,
246 TEST_STENCIL_CLEAR = 1u << 4,
247 TEST_ALL = 1u << 5,
248 TEST_PRECISE_BIT = 1u << 6
249 };
250
251 class OcclusionQueryTestInstance : public TestInstance
252 {
253 public:
254 OcclusionQueryTestInstance (Context& context,
255 const tcu::IVec2 renderSize,
256 const bool preciseBitEnabled,
257 const bool scissorTestEnabled,
258 const bool depthTestEnabled,
259 const bool stencilTestEnabled,
260 const bool depthWriteEnabled,
261 const bool stencilWriteEnabled);
262
263 tcu::TestStatus iterate (void);
264
265 private:
266 const tcu::IVec2 m_renderSize;
267 const bool m_preciseBitEnabled;
268 const bool m_scissorTestEnabled;
269 const bool m_depthClearTestEnabled;
270 const bool m_stencilClearTestEnabled;
271 const bool m_depthWriteTestEnabled;
272 const bool m_stencilWriteTestEnabled;
273 };
274
OcclusionQueryTestInstance(Context & context,const tcu::IVec2 renderSize,const bool preciseBitEnabled,const bool scissorTestEnabled,const bool depthClearTestEnabled,const bool stencilClearTestEnabled,const bool depthWriteTestEnabled,const bool stencilWriteTestEnabled)275 OcclusionQueryTestInstance::OcclusionQueryTestInstance (Context& context,
276 const tcu::IVec2 renderSize,
277 const bool preciseBitEnabled,
278 const bool scissorTestEnabled,
279 const bool depthClearTestEnabled,
280 const bool stencilClearTestEnabled,
281 const bool depthWriteTestEnabled,
282 const bool stencilWriteTestEnabled)
283 : TestInstance (context)
284 , m_renderSize (renderSize)
285 , m_preciseBitEnabled (preciseBitEnabled)
286 , m_scissorTestEnabled (scissorTestEnabled)
287 , m_depthClearTestEnabled (depthClearTestEnabled)
288 , m_stencilClearTestEnabled (stencilClearTestEnabled)
289 , m_depthWriteTestEnabled (depthWriteTestEnabled)
290 , m_stencilWriteTestEnabled (stencilWriteTestEnabled)
291 {
292 }
293
iterate(void)294 tcu::TestStatus OcclusionQueryTestInstance::iterate (void)
295 {
296 const DeviceInterface& vk = m_context.getDeviceInterface();
297 const InstanceInterface& vki = m_context.getInstanceInterface();
298 const VkDevice device = m_context.getDevice();
299 const VkPhysicalDevice physDevice = m_context.getPhysicalDevice();
300 const VkQueue queue = m_context.getUniversalQueue();
301 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
302 Allocator& allocator = m_context.getDefaultAllocator();
303 VkQueryPool queryPool;
304 const deUint32 queryCount = 1u;
305 std::vector<VkDeviceSize> sampleCounts (queryCount);
306
307 // Create a query pool for storing the occlusion query result
308 {
309 VkQueryPoolCreateInfo queryPoolInfo
310 {
311 VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, // VkStructureType sType;
312 DE_NULL, // const void* pNext;
313 (VkQueryPoolCreateFlags)0, // VkQueryPoolCreateFlags flags;
314 VK_QUERY_TYPE_OCCLUSION, // VkQueryType queryType;
315 queryCount, // uint32_t queryCount;
316 0u, // VkQueryPipelineStatisticFlags pipelineStatistics;
317 };
318 VK_CHECK(vk.createQueryPool(device, &queryPoolInfo, NULL, &queryPool));
319 }
320
321 // Color attachment
322 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
323 const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
324 const Unique<VkImage> colorImage (makeImage(vk, device, makeImageCreateInfo(m_renderSize, colorFormat, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
325 const UniquePtr<Allocation> colorImageAlloc (bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any));
326 const Unique<VkImageView> colorImageView (makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange));
327
328 std::vector<VkImageView> attachmentImages = { *colorImageView };
329
330 bool depthTestsEnabled = (m_depthClearTestEnabled || m_depthWriteTestEnabled);
331 bool stencilTestsEnabled = (m_stencilClearTestEnabled || m_stencilWriteTestEnabled);
332
333 const VkFormat testFormat = (depthTestsEnabled && stencilTestsEnabled
334 ? pickSupportedDepthStencilFormat(vki, physDevice)
335 : !depthTestsEnabled && stencilTestsEnabled
336 ? VK_FORMAT_S8_UINT
337 : VK_FORMAT_D16_UNORM);
338
339 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Using depth/stencil format " << getFormatName(testFormat) << tcu::TestLog::EndMessage;
340
341 const VkImageSubresourceRange testSubresourceRange = makeImageSubresourceRange(getImageAspectFlags(testFormat), 0u, 1u, 0u, 1u);
342 const Unique<VkImage> testImage(makeImage(vk, device, makeImageCreateInfo(m_renderSize, testFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)));
343 const UniquePtr<Allocation> testImageAlloc(bindImage(vk, device, allocator, *testImage, MemoryRequirement::Any));
344 const Unique<VkImageView> testImageView(makeImageView(vk, device, *testImage, VK_IMAGE_VIEW_TYPE_2D, testFormat, testSubresourceRange));
345
346 if (depthTestsEnabled || stencilTestsEnabled)
347 attachmentImages.push_back(*testImageView);
348
349 const deUint32 numUsedAttachmentImages = deUint32(attachmentImages.size());
350
351 // Depth occluder vertex buffer
352 const deUint32 numDepthOccVertices = 6;
353 const VkDeviceSize dOccVertBuffSizeBytes = 256;
354 const Unique<VkBuffer> dOccluderVertexBuffer (makeBuffer(vk, device, dOccVertBuffSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
355 const UniquePtr<Allocation> dOccVertexBufferAlloc (bindBuffer(vk, device, allocator, *dOccluderVertexBuffer, MemoryRequirement::HostVisible));
356
357 {
358 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(dOccVertexBufferAlloc->getHostPtr());
359
360 pVertices[0] = tcu::Vec4(-0.25f, -0.50f , 0.0f, 1.0f); // Top Right
361 pVertices[1] = tcu::Vec4(-0.50f, -0.50f , 0.0f, 1.0f); // Top Left
362 pVertices[2] = tcu::Vec4(-0.25f, -0.25f, 0.0f, 1.0f); // Bottom Right
363 pVertices[3] = tcu::Vec4(-0.50f, -0.25f, 0.0f, 1.0f); // Bottom Left
364 pVertices[4] = tcu::Vec4(-0.25f, -0.25f, 0.0f, 1.0f); // Bottom Right
365 pVertices[5] = tcu::Vec4(-0.50f, -0.50f, 0.0f, 1.0f); // Top Left
366
367 flushAlloc(vk, device, *dOccVertexBufferAlloc);
368 }
369
370 // Stencil occluder vertex buffer
371 const deUint32 numStencilOccVertices = 6;
372 const VkDeviceSize sOccVertBuffSizeBytes = 256;
373 const Unique<VkBuffer> sOccluderVertexBuffer (makeBuffer(vk, device, sOccVertBuffSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
374 const UniquePtr<Allocation> sOccVertexBufferAlloc (bindBuffer(vk, device, allocator, *sOccluderVertexBuffer, MemoryRequirement::HostVisible));
375
376 {
377 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(sOccVertexBufferAlloc->getHostPtr());
378
379 pVertices[0] = tcu::Vec4(-0.25f, -0.25f, 0.0f, 1.0f); // Top Right
380 pVertices[1] = tcu::Vec4(-0.50f, -0.25f, 0.0f, 1.0f); // Top Left
381 pVertices[2] = tcu::Vec4(-0.25f, 0.00f, 0.0f, 1.0f); // Bottom Right
382 pVertices[3] = tcu::Vec4(-0.50f, 0.00f, 0.0f, 1.0f); // Bottom Left
383 pVertices[4] = tcu::Vec4(-0.25f, 0.00f, 0.0f, 1.0f); // Bottom Right
384 pVertices[5] = tcu::Vec4(-0.50f, -0.25f, 0.0f, 1.0f); // Top Left
385
386 flushAlloc(vk, device, *sOccVertexBufferAlloc);
387 }
388
389 // Main vertex buffer
390 const deUint32 numVertices = 6;
391 const VkDeviceSize vertexBufferSizeBytes = 256;
392 const Unique<VkBuffer> vertexBuffer (makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
393 const UniquePtr<Allocation> vertexBufferAlloc (bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
394
395 {
396 tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());
397
398 pVertices[0] = tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f);
399 pVertices[1] = tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
400 pVertices[2] = tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f);
401 pVertices[3] = tcu::Vec4(-1.0f, 1.0f, 1.0f, 1.0f);
402 pVertices[4] = tcu::Vec4( 1.0f, 1.0f, 1.0f, 1.0f);
403 pVertices[5] = tcu::Vec4( 1.0f, -1.0f, 1.0f, 1.0f);
404
405 flushAlloc(vk, device, *vertexBufferAlloc);
406 }
407
408 // Render result buffer (to retrieve color attachment contents)
409 const VkDeviceSize colorBufferSizeBytes = tcu::getPixelSize(mapVkFormat(colorFormat)) * m_renderSize.x() * m_renderSize.y();
410 const Unique<VkBuffer> colorBuffer (makeBuffer(vk, device, colorBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
411 const UniquePtr<Allocation> colorBufferAlloc (bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
412
413 // Pipeline
414 const Unique<VkShaderModule> vertexModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
415 const Unique<VkShaderModule> fragmentModule (createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
416 const Unique<VkRenderPass> renderPass (makeRenderPass(vk, device, colorFormat, (depthTestsEnabled || stencilTestsEnabled), testFormat));
417 const Unique<VkFramebuffer> framebuffer (makeFramebuffer(vk, device, *renderPass, numUsedAttachmentImages, attachmentImages.data(), m_renderSize.x(), m_renderSize.y()));
418 const Unique<VkPipelineLayout> pipelineLayout (makePipelineLayout(vk, device, DE_NULL));
419 const Unique<VkPipeline> pipeline (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, m_renderSize,
420 m_scissorTestEnabled, depthTestsEnabled, stencilTestsEnabled, false));
421
422 const Unique<VkPipeline> pipelineStencilWrite (makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, m_renderSize,
423 m_scissorTestEnabled, false, stencilTestsEnabled, true));
424
425 // Command buffer
426 const Unique<VkCommandPool> cmdPool (createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
427 const Unique<VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
428
429 {
430 const tcu::Vec4 clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
431 const float clearDepth = 0.5f;
432 const deUint32 clearStencil = 1u;
433 const VkDeviceSize vertexBufferOffset = 0ull;
434
435 const VkRect2D renderArea =
436 {
437 makeOffset2D(0, 0),
438 makeExtent2D(m_renderSize.x(), m_renderSize.y()),
439 };
440
441 beginCommandBuffer(vk, *cmdBuffer);
442
443 vk.cmdResetQueryPool(*cmdBuffer, queryPool, 0, queryCount);
444
445 // Will clear the attachments with specified depth and stencil values.
446 beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, renderArea, clearColor, clearDepth, clearStencil);
447
448 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
449
450 // Mask half of the attachment image with value that will pass the stencil test.
451 if (m_depthClearTestEnabled)
452 commandClearDepthAttachment(vk, *cmdBuffer, makeOffset2D(0, m_renderSize.y() / 2), makeExtent2D(m_renderSize.x(), m_renderSize.y() / 2), 1u);
453
454 // Mask half of the attachment image with value that will pass the stencil test.
455 if (m_stencilClearTestEnabled)
456 commandClearStencilAttachment(vk, *cmdBuffer, makeOffset2D(m_renderSize.x() / 2, 0), makeExtent2D(m_renderSize.x() / 2, m_renderSize.y()), 0u);
457
458 if (m_depthWriteTestEnabled)
459 {
460 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &dOccluderVertexBuffer.get(), &vertexBufferOffset);
461 vk.cmdDraw(*cmdBuffer, numDepthOccVertices, 1u, 0u, 0u);
462 }
463
464 if (m_stencilWriteTestEnabled)
465 {
466 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineStencilWrite);
467 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &sOccluderVertexBuffer.get(), &vertexBufferOffset);
468 vk.cmdDraw(*cmdBuffer, numStencilOccVertices, 1u, 0u, 0u);
469 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
470 }
471
472 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
473
474 if (m_preciseBitEnabled)
475 {
476 vk.cmdBeginQuery(cmdBuffer.get(), queryPool, 0, VK_QUERY_CONTROL_PRECISE_BIT);
477 }
478 else
479 {
480 vk.cmdBeginQuery(cmdBuffer.get(), queryPool, 0, DE_NULL);
481 }
482
483 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
484 vk.cmdEndQuery(cmdBuffer.get(), queryPool, 0);
485
486 endRenderPass(vk, *cmdBuffer);
487
488 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, m_renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
489
490 endCommandBuffer(vk, *cmdBuffer);
491 submitCommandsAndWait(vk, device, queue, *cmdBuffer);
492 }
493
494 // Check results
495 {
496 deUint64 expResult = 0;
497
498 if (m_preciseBitEnabled)
499 {
500 const deUint64 imageSize = m_scissorTestEnabled ? deUint64(m_renderSize.x()) * deUint64(m_renderSize.y()) / 4u
501 : deUint64(m_renderSize.x()) * deUint64(m_renderSize.y());
502
503 const deUint64 renderHeight = m_scissorTestEnabled ? deUint64(m_renderSize.y() / 2u)
504 : deUint64(m_renderSize.y());
505
506 const deUint64 occluderWriteSize = deUint64(m_renderSize.x()) * deUint64(m_renderSize.y()) / 64u;
507
508 if (m_depthClearTestEnabled || m_stencilClearTestEnabled)
509 {
510 if (m_depthClearTestEnabled && m_stencilClearTestEnabled)
511 {
512 expResult = imageSize / 4;
513 }
514
515 if (!m_depthClearTestEnabled && m_stencilClearTestEnabled)
516 {
517 expResult = imageSize / 2;
518 }
519
520 if (m_depthClearTestEnabled && !m_stencilClearTestEnabled)
521 {
522 expResult = imageSize / 2 - imageSize / 8 - renderHeight / 4;
523 }
524 }
525 else if (m_depthWriteTestEnabled)
526 {
527 expResult = imageSize / 2 - renderHeight / 2;
528 }
529 else
530 {
531 expResult = imageSize;
532 }
533
534 if (m_depthWriteTestEnabled)
535 {
536 expResult -= occluderWriteSize;
537
538 if (m_stencilClearTestEnabled && !m_depthClearTestEnabled)
539 {
540 expResult -= (imageSize / 8 + renderHeight / 4);
541 }
542 }
543
544 if (m_stencilWriteTestEnabled)
545 {
546 expResult -= occluderWriteSize;
547 }
548 }
549
550 VK_CHECK(vk.getQueryPoolResults(device, queryPool, 0u, queryCount, queryCount * sizeof(VkDeviceSize), sampleCounts.data(), sizeof(VkDeviceSize), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT));
551
552 // Log test results
553 {
554 tcu::TestLog& log = m_context.getTestContext().getLog();
555 log << tcu::TestLog::Message << "Passed Samples : " << de::toString(sampleCounts[0]) << " / " << expResult << tcu::TestLog::EndMessage;
556 }
557
558 #ifndef CTS_USES_VULKANSC
559 vk.destroyQueryPool(device, queryPool, nullptr);
560 #endif // CTS_USES_VULKANSC
561
562 if ((m_preciseBitEnabled && sampleCounts[0] == expResult) || (!m_preciseBitEnabled && sampleCounts[0] > 0))
563 {
564 return tcu::TestStatus::pass("Success");
565 }
566 else
567 {
568
569 invalidateAlloc(vk, device, *colorBufferAlloc);
570
571 const tcu::ConstPixelBufferAccess imagePixelAccess (mapVkFormat(colorFormat), m_renderSize.x(), m_renderSize.y(), 1, colorBufferAlloc->getHostPtr());
572 tcu::TestLog& log = m_context.getTestContext().getLog();
573
574 log << tcu::TestLog::Image("color0", "Rendered image", imagePixelAccess);
575
576 return tcu::TestStatus::fail("Failure");
577 }
578 }
579 }
580
581 class OcclusionQueryTest : public TestCase
582 {
583 public:
584 OcclusionQueryTest (tcu::TestContext& testCtx,
585 const std::string name,
586 const deUint32 flags,
587 const int renderWidth,
588 const int renderHeight);
589
590 void initPrograms (SourceCollections& programCollection) const;
591 TestInstance* createInstance (Context& context) const;
592 virtual void checkSupport (Context& context) const;
593
594 private:
595 const bool m_preciseBitEnabled;
596 const bool m_scissorTestEnabled;
597 const bool m_depthClearTestEnabled;
598 const bool m_stencilClearTestEnabled;
599 const bool m_depthWriteTestEnabled;
600 const bool m_stencilWriteTestEnabled;
601 const int m_renderWidth;
602 const int m_renderHeight;
603 };
604
OcclusionQueryTest(tcu::TestContext & testCtx,const std::string name,const deUint32 flags,const int renderWidth,const int renderHeight)605 OcclusionQueryTest::OcclusionQueryTest (tcu::TestContext& testCtx, const std::string name, const deUint32 flags, const int renderWidth, const int renderHeight)
606 : TestCase (testCtx, name, "")
607 , m_preciseBitEnabled (flags & TEST_PRECISE_BIT)
608 , m_scissorTestEnabled (flags & TEST_SCISSOR)
609 , m_depthClearTestEnabled (flags & TEST_DEPTH_CLEAR || flags & TEST_ALL)
610 , m_stencilClearTestEnabled (flags & TEST_STENCIL_CLEAR || flags & TEST_ALL)
611 , m_depthWriteTestEnabled (flags & TEST_DEPTH_WRITE || flags & TEST_ALL)
612 , m_stencilWriteTestEnabled (flags & TEST_STENCIL_WRITE || flags & TEST_ALL)
613 , m_renderWidth (renderWidth)
614 , m_renderHeight (renderHeight)
615 {
616 }
617
initPrograms(SourceCollections & programCollection) const618 void OcclusionQueryTest::initPrograms (SourceCollections& programCollection) const
619 {
620 // Vertex
621 {
622 std::ostringstream src;
623
624 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
625 << "\n"
626 << "layout(location = 0) in highp vec4 position;\n"
627 << "\n"
628 << "out gl_PerVertex\n"
629 << "{\n"
630 << " vec4 gl_Position;\n"
631 << "};\n"
632 << "\n"
633 << "void main (void)\n"
634 << "{\n"
635 << " gl_Position = position;\n"
636 << "}\n";
637
638 programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
639 }
640
641 // Fragment
642 {
643 std::ostringstream src;
644
645 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
646 << "\n"
647 << "layout(location = 0) out highp vec4 fragColor;\n"
648 << "\n"
649 << "void main (void)\n"
650 << "{\n"
651 << " fragColor = vec4(gl_FragCoord.x / " << m_renderWidth << ", gl_FragCoord.y / " << m_renderHeight << ", 0.0, 1.0); \n"
652 << "}\n";
653
654 programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
655 }
656 }
657
createInstance(Context & context) const658 TestInstance* OcclusionQueryTest::createInstance (Context& context) const
659 {
660 return new OcclusionQueryTestInstance (context, tcu::IVec2(m_renderWidth, m_renderHeight),
661 m_preciseBitEnabled, m_scissorTestEnabled,
662 m_depthClearTestEnabled, m_stencilClearTestEnabled,
663 m_depthWriteTestEnabled, m_stencilWriteTestEnabled);
664 }
665
checkSupport(Context & context) const666 void OcclusionQueryTest::checkSupport (Context& context) const
667 {
668 const InstanceInterface& vki = context.getInstanceInterface();
669 const VkPhysicalDevice physDevice = context.getPhysicalDevice();
670 VkImageFormatProperties formatProperties;
671
672 bool depthTestsEnabled = (m_depthClearTestEnabled || m_depthWriteTestEnabled);
673 bool stencilTestsEnabled = (m_stencilClearTestEnabled || m_stencilWriteTestEnabled);
674
675 const VkFormat testFormat = (stencilTestsEnabled && depthTestsEnabled
676 ? pickSupportedDepthStencilFormat(vki, physDevice)
677 : stencilTestsEnabled
678 ? VK_FORMAT_S8_UINT
679 : VK_FORMAT_D16_UNORM);
680
681 if (m_preciseBitEnabled)
682 {
683 vk::VkQueryControlFlags queryControlFlags = { VK_QUERY_CONTROL_PRECISE_BIT };
684
685 if (queryControlFlags && vk::VK_QUERY_CONTROL_PRECISE_BIT != context.getDeviceFeatures().occlusionQueryPrecise)
686 TCU_THROW(NotSupportedError, "Precise occlusion queries are not supported");
687 }
688
689 vki.getPhysicalDeviceImageFormatProperties(physDevice, testFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, 0u, &formatProperties);
690 if (formatProperties.sampleCounts == 0 || testFormat == VK_FORMAT_UNDEFINED)
691 TCU_THROW(NotSupportedError, de::toString(testFormat) + " not supported");
692 }
693
694 } // anonymous ns
695
createOcclusionQueryTests(tcu::TestContext & testCtx)696 tcu::TestCaseGroup* createOcclusionQueryTests(tcu::TestContext& testCtx)
697 {
698 de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "occlusion_query", "occlusion query test cases"));
699
700 {
701 static const struct
702 {
703 std::string caseName;
704 deUint32 flags;
705 } cases[] =
706 {
707 { "_test_scissors_clear_color", TEST_SCISSOR },
708 { "_test_scissors_depth_clear", TEST_SCISSOR | TEST_DEPTH_CLEAR },
709 { "_test_scissors_depth_write", TEST_SCISSOR | TEST_DEPTH_WRITE },
710 { "_test_scissors_depth_clear_depth_write", TEST_SCISSOR | TEST_DEPTH_CLEAR | TEST_DEPTH_WRITE },
711 { "_test_scissors_stencil_clear", TEST_SCISSOR | TEST_STENCIL_CLEAR },
712 { "_test_scissors_stencil_write", TEST_SCISSOR | TEST_STENCIL_WRITE },
713 { "_test_scissors_stencil_clear_stencil_write", TEST_SCISSOR | TEST_STENCIL_CLEAR | TEST_STENCIL_WRITE },
714 { "_test_scissors_depth_clear_stencil_clear", TEST_SCISSOR | TEST_DEPTH_CLEAR | TEST_STENCIL_CLEAR },
715 { "_test_scissors_depth_write_stencil_clear", TEST_SCISSOR | TEST_DEPTH_WRITE | TEST_STENCIL_CLEAR },
716 { "_test_scissors_depth_clear_stencil_write", TEST_SCISSOR | TEST_DEPTH_CLEAR | TEST_STENCIL_WRITE },
717 { "_test_scissors_depth_write_stencil_write", TEST_SCISSOR | TEST_DEPTH_WRITE | TEST_STENCIL_WRITE },
718 { "_test_scissors_depth_clear_stencil_clear_depth_write", TEST_SCISSOR | TEST_DEPTH_CLEAR | TEST_DEPTH_WRITE | TEST_STENCIL_CLEAR },
719 { "_test_scissors_depth_clear_stencil_clear_stencil_write", TEST_SCISSOR | TEST_DEPTH_CLEAR | TEST_STENCIL_CLEAR | TEST_STENCIL_WRITE },
720 { "_test_scissors_depth_clear_depth_write_stencil_write", TEST_SCISSOR | TEST_DEPTH_CLEAR | TEST_DEPTH_WRITE | TEST_STENCIL_WRITE },
721 { "_test_scissors_depth_write_stencil_clear_stencil_write", TEST_SCISSOR | TEST_DEPTH_WRITE | TEST_STENCIL_CLEAR | TEST_STENCIL_WRITE },
722 { "_test_scissors_test_all", TEST_SCISSOR | TEST_ALL },
723 { "_test_clear_color", TEST_NO_FLAGS },
724 { "_test_depth_clear", TEST_DEPTH_CLEAR },
725 { "_test_depth_write", TEST_DEPTH_WRITE },
726 { "_test_depth_clear_depth_write", TEST_DEPTH_CLEAR | TEST_DEPTH_WRITE },
727 { "_test_stencil_clear", TEST_STENCIL_CLEAR },
728 { "_test_stencil_write", TEST_STENCIL_WRITE },
729 { "_test_stencil_clear_stencil_write", TEST_STENCIL_CLEAR | TEST_STENCIL_WRITE },
730 { "_test_depth_clear_stencil_clear", TEST_DEPTH_CLEAR | TEST_STENCIL_CLEAR },
731 { "_test_depth_write_stencil_clear", TEST_DEPTH_WRITE | TEST_STENCIL_CLEAR },
732 { "_test_depth_clear_stencil_write", TEST_DEPTH_CLEAR | TEST_STENCIL_WRITE },
733 { "_test_depth_write_stencil_write", TEST_DEPTH_WRITE | TEST_STENCIL_WRITE },
734 { "_test_depth_clear_stencil_clear_depth_write", TEST_DEPTH_CLEAR | TEST_DEPTH_WRITE | TEST_STENCIL_CLEAR },
735 { "_test_depth_clear_stencil_clear_stencil_write", TEST_DEPTH_CLEAR | TEST_STENCIL_CLEAR | TEST_STENCIL_WRITE },
736 { "_test_depth_clear_depth_write_stencil_write", TEST_DEPTH_CLEAR | TEST_DEPTH_WRITE | TEST_STENCIL_WRITE },
737 { "_test_depth_write_stencil_clear_stencil_write", TEST_DEPTH_WRITE | TEST_STENCIL_CLEAR | TEST_STENCIL_WRITE },
738 { "_test_test_all", TEST_ALL }
739 };
740
741 // Conservative tests
742 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
743 testGroup->addChild(new OcclusionQueryTest(testCtx, "conservative" + cases[i].caseName, cases[i].flags, 32, 32));
744
745 // Precise tests
746 for (int i = 0; i < DE_LENGTH_OF_ARRAY(cases); ++i)
747 testGroup->addChild(new OcclusionQueryTest(testCtx, "precise" + cases[i].caseName, cases[i].flags | TEST_PRECISE_BIT, 32, 32));
748 }
749
750 return testGroup.release();
751 }
752
753 } // FragmentOperations
754 } // vkt
755