1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2023 The Khronos Group Inc.
6 * Copyright (c) 2023 Valve Corporation
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 VK_EXT_dynamic_rendering_unused_attachments Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktDynamicRenderingUnusedAttachmentsTests.hpp"
26 #include "vktTestCase.hpp"
27
28 #include "vkImageUtil.hpp"
29 #include "vkQueryUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vkBarrierUtil.hpp"
33
34 #include "tcuStringTemplate.hpp"
35 #include "tcuImageCompare.hpp"
36 #include "tcuTextureUtil.hpp"
37
38 #include <string>
39 #include <sstream>
40 #include <vector>
41 #include <memory>
42 #include <bitset>
43 #include <algorithm>
44 #include <iterator>
45 #include <iomanip>
46
47 namespace vkt
48 {
49 namespace renderpass
50 {
51
52 namespace
53 {
54
55 using namespace vk;
56
57 static constexpr VkFormat kColorFormat = VK_FORMAT_R8G8B8A8_UINT;
58 static constexpr VkFormat kBadColorFormat = VK_FORMAT_R32G32B32A32_UINT;
59
getDSFormatList(void)60 std::vector<VkFormat> getDSFormatList (void)
61 {
62 // The spec mandates support for one of these two formats.
63 static const VkFormat kDSFormatList[] = { VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT };
64 return std::vector<VkFormat>(kDSFormatList, kDSFormatList + de::arrayLength(kDSFormatList));
65 }
66
67 // Find a suitable format for the depth/stencil buffer.
chooseDepthStencilFormat(const InstanceInterface & vki,VkPhysicalDevice physDev)68 VkFormat chooseDepthStencilFormat (const InstanceInterface& vki, VkPhysicalDevice physDev)
69 {
70 const auto candidates = getDSFormatList();
71
72 for (const auto& format : candidates)
73 {
74 const auto properties = getPhysicalDeviceFormatProperties(vki, physDev, format);
75 if ((properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0u)
76 return format;
77 }
78
79 TCU_FAIL("No suitable depth/stencil format found");
80 return VK_FORMAT_UNDEFINED; // Unreachable.
81 }
82
83 // Return a different depth/stencil format from the one chosen.
chooseAltDSFormat(VkFormat chosenFormat)84 VkFormat chooseAltDSFormat (VkFormat chosenFormat)
85 {
86 const auto candidates = getDSFormatList();
87
88 for (const auto& format : candidates)
89 {
90 if (format != chosenFormat)
91 return format;
92 }
93
94 DE_ASSERT(false);
95 return candidates.at(0u);
96 }
97
98 struct TestParams
99 {
100 static constexpr uint32_t kMaxFragAttachments = 8u; // Based on real-world maxFragmentOutputAttachments values.
101 static constexpr uint32_t kMaxFramebufferAttachments = 2u * kMaxFragAttachments; // Slightly arbitrary, based on the previous number.
102
103 const uint32_t pipeFBAttachmentCount; // Number of attachments specified in the pipeline and framebuffer (VUID-vkCmdDraw-colorAttachmentCount-06179).
104 const uint32_t fragAttachmentCount; // Frag shader outputs. Needs to be >= pipeFBAttachmentCount.
105
106 const uint32_t layerCount; // Image layers.
107 const uint32_t layerMask; // Which layers are going to be written to, either using viewMask or manual calls.
108 const bool multiView; // Manual or "automatic" layer handling.
109
110 const uint32_t formatMask; // Which attachments will have VK_FORMAT_UNDEFINED in the pipeline (0 for undefined, 1 for defined).
111 const uint32_t framebufferMask; // Which attachments will be VK_NULL_HANDLE in the framebuffer (0 for null, 1 for valid handle).
112
113 const bool depthPresent; // Create the pipeline with a depth attachment or not.
114 const bool depthDefined; // Make the depth attachment have VK_FORMAT_UNDEFINED in the pipeline or not.
115 const bool depthValidHandle; // Make the depth attachment be VK_NULL_HANDLE in the framebuffer or not.
116
117 const bool stencilPresent; // Create the pipeline with a stencil attachment or not.
118 const bool stencilDefined; // Make the stencil attachment have VK_FORMAT_UNDEFINED in the pipeline or not.
119 const bool stencilValidHandle; // Make the stencil attachment be VK_NULL_HANDLE in the framebuffer or not.
120
121 const bool useSecondaries; // Use secondary command buffers inside the render pass.
122 const bool wrongFormatWithNullViews; // Use the wrong format value if the image view handle is VK_NULL_HANDLE.
123
TestParamsvkt::renderpass::__anonc4d983010111::TestParams124 TestParams (uint32_t pipeFBAttachmentCount_,
125 uint32_t fragAttachmentCount_,
126 uint32_t layerCount_,
127 uint32_t layerMask_,
128 bool multiView_,
129 uint32_t formatMask_,
130 uint32_t framebufferMask_,
131 bool depthPresent_,
132 bool depthDefined_,
133 bool depthValidHandle_,
134 bool stencilPresent_,
135 bool stencilDefined_,
136 bool stencilValidHandle_,
137 bool useSecondaries_,
138 bool wrongFormatWithNullViews_)
139 : pipeFBAttachmentCount (pipeFBAttachmentCount_)
140 , fragAttachmentCount (fragAttachmentCount_)
141 , layerCount (layerCount_)
142 , layerMask (layerMask_)
143 , multiView (multiView_)
144 , formatMask (formatMask_)
145 , framebufferMask (framebufferMask_)
146 , depthPresent (depthPresent_)
147 , depthDefined (depthDefined_)
148 , depthValidHandle (depthValidHandle_)
149 , stencilPresent (stencilPresent_)
150 , stencilDefined (stencilDefined_)
151 , stencilValidHandle (stencilValidHandle_)
152 , useSecondaries (useSecondaries_)
153 , wrongFormatWithNullViews (wrongFormatWithNullViews_)
154 {
155 DE_ASSERT(fragAttachmentCount <= kMaxFragAttachments);
156 DE_ASSERT(pipeFBAttachmentCount <= kMaxFramebufferAttachments);
157 DE_ASSERT(fragAttachmentCount >= pipeFBAttachmentCount);
158 DE_ASSERT(layerCount >= 1u);
159 }
160
161 private:
getFlagTextvkt::renderpass::__anonc4d983010111::TestParams162 inline const char* getFlagText (bool flag, const char* trueText, const char* falseText) const
163 {
164 return (flag ? trueText : falseText);
165 }
166
getPresentvkt::renderpass::__anonc4d983010111::TestParams167 inline const char* getPresent (bool flag) const { return getFlagText(flag, "yes", "no"); }
getDefinedvkt::renderpass::__anonc4d983010111::TestParams168 inline const char* getDefined (bool flag) const { return getFlagText(flag, "def", "undef"); }
getValidvkt::renderpass::__anonc4d983010111::TestParams169 inline const char* getValid (bool flag) const { return getFlagText(flag, "valid", "null"); }
170
171 public:
getTestNamevkt::renderpass::__anonc4d983010111::TestParams172 std::string getTestName (void) const
173 {
174 // Yes, this is an awfully long string.
175 std::ostringstream testName;
176 testName
177 << "pipe_" << pipeFBAttachmentCount
178 << "_frag_" << fragAttachmentCount
179 << "_layers_" << layerCount
180 << "_mask_0x" << std::hex << std::setfill('0') << std::setw(2) << layerMask
181 << "_formats_0x" << std::hex << std::setfill('0') << std::setw(8) << formatMask
182 << "_handles_0x" << std::hex << std::setfill('0') << std::setw(8) << framebufferMask
183 << "_depth_" << getPresent(depthPresent) << "_" << getDefined(depthDefined) << "_" << getValid(depthValidHandle)
184 << "_stencil_" << getPresent(stencilPresent) << "_" << getDefined(stencilDefined) << "_" << getValid(stencilValidHandle)
185 << (multiView ? "_multiview" : "")
186 //<< (wrongFormatWithNullViews ? "_bad_formats" : "")
187 ;
188 return testName.str();
189 }
190
depthStencilNeededvkt::renderpass::__anonc4d983010111::TestParams191 bool depthStencilNeeded (void) const
192 {
193 return (depthPresent || stencilPresent);
194 }
195
196 // Returns true if the vertex shader has to write to the Layer built-in.
vertExportsLayervkt::renderpass::__anonc4d983010111::TestParams197 bool vertExportsLayer (void) const
198 {
199 return (!multiView && layerCount > 1u);
200 }
201
202 protected:
getFormatVectorForMaskvkt::renderpass::__anonc4d983010111::TestParams203 std::vector<VkFormat> getFormatVectorForMask (const VkFormat colorFormat, const uint32_t bitMask, const uint32_t attachmentCount) const
204 {
205 std::bitset<kMaxFragAttachments> mask (static_cast<unsigned long long>(bitMask));
206 std::vector<VkFormat> formats;
207
208 formats.reserve(attachmentCount);
209 for (uint32_t attIdx = 0u; attIdx < attachmentCount; ++attIdx)
210 formats.push_back(mask[attIdx] ? colorFormat : VK_FORMAT_UNDEFINED);
211
212 return formats;
213 }
214
215 public:
getPipelineFormatVectorvkt::renderpass::__anonc4d983010111::TestParams216 std::vector<VkFormat> getPipelineFormatVector (const VkFormat colorFormat) const
217 {
218 return getFormatVectorForMask(colorFormat, formatMask, pipeFBAttachmentCount);
219 }
220
getInheritanceFormatVectorvkt::renderpass::__anonc4d983010111::TestParams221 std::vector<VkFormat> getInheritanceFormatVector (const VkFormat colorFormat) const
222 {
223 return getFormatVectorForMask(colorFormat, framebufferMask, pipeFBAttachmentCount);
224 }
225
getPipelineDepthFormatvkt::renderpass::__anonc4d983010111::TestParams226 inline VkFormat getPipelineDepthFormat (VkFormat dsFormat) const
227 {
228 return ((depthPresent && depthDefined) ? dsFormat : VK_FORMAT_UNDEFINED);
229 }
230
getInheritanceDepthFormatvkt::renderpass::__anonc4d983010111::TestParams231 inline VkFormat getInheritanceDepthFormat (VkFormat dsFormat) const
232 {
233 return ((depthPresent && depthValidHandle) ? dsFormat : VK_FORMAT_UNDEFINED);
234 }
235
getPipelineStencilFormatvkt::renderpass::__anonc4d983010111::TestParams236 inline VkFormat getPipelineStencilFormat (VkFormat dsFormat) const
237 {
238 return ((stencilPresent && stencilDefined) ? dsFormat : VK_FORMAT_UNDEFINED);
239 }
240
getInheritanceStencilFormatvkt::renderpass::__anonc4d983010111::TestParams241 inline VkFormat getInheritanceStencilFormat (VkFormat dsFormat) const
242 {
243 return ((stencilPresent && stencilValidHandle) ? dsFormat : VK_FORMAT_UNDEFINED);
244 }
245
getClearValuevkt::renderpass::__anonc4d983010111::TestParams246 static VkClearValue getClearValue (void)
247 {
248 VkClearValue clearValue;
249 deMemset(&clearValue, 0, sizeof(clearValue));
250 return clearValue;
251 }
252
getRenderingAttachmentInfosvkt::renderpass::__anonc4d983010111::TestParams253 std::vector<VkRenderingAttachmentInfo> getRenderingAttachmentInfos (const std::vector<VkImageView>& imageViews) const
254 {
255 DE_ASSERT(imageViews.size() == static_cast<size_t>(pipeFBAttachmentCount));
256
257 std::bitset<kMaxFramebufferAttachments> mask (static_cast<unsigned long long>(framebufferMask));
258 const auto clearValue = getClearValue();
259 std::vector<VkRenderingAttachmentInfo> infos;
260
261 infos.reserve(pipeFBAttachmentCount);
262 for (uint32_t attIdx = 0u; attIdx < pipeFBAttachmentCount; ++attIdx)
263 {
264 const auto imgView = (mask[attIdx] ? imageViews.at(attIdx) : VK_NULL_HANDLE);
265
266 infos.push_back(VkRenderingAttachmentInfo{
267 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType sType;
268 nullptr, // const void* pNext;
269 imgView, // VkImageView imageView;
270 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
271 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
272 VK_NULL_HANDLE, // VkImageView resolveImageView;
273 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout;
274 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
275 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
276 clearValue, // VkClearValue clearValue;
277 });
278 }
279
280 return infos;
281 }
282
getDepthAttachmentInfovkt::renderpass::__anonc4d983010111::TestParams283 VkRenderingAttachmentInfo getDepthAttachmentInfo (const VkImageView imageView) const
284 {
285 const auto clearValue = getClearValue();
286 const auto attView = ((depthPresent && depthValidHandle) ? imageView : VK_NULL_HANDLE);
287
288 return VkRenderingAttachmentInfo{
289 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType sType;
290 nullptr, // const void* pNext;
291 attView, // VkImageView imageView;
292 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
293 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
294 VK_NULL_HANDLE, // VkImageView resolveImageView;
295 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout;
296 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
297 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
298 clearValue, // VkClearValue clearValue;
299 };
300 }
301
getStencilAttachmentInfovkt::renderpass::__anonc4d983010111::TestParams302 VkRenderingAttachmentInfo getStencilAttachmentInfo (const VkImageView imageView) const
303 {
304 const auto clearValue = getClearValue();
305 const auto attView = ((stencilPresent && stencilValidHandle) ? imageView : VK_NULL_HANDLE);
306
307 return VkRenderingAttachmentInfo{
308 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType sType;
309 nullptr, // const void* pNext;
310 attView, // VkImageView imageView;
311 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
312 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
313 VK_NULL_HANDLE, // VkImageView resolveImageView;
314 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout;
315 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp;
316 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
317 clearValue, // VkClearValue clearValue;
318 };
319 }
320 };
321
322 class DynamicUnusedAttachmentsInstance : public vkt::TestInstance
323 {
324 public:
DynamicUnusedAttachmentsInstance(Context & context,const TestParams & params)325 DynamicUnusedAttachmentsInstance (Context& context, const TestParams& params)
326 : vkt::TestInstance (context)
327 , m_params (params)
328 {}
~DynamicUnusedAttachmentsInstance(void)329 virtual ~DynamicUnusedAttachmentsInstance (void) {}
330
331 tcu::TestStatus iterate (void) override;
332
333 protected:
334 const TestParams m_params;
335 };
336
337 class DynamicUnusedAttachmentsCase : public vkt::TestCase
338 {
339 public:
DynamicUnusedAttachmentsCase(tcu::TestContext & testCtx,const std::string & name,const TestParams & params)340 DynamicUnusedAttachmentsCase (tcu::TestContext& testCtx, const std::string& name, const TestParams& params)
341 : vkt::TestCase (testCtx, name)
342 , m_params (params)
343 {}
createInstance(Context & context) const344 TestInstance* createInstance (Context& context) const override { return new DynamicUnusedAttachmentsInstance(context, m_params); }
345 void initPrograms (vk::SourceCollections& programCollection) const override;
346 void checkSupport (Context& context) const override;
347
348 protected:
349 const TestParams m_params;
350 };
351
initPrograms(vk::SourceCollections & programCollection) const352 void DynamicUnusedAttachmentsCase::initPrograms (vk::SourceCollections& programCollection) const
353 {
354 const bool vertExportsLayer = m_params.vertExportsLayer();
355
356 std::ostringstream vert;
357 vert
358 << "#version 460\n"
359 << "#extension GL_ARB_shader_viewport_layer_array : enable\n"
360 << "layout (push_constant, std430) uniform PushConstantBlock { int layerIndex; } pc;\n"
361 << "vec2 positions[3] = vec2[](\n"
362 << " vec2(-1.0, -1.0),\n"
363 << " vec2(-1.0, 3.0),\n"
364 << " vec2( 3.0, -1.0)\n"
365 << ");\n"
366 << "void main() {\n"
367 << " gl_Position = vec4(positions[gl_VertexIndex % 3], 1.0, 1.0);\n"
368 << (vertExportsLayer ? " gl_Layer = pc.layerIndex;\n" : "")
369 << "}\n"
370 ;
371 {
372 // This is required by the validation layers for the program to be correct. A SPIR-V 1.0 module that exports the Layer
373 // built-in will use the ShaderViewportIndexLayerEXT capability, which is enabled by the VK_EXT_shader_viewport_index_layer
374 // extension.
375 //
376 // However, in Vulkan 1.2+ the extension was promoted to core and that capability was replaced by the ShaderLayer and
377 // ShaderViewportIndex capabilities, which are enabled by the shaderOutputViewportIndex and shaderOutputLayer features in
378 // VkPhysicalDeviceVulkan12Features. In a Vulkan 1.2+ context, CTS will not enable VK_EXT_shader_viewport_index_layer as
379 // that's part of the core extensions, and will enable the Vulkan 1.2 features instead. These will allow access to the
380 // ShaderLayer and ShaderViewportIndex capabilities, but not the ShaderViewportIndexLayerEXT capability.
381 //
382 // When building the vertex module, glslang will, by default, target SPIR-V 1.0 and create a module that uses the
383 // ShaderViewportIndexLayerEXT capability. When targetting SPIR-V 1.5 explicitly, glslang will generate a module that uses
384 // the ShaderLayer capability.
385 //
386 // We cannot use a SPIR-V 1.0 module in a Vulkan 1.2+ context, because it will use the ShaderViewportIndexLayerEXT
387 // capability, which will not be enabled. In that case, we must use a SPIR-V 1.5 module that depends on the ShaderLayer
388 // capability.
389 //
390 // We cannot use a SPIR-V 1.5 module in a Vulkan <1.2 context, because it will use the ShaderLayer capability, which will
391 // not be enabled. In these cases, we must use a SPIR-V 1.0 module that depends on the ShaderViewportIndexLayerEXT
392 // capability.
393 //
394 // So we need both versions of the vertex shader and we need to choose at runtime.
395 //
396 const auto src = vert.str();
397 const vk::ShaderBuildOptions spv15Opts (programCollection.usedVulkanVersion, vk::SPIRV_VERSION_1_5, 0u, false);
398
399 programCollection.glslSources.add("vert-spv10") << glu::VertexSource(src);
400 programCollection.glslSources.add("vert-spv15") << glu::VertexSource(src) << spv15Opts;
401 }
402
403 // Make sure the fragment shader does not write to any attachment which will have an undefined format in the pipeline.
404 std::vector<bool> fragAttachmentUsed (m_params.fragAttachmentCount, true);
405 const auto pipelineFormats = m_params.getPipelineFormatVector(kColorFormat);
406
407 for (size_t i = 0; i < pipelineFormats.size(); ++i)
408 {
409 if (pipelineFormats[i] == VK_FORMAT_UNDEFINED)
410 fragAttachmentUsed.at(i) = false;
411 }
412
413 std::ostringstream frag;
414
415 frag
416 << "#version 460\n"
417 << "#extension " << (m_params.multiView ? "GL_EXT_multiview" : "GL_ARB_shader_viewport_layer_array") << " : enable\n";
418 ;
419
420 // Color outputs.
421 for (uint32_t i = 0u; i < m_params.fragAttachmentCount; ++i)
422 {
423 if (fragAttachmentUsed.at(i))
424 frag << "layout (location=" << i << ") out uvec4 color" << i << ";\n";
425 }
426
427 const char* layerIndexExpr;
428
429 if (m_params.multiView)
430 layerIndexExpr = "uint(gl_ViewIndex)";
431 else if (vertExportsLayer)
432 layerIndexExpr = "uint(gl_Layer)";
433 else
434 layerIndexExpr = "0u";
435
436 frag
437 << "void main (void) {\n"
438 << " const uint layerIndex = " << layerIndexExpr << ";\n"
439 ;
440
441 for (uint32_t i = 0u; i < m_params.fragAttachmentCount; ++i)
442 {
443 if (fragAttachmentUsed.at(i))
444 frag << " color" << i << " = uvec4(layerIndex, 255, " << i << ", 255);\n";
445 }
446
447 frag << "}\n";
448
449 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
450 }
451
checkSupport(Context & context) const452 void DynamicUnusedAttachmentsCase::checkSupport (Context& context) const
453 {
454 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
455 context.requireDeviceFunctionality("VK_EXT_dynamic_rendering_unused_attachments");
456
457 const auto& properties = context.getDeviceProperties();
458 if (m_params.fragAttachmentCount > properties.limits.maxFragmentOutputAttachments)
459 TCU_THROW(NotSupportedError, "Unsupported number of attachments");
460
461 if (m_params.vertExportsLayer())
462 {
463 // This will check the right extension or Vulkan 1.2 features automatically.
464 context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
465
466 // We also need geometry shader support to be able to use gl_Layer from frag shaders.
467 context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
468 }
469
470 if (m_params.multiView)
471 context.requireDeviceFunctionality("VK_KHR_multiview");
472 }
473
iterate(void)474 tcu::TestStatus DynamicUnusedAttachmentsInstance::iterate (void)
475 {
476 const auto ctx = m_context.getContextCommonData();
477 const tcu::IVec3 fbDim (1, 1, 1);
478 const auto fbExtent = makeExtent3D(fbDim);
479 const auto fbSamples = VK_SAMPLE_COUNT_1_BIT;
480 const auto colorUsage = (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
481 const auto dsUsage = (VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
482 const auto colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_params.layerCount);
483 const auto dsSRR = makeImageSubresourceRange((VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT), 0u, 1u, 0u, m_params.layerCount);
484 const auto colorSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, m_params.layerCount);
485 const auto depthSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 0u, m_params.layerCount);
486 const auto stencilSRL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 0u, m_params.layerCount);
487 const auto dsNeeded = m_params.depthStencilNeeded();
488
489 using ImageWithBufferPtr = std::unique_ptr<ImageWithBuffer>;
490
491 // Allocate color attachments.
492 std::vector<ImageWithBufferPtr> colorImages (m_params.pipeFBAttachmentCount);
493 for (uint32_t i = 0; i < m_params.pipeFBAttachmentCount; ++i)
494 colorImages[i].reset(new ImageWithBuffer(ctx.vkd, ctx.device, ctx.allocator, fbExtent, kColorFormat, colorUsage, VK_IMAGE_TYPE_2D, colorSRR, m_params.layerCount));
495
496 VkFormat dsFormat = VK_FORMAT_UNDEFINED;
497 std::unique_ptr<ImageWithMemory> dsImage;
498 Move<VkImageView> dsImageView;
499 tcu::TextureFormat depthCopyFormat;
500 tcu::TextureFormat stencilCopyFormat;
501 std::unique_ptr<BufferWithMemory> depthVerificationBuffer;
502 std::unique_ptr<BufferWithMemory> stencilVerificationBuffer;
503
504 if (dsNeeded)
505 dsFormat = chooseDepthStencilFormat(ctx.vki, ctx.physicalDevice);
506
507 if (dsNeeded)
508 {
509 const VkImageCreateInfo dsCreateInfo =
510 {
511 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
512 nullptr, // const void* pNext;
513 0u, // VkImageCreateFlags flags;
514 VK_IMAGE_TYPE_2D, // VkImageType imageType;
515 dsFormat, // VkFormat format;
516 fbExtent, // VkExtent3D extent;
517 1u, // uint32_t mipLevels;
518 m_params.layerCount, // uint32_t arrayLayers;
519 fbSamples, // VkSampleCountFlagBits samples;
520 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
521 dsUsage, // VkImageUsageFlags usage;
522 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
523 0u, // uint32_t queueFamilyIndexCount;
524 nullptr, // const uint32_t* pQueueFamilyIndices;
525 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
526 };
527 dsImage.reset(new ImageWithMemory(ctx.vkd, ctx.device, ctx.allocator, dsCreateInfo, MemoryRequirement::Any));
528
529 const auto dsImageViewType = (m_params.layerCount > 1u ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D);
530 dsImageView = makeImageView(ctx.vkd, ctx.device, dsImage->get(), dsImageViewType, dsFormat, dsSRR);
531 depthCopyFormat = getDepthCopyFormat(dsFormat);
532 stencilCopyFormat = getStencilCopyFormat(dsFormat);
533
534 const auto depthVerificationBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(depthCopyFormat) * fbExtent.width * fbExtent.height * fbExtent.depth * m_params.layerCount);
535 const auto depthVerificationBufferInfo = makeBufferCreateInfo(depthVerificationBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
536 depthVerificationBuffer.reset(new BufferWithMemory(ctx.vkd, ctx.device, ctx.allocator, depthVerificationBufferInfo, MemoryRequirement::HostVisible));
537
538 const auto stencilVerificationBufferSize = static_cast<VkDeviceSize>(tcu::getPixelSize(stencilCopyFormat) * fbExtent.width * fbExtent.height * fbExtent.depth * m_params.layerCount);
539 const auto stencilVerificationBufferInfo = makeBufferCreateInfo(stencilVerificationBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
540 stencilVerificationBuffer.reset(new BufferWithMemory(ctx.vkd, ctx.device, ctx.allocator, stencilVerificationBufferInfo, MemoryRequirement::HostVisible));
541 }
542
543 const std::vector<VkViewport> viewports (1u, makeViewport(fbExtent));
544 const std::vector<VkRect2D> scissors (1u, makeRect2D(fbExtent));
545
546 const auto& binaries = m_context.getBinaryCollection();
547 const auto vk12Support = m_context.contextSupports(vk::ApiVersion(0u, 1u, 2u, 0u));
548 const auto vertModule = createShaderModule(ctx.vkd, ctx.device, binaries.get(vk12Support ? "vert-spv15" : "vert-spv10"));
549 const auto fragModule = createShaderModule(ctx.vkd, ctx.device, binaries.get("frag"));
550
551 const auto pcSize = static_cast<uint32_t>(sizeof(int32_t));
552 const auto pcStages = VK_SHADER_STAGE_VERTEX_BIT;
553 const auto pcRange = makePushConstantRange(pcStages, 0u, pcSize);
554 const auto pipelineLayout = makePipelineLayout(ctx.vkd, ctx.device, VK_NULL_HANDLE, &pcRange);
555
556 const VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo = initVulkanStructure();
557 const auto stencilOpState = makeStencilOpState(VK_STENCIL_OP_KEEP, VK_STENCIL_OP_REPLACE, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_GREATER_OR_EQUAL, 0xFFu, 0xFFu, 0xFFu);
558 // If the depth or stencil test is enabled and the image view is not VK_NULL_HANDLE, the format cannot be UNDEFINED.
559 const auto depthEnabled = (m_params.depthPresent && !(!m_params.depthDefined && m_params.depthValidHandle));
560 const auto stencilEnabled = (m_params.stencilPresent && !(!m_params.stencilDefined && m_params.stencilValidHandle));
561 const VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo =
562 {
563 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType;
564 nullptr, // const void* pNext;
565 0u, // VkPipelineDepthStencilStateCreateFlags flags;
566 depthEnabled, // VkBool32 depthTestEnable;
567 depthEnabled, // VkBool32 depthWriteEnable;
568 VK_COMPARE_OP_GREATER_OR_EQUAL, // VkCompareOp depthCompareOp;
569 VK_FALSE, // VkBool32 depthBoundsTestEnable;
570 stencilEnabled, // VkBool32 stencilTestEnable;
571 stencilOpState, // VkStencilOpState front;
572 stencilOpState, // VkStencilOpState back;
573 0.0f, // float minDepthBounds;
574 1.0f, // float maxDepthBounds;
575 };
576
577 auto colorPipelineFormats = m_params.getPipelineFormatVector(kColorFormat);
578 auto depthPipelineFormat = m_params.getPipelineDepthFormat(dsFormat);
579 auto stencilPipelineFormat = m_params.getPipelineStencilFormat(dsFormat);
580 const auto viewMask = (m_params.multiView ? m_params.layerMask : 0u);
581
582 std::vector<VkImageView> rawColorViews;
583 rawColorViews.reserve(colorImages.size());
584 std::transform(begin(colorImages), end(colorImages), std::back_inserter(rawColorViews),
585 [](const ImageWithBufferPtr& ib) { return (ib.get() ? ib->getImageView() : VK_NULL_HANDLE); });
586
587 const auto renderingAttInfos = m_params.getRenderingAttachmentInfos(rawColorViews);
588
589 using RenderingAttachmentInfoPtr = std::unique_ptr<VkRenderingAttachmentInfo>;
590 RenderingAttachmentInfoPtr depthAttachmentPtr;
591 RenderingAttachmentInfoPtr stencilAttachmentPtr;
592
593 if (dsNeeded)
594 {
595 const auto& imgView = dsImageView.get();
596 DE_ASSERT(imgView != VK_NULL_HANDLE);
597 depthAttachmentPtr.reset(new VkRenderingAttachmentInfo(m_params.getDepthAttachmentInfo(imgView)));
598 stencilAttachmentPtr.reset(new VkRenderingAttachmentInfo(m_params.getStencilAttachmentInfo(imgView)));
599 }
600
601 if (m_params.wrongFormatWithNullViews)
602 {
603 DE_ASSERT(renderingAttInfos.size() == colorPipelineFormats.size());
604
605 // Use wrong formats when the image view is VK_NULL_HANDLE.
606 for (size_t i = 0u; i < renderingAttInfos.size(); ++i)
607 {
608 if (renderingAttInfos[i].imageView == VK_NULL_HANDLE)
609 colorPipelineFormats[i] = kBadColorFormat;
610 }
611
612 const auto badDSFormat = chooseAltDSFormat(dsFormat);
613
614 if (depthAttachmentPtr.get() && depthAttachmentPtr->imageView == VK_NULL_HANDLE)
615 depthPipelineFormat = badDSFormat;
616
617 if (stencilAttachmentPtr.get() && stencilAttachmentPtr->imageView == VK_NULL_HANDLE)
618 stencilPipelineFormat = badDSFormat;
619 }
620
621 const VkPipelineRenderingCreateInfo pipelineRenderingCreateInfo =
622 {
623 VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, // VkStructureType sType;
624 nullptr, // const void* pNext;
625 viewMask, // uint32_t viewMask;
626 de::sizeU32(colorPipelineFormats), // uint32_t colorAttachmentCount;
627 de::dataOrNull(colorPipelineFormats), // const VkFormat* pColorAttachmentFormats;
628 depthPipelineFormat, // VkFormat depthAttachmentFormat;
629 stencilPipelineFormat, // VkFormat stencilAttachmentFormat;
630 };
631
632 const auto colorWriteMask = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT);
633 const auto colorBlendAttState = makePipelineColorBlendAttachmentState(VK_FALSE, VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_ZERO, VK_BLEND_FACTOR_ZERO, VK_BLEND_OP_ADD, colorWriteMask);
634
635 const std::vector<VkPipelineColorBlendAttachmentState> colorBlendStateVec (pipelineRenderingCreateInfo.colorAttachmentCount, colorBlendAttState);
636
637 const VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo =
638 {
639 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType;
640 nullptr, // const void* pNext;
641 0u, // VkPipelineColorBlendStateCreateFlags flags;
642 VK_FALSE, // VkBool32 logicOpEnable;
643 VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp;
644 de::sizeU32(colorBlendStateVec), // uint32_t attachmentCount;
645 de::dataOrNull(colorBlendStateVec), // const VkPipelineColorBlendAttachmentState* pAttachments;
646 { 0.0f, 0.0f, 0.0f, 0.0f }, // float blendConstants[4];
647 };
648
649 const auto pipeline = makeGraphicsPipeline(ctx.vkd, ctx.device, pipelineLayout.get(),
650 vertModule.get(), VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE, fragModule.get(),
651 VK_NULL_HANDLE, viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u,
652 &vertexInputStateCreateInfo, nullptr, nullptr, &depthStencilStateCreateInfo, &colorBlendStateCreateInfo, nullptr, &pipelineRenderingCreateInfo);
653
654 CommandPoolWithBuffer cmd (ctx.vkd, ctx.device, ctx.qfIndex);
655 const auto cmdBuffer = cmd.cmdBuffer.get();
656 Move<VkCommandBuffer> secondaryCmdBuffer;
657
658 if (m_params.useSecondaries)
659 secondaryCmdBuffer = allocateCommandBuffer(ctx.vkd, ctx.device, cmd.cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_SECONDARY);
660
661 const auto rpCmdBuffer = (m_params.useSecondaries ? secondaryCmdBuffer.get() : cmdBuffer);
662
663 const auto renderingFlags = (m_params.useSecondaries
664 ? static_cast<VkRenderingFlags>(VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT)
665 : 0);
666
667 const VkRenderingInfo renderingInfo =
668 {
669 VK_STRUCTURE_TYPE_RENDERING_INFO_KHR, // VkStructureType sType;
670 nullptr, // const void* pNext;
671 renderingFlags, // VkRenderingFlags flags;
672 scissors.at(0u), // VkRect2D renderArea;
673 (m_params.multiView ? 1u : m_params.layerCount), // uint32_t layerCount;
674 viewMask, // uint32_t viewMask;
675 de::sizeU32(renderingAttInfos), // uint32_t colorAttachmentCount;
676 de::dataOrNull(renderingAttInfos), // const VkRenderingAttachmentInfo* pColorAttachments;
677 depthAttachmentPtr.get(), // const VkRenderingAttachmentInfo* pDepthAttachment;
678 stencilAttachmentPtr.get(), // const VkRenderingAttachmentInfo* pStencilAttachment;
679 };
680
681 beginCommandBuffer(ctx.vkd, cmdBuffer);
682
683 // Transition the layout of every image.
684 {
685 std::vector<VkImageMemoryBarrier> initialLayoutBarriers;
686
687 for (const auto& img : colorImages)
688 {
689 const auto colorBarrier = makeImageMemoryBarrier(
690 0u,
691 VK_ACCESS_TRANSFER_WRITE_BIT,
692 VK_IMAGE_LAYOUT_UNDEFINED,
693 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
694 img->getImage(), colorSRR);
695 initialLayoutBarriers.push_back(colorBarrier);
696 }
697 if (dsNeeded)
698 {
699 const auto dsBarrier = makeImageMemoryBarrier(
700 0u,
701 VK_ACCESS_TRANSFER_WRITE_BIT,
702 VK_IMAGE_LAYOUT_UNDEFINED,
703 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
704 dsImage->get(), dsSRR);
705 initialLayoutBarriers.push_back(dsBarrier);
706 }
707
708 ctx.vkd.cmdPipelineBarrier(cmdBuffer,
709 VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
710 VK_PIPELINE_STAGE_TRANSFER_BIT,
711 0u, 0u, nullptr, 0u, nullptr,
712 de::sizeU32(initialLayoutBarriers), de::dataOrNull(initialLayoutBarriers));
713 }
714
715 // Clear images.
716 {
717 const auto clearValue = TestParams::getClearValue();
718
719 for (const auto& img : colorImages)
720 ctx.vkd.cmdClearColorImage(cmdBuffer, img->getImage(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1u, &colorSRR);
721 if (dsNeeded)
722 ctx.vkd.cmdClearDepthStencilImage(cmdBuffer, dsImage->get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.depthStencil, 1u, &dsSRR);
723 }
724
725 // Transition the layout of every image.
726 {
727 std::vector<VkImageMemoryBarrier> initialLayoutBarriers;
728
729 for (const auto& img : colorImages)
730 {
731 const auto colorBarrier = makeImageMemoryBarrier(
732 VK_ACCESS_TRANSFER_WRITE_BIT,
733 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
734 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
735 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
736 img->getImage(), colorSRR);
737 initialLayoutBarriers.push_back(colorBarrier);
738 }
739 if (dsNeeded)
740 {
741 const auto dsBarrier = makeImageMemoryBarrier(
742 VK_ACCESS_TRANSFER_WRITE_BIT,
743 (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT),
744 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
745 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
746 dsImage->get(), dsSRR);
747 initialLayoutBarriers.push_back(dsBarrier);
748 }
749
750 ctx.vkd.cmdPipelineBarrier(cmdBuffer,
751 VK_PIPELINE_STAGE_TRANSFER_BIT,
752 (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT),
753 0u, 0u, nullptr, 0u, nullptr,
754 de::sizeU32(initialLayoutBarriers), de::dataOrNull(initialLayoutBarriers));
755 }
756
757 ctx.vkd.cmdBeginRendering(cmdBuffer, &renderingInfo);
758
759 if (m_params.useSecondaries)
760 {
761 // The inheritance info and framebuffer attachments must match (null handle -> undefined format, non-null handle -> valid format).
762 // The pipeline rendering info will later be able to selectively disable an attachment.
763 const auto inheritanceColorFormats = m_params.getInheritanceFormatVector(kColorFormat);
764 const auto inheritanceDepthFormat = m_params.getInheritanceDepthFormat(dsFormat);
765 const auto inheritanceStencilFormat = m_params.getInheritanceStencilFormat(dsFormat);
766
767 const VkCommandBufferInheritanceRenderingInfo inheritanceRenderingInfo =
768 {
769 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO, // VkStructureType sType;
770 nullptr, // const void* pNext;
771 0u, // VkRenderingFlags flags;
772 viewMask, // uint32_t viewMask;
773 de::sizeU32(inheritanceColorFormats), // uint32_t colorAttachmentCount;
774 de::dataOrNull(inheritanceColorFormats), // const VkFormat* pColorAttachmentFormats;
775 inheritanceDepthFormat, // VkFormat depthAttachmentFormat;
776 inheritanceStencilFormat, // VkFormat stencilAttachmentFormat;
777 fbSamples, // VkSampleCountFlagBits rasterizationSamples;
778 };
779
780 const VkCommandBufferInheritanceInfo inheritanceInfo =
781 {
782 VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, // VkStructureType sType;
783 &inheritanceRenderingInfo, // const void* pNext;
784 VK_NULL_HANDLE, // VkRenderPass renderPass;
785 0u, // uint32_t subpass;
786 VK_NULL_HANDLE, // VkFramebuffer framebuffer;
787 VK_FALSE, // VkBool32 occlusionQueryEnable;
788 0u, // VkQueryControlFlags queryFlags;
789 0u, // VkQueryPipelineStatisticFlags pipelineStatistics;
790 };
791
792 const VkCommandBufferBeginInfo beginInfo =
793 {
794 VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, // VkStructureType sType;
795 nullptr, // const void* pNext;
796 VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, // VkCommandBufferUsageFlags flags;
797 &inheritanceInfo, // const VkCommandBufferInheritanceInfo* pInheritanceInfo;
798 };
799
800 ctx.vkd.beginCommandBuffer(secondaryCmdBuffer.get(), &beginInfo);
801 }
802
803 ctx.vkd.cmdBindPipeline(rpCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
804 {
805 const auto iterCount = (m_params.multiView ? 1u : m_params.layerCount);
806 for (uint32_t i = 0; i < iterCount; ++i)
807 {
808 // In non-multiview mode, we have to skip some layers manually.
809 if (!m_params.multiView && ((m_params.layerMask & (1u << i)) == 0u))
810 continue;
811
812 ctx.vkd.cmdPushConstants(rpCmdBuffer, pipelineLayout.get(), pcStages, 0u, pcSize, &i);
813 ctx.vkd.cmdDraw(rpCmdBuffer, 3u, 1u, 0u, 0u);
814 }
815 }
816
817 if (m_params.useSecondaries)
818 {
819 endCommandBuffer(ctx.vkd, secondaryCmdBuffer.get());
820 ctx.vkd.cmdExecuteCommands(cmdBuffer, 1u, &secondaryCmdBuffer.get());
821 }
822
823 ctx.vkd.cmdEndRendering(cmdBuffer);
824
825 // Transition the layout of all images again for verification.
826 {
827 std::vector<VkImageMemoryBarrier> preCopyLayoutBarriers;
828
829 for (const auto& img : colorImages)
830 {
831 const auto colorBarrier = makeImageMemoryBarrier(
832 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
833 VK_ACCESS_TRANSFER_READ_BIT,
834 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
835 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
836 img->getImage(), colorSRR);
837 preCopyLayoutBarriers.push_back(colorBarrier);
838 }
839 if (dsNeeded)
840 {
841 const auto dsBarrier = makeImageMemoryBarrier(
842 (VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT),
843 VK_ACCESS_TRANSFER_READ_BIT,
844 VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
845 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
846 dsImage->get(), dsSRR);
847 preCopyLayoutBarriers.push_back(dsBarrier);
848 }
849
850 ctx.vkd.cmdPipelineBarrier(cmdBuffer,
851 (VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT),
852 VK_PIPELINE_STAGE_TRANSFER_BIT,
853 0u, 0u, nullptr, 0u, nullptr,
854 de::sizeU32(preCopyLayoutBarriers), de::dataOrNull(preCopyLayoutBarriers));
855 }
856
857 // Copy all image contents to their verification buffers (note depth/stencil uses two buffers).
858 for (const auto& img : colorImages)
859 {
860 const auto copyRegion = makeBufferImageCopy(fbExtent, colorSRL);
861 ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, img->getImage(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, img->getBuffer(), 1u, ©Region);
862 }
863 if (dsNeeded)
864 {
865 const auto depthCopyRegion = makeBufferImageCopy(fbExtent, depthSRL);
866 const auto stencilCopyRegion = makeBufferImageCopy(fbExtent, stencilSRL);
867
868 ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, dsImage->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, depthVerificationBuffer->get(), 1u, &depthCopyRegion);
869 ctx.vkd.cmdCopyImageToBuffer(cmdBuffer, dsImage->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stencilVerificationBuffer->get(), 1u, &stencilCopyRegion);
870 }
871
872 // Global barrier to synchronize verification buffers to host reads.
873 {
874 const auto transfer2HostBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
875 cmdPipelineMemoryBarrier(ctx.vkd, cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, &transfer2HostBarrier);
876 }
877
878 endCommandBuffer(ctx.vkd, cmdBuffer);
879 submitCommandsAndWait(ctx.vkd, ctx.device, ctx.queue, cmdBuffer);
880
881 // Invalidate all allocations.
882 for (uint32_t i = 0; i < m_params.pipeFBAttachmentCount; ++i)
883 invalidateAlloc(ctx.vkd, ctx.device, colorImages.at(i)->getBufferAllocation());
884 if (dsNeeded)
885 {
886 invalidateAlloc(ctx.vkd, ctx.device, depthVerificationBuffer->getAllocation());
887 invalidateAlloc(ctx.vkd, ctx.device, stencilVerificationBuffer->getAllocation());
888 }
889
890 // Verify all layers in all images.
891 const auto colorTcuFormat = mapVkFormat(kColorFormat);
892 const auto colorPixelSize = tcu::getPixelSize(colorTcuFormat);
893 const auto colorLayerSize = static_cast<size_t>(fbDim.x() * fbDim.y() * fbDim.z() * colorPixelSize);
894
895 const tcu::UVec4 threshold (0u, 0u, 0u, 0u); // We expect exact results.
896 auto& log = m_context.getTestContext().getLog();
897 bool failure = false;
898
899 for (size_t colorImgIdx = 0u; colorImgIdx < colorImages.size(); ++colorImgIdx)
900 {
901 const auto& colorImg = colorImages.at(colorImgIdx);
902 const auto dataPtr = reinterpret_cast<const char*>(colorImg->getBufferAllocation().getHostPtr());
903 const bool imgWritten = (colorImgIdx < colorPipelineFormats.size() && colorPipelineFormats.at(colorImgIdx) != VK_FORMAT_UNDEFINED
904 && colorImgIdx < renderingAttInfos.size() && renderingAttInfos.at(colorImgIdx).imageView != VK_NULL_HANDLE);
905
906 for (uint32_t layerIdx = 0u; layerIdx < m_params.layerCount; ++layerIdx)
907 {
908 const bool layerWritten = imgWritten && ((m_params.layerMask & (1 << layerIdx)) != 0u);
909 const auto layerDataPtr = dataPtr + colorLayerSize * layerIdx;
910 const tcu::ConstPixelBufferAccess layerAccess (colorTcuFormat, fbDim, layerDataPtr);
911 const tcu::UVec4 expectedColor = (layerWritten
912 ? tcu::UVec4(layerIdx, 255u, static_cast<uint32_t>(colorImgIdx), 255u) // Needs to match frag shader.
913 : tcu::UVec4(0u, 0u, 0u, 0u));
914 const std::string logImgName = "ColorAttachment" + std::to_string(colorImgIdx) + "-Layer" + std::to_string(layerIdx);
915 tcu::TextureLevel refLevel (colorTcuFormat, fbDim.x(), fbDim.y(), fbDim.z());
916 tcu::PixelBufferAccess refAccess = refLevel.getAccess();
917
918 tcu::clear(refAccess, expectedColor);
919 if (!tcu::intThresholdCompare(log, logImgName.c_str(), "", refAccess, layerAccess, threshold, tcu::COMPARE_LOG_EVERYTHING))
920 failure = true;
921 }
922 }
923
924 if (dsNeeded)
925 {
926 const bool depthWritten = (m_params.depthPresent && m_params.depthDefined && m_params.depthValidHandle);
927 const bool stencilWritten = (m_params.stencilPresent && m_params.stencilDefined && m_params.stencilValidHandle);
928
929 // Depth.
930 {
931 const auto dataPtr = reinterpret_cast<const char*>(depthVerificationBuffer->getAllocation().getHostPtr());
932 const auto depthPixelSize = tcu::getPixelSize(depthCopyFormat);
933 const auto depthLayerSize = static_cast<size_t>(fbDim.x() * fbDim.y() * fbDim.z() * depthPixelSize);
934 const auto depthThreshold = 0.0f; // We expect exact results.
935
936 for (uint32_t layerIdx = 0u; layerIdx < m_params.layerCount; ++layerIdx)
937 {
938 const bool layerWritten = depthWritten && ((m_params.layerMask & (1 << layerIdx)) != 0u);
939 const auto layerDataPtr = dataPtr + depthLayerSize * layerIdx;
940 const tcu::ConstPixelBufferAccess layerAccess (depthCopyFormat, fbDim, layerDataPtr);
941 const float expectedDepth = (layerWritten ? 1.0f : 0.0f); // Needs to match the vertex shader and depth/stencil config.
942 const std::string logImgName = "DepthAttachment-Layer" + std::to_string(layerIdx);
943 tcu::TextureLevel refLevel (depthCopyFormat, fbDim.x(), fbDim.y(), fbDim.z());
944 tcu::PixelBufferAccess refAccess = refLevel.getAccess();
945
946 tcu::clearDepth(refAccess, expectedDepth);
947 if (!tcu::dsThresholdCompare(log, logImgName.c_str(), "", refAccess, layerAccess, depthThreshold, tcu::COMPARE_LOG_ON_ERROR))
948 failure = true;
949 }
950 }
951
952 // Stencil.
953 {
954 const auto dataPtr = reinterpret_cast<const char*>(stencilVerificationBuffer->getAllocation().getHostPtr());
955 const auto stencilPixelSize = tcu::getPixelSize(stencilCopyFormat);
956 const auto stencilLayerSize = static_cast<size_t>(fbDim.x() * fbDim.y() * fbDim.z() * stencilPixelSize);
957 const auto stencilThreshold = 0.0f; // We expect exact results.
958
959 for (uint32_t layerIdx = 0u; layerIdx < m_params.layerCount; ++layerIdx)
960 {
961 const bool layerWritten = stencilWritten && ((m_params.layerMask & (1 << layerIdx)) != 0u);
962 const auto layerDataPtr = dataPtr + stencilLayerSize * layerIdx;
963 const tcu::ConstPixelBufferAccess layerAccess (stencilCopyFormat, fbDim, layerDataPtr);
964 const int expectedStencil = (layerWritten ? 0xFF : 0); // Needs to match the stencil op config.
965 const std::string logImgName = "StencilAttachment-Layer" + std::to_string(layerIdx);
966 tcu::TextureLevel refLevel (stencilCopyFormat, fbDim.x(), fbDim.y(), fbDim.z());
967 tcu::PixelBufferAccess refAccess = refLevel.getAccess();
968
969 tcu::clearStencil(refAccess, expectedStencil);
970 if (!tcu::dsThresholdCompare(log, logImgName.c_str(), "", refAccess, layerAccess, stencilThreshold, tcu::COMPARE_LOG_ON_ERROR))
971 failure = true;
972 }
973 }
974 }
975
976 if (failure)
977 return tcu::TestStatus::fail("Invalid value found in verification buffers; check log for details");
978
979 return tcu::TestStatus::pass("Pass");
980 }
981
982 using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;
983
984 } // anonymous namespace
985
createDynamicRenderingUnusedAttachmentsTests(tcu::TestContext & testCtx,bool useSecondaries)986 tcu::TestCaseGroup* createDynamicRenderingUnusedAttachmentsTests (tcu::TestContext& testCtx, bool useSecondaries)
987 {
988 // Tests for VK_EXT_dynamic_rendering_unused_attachments
989 GroupPtr group (new tcu::TestCaseGroup(testCtx, "unused_attachments"));
990
991 // Add a combination subgroup just in case we want to add more test cases later to another subgroup.
992 GroupPtr combGroup (new tcu::TestCaseGroup(testCtx, "comb", "VK_EXT_dynamic_rendering_unused_attachments with different combinations"));
993 GroupPtr colorGroup (new tcu::TestCaseGroup(testCtx, "color"));
994 GroupPtr dsGroup (new tcu::TestCaseGroup(testCtx, "depth_stencil"));
995 GroupPtr badFmtGrp (new tcu::TestCaseGroup(testCtx, "bad_formats", "Test using wrong formats when the handle is VK_NULL_HANDLE"));
996
997 const uint32_t attachmentCounts[] = { 1u, 4u, 8u, };
998 const uint32_t layerCounts[] = { 1u, 4u, };
999 const uint32_t masksToTest[] = { 0xFFFFFFFFu, 0x0u, 0x55555555u, 0xAAAAAAAAu, };
1000
1001 {
1002 // Combinations of color attachment counts, no depth/stencil.
1003 for (const auto& pipeAtt : attachmentCounts)
1004 for (const auto& fragAtt : attachmentCounts)
1005 {
1006 if (fragAtt < pipeAtt)
1007 continue;
1008
1009 for (const auto& layerCount : layerCounts)
1010 for (const auto& layerMask : masksToTest)
1011 {
1012 // Avoid duplicate cases.
1013 if (layerCount == 1u && layerMask != masksToTest[0] && layerMask != masksToTest[1])
1014 continue;
1015
1016 for (const auto& formatMask : masksToTest)
1017 for (const auto& handleMask : masksToTest)
1018 {
1019 for (const auto multiview : { false, true })
1020 {
1021 const auto viewMask = (((1u << layerCount) - 1u) & layerMask);
1022
1023 if (multiview && viewMask == 0u)
1024 continue;
1025
1026 const TestParams params
1027 (
1028 pipeAtt, fragAtt, layerCount,
1029 viewMask,
1030 multiview,
1031 formatMask, handleMask,
1032 false, false, false,
1033 false, false, false,
1034 useSecondaries, false
1035 );
1036 colorGroup->addChild(new DynamicUnusedAttachmentsCase(testCtx, params.getTestName(), params));
1037 }
1038 }
1039 }
1040 }
1041
1042 // Combinations of depth/stencil parameters, single color attachment.
1043 for (const auto depthPresent : { false, true })
1044 for (const auto depthDefined : { false, true })
1045 for (const auto depthValidHandle : { false, true })
1046 {
1047 if (!depthPresent && (depthDefined || depthValidHandle))
1048 continue;
1049
1050 for (const auto stencilPresent : { false, true })
1051 for (const auto stencilDefined : { false, true })
1052 for (const auto stencilValidHandle : { false, true })
1053 {
1054 if (!stencilPresent && (stencilDefined || stencilValidHandle))
1055 continue;
1056
1057 // Either both or none according to VUID-VkRenderingInfo-pDepthAttachment-06085
1058 if (depthValidHandle != stencilValidHandle)
1059 continue;
1060
1061 // So far there is no VU that prevents only one of the depth/stencil formats from being
1062 // VK_FORMAT_UNDEFINED while the other one is not. However, that would mean disabling the
1063 // depth/stencil test (or at least make that aspect read-only, it's not clear) through a second
1064 // mechanism in the pipeline configuration.
1065 //
1066 // We can still test the VK_NULL_HANDLE/VK_FORMAT_UNDEFINED inconsistency, just not separately for
1067 // depth and stencil, which is one of the focus of these tests.
1068 if (depthDefined != stencilDefined)
1069 continue;
1070
1071 for (const auto& layerCount : layerCounts)
1072 for (const auto& layerMask : masksToTest)
1073 {
1074 // Avoid duplicate cases.
1075 if (layerCount == 1u && layerMask != masksToTest[0] && layerMask != masksToTest[1])
1076 continue;
1077
1078 for (const auto multiview : { false, true })
1079 {
1080 const auto viewMask = (((1u << layerCount) - 1u) & layerMask);
1081
1082 if (multiview && viewMask == 0u)
1083 continue;
1084
1085 const TestParams params
1086 (
1087 1u, 1u, layerCount,
1088 viewMask,
1089 multiview,
1090 0xFFFFFFFFu, 0xFFFFFFFFu,
1091 depthPresent, depthDefined, depthValidHandle,
1092 stencilPresent, stencilDefined, stencilValidHandle,
1093 useSecondaries, false
1094 );
1095 dsGroup->addChild(new DynamicUnusedAttachmentsCase(testCtx, params.getTestName(), params));
1096 }
1097 }
1098 }
1099 }
1100
1101 combGroup->addChild(colorGroup.release());
1102 combGroup->addChild(dsGroup.release());
1103 }
1104 group->addChild(combGroup.release());
1105
1106 // Bad format tests.
1107 {
1108 for (const auto& formatMask : masksToTest)
1109 for (const auto& handleMask : masksToTest)
1110 {
1111 if (handleMask == 0xFFFFFFFFu || formatMask == handleMask)
1112 continue;
1113
1114 const TestParams params
1115 (
1116 4u, 4u, 1u,
1117 1u,
1118 false,
1119 formatMask, handleMask,
1120 true, true, false,
1121 true, true, false,
1122 useSecondaries, true
1123 );
1124 badFmtGrp->addChild(new DynamicUnusedAttachmentsCase(testCtx, params.getTestName(), params));
1125 }
1126 }
1127 group->addChild(badFmtGrp.release());
1128
1129 return group.release();
1130 }
1131
1132 } // renderpass
1133 } // vkt
1134