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