1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2023 The Khronos Group Inc.
6 * Copyright (c) 2023 Google Inc.
7 * Copyright (c) 2023 LunarG, Inc.
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 Dynamic vertex attribute tests
24 *//*--------------------------------------------------------------------*/
25
26 #include "vktPipelineDynamicVertexAttributeTests.hpp"
27 #include "vktPipelineClearUtil.hpp"
28 #include "vktPipelineExtendedDynamicStateTests.hpp"
29
30 #include "vktCustomInstancesDevices.hpp"
31 #include "vktTestCase.hpp"
32
33 #include "vkImageUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkCmdUtil.hpp"
37 #include "vkObjUtil.hpp"
38
39 #include "tcuCommandLine.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuTestLog.hpp"
42 #include "tcuTextureUtil.hpp"
43
44 #include <array>
45 #include <set>
46
47 namespace vkt
48 {
49 namespace pipeline
50 {
51
52 namespace
53 {
54
makeVertexInputAttributeDescription2EXT(deUint32 location,deUint32 binding,vk::VkFormat format,deUint32 offset)55 vk::VkVertexInputAttributeDescription2EXT makeVertexInputAttributeDescription2EXT (deUint32 location, deUint32 binding, vk::VkFormat format, deUint32 offset)
56 {
57 vk::VkVertexInputAttributeDescription2EXT desc = vk::initVulkanStructure();
58
59 desc.location = location;
60 desc.binding = binding;
61 desc.format = format;
62 desc.offset = offset;
63
64 return desc;
65 }
66
makeVertexInputBindingDescription2EXT(deUint32 binding,deUint32 stride,vk::VkVertexInputRate inputRate)67 vk::VkVertexInputBindingDescription2EXT makeVertexInputBindingDescription2EXT (deUint32 binding, deUint32 stride, vk::VkVertexInputRate inputRate)
68 {
69 vk::VkVertexInputBindingDescription2EXT desc = vk::initVulkanStructure();
70
71 desc.binding = binding;
72 desc.stride = stride;
73 desc.inputRate = inputRate;
74 desc.divisor = 1u;
75
76 return desc;
77 }
78
makeImageCreateInfo(const tcu::IVec2 & size,const vk::VkFormat format,const vk::VkImageUsageFlags usage)79 vk::VkImageCreateInfo makeImageCreateInfo (const tcu::IVec2& size, const vk::VkFormat format, const vk::VkImageUsageFlags usage)
80 {
81 const vk::VkImageCreateInfo imageParams =
82 {
83 vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType;
84 DE_NULL, // const void* pNext;
85 (vk::VkImageCreateFlags)0u, // VkImageCreateFlags flags;
86 vk::VK_IMAGE_TYPE_2D, // VkImageType imageType;
87 format, // VkFormat format;
88 vk::makeExtent3D(size.x(), size.y(), 1), // VkExtent3D extent;
89 1u, // deUint32 mipLevels;
90 1u, // deUint32 arrayLayers;
91 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples;
92 vk::VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling;
93 usage, // VkImageUsageFlags usage;
94 vk::VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode;
95 0u, // deUint32 queueFamilyIndexCount;
96 DE_NULL, // const deUint32* pQueueFamilyIndices;
97 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout;
98 };
99
100 return imageParams;
101 }
102
removeExtensions(const std::vector<std::string> & a,const std::vector<const char * > & b)103 static std::vector <std::string> removeExtensions (const std::vector<std::string>& a, const std::vector<const char*>& b)
104 {
105 std::vector<std::string> res;
106 std::set<std::string> removeExts(b.begin(), b.end());
107
108 for (std::vector<std::string>::const_iterator aIter = a.begin(); aIter != a.end(); ++aIter)
109 {
110 if (!de::contains(removeExts, *aIter))
111 res.push_back(*aIter);
112 }
113
114 return res;
115 }
116
createDynamicVertexStateDevice(Context & context,const deUint32 testQueueFamilyIndex,const vk::PipelineConstructionType pipelineConstructionType)117 vk::Move<vk::VkDevice> createDynamicVertexStateDevice (Context& context, const deUint32 testQueueFamilyIndex, const vk::PipelineConstructionType pipelineConstructionType)
118 {
119 DE_UNREF(pipelineConstructionType);
120
121 void* pNext = DE_NULL;
122
123 #ifndef CTS_USES_VULKANSC
124 vk::VkPhysicalDeviceGraphicsPipelineLibraryFeaturesEXT graphicsPipelineFeatures
125 {
126 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_FEATURES_EXT, // VkStructureType sType;
127 pNext, // void* pNext;
128 VK_TRUE, // VkBool32 graphicsPipelineLibrary;
129 };
130
131 if (vk::isConstructionTypeLibrary(pipelineConstructionType))
132 pNext = &graphicsPipelineFeatures;
133 vk::VkPhysicalDeviceDynamicRenderingFeaturesKHR dynamicRenderingFeatures
134 {
135 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DYNAMIC_RENDERING_FEATURES_KHR, // VkStructureType sType;
136 pNext, // void* pNext;
137 VK_TRUE, // VkBool32 dynamicRendering;
138 };
139 vk::VkPhysicalDeviceShaderObjectFeaturesEXT shaderObjectFeatures
140 {
141 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT, // VkStructureType sType;
142 &dynamicRenderingFeatures, // void* pNext;
143 VK_TRUE, // VkBool32 shaderObject;
144 };
145
146 if (vk::isConstructionTypeShaderObject(pipelineConstructionType))
147 pNext = &shaderObjectFeatures;
148 #endif
149
150 vk::VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT dynamicVertexState
151 {
152 vk::VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT, // VkStructureType sType;
153 pNext, // void* pNext;
154 VK_TRUE, // VkBool32 vertexInputDynamicState;
155 };
156
157 vk::VkPhysicalDeviceFeatures2 physDeviceFeats2 = context.getDeviceFeatures2();
158
159 physDeviceFeats2.features = context.getDeviceFeatures();
160 physDeviceFeats2.pNext = &dynamicVertexState;
161
162 const float queuePriority = 1.0f;
163
164 const vk::VkDeviceQueueCreateInfo queueParams =
165 {
166 vk::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType;
167 DE_NULL, // const void* pNext;
168 0u, // VkDeviceQueueCreateFlags flags;
169 testQueueFamilyIndex, // deUint32 queueFamilyIndex;
170 1u, // deUint32 queueCount;
171 &queuePriority // const float* pQueuePriorities;
172 };
173
174 std::vector<const char*> extensionPtrs;
175 std::vector<const char*> coreExtensions;
176
177 vk::getCoreDeviceExtensions(context.getUsedApiVersion(), coreExtensions);
178
179 std::vector<std::string> nonCoreExtensions (removeExtensions(context.getDeviceExtensions(), coreExtensions));
180
181 extensionPtrs.resize(nonCoreExtensions.size());
182
183 for (size_t ndx = 0; ndx < nonCoreExtensions.size(); ++ndx)
184 extensionPtrs[ndx] = nonCoreExtensions[ndx].c_str();
185
186 const vk::VkDeviceCreateInfo deviceInfo =
187 {
188 vk::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // VkStructureType sType;
189 &physDeviceFeats2, // const void* pNext;
190 0u, // VkDeviceCreateFlags flags;
191 1u, // deUint32 queueCreateInfoCount;
192 &queueParams, // const VkDeviceQueueCreateInfo* pQueueCreateInfos;
193 0u, // deUint32 enabledLayerCount;
194 DE_NULL, // const char* const* ppEnabledLayerNames;
195 (deUint32)extensionPtrs.size(), // deUint32 enabledExtensionCount;
196 extensionPtrs.data(), // const char* const* ppEnabledExtensionNames;
197 NULL // const VkPhysicalDeviceFeatures* pEnabledFeatures;
198 };
199
200 return createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(), context.getPlatformInterface(),
201 context.getInstance(), context.getInstanceInterface(), context.getPhysicalDevice(), &deviceInfo);
202 }
203
204 class NonSequentialInstance : public TestInstance
205 {
206 public:
NonSequentialInstance(Context & context,const vk::PipelineConstructionType pipelineConstructionType,const deUint32 numInstances,const std::vector<deUint32> attributeLocations)207 NonSequentialInstance (Context& context,
208 const vk::PipelineConstructionType pipelineConstructionType,
209 const deUint32 numInstances,
210 const std::vector<deUint32> attributeLocations)
211 : TestInstance (context)
212 , m_pipelineConstructionType (pipelineConstructionType)
213 , m_numInstances (numInstances)
214 , m_attributeLocations (attributeLocations)
215 {}
216
~NonSequentialInstance()217 ~NonSequentialInstance ()
218 {}
219
220 virtual tcu::TestStatus iterate (void);
221
222 private:
223 struct VertexInfo
224 {
225 tcu::Vec4 position;
226 tcu::Vec4 color;
227 };
228
229 const vk::PipelineConstructionType m_pipelineConstructionType;
230 const deUint32 m_numInstances;
231 const std::vector<deUint32> m_attributeLocations;
232 };
233
iterate(void)234 tcu::TestStatus NonSequentialInstance::iterate (void)
235 {
236 tcu::TestLog& log = m_context.getTestContext().getLog();
237 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
238 const vk::PlatformInterface& vkp = m_context.getPlatformInterface();
239 const vk::VkInstance vki = m_context.getInstance();
240 const vk::InstanceInterface& instanceInterface = m_context.getInstanceInterface();
241 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
242 const vk::VkPhysicalDevice physicalDevice = m_context.getPhysicalDevice();
243 const vk::Move<vk::VkDevice> device = createDynamicVertexStateDevice(m_context, queueFamilyIndex, m_pipelineConstructionType);
244 vk::SimpleAllocator allocator (vk, *device, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
245 const vk::DeviceDriver deviceDriver (vkp, vki, *device, m_context.getUsedApiVersion());
246 const vk::VkQueue queue = getDeviceQueue(deviceDriver, *device, queueFamilyIndex, 0u);
247 const auto& deviceExtensions = m_context.getDeviceExtensions();
248
249 // Create shaders
250 const std::array<vk::ShaderWrapper, 2> vertexShaderModules =
251 {
252 vk::ShaderWrapper(vk, *device, m_context.getBinaryCollection().get("vert_0")),
253 vk::ShaderWrapper(vk, *device, m_context.getBinaryCollection().get("vert_1"))
254 };
255
256 const vk::ShaderWrapper fragmentShaderModule = vk::ShaderWrapper(vk, *device, m_context.getBinaryCollection().get("frag"));
257
258 const deUint32 vertexBufferBindIndex = 0u;
259
260 // Vertex input state and binding
261 const vk::VkVertexInputBindingDescription2EXT bindingDescription2EXT = makeVertexInputBindingDescription2EXT(vertexBufferBindIndex, sizeof(VertexInfo), vk::VK_VERTEX_INPUT_RATE_VERTEX);
262
263 const std::array<vk::VkVertexInputAttributeDescription2EXT, 2> vertexInputAttributeDesc2EXTGreens
264 {
265 makeVertexInputAttributeDescription2EXT(0, vertexBufferBindIndex, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u),
266 makeVertexInputAttributeDescription2EXT(m_attributeLocations[0], vertexBufferBindIndex, vk::VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float)) * 4u)
267 };
268
269 const std::array<vk::VkVertexInputAttributeDescription2EXT, 2> vertexInputAttributeDesc2EXT2Reds
270 {
271 makeVertexInputAttributeDescription2EXT(0, vertexBufferBindIndex, vk::VK_FORMAT_R32G32B32A32_SFLOAT, 0u),
272 makeVertexInputAttributeDescription2EXT(m_attributeLocations[1], vertexBufferBindIndex, vk::VK_FORMAT_R32G32B32A32_SFLOAT, deUint32(sizeof(float)) * 4u)
273 };
274
275 const vk::VkPipelineVertexInputStateCreateInfo vertexInputStateCreateInfo
276 {
277 vk::VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, // VkStructureType sType;
278 DE_NULL, // const void* pNext;
279 (vk::VkPipelineVertexInputStateCreateFlags)0u, // VkPipelineVertexInputStateCreateFlags flags;
280 0u, // uint32_t vertexBindingDescriptionCount;
281 DE_NULL, // const VkVertexInputBindingDescription* pVertexBindingDescriptions;
282 0u, // uint32_t vertexAttributeDescriptionCount;
283 DE_NULL // const VkVertexInputAttributeDescription* pVertexAttributeDescriptions;
284 };
285
286 vk::Move<vk::VkImage> colorImage = (makeImage(vk, *device, makeImageCreateInfo(tcu::IVec2(32, 32), vk::VK_FORMAT_R8G8B8A8_UNORM, vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT)));
287
288 // Allocate and bind color image memory
289 const vk::VkImageSubresourceRange colorSubresourceRange = vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
290 const de::UniquePtr<vk::Allocation> colorImageAlloc (bindImage(vk,*device, allocator, *colorImage, vk::MemoryRequirement::Any));
291 vk::Move<vk::VkImageView> colorImageView = (makeImageView(vk,*device, *colorImage, vk::VK_IMAGE_VIEW_TYPE_2D, vk::VK_FORMAT_R8G8B8A8_UNORM, colorSubresourceRange));
292
293 // Create renderpass
294 const vk::VkAttachmentDescription attachmentDescription =
295 {
296 (vk::VkAttachmentDescriptionFlags)0u, // VkAttachmentDescriptionFlags flags
297 vk::VK_FORMAT_R8G8B8A8_UNORM, // VkFormat format
298 vk::VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
299 vk::VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
300 vk::VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
301 vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
302 vk::VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
303 vk::VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout
304 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL// VkImageLayout finalLayout
305 };
306
307 const vk::VkAttachmentReference attachmentReference =
308 {
309 0u, // deUint32 attachment
310 vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout
311 };
312
313 const vk::VkSubpassDescription subpassDescription =
314 {
315 (vk::VkSubpassDescriptionFlags)0u, // VkSubpassDescriptionFlags flags
316 vk::VK_PIPELINE_BIND_POINT_GRAPHICS,// VkPipelineBindPoint pipelineBindPoint
317 0u, // deUint32 inputAttachmentCount
318 DE_NULL, // const VkAttachmentReference* pInputAttachments
319 1u, // deUint32 colorAttachmentCount
320 &attachmentReference, // const VkAttachmentReference* pColorAttachments
321 DE_NULL, // const VkAttachmentReference* pResolveAttachments
322 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
323 0u, // deUint32 preserveAttachmentCount
324 DE_NULL // const deUint32* pPreserveAttachments
325 };
326
327 const vk::VkRenderPassCreateInfo renderPassInfo =
328 {
329 vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureTypei sType
330 DE_NULL, // const void* pNext
331 (vk::VkRenderPassCreateFlags)0u, // VkRenderPassCreateFlags flags
332 1u, // deUint32 attachmentCount
333 &attachmentDescription, // const VkAttachmentDescription* pAttachments
334 1u, // deUint32 subpassCount
335 &subpassDescription, // const VkSubpassDescription* pSubpasses
336 0u, // deUint32 dependencyCount
337 DE_NULL // const VkSubpassDependency* pDependencies
338 };
339
340 vk::RenderPassWrapper renderPass = vk::RenderPassWrapper(m_pipelineConstructionType, vk, *device, &renderPassInfo);
341
342 // Create framebuffer
343 const vk::VkImageView attachmentBindInfos[] =
344 {
345 *colorImageView
346 };
347
348 const vk::VkFramebufferCreateInfo framebufferCreateInfo =
349 {
350 vk::VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType;
351 DE_NULL, // const void* pNext;
352 vk::VkFramebufferCreateFlags(0), // VkFramebufferCreateFlags flags;
353 *renderPass, // VkRenderPass renderPass;
354 1u, // deUint32 attachmentCount;
355 attachmentBindInfos, // const VkImageView* pAttachments;
356 32u, // deUint32 width;
357 32u, // deUint32 height;
358 1u // deUint32 layers;
359 };
360
361 renderPass.createFramebuffer(vk, *device, &framebufferCreateInfo, { *colorImage });
362
363 std::array<vk::VkDynamicState, 1> dynamicStates
364 {
365 vk::VK_DYNAMIC_STATE_VERTEX_INPUT_EXT,
366 };
367
368 vk::VkPipelineDynamicStateCreateInfo pipelineDynamicStateNfo
369 {
370 vk::VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, // VkStructureType sType;
371 DE_NULL, // const void* pNext;
372 (vk::VkPipelineDynamicStateCreateFlags)0u, // VkPipelineDynamicStateCreateFlags flags;
373 static_cast<deUint32>(dynamicStates.size()), // uint32_t dynamicStateCount;
374 dynamicStates.data() // const VkDynamicState* pDynamicStates;
375 };
376
377 // Create pipeline layout
378 const vk::VkPipelineLayoutCreateInfo pipelineLayoutInfo =
379 {
380 vk::VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // VkStructureType sType;
381 DE_NULL, // const void* pNext;
382 0u, // VkPipelineLayoutCreateFlags flags;
383 0u, // deUint32 descriptorSetCount;
384 DE_NULL, // const VkDescriptorSetLayout* pSetLayouts;
385 0u, // deUint32 pushConstantRangeCount;
386 DE_NULL // const VkPushDescriptorRange* pPushDescriptorRanges;
387 };
388
389 vk::PipelineLayoutWrapper pipelineLayout (m_pipelineConstructionType, vk, *device, &pipelineLayoutInfo);
390
391 // Create graphics pipeline
392 vk::GraphicsPipelineWrapper graphicsPipelines[2] { { instanceInterface, vk, physicalDevice, *device, deviceExtensions, m_pipelineConstructionType}, { instanceInterface, vk, physicalDevice, *device, deviceExtensions, m_pipelineConstructionType} };
393
394 const vk::VkExtent2D extent = {32, 32};
395 const std::vector<vk::VkViewport> viewports (1, vk::makeViewport(extent));
396 const std::vector<vk::VkRect2D> scissors (1, vk::makeRect2D(extent));
397
398 for (deUint32 i = 0u; i < static_cast<deUint32>(vertexShaderModules.size()); ++i)
399 {
400 graphicsPipelines[i].setDefaultDepthStencilState()
401 .setDefaultColorBlendState()
402 .setDynamicState(&pipelineDynamicStateNfo)
403 .setDefaultMultisampleState()
404 .setDefaultTopology(vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST)
405 .setDefaultRasterizationState()
406 .setupVertexInputState(&vertexInputStateCreateInfo)
407 .setupPreRasterizationShaderState(viewports,
408 scissors,
409 pipelineLayout,
410 *renderPass,
411 0u,
412 vertexShaderModules[i])
413 .setupFragmentShaderState(pipelineLayout,
414 *renderPass,
415 0u,
416 fragmentShaderModule,
417 DE_NULL,
418 DE_NULL)
419 .setupFragmentOutputState(*renderPass)
420 .setMonolithicPipelineLayout(pipelineLayout)
421 .buildPipeline();
422 }
423
424 // Create vertex buffer
425 const deUint32 numVertices = 6;
426 const vk::VkDeviceSize vertexBufferSizeBytes = 256;
427
428 const std::array<vk::Move<vk::VkBuffer>, 2> vertexBuffers =
429 {
430 (makeBuffer(vk,*device, vertexBufferSizeBytes, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)),
431 (makeBuffer(vk,*device, vertexBufferSizeBytes, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT))
432 };
433
434 const std::array<de::MovePtr<vk::Allocation>, 2> vertexBufferAllocs =
435 {
436 (bindBuffer(vk,*device, allocator, *vertexBuffers[0], vk::MemoryRequirement::HostVisible)),
437 (bindBuffer(vk,*device, allocator, *vertexBuffers[1], vk::MemoryRequirement::HostVisible))
438 };
439
440 const deUint32 instanceSize = (deUint32)sqrt(m_numInstances);
441 const float posIncrement = 1.0f / (float)m_numInstances * (float)instanceSize;
442
443 for (deUint32 i = 0u; i < static_cast<deUint32>(vertexShaderModules.size()); ++i)
444 {
445 tcu::Vec4 vertexColor = (i == 0u ? tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f) : tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f));
446 VertexInfo* const pVertices = static_cast<VertexInfo*>(vertexBufferAllocs[i]->getHostPtr());
447
448 pVertices[0] = { tcu::Vec4( posIncrement, -posIncrement, 0.0f, 1.0f), vertexColor };
449 pVertices[1] = { tcu::Vec4(-posIncrement, -posIncrement, 0.0f, 1.0f), vertexColor };
450 pVertices[2] = { tcu::Vec4(-posIncrement, posIncrement, 0.0f, 1.0f), vertexColor };
451 pVertices[3] = { tcu::Vec4(-posIncrement, posIncrement, 1.0f, 1.0f), vertexColor };
452 pVertices[4] = { tcu::Vec4( posIncrement, posIncrement, 1.0f, 1.0f), vertexColor };
453 pVertices[5] = { tcu::Vec4( posIncrement, -posIncrement, 1.0f, 1.0f), vertexColor };
454
455 flushAlloc(vk,*device, *vertexBufferAllocs[i]);
456 }
457
458 // Command buffer
459 const vk::Unique<vk::VkCommandPool> cmdPool (createCommandPool(vk, *device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
460 const vk::Unique<vk::VkCommandBuffer> cmdBuffer (allocateCommandBuffer(vk,*device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));
461
462 const vk::VkDeviceSize vertexBufferOffset = 0u;
463
464 // Render result buffer
465 const vk::VkDeviceSize colorBufferSizeBytes = static_cast<vk::VkDeviceSize>(tcu::getPixelSize(mapVkFormat(vk::VK_FORMAT_R8G8B8A8_UNORM)) * 32 * 32);
466 const vk::Unique<vk::VkBuffer> colorBuffer (makeBuffer(vk,*device, colorBufferSizeBytes, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT));
467 const de::UniquePtr<vk::Allocation> colorBufferAlloc (bindBuffer(vk,*device, allocator, *colorBuffer, vk::MemoryRequirement::HostVisible));
468
469 const vk::VkClearValue clearColorValue = defaultClearValue(vk::VK_FORMAT_R8G8B8A8_UNORM);
470
471 beginCommandBuffer(vk, *cmdBuffer);
472
473 renderPass.begin(vk, *cmdBuffer, vk::makeRect2D(0, 0, 32u, 32u), clearColorValue);
474
475 graphicsPipelines[0].bind(*cmdBuffer);
476 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffers[0].get(), &vertexBufferOffset);
477 vk.cmdSetVertexInputEXT(*cmdBuffer, 1u, &bindingDescription2EXT, static_cast<deUint32>(vertexInputAttributeDesc2EXTGreens.size()), vertexInputAttributeDesc2EXTGreens.data());
478 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
479
480 graphicsPipelines[1].bind(*cmdBuffer);
481 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffers[1].get(), &vertexBufferOffset);
482 vk.cmdSetVertexInputEXT(*cmdBuffer, 1u, &bindingDescription2EXT, static_cast<deUint32>(vertexInputAttributeDesc2EXT2Reds.size()), vertexInputAttributeDesc2EXT2Reds.data());
483 vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
484
485 renderPass.end(vk, *cmdBuffer);
486 copyImageToBuffer(vk, *cmdBuffer, *colorImage, *colorBuffer, tcu::IVec2(32, 32), vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT);
487
488 endCommandBuffer(vk, *cmdBuffer);
489
490 submitCommandsAndWait(vk,*device, queue, *cmdBuffer);
491
492 // Check result image
493 {
494 tcu::TextureLevel referenceTexture (mapVkFormat(vk::VK_FORMAT_R8G8B8A8_UNORM), 32, 32);
495 const tcu::PixelBufferAccess referenceAccess = referenceTexture.getAccess();
496 const int segmentSize = static_cast<deInt32>(32u / instanceSize);
497 const int segmentLoc = (32 - segmentSize) / 2;
498
499 tcu::clear(referenceTexture.getAccess(), clearColorValue.color.float32);
500
501 // Create reference image
502 for (int y = 0; y < segmentSize; ++y)
503 {
504 for (int x = 0; x < segmentSize; ++x)
505 {
506 // While running test for all offsets, we create a nice gradient-like color for the pixels.
507 referenceAccess.setPixel(tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f), segmentLoc + x, segmentLoc + y);
508 }
509 }
510
511 invalidateAlloc(vk,*device, *colorBufferAlloc);
512
513 const tcu::ConstPixelBufferAccess resultPixelAccess(mapVkFormat(vk::VK_FORMAT_R8G8B8A8_UNORM), (int)extent.width, (int)extent.height, 1, colorBufferAlloc->getHostPtr());
514
515 if (!tcu::floatThresholdCompare(log, "color", "Image compare", referenceAccess, resultPixelAccess, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT))
516 return tcu::TestStatus::fail("Rendered image is not correct");
517 }
518
519 return tcu::TestStatus::pass("Success");
520 }
521
522 class NonSequentialCase : public vkt::TestCase
523 {
524 public:
NonSequentialCase(tcu::TestContext & testContext,const std::string & name,const vk::PipelineConstructionType pipelineConstructionType,const deUint32 numInstances,const std::vector<deUint32> attributeLocations)525 NonSequentialCase (tcu::TestContext& testContext,
526 const std::string& name,
527 const vk::PipelineConstructionType pipelineConstructionType,
528 const deUint32 numInstances,
529 const std::vector<deUint32> attributeLocations)
530 : vkt::TestCase (testContext, name)
531 , m_pipelineConstructionType (pipelineConstructionType)
532 , m_numInstances (numInstances)
533 , m_attributeLocations (attributeLocations)
534 {}
535
~NonSequentialCase(void)536 ~NonSequentialCase (void)
537 {}
538
539 virtual void checkSupport (Context& context) const override;
540 virtual void initPrograms (vk::SourceCollections& sourceCollections) const override;
541 virtual TestInstance *createInstance (Context& context) const override;
542
543 private:
544 const vk::PipelineConstructionType m_pipelineConstructionType;
545 const deUint32 m_numInstances;
546 const std::vector<deUint32> m_attributeLocations;
547 };
548
checkSupport(Context & context) const549 void NonSequentialCase::checkSupport (Context& context) const
550 {
551 const vk::InstanceInterface& vki = context.getInstanceInterface();
552 const vk::VkPhysicalDevice physDevice = context.getPhysicalDevice();
553
554 std::array<std::string, 3> extensions =
555 {
556 "VK_EXT_extended_dynamic_state",
557 "VK_EXT_vertex_input_dynamic_state",
558 "VK_EXT_extended_dynamic_state2"
559 };
560
561 // Check extension support.
562 for (const auto& extension : extensions)
563 context.requireDeviceFunctionality(extension);
564
565 vk::checkPipelineConstructionRequirements(vki, physDevice, m_pipelineConstructionType);
566 }
567
initPrograms(vk::SourceCollections & sourceCollections) const568 void NonSequentialCase::initPrograms (vk::SourceCollections& sourceCollections) const
569 {
570 // Vertex
571 {
572 for (size_t i = 0; i < m_attributeLocations.size(); ++i)
573 {
574 std::ostringstream src;
575
576 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
577 << "\n"
578 << "layout(location = 0) in vec4 inPosition;\n"
579 << "layout(location = " << m_attributeLocations[i] << ") in vec4 inColor;\n"
580 << "layout(location = 0) out vec4 outColor;\n"
581 << "\n"
582 << "void main (void)\n"
583 << "{\n"
584 << " gl_Position = inPosition;\n"
585 << " outColor = inColor;\n"
586 << "}\n";
587
588 sourceCollections.glslSources.add("vert_" + std::to_string(i)) << glu::VertexSource(src.str());
589 }
590 }
591
592 // Fragment
593 {
594 std::ostringstream src;
595
596 src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
597 << "\n"
598 << "layout(location = 0) in vec4 inColor;\n"
599 << "layout(location = 0) out vec4 outColor;\n"
600 << "\n"
601 << "void main (void)\n"
602 << "{\n"
603 << " outColor = inColor;\n"
604 << "}\n";
605
606 sourceCollections.glslSources.add("frag") << glu::FragmentSource(src.str());
607 }
608 }
609
createInstance(Context & context) const610 TestInstance* NonSequentialCase::createInstance (Context& context) const
611 {
612 return new NonSequentialInstance(context, m_pipelineConstructionType, m_numInstances, m_attributeLocations);
613 }
614
615 } // anonymous
616
createDynamicVertexAttributeTests(tcu::TestContext & testCtx,vk::PipelineConstructionType pipelineConstructionType)617 tcu::TestCaseGroup* createDynamicVertexAttributeTests (tcu::TestContext& testCtx, vk::PipelineConstructionType pipelineConstructionType)
618 {
619 de::MovePtr<tcu::TestCaseGroup> nonSequentialTestsGroup(new tcu::TestCaseGroup(testCtx, "dynamic_vertex_attribute"));
620
621 nonSequentialTestsGroup->addChild(new NonSequentialCase(testCtx, "nonsequential", pipelineConstructionType, 16u, { 1u, 7u }));
622
623 return nonSequentialTestsGroup.release();
624 }
625
626 } // pipeline
627 } // vkt
628