1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2023 LunarG, Inc.
6  * Copyright (c) 2023 Nintendo
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 Shader Object Link Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktShaderObjectRenderingTests.hpp"
26 #include "deUniquePtr.hpp"
27 #include "tcuTestCase.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vktShaderObjectCreateUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "deRandom.hpp"
34 #include "vkBuilderUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 #include "tcuTextureUtil.hpp"
37 #include "tcuImageCompare.hpp"
38 #include "tcuVectorUtil.hpp"
39 #include <cmath>
40 
41 namespace vkt
42 {
43 namespace ShaderObject
44 {
45 
46 namespace
47 {
48 
49 enum ExtraAttachments
50 {
51     NONE = 0,
52     BEFORE,
53     BETWEEN,
54     AFTER,
55 };
56 
57 enum DummyRenderPass
58 {
59     DUMMY_NONE = 0,
60     DUMMY_DYNAMIC,
61     DUMMY_STATIC,
62 };
63 
64 struct TestParams
65 {
66     uint32_t colorAttachmentCount;
67     uint32_t extraAttachmentCount;
68     ExtraAttachments extraAttachments;
69     uint32_t extraFragmentOutputCount;
70     ExtraAttachments extraOutputs;
71     bool useDepthAttachment;
72     vk::VkFormat colorFormat;
73     vk::VkFormat depthFormat;
74     bool bindShadersBeforeBeginRendering;
75     DummyRenderPass dummyRenderPass;
76     bool writeGlFragDepth;
77     bool randomColorFormats;
78 };
79 
80 const vk::VkFormat colorFormats[] = {
81     vk::VK_FORMAT_R4G4_UNORM_PACK8,
82     vk::VK_FORMAT_R4G4B4A4_UNORM_PACK16,
83     vk::VK_FORMAT_B4G4R4A4_UNORM_PACK16,
84     vk::VK_FORMAT_R5G6B5_UNORM_PACK16,
85     vk::VK_FORMAT_B5G6R5_UNORM_PACK16,
86     vk::VK_FORMAT_R5G5B5A1_UNORM_PACK16,
87     vk::VK_FORMAT_B5G5R5A1_UNORM_PACK16,
88     vk::VK_FORMAT_A1R5G5B5_UNORM_PACK16,
89     vk::VK_FORMAT_R8_UNORM,
90     vk::VK_FORMAT_R8_SNORM,
91     vk::VK_FORMAT_R8_USCALED,
92     vk::VK_FORMAT_R8_SSCALED,
93     vk::VK_FORMAT_R8_UINT,
94     vk::VK_FORMAT_R8_SINT,
95     vk::VK_FORMAT_R8_SRGB,
96     vk::VK_FORMAT_R8G8_UNORM,
97     vk::VK_FORMAT_R8G8_SNORM,
98     vk::VK_FORMAT_R8G8_USCALED,
99     vk::VK_FORMAT_R8G8_SSCALED,
100     vk::VK_FORMAT_R8G8_UINT,
101     vk::VK_FORMAT_R8G8_SINT,
102     vk::VK_FORMAT_R8G8_SRGB,
103     vk::VK_FORMAT_R8G8B8_UNORM,
104     vk::VK_FORMAT_R8G8B8_SNORM,
105     vk::VK_FORMAT_R8G8B8_USCALED,
106     vk::VK_FORMAT_R8G8B8_SSCALED,
107     vk::VK_FORMAT_R8G8B8_UINT,
108     vk::VK_FORMAT_R8G8B8_SINT,
109     vk::VK_FORMAT_R8G8B8_SRGB,
110     vk::VK_FORMAT_B8G8R8_UNORM,
111     vk::VK_FORMAT_B8G8R8_SNORM,
112     vk::VK_FORMAT_B8G8R8_USCALED,
113     vk::VK_FORMAT_B8G8R8_SSCALED,
114     vk::VK_FORMAT_B8G8R8_UINT,
115     vk::VK_FORMAT_B8G8R8_SINT,
116     vk::VK_FORMAT_B8G8R8_SRGB,
117     vk::VK_FORMAT_R8G8B8A8_UNORM,
118     vk::VK_FORMAT_R8G8B8A8_SNORM,
119     vk::VK_FORMAT_R8G8B8A8_USCALED,
120     vk::VK_FORMAT_R8G8B8A8_SSCALED,
121     vk::VK_FORMAT_R8G8B8A8_UINT,
122     vk::VK_FORMAT_R8G8B8A8_SINT,
123     vk::VK_FORMAT_R8G8B8A8_SRGB,
124     vk::VK_FORMAT_B8G8R8A8_UNORM,
125     vk::VK_FORMAT_B8G8R8A8_SNORM,
126     vk::VK_FORMAT_B8G8R8A8_USCALED,
127     vk::VK_FORMAT_B8G8R8A8_SSCALED,
128     vk::VK_FORMAT_B8G8R8A8_UINT,
129     vk::VK_FORMAT_B8G8R8A8_SINT,
130     vk::VK_FORMAT_B8G8R8A8_SRGB,
131     vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32,
132     vk::VK_FORMAT_A8B8G8R8_SNORM_PACK32,
133     vk::VK_FORMAT_A8B8G8R8_USCALED_PACK32,
134     vk::VK_FORMAT_A8B8G8R8_SSCALED_PACK32,
135     vk::VK_FORMAT_A8B8G8R8_UINT_PACK32,
136     vk::VK_FORMAT_A8B8G8R8_SINT_PACK32,
137     vk::VK_FORMAT_A8B8G8R8_SRGB_PACK32,
138     vk::VK_FORMAT_A2R10G10B10_UNORM_PACK32,
139     vk::VK_FORMAT_A2R10G10B10_SNORM_PACK32,
140     vk::VK_FORMAT_A2R10G10B10_USCALED_PACK32,
141     vk::VK_FORMAT_A2R10G10B10_SSCALED_PACK32,
142     vk::VK_FORMAT_A2R10G10B10_UINT_PACK32,
143     vk::VK_FORMAT_A2R10G10B10_SINT_PACK32,
144     vk::VK_FORMAT_A2B10G10R10_UNORM_PACK32,
145     vk::VK_FORMAT_A2B10G10R10_SNORM_PACK32,
146     vk::VK_FORMAT_A2B10G10R10_USCALED_PACK32,
147     vk::VK_FORMAT_A2B10G10R10_SSCALED_PACK32,
148     vk::VK_FORMAT_A2B10G10R10_UINT_PACK32,
149     vk::VK_FORMAT_A2B10G10R10_SINT_PACK32,
150     vk::VK_FORMAT_R16_UNORM,
151     vk::VK_FORMAT_R16_SNORM,
152     vk::VK_FORMAT_R16_USCALED,
153     vk::VK_FORMAT_R16_SSCALED,
154     vk::VK_FORMAT_R16_UINT,
155     vk::VK_FORMAT_R16_SINT,
156     vk::VK_FORMAT_R16_SFLOAT,
157     vk::VK_FORMAT_R16G16_UNORM,
158     vk::VK_FORMAT_R16G16_SNORM,
159     vk::VK_FORMAT_R16G16_USCALED,
160     vk::VK_FORMAT_R16G16_SSCALED,
161     vk::VK_FORMAT_R16G16_UINT,
162     vk::VK_FORMAT_R16G16_SINT,
163     vk::VK_FORMAT_R16G16_SFLOAT,
164     vk::VK_FORMAT_R16G16B16_UNORM,
165     vk::VK_FORMAT_R16G16B16_SNORM,
166     vk::VK_FORMAT_R16G16B16_USCALED,
167     vk::VK_FORMAT_R16G16B16_SSCALED,
168     vk::VK_FORMAT_R16G16B16_UINT,
169     vk::VK_FORMAT_R16G16B16_SINT,
170     vk::VK_FORMAT_R16G16B16_SFLOAT,
171     vk::VK_FORMAT_R16G16B16A16_UNORM,
172     vk::VK_FORMAT_R16G16B16A16_SNORM,
173     vk::VK_FORMAT_R16G16B16A16_USCALED,
174     vk::VK_FORMAT_R16G16B16A16_SSCALED,
175     vk::VK_FORMAT_R16G16B16A16_UINT,
176     vk::VK_FORMAT_R16G16B16A16_SINT,
177     vk::VK_FORMAT_R16G16B16A16_SFLOAT,
178     vk::VK_FORMAT_R32_UINT,
179     vk::VK_FORMAT_R32_SINT,
180     vk::VK_FORMAT_R32_SFLOAT,
181     vk::VK_FORMAT_R32G32_UINT,
182     vk::VK_FORMAT_R32G32_SINT,
183     vk::VK_FORMAT_R32G32_SFLOAT,
184     vk::VK_FORMAT_R32G32B32_UINT,
185     vk::VK_FORMAT_R32G32B32_SINT,
186     vk::VK_FORMAT_R32G32B32_SFLOAT,
187     vk::VK_FORMAT_R32G32B32A32_UINT,
188     vk::VK_FORMAT_R32G32B32A32_SINT,
189     vk::VK_FORMAT_R32G32B32A32_SFLOAT,
190 };
191 
192 const vk::VkFormat randomColorFormats[] = {
193     vk::VK_FORMAT_R8_UNORM,
194     vk::VK_FORMAT_R8_SNORM,
195     vk::VK_FORMAT_R8G8_UNORM,
196     vk::VK_FORMAT_R8G8_SNORM,
197     vk::VK_FORMAT_R8G8B8A8_UNORM,
198     vk::VK_FORMAT_R8G8B8A8_SNORM,
199     vk::VK_FORMAT_A8B8G8R8_UNORM_PACK32,
200     vk::VK_FORMAT_A8B8G8R8_SNORM_PACK32,
201     vk::VK_FORMAT_R16_UNORM,
202     vk::VK_FORMAT_R16_SNORM,
203     vk::VK_FORMAT_R16G16_UNORM,
204     vk::VK_FORMAT_R16G16_SNORM,
205     vk::VK_FORMAT_R16G16_SFLOAT,
206     vk::VK_FORMAT_R16G16B16_UNORM,
207     vk::VK_FORMAT_R16G16B16_SNORM,
208     vk::VK_FORMAT_R16G16B16_SFLOAT,
209     vk::VK_FORMAT_R16G16B16A16_UNORM,
210     vk::VK_FORMAT_R16G16B16A16_SNORM,
211     vk::VK_FORMAT_R16G16B16A16_SFLOAT,
212     vk::VK_FORMAT_R32_SFLOAT,
213     vk::VK_FORMAT_R32G32_SFLOAT,
214     vk::VK_FORMAT_R32G32B32_SFLOAT,
215     vk::VK_FORMAT_R32G32B32A32_SFLOAT,
216 };
217 
readDepthAttachment(const vk::DeviceInterface & vk,vk::VkDevice device,vk::VkQueue queue,uint32_t queueFamilyIndex,vk::Allocator & allocator,vk::VkImage image,vk::VkFormat format,const tcu::UVec2 & renderSize,vk::VkImageLayout currentLayout)218 de::MovePtr<tcu::TextureLevel> readDepthAttachment(const vk::DeviceInterface &vk, vk::VkDevice device,
219                                                    vk::VkQueue queue, uint32_t queueFamilyIndex,
220                                                    vk::Allocator &allocator, vk::VkImage image, vk::VkFormat format,
221                                                    const tcu::UVec2 &renderSize, vk::VkImageLayout currentLayout)
222 {
223     vk::Move<vk::VkBuffer> buffer;
224     de::MovePtr<vk::Allocation> bufferAlloc;
225     vk::Move<vk::VkCommandPool> cmdPool;
226     vk::Move<vk::VkCommandBuffer> cmdBuffer;
227 
228     tcu::TextureFormat retFormat(tcu::TextureFormat::D, tcu::TextureFormat::CHANNELTYPE_LAST);
229     tcu::TextureFormat bufferFormat(tcu::TextureFormat::D, tcu::TextureFormat::CHANNELTYPE_LAST);
230     const vk::VkImageAspectFlags barrierAspect =
231         vk::VK_IMAGE_ASPECT_DEPTH_BIT |
232         (mapVkFormat(format).order == tcu::TextureFormat::DS ? vk::VK_IMAGE_ASPECT_STENCIL_BIT :
233                                                                (vk::VkImageAspectFlagBits)0);
234 
235     switch (format)
236     {
237     case vk::VK_FORMAT_D16_UNORM:
238     case vk::VK_FORMAT_D16_UNORM_S8_UINT:
239         bufferFormat.type = retFormat.type = tcu::TextureFormat::UNORM_INT16;
240         break;
241     case vk::VK_FORMAT_D24_UNORM_S8_UINT:
242     case vk::VK_FORMAT_X8_D24_UNORM_PACK32:
243         retFormat.type = tcu::TextureFormat::UNORM_INT24;
244         // vkCmdCopyBufferToImage copies D24 data to 32-bit pixels.
245         bufferFormat.type = tcu::TextureFormat::UNSIGNED_INT_24_8_REV;
246         break;
247     case vk::VK_FORMAT_D32_SFLOAT:
248     case vk::VK_FORMAT_D32_SFLOAT_S8_UINT:
249         bufferFormat.type = retFormat.type = tcu::TextureFormat::FLOAT;
250         break;
251     default:
252         TCU_FAIL("unrecognized format");
253     }
254 
255     const vk::VkDeviceSize pixelDataSize = renderSize.x() * renderSize.y() * bufferFormat.getPixelSize();
256     de::MovePtr<tcu::TextureLevel> resultLevel(new tcu::TextureLevel(retFormat, renderSize.x(), renderSize.y()));
257 
258     // Create destination buffer
259     {
260         const vk::VkBufferCreateInfo bufferParams = {
261             vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
262             DE_NULL,                                  // const void* pNext;
263             0u,                                       // VkBufferCreateFlags flags;
264             pixelDataSize,                            // VkDeviceSize size;
265             vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT,     // VkBufferUsageFlags usage;
266             vk::VK_SHARING_MODE_EXCLUSIVE,            // VkSharingMode sharingMode;
267             0u,                                       // uint32_t queueFamilyIndexCount;
268             DE_NULL                                   // const uint32_t* pQueueFamilyIndices;
269         };
270 
271         buffer = createBuffer(vk, device, &bufferParams);
272         bufferAlloc =
273             allocator.allocate(getBufferMemoryRequirements(vk, device, *buffer), vk::MemoryRequirement::HostVisible);
274         VK_CHECK(vk.bindBufferMemory(device, *buffer, bufferAlloc->getMemory(), bufferAlloc->getOffset()));
275     }
276 
277     // Create command pool and buffer
278     cmdPool   = createCommandPool(vk, device, vk::VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
279     cmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
280 
281     beginCommandBuffer(vk, *cmdBuffer);
282     copyImageToBuffer(vk, *cmdBuffer, image, *buffer, tcu::IVec2(renderSize.x(), renderSize.y()),
283                       vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, currentLayout, 1u, barrierAspect,
284                       vk::VK_IMAGE_ASPECT_DEPTH_BIT);
285     endCommandBuffer(vk, *cmdBuffer);
286 
287     submitCommandsAndWait(vk, device, queue, cmdBuffer.get());
288 
289     // Read buffer data
290     invalidateAlloc(vk, device, *bufferAlloc);
291     tcu::copy(*resultLevel,
292               tcu::ConstPixelBufferAccess(bufferFormat, resultLevel->getSize(), bufferAlloc->getHostPtr()));
293 
294     return resultLevel;
295 }
296 
297 class ShaderObjectRenderingInstance : public vkt::TestInstance
298 {
299 public:
ShaderObjectRenderingInstance(Context & context,const TestParams & params)300     ShaderObjectRenderingInstance(Context &context, const TestParams &params)
301         : vkt::TestInstance(context)
302         , m_params(params)
303     {
304     }
~ShaderObjectRenderingInstance(void)305     virtual ~ShaderObjectRenderingInstance(void)
306     {
307     }
308 
309     tcu::TestStatus iterate(void) override;
310 
311 private:
312     void beginRendering(vk::VkCommandBuffer cmdBuffer);
313     void createDummyImage(void);
314     void createDummyRenderPass(void);
315     void setColorFormats(const vk::InstanceDriver &vki);
316     void generateExpectedImage(const tcu::PixelBufferAccess &outputImage, const uint32_t width, const uint32_t height,
317                                uint32_t attachmentIndex);
318 
319     TestParams m_params;
320 
321     const vk::VkRect2D m_renderArea = vk::makeRect2D(0, 0, 32, 32);
322     std::vector<vk::VkFormat> m_colorFormats;
323     std::vector<vk::Move<vk::VkImageView>> m_colorImageViews;
324     vk::Move<vk::VkImageView> m_depthImageView;
325 
326     de::MovePtr<vk::ImageWithMemory> m_dummyImage;
327     vk::Move<vk::VkImageView> m_dummyImageView;
328     vk::Move<vk::VkRenderPass> m_dummyRenderPass;
329     vk::Move<vk::VkFramebuffer> m_dummyFramebuffer;
330 };
331 
createDummyImage(void)332 void ShaderObjectRenderingInstance::createDummyImage(void)
333 {
334     const vk::DeviceInterface &vk    = m_context.getDeviceInterface();
335     const vk::VkDevice device        = m_context.getDevice();
336     auto &alloc                      = m_context.getDefaultAllocator();
337     const auto colorSubresourceRange = makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
338 
339     vk::VkFormat format = m_params.colorFormat == vk::VK_FORMAT_R8G8B8A8_UNORM ? vk::VK_FORMAT_R32G32B32A32_SFLOAT :
340                                                                                  vk::VK_FORMAT_R8G8B8A8_UNORM;
341 
342     const vk::VkImageCreateInfo createInfo = {
343         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
344         DE_NULL,                                 // const void*                pNext
345         0u,                                      // VkImageCreateFlags        flags
346         vk::VK_IMAGE_TYPE_2D,                    // VkImageType                imageType
347         format,                                  // VkFormat                    format
348         {32, 32, 1},                             // VkExtent3D                extent
349         1u,                                      // uint32_t                    mipLevels
350         1u,                                      // uint32_t                    arrayLayers
351         vk::VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits    samples
352         vk::VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling            tiling
353         vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags        usage
354         vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode            sharingMode
355         0,                             // uint32_t                    queueFamilyIndexCount
356         DE_NULL,                       // const uint32_t*            pQueueFamilyIndices
357         vk::VK_IMAGE_LAYOUT_UNDEFINED  // VkImageLayout            initialLayout
358     };
359 
360     m_dummyImage = de::MovePtr<vk::ImageWithMemory>(
361         new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
362     m_dummyImageView =
363         vk::makeImageView(vk, device, **m_dummyImage, vk::VK_IMAGE_VIEW_TYPE_2D, format, colorSubresourceRange);
364 }
365 
createDummyRenderPass(void)366 void ShaderObjectRenderingInstance::createDummyRenderPass(void)
367 {
368     const vk::DeviceInterface &vk = m_context.getDeviceInterface();
369     const vk::VkDevice device     = m_context.getDevice();
370     vk::VkFormat format = m_params.colorFormat == vk::VK_FORMAT_R8G8B8A8_UNORM ? vk::VK_FORMAT_R32G32B32A32_SFLOAT :
371                                                                                  vk::VK_FORMAT_R8G8B8A8_UNORM;
372     m_dummyRenderPass   = vk::makeRenderPass(vk, device, format);
373     m_dummyFramebuffer  = vk::makeFramebuffer(vk, device, *m_dummyRenderPass, 1u, &*m_dummyImageView,
374                                               m_renderArea.extent.width, m_renderArea.extent.height);
375 }
376 
getClearValue(const tcu::TextureFormat tcuFormat)377 vk::VkClearValue getClearValue(const tcu::TextureFormat tcuFormat)
378 {
379     const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(tcuFormat.type);
380 
381     if (channelClass != tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER &&
382         channelClass != tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
383         return vk::makeClearValueColor({0.0f, 0.0f, 0.0f, 1.0f});
384 
385     const tcu::IVec4 bits = tcu::min(tcu::getTextureFormatBitDepth(tcuFormat), tcu::IVec4(32));
386     const int signBit     = (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER ? 1 : 0);
387 
388     if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
389         return vk::makeClearValueColorU32(0u, 0u, 0u, uint32_t((uint64_t(1) << (bits[3] - signBit)) - 1));
390 
391     return vk::makeClearValueColorI32(0u, 0u, 0u, int32_t((uint64_t(1) << (bits[3] - signBit)) - 1));
392 }
393 
beginRendering(vk::VkCommandBuffer cmdBuffer)394 void ShaderObjectRenderingInstance::beginRendering(vk::VkCommandBuffer cmdBuffer)
395 {
396     const vk::DeviceInterface &vk          = m_context.getDeviceInterface();
397     const vk::VkClearValue floatClearValue = vk::makeClearValueColor({0.0f, 0.0f, 0.0f, 1.0f});
398     const vk::VkClearValue clearDepthValue = vk::makeClearValueDepthStencil(1.0f, 0u);
399 
400     vk::VkRenderingAttachmentInfo colorAttachment{
401         vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
402         DE_NULL,                                             // const void* pNext;
403         VK_NULL_HANDLE,                                      // VkImageView imageView;
404         vk::VK_IMAGE_LAYOUT_GENERAL,                         // VkImageLayout imageLayout;
405         vk::VK_RESOLVE_MODE_NONE,                            // VkResolveModeFlagBits resolveMode;
406         DE_NULL,                                             // VkImageView resolveImageView;
407         vk::VK_IMAGE_LAYOUT_UNDEFINED,                       // VkImageLayout resolveImageLayout;
408         vk::VK_ATTACHMENT_LOAD_OP_CLEAR,                     // VkAttachmentLoadOp loadOp;
409         vk::VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp storeOp;
410         floatClearValue                                      // VkClearValue clearValue;
411     };
412 
413     uint32_t outputCount =
414         m_params.colorAttachmentCount + m_params.extraFragmentOutputCount + m_params.extraAttachmentCount;
415     std::vector<vk::VkRenderingAttachmentInfo> colorAttachments(outputCount);
416     uint32_t i = 0;
417     if (m_params.extraOutputs == BEFORE ||
418         (m_params.extraOutputs == BETWEEN && m_params.colorAttachmentCount + m_params.extraAttachmentCount == 0))
419     {
420         colorAttachment.imageView = VK_NULL_HANDLE;
421         for (uint32_t j = 0; j < m_params.extraFragmentOutputCount; ++j)
422             colorAttachments[i++] = colorAttachment;
423     }
424     for (uint32_t j = 0; j < m_params.colorAttachmentCount + m_params.extraAttachmentCount; ++j)
425     {
426         if (m_params.extraOutputs == BETWEEN &&
427             i == (m_params.colorAttachmentCount + m_params.extraAttachmentCount) / 2 + 1)
428         {
429             colorAttachment.imageView = VK_NULL_HANDLE;
430             for (uint32_t k = 0; k < m_params.extraFragmentOutputCount; ++k)
431                 colorAttachments[i++] = colorAttachment;
432         }
433         colorAttachment.imageView  = *m_colorImageViews[j];
434         colorAttachment.clearValue = getClearValue(vk::mapVkFormat(m_colorFormats[j]));
435 
436         colorAttachments[i++] = colorAttachment;
437     }
438     if (m_params.extraOutputs == AFTER ||
439         (m_params.extraOutputs == BETWEEN && m_params.colorAttachmentCount + m_params.extraAttachmentCount == 1))
440     {
441         colorAttachment.imageView = VK_NULL_HANDLE;
442         for (uint32_t j = 0; j < m_params.extraFragmentOutputCount; ++j)
443             colorAttachments[i++] = colorAttachment;
444     }
445 
446     vk::VkRenderingAttachmentInfo depthAttachment{
447         vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR, // VkStructureType sType;
448         DE_NULL,                                             // const void* pNext;
449         *m_depthImageView,                                   // VkImageView imageView;
450         vk::VK_IMAGE_LAYOUT_GENERAL,                         // VkImageLayout imageLayout;
451         vk::VK_RESOLVE_MODE_NONE,                            // VkResolveModeFlagBits resolveMode;
452         DE_NULL,                                             // VkImageView resolveImageView;
453         vk::VK_IMAGE_LAYOUT_UNDEFINED,                       // VkImageLayout resolveImageLayout;
454         vk::VK_ATTACHMENT_LOAD_OP_CLEAR,                     // VkAttachmentLoadOp loadOp;
455         vk::VK_ATTACHMENT_STORE_OP_STORE,                    // VkAttachmentStoreOp storeOp;
456         clearDepthValue                                      // VkClearValue clearValue;
457     };
458 
459     vk::VkRenderingInfoKHR renderingInfo{
460         vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
461         DE_NULL,
462         (vk::VkRenderingFlags)0u,          // VkRenderingFlagsKHR flags;
463         m_renderArea,                      // VkRect2D renderArea;
464         1u,                                // uint32_t layerCount;
465         0x0,                               // uint32_t viewMask;
466         (uint32_t)colorAttachments.size(), // uint32_t colorAttachmentCount;
467         colorAttachments.data(),           // const VkRenderingAttachmentInfoKHR* pColorAttachments;
468         m_params.useDepthAttachment ? &depthAttachment :
469                                       DE_NULL, // const VkRenderingAttachmentInfoKHR* pDepthAttachment;
470         DE_NULL,                               // const VkRenderingAttachmentInfoKHR* pStencilAttachment;
471     };
472 
473     vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
474 }
475 
setColorFormats(const vk::InstanceDriver & vki)476 void ShaderObjectRenderingInstance::setColorFormats(const vk::InstanceDriver &vki)
477 {
478     const auto physicalDevice = m_context.getPhysicalDevice();
479 
480     m_colorFormats.resize(m_params.colorAttachmentCount + m_params.extraAttachmentCount);
481     if (m_params.randomColorFormats)
482     {
483         if (m_colorFormats.size() > 0)
484         {
485             m_colorFormats[0] = m_params.colorFormat;
486         }
487         de::Random random(102030);
488         for (uint32_t i = 1; i < (uint32_t)m_colorFormats.size(); ++i)
489         {
490             if (i <= m_params.extraAttachmentCount && m_params.extraAttachments == BEFORE)
491                 m_colorFormats[i] = m_params.colorFormat;
492             else
493             {
494                 while (true)
495                 {
496                     // Find random color format, and make sure it is supported
497                     vk::VkFormat format =
498                         randomColorFormats[random.getUint32() % DE_LENGTH_OF_ARRAY(randomColorFormats)];
499                     vk::VkImageFormatProperties colorImageFormatProperties;
500                     const auto colorResult = vki.getPhysicalDeviceImageFormatProperties(
501                         physicalDevice, format, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL,
502                         (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT), 0,
503                         &colorImageFormatProperties);
504                     if (colorResult == vk::VK_SUCCESS)
505                     {
506                         m_colorFormats[i] = format;
507                         break;
508                     }
509                 }
510             }
511         }
512     }
513     else
514     {
515         for (auto &colorFormat : m_colorFormats)
516             colorFormat = m_params.colorFormat;
517     }
518 }
519 
generateExpectedImage(const tcu::PixelBufferAccess & outputImage,const uint32_t width,const uint32_t height,uint32_t attachmentIndex)520 void ShaderObjectRenderingInstance::generateExpectedImage(const tcu::PixelBufferAccess &outputImage,
521                                                           const uint32_t width, const uint32_t height,
522                                                           uint32_t attachmentIndex)
523 {
524     const tcu::TextureChannelClass channelClass = tcu::getTextureChannelClass(outputImage.getFormat().type);
525     const vk::VkClearValue clearValue           = getClearValue(outputImage.getFormat());
526 
527     const uint32_t xOffset = 8;
528     const uint32_t yOffset = 8;
529 
530     if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
531         tcu::clear(outputImage, tcu::UVec4(clearValue.color.uint32));
532     else if (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
533         tcu::clear(outputImage, tcu::IVec4(clearValue.color.int32));
534     else
535         tcu::clear(outputImage, tcu::Vec4(clearValue.color.float32));
536 
537     if ((m_params.extraAttachments == BEFORE && attachmentIndex < m_params.extraAttachmentCount) ||
538         (m_params.extraAttachments == BETWEEN && attachmentIndex > m_params.colorAttachmentCount / 2u &&
539          attachmentIndex <= m_params.colorAttachmentCount / 2u + m_params.extraAttachmentCount) ||
540         (m_params.extraAttachments == AFTER && attachmentIndex >= m_params.colorAttachmentCount))
541         return;
542 
543     tcu::Vec4 setColor      = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
544     tcu::IVec4 setColorInt  = tcu::IVec4(0, 0, 0, 0);
545     tcu::UVec4 setColorUint = tcu::UVec4(0u, 0u, 0u, 0u);
546 
547     for (int32_t i = 0; i < tcu::getNumUsedChannels(outputImage.getFormat().order); ++i)
548     {
549         setColor[i]     = 1.0f;
550         setColorInt[i]  = 255;
551         setColorUint[i] = 255u;
552     }
553 
554     for (uint32_t j = 0; j < height; ++j)
555     {
556         for (uint32_t i = 0; i < width; ++i)
557         {
558             if (i >= xOffset && i < width - xOffset && j >= yOffset && j < height - yOffset)
559             {
560                 if (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER)
561                     outputImage.setPixel(setColorUint, i, j, 0);
562                 else if (channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER)
563                     outputImage.setPixel(setColorInt, i, j, 0);
564                 else
565                     outputImage.setPixel(setColor, i, j, 0);
566             }
567         }
568     }
569 }
570 
iterate(void)571 tcu::TestStatus ShaderObjectRenderingInstance::iterate(void)
572 {
573     const vk::VkInstance instance = m_context.getInstance();
574     const vk::InstanceDriver instanceDriver(m_context.getPlatformInterface(), instance);
575     const vk::DeviceInterface &vk   = m_context.getDeviceInterface();
576     const vk::VkDevice device       = m_context.getDevice();
577     const vk::VkQueue queue         = m_context.getUniversalQueue();
578     const uint32_t queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
579     auto &alloc                     = m_context.getDefaultAllocator();
580     tcu::TestLog &log               = m_context.getTestContext().getLog();
581     const auto deviceExtensions     = vk::removeUnsupportedShaderObjectExtensions(
582         m_context.getInstanceInterface(), m_context.getPhysicalDevice(), m_context.getDeviceExtensions());
583     const bool tessellationSupported = m_context.getDeviceFeatures().tessellationShader;
584     const bool geometrySupported     = m_context.getDeviceFeatures().geometryShader;
585     const bool taskSupported         = m_context.getMeshShaderFeaturesEXT().taskShader;
586     const bool meshSupported         = m_context.getMeshShaderFeaturesEXT().meshShader;
587 
588     const auto colorSubresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
589     auto depthSubresourceRange       = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_DEPTH_BIT, 0u, 1u, 0u, 1u);
590     if (m_params.useDepthAttachment && tcu::hasStencilComponent(mapVkFormat(m_params.depthFormat).order))
591         depthSubresourceRange.aspectMask |= vk::VK_IMAGE_ASPECT_STENCIL_BIT;
592     const auto colorSubresourceLayers = vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
593     vk::VkExtent3D extent             = {m_renderArea.extent.width, m_renderArea.extent.height, 1};
594 
595     setColorFormats(instanceDriver);
596 
597     vk::VkImageCreateInfo createInfo = {
598         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
599         DE_NULL,                                 // const void*                pNext
600         0u,                                      // VkImageCreateFlags        flags
601         vk::VK_IMAGE_TYPE_2D,                    // VkImageType                imageType
602         vk::VK_FORMAT_UNDEFINED,                 // VkFormat                    format
603         {32, 32, 1},                             // VkExtent3D                extent
604         1u,                                      // uint32_t                    mipLevels
605         1u,                                      // uint32_t                    arrayLayers
606         vk::VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits    samples
607         vk::VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling            tiling
608         vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags        usage
609         vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode            sharingMode
610         0,                             // uint32_t                    queueFamilyIndexCount
611         DE_NULL,                       // const uint32_t*            pQueueFamilyIndices
612         vk::VK_IMAGE_LAYOUT_UNDEFINED  // VkImageLayout            initialLayout
613     };
614 
615     const vk::VkImageCreateInfo depthCreateInfo = {
616         vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType            sType
617         DE_NULL,                                 // const void*                pNext
618         0u,                                      // VkImageCreateFlags        flags
619         vk::VK_IMAGE_TYPE_2D,                    // VkImageType                imageType
620         m_params.depthFormat,                    // VkFormat                    format
621         {32, 32, 1},                             // VkExtent3D                extent
622         1u,                                      // uint32_t                    mipLevels
623         1u,                                      // uint32_t                    arrayLayers
624         vk::VK_SAMPLE_COUNT_1_BIT,               // VkSampleCountFlagBits    samples
625         vk::VK_IMAGE_TILING_OPTIMAL,             // VkImageTiling            tiling
626         vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT |
627             vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags        usage
628         vk::VK_SHARING_MODE_EXCLUSIVE,           // VkSharingMode            sharingMode
629         0,                                       // uint32_t                    queueFamilyIndexCount
630         DE_NULL,                                 // const uint32_t*            pQueueFamilyIndices
631         vk::VK_IMAGE_LAYOUT_UNDEFINED            // VkImageLayout            initialLayout
632     };
633 
634     uint32_t colorAttachmentCount = m_params.colorAttachmentCount + m_params.extraAttachmentCount;
635     std::vector<de::MovePtr<vk::ImageWithMemory>> colorImages(colorAttachmentCount);
636     m_colorImageViews.resize(colorAttachmentCount);
637     for (uint32_t i = 0; i < colorAttachmentCount; ++i)
638     {
639         createInfo.format = m_colorFormats[i];
640         colorImages[i]    = de::MovePtr<vk::ImageWithMemory>(
641             new vk::ImageWithMemory(vk, device, alloc, createInfo, vk::MemoryRequirement::Any));
642         m_colorImageViews[i] = vk::makeImageView(vk, device, **colorImages[i], vk::VK_IMAGE_VIEW_TYPE_2D,
643                                                  createInfo.format, colorSubresourceRange);
644     }
645 
646     de::MovePtr<vk::ImageWithMemory> depthImage;
647     if (m_params.useDepthAttachment)
648     {
649         depthImage = de::MovePtr<vk::ImageWithMemory>(
650             new vk::ImageWithMemory(vk, device, alloc, depthCreateInfo, vk::MemoryRequirement::Any));
651         m_depthImageView = vk::makeImageView(vk, device, **depthImage, vk::VK_IMAGE_VIEW_TYPE_2D, m_params.depthFormat,
652                                              depthSubresourceRange);
653     }
654 
655     std::vector<de::MovePtr<vk::BufferWithMemory>> colorOutputBuffers;
656     for (uint32_t i = 0; i < colorAttachmentCount; ++i)
657     {
658         const vk::VkDeviceSize colorOutputBufferSize = m_renderArea.extent.width * m_renderArea.extent.height *
659                                                        tcu::getPixelSize(vk::mapVkFormat(m_colorFormats[i]));
660         colorOutputBuffers.push_back(de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
661             vk, device, alloc, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT),
662             vk::MemoryRequirement::HostVisible)));
663     }
664 
665     const auto &binaries = m_context.getBinaryCollection();
666     const auto vertShader =
667         vk::createShader(vk, device,
668                          vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_VERTEX_BIT, binaries.get("vertDepth"),
669                                                   tessellationSupported, geometrySupported));
670     const auto fragShader =
671         vk::createShader(vk, device,
672                          vk::makeShaderCreateInfo(vk::VK_SHADER_STAGE_FRAGMENT_BIT, binaries.get("fragMulti"),
673                                                   tessellationSupported, geometrySupported));
674 
675     const vk::Move<vk::VkCommandPool> cmdPool(vk::createCommandPool(vk, device, 0u, queueFamilyIndex));
676     const vk::Move<vk::VkCommandBuffer> cmdBuffer(
677         vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
678 
679     vk::beginCommandBuffer(vk, *cmdBuffer);
680 
681     if (m_params.dummyRenderPass == DUMMY_DYNAMIC)
682     {
683         createDummyImage();
684         const vk::VkClearValue clearValue = vk::makeClearValueColor({0.0f, 0.0f, 0.0f, 1.0f});
685         vk::beginRendering(vk, *cmdBuffer, *m_dummyImageView, m_renderArea, clearValue);
686     }
687     else if (m_params.dummyRenderPass == DUMMY_STATIC)
688     {
689         createDummyImage();
690         createDummyRenderPass();
691         const vk::VkClearValue clearValue = vk::makeClearValueColor({0.0f, 0.0f, 0.0f, 1.0f});
692         vk::beginRenderPass(vk, *cmdBuffer, *m_dummyRenderPass, *m_dummyFramebuffer, m_renderArea, clearValue);
693     }
694 
695     if (m_params.bindShadersBeforeBeginRendering)
696         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE,
697                                 *fragShader, taskSupported, meshSupported);
698 
699     if (m_params.dummyRenderPass == DUMMY_DYNAMIC)
700     {
701         vk::endRendering(vk, *cmdBuffer);
702     }
703     else if (m_params.dummyRenderPass == DUMMY_STATIC)
704     {
705         vk::endRenderPass(vk, *cmdBuffer);
706     }
707 
708     for (const auto &colorImage : colorImages)
709     {
710         vk::VkImageMemoryBarrier preImageBarrier = vk::makeImageMemoryBarrier(
711             vk::VK_ACCESS_NONE, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED,
712             vk::VK_IMAGE_LAYOUT_GENERAL, **colorImage, colorSubresourceRange);
713         vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
714                               vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (vk::VkDependencyFlags)0u, 0u,
715                               (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
716                               &preImageBarrier);
717     }
718 
719     if (m_params.useDepthAttachment)
720     {
721         vk::VkImageMemoryBarrier preDepthImageBarrier = vk::makeImageMemoryBarrier(
722             vk::VK_ACCESS_NONE, vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED,
723             vk::VK_IMAGE_LAYOUT_GENERAL, **depthImage, depthSubresourceRange);
724         vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
725                               vk::VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, (vk::VkDependencyFlags)0u, 0u,
726                               (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
727                               &preDepthImageBarrier);
728     }
729 
730     beginRendering(*cmdBuffer);
731     vk::setDefaultShaderObjectDynamicStates(vk, *cmdBuffer, deviceExtensions, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
732     vk::VkBool32 colorBlendEnable                  = VK_FALSE;
733     vk::VkColorBlendEquationEXT colorBlendEquation = {
734         vk::VK_BLEND_FACTOR_ONE, // VkBlendFactor srcColorBlendFactor;
735         vk::VK_BLEND_FACTOR_ONE, // VkBlendFactor dstColorBlendFactor;
736         vk::VK_BLEND_OP_ADD,     // VkBlendOp colorBlendOp;
737         vk::VK_BLEND_FACTOR_ONE, // VkBlendFactor srcAlphaBlendFactor;
738         vk::VK_BLEND_FACTOR_ONE, // VkBlendFactor dstAlphaBlendFactor;
739         vk::VK_BLEND_OP_ADD,     // VkBlendOp alphaBlendOp;
740     };
741     vk::VkColorComponentFlags colorWriteMask = vk::VK_COLOR_COMPONENT_R_BIT | vk::VK_COLOR_COMPONENT_G_BIT |
742                                                vk::VK_COLOR_COMPONENT_B_BIT | vk::VK_COLOR_COMPONENT_A_BIT;
743     uint32_t count = colorAttachmentCount + m_params.extraFragmentOutputCount;
744     if (count == 0)
745         ++count;
746     std::vector<vk::VkBool32> colorBlendEnables(count, colorBlendEnable);
747     std::vector<vk::VkColorBlendEquationEXT> colorBlendEquations(count, colorBlendEquation);
748     std::vector<vk::VkColorComponentFlags> colorWriteMasks(count, colorWriteMask);
749     vk.cmdSetColorBlendEnableEXT(*cmdBuffer, 0u, count, colorBlendEnables.data());
750     vk.cmdSetColorBlendEquationEXT(*cmdBuffer, 0u, count, colorBlendEquations.data());
751     vk.cmdSetColorWriteMaskEXT(*cmdBuffer, 0u, count, colorWriteMasks.data());
752     std::vector<vk::VkBool32> colorWriteEnables(count, VK_TRUE);
753     vk.cmdSetColorWriteEnableEXT(*cmdBuffer, count, colorWriteEnables.data());
754     vk.cmdSetDepthWriteEnable(*cmdBuffer, VK_TRUE);
755     vk.cmdSetDepthTestEnable(*cmdBuffer, VK_TRUE);
756     vk.cmdSetDepthCompareOp(*cmdBuffer, vk::VK_COMPARE_OP_LESS);
757     vk::bindNullTaskMeshShaders(vk, *cmdBuffer, m_context.getMeshShaderFeaturesEXT());
758     if (!m_params.bindShadersBeforeBeginRendering)
759         vk::bindGraphicsShaders(vk, *cmdBuffer, *vertShader, VK_NULL_HANDLE, VK_NULL_HANDLE, VK_NULL_HANDLE,
760                                 *fragShader, taskSupported, meshSupported);
761     vk.cmdDraw(*cmdBuffer, 4, 1, 0, 0);
762     vk::endRendering(vk, *cmdBuffer);
763 
764     for (const auto &colorImage : colorImages)
765     {
766         vk::VkImageMemoryBarrier postImageBarrier = vk::makeImageMemoryBarrier(
767             vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_GENERAL,
768             vk::VK_IMAGE_LAYOUT_GENERAL, **colorImage, colorSubresourceRange);
769         vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
770                               vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u,
771                               (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
772                               &postImageBarrier);
773     }
774 
775     if (m_params.useDepthAttachment)
776     {
777         vk::VkImageMemoryBarrier postDepthImageBarrier = vk::makeImageMemoryBarrier(
778             vk::VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT,
779             vk::VK_IMAGE_LAYOUT_GENERAL, vk::VK_IMAGE_LAYOUT_GENERAL, **depthImage, depthSubresourceRange);
780         vk.cmdPipelineBarrier(*cmdBuffer, vk::VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
781                               vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u,
782                               (const vk::VkMemoryBarrier *)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier *)DE_NULL, 1u,
783                               &postDepthImageBarrier);
784     }
785 
786     const vk::VkBufferImageCopy colorCopyRegion = vk::makeBufferImageCopy(extent, colorSubresourceLayers);
787     for (uint32_t i = 0; i < colorAttachmentCount; ++i)
788         vk.cmdCopyImageToBuffer(*cmdBuffer, **colorImages[i], vk::VK_IMAGE_LAYOUT_GENERAL, **colorOutputBuffers[i], 1u,
789                                 &colorCopyRegion);
790 
791     vk::endCommandBuffer(vk, *cmdBuffer);
792 
793     vk::submitCommandsAndWait(vk, device, queue, *cmdBuffer);
794 
795     std::vector<tcu::ConstPixelBufferAccess> colorResultBuffers;
796     for (uint32_t i = 0; i < colorAttachmentCount; ++i)
797         colorResultBuffers.push_back(tcu::ConstPixelBufferAccess(
798             vk::mapVkFormat(m_colorFormats[i]), m_renderArea.extent.width, m_renderArea.extent.height, 1,
799             (const void *)colorOutputBuffers[i]->getAllocation().getHostPtr()));
800 
801     const uint32_t width   = m_renderArea.extent.width;
802     const uint32_t height  = m_renderArea.extent.height;
803     const uint32_t xOffset = 8;
804     const uint32_t yOffset = 8;
805 
806     for (uint32_t k = 0; k < (uint32_t)colorImages.size(); ++k)
807     {
808         tcu::TextureLevel textureLevel(mapVkFormat(m_colorFormats[k]), width, height);
809         const tcu::PixelBufferAccess expectedImage = textureLevel.getAccess();
810         generateExpectedImage(expectedImage, width, height, k);
811 
812         if (vk::isFloatFormat(m_colorFormats[k]))
813         {
814             if (!tcu::floatThresholdCompare(log, "Image Comparison", "", expectedImage, colorResultBuffers[k],
815                                             tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
816                 return tcu::TestStatus::fail("Fail");
817         }
818         else
819         {
820             if (!tcu::intThresholdCompare(log, "Image Comparison", "", expectedImage, colorResultBuffers[k],
821                                           tcu::UVec4(2), tcu::COMPARE_LOG_RESULT))
822                 return tcu::TestStatus::fail("Fail");
823         }
824     }
825 
826     if (m_params.useDepthAttachment)
827     {
828         const auto depthBuffer = readDepthAttachment(
829             vk, device, queue, queueFamilyIndex, alloc, **depthImage, m_params.depthFormat,
830             tcu::UVec2(m_renderArea.extent.width, m_renderArea.extent.height), vk::VK_IMAGE_LAYOUT_GENERAL);
831         const auto depthAccess = depthBuffer->getAccess();
832 
833         const float depthEpsilon = 0.02f;
834         for (uint32_t j = 0; j < height; ++j)
835         {
836             for (uint32_t i = 0; i < width; ++i)
837             {
838                 const float depth = depthAccess.getPixDepth(i, j);
839                 if (i >= xOffset && i < width - xOffset && j >= yOffset && j < height - yOffset)
840                 {
841                     if (deFloatAbs(depth - 0.5f) > depthEpsilon)
842                     {
843                         log << tcu::TestLog::Message << "Depth at (" << i << ", " << j
844                             << ") is expected to be 0.5, but was (" << depth << ")" << tcu::TestLog::EndMessage;
845                         return tcu::TestStatus::fail("Fail");
846                     }
847                 }
848                 else
849                 {
850                     if (deFloatAbs(depth - 1.0f) > depthEpsilon)
851                     {
852                         log << tcu::TestLog::Message << "Color at (" << i << ", " << j
853                             << ") is expected to be 0.0, but was (" << depth << ")" << tcu::TestLog::EndMessage;
854                         return tcu::TestStatus::fail("Fail");
855                     }
856                 }
857             }
858         }
859     }
860 
861     return tcu::TestStatus::pass("Pass");
862 }
863 
864 class ShaderObjectRenderingCase : public vkt::TestCase
865 {
866 public:
ShaderObjectRenderingCase(tcu::TestContext & testCtx,const std::string & name,const TestParams & params)867     ShaderObjectRenderingCase(tcu::TestContext &testCtx, const std::string &name, const TestParams &params)
868         : vkt::TestCase(testCtx, name)
869         , m_params(params)
870     {
871     }
~ShaderObjectRenderingCase(void)872     virtual ~ShaderObjectRenderingCase(void)
873     {
874     }
875 
876     void checkSupport(vkt::Context &context) const override;
877     virtual void initPrograms(vk::SourceCollections &programCollection) const override;
createInstance(Context & context) const878     TestInstance *createInstance(Context &context) const override
879     {
880         return new ShaderObjectRenderingInstance(context, m_params);
881     }
882 
883 private:
884     TestParams m_params;
885 };
886 
checkSupport(Context & context) const887 void ShaderObjectRenderingCase::checkSupport(Context &context) const
888 {
889     const auto &vki                                 = context.getInstanceInterface();
890     const auto physicalDevice                       = context.getPhysicalDevice();
891     const vk::VkPhysicalDeviceProperties properties = vk::getPhysicalDeviceProperties(vki, physicalDevice);
892 
893     context.requireDeviceFunctionality("VK_EXT_shader_object");
894 
895     if (m_params.colorAttachmentCount + m_params.extraAttachmentCount + m_params.extraFragmentOutputCount >
896         properties.limits.maxColorAttachments)
897         TCU_THROW(NotSupportedError,
898                   "Tests uses more color attachments than VkPhysicalDeviceLimits::maxColorAttachments");
899 
900     vk::VkImageFormatProperties colorImageFormatProperties;
901     const auto colorResult = vki.getPhysicalDeviceImageFormatProperties(
902         physicalDevice, m_params.colorFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL,
903         (vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT), 0,
904         &colorImageFormatProperties);
905     if (colorResult != vk::VK_SUCCESS)
906         TCU_THROW(NotSupportedError, "Format unsupported for tiling");
907     vk::VkImageFormatProperties depthImageFormatProperties;
908     if (m_params.useDepthAttachment)
909     {
910         const auto depthResult = vki.getPhysicalDeviceImageFormatProperties(
911             physicalDevice, m_params.depthFormat, vk::VK_IMAGE_TYPE_2D, vk::VK_IMAGE_TILING_OPTIMAL,
912             (vk::VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT), 0,
913             &depthImageFormatProperties);
914         if (depthResult != vk::VK_SUCCESS)
915             TCU_THROW(NotSupportedError, "Format unsupported for tiling");
916     }
917 }
918 
initPrograms(vk::SourceCollections & programCollection) const919 void ShaderObjectRenderingCase::initPrograms(vk::SourceCollections &programCollection) const
920 {
921     std::stringstream vertDepth;
922     std::stringstream fragMulti;
923 
924     vertDepth << "#version 450\n"
925               << "void main() {\n"
926               << "    vec2 pos = vec2(float(gl_VertexIndex & 1), float((gl_VertexIndex >> 1) & 1));\n"
927               << "    gl_Position = vec4(pos - 0.5f, 0.5f, 1.0f);\n"
928               << "}\n";
929 
930     fragMulti << "#version 450\n";
931     uint32_t outputCount = m_params.colorAttachmentCount + m_params.extraFragmentOutputCount;
932     for (uint32_t i = 0; i < outputCount; ++i)
933     {
934         uint32_t j = i;
935         if (m_params.extraAttachments == BEFORE || (m_params.extraAttachments == BETWEEN && i > outputCount / 2))
936             j += m_params.extraAttachmentCount;
937         bool firstWrittenAttachment =
938             (m_params.extraOutputs == BEFORE) ? (i == m_params.extraFragmentOutputCount) : (i == 0);
939         if (vk::isUintFormat(m_params.colorFormat) && (firstWrittenAttachment || !m_params.randomColorFormats))
940             fragMulti << "layout (location = " << j << ") out uvec4 outColor" << j << ";\n";
941         else if (vk::isIntFormat(m_params.colorFormat) && (firstWrittenAttachment || !m_params.randomColorFormats))
942             fragMulti << "layout (location = " << j << ") out ivec4 outColor" << j << ";\n";
943         else
944             fragMulti << "layout (location = " << j << ") out vec4 outColor" << j << ";\n";
945     }
946     fragMulti << "void main() {\n";
947     for (uint32_t i = 0; i < outputCount; ++i)
948     {
949         uint32_t j = i;
950         if (m_params.extraAttachments == BEFORE || (m_params.extraAttachments == BETWEEN && i > outputCount / 2))
951             j += m_params.extraAttachmentCount;
952         bool firstWrittenAttachment =
953             (m_params.extraOutputs == BEFORE) ? (i == m_params.extraFragmentOutputCount) : (i == 0);
954         if (vk::isUintFormat(m_params.colorFormat) && (firstWrittenAttachment || !m_params.randomColorFormats))
955             fragMulti << "    outColor" << j << " = uvec4(255);\n";
956         else if (vk::isIntFormat(m_params.colorFormat) && (firstWrittenAttachment || !m_params.randomColorFormats))
957             fragMulti << "    outColor" << j << " = ivec4(255);\n";
958         else
959             fragMulti << "    outColor" << j << " = vec4(1.0f);\n";
960     }
961     if (m_params.writeGlFragDepth)
962         fragMulti << "    gl_FragDepth = 0.5f;\n";
963     fragMulti << "}\n";
964 
965     programCollection.glslSources.add("vertDepth") << glu::VertexSource(vertDepth.str());
966     programCollection.glslSources.add("fragMulti") << glu::FragmentSource(fragMulti.str());
967 }
968 
969 } // namespace
970 
getFormatCaseName(vk::VkFormat format)971 std::string getFormatCaseName(vk::VkFormat format)
972 {
973     return de::toLower(de::toString(getFormatStr(format)).substr(10));
974 }
975 
createShaderObjectRenderingTests(tcu::TestContext & testCtx)976 tcu::TestCaseGroup *createShaderObjectRenderingTests(tcu::TestContext &testCtx)
977 {
978     de::MovePtr<tcu::TestCaseGroup> renderingGroup(new tcu::TestCaseGroup(testCtx, "rendering"));
979 
980     const struct
981     {
982         uint32_t colorAttachmentCount;
983         const char *name;
984     } colorAttachmentCountTests[] = {
985         {
986             0u,
987             "color_attachment_count_0",
988         },
989         {
990             1u,
991             "color_attachment_count_1",
992         },
993         {
994             4u,
995             "color_attachment_count_4",
996         },
997         {
998             8u,
999             "color_attachment_count_8",
1000         },
1001     };
1002 
1003     const struct
1004     {
1005         uint32_t extraAttachmentCount;
1006         ExtraAttachments extraAttachment;
1007         const char *name;
1008     } extraAttachmentTests[] = {
1009         {
1010             0u,
1011             NONE,
1012             "none",
1013         },
1014         {
1015             1u,
1016             BEFORE,
1017             "extra_attachment_before_1",
1018         },
1019         {
1020             1u,
1021             BETWEEN,
1022             "extra_attachment_between_1",
1023         },
1024         {
1025             1u,
1026             AFTER,
1027             "extra_attachment_after_1",
1028         },
1029         {
1030             2u,
1031             BEFORE,
1032             "extra_attachment_before_2",
1033         },
1034         {
1035             2u,
1036             BETWEEN,
1037             "extra_attachment_between_2",
1038         },
1039         {
1040             2u,
1041             AFTER,
1042             "extra_attachment_after_2",
1043         },
1044     };
1045 
1046     const struct
1047     {
1048         uint32_t extraFragmentOutputCount;
1049         ExtraAttachments extraAttachment;
1050         const char *name;
1051     } extraOutputTests[] = {
1052         {
1053             0u,
1054             NONE,
1055             "none",
1056         },
1057         {
1058             1u,
1059             BEFORE,
1060             "extra_output_before_1",
1061         },
1062         {
1063             1u,
1064             BETWEEN,
1065             "extra_output_between_1",
1066         },
1067         {
1068             1u,
1069             AFTER,
1070             "extra_output_after_1",
1071         },
1072         {
1073             2u,
1074             BEFORE,
1075             "extra_output_before_2",
1076         },
1077         {
1078             2u,
1079             BETWEEN,
1080             "extra_output_between_2",
1081         },
1082         {
1083             2u,
1084             AFTER,
1085             "extra_output_after_2",
1086         },
1087     };
1088 
1089     const vk::VkFormat depthStencilFormats[] = {
1090         vk::VK_FORMAT_D16_UNORM,         vk::VK_FORMAT_X8_D24_UNORM_PACK32, vk::VK_FORMAT_D32_SFLOAT,
1091         vk::VK_FORMAT_D16_UNORM_S8_UINT, vk::VK_FORMAT_D24_UNORM_S8_UINT,   vk::VK_FORMAT_D32_SFLOAT_S8_UINT,
1092     };
1093 
1094     const struct
1095     {
1096         DummyRenderPass dummyRenderPass;
1097         const char *name;
1098     } dummyRenderPassTests[] = {
1099         {
1100             DUMMY_NONE,
1101             "none",
1102         },
1103         {
1104             DUMMY_DYNAMIC,
1105             "dynamic",
1106         },
1107         {
1108             DUMMY_STATIC,
1109             "static",
1110         },
1111     };
1112 
1113     for (const auto &colorAttachmentCountTest : colorAttachmentCountTests)
1114     {
1115         de::MovePtr<tcu::TestCaseGroup> colorAttachmentGroup(
1116             new tcu::TestCaseGroup(testCtx, colorAttachmentCountTest.name));
1117         for (const auto &extraAttachment : extraAttachmentTests)
1118         {
1119             de::MovePtr<tcu::TestCaseGroup> extraAttachmentGroup(new tcu::TestCaseGroup(testCtx, extraAttachment.name));
1120             for (const auto &extraOutput : extraOutputTests)
1121             {
1122                 if (extraAttachment.extraAttachment != NONE && extraOutput.extraFragmentOutputCount != NONE)
1123                     continue;
1124 
1125                 de::MovePtr<tcu::TestCaseGroup> extraOutputGroup(new tcu::TestCaseGroup(testCtx, extraOutput.name));
1126 
1127                 for (const auto &dummyRenderPass : dummyRenderPassTests)
1128                 {
1129                     de::MovePtr<tcu::TestCaseGroup> dummyRenderPassGroup(
1130                         new tcu::TestCaseGroup(testCtx, dummyRenderPass.name));
1131                     for (uint32_t m = 0; m < 2; ++m)
1132                     {
1133                         bool useRandomColorFormats = m == 0;
1134                         if (useRandomColorFormats && colorAttachmentCountTest.colorAttachmentCount < 2)
1135                             continue;
1136                         std::string randomColorFormatsName =
1137                             useRandomColorFormats ? "random_color_formats" : "same_color_formats";
1138                         de::MovePtr<tcu::TestCaseGroup> randomColorFormatsGroup(
1139                             new tcu::TestCaseGroup(testCtx, randomColorFormatsName.c_str()));
1140                         for (uint32_t k = 0; k < 2; ++k)
1141                         {
1142                             bool bindShadersBeforeBeginRendering = k == 0;
1143                             std::string bindName                 = bindShadersBeforeBeginRendering ? "before" : "after";
1144                             de::MovePtr<tcu::TestCaseGroup> bindGroup(
1145                                 new tcu::TestCaseGroup(testCtx, bindName.c_str()));
1146                             for (uint32_t l = 0; l < 2; ++l)
1147                             {
1148                                 bool writeGlFragDepth       = l == 0;
1149                                 std::string writeGlFragName = writeGlFragDepth ? "gl_frag_write" : "none";
1150                                 de::MovePtr<tcu::TestCaseGroup> fragWriteGroup(
1151                                     new tcu::TestCaseGroup(testCtx, writeGlFragName.c_str()));
1152                                 for (uint32_t i = 0; i < DE_LENGTH_OF_ARRAY(colorFormats); ++i)
1153                                 {
1154                                     if (extraAttachment.extraAttachmentCount >
1155                                         colorAttachmentCountTest.colorAttachmentCount)
1156                                         continue;
1157 
1158                                     if (!bindShadersBeforeBeginRendering &&
1159                                         dummyRenderPass.dummyRenderPass != DUMMY_NONE)
1160                                         continue;
1161 
1162                                     const auto colorFormat = colorFormats[i];
1163 
1164                                     TestParams params;
1165                                     params.colorAttachmentCount     = colorAttachmentCountTest.colorAttachmentCount;
1166                                     params.extraAttachmentCount     = extraAttachment.extraAttachmentCount;
1167                                     params.extraAttachments         = extraAttachment.extraAttachment;
1168                                     params.extraFragmentOutputCount = extraOutput.extraFragmentOutputCount;
1169                                     params.extraOutputs             = extraOutput.extraAttachment;
1170                                     params.useDepthAttachment       = false;
1171                                     params.colorFormat              = colorFormat;
1172                                     params.depthFormat              = vk::VK_FORMAT_UNDEFINED;
1173                                     params.bindShadersBeforeBeginRendering = bindShadersBeforeBeginRendering;
1174                                     params.dummyRenderPass                 = dummyRenderPass.dummyRenderPass;
1175                                     params.writeGlFragDepth                = writeGlFragDepth;
1176                                     params.randomColorFormats              = useRandomColorFormats;
1177 
1178                                     std::string name = getFormatCaseName(colorFormat);
1179                                     fragWriteGroup->addChild(new ShaderObjectRenderingCase(testCtx, name, params));
1180 
1181                                     if (writeGlFragDepth)
1182                                         continue;
1183 
1184                                     for (uint32_t j = 0; j < DE_LENGTH_OF_ARRAY(depthStencilFormats); ++j)
1185                                     {
1186                                         const auto depthFormat    = depthStencilFormats[j];
1187                                         params.useDepthAttachment = true;
1188                                         params.depthFormat        = depthFormat;
1189 
1190                                         std::string depthTestName = name + "_" + getFormatCaseName(depthFormat);
1191                                         fragWriteGroup->addChild(
1192                                             new ShaderObjectRenderingCase(testCtx, depthTestName, params));
1193                                     }
1194                                 }
1195                                 bindGroup->addChild(fragWriteGroup.release());
1196                             }
1197                             randomColorFormatsGroup->addChild(bindGroup.release());
1198                         }
1199                         dummyRenderPassGroup->addChild(randomColorFormatsGroup.release());
1200                     }
1201                     extraOutputGroup->addChild(dummyRenderPassGroup.release());
1202                 }
1203                 extraAttachmentGroup->addChild(extraOutputGroup.release());
1204             }
1205             colorAttachmentGroup->addChild(extraAttachmentGroup.release());
1206         }
1207         renderingGroup->addChild(colorAttachmentGroup.release());
1208     }
1209 
1210     return renderingGroup.release();
1211 }
1212 
1213 } // namespace ShaderObject
1214 } // namespace vkt
1215