1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2023 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Vulkan Dynamic Rendering Local Read Tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "deRandom.hpp"
25 #include "deUniquePtr.hpp"
26
27 #include "tcuImageCompare.hpp"
28 #include "tcuRGBA.hpp"
29 #include "tcuTestLog.hpp"
30 #include "tcuTextureUtil.hpp"
31 #include "tcuVectorUtil.hpp"
32
33 #include "vkBarrierUtil.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkCmdUtil.hpp"
36 #include "vktDynamicRenderingLocalReadTests.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkObjUtil.hpp"
39 #include "vkQueryUtil.hpp"
40 #include "vkRefUtil.hpp"
41 #include "vktTestGroupUtil.hpp"
42 #include "vktTestCase.hpp"
43 #include "vkTypeUtil.hpp"
44
45 #include <iostream>
46 #include <algorithm>
47
48 namespace vkt
49 {
50 namespace renderpass
51 {
52 namespace
53 {
54
55 using namespace vk;
56
57 enum class TestType
58 {
59 // Test maximum number of attachments(color + depth + stencil) readback as input
60 MAX_INPUT_ATTACHMENTS = 0,
61
62 // Test maximum attachments remapped repeatedly
63 MAX_ATTACHMENTS_REMAPPED_REPEATEDLY,
64
65 // Test that color attachment locations set to ATTACHMENT_UNUSED are not written, and that writes to unmapped locations are discarded
66 UNUSED_WRITEN_DISCARDED,
67
68 // Test mapping depth + stencil to no index
69 DEPTH_STENCIL_MAPPING_TO_NO_INDEX,
70
71 // Test mapping depth + stencil to the same index
72 DEPTH_STENCIL_MAPPING_TO_SAME_INDEX,
73
74 // Test mapping depth + stencil so only one takes an index, the other does not
75 DEPTH_MAPPING_STENCIL_NOT,
76
77 // Test that blend state is using unmapped indexes
78 MAPPING_NOT_AFFECTING_BLEND_STATE,
79
80 // Test interaction with VK_EXT_color_write_enable
81 INTERACTION_WITH_COLOR_WRITE_ENABLE,
82
83 // Test interaction with VK_EXT_extended_dynamic_state3
84 INTERACTION_WITH_EXTENDED_DYNAMIC_STATE3
85 };
86
87 // During test creation we dont know what is the maximal number of input attachments.
88 // To be able to test maximal number of attachments we need to construct shaders for all possible
89 // numbers of input attachments. This number must also not be greater then maxColorAttachments.
90 static uint32_t inputAttachmentsPossibleValues[] = {4, 5, 6, 7, 8, 9, 10, 16, 17, 18};
91
92 using ImageWithMemorySp = de::SharedPtr<ImageWithMemory>;
93 using BufferWithMemorySp = de::SharedPtr<BufferWithMemory>;
94 using VkImageViewSp = de::SharedPtr<Move<VkImageView>>;
95
createImage(Context & context,uint32_t renderSize,VkFormat format,VkImageUsageFlags usage)96 ImageWithMemorySp createImage(Context &context, uint32_t renderSize, VkFormat format, VkImageUsageFlags usage)
97 {
98 const DeviceInterface &vk = context.getDeviceInterface();
99 VkDevice device = context.getDevice();
100 Allocator &memAlloc = context.getDefaultAllocator();
101 VkExtent3D extent = makeExtent3D(renderSize, renderSize, 1u);
102
103 const VkImageCreateInfo imageCreateInfo{
104 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
105 DE_NULL, // const void* pNext;
106 0u, // VkImageCreateFlags flags;
107 VK_IMAGE_TYPE_2D, // VkImageType imageType;
108 format, // VkFormat format;
109 extent, // VkExtent3D extent;
110 1u, // uint32_t mipLevels;
111 1u, // uint32_t arrayLayers;
112 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
113 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
114 usage, // VkImageUsageFlags usage;
115 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
116 0u, // uint32_t queueFamilyIndexCount;
117 DE_NULL, // const uint32_t* pQueueFamilyIndices;
118 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
119 };
120
121 return ImageWithMemorySp(new ImageWithMemory(vk, device, memAlloc, imageCreateInfo, MemoryRequirement::Any));
122 }
123
124 class BasicLocalReadTestInstance : public vkt::TestInstance
125 {
126 public:
127 BasicLocalReadTestInstance(Context &context, TestType testType);
128
129 protected:
130 tcu::TestStatus iterate(void) override;
131
132 private:
133 void CalculateExpectedValues(void);
134 bool UseColorWriteEnable(void) const;
135 uint32_t GetRemappedColorAttachment(uint32_t inputDrawId, uint32_t location) const;
136 uint32_t GetRemappedColorInputAttachment(uint32_t outputDrawId, uint32_t inputAttachmentIdx) const;
137
138 const TestType m_testType;
139 const uint32_t m_renderSize;
140 VkFormat m_dsFormat;
141
142 uint32_t m_colorAttachmentCount;
143 uint32_t m_inputDrawsCount;
144 uint32_t m_outputDrawsCount;
145 std::string m_writeFragName;
146 std::string m_readFragName;
147 std::vector<std::vector<uint32_t>> m_colorAttachmentLocations;
148 std::vector<std::vector<uint32_t>> m_colorAttachmentInputIndices;
149 uint32_t m_depthInputAttachmentIndex;
150 uint32_t m_stencilInputAttachmentIndex;
151 const VkBool32 m_colorWriteEnables[4];
152 VkBool32 m_useStencilInReadFrag;
153 std::vector<uint32_t> m_expectedValues;
154 };
155
BasicLocalReadTestInstance(Context & context,TestType testType)156 BasicLocalReadTestInstance::BasicLocalReadTestInstance(Context &context, TestType testType)
157 : vkt::TestInstance(context)
158 , m_testType(testType)
159 , m_renderSize(16)
160 , m_dsFormat(VK_FORMAT_D24_UNORM_S8_UINT)
161 , m_colorAttachmentCount(4)
162 , m_inputDrawsCount(1)
163 , m_outputDrawsCount(1)
164 , m_writeFragName("frag0")
165 , m_readFragName("frag1")
166 , m_colorAttachmentLocations{{0, 1, 2, 3}}
167 , m_colorAttachmentInputIndices{{0, 1, 2, 3}}
168 , m_depthInputAttachmentIndex(4)
169 , m_stencilInputAttachmentIndex(5)
170 , m_colorWriteEnables{0, 1, 0, 1}
171 , m_useStencilInReadFrag(true)
172 , m_expectedValues{0}
173 {
174 const InstanceInterface &vki = m_context.getInstanceInterface();
175 VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
176 const VkPhysicalDeviceProperties properties = getPhysicalDeviceProperties(vki, physicalDevice);
177
178 // pick depth stencil format (one of those two has to be supported)
179 VkImageFormatProperties imageFormatProperties;
180 if (vki.getPhysicalDeviceImageFormatProperties(
181 physicalDevice, m_dsFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
182 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, 0,
183 &imageFormatProperties))
184 m_dsFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
185
186 // setup test configuration - all test cases use same test instance code but with diferent parameters
187 switch (m_testType)
188 {
189 case TestType::MAX_INPUT_ATTACHMENTS:
190 {
191 m_colorAttachmentCount = deMinu32(properties.limits.maxColorAttachments,
192 properties.limits.maxPerStageDescriptorInputAttachments - 2u);
193
194 // if this assert is trigered then shader for number m_colorAttachmentCount+2 was not prepared;
195 // to fix this just add value of m_colorAttachmentCount+2 to the inputAttachmentsPossibleValues array on top of this file
196 DE_ASSERT(std::find(std::begin(inputAttachmentsPossibleValues), std::end(inputAttachmentsPossibleValues),
197 m_colorAttachmentCount + 2) != std::end(inputAttachmentsPossibleValues));
198
199 m_writeFragName += "_" + std::to_string(m_colorAttachmentCount);
200 m_readFragName +=
201 "_" + std::to_string(m_colorAttachmentCount + 2u); // +2 because depth and stencil are read too
202 m_depthInputAttachmentIndex = m_colorAttachmentCount;
203 m_stencilInputAttachmentIndex = m_colorAttachmentCount + 1;
204
205 m_colorAttachmentLocations[0].resize(m_colorAttachmentCount);
206 m_colorAttachmentInputIndices[0].resize(m_colorAttachmentCount);
207 for (uint32_t attIndex = 0; attIndex < m_colorAttachmentCount; ++attIndex)
208 {
209 m_colorAttachmentLocations[0][attIndex] = attIndex;
210 m_colorAttachmentInputIndices[0][attIndex] = attIndex;
211 }
212 break;
213 }
214 case TestType::MAX_ATTACHMENTS_REMAPPED_REPEATEDLY:
215 {
216 m_colorAttachmentCount = deMinu32(properties.limits.maxColorAttachments,
217 properties.limits.maxPerStageDescriptorInputAttachments - 2u);
218 m_inputDrawsCount = m_colorAttachmentCount / 2u;
219 m_colorAttachmentCount = m_inputDrawsCount * 2u;
220 m_outputDrawsCount = 3;
221 m_readFragName +=
222 "_" + std::to_string(m_colorAttachmentCount + 2u); // +2 because depth and stencil are read too
223 m_depthInputAttachmentIndex = m_colorAttachmentCount;
224 m_stencilInputAttachmentIndex = m_colorAttachmentCount + 1;
225
226 // each input draw uses just two color attachments; each time its different pair that is always mapped to location 0 and 1
227 m_colorAttachmentLocations.clear();
228 m_colorAttachmentLocations.resize(m_inputDrawsCount,
229 std::vector<uint32_t>(m_colorAttachmentCount, VK_ATTACHMENT_UNUSED));
230 for (uint32_t inputDraw = 0; inputDraw < m_inputDrawsCount; ++inputDraw)
231 {
232 auto &colorAttachmentLocations = m_colorAttachmentLocations[inputDraw];
233 uint32_t index = 2u * inputDraw;
234 colorAttachmentLocations[index] = 0u;
235 colorAttachmentLocations[index + 1u] = 1u;
236 }
237
238 // allocate space for all different remappings
239 m_colorAttachmentInputIndices.resize(m_outputDrawsCount);
240 for (auto &inputIndices : m_colorAttachmentInputIndices)
241 inputIndices.resize(m_colorAttachmentCount);
242
243 // each output draw will use all input attachments but remapped differently
244 // first remapping: reversed order, from greatest index to smallest
245 // second remapping: alternately takes the smallest not used index and then the largest not used index
246 // third remapping: same order as index, from smallest index to greatest
247 for (uint32_t attIndex = 0; attIndex < m_colorAttachmentCount; ++attIndex)
248 {
249 m_colorAttachmentInputIndices[0][attIndex] = m_colorAttachmentCount - 1 - attIndex;
250 m_colorAttachmentInputIndices[1][attIndex] =
251 (attIndex % 2) ? (m_colorAttachmentCount - 1 - attIndex / 2u) : (attIndex / 2u);
252 m_colorAttachmentInputIndices[2][attIndex] = attIndex;
253 }
254 break;
255 }
256 case TestType::UNUSED_WRITEN_DISCARDED:
257 {
258 m_useStencilInReadFrag = true;
259 m_colorAttachmentCount = 4;
260 m_colorAttachmentLocations[0][0] = VK_ATTACHMENT_UNUSED;
261 m_colorAttachmentLocations[0][2] = VK_ATTACHMENT_UNUSED;
262 break;
263 }
264 case TestType::DEPTH_STENCIL_MAPPING_TO_NO_INDEX:
265 {
266 m_useStencilInReadFrag = true;
267 m_colorAttachmentCount = 2;
268 m_depthInputAttachmentIndex = VK_ATTACHMENT_UNUSED;
269 m_stencilInputAttachmentIndex = VK_ATTACHMENT_UNUSED;
270 break;
271 }
272 case TestType::DEPTH_STENCIL_MAPPING_TO_SAME_INDEX:
273 {
274 m_useStencilInReadFrag = true;
275 m_colorAttachmentCount = 2;
276 m_depthInputAttachmentIndex = 2;
277 m_stencilInputAttachmentIndex = 2;
278 break;
279 }
280 case TestType::DEPTH_MAPPING_STENCIL_NOT:
281 {
282 m_useStencilInReadFrag = false;
283 m_colorAttachmentCount = 4;
284 m_depthInputAttachmentIndex = 4;
285 m_stencilInputAttachmentIndex = VK_ATTACHMENT_UNUSED;
286 break;
287 }
288 case TestType::INTERACTION_WITH_COLOR_WRITE_ENABLE:
289 {
290 m_useStencilInReadFrag = false;
291 m_colorAttachmentCount = 4;
292 m_colorAttachmentLocations = {{0, 3, 1, 2}};
293 m_depthInputAttachmentIndex = 4;
294 m_stencilInputAttachmentIndex = VK_ATTACHMENT_UNUSED;
295 break;
296 }
297 case TestType::INTERACTION_WITH_EXTENDED_DYNAMIC_STATE3:
298 {
299 m_useStencilInReadFrag = false;
300 m_colorAttachmentCount = 4;
301 m_colorAttachmentLocations = {{0, 3, 1, 2}};
302 m_depthInputAttachmentIndex = 4;
303 m_stencilInputAttachmentIndex = VK_ATTACHMENT_UNUSED;
304 break;
305 }
306 default:
307 DE_ASSERT(false);
308 break;
309 }
310
311 CalculateExpectedValues();
312 }
313
GetRemappedColorAttachment(uint32_t inputDrawId,uint32_t location) const314 uint32_t BasicLocalReadTestInstance::GetRemappedColorAttachment(uint32_t inputDrawId, uint32_t location) const
315 {
316 uint32_t attIndexRemaped = VK_ATTACHMENT_UNUSED;
317
318 // Find the remapped attachment index of a output color with decorator location = colorIdx in generateWriteFragSource
319 for (uint32_t i = 0; i < m_colorAttachmentCount; i++)
320 {
321 if (location == m_colorAttachmentLocations[inputDrawId][i])
322 {
323 attIndexRemaped = i;
324 break;
325 }
326 }
327
328 return attIndexRemaped;
329 }
330
GetRemappedColorInputAttachment(uint32_t outputDrawId,uint32_t inputAttachmentIdx) const331 uint32_t BasicLocalReadTestInstance::GetRemappedColorInputAttachment(uint32_t outputDrawId,
332 uint32_t inputAttachmentIdx) const
333 {
334 // perform same operation as in frag1_* shader to calculate final expected value
335 uint32_t attIndexRemaped = VK_ATTACHMENT_UNUSED;
336
337 for (uint32_t i = 0; i < m_colorAttachmentCount; i++)
338 {
339 if (inputAttachmentIdx == m_colorAttachmentInputIndices[outputDrawId][i])
340 {
341 attIndexRemaped = i;
342 break;
343 }
344 }
345
346 DE_ASSERT(attIndexRemaped != VK_ATTACHMENT_UNUSED);
347
348 return attIndexRemaped;
349 }
350
CalculateExpectedValues()351 void BasicLocalReadTestInstance::CalculateExpectedValues()
352 {
353 // generate same valueas for each attachment as in frag0_* shader
354 std::vector<uint32_t> valuesPerColorAttachment(m_colorAttachmentCount, 0);
355
356 for (uint32_t inputDraw = 0; inputDraw < m_inputDrawsCount; ++inputDraw)
357 {
358 for (uint32_t colorIdx = 0; colorIdx < m_colorAttachmentCount / m_inputDrawsCount; colorIdx++)
359 {
360 uint32_t outColor = 0;
361 uint32_t attIndexRemaped = GetRemappedColorAttachment(inputDraw, colorIdx);
362
363 // Calculate the shader ouput in generateWriteFragSource
364 if ((UseColorWriteEnable() == false) || (m_colorWriteEnables[attIndexRemaped] == 1))
365 {
366 outColor = (2u * inputDraw + colorIdx + 1u) * (2u * inputDraw + colorIdx + 1u);
367 }
368
369 // Write color output to the remapped attachment
370 if (attIndexRemaped != VK_ATTACHMENT_UNUSED)
371 {
372 valuesPerColorAttachment[attIndexRemaped] = outColor;
373 }
374 }
375 }
376
377 // calculate expected values for all three output draws, same as it will be done in frag1_* shader
378 m_expectedValues.resize(m_outputDrawsCount);
379
380 for (uint32_t outputDraw = 0; outputDraw < m_outputDrawsCount; ++outputDraw)
381 {
382 // Depth read is 0.6 and stencil read is 1. Depth read is already enabled, but stencil read depends on test type.
383 const float depthRead = 0.6f;
384 const uint32_t stencilRead = 1;
385
386 if (m_testType == TestType::DEPTH_STENCIL_MAPPING_TO_NO_INDEX)
387 {
388 // Depth read and stencil read are both enabled
389 m_expectedValues[outputDraw] = static_cast<uint32_t>(depthRead * 1000) + stencilRead * 100;
390 }
391 else if (m_testType == TestType::DEPTH_STENCIL_MAPPING_TO_SAME_INDEX)
392 {
393 // Depth read and stencil read are both enabled
394 m_expectedValues[outputDraw] = static_cast<uint32_t>(depthRead * 1000) + stencilRead;
395 }
396 else
397 {
398 m_expectedValues[outputDraw] =
399 static_cast<uint32_t>(depthRead * 1000) + ((m_useStencilInReadFrag) ? (stencilRead * 1000) : 0);
400 }
401
402 // each output draw uses all attachments but remaped differently
403 for (uint32_t attIndex = 0; attIndex < m_colorAttachmentCount; ++attIndex)
404 {
405 uint32_t attIndexRemaped = GetRemappedColorInputAttachment(outputDraw, attIndex);
406
407 if (m_testType == TestType::DEPTH_STENCIL_MAPPING_TO_NO_INDEX)
408 {
409 // Accumulate inColor_i, in which inColor_i is the color attachment with location = i in shader
410 m_expectedValues[outputDraw] += valuesPerColorAttachment[attIndexRemaped];
411 }
412 else if (m_testType == TestType::DEPTH_STENCIL_MAPPING_TO_SAME_INDEX)
413 {
414 // No color is read
415 break;
416 }
417 else
418 {
419 // Accumulate i * inColor_i, in which inColor_i is the color attachment with location = i in shader
420 m_expectedValues[outputDraw] += (attIndex + 1u) * valuesPerColorAttachment[attIndexRemaped];
421 }
422 }
423 }
424 }
425
UseColorWriteEnable() const426 bool BasicLocalReadTestInstance::UseColorWriteEnable() const
427 {
428 return (m_testType == TestType::INTERACTION_WITH_COLOR_WRITE_ENABLE) ? true : false;
429 }
430
iterate(void)431 tcu::TestStatus BasicLocalReadTestInstance::iterate(void)
432 {
433 const DeviceInterface &vk = m_context.getDeviceInterface();
434 const VkDevice device = m_context.getDevice();
435 Allocator &memAlloc = m_context.getDefaultAllocator();
436 VkQueue queue = m_context.getUniversalQueue();
437 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
438 const VkImageSubresourceRange colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
439 const VkImageSubresourceRange dSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
440 const VkImageSubresourceRange sSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_STENCIL_BIT, 0u, 1u, 0u, 1u);
441 const VkImageSubresourceRange dsSRR = makeImageSubresourceRange(dSRR.aspectMask | sSRR.aspectMask, 0u, 1u, 0u, 1u);
442 const std::vector<VkViewport> viewports{makeViewport(m_renderSize, m_renderSize)};
443 const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize, m_renderSize)};
444 const bool useColorWriteEnable = UseColorWriteEnable();
445 const bool useUseExtendedDynamicState3(m_testType == TestType::INTERACTION_WITH_EXTENDED_DYNAMIC_STATE3);
446
447 // define few structures that will be modified and reused in multiple places
448 VkImageMemoryBarrier colorImageBarrier =
449 makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
450 VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR, 0, colorSRR);
451 VkImageMemoryBarrier dsImageBarrier =
452 makeImageMemoryBarrier(0, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
453 VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR, 0, dsSRR);
454 VkRenderingAttachmentInfo depthStencilAttachment{
455 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType sType;
456 DE_NULL, // const void* pNext;
457 DE_NULL, // VkImageView imageView;
458 VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR, // VkImageLayout imageLayout;
459 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
460 DE_NULL, // VkImageView resolveImageView;
461 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout;
462 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
463 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
464 makeClearValueColor(tcu::Vec4(0.0f)) // VkClearValue clearValue;
465 };
466 VkImageUsageFlags imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
467 VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
468 VkDescriptorImageInfo depthImageDescriptor(
469 makeDescriptorImageInfo(DE_NULL, DE_NULL, VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR));
470 VkDescriptorImageInfo stencilImageDescriptor(depthImageDescriptor);
471
472 // construct required containers
473 std::vector<ImageWithMemorySp> images(m_colorAttachmentCount + 1,
474 ImageWithMemorySp()); // +1 for depth+stencil image
475 std::vector<VkImageViewSp> imageViews(m_colorAttachmentCount + 3,
476 VkImageViewSp()); // +3 for separate depth and stencil and depth+stencil
477 std::vector<VkFormat> colorImageFormats(m_colorAttachmentCount, VK_FORMAT_R32_UINT);
478 std::vector<VkImageMemoryBarrier> colorImageBarriers(m_colorAttachmentCount, colorImageBarrier);
479 std::vector<VkRenderingAttachmentInfo> colorAttachments(m_colorAttachmentCount, depthStencilAttachment);
480 std::vector<VkDescriptorImageInfo> colorImageDescriptors(m_colorAttachmentCount, depthImageDescriptor);
481 std::vector<BufferWithMemorySp> outputBuffers(m_outputDrawsCount, BufferWithMemorySp());
482 std::vector<Move<VkPipeline>> writeGraphicsPipelines(m_inputDrawsCount);
483 std::vector<Move<VkPipeline>> readGraphicsPipelines(m_outputDrawsCount);
484
485 // create images and image views for color attachments and use same loop to fill other needed containers
486 for (uint32_t attIndex = 0; attIndex < m_colorAttachmentCount; ++attIndex)
487 {
488 images[attIndex] = createImage(m_context, m_renderSize, colorImageFormats[attIndex], imageUsage);
489 imageViews[attIndex] = VkImageViewSp(new vk::Move<VkImageView>(makeImageView(
490 vk, device, **images[attIndex], VK_IMAGE_VIEW_TYPE_2D, colorImageFormats[attIndex], colorSRR)));
491
492 colorImageBarriers[attIndex].image = **images[attIndex];
493 colorAttachments[attIndex].imageView = **imageViews[attIndex];
494 colorImageDescriptors[attIndex].imageView = **imageViews[attIndex];
495 }
496
497 // create image and image views for depth/stencil attachments
498 uint32_t depthIndex = m_colorAttachmentCount;
499 images[depthIndex] = createImage(m_context, m_renderSize, m_dsFormat,
500 VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
501 VK_IMAGE_USAGE_TRANSFER_DST_BIT);
502 imageViews[depthIndex] = VkImageViewSp(new vk::Move<VkImageView>(
503 makeImageView(vk, device, **images[depthIndex], VK_IMAGE_VIEW_TYPE_2D, m_dsFormat, dSRR)));
504 imageViews[depthIndex + 1] = VkImageViewSp(new vk::Move<VkImageView>(
505 makeImageView(vk, device, **images[depthIndex], VK_IMAGE_VIEW_TYPE_2D, m_dsFormat, sSRR)));
506 imageViews[depthIndex + 2] = VkImageViewSp(new vk::Move<VkImageView>(
507 makeImageView(vk, device, **images[depthIndex], VK_IMAGE_VIEW_TYPE_2D, m_dsFormat, dsSRR)));
508 dsImageBarrier.image = **images[depthIndex];
509 depthImageDescriptor.imageView = **imageViews[depthIndex];
510 stencilImageDescriptor.imageView = **imageViews[depthIndex + 1];
511 depthStencilAttachment.imageView = **imageViews[depthIndex + 2];
512
513 // define buffers for output
514 const VkDeviceSize outputBufferSize = static_cast<VkDeviceSize>(m_renderSize * m_renderSize * sizeof(uint32_t));
515 const VkBufferCreateInfo bufferCreateInfo =
516 makeBufferCreateInfo(outputBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
517 for (uint32_t buffIndex = 0; buffIndex < m_outputDrawsCount; ++buffIndex)
518 outputBuffers[buffIndex] = BufferWithMemorySp(
519 new BufferWithMemory(vk, device, memAlloc, bufferCreateInfo, MemoryRequirement::HostVisible));
520
521 // create descriptors, they are needed just for read pipelines (usually there is just one read pipeline)
522 Move<VkDescriptorPool> descriptorPool =
523 DescriptorPoolBuilder()
524 .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, (m_colorAttachmentCount + 2u) * m_outputDrawsCount)
525 .addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, m_outputDrawsCount)
526 .build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 2u * m_outputDrawsCount);
527
528 // first descriptor set contains all input attachments
529 DescriptorSetLayoutBuilder descriptorSetLayoutABuilder;
530 for (uint32_t attIndex = 0; attIndex < m_colorAttachmentCount + 2; ++attIndex)
531 descriptorSetLayoutABuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT);
532 Move<VkDescriptorSetLayout> descriptorSetLayoutA = descriptorSetLayoutABuilder.build(vk, device);
533
534 // second and following descriptor sets contain just single output buffer each
535 Move<VkDescriptorSetLayout> descriptorSetLayoutB =
536 DescriptorSetLayoutBuilder()
537 .addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_FRAGMENT_BIT)
538 .build(vk, device);
539
540 std::vector<Move<VkDescriptorSet>> bufferDescriptorSets(m_outputDrawsCount);
541 std::vector<Move<VkDescriptorSet>> inputAttachmentsDescriptorSets(m_outputDrawsCount);
542 for (uint32_t i = 0; i < m_outputDrawsCount; ++i)
543 {
544 inputAttachmentsDescriptorSets[i] = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayoutA);
545 bufferDescriptorSets[i] = makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayoutB);
546 }
547
548 // set descriptor sets for all input attachments
549 using DSLocation = DescriptorSetUpdateBuilder::Location;
550 DescriptorSetUpdateBuilder descriptorSetUpdateBuilder;
551 for (uint32_t i = 0; i < m_outputDrawsCount; ++i)
552 {
553 // content of the descriptor set with input attachment bindings must be consistent with the remapping
554 for (uint32_t attIndex = 0; attIndex < m_colorAttachmentCount; ++attIndex)
555 {
556 uint32_t remapedIndex = GetRemappedColorInputAttachment(i, attIndex);
557
558 descriptorSetUpdateBuilder.writeSingle(*inputAttachmentsDescriptorSets[i], DSLocation::binding(attIndex),
559 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
560 &colorImageDescriptors[remapedIndex]);
561 }
562 descriptorSetUpdateBuilder.writeSingle(*inputAttachmentsDescriptorSets[i],
563 DSLocation::binding(m_colorAttachmentCount),
564 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &depthImageDescriptor);
565 descriptorSetUpdateBuilder.writeSingle(*inputAttachmentsDescriptorSets[i],
566 DSLocation::binding(m_colorAttachmentCount + 1),
567 VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &stencilImageDescriptor);
568 }
569
570 // set descriptor sets for all output buffers
571 VkDescriptorBufferInfo bufferInfo = makeDescriptorBufferInfo(DE_NULL, 0u, VK_WHOLE_SIZE);
572 for (uint32_t buffIndex = 0; buffIndex < m_outputDrawsCount; ++buffIndex)
573 {
574 bufferInfo.buffer = **outputBuffers[buffIndex];
575 descriptorSetUpdateBuilder.writeSingle(*bufferDescriptorSets[buffIndex], DSLocation::binding(0),
576 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo);
577 }
578
579 // update descriptor sets
580 descriptorSetUpdateBuilder.update(vk, device);
581
582 // create components for pipelines
583 const VkPushConstantRange pushConstantRange = {VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4};
584 std::vector<VkDescriptorSetLayout> descriptorSetLayouts = {*descriptorSetLayoutA, *descriptorSetLayoutB};
585 Move<VkPipelineLayout> writePipelineLayout = makePipelineLayout(vk, device, 0, DE_NULL, 1u, &pushConstantRange);
586 Move<VkPipelineLayout> readPipelineLayout = makePipelineLayout(vk, device, descriptorSetLayouts);
587 Move<VkShaderModule> vertShaderModule =
588 createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
589 Move<VkShaderModule> writeFragShaderModule =
590 createShaderModule(vk, device, m_context.getBinaryCollection().get(m_writeFragName), 0);
591 Move<VkShaderModule> readFragShaderModule =
592 createShaderModule(vk, device, m_context.getBinaryCollection().get(m_readFragName), 0);
593
594 // define empty VertexInputState, full screen quad will be generated in vertex shader
595 const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
596
597 // define ColorBlendState so that we can write to multiple color attachments
598 const VkPipelineColorBlendAttachmentState colorBlendAttachmentState{0,
599 VK_BLEND_FACTOR_ZERO,
600 VK_BLEND_FACTOR_ZERO,
601 VK_BLEND_OP_ADD,
602 VK_BLEND_FACTOR_ZERO,
603 VK_BLEND_FACTOR_ZERO,
604 VK_BLEND_OP_ADD,
605 0xf};
606 std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates(m_colorAttachmentCount,
607 colorBlendAttachmentState);
608 VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = initVulkanStructure();
609 colorBlendStateCreateInfo.attachmentCount = (uint32_t)colorBlendAttachmentStates.size();
610 colorBlendStateCreateInfo.pAttachments = colorBlendAttachmentStates.data();
611
612 // define MultisampleState, it is only needed to test if CmdSetRasterizationSamplesEXT does not affect local_read remappings
613 VkPipelineMultisampleStateCreateInfo multisampleStateCreateInfo = initVulkanStructure();
614 multisampleStateCreateInfo.rasterizationSamples =
615 useUseExtendedDynamicState3 ? VK_SAMPLE_COUNT_2_BIT : VK_SAMPLE_COUNT_1_BIT;
616 multisampleStateCreateInfo.minSampleShading = 1.0f;
617
618 // define DepthStencilState so that we can write to depth and stencil attachments
619 const VkStencilOpState stencilOpState{
620 VK_STENCIL_OP_KEEP, // VkStencilOp failOp
621 VK_STENCIL_OP_INCREMENT_AND_CLAMP, // VkStencilOp passOp
622 VK_STENCIL_OP_KEEP, // VkStencilOp depthFailOp
623 VK_COMPARE_OP_ALWAYS, // VkCompareOp compareOp
624 0xffu, // uint32_t compareMask
625 0xffu, // uint32_t writeMask
626 0 // uint32_t reference
627 };
628 VkPipelineDepthStencilStateCreateInfo depthStencilStateCreateInfo{
629 VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, // VkStructureType sType
630 DE_NULL, // const void* pNext
631 0u, // VkPipelineDepthStencilStateCreateFlags flags
632 VK_TRUE, // VkBool32 depthTestEnable
633 VK_TRUE, // VkBool32 depthWriteEnable
634 VK_COMPARE_OP_GREATER, // VkCompareOp depthCompareOp
635 VK_FALSE, // VkBool32 depthBoundsTestEnable
636 VK_TRUE, // VkBool32 stencilTestEnable
637 stencilOpState, // VkStencilOpState front
638 stencilOpState, // VkStencilOpState back
639 0.0f, // float minDepthBounds
640 1.0f, // float maxDepthBounds
641 };
642
643 VkDynamicState dynamicState = VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
644 if (useUseExtendedDynamicState3)
645 dynamicState = VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT;
646 VkPipelineDynamicStateCreateInfo dynamicStateCreateInfo{
647 VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType
648 DE_NULL, // const void* pNext
649 0u, // VkPipelineDynamicStateCreateFlags flags
650 1u, // uint32_t dynamicStateCount
651 &dynamicState // const VkDynamicState* pDynamicStates
652 };
653 VkPipelineDynamicStateCreateInfo *writeDynamicStateCreateInfo = nullptr;
654 if (useColorWriteEnable || useUseExtendedDynamicState3)
655 writeDynamicStateCreateInfo = &dynamicStateCreateInfo;
656
657 VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocationInfo{
658 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR, DE_NULL, m_colorAttachmentCount, DE_NULL};
659 VkRenderingInputAttachmentIndexInfoKHR renderingInputAttachmentIndexInfo{
660 VK_STRUCTURE_TYPE_RENDERING_INPUT_ATTACHMENT_INDEX_INFO_KHR,
661 DE_NULL,
662 m_colorAttachmentCount,
663 DE_NULL,
664 &m_depthInputAttachmentIndex,
665 &m_stencilInputAttachmentIndex};
666 VkPipelineRenderingCreateInfo renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
667 &renderingAttachmentLocationInfo,
668 0u,
669 (uint32_t)colorImageFormats.size(),
670 colorImageFormats.data(),
671 m_dsFormat,
672 m_dsFormat};
673
674 // create write pipelines that writes to color attachments
675 for (uint32_t pipelineIndex = 0; pipelineIndex < m_inputDrawsCount; ++pipelineIndex)
676 {
677 renderingAttachmentLocationInfo.pColorAttachmentLocations = m_colorAttachmentLocations[pipelineIndex].data();
678 writeGraphicsPipelines[pipelineIndex] = makeGraphicsPipeline(
679 vk, device, *writePipelineLayout, *vertShaderModule, DE_NULL, DE_NULL, DE_NULL, *writeFragShaderModule,
680 DE_NULL, viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 0, &vertexInputState, DE_NULL,
681 &multisampleStateCreateInfo, &depthStencilStateCreateInfo, &colorBlendStateCreateInfo,
682 writeDynamicStateCreateInfo, &renderingCreateInfo);
683
684 // writte to depth and stencil only in first pipeline
685 depthStencilStateCreateInfo.depthTestEnable = false;
686 depthStencilStateCreateInfo.stencilTestEnable = false;
687 }
688
689 // read pipelines need input attachments remaping
690 renderingCreateInfo.pNext = &renderingInputAttachmentIndexInfo;
691
692 // read pipelines don't write to the color attachments
693 for (auto &cb : colorBlendAttachmentStates)
694 cb.colorWriteMask = 0;
695
696 // Per spec, if either of pDepthInputAttachmentIndex or pStencilInputAttachmentIndex are set to NULL it means that these are only accessible in the shader
697 // if the shader does not associate these input attachments with an InputAttachmentIndex.
698 if (m_testType == TestType::DEPTH_STENCIL_MAPPING_TO_NO_INDEX)
699 {
700 renderingInputAttachmentIndexInfo.pDepthInputAttachmentIndex = NULL;
701 renderingInputAttachmentIndexInfo.pStencilInputAttachmentIndex = NULL;
702 }
703
704 for (uint32_t pipelineIndex = 0; pipelineIndex < m_outputDrawsCount; ++pipelineIndex)
705 {
706 renderingInputAttachmentIndexInfo.pColorAttachmentInputIndices =
707 m_colorAttachmentInputIndices[pipelineIndex].data();
708 readGraphicsPipelines[pipelineIndex] = makeGraphicsPipeline(
709 vk, device, *readPipelineLayout, *vertShaderModule, DE_NULL, DE_NULL, DE_NULL, *readFragShaderModule,
710 DE_NULL, viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 1, 0, &vertexInputState, DE_NULL,
711 DE_NULL, DE_NULL, &colorBlendStateCreateInfo, DE_NULL, &renderingCreateInfo);
712 }
713
714 Move<VkCommandPool> commandPool =
715 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
716 Move<VkCommandBuffer> commandBuffer =
717 allocateCommandBuffer(vk, device, *commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
718 VkCommandBuffer cmdBuffer = *commandBuffer;
719
720 VkRenderingInfo renderingInfo{
721 VK_STRUCTURE_TYPE_RENDERING_INFO,
722 DE_NULL,
723 0u, // VkRenderingFlags flags
724 scissors[0], // VkRect2D renderArea
725 1u, // uint32_t layerCount
726 0u, // uint32_t viewMask
727 (uint32_t)colorAttachments.size(), // uint32_t colorAttachmentCount
728 colorAttachments.data(), // const VkRenderingAttachmentInfo* pColorAttachments
729 &depthStencilAttachment, // const VkRenderingAttachmentInfo* pDepthAttachment
730 &depthStencilAttachment // const VkRenderingAttachmentInfo* pStencilAttachment
731 };
732
733 // record commands
734 beginCommandBuffer(vk, cmdBuffer);
735
736 // transition all images to proper layouts
737 vk.cmdPipelineBarrier(cmdBuffer, 0, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, DE_NULL, 0, DE_NULL,
738 (uint32_t)colorImageBarriers.size(), colorImageBarriers.data());
739 vk.cmdPipelineBarrier(cmdBuffer, 0, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, 0, 0, DE_NULL, 0, DE_NULL, 1u,
740 &dsImageBarrier);
741
742 vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
743
744 // draw using write pipelines
745 for (uint32_t pipelineIndex = 0; pipelineIndex < m_inputDrawsCount; ++pipelineIndex)
746 {
747 renderingAttachmentLocationInfo.pColorAttachmentLocations = m_colorAttachmentLocations[pipelineIndex].data();
748
749 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *writeGraphicsPipelines[pipelineIndex]);
750 vk.cmdPushConstants(cmdBuffer, *writePipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, 4, &pipelineIndex);
751 vk.cmdSetRenderingAttachmentLocationsKHR(cmdBuffer, &renderingAttachmentLocationInfo);
752
753 if (useColorWriteEnable)
754 vk.cmdSetColorWriteEnableEXT(cmdBuffer, 4u, m_colorWriteEnables);
755 if (useUseExtendedDynamicState3)
756 vk.cmdSetRasterizationSamplesEXT(cmdBuffer, VK_SAMPLE_COUNT_1_BIT);
757
758 vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
759 }
760
761 // reuse existing barrier structures to finish rendering before next subpass
762 dsImageBarrier.oldLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
763 dsImageBarrier.newLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
764 dsImageBarrier.srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
765 dsImageBarrier.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
766 for (auto &barrier : colorImageBarriers)
767 {
768 barrier.oldLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
769 barrier.newLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
770 barrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
771 barrier.dstAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
772 }
773 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
774 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_DEPENDENCY_BY_REGION_BIT, 0, DE_NULL, 0, DE_NULL,
775 (uint32_t)colorImageBarriers.size(), colorImageBarriers.data());
776 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
777 VK_DEPENDENCY_BY_REGION_BIT, 0, DE_NULL, 0, DE_NULL, 1u, &dsImageBarrier);
778
779 // draw using read pipelines
780 for (uint32_t pipelineIndex = 0; pipelineIndex < m_outputDrawsCount; ++pipelineIndex)
781 {
782 VkDescriptorSet descriptorSets[] = {*inputAttachmentsDescriptorSets[pipelineIndex],
783 *bufferDescriptorSets[pipelineIndex]};
784 renderingInputAttachmentIndexInfo.pColorAttachmentInputIndices =
785 m_colorAttachmentInputIndices[pipelineIndex].data();
786
787 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *readGraphicsPipelines[pipelineIndex]);
788 vk.cmdSetRenderingInputAttachmentIndicesKHR(cmdBuffer, &renderingInputAttachmentIndexInfo);
789 vk.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *readPipelineLayout, 0u, 2u,
790 descriptorSets, 0u, DE_NULL);
791 vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
792 }
793
794 vk.cmdEndRendering(cmdBuffer);
795
796 endCommandBuffer(vk, cmdBuffer);
797 submitCommandsAndWait(vk, device, queue, cmdBuffer);
798
799 // verify all output buffers
800 bool allOk = true;
801 auto &log = m_context.getTestContext().getLog();
802 DE_ASSERT(m_expectedValues.size() == m_outputDrawsCount);
803 for (uint32_t buffIndex = 0; buffIndex < m_outputDrawsCount; ++buffIndex)
804 {
805 // get output buffer
806 const Allocation &bufferAllocation = outputBuffers[buffIndex]->getAllocation();
807 invalidateAlloc(vk, device, bufferAllocation);
808
809 // validate result
810 const uint32_t *bufferPtr = static_cast<uint32_t *>(bufferAllocation.getHostPtr());
811 const uint32_t expected = m_expectedValues[buffIndex];
812 for (uint32_t i = 0; i < m_renderSize * m_renderSize; ++i)
813 {
814 if (bufferPtr[i] != expected)
815 {
816 log << tcu::TestLog::Message << "Result for buffer " << buffIndex << ": expected " << expected
817 << " got " << bufferPtr[i] << " at index " << i << tcu::TestLog::EndMessage;
818 allOk = false;
819 break;
820 }
821 }
822 }
823
824 if (allOk)
825 return tcu::TestStatus::pass("Pass");
826
827 const VkBufferCreateInfo attBufferCreateInfo =
828 makeBufferCreateInfo(outputBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
829 BufferWithMemorySp attBuffer(
830 new BufferWithMemory(vk, device, memAlloc, attBufferCreateInfo, MemoryRequirement::HostVisible));
831 vk::VkBufferImageCopy region{0, 0, 0, {1, 0, 0, 1}, {0, 0, 0}, {1, 1, 1}};
832 auto &barrier = colorImageBarriers[0];
833
834 // reuse first barrier structure
835 barrier.oldLayout = VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR;
836 barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
837 barrier.srcAccessMask = VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
838 barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
839
840 // log content of each color attachment
841 for (uint32_t attIndex = 0; attIndex < m_colorAttachmentCount; ++attIndex)
842 {
843 barrier.image = **images[attIndex];
844 commandBuffer = allocateCommandBuffer(vk, device, *commandPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
845 cmdBuffer = *commandBuffer;
846
847 beginCommandBuffer(vk, cmdBuffer);
848 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, 0, 0,
849 0, 1, &barrier);
850 vk.cmdCopyImageToBuffer(cmdBuffer, barrier.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **attBuffer, 1,
851 ®ion);
852 endCommandBuffer(vk, cmdBuffer);
853
854 submitCommandsAndWait(vk, device, queue, cmdBuffer);
855
856 const Allocation &bufferAllocation = attBuffer->getAllocation();
857 invalidateAlloc(vk, device, bufferAllocation);
858 const uint32_t *bufferPtr = static_cast<uint32_t *>(bufferAllocation.getHostPtr());
859 log << tcu::TestLog::Message << "Color attachment " << attIndex << " contains: " << bufferPtr[0]
860 << tcu::TestLog::EndMessage;
861 }
862
863 return tcu::TestStatus::fail("Fail");
864 }
865
866 class MappingWithBlendStateTestInstance : public vkt::TestInstance
867 {
868 public:
869 MappingWithBlendStateTestInstance(Context &context, const TestType testType);
870
871 protected:
872 tcu::TestStatus iterate(void) override;
873
874 private:
875 const uint32_t m_renderSize;
876 };
877
MappingWithBlendStateTestInstance(Context & context,const TestType testType)878 MappingWithBlendStateTestInstance::MappingWithBlendStateTestInstance(Context &context, const TestType testType)
879 : vkt::TestInstance(context)
880 , m_renderSize(16)
881 {
882 DE_UNREF(testType);
883 }
884
iterate()885 tcu::TestStatus MappingWithBlendStateTestInstance::iterate()
886 {
887 const DeviceInterface &vk = m_context.getDeviceInterface();
888 const VkDevice device = m_context.getDevice();
889 Allocator &memAlloc = m_context.getDefaultAllocator();
890 VkQueue queue = m_context.getUniversalQueue();
891 const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
892 const VkFormat imageFormat = VK_FORMAT_R8G8B8A8_UNORM;
893 const tcu::TextureFormat textureFormat = mapVkFormat(imageFormat);
894 const uint32_t colorAttachmentCount = 4u;
895
896 const VkImageSubresourceRange colorSRR = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
897 const VkImageSubresourceLayers colorSL = makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
898 const VkBufferImageCopy copyRegion = makeBufferImageCopy({m_renderSize, m_renderSize, 1u}, colorSL);
899
900 Move<VkCommandPool> commandPool =
901 createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex);
902 Move<VkCommandBuffer> commandBuffer =
903 allocateCommandBuffer(vk, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
904 VkCommandBuffer cmdBuffer = *commandBuffer;
905
906 const std::vector<VkViewport> viewports{makeViewport(m_renderSize, m_renderSize)};
907 const std::vector<VkRect2D> scissors{makeRect2D(m_renderSize, m_renderSize)};
908
909 const tcu::Vec4 clearValues[] // blend src color
910 {
911 {0.5f, 0.5f, 0.4f, 1.0f},
912 {0.2f, 0.4f, 0.3f, 0.1f},
913 {0.2f, 1.0f, 0.5f, 0.8f},
914 {1.0f, 0.1f, 0.3f, 0.5f},
915 };
916 DE_ASSERT(DE_LENGTH_OF_ARRAY(clearValues) == colorAttachmentCount);
917
918 const VkPipelineColorBlendAttachmentState colorBlendAttachmentStates[]{
919 {1, VK_BLEND_FACTOR_SRC_ALPHA, VK_BLEND_FACTOR_DST_ALPHA, VK_BLEND_OP_ADD, VK_BLEND_FACTOR_SRC_ALPHA,
920 VK_BLEND_FACTOR_DST_ALPHA, VK_BLEND_OP_MAX, 0xf},
921 {1, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, VK_BLEND_OP_SUBTRACT,
922 VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, VK_BLEND_FACTOR_DST_ALPHA, VK_BLEND_OP_ADD, 0xf},
923 {1, VK_BLEND_FACTOR_ONE, VK_BLEND_FACTOR_ONE, VK_BLEND_OP_MIN, VK_BLEND_FACTOR_SRC_ALPHA,
924 VK_BLEND_FACTOR_DST_ALPHA, VK_BLEND_OP_MAX, 0xf},
925 {1, VK_BLEND_FACTOR_SRC_COLOR, VK_BLEND_FACTOR_DST_COLOR, VK_BLEND_OP_MAX, VK_BLEND_FACTOR_SRC_ALPHA,
926 VK_BLEND_FACTOR_DST_ALPHA, VK_BLEND_OP_MIN, 0xf},
927 };
928 DE_ASSERT(DE_LENGTH_OF_ARRAY(colorBlendAttachmentStates) == colorAttachmentCount);
929
930 const uint32_t colorAttachmentLocations[]{3, 0, 2, 1};
931 DE_ASSERT(DE_LENGTH_OF_ARRAY(colorAttachmentLocations) == colorAttachmentCount);
932
933 VkRenderingAttachmentInfo colorAttachment{
934 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO, // VkStructureType sType;
935 DE_NULL, // const void* pNext;
936 DE_NULL, // VkImageView imageView;
937 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout imageLayout;
938 VK_RESOLVE_MODE_NONE, // VkResolveModeFlagBits resolveMode;
939 DE_NULL, // VkImageView resolveImageView;
940 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout resolveImageLayout;
941 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp;
942 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp;
943 makeClearValueColor(tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)) // VkClearValue clearValue;
944 };
945 VkImageMemoryBarrier imageMemoryBarrier =
946 makeImageMemoryBarrier(0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
947 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, DE_NULL, colorSRR);
948 const VkDeviceSize outputBufferSize = (VkDeviceSize)m_renderSize * m_renderSize * tcu::getPixelSize(textureFormat);
949 const VkBufferCreateInfo outputBufferInfo =
950 makeBufferCreateInfo(outputBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
951
952 // construct required containers
953 std::vector<ImageWithMemorySp> images(colorAttachmentCount, ImageWithMemorySp());
954 std::vector<VkImageViewSp> imageViews(colorAttachmentCount, VkImageViewSp());
955 std::vector<VkFormat> colorImageFormats(colorAttachmentCount, imageFormat);
956 std::vector<VkRenderingAttachmentInfo> colorAttachments(colorAttachmentCount, colorAttachment);
957 std::vector<VkImageMemoryBarrier> colorImageBarriers(colorAttachmentCount, imageMemoryBarrier);
958 std::vector<BufferWithMemorySp> outputBuffers(colorAttachmentCount, BufferWithMemorySp());
959
960 for (uint32_t i = 0; i < colorAttachmentCount; ++i)
961 {
962 // create images and image views for input attachments
963 images[i] = createImage(m_context, m_renderSize, imageFormat,
964 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
965 imageViews[i] = VkImageViewSp(new vk::Move<VkImageView>(
966 makeImageView(vk, device, **images[i], VK_IMAGE_VIEW_TYPE_2D, imageFormat, colorSRR)));
967
968 colorAttachments[i].imageView = **imageViews[i];
969 colorAttachments[i].clearValue = makeClearValueColor(clearValues[i]);
970 colorImageBarriers[i].image = **images[i];
971
972 // create output buffers that will be used to get attachments data
973 outputBuffers[i] = BufferWithMemorySp(
974 new BufferWithMemory(vk, device, memAlloc, outputBufferInfo, MemoryRequirement::HostVisible));
975 }
976
977 Move<VkPipelineLayout> pipelineLayout = makePipelineLayout(vk, device, DE_NULL);
978 Move<VkShaderModule> vertShaderModule =
979 createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0);
980 Move<VkShaderModule> fragShaderModule =
981 createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0);
982
983 // define empty VertexInputState, full screen quad will be generated in vertex shader
984 const VkPipelineVertexInputStateCreateInfo vertexInputState = initVulkanStructure();
985
986 // define ColorBlendState so that we can write to multiple color attachments
987 VkPipelineColorBlendStateCreateInfo colorBlendStateCreateInfo = initVulkanStructure();
988 colorBlendStateCreateInfo.attachmentCount = colorAttachmentCount;
989 colorBlendStateCreateInfo.pAttachments = colorBlendAttachmentStates;
990
991 VkRenderingAttachmentLocationInfoKHR renderingAttachmentLocations{
992 VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_LOCATION_INFO_KHR, DE_NULL, colorAttachmentCount,
993 colorAttachmentLocations};
994 VkPipelineRenderingCreateInfo renderingCreateInfo{VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
995 &renderingAttachmentLocations,
996 0u,
997 colorAttachmentCount,
998 colorImageFormats.data(),
999 VK_FORMAT_UNDEFINED,
1000 VK_FORMAT_UNDEFINED};
1001
1002 Move<VkPipeline> graphicsPipeline = makeGraphicsPipeline(
1003 vk, device, *pipelineLayout, *vertShaderModule, DE_NULL, DE_NULL, DE_NULL, *fragShaderModule, DE_NULL,
1004 viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 0, &vertexInputState, DE_NULL, DE_NULL, DE_NULL,
1005 &colorBlendStateCreateInfo, DE_NULL, &renderingCreateInfo);
1006
1007 VkRenderingInfo renderingInfo{
1008 VK_STRUCTURE_TYPE_RENDERING_INFO,
1009 DE_NULL,
1010 0u, // VkRenderingFlags flags
1011 scissors[0], // VkRect2D renderArea
1012 1u, // uint32_t layerCount
1013 0u, // uint32_t viewMask
1014 colorAttachmentCount, // uint32_t colorAttachmentCount
1015 colorAttachments.data(), // const VkRenderingAttachmentInfo* pColorAttachments
1016 DE_NULL, // const VkRenderingAttachmentInfo* pDepthAttachment
1017 DE_NULL // const VkRenderingAttachmentInfo* pStencilAttachment
1018 };
1019
1020 // record primary command buffer
1021 beginCommandBuffer(vk, cmdBuffer);
1022
1023 // transfer layout to color attachment optimal
1024 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_NONE, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, 0u,
1025 0u, 0u, colorAttachmentCount, colorImageBarriers.data());
1026
1027 vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
1028
1029 // remaping should affect to which attachments shader writes but not blend state
1030 vk.cmdSetRenderingAttachmentLocationsKHR(cmdBuffer, &renderingAttachmentLocations);
1031
1032 vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
1033 vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
1034
1035 vk.cmdEndRendering(cmdBuffer);
1036
1037 // transition colorbuffers layout to transfer source optimal
1038 for (uint32_t i = 0; i < colorAttachmentCount; ++i)
1039 {
1040 colorImageBarriers[i].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
1041 colorImageBarriers[i].dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1042 colorImageBarriers[i].oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1043 colorImageBarriers[i].newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1044 }
1045 vk.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1046 0u, 0u, 0u, 0u, colorAttachmentCount, colorImageBarriers.data());
1047
1048 // read back color images
1049 for (uint32_t i = 0; i < colorAttachmentCount; ++i)
1050 vk.cmdCopyImageToBuffer(cmdBuffer, **images[i], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, **outputBuffers[i], 1u,
1051 ©Region);
1052
1053 endCommandBuffer(vk, cmdBuffer);
1054 submitCommandsAndWait(vk, device, queue, cmdBuffer);
1055
1056 const tcu::Vec4 expectedLeftSideColors[]{
1057 {0.50f, 0.98f, 0.72f, 1.00f},
1058 {0.42f, 0.44f, 0.63f, 0.17f},
1059 {0.10f, 0.30f, 0.50f, 0.80f},
1060 {1.00f, 0.40f, 0.30f, 0.50f},
1061 };
1062 DE_ASSERT(DE_LENGTH_OF_ARRAY(expectedLeftSideColors) == colorAttachmentCount);
1063
1064 bool testPassed(true);
1065 const tcu::Vec4 colorPrecision(0.05f);
1066 auto &log(m_context.getTestContext().getLog());
1067
1068 // verify result
1069 for (uint32_t i = 0; i < colorAttachmentCount; ++i)
1070 {
1071 bool colorIsCorrect = true;
1072 auto &allocation = outputBuffers[i]->getAllocation();
1073 invalidateAlloc(vk, device, allocation);
1074
1075 tcu::ConstPixelBufferAccess outputAccess(textureFormat, m_renderSize, m_renderSize, 1u,
1076 allocation.getHostPtr());
1077
1078 // check one fragment from the left side of image (after blending)
1079 tcu::Vec4 fragmentColorOnLeftSide = outputAccess.getPixel(i, i, 0);
1080 if (tcu::boolAny(
1081 tcu::greaterThan(tcu::absDiff(fragmentColorOnLeftSide, expectedLeftSideColors[i]), colorPrecision)))
1082 colorIsCorrect = false;
1083
1084 // check one fragment from the right side of image (clear color should be there)
1085 tcu::Vec4 fragmentColorOnRightSide(outputAccess.getPixel(m_renderSize - 1 - i, m_renderSize - 1 - i, 0));
1086 if (tcu::boolAny(tcu::greaterThan(tcu::absDiff(fragmentColorOnRightSide, clearValues[i]), colorPrecision)))
1087 colorIsCorrect = false;
1088
1089 if (!colorIsCorrect)
1090 {
1091 std::string imageName = std::string("Attachment") + std::to_string(i);
1092 log << tcu::TestLog::Image(imageName, imageName, outputAccess);
1093 testPassed = false;
1094 }
1095 }
1096
1097 if (testPassed)
1098 return tcu::TestStatus::pass("Pass");
1099
1100 return tcu::TestStatus::fail("Fail");
1101 }
1102
1103 class LocalReadTestCase : public vkt::TestCase
1104 {
1105 public:
1106 LocalReadTestCase(tcu::TestContext &context, const std::string &name, TestType testType);
1107 virtual ~LocalReadTestCase(void) = default;
1108
1109 protected:
1110 void checkSupport(Context &context) const override;
1111 void initPrograms(SourceCollections &programCollection) const override;
1112 TestInstance *createInstance(Context &context) const override;
1113
1114 TestType m_testType;
1115 };
1116
LocalReadTestCase(tcu::TestContext & context,const std::string & name,TestType testType)1117 LocalReadTestCase::LocalReadTestCase(tcu::TestContext &context, const std::string &name, TestType testType)
1118 : vkt::TestCase(context, name)
1119 , m_testType(testType)
1120 {
1121 }
1122
checkSupport(Context & context) const1123 void LocalReadTestCase::checkSupport(Context &context) const
1124 {
1125 context.requireDeviceFunctionality("VK_KHR_dynamic_rendering_local_read");
1126
1127 if (m_testType == TestType::INTERACTION_WITH_COLOR_WRITE_ENABLE)
1128 context.requireDeviceFunctionality("VK_EXT_color_write_enable");
1129 else if (m_testType == TestType::INTERACTION_WITH_EXTENDED_DYNAMIC_STATE3)
1130 {
1131 context.requireDeviceFunctionality("VK_EXT_extended_dynamic_state3");
1132 if (!context.getExtendedDynamicState3FeaturesEXT().extendedDynamicState3RasterizationSamples)
1133 TCU_THROW(NotSupportedError, "extendedDynamicState3RasterizationSamples not supported");
1134 }
1135 }
1136
initPrograms(SourceCollections & programCollection) const1137 void LocalReadTestCase::initPrograms(SourceCollections &programCollection) const
1138 {
1139 // vertex shader generates fullscreen quad
1140 std::string vertSrc("#version 450\n"
1141 "void main (void)\n"
1142 "{\n"
1143 " const float x = (-1.0+2.0*((gl_VertexIndex & 2)>>1));\n"
1144 " const float y = ( 1.0-2.0* (gl_VertexIndex % 2));\n"
1145 " gl_Position = vec4(x, y, 0.6, 1.0);\n"
1146 "}\n");
1147 auto &glslSources = programCollection.glslSources;
1148 glslSources.add("vert") << glu::VertexSource(vertSrc);
1149
1150 // helper lambda that generates fragment shader that writes to specified number of color attachments
1151 auto generateWriteFragSource = [](uint32_t colorAttachmentCount)
1152 {
1153 std::stringstream fragSrc;
1154 fragSrc << "#version 450\n"
1155 "layout(push_constant) uniform InputDraw {\n"
1156 " uint count;\n"
1157 "} inputDraw;\n";
1158 for (uint32_t i = 0; i < colorAttachmentCount; ++i)
1159 fragSrc << "layout(location=" << i << ") out uint outColor" << i << ";\n";
1160 fragSrc << "void main()\n{\n";
1161 for (uint32_t i = 0; i < colorAttachmentCount; ++i)
1162 {
1163 fragSrc << " outColor" << i << " = 2u * inputDraw.count + " << i + 1 << ";\n";
1164 fragSrc << " outColor" << i << " *= "
1165 << "outColor" << i << ";\n";
1166 }
1167 fragSrc << "}\n";
1168 return fragSrc.str();
1169 };
1170
1171 // helper lambda that generates fragment shader that reads from specified number of input attachments
1172 auto generateReadFragSource = [](uint32_t inputAttachmentCount, bool useStencil = true)
1173 {
1174 uint32_t colorInputAttachmentCount = inputAttachmentCount - 1u - useStencil;
1175 std::stringstream fragSrc;
1176 fragSrc << "#version 450\n";
1177 for (uint32_t i = 0; i < colorInputAttachmentCount; ++i)
1178 fragSrc << "layout(input_attachment_index=" << i << ", binding=" << i << ") uniform usubpassInput inColor"
1179 << i << ";\n";
1180
1181 fragSrc << "layout(input_attachment_index = " << colorInputAttachmentCount
1182 << ", binding = " << colorInputAttachmentCount << ") uniform subpassInput inDepth;\n";
1183 if (useStencil)
1184 fragSrc << "layout(input_attachment_index = " << colorInputAttachmentCount + 1
1185 << ", binding = " << colorInputAttachmentCount + 1 << ") uniform usubpassInput inStencil;\n";
1186
1187 fragSrc << "layout(set=1, binding=0, std430) writeonly buffer Output\n{\n"
1188 " uint v[];\n"
1189 "} outBuffer;\n"
1190 "void main()\n{\n"
1191 " uint result = 0;\n";
1192 for (uint32_t i = 0; i < colorInputAttachmentCount; ++i)
1193 fragSrc << " result = result + " << i + 1 << " * subpassLoad(inColor" << i << ").x; \n";
1194 fragSrc << " result = result + uint(subpassLoad(inDepth).x * 1000);\n"; // 0.6*1000
1195 if (useStencil)
1196 fragSrc << " result = result + uint(subpassLoad(inStencil).x * 1000);\n"; // 1 * 1000
1197 fragSrc << " const uvec2 i = uvec2(trunc(gl_FragCoord.xy));\n"
1198 " outBuffer.v[i.x+i.y*16] = result;\n"
1199 "}\n";
1200 return fragSrc.str();
1201 };
1202
1203 if (m_testType == TestType::MAX_INPUT_ATTACHMENTS)
1204 {
1205 // generate fragment shader for maximal number of input attachments;
1206 // during test execution proper shader will be picked
1207 for (uint32_t inputAttachmentCount : inputAttachmentsPossibleValues)
1208 {
1209 // subtract 2 because we will write to depth and stencil and those
1210 // attachments will later consume 2 input attachment slots
1211 uint32_t colorAttachmentCount = inputAttachmentCount - 2u;
1212 glslSources.add(std::string("frag0_") + std::to_string(colorAttachmentCount))
1213 << glu::FragmentSource(generateWriteFragSource(colorAttachmentCount));
1214 }
1215 }
1216 else if (m_testType == TestType::MAX_ATTACHMENTS_REMAPPED_REPEATEDLY)
1217 {
1218 glslSources.add("frag0") << glu::FragmentSource(generateWriteFragSource(2));
1219 }
1220 else if (m_testType == TestType::UNUSED_WRITEN_DISCARDED)
1221 {
1222 glslSources.add("frag0") << glu::FragmentSource(generateWriteFragSource(4));
1223 glslSources.add("frag1") << glu::FragmentSource(generateReadFragSource(6));
1224 }
1225 else if (m_testType == TestType::DEPTH_STENCIL_MAPPING_TO_NO_INDEX)
1226 {
1227 glslSources.add("frag0") << glu::FragmentSource(generateWriteFragSource(2));
1228
1229 // Per spec, if either of pDepthInputAttachmentIndex or pStencilInputAttachmentIndex are set to
1230 // NULL it means that these are only accessible in the shader if the shader does not associate
1231 // these input attachments with an InputAttachmentIndex.
1232
1233 // NOTE at the memoment glslang doesn't support input attachments without
1234 // input_attachment_index qualifiers
1235
1236 //std::string fragSrc(
1237 // "#version 450\n"
1238 // "layout(input_attachment_index=0, binding=0) uniform usubpassInput inColor0;\n"
1239 // "layout(input_attachment_index=1, binding=1) uniform usubpassInput inColor1;\n"
1240 // "layout(binding=2) uniform subpassInput inDepth;\n"
1241 // "layout(binding=3) uniform usubpassInput inStencil;\n"
1242 // "layout(set=1, binding=0, std430) writeonly buffer Output\n{\n"
1243 // " uint v[];\n"
1244 // "} outBuffer;\n"
1245 // "void main()\n{\n"
1246 // " uint result = subpassLoad(inColor0).x + subpassLoad(inColor1).x;\n" // 1 + 2
1247 // " result = result + uint(subpassLoad(inDepth).x * 1000);\n" // 0.6*1000
1248 // " result = result + uint(subpassLoad(inStencil).x * 100);\n" // 1*100
1249 // " const uvec2 i = uvec2(trunc(gl_FragCoord.xy));\n"
1250 // " outBuffer.v[i.x+i.y*16] = result;\n"
1251 // "}\n");
1252 //glslSources.add("frag1") << glu::FragmentSource(fragSrc);
1253
1254 programCollection.spirvAsmSources.add("frag1") << "OpCapability Shader\n"
1255 "OpCapability InputAttachment\n"
1256 "%1 = OpExtInstImport \"GLSL.std.450\";\n"
1257 "OpMemoryModel Logical GLSL450\n"
1258 "OpEntryPoint Fragment %4 \"main\" %51\n"
1259 "OpExecutionMode %4 OriginUpperLeft\n"
1260 "OpDecorate %11 DescriptorSet 0\n"
1261 "OpDecorate %11 Binding 0\n"
1262 "OpDecorate %11 InputAttachmentIndex 0\n"
1263 "OpDecorate %21 DescriptorSet 0\n"
1264 "OpDecorate %21 Binding 1\n"
1265 "OpDecorate %21 InputAttachmentIndex 1\n"
1266 "OpDecorate %30 DescriptorSet 0\n"
1267 "OpDecorate %30 Binding 2\n"
1268 //"OpDecorate %30 InputAttachmentIndex 2\n"
1269 "OpDecorate %40 DescriptorSet 0\n"
1270 "OpDecorate %40 Binding 3\n"
1271 //"OpDecorate %40 InputAttachmentIndex 3\n"
1272 "OpDecorate %51 BuiltIn FragCoord\n"
1273 "OpDecorate %57 ArrayStride 4\n"
1274 "OpMemberDecorate %58 0 NonReadable\n"
1275 "OpMemberDecorate %58 0 Offset 0\n"
1276 "OpDecorate %58 BufferBlock\n"
1277 "OpDecorate %60 DescriptorSet 1\n"
1278 "OpDecorate %60 Binding 0\n"
1279 "%2 = OpTypeVoid\n"
1280 "%3 = OpTypeFunction %2\n"
1281 "%6 = OpTypeInt 32 0\n"
1282 "%7 = OpTypePointer Function %6\n"
1283 "%9 = OpTypeImage %6 SubpassData 0 0 0 2 Unknown\n"
1284 "%10 = OpTypePointer UniformConstant %9\n"
1285 "%11 = OpVariable %10 UniformConstant\n"
1286 "%13 = OpTypeInt 32 1\n"
1287 "%14 = OpConstant %13 0\n"
1288 "%15 = OpTypeVector %13 2\n"
1289 "%16 = OpConstantComposite %15 %14 %14\n"
1290 "%17 = OpTypeVector %6 4\n"
1291 "%19 = OpConstant %6 0\n"
1292 "%21 = OpVariable %10 UniformConstant\n"
1293 "%27 = OpTypeFloat 32\n"
1294 "%28 = OpTypeImage %27 SubpassData 0 0 0 2 Unknown\n"
1295 "%29 = OpTypePointer UniformConstant %28\n"
1296 "%30 = OpVariable %29 UniformConstant\n"
1297 "%32 = OpTypeVector %27 4\n"
1298 "%35 = OpConstant %27 1000\n"
1299 "%40 = OpVariable %10 UniformConstant\n"
1300 "%44 = OpConstant %6 100\n"
1301 "%47 = OpTypeVector %6 2\n"
1302 "%48 = OpTypePointer Function %47\n"
1303 "%50 = OpTypePointer Input %32\n"
1304 "%51 = OpVariable %50 Input\n"
1305 "%52 = OpTypeVector %27 2\n"
1306 "%57 = OpTypeRuntimeArray %6\n"
1307 "%58 = OpTypeStruct %57\n"
1308 "%59 = OpTypePointer Uniform %58\n"
1309 "%60 = OpVariable %59 Uniform\n"
1310 "%63 = OpConstant %6 1\n"
1311 "%66 = OpConstant %6 16\n"
1312 "%70 = OpTypePointer Uniform %6\n"
1313 "%4 = OpFunction %2 None %3\n"
1314 "%5 = OpLabel\n"
1315 "%8 = OpVariable %7 Function\n"
1316 "%49 = OpVariable %48 Function\n"
1317 "%12 = OpLoad %9 %11\n"
1318 "%18 = OpImageRead %17 %12 %16\n"
1319 "%20 = OpCompositeExtract %6 %18 0\n"
1320 "%22 = OpLoad %9 %21\n"
1321 "%23 = OpImageRead %17 %22 %16\n"
1322 "%24 = OpCompositeExtract %6 %23 0\n"
1323 "%25 = OpIAdd %6 %20 %24\n"
1324 "OpStore %8 %25\n"
1325 "%26 = OpLoad %6 %8\n"
1326 "%31 = OpLoad %28 %30\n"
1327 "%33 = OpImageRead %32 %31 %16\n"
1328 "%34 = OpCompositeExtract %27 %33 0\n"
1329 "%36 = OpFMul %27 %34 %35\n"
1330 "%37 = OpConvertFToU %6 %36\n"
1331 "%38 = OpIAdd %6 %26 %37\n"
1332 "OpStore %8 %38\n"
1333 "%39 = OpLoad %6 %8\n"
1334 "%41 = OpLoad %9 %40\n"
1335 "%42 = OpImageRead %17 %41 %16\n"
1336 "%43 = OpCompositeExtract %6 %42 0\n"
1337 "%45 = OpIMul %6 %43 %44\n"
1338 "%46 = OpIAdd %6 %39 %45\n"
1339 "OpStore %8 %46\n"
1340 "%53 = OpLoad %32 %51\n"
1341 "%54 = OpVectorShuffle %52 %53 %53 0 1\n"
1342 "%55 = OpExtInst %52 %1 Trunc %54\n"
1343 "%56 = OpConvertFToU %47 %55\n"
1344 "OpStore %49 %56\n"
1345 "%61 = OpAccessChain %7 %49 %19\n"
1346 "%62 = OpLoad %6 %61\n"
1347 "%64 = OpAccessChain %7 %49 %63\n"
1348 "%65 = OpLoad %6 %64\n"
1349 "%67 = OpIMul %6 %65 %66\n"
1350 "%68 = OpIAdd %6 %62 %67\n"
1351 "%69 = OpLoad %6 %8\n"
1352 "%71 = OpAccessChain %70 %60 %14 %68\n"
1353 "OpStore %71 %69\n"
1354 "OpReturn\n"
1355 "OpFunctionEnd\n";
1356 }
1357 else if ((m_testType == TestType::DEPTH_MAPPING_STENCIL_NOT) ||
1358 (m_testType == TestType::INTERACTION_WITH_COLOR_WRITE_ENABLE) ||
1359 (m_testType == TestType::INTERACTION_WITH_EXTENDED_DYNAMIC_STATE3))
1360 {
1361 glslSources.add("frag0") << glu::FragmentSource(generateWriteFragSource(4));
1362 glslSources.add("frag1") << glu::FragmentSource(generateReadFragSource(5, false));
1363 }
1364 else if (m_testType == TestType::DEPTH_STENCIL_MAPPING_TO_SAME_INDEX)
1365 {
1366 std::string fragSrc(
1367 "#version 450\n"
1368 "layout(input_attachment_index = 0, binding = 0) uniform usubpassInput inColor0;\n"
1369 "layout(input_attachment_index = 1, binding = 1) uniform usubpassInput inColor1;\n"
1370 "layout(input_attachment_index = 2, binding = 2) uniform subpassInput inDepth;\n"
1371 "layout(input_attachment_index = 2, binding = 3) uniform usubpassInput inStencil;\n"
1372 "layout(set=1, binding=0, std430) writeonly buffer Output\n{\n"
1373 " uint v[];\n"
1374 "} outBuffer;\n"
1375 "void main()\n{\n"
1376 " const uvec2 i = uvec2(trunc(gl_FragCoord.xy));\n"
1377 " outBuffer.v[i.x+i.y*16] = uint(subpassLoad(inDepth).x * 1000) + subpassLoad(inStencil).x;\n"
1378 "}\n");
1379 glslSources.add("frag0") << glu::FragmentSource(generateWriteFragSource(2));
1380 glslSources.add("frag1") << glu::FragmentSource(fragSrc);
1381 }
1382
1383 if ((m_testType == TestType::MAX_INPUT_ATTACHMENTS) ||
1384 (m_testType == TestType::MAX_ATTACHMENTS_REMAPPED_REPEATEDLY))
1385 {
1386 // generate fragment shaders for all posible number of input attachments;
1387 // during test execution proper shader will be picked
1388 for (uint32_t inputAttachmentCount : inputAttachmentsPossibleValues)
1389 glslSources.add(std::string("frag1_") + std::to_string(inputAttachmentCount))
1390 << glu::FragmentSource(generateReadFragSource(inputAttachmentCount));
1391 }
1392
1393 if (m_testType == TestType::MAPPING_NOT_AFFECTING_BLEND_STATE)
1394 {
1395 std::string fragSrc("#version 450\n"
1396 "layout(location = 0) out vec4 outColor0;\n"
1397 "layout(location = 1) out vec4 outColor1;\n"
1398 "layout(location = 2) out vec4 outColor2;\n"
1399 "layout(location = 3) out vec4 outColor3;\n"
1400 "void main()\n{\n"
1401 " if (gl_FragCoord.x > 8.0)\n"
1402 " discard;\n"
1403 " outColor0 = vec4(0.6, 0.8, 0.9, 0.2);\n" // used for attachment 1
1404 " outColor1 = vec4(0.6, 0.4, 0.2, 0.6);\n" // used for attachment 3
1405 " outColor2 = vec4(0.1, 0.3, 0.6, 0.2);\n" // used for attachment 2
1406 " outColor3 = vec4(0.0, 0.6, 0.4, 0.8);\n" // used for attachment 0
1407 "}\n");
1408 glslSources.add("frag") << glu::FragmentSource(fragSrc);
1409 }
1410 }
1411
createInstance(Context & context) const1412 TestInstance *LocalReadTestCase::createInstance(Context &context) const
1413 {
1414 if (m_testType == TestType::MAPPING_NOT_AFFECTING_BLEND_STATE)
1415 return new MappingWithBlendStateTestInstance(context, m_testType);
1416
1417 return new BasicLocalReadTestInstance(context, m_testType);
1418 }
1419
1420 } // namespace
1421
createDynamicRenderingLocalReadTests(tcu::TestContext & testCtx)1422 tcu::TestCaseGroup *createDynamicRenderingLocalReadTests(tcu::TestContext &testCtx)
1423 {
1424 struct TestConfig
1425 {
1426 std::string name;
1427 TestType testType;
1428 };
1429 std::vector<TestConfig> testConfigs{
1430 {"max_input_attachments", TestType::MAX_INPUT_ATTACHMENTS},
1431 {"max_attachments_remapped_repeatedly", TestType::MAX_ATTACHMENTS_REMAPPED_REPEATEDLY},
1432 {"unused_writen_discarded", TestType::UNUSED_WRITEN_DISCARDED},
1433 {"depth_stencil_mapping_to_no_index", TestType::DEPTH_STENCIL_MAPPING_TO_NO_INDEX},
1434 {"depth_stencil_mapping_to_same_index", TestType::DEPTH_STENCIL_MAPPING_TO_SAME_INDEX},
1435 {"depth_mapping_stencil_not", TestType::DEPTH_MAPPING_STENCIL_NOT},
1436 {"mapping_not_affecting_blend_state", TestType::MAPPING_NOT_AFFECTING_BLEND_STATE},
1437 {"interaction_with_color_write_enable", TestType::INTERACTION_WITH_COLOR_WRITE_ENABLE},
1438 {"interaction_with_extended_dynamic_state3", TestType::INTERACTION_WITH_EXTENDED_DYNAMIC_STATE3},
1439 };
1440
1441 de::MovePtr<tcu::TestCaseGroup> mainGroup(
1442 new tcu::TestCaseGroup(testCtx, "local_read", "Test dynamic rendering local read"));
1443
1444 for (const auto &testConfig : testConfigs)
1445 mainGroup->addChild(new LocalReadTestCase(testCtx, testConfig.name, testConfig.testType));
1446
1447 return mainGroup.release();
1448 }
1449
1450 } // namespace renderpass
1451 } // namespace vkt
1452