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