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