1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2019 The Khronos Group Inc.
6 * Copyright (c) 2018 Google Inc.
7 * Copyright (c) 2015 Imagination Technologies Ltd.
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 * http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Tests sparse input attachments in VkSubpassDescription::pInputAttachments
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktRenderPassUnusedAttachmentSparseFillingTests.hpp"
27 #include "vktRenderPassTestsUtil.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkImageUtil.hpp"
30 #include "vkBuilderUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkCmdUtil.hpp"
33 #include "vkObjUtil.hpp"
34 #include "tcuTestLog.hpp"
35 #include "deRandom.hpp"
36 #include <sstream>
37 #include <vector>
38 #include <algorithm>
39 #include <numeric>
40 #include <random>
41
42 typedef de::SharedPtr<vk::Unique<vk::VkImage> > VkImageSp;
43 typedef de::SharedPtr<vk::Unique<vk::VkImageView> > VkImageViewSp;
44 typedef de::SharedPtr<vk::Unique<vk::VkBuffer> > VkBufferSp;
45 typedef de::SharedPtr<vk::Allocation> AllocationSp;
46
47 namespace vkt
48 {
49
50 namespace renderpass
51 {
52
53 using namespace vk;
54
55 template<typename T>
safeSharedPtr(T * ptr)56 de::SharedPtr<T> safeSharedPtr(T* ptr)
57 {
58 try
59 {
60 return de::SharedPtr<T>(ptr);
61 }
62 catch (...)
63 {
64 delete ptr;
65 throw;
66 }
67 }
68
69 static const deUint32 RENDER_SIZE = 8u;
70 static const unsigned int DEFAULT_SEED = 31u;
71
72 namespace
73 {
74
75 struct TestParams
76 {
77 RenderingType renderingType;
78 deUint32 activeInputAttachmentCount;
79 };
80
81 struct Vertex
82 {
83 tcu::Vec4 position;
84 tcu::Vec4 uv;
85 };
86
createFullscreenTriangle(void)87 std::vector<Vertex> createFullscreenTriangle (void)
88 {
89 std::vector<Vertex> vertices;
90
91 for (deUint32 i = 0; i < 3; ++i)
92 {
93 float x = static_cast<float>((i << 1) & 2);
94 float y = static_cast<float>(i & 2);
95 vertices.push_back(Vertex{ tcu::Vec4(x * 2.0f - 1.0f, y * 2.0f - 1.0f, 0.0f, 1.0f), tcu::Vec4(x,y,0.0f,0.0f) });
96 }
97 return vertices;
98 }
99
generateInputAttachmentParams(deUint32 activeAttachmentCount,deUint32 allAttachmentCount,std::vector<deUint32> & attachmentIndices,std::vector<deUint32> & descriptorBindings)100 void generateInputAttachmentParams(deUint32 activeAttachmentCount, deUint32 allAttachmentCount, std::vector<deUint32>& attachmentIndices, std::vector<deUint32>& descriptorBindings)
101 {
102 attachmentIndices.resize(allAttachmentCount);
103 std::iota(begin(attachmentIndices), begin(attachmentIndices) + activeAttachmentCount, 0);
104 std::fill(begin(attachmentIndices) + activeAttachmentCount, end(attachmentIndices), VK_ATTACHMENT_UNUSED);
105 de::Random random(DEFAULT_SEED);
106 random.shuffle(begin(attachmentIndices), end(attachmentIndices));
107
108 descriptorBindings.resize(activeAttachmentCount+1);
109 descriptorBindings[0] = VK_ATTACHMENT_UNUSED;
110 for (deUint32 i = 0, lastBinding = 1; i < allAttachmentCount; ++i)
111 {
112 if (attachmentIndices[i] != VK_ATTACHMENT_UNUSED)
113 descriptorBindings[lastBinding++] = i;
114 }
115 }
116
117 class InputAttachmentSparseFillingTest : public vkt::TestCase
118 {
119 public:
120 InputAttachmentSparseFillingTest (tcu::TestContext& testContext,
121 const std::string& name,
122 const std::string& description,
123 const TestParams& testParams);
124 virtual ~InputAttachmentSparseFillingTest (void);
125 virtual void initPrograms (SourceCollections& sourceCollections) const;
126 virtual TestInstance* createInstance (Context& context) const;
127 virtual void checkSupport (Context& context) const;
128
129 private:
130 TestParams m_testParams;
131 };
132
133 class InputAttachmentSparseFillingTestInstance : public vkt::TestInstance
134 {
135 public:
136 InputAttachmentSparseFillingTestInstance (Context& context,
137 const TestParams& testParams);
138 virtual ~InputAttachmentSparseFillingTestInstance (void);
139 virtual tcu::TestStatus iterate (void);
140 template<typename RenderpassSubpass>
141 void createCommandBuffer (const DeviceInterface& vk,
142 VkDevice vkDevice);
143
144 template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
145 Move<VkRenderPass> createRenderPass (const DeviceInterface& vk,
146 VkDevice vkDevice);
147 private:
148 tcu::TestStatus verifyImage (void);
149
150 const tcu::UVec2 m_renderSize;
151 std::vector<Vertex> m_vertices;
152 TestParams m_testParams;
153
154 std::vector<VkImageSp> m_inputImages;
155 std::vector<AllocationSp> m_inputImageMemory;
156 std::vector<VkImageViewSp> m_inputImageViews;
157
158 VkImageSp m_outputImage;
159 AllocationSp m_outputImageMemory;
160 VkImageViewSp m_outputImageView;
161
162 VkBufferSp m_outputBuffer;
163 AllocationSp m_outputBufferMemory;
164
165 Move<VkDescriptorSetLayout> m_descriptorSetLayout;
166 Move<VkDescriptorPool> m_descriptorPool;
167 Move<VkDescriptorSet> m_descriptorSet;
168 Move<VkRenderPass> m_renderPass;
169 Move<VkFramebuffer> m_framebuffer;
170
171 Move<VkShaderModule> m_vertexShaderModule;
172 Move<VkShaderModule> m_fragmentShaderModule;
173
174 Move<VkBuffer> m_vertexBuffer;
175 de::MovePtr<Allocation> m_vertexBufferAlloc;
176
177 Move<VkPipelineLayout> m_pipelineLayout;
178 Move<VkPipeline> m_graphicsPipeline;
179
180 Move<VkCommandPool> m_cmdPool;
181 Move<VkCommandBuffer> m_cmdBuffer;
182 };
183
InputAttachmentSparseFillingTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const TestParams & testParams)184 InputAttachmentSparseFillingTest::InputAttachmentSparseFillingTest (tcu::TestContext& testContext,
185 const std::string& name,
186 const std::string& description,
187 const TestParams& testParams)
188 : vkt::TestCase (testContext, name, description), m_testParams(testParams)
189 {
190 }
191
~InputAttachmentSparseFillingTest(void)192 InputAttachmentSparseFillingTest::~InputAttachmentSparseFillingTest (void)
193 {
194 }
195
initPrograms(SourceCollections & sourceCollections) const196 void InputAttachmentSparseFillingTest::initPrograms (SourceCollections& sourceCollections) const
197 {
198 std::ostringstream fragmentSource;
199
200 sourceCollections.glslSources.add("vertex") << glu::VertexSource(
201 "#version 450\n"
202 "layout(location = 0) in vec4 position;\n"
203 "layout(location = 1) in vec4 uv;\n"
204 "layout(location = 0) out vec4 outUV;\n"
205 "void main (void)\n"
206 "{\n"
207 " gl_Position = position;\n"
208 " outUV = uv;\n"
209 "}\n");
210
211 // We read from X input attachments randomly spread in input attachment array of size 2*X
212 std::ostringstream str;
213 str << "#version 450\n"
214 << "layout(location = 0) in vec4 inUV;\n"
215 << "layout(binding = 0, rg32ui) uniform uimage2D resultImage;\n";
216
217 std::vector<deUint32> attachmentIndices, descriptorBindings;
218 generateInputAttachmentParams(m_testParams.activeInputAttachmentCount, 2u * m_testParams.activeInputAttachmentCount, attachmentIndices, descriptorBindings);
219
220 for (std::size_t i = 1; i < descriptorBindings.size(); ++i)
221 str << "layout(binding = " << i << ", input_attachment_index = " << descriptorBindings[i] <<") uniform subpassInput attach" << i <<";\n";
222
223 str << "void main (void)\n"
224 << "{\n"
225 << " uvec4 result = uvec4(0);\n";
226
227 for (std::size_t i = 1; i < descriptorBindings.size(); ++i)
228 {
229 str << " result.x = result.x + 1;\n";
230 str << " if(subpassLoad(attach" << i << ").x > 0.0)\n";
231 str << " result.y = result.y + 1;\n";
232 }
233
234 str << " imageStore(resultImage, ivec2(imageSize(resultImage) * inUV.xy), result);\n"
235 << "}\n";
236
237 sourceCollections.glslSources.add("fragment") << glu::FragmentSource(str.str());
238 }
239
createInstance(Context & context) const240 TestInstance* InputAttachmentSparseFillingTest::createInstance(Context& context) const
241 {
242 return new InputAttachmentSparseFillingTestInstance(context, m_testParams);
243 }
244
checkSupport(Context & context) const245 void InputAttachmentSparseFillingTest::checkSupport(Context& context) const
246 {
247 if (m_testParams.renderingType == RENDERING_TYPE_RENDERPASS2)
248 context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
249
250 const vk::VkPhysicalDeviceLimits limits = getPhysicalDeviceProperties(context.getInstanceInterface(), context.getPhysicalDevice()).limits;
251
252 if( 2u * m_testParams.activeInputAttachmentCount > limits.maxPerStageDescriptorInputAttachments )
253 TCU_THROW(NotSupportedError, "Input attachment count including unused elements exceeds maxPerStageDescriptorInputAttachments");
254
255 if ( 2u * m_testParams.activeInputAttachmentCount > limits.maxPerStageResources)
256 TCU_THROW(NotSupportedError, "Input attachment count including unused elements exceeds maxPerStageResources");
257 }
258
InputAttachmentSparseFillingTestInstance(Context & context,const TestParams & testParams)259 InputAttachmentSparseFillingTestInstance::InputAttachmentSparseFillingTestInstance (Context& context, const TestParams& testParams)
260 : vkt::TestInstance (context)
261 , m_renderSize (RENDER_SIZE, RENDER_SIZE)
262 , m_vertices (createFullscreenTriangle())
263 , m_testParams (testParams)
264 {
265 const DeviceInterface& vk = m_context.getDeviceInterface();
266 const VkDevice vkDevice = m_context.getDevice();
267 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
268 SimpleAllocator memAlloc (vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
269 const VkComponentMapping componentMappingRGBA = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
270
271 {
272 const VkImageCreateInfo inputImageParams =
273 {
274 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
275 DE_NULL, // const void* pNext;
276 0u, // VkImageCreateFlags flags;
277 VK_IMAGE_TYPE_2D, // VkImageType imageType;
278 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
279 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
280 1u, // deUint32 mipLevels;
281 1u, // deUint32 arrayLayers;
282 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
283 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
284 VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
285 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
286 1u, // deUint32 queueFamilyIndexCount;
287 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
288 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
289 };
290
291 VkImageViewCreateInfo inputAttachmentViewParams =
292 {
293 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
294 DE_NULL, // const void* pNext;
295 0u, // VkImageViewCreateFlags flags;
296 0, // VkImage image;
297 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
298 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format;
299 componentMappingRGBA, // VkChannelMapping channels;
300 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
301 };
302
303 // Create input attachment images with image views
304 for (deUint32 imageNdx = 0; imageNdx < m_testParams.activeInputAttachmentCount; ++imageNdx)
305 {
306 auto inputImage = safeSharedPtr(new Unique<VkImage>(vk::createImage(vk, vkDevice, &inputImageParams)));
307
308 auto inputImageAlloc = safeSharedPtr(memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, **inputImage), MemoryRequirement::Any).release());
309 VK_CHECK(vk.bindImageMemory(vkDevice, **inputImage, inputImageAlloc->getMemory(), inputImageAlloc->getOffset()));
310
311 inputAttachmentViewParams.image = **inputImage;
312 auto inputImageView = safeSharedPtr(new Unique<VkImageView>(createImageView(vk, vkDevice, &inputAttachmentViewParams)));
313
314 m_inputImages.push_back(inputImage);
315 m_inputImageMemory.push_back(inputImageAlloc);
316 m_inputImageViews.push_back(inputImageView);
317 }
318 }
319
320 {
321 const VkImageCreateInfo outputImageParams =
322 {
323 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
324 DE_NULL, // const void* pNext;
325 0u, // VkImageCreateFlags flags;
326 VK_IMAGE_TYPE_2D, // VkImageType imageType;
327 VK_FORMAT_R32G32_UINT, // VkFormat format;
328 { m_renderSize.x(), m_renderSize.y(), 1u }, // VkExtent3D extent;
329 1u, // deUint32 mipLevels;
330 1u, // deUint32 arrayLayers;
331 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
332 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
333 VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
334 VK_IMAGE_USAGE_TRANSFER_DST_BIT, // VkImageUsageFlags usage;
335 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
336 1u, // deUint32 queueFamilyIndexCount;
337 &queueFamilyIndex, // const deUint32* pQueueFamilyIndices;
338 VK_IMAGE_LAYOUT_UNDEFINED // VkImageLayout initialLayout;
339 };
340
341 m_outputImage = safeSharedPtr(new Unique<VkImage>(vk::createImage(vk, vkDevice, &outputImageParams)));
342 m_outputImageMemory = safeSharedPtr(memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, **m_outputImage), MemoryRequirement::Any).release());
343 VK_CHECK(vk.bindImageMemory(vkDevice, **m_outputImage, m_outputImageMemory->getMemory(), m_outputImageMemory->getOffset()));
344
345 VkImageViewCreateInfo inputAttachmentViewParams =
346 {
347 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType;
348 DE_NULL, // const void* pNext;
349 0u, // VkImageViewCreateFlags flags;
350 **m_outputImage, // VkImage image;
351 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType;
352 VK_FORMAT_R32G32_UINT, // VkFormat format;
353 componentMappingRGBA, // VkChannelMapping channels;
354 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u } // VkImageSubresourceRange subresourceRange;
355 };
356 m_outputImageView = safeSharedPtr(new Unique<VkImageView>(createImageView(vk, vkDevice, &inputAttachmentViewParams)));
357 }
358
359 {
360 const VkDeviceSize outputBufferSizeBytes = m_renderSize.x() * m_renderSize.y() * tcu::getPixelSize(mapVkFormat(VK_FORMAT_R32G32_UINT));
361 const VkBufferCreateInfo outputBufferParams =
362 {
363 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
364 DE_NULL, // pNext
365 (VkBufferCreateFlags)0u, // flags
366 outputBufferSizeBytes, // size
367 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
368 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
369 1u, // queueFamilyIndexCount
370 &queueFamilyIndex, // pQueueFamilyIndices
371 };
372 m_outputBuffer = safeSharedPtr(new Unique<VkBuffer>(createBuffer(vk, vkDevice, &outputBufferParams)));
373 m_outputBufferMemory = safeSharedPtr(memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, **m_outputBuffer), MemoryRequirement::HostVisible).release());
374 VK_CHECK(vk.bindBufferMemory(vkDevice, **m_outputBuffer, m_outputBufferMemory->getMemory(), m_outputBufferMemory->getOffset()));
375 }
376
377 // Create render pass
378 if (testParams.renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
379 m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice);
380 else
381 m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice);
382
383 std::vector<VkDescriptorImageInfo> descriptorImageInfos;
384 std::vector<VkImageView> framebufferImageViews;
385 descriptorImageInfos.push_back(
386 VkDescriptorImageInfo{
387 DE_NULL, // VkSampleri sampler;
388 **m_outputImageView, // VkImageView imageView;
389 VK_IMAGE_LAYOUT_GENERAL // VkImageLayout imageLayout;
390 }
391 );
392 for (auto& inputImageView : m_inputImageViews)
393 {
394 framebufferImageViews.push_back(**inputImageView);
395 descriptorImageInfos.push_back(
396 VkDescriptorImageInfo{
397 DE_NULL, // VkSampleri sampler;
398 **inputImageView, // VkImageView imageView;
399 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout imageLayout;
400 }
401 );
402 }
403
404 // Create framebuffer
405 {
406 const VkFramebufferCreateInfo framebufferParams =
407 {
408 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
409 DE_NULL, // const void* pNext;
410 0u, // VkFramebufferCreateFlags flags;
411 *m_renderPass, // VkRenderPass renderPass;
412 static_cast<deUint32>(framebufferImageViews.size()), // deUint32 attachmentCount;
413 framebufferImageViews.data(), // const VkImageView* pAttachments;
414 static_cast<deUint32>(m_renderSize.x()), // deUint32 width;
415 static_cast<deUint32>(m_renderSize.y()), // deUint32 height;
416 1u // deUint32 layers;
417 };
418
419 m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
420 }
421
422 // Create pipeline layout
423 {
424 DescriptorSetLayoutBuilder layoutBuilder;
425 // add output image storage
426 layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT);
427 // add input attachments
428 for (deUint32 imageNdx = 0; imageNdx < m_testParams.activeInputAttachmentCount; ++imageNdx)
429 layoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT);
430 m_descriptorSetLayout = layoutBuilder.build(vk, vkDevice);
431
432 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
433 {
434 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
435 DE_NULL, // const void* pNext;
436 0u, // VkPipelineLayoutCreateFlags flags;
437 1u, // deUint32 setLayoutCount;
438 &m_descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts;
439 0u, // deUint32 pushConstantRangeCount;
440 DE_NULL // const VkPushConstantRange* pPushConstantRanges;
441 };
442
443 m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
444 }
445
446 // Update descriptor set
447 {
448 m_descriptorPool = DescriptorPoolBuilder()
449 .addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u)
450 .addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, m_testParams.activeInputAttachmentCount)
451 .build(vk, vkDevice, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
452
453 const VkDescriptorSetAllocateInfo descriptorSetAllocateInfo =
454 {
455 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType
456 DE_NULL, // const void* pNext
457 *m_descriptorPool, // VkDescriptorPool descriptorPool
458 1u, // deUint32 descriptorSetCount
459 &m_descriptorSetLayout.get(), // const VkDescriptorSetLayout* pSetLayouts
460 };
461 m_descriptorSet = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
462
463 DescriptorSetUpdateBuilder builder;
464 builder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfos[0]);
465 for( deUint32 i=1; i<static_cast<deUint32>(descriptorImageInfos.size()); ++i)
466 builder.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(i), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descriptorImageInfos[i]);
467 builder.update(vk, vkDevice);
468 }
469
470 m_vertexShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vertex"), 0);
471 m_fragmentShaderModule = createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("fragment"), 0);
472
473 // Create pipelines
474 {
475 const VkVertexInputBindingDescription vertexInputBindingDescription =
476 {
477 0u, // deUint32 binding;
478 sizeof(Vertex), // deUint32 strideInBytes;
479 VK_VERTEX_INPUT_RATE_VERTEX // VkVertexInputStepRate inputRate;
480 };
481
482 std::vector<VkVertexInputAttributeDescription> vertexInputAttributeDescription =
483 {
484 {
485 0u, // deUint32 location;
486 0u, // deUint32 binding;
487 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
488 0u // deUint32 offset;
489 },
490 {
491 1u, // deUint32 location;
492 0u, // deUint32 binding;
493 VK_FORMAT_R32G32B32A32_SFLOAT, // VkFormat format;
494 DE_OFFSET_OF(Vertex, uv) // deUint32 offset;
495 }
496 };
497
498 const VkPipelineVertexInputStateCreateInfo vertexInputStateParams =
499 {
500 VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
501 DE_NULL, // const void* pNext;
502 0u, // VkPipelineVertexInputStateCreateFlags flags;
503 1u, // deUint32 vertexBindingDescriptionCount;
504 &vertexInputBindingDescription, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
505 static_cast<deUint32>(vertexInputAttributeDescription.size()), // deUint32 vertexAttributeDescriptionCount;
506 vertexInputAttributeDescription.data() // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
507 };
508
509 const std::vector<VkViewport> viewports (1, makeViewport(m_renderSize));
510 const std::vector<VkRect2D> scissors (1, makeRect2D(m_renderSize));
511
512 {
513 m_graphicsPipeline = makeGraphicsPipeline(vk, // const DeviceInterface& vk
514 vkDevice, // const VkDevice device
515 *m_pipelineLayout, // const VkPipelineLayout pipelineLayout
516 *m_vertexShaderModule, // const VkShaderModule vertexShaderModule
517 DE_NULL, // const VkShaderModule tessellationControlModule
518 DE_NULL, // const VkShaderModule tessellationEvalModule
519 DE_NULL, // const VkShaderModule geometryShaderModule
520 *m_fragmentShaderModule, // const VkShaderModule fragmentShaderModule
521 *m_renderPass, // const VkRenderPass renderPass
522 viewports, // const std::vector<VkViewport>& viewports
523 scissors, // const std::vector<VkRect2D>& scissors
524 VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, // const VkPrimitiveTopology topology
525 0u, // const deUint32 subpass
526 0u, // const deUint32 patchControlPoints
527 &vertexInputStateParams); // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
528 }
529 }
530
531 // Create vertex buffer
532 {
533 const VkBufferCreateInfo vertexBufferParams =
534 {
535 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType;
536 DE_NULL, // const void* pNext;
537 0u, // VkBufferCreateFlags flags;
538 (VkDeviceSize)(sizeof(Vertex) * m_vertices.size()), // VkDeviceSize size;
539 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, // VkBufferUsageFlags usage;
540 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
541 1u, // deUint32 queueFamilyIndexCount;
542 &queueFamilyIndex // const deUint32* pQueueFamilyIndices;
543 };
544
545 m_vertexBuffer = createBuffer(vk, vkDevice, &vertexBufferParams);
546 m_vertexBufferAlloc = memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
547 VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
548
549 // Upload vertex data
550 deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex));
551 flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
552 }
553
554 // Create command pool
555 m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
556
557 // Create command buffer
558 if (testParams.renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
559 createCommandBuffer<RenderpassSubpass1>(vk, vkDevice);
560 else
561 createCommandBuffer<RenderpassSubpass2>(vk, vkDevice);
562 }
563
~InputAttachmentSparseFillingTestInstance(void)564 InputAttachmentSparseFillingTestInstance::~InputAttachmentSparseFillingTestInstance (void)
565 {
566 }
567
568 template<typename RenderpassSubpass>
createCommandBuffer(const DeviceInterface & vk,VkDevice vkDevice)569 void InputAttachmentSparseFillingTestInstance::createCommandBuffer (const DeviceInterface& vk,
570 VkDevice vkDevice)
571 {
572 m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
573
574 beginCommandBuffer(vk, *m_cmdBuffer, 0u);
575
576 // clear output image (rg16ui) to (0,0), set image layout to VK_IMAGE_LAYOUT_GENERAL
577 VkImageSubresourceRange range = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
578 {
579 const VkImageMemoryBarrier outputImageInitBarrier =
580 {
581 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
582 DE_NULL, // const void* pNext;
583 0u, // VkAccessFlags srcAccessMask;
584 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAcessMask;
585 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
586 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
587 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
588 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
589 **m_outputImage, // VkImage image;
590 range // VkImageSubresourceRange subresourceRange;
591 };
592 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &outputImageInitBarrier);
593 VkClearValue clearColor = makeClearValueColorU32(0, 0, 0, 0);
594 vk.cmdClearColorImage(*m_cmdBuffer, **m_outputImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
595 VkMemoryBarrier memBarrier =
596 {
597 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
598 DE_NULL, // pNext
599 VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask
600 VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT // dstAccessMask
601 };
602 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
603 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
604 }
605 // clear all input attachments (rgba8) to (1,1,1,1), set image layout to VK_IMAGE_LAYOUT_GENERAL
606 for (auto& inputImage : m_inputImages)
607 {
608 const VkImageMemoryBarrier inputImageInitBarrier =
609 {
610 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
611 DE_NULL, // const void* pNext;
612 0u, // VkAccessFlags srcAccessMask;
613 VK_ACCESS_MEMORY_WRITE_BIT, // VkAccessFlags dstAcessMask;
614 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
615 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout newLayout;
616 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
617 VK_QUEUE_FAMILY_IGNORED, // deUint32 destQueueFamilyIndex;
618 **inputImage, // VkImage image;
619 range // VkImageSubresourceRange subresourceRange;
620 };
621 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &inputImageInitBarrier);
622 VkClearValue clearColor = makeClearValueColorF32(1.0f, 1.0f, 1.0f, 1.0f);
623
624 vk.cmdClearColorImage(*m_cmdBuffer, **inputImage, VK_IMAGE_LAYOUT_GENERAL, &clearColor.color, 1, &range);
625
626 VkMemoryBarrier memBarrier =
627 {
628 VK_STRUCTURE_TYPE_MEMORY_BARRIER, // sType
629 DE_NULL, // pNext
630 VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask
631 VK_ACCESS_INPUT_ATTACHMENT_READ_BIT // dstAccessMask
632 };
633 vk.cmdPipelineBarrier(*m_cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
634 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
635 }
636
637 // Render pass does not use clear values - input images were prepared beforehand
638 const VkRenderPassBeginInfo renderPassBeginInfo =
639 {
640 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // VkStructureType sType;
641 DE_NULL, // const void* pNext;
642 *m_renderPass, // VkRenderPass renderPass;
643 *m_framebuffer, // VkFramebuffer framebuffer;
644 makeRect2D(m_renderSize), // VkRect2D renderArea;
645 0, // uint32_t clearValueCount;
646 DE_NULL // const VkClearValue* pClearValues;
647 };
648 const typename RenderpassSubpass::SubpassBeginInfo subpassBeginInfo(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
649 RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
650
651 const VkDeviceSize vertexBufferOffset = 0;
652 vk.cmdBindPipeline (*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
653 vk.cmdBindDescriptorSets (*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);
654 vk.cmdBindVertexBuffers (*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
655 vk.cmdDraw (*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
656
657 const typename RenderpassSubpass::SubpassEndInfo subpassEndInfo(DE_NULL);
658 RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
659
660 copyImageToBuffer(vk, *m_cmdBuffer, **m_outputImage, **m_outputBuffer, tcu::IVec2(m_renderSize.x(), m_renderSize.y()), VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_GENERAL);
661
662 endCommandBuffer(vk, *m_cmdBuffer);
663 }
664
665 template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vk,VkDevice vkDevice)666 Move<VkRenderPass> InputAttachmentSparseFillingTestInstance::createRenderPass (const DeviceInterface& vk,
667 VkDevice vkDevice)
668 {
669 const VkImageAspectFlags aspectMask = m_testParams.renderingType == RENDERING_TYPE_RENDERPASS_LEGACY ? 0 : VK_IMAGE_ASPECT_COLOR_BIT;
670 std::vector<AttachmentDesc> attachmentDescriptions;
671 std::vector<AttachmentRef> attachmentRefs;
672
673 std::vector<deUint32> attachmentIndices;
674 std::vector<deUint32> descriptorBindings;
675 generateInputAttachmentParams(m_testParams.activeInputAttachmentCount, 2u * m_testParams.activeInputAttachmentCount, attachmentIndices, descriptorBindings);
676
677 for (deUint32 i = 0; i < m_testParams.activeInputAttachmentCount; ++i)
678 {
679 attachmentDescriptions.push_back(
680 AttachmentDesc(
681 DE_NULL, // const void* pNext
682 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
683 VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format
684 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
685 VK_ATTACHMENT_LOAD_OP_LOAD, // VkAttachmentLoadOp loadOp
686 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
687 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
688 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
689 VK_IMAGE_LAYOUT_GENERAL, // VkImageLayout initialLayout
690 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL // VkImageLayout finalLayout
691 )
692 );
693 }
694 for (std::size_t i = 0; i < attachmentIndices.size(); ++i)
695 attachmentRefs.push_back(
696 AttachmentRef(
697 DE_NULL, // const void* pNext
698 attachmentIndices[i], // deUint32 attachment
699 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, // VkImageLayout layout
700 aspectMask // VkImageAspectFlags aspectMask
701 )
702 );
703
704 std::vector<SubpassDesc> subpassDescriptions =
705 {
706 SubpassDesc (
707 DE_NULL,
708 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
709 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
710 0u, // deUint32 viewMask
711 static_cast<deUint32>(attachmentRefs.size()), // deUint32 inputAttachmentCount
712 attachmentRefs.data(), // const VkAttachmentReference* pInputAttachments
713 0u, // deUint32 colorAttachmentCount
714 DE_NULL, // const VkAttachmentReference* pColorAttachments
715 DE_NULL, // const VkAttachmentReference* pResolveAttachments
716 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
717 0u, // deUint32 preserveAttachmentCount
718 DE_NULL // const deUint32* pPreserveAttachments
719 ),
720 };
721 std::vector<SubpassDep> subpassDependencies =
722 {
723 SubpassDep (
724 DE_NULL,
725 0u, // deUint32 srcPass
726 VK_SUBPASS_EXTERNAL, // deUint32 dstPass
727 VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, // VkPipelineStageFlags srcStageMask
728 VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, // VkPipelineStageFlags dstStageMask
729 VK_ACCESS_SHADER_WRITE_BIT, // VkAccessFlags srcAccessMask
730 VK_ACCESS_INDIRECT_COMMAND_READ_BIT, // VkAccessFlags dstAccessMask
731 0, // VkDependencyFlags flags
732 0 // deInt32 viewOffset
733 ),
734 };
735
736 const RenderPassCreateInfo renderPassInfo (
737 DE_NULL, // const void* pNext
738 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
739 static_cast<deUint32>(attachmentDescriptions.size()), // deUint32 attachmentCount
740 attachmentDescriptions.data(), // const VkAttachmentDescription* pAttachments
741 static_cast<deUint32>(subpassDescriptions.size()), // deUint32 subpassCount
742 subpassDescriptions.data(), // const VkSubpassDescription* pSubpasses
743 static_cast<deUint32>(subpassDependencies.size()), // deUint32 dependencyCount
744 subpassDependencies.data(), // const VkSubpassDependency* pDependencies
745 0u, // deUint32 correlatedViewMaskCount
746 DE_NULL // const deUint32* pCorrelatedViewMasks
747 );
748
749 return renderPassInfo.createRenderPass(vk, vkDevice);
750 }
751
iterate(void)752 tcu::TestStatus InputAttachmentSparseFillingTestInstance::iterate (void)
753 {
754 const DeviceInterface& vk = m_context.getDeviceInterface();
755 const VkDevice vkDevice = m_context.getDevice();
756 const VkQueue queue = m_context.getUniversalQueue();
757
758 submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
759
760 return verifyImage();
761 }
762
verifyImage(void)763 tcu::TestStatus InputAttachmentSparseFillingTestInstance::verifyImage (void)
764 {
765 const DeviceInterface& vk = m_context.getDeviceInterface();
766 const VkDevice vkDevice = m_context.getDevice();
767
768 invalidateAlloc(vk, vkDevice, *m_outputBufferMemory);
769 const tcu::ConstPixelBufferAccess resultAccess(mapVkFormat(VK_FORMAT_R32G32_UINT), m_renderSize.x(), m_renderSize.y(), 1u, m_outputBufferMemory->getHostPtr());
770
771 // Log result image
772 m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Result", "Result images")
773 << tcu::TestLog::Image("Rendered", "Rendered image", resultAccess)
774 << tcu::TestLog::EndImageSet;
775
776 // Check the unused image data hasn't changed.
777 for (int y = 0; y < resultAccess.getHeight(); y++)
778 for (int x = 0; x < resultAccess.getWidth(); x++)
779 {
780 tcu::UVec4 color = resultAccess.getPixelUint(x, y);
781 if( color.x() != m_testParams.activeInputAttachmentCount)
782 return tcu::TestStatus::fail("Wrong attachment count");
783 if( color.y() != m_testParams.activeInputAttachmentCount )
784 return tcu::TestStatus::fail("Wrong active attachment count");
785 }
786
787 return tcu::TestStatus::pass("Pass");
788 }
789
790 } // anonymous
791
createRenderPassUnusedAttachmentSparseFillingTests(tcu::TestContext & testCtx,const RenderingType renderingType)792 tcu::TestCaseGroup* createRenderPassUnusedAttachmentSparseFillingTests (tcu::TestContext& testCtx, const RenderingType renderingType)
793 {
794 de::MovePtr<tcu::TestCaseGroup> unusedAttTests (new tcu::TestCaseGroup(testCtx, "attachment_sparse_filling", "Unused attachment tests"));
795
796 const std::vector<deUint32> activeInputAttachmentCount
797 {
798 1u,
799 3u,
800 7u,
801 15u,
802 31u,
803 63u,
804 127u
805 };
806
807 for (std::size_t attachmentNdx = 0; attachmentNdx < activeInputAttachmentCount.size(); ++attachmentNdx)
808 {
809 TestParams testParams{ renderingType, activeInputAttachmentCount[attachmentNdx] };
810 unusedAttTests->addChild(new InputAttachmentSparseFillingTest(testCtx, std::string("input_attachment_") + de::toString(activeInputAttachmentCount[attachmentNdx]), "", testParams));
811 }
812
813 return unusedAttTests.release();
814 }
815
816 } // renderpass
817
818 } // vkt
819