1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 The Khronos Group Inc.
6 * Copyright (c) 2017 Nvidia Corporation
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 *
20 *//*!
21 * \file
22 * \brief Device Group Tests
23 *//*--------------------------------------------------------------------*/
24
25 #include "vktDeviceGroupTests.hpp"
26 #include "vktCustomInstancesDevices.hpp"
27
28 #include "vkDefs.hpp"
29 #include "vkDeviceUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkPlatform.hpp"
33 #include "vkPrograms.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkRef.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkStrUtil.hpp"
38 #include "vkTypeUtil.hpp"
39 #include "vkCmdUtil.hpp"
40 #include "vkObjUtil.hpp"
41 #include "vkSafetyCriticalUtil.hpp"
42 #include "vktTestCase.hpp"
43 #include "vktTestCaseUtil.hpp"
44 #include "vktTestGroupUtil.hpp"
45
46 #include "tcuDefs.hpp"
47 #include "tcuFormatUtil.hpp"
48 #include "tcuImageCompare.hpp"
49 #include "tcuResource.hpp"
50 #include "tcuTestCase.hpp"
51 #include "tcuTestLog.hpp"
52 #include "tcuCommandLine.hpp"
53 #include "tcuTextureUtil.hpp"
54 #include "tcuImageIO.hpp"
55
56 #include "rrRenderer.hpp"
57
58 #include <sstream>
59
60 namespace vkt
61 {
62 namespace DeviceGroup
63 {
64 namespace
65 {
66
67 using namespace vk;
68 using std::string;
69 using std::vector;
70 using tcu::TestLog;
71 using de::UniquePtr;
72
73 //Device group test modes
74 enum TestModeType
75 {
76 TEST_MODE_SFR = 1 << 0, //!< Split frame rendering
77 TEST_MODE_AFR = 1 << 1, //!< Alternate frame rendering
78 TEST_MODE_HOSTMEMORY = 1 << 2, //!< Use host memory for rendertarget
79 TEST_MODE_DEDICATED = 1 << 3, //!< Use dedicated allocations
80 TEST_MODE_PEER_FETCH = 1 << 4, //!< Peer vertex attributes from peer memory
81 TEST_MODE_TESSELLATION = 1 << 5, //!< Generate a tessellated sphere instead of triangle
82 TEST_MODE_LINEFILL = 1 << 6, //!< Draw polygon edges as line segments
83 };
84
85 class RefVertexShader : public rr::VertexShader
86 {
87 public:
RefVertexShader(void)88 RefVertexShader (void)
89 : rr::VertexShader(1, 0)
90 {
91 m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
92 }
~RefVertexShader(void)93 virtual ~RefVertexShader(void) {}
94
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const95 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
96 {
97 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
98 {
99 packets[packetNdx]->position = rr::readVertexAttribFloat(inputs[0],
100 packets[packetNdx]->instanceNdx,
101 packets[packetNdx]->vertexNdx);
102 }
103 }
104 };
105
106 class RefFragmentShader : public rr::FragmentShader
107 {
108 public:
RefFragmentShader(void)109 RefFragmentShader (void)
110 : rr::FragmentShader(0, 1)
111 {
112 m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
113 }
114
~RefFragmentShader(void)115 virtual ~RefFragmentShader(void) {}
116
shadeFragments(rr::FragmentPacket *,const int numPackets,const rr::FragmentShadingContext & context) const117 void shadeFragments (rr::FragmentPacket*, const int numPackets, const rr::FragmentShadingContext& context) const
118 {
119 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
120 {
121 for (int fragNdx = 0; fragNdx < rr::NUM_FRAGMENTS_PER_PACKET; ++fragNdx)
122 {
123 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f));
124 }
125 }
126 }
127 };
128
renderReferenceTriangle(const tcu::PixelBufferAccess & dst,const tcu::Vec4 (& vertices)[3],const int subpixelBits)129 void renderReferenceTriangle (const tcu::PixelBufferAccess& dst, const tcu::Vec4(&vertices)[3], const int subpixelBits)
130 {
131 const RefVertexShader vertShader;
132 const RefFragmentShader fragShader;
133 const rr::Program program(&vertShader, &fragShader);
134 const rr::MultisamplePixelBufferAccess colorBuffer = rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(dst);
135 const rr::RenderTarget renderTarget(colorBuffer);
136 const rr::RenderState renderState((rr::ViewportState(colorBuffer)), subpixelBits);
137 const rr::Renderer renderer;
138 const rr::VertexAttrib vertexAttribs[] =
139 {
140 rr::VertexAttrib(rr::VERTEXATTRIBTYPE_FLOAT, 4, sizeof(tcu::Vec4), 0, vertices[0].getPtr())
141 };
142 renderer.draw(rr::DrawCommand(renderState,
143 renderTarget,
144 program,
145 DE_LENGTH_OF_ARRAY(vertexAttribs),
146 &vertexAttribs[0],
147 rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, DE_LENGTH_OF_ARRAY(vertices), 0)));
148 }
149
150 class DeviceGroupTestInstance : public TestInstance
151 {
152 public:
153 DeviceGroupTestInstance(Context& context, deUint32 mode);
154 ~DeviceGroupTestInstance(void);
155 private:
156 void init (void);
157 deUint32 getMemoryIndex (deUint32 memoryTypeBits, deUint32 memoryPropertyFlag);
158 bool isPeerFetchAllowed (deUint32 memoryTypeIndex, deUint32 firstdeviceID, deUint32 seconddeviceID);
159 void submitBufferAndWaitForIdle (const vk::DeviceInterface& vk, VkCommandBuffer cmdBuf, deUint32 deviceMask);
160 virtual tcu::TestStatus iterate (void);
161
162 std::shared_ptr<CustomInstanceWrapper> m_instanceWrapper;
163 Move<VkDevice> m_deviceGroup;
164 #ifndef CTS_USES_VULKANSC
165 de::MovePtr<vk::DeviceDriver> m_deviceDriver;
166 #else
167 de::MovePtr<vk::DeviceDriverSC, vk::DeinitDeviceDeleter> m_deviceDriver;
168 #endif // CTS_USES_VULKANSC
169 deUint32 m_physicalDeviceCount;
170 VkQueue m_deviceGroupQueue;
171 vector<VkPhysicalDevice> m_physicalDevices;
172
173 deUint32 m_testMode;
174 bool m_useHostMemory;
175 bool m_useDedicated;
176 bool m_usePeerFetch;
177 bool m_subsetAllocation;
178 bool m_fillModeNonSolid;
179 bool m_drawTessellatedSphere;
180 };
181
DeviceGroupTestInstance(Context & context,const deUint32 mode)182 DeviceGroupTestInstance::DeviceGroupTestInstance (Context& context, const deUint32 mode)
183 : TestInstance (context)
184 , m_instanceWrapper (new CustomInstanceWrapper(context))
185 , m_physicalDeviceCount (0)
186 , m_deviceGroupQueue (DE_NULL)
187 , m_testMode (mode)
188 , m_useHostMemory (m_testMode & TEST_MODE_HOSTMEMORY)
189 , m_useDedicated (m_testMode & TEST_MODE_DEDICATED)
190 , m_usePeerFetch (m_testMode & TEST_MODE_PEER_FETCH)
191 , m_subsetAllocation (true)
192 , m_fillModeNonSolid (m_testMode & TEST_MODE_LINEFILL)
193 , m_drawTessellatedSphere (m_testMode & TEST_MODE_TESSELLATION)
194 {
195 init();
196 }
197
~DeviceGroupTestInstance()198 DeviceGroupTestInstance::~DeviceGroupTestInstance()
199 {
200 }
201
getMemoryIndex(const deUint32 memoryTypeBits,const deUint32 memoryPropertyFlag)202 deUint32 DeviceGroupTestInstance::getMemoryIndex (const deUint32 memoryTypeBits, const deUint32 memoryPropertyFlag)
203 {
204 const VkPhysicalDeviceMemoryProperties deviceMemProps = getPhysicalDeviceMemoryProperties(m_instanceWrapper->instance.getDriver(), m_context.getPhysicalDevice());
205 for (deUint32 memoryTypeNdx = 0; memoryTypeNdx < deviceMemProps.memoryTypeCount; memoryTypeNdx++)
206 {
207 if ((memoryTypeBits & (1u << memoryTypeNdx)) != 0 &&
208 (deviceMemProps.memoryTypes[memoryTypeNdx].propertyFlags & memoryPropertyFlag) == memoryPropertyFlag)
209 return memoryTypeNdx;
210 }
211 TCU_THROW(NotSupportedError, "No compatible memory type found");
212 }
213
isPeerFetchAllowed(deUint32 memoryTypeIndex,deUint32 firstdeviceID,deUint32 seconddeviceID)214 bool DeviceGroupTestInstance::isPeerFetchAllowed (deUint32 memoryTypeIndex, deUint32 firstdeviceID, deUint32 seconddeviceID)
215 {
216 VkPeerMemoryFeatureFlags peerMemFeatures1;
217 VkPeerMemoryFeatureFlags peerMemFeatures2;
218 const DeviceDriver vk (m_context.getPlatformInterface(), m_instanceWrapper->instance, *m_deviceGroup);
219 const VkPhysicalDeviceMemoryProperties deviceMemProps1 = getPhysicalDeviceMemoryProperties(m_instanceWrapper->instance.getDriver(), m_physicalDevices[firstdeviceID]);
220 const VkPhysicalDeviceMemoryProperties deviceMemProps2 = getPhysicalDeviceMemoryProperties(m_instanceWrapper->instance.getDriver(), m_physicalDevices[seconddeviceID]);
221 vk.getDeviceGroupPeerMemoryFeatures(*m_deviceGroup, deviceMemProps2.memoryTypes[memoryTypeIndex].heapIndex, firstdeviceID, seconddeviceID, &peerMemFeatures1);
222 vk.getDeviceGroupPeerMemoryFeatures(*m_deviceGroup, deviceMemProps1.memoryTypes[memoryTypeIndex].heapIndex, seconddeviceID, firstdeviceID, &peerMemFeatures2);
223 return (peerMemFeatures1 & VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT) && (peerMemFeatures2 & VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT);
224 }
225
init(void)226 void DeviceGroupTestInstance::init (void)
227 {
228 if (!m_context.isInstanceFunctionalitySupported("VK_KHR_device_group_creation"))
229 TCU_THROW(NotSupportedError, "Device Group tests are not supported, no device group extension present.");
230
231 if (!m_context.isDeviceFunctionalitySupported("VK_KHR_device_group"))
232 TCU_THROW(NotSupportedError, "Missing extension: VK_KHR_device_group");
233
234 vector<string> deviceExtensions;
235
236 if (!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_device_group"))
237 deviceExtensions.push_back("VK_KHR_device_group");
238
239 if(m_useDedicated)
240 {
241 if (!m_context.isDeviceFunctionalitySupported("VK_KHR_dedicated_allocation"))
242 TCU_THROW(NotSupportedError, "Missing extension: VK_KHR_dedicated_allocation");
243
244 if (!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_dedicated_allocation"))
245 deviceExtensions.push_back("VK_KHR_dedicated_allocation");
246 }
247
248 const InstanceInterface& instanceDriver = m_instanceWrapper->instance.getDriver();
249 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
250 const deUint32 queueIndex = 0;
251 const float queuePriority = 1.0f;
252 vector<const char*> extensionPtrs;
253 vector<const char*> layerPtrs;
254 vector<string> enabledLayers;
255
256 {
257 const tcu::CommandLine& cmdLine = m_context.getTestContext().getCommandLine();
258 const vector<vk::VkPhysicalDeviceGroupProperties> properties = enumeratePhysicalDeviceGroups(instanceDriver, m_instanceWrapper->instance);
259 const int kGroupId = cmdLine.getVKDeviceGroupId();
260 const int kGroupIndex = kGroupId - 1;
261 const int kDevId = cmdLine.getVKDeviceId();
262 const int kDevIndex = kDevId - 1;
263
264 if (kGroupId < 1 || static_cast<size_t>(kGroupId) > properties.size())
265 {
266 std::ostringstream msg;
267 msg << "Invalid device group id " << kGroupId << " (only " << properties.size() << " device groups found)";
268 TCU_THROW(NotSupportedError, msg.str());
269 }
270
271 m_physicalDeviceCount = properties[kGroupIndex].physicalDeviceCount;
272 for (deUint32 idx = 0; idx < m_physicalDeviceCount; idx++)
273 {
274 m_physicalDevices.push_back(properties[kGroupIndex].physicalDevices[idx]);
275 }
276
277 if (m_usePeerFetch && m_physicalDeviceCount < 2)
278 TCU_THROW(NotSupportedError, "Peer fetching needs more than 1 physical device.");
279
280 if (!(m_testMode & TEST_MODE_AFR) || (m_physicalDeviceCount > 1))
281 {
282 if (!de::contains(m_context.getDeviceExtensions().begin(), m_context.getDeviceExtensions().end(), std::string("VK_KHR_bind_memory2")))
283 TCU_THROW(NotSupportedError, "Missing extension: VK_KHR_bind_memory2");
284 if (!isCoreDeviceExtension(m_context.getUsedApiVersion(), "VK_KHR_bind_memory2"))
285 deviceExtensions.push_back("VK_KHR_bind_memory2");
286 }
287
288 const VkDeviceQueueCreateInfo deviceQueueCreateInfo =
289 {
290 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, //type
291 DE_NULL, //pNext
292 (VkDeviceQueueCreateFlags)0u, //flags
293 queueFamilyIndex, //queueFamilyIndex;
294 1u, //queueCount;
295 &queuePriority, //pQueuePriorities;
296 };
297 VkDeviceGroupDeviceCreateInfo deviceGroupInfo =
298 {
299 VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO, //stype
300 DE_NULL, //pNext
301 properties[kGroupIndex].physicalDeviceCount, //physicalDeviceCount
302 properties[kGroupIndex].physicalDevices //physicalDevices
303 };
304
305 if (kDevId < 1 || static_cast<deUint32>(kDevId) > m_physicalDeviceCount)
306 {
307 std::ostringstream msg;
308 msg << "Device id " << kDevId << " invalid for group " << kGroupId << " (group " << kGroupId << " has " << m_physicalDeviceCount << " devices)";
309 TCU_THROW(NotSupportedError, msg.str());
310 }
311
312 VkPhysicalDevice physicalDevice = properties[kGroupIndex].physicalDevices[kDevIndex];
313 VkPhysicalDeviceFeatures enabledDeviceFeatures = getPhysicalDeviceFeatures(instanceDriver, physicalDevice);
314 m_subsetAllocation = properties[kGroupIndex].subsetAllocation;
315
316 if (m_drawTessellatedSphere & static_cast<bool>(!enabledDeviceFeatures.tessellationShader))
317 TCU_THROW(NotSupportedError, "Tessellation is not supported.");
318
319 if (m_fillModeNonSolid & static_cast<bool>(!enabledDeviceFeatures.fillModeNonSolid))
320 TCU_THROW(NotSupportedError, "Line polygon mode is not supported.");
321
322 extensionPtrs.resize(deviceExtensions.size());
323 for (size_t ndx = 0; ndx < deviceExtensions.size(); ++ndx)
324 extensionPtrs[ndx] = deviceExtensions[ndx].c_str();
325
326 void* pNext = &deviceGroupInfo;
327 #ifdef CTS_USES_VULKANSC
328 VkDeviceObjectReservationCreateInfo memReservationInfo = cmdLine.isSubProcess() ? m_context.getResourceInterface()->getStatMax() : resetDeviceObjectReservationCreateInfo();
329 memReservationInfo.pNext = pNext;
330 pNext = &memReservationInfo;
331
332 VkPhysicalDeviceVulkanSC10Features sc10Features = createDefaultSC10Features();
333 sc10Features.pNext = pNext;
334 pNext = &sc10Features;
335 VkPipelineCacheCreateInfo pcCI;
336 std::vector<VkPipelinePoolSize> poolSizes;
337 if (m_context.getTestContext().getCommandLine().isSubProcess())
338 {
339 if (m_context.getResourceInterface()->getCacheDataSize() > 0)
340 {
341 pcCI =
342 {
343 VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, // VkStructureType sType;
344 DE_NULL, // const void* pNext;
345 VK_PIPELINE_CACHE_CREATE_READ_ONLY_BIT |
346 VK_PIPELINE_CACHE_CREATE_USE_APPLICATION_STORAGE_BIT, // VkPipelineCacheCreateFlags flags;
347 m_context.getResourceInterface()->getCacheDataSize(), // deUintptr initialDataSize;
348 m_context.getResourceInterface()->getCacheData() // const void* pInitialData;
349 };
350 memReservationInfo.pipelineCacheCreateInfoCount = 1;
351 memReservationInfo.pPipelineCacheCreateInfos = &pcCI;
352 }
353
354 poolSizes = m_context.getResourceInterface()->getPipelinePoolSizes();
355 if (!poolSizes.empty())
356 {
357 memReservationInfo.pipelinePoolSizeCount = deUint32(poolSizes.size());
358 memReservationInfo.pPipelinePoolSizes = poolSizes.data();
359 }
360 }
361 #endif // CTS_USES_VULKANSC
362
363 const VkDeviceCreateInfo deviceCreateInfo =
364 {
365 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, //sType;
366 pNext, //pNext;
367 (VkDeviceCreateFlags)0u, //flags
368 1, //queueRecordCount;
369 &deviceQueueCreateInfo, //pRequestedQueues;
370 0u, //layerCount;
371 DE_NULL, //ppEnabledLayerNames;
372 (deUint32)extensionPtrs.size(), //extensionCount;
373 (extensionPtrs.empty() ? DE_NULL : &extensionPtrs[0]), //ppEnabledExtensionNames;
374 &enabledDeviceFeatures, //pEnabledFeatures;
375 };
376 m_deviceGroup = createCustomDevice(m_context.getTestContext().getCommandLine().isValidationEnabled(), m_context.getPlatformInterface(), m_instanceWrapper->instance, instanceDriver, physicalDevice, &deviceCreateInfo);
377 #ifndef CTS_USES_VULKANSC
378 m_deviceDriver = de::MovePtr<DeviceDriver>(new DeviceDriver(m_context.getPlatformInterface(), m_instanceWrapper->instance, *m_deviceGroup));
379 #else
380 m_deviceDriver = de::MovePtr<DeviceDriverSC, DeinitDeviceDeleter>(new DeviceDriverSC(m_context.getPlatformInterface(), m_instanceWrapper->instance, *m_deviceGroup, m_context.getTestContext().getCommandLine(), m_context.getResourceInterface(), m_context.getDeviceVulkanSC10Properties(), m_context.getDeviceProperties()), vk::DeinitDeviceDeleter(m_context.getResourceInterface().get(), *m_deviceGroup));
381 #endif // CTS_USES_VULKANSC
382 }
383
384 m_deviceGroupQueue = getDeviceQueue(*m_deviceDriver, *m_deviceGroup, queueFamilyIndex, queueIndex);
385 }
386
submitBufferAndWaitForIdle(const vk::DeviceInterface & vk,VkCommandBuffer cmdBuf,deUint32 deviceMask)387 void DeviceGroupTestInstance::submitBufferAndWaitForIdle(const vk::DeviceInterface& vk, VkCommandBuffer cmdBuf, deUint32 deviceMask)
388 {
389 submitCommandsAndWait(vk, *m_deviceGroup, m_deviceGroupQueue, cmdBuf, true, deviceMask);
390 VK_CHECK(vk.deviceWaitIdle(*m_deviceGroup));
391 }
392
iterate(void)393 tcu::TestStatus DeviceGroupTestInstance::iterate (void)
394 {
395 const InstanceInterface& vki = m_instanceWrapper->instance.getDriver();
396 const vk::DeviceInterface& vk = m_context.getDeviceInterface();
397 const deUint32 queueFamilyIndex = m_context.getUniversalQueueFamilyIndex();
398 const tcu::UVec2 renderSize (256, 256);
399 const VkFormat colorFormat = VK_FORMAT_R8G8B8A8_UNORM;
400 const tcu::Vec4 clearColor (0.125f, 0.25f, 0.75f, 1.0f);
401 const tcu::Vec4 drawColor (1.0f, 1.0f, 0.0f, 1.0f);
402 const float tessLevel = 16.0f;
403 SimpleAllocator memAlloc (vk, *m_deviceGroup, getPhysicalDeviceMemoryProperties(vki, m_context.getPhysicalDevice()));
404 bool iterateResultSuccess = false;
405 const tcu::Vec4 sphereVertices[] =
406 {
407 tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f),
408 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
409 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
410 tcu::Vec4(0.0f, 0.0f, -1.0f, 1.0f),
411 tcu::Vec4(0.0f, -1.0f, 0.0f, 1.0f),
412 tcu::Vec4(-1.0f, 0.0f, 0.0f, 1.0f),
413 };
414 const deUint32 sphereIndices[] = {0, 1, 2, 2, 1, 3, 3, 1, 5, 5, 1, 0, 0, 2, 4, 2, 3, 4, 3, 5, 4, 5, 0, 4};
415 const tcu::Vec4 triVertices[] =
416 {
417 tcu::Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
418 tcu::Vec4(+0.5f, -0.5f, 0.0f, 1.0f),
419 tcu::Vec4(0.0f, +0.5f, 0.0f, 1.0f)
420 };
421 const deUint32 triIndices[] = {0, 1, 2};
422 const tcu::Vec4 * vertices = m_drawTessellatedSphere ? &sphereVertices[0] : &triVertices[0];
423 const deUint32 * indices = m_drawTessellatedSphere ? &sphereIndices[0] : &triIndices[0];
424 const deUint32 verticesSize = m_drawTessellatedSphere ? deUint32(sizeof(sphereVertices)) : deUint32(sizeof(triVertices));
425 const deUint32 numIndices = m_drawTessellatedSphere ? deUint32(sizeof(sphereIndices)/sizeof(sphereIndices[0])) : deUint32(sizeof(triIndices)/sizeof(triIndices[0]));
426 const deUint32 indicesSize = m_drawTessellatedSphere ? deUint32(sizeof(sphereIndices)) : deUint32(sizeof(triIndices));
427
428 // Loop through all physical devices in the device group
429 for (deUint32 physDevID = 0; physDevID < m_physicalDeviceCount; physDevID++)
430 {
431 const deUint32 firstDeviceID = physDevID;
432 const deUint32 secondDeviceID = (firstDeviceID + 1 ) % m_physicalDeviceCount;
433 vector<deUint32> deviceIndices (m_physicalDeviceCount);
434 bool isPeerMemAsCopySrcAllowed = true;
435 // Set broadcast on memory allocation
436 const deUint32 allocDeviceMask = m_subsetAllocation ? (1 << firstDeviceID) | (1 << secondDeviceID) : (1 << m_physicalDeviceCount) - 1;
437
438 for (deUint32 i = 0; i < m_physicalDeviceCount; i++)
439 deviceIndices[i] = i;
440 deviceIndices[firstDeviceID] = secondDeviceID;
441 deviceIndices[secondDeviceID] = firstDeviceID;
442
443 VkMemoryRequirements memReqs =
444 {
445 0, // VkDeviceSize size
446 0, // VkDeviceSize alignment
447 0, // uint32_t memoryTypeBits
448 };
449 deUint32 memoryTypeNdx = 0;
450 de::MovePtr<Allocation> stagingVertexBufferMemory;
451 de::MovePtr<Allocation> stagingIndexBufferMemory;
452 de::MovePtr<Allocation> stagingUniformBufferMemory;
453 de::MovePtr<Allocation> stagingSboBufferMemory;
454
455 vk::Move<vk::VkDeviceMemory> vertexBufferMemory;
456 vk::Move<vk::VkDeviceMemory> indexBufferMemory;
457 vk::Move<vk::VkDeviceMemory> uniformBufferMemory;
458 vk::Move<vk::VkDeviceMemory> sboBufferMemory;
459 vk::Move<vk::VkDeviceMemory> renderImageMemory;
460 vk::Move<vk::VkDeviceMemory> readImageMemory;
461
462 Move<VkRenderPass> renderPass;
463 Move<VkImage> renderImage;
464 Move<VkImage> readImage;
465
466 Move<VkDescriptorSetLayout> descriptorSetLayout;
467 Move<VkDescriptorPool> descriptorPool;
468 Move<VkDescriptorSet> descriptorSet;
469
470 Move<VkBuffer> stagingVertexBuffer;
471 Move<VkBuffer> stagingUniformBuffer;
472 Move<VkBuffer> stagingIndexBuffer;
473 Move<VkBuffer> stagingSboBuffer;
474
475 Move<VkBuffer> vertexBuffer;
476 Move<VkBuffer> indexBuffer;
477 Move<VkBuffer> uniformBuffer;
478 Move<VkBuffer> sboBuffer;
479
480 Move<VkPipeline> pipeline;
481 Move<VkPipelineLayout> pipelineLayout;
482
483 Move<VkImageView> colorAttView;
484 Move<VkFramebuffer> framebuffer;
485 Move<VkCommandPool> cmdPool;
486 Move<VkCommandBuffer> cmdBuffer;
487
488 VkMemoryDedicatedAllocateInfo dedicatedAllocInfo =
489 {
490 VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, // sType
491 DE_NULL, // pNext
492 DE_NULL, // image
493 DE_NULL // buffer
494 };
495
496 VkMemoryAllocateFlagsInfo allocDeviceMaskInfo =
497 {
498 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO, // sType
499 m_useDedicated ? &dedicatedAllocInfo : DE_NULL, // pNext
500 VK_MEMORY_ALLOCATE_DEVICE_MASK_BIT, // flags
501 allocDeviceMask, // deviceMask
502 };
503
504 VkMemoryAllocateInfo allocInfo =
505 {
506 VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // sType
507 &allocDeviceMaskInfo, // pNext
508 0u, // allocationSize
509 0u, // memoryTypeIndex
510 };
511
512 // create vertex buffers
513 {
514 const VkBufferCreateInfo stagingVertexBufferParams =
515 {
516 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
517 DE_NULL, // pNext
518 0u, // flags
519 (VkDeviceSize)verticesSize, // size
520 VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
521 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
522 1u, // queueFamilyIndexCount
523 &queueFamilyIndex, // pQueueFamilyIndices
524 };
525 stagingVertexBuffer = createBuffer(vk, *m_deviceGroup, &stagingVertexBufferParams);
526 stagingVertexBufferMemory = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_deviceGroup, *stagingVertexBuffer), MemoryRequirement::HostVisible);
527 VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *stagingVertexBuffer, stagingVertexBufferMemory->getMemory(), stagingVertexBufferMemory->getOffset()));
528
529 void* vertexBufPtr = stagingVertexBufferMemory->getHostPtr();
530 deMemcpy(vertexBufPtr, &vertices[0], verticesSize);
531 flushAlloc(vk, *m_deviceGroup, *stagingVertexBufferMemory);
532 }
533
534 {
535 const VkBufferCreateInfo vertexBufferParams =
536 {
537 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
538 DE_NULL, // pNext
539 0u, // flags
540 (VkDeviceSize)verticesSize, // size
541 VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
542 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
543 1u, // queueFamilyIndexCount
544 &queueFamilyIndex, // pQueueFamilyIndices
545 };
546 vertexBuffer = createBuffer(vk, *m_deviceGroup, &vertexBufferParams);
547
548 memReqs = getBufferMemoryRequirements(vk, *m_deviceGroup, vertexBuffer.get());
549 memoryTypeNdx = getMemoryIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
550
551 dedicatedAllocInfo.buffer = vertexBuffer.get();
552 allocInfo.allocationSize = memReqs.size;
553 allocInfo.memoryTypeIndex = memoryTypeNdx;
554 vertexBufferMemory = allocateMemory(vk, *m_deviceGroup, &allocInfo);
555
556 if (m_usePeerFetch && !isPeerFetchAllowed(memoryTypeNdx, firstDeviceID, secondDeviceID))
557 TCU_THROW(NotSupportedError, "Peer fetch is not supported.");
558
559 // Bind vertex buffer
560 if (m_usePeerFetch)
561 {
562 VkBindBufferMemoryDeviceGroupInfo devGroupBindInfo =
563 {
564 VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO, // sType
565 DE_NULL, // pNext
566 m_physicalDeviceCount, // deviceIndexCount
567 &deviceIndices[0], // pDeviceIndices
568 };
569
570 VkBindBufferMemoryInfo bindInfo =
571 {
572 VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, // sType
573 &devGroupBindInfo, // pNext
574 vertexBuffer.get(), // buffer
575 vertexBufferMemory.get(), // memory
576 0u, // memoryOffset
577 };
578 VK_CHECK(vk.bindBufferMemory2(*m_deviceGroup, 1, &bindInfo));
579 }
580 else
581 VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *vertexBuffer, vertexBufferMemory.get(), 0));
582 }
583
584 // create index buffers
585 {
586 const VkBufferCreateInfo stagingIndexBufferParams =
587 {
588 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
589 DE_NULL, // pNext
590 0u, // flags
591 (VkDeviceSize)indicesSize, // size
592 VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
593 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
594 1u, // queueFamilyIndexCount
595 &queueFamilyIndex, // pQueueFamilyIndices
596 };
597 stagingIndexBuffer = createBuffer(vk, *m_deviceGroup, &stagingIndexBufferParams);
598 stagingIndexBufferMemory = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_deviceGroup, *stagingIndexBuffer), MemoryRequirement::HostVisible);
599 VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *stagingIndexBuffer, stagingIndexBufferMemory->getMemory(), stagingIndexBufferMemory->getOffset()));
600
601 void* indexBufPtr = stagingIndexBufferMemory->getHostPtr();
602 deMemcpy(indexBufPtr, &indices[0], indicesSize);
603 flushAlloc(vk, *m_deviceGroup, *stagingIndexBufferMemory);
604 }
605
606 {
607 const VkBufferCreateInfo indexBufferParams =
608 {
609 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
610 DE_NULL, // pNext
611 0u, // flags
612 (VkDeviceSize)indicesSize, // size
613 VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
614 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
615 1u, // queueFamilyIndexCount
616 &queueFamilyIndex, // pQueueFamilyIndices
617 };
618 indexBuffer = createBuffer(vk, *m_deviceGroup, &indexBufferParams);
619
620 memReqs = getBufferMemoryRequirements(vk, *m_deviceGroup, indexBuffer.get());
621 memoryTypeNdx = getMemoryIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
622
623 dedicatedAllocInfo.buffer = indexBuffer.get();
624 allocInfo.allocationSize = memReqs.size;
625 allocInfo.memoryTypeIndex = memoryTypeNdx;
626 indexBufferMemory = allocateMemory(vk, *m_deviceGroup, &allocInfo);
627
628 if (m_usePeerFetch && !isPeerFetchAllowed(memoryTypeNdx, firstDeviceID, secondDeviceID))
629 TCU_THROW(NotSupportedError, "Peer fetch is not supported.");
630
631 // Bind index buffer
632 if (m_usePeerFetch)
633 {
634 VkBindBufferMemoryDeviceGroupInfo devGroupBindInfo =
635 {
636 VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO, // sType
637 DE_NULL, // pNext
638 m_physicalDeviceCount, // deviceIndexCount
639 &deviceIndices[0], // pDeviceIndices
640 };
641
642 VkBindBufferMemoryInfo bindInfo =
643 {
644 VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, // sType
645 &devGroupBindInfo, // pNext
646 indexBuffer.get(), // buffer
647 indexBufferMemory.get(), // memory
648 0u, // memoryOffset
649 };
650 VK_CHECK(vk.bindBufferMemory2(*m_deviceGroup, 1, &bindInfo));
651 }
652 else
653 VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *indexBuffer, indexBufferMemory.get(), 0));
654 }
655
656 // create uniform buffers
657 {
658 const VkBufferCreateInfo stagingUniformBufferParams =
659 {
660 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
661 DE_NULL, // pNext
662 0u, // flags
663 (VkDeviceSize)sizeof(drawColor), // size
664 VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
665 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
666 1u, // queueFamilyIndexCount
667 &queueFamilyIndex, // pQueueFamilyIndices
668 };
669 stagingUniformBuffer = createBuffer(vk, *m_deviceGroup, &stagingUniformBufferParams);
670 stagingUniformBufferMemory = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_deviceGroup, *stagingUniformBuffer), MemoryRequirement::HostVisible);
671 VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *stagingUniformBuffer, stagingUniformBufferMemory->getMemory(), stagingUniformBufferMemory->getOffset()));
672
673 void* uniformBufPtr = stagingUniformBufferMemory->getHostPtr();
674 deMemcpy(uniformBufPtr, &drawColor[0], sizeof(drawColor));
675 flushAlloc(vk, *m_deviceGroup, *stagingUniformBufferMemory);
676 }
677
678 {
679 const VkBufferCreateInfo uniformBufferParams =
680 {
681 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
682 DE_NULL, // pNext
683 0u, // flags
684 (VkDeviceSize)sizeof(drawColor), // size
685 VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
686 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
687 1u, // queueFamilyIndexCount
688 &queueFamilyIndex, // pQueueFamilyIndices
689 };
690 uniformBuffer = createBuffer(vk, *m_deviceGroup, &uniformBufferParams);
691
692 memReqs = getBufferMemoryRequirements(vk, *m_deviceGroup, uniformBuffer.get());
693 memoryTypeNdx = getMemoryIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
694
695 dedicatedAllocInfo.buffer = uniformBuffer.get();
696 allocInfo.allocationSize = memReqs.size;
697 allocInfo.memoryTypeIndex = memoryTypeNdx;
698 uniformBufferMemory = allocateMemory(vk, *m_deviceGroup, &allocInfo);
699
700 if (m_usePeerFetch && !isPeerFetchAllowed(memoryTypeNdx, firstDeviceID, secondDeviceID))
701 TCU_THROW(NotSupportedError, "Peer fetch is not supported.");
702
703 if (m_usePeerFetch)
704 {
705 VkBindBufferMemoryDeviceGroupInfo devGroupBindInfo =
706 {
707 VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO, // sType
708 DE_NULL, // pNext
709 m_physicalDeviceCount, // deviceIndexCount
710 &deviceIndices[0], // pDeviceIndices
711 };
712
713 VkBindBufferMemoryInfo bindInfo =
714 {
715 VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, // sType
716 &devGroupBindInfo, // pNext
717 uniformBuffer.get(), // buffer
718 uniformBufferMemory.get(), // memory
719 0u, // memoryOffset
720 };
721 VK_CHECK(vk.bindBufferMemory2(*m_deviceGroup, 1, &bindInfo));
722 }
723 else
724 VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, uniformBuffer.get(), uniformBufferMemory.get(), 0));
725 }
726
727 // create SBO buffers
728 {
729 const VkBufferCreateInfo stagingSboBufferParams =
730 {
731 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
732 DE_NULL, // pNext
733 0u, // flags
734 (VkDeviceSize)sizeof(tessLevel), // size
735 VK_BUFFER_USAGE_TRANSFER_SRC_BIT, // usage
736 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
737 1u, // queueFamilyIndexCount
738 &queueFamilyIndex, // pQueueFamilyIndices
739 };
740 stagingSboBuffer = createBuffer(vk, *m_deviceGroup, &stagingSboBufferParams);
741 stagingSboBufferMemory = memAlloc.allocate(getBufferMemoryRequirements(vk, *m_deviceGroup, *stagingSboBuffer), MemoryRequirement::HostVisible);
742 VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *stagingSboBuffer, stagingSboBufferMemory->getMemory(), stagingSboBufferMemory->getOffset()));
743
744 void* sboBufPtr = stagingSboBufferMemory->getHostPtr();
745 deMemcpy(sboBufPtr, &tessLevel, sizeof(tessLevel));
746 flushAlloc(vk, *m_deviceGroup, *stagingSboBufferMemory);
747 }
748
749 {
750 const VkBufferCreateInfo sboBufferParams =
751 {
752 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
753 DE_NULL, // pNext
754 0u, // flags
755 (VkDeviceSize)sizeof(tessLevel), // size
756 VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
757 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
758 1u, // queueFamilyIndexCount
759 &queueFamilyIndex, // pQueueFamilyIndices
760 };
761 sboBuffer = createBuffer(vk, *m_deviceGroup, &sboBufferParams);
762
763 memReqs = getBufferMemoryRequirements(vk, *m_deviceGroup, sboBuffer.get());
764 memoryTypeNdx = getMemoryIndex(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
765
766 dedicatedAllocInfo.buffer = sboBuffer.get();
767 allocInfo.allocationSize = memReqs.size;
768 allocInfo.memoryTypeIndex = memoryTypeNdx;
769 sboBufferMemory = allocateMemory(vk, *m_deviceGroup, &allocInfo);
770
771 if (m_usePeerFetch && !isPeerFetchAllowed(memoryTypeNdx, firstDeviceID, secondDeviceID))
772 TCU_THROW(NotSupportedError, "Peer fetch is not supported.");
773
774 if (m_usePeerFetch)
775 {
776 VkBindBufferMemoryDeviceGroupInfo devGroupBindInfo =
777 {
778 VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_DEVICE_GROUP_INFO, // sType
779 DE_NULL, // pNext
780 m_physicalDeviceCount, // deviceIndexCount
781 &deviceIndices[0], // pDeviceIndices
782 };
783
784 VkBindBufferMemoryInfo bindInfo =
785 {
786 VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO, // sType
787 &devGroupBindInfo, // pNext
788 sboBuffer.get(), // buffer
789 sboBufferMemory.get(), // memory
790 0u, // memoryOffset
791 };
792 VK_CHECK(vk.bindBufferMemory2(*m_deviceGroup, 1, &bindInfo));
793 }
794 else
795 VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, sboBuffer.get(), sboBufferMemory.get(), 0));
796 }
797
798 // Create image resources
799 // Use a consistent usage flag because of memory aliasing
800 VkImageUsageFlags imageUsageFlag = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
801 {
802 // Check for SFR support
803 VkImageFormatProperties properties;
804 if ((m_testMode & TEST_MODE_SFR) && vki.getPhysicalDeviceImageFormatProperties(m_context.getPhysicalDevice(),
805 colorFormat, // format
806 VK_IMAGE_TYPE_2D, // type
807 VK_IMAGE_TILING_OPTIMAL, // tiling
808 VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // usage
809 VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT, // flags
810 &properties) != VK_SUCCESS) // properties
811 {
812 TCU_THROW(NotSupportedError, "Format not supported for SFR");
813 }
814
815 VkImageCreateFlags imageCreateFlags = VK_IMAGE_CREATE_ALIAS_BIT; // The image objects alias same memory
816 if ((m_testMode & TEST_MODE_SFR) && (m_physicalDeviceCount > 1))
817 {
818 imageCreateFlags |= VK_IMAGE_CREATE_SPLIT_INSTANCE_BIND_REGIONS_BIT;
819 }
820
821 const VkImageCreateInfo imageParams =
822 {
823 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
824 DE_NULL, // pNext
825 imageCreateFlags, // flags
826 VK_IMAGE_TYPE_2D, // imageType
827 colorFormat, // format
828 { renderSize.x(), renderSize.y(), 1 }, // extent
829 1u, // mipLevels
830 1u, // arraySize
831 VK_SAMPLE_COUNT_1_BIT, // samples
832 VK_IMAGE_TILING_OPTIMAL, // tiling
833 imageUsageFlag, // usage
834 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
835 1u, // queueFamilyIndexCount
836 &queueFamilyIndex, // pQueueFamilyIndices
837 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
838 };
839
840 renderImage = createImage(vk, *m_deviceGroup, &imageParams);
841 readImage = createImage(vk, *m_deviceGroup, &imageParams);
842
843 dedicatedAllocInfo.image = *renderImage;
844 dedicatedAllocInfo.buffer = DE_NULL;
845 memReqs = getImageMemoryRequirements(vk, *m_deviceGroup, renderImage.get());
846 memoryTypeNdx = getMemoryIndex(memReqs.memoryTypeBits, m_useHostMemory ? 0 : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
847 allocInfo.allocationSize = memReqs.size;
848 allocInfo.memoryTypeIndex = memoryTypeNdx;
849 renderImageMemory = allocateMemory(vk, *m_deviceGroup, &allocInfo);
850
851 dedicatedAllocInfo.image = *readImage;
852 dedicatedAllocInfo.buffer = DE_NULL;
853 memReqs = getImageMemoryRequirements(vk, *m_deviceGroup, readImage.get());
854 memoryTypeNdx = getMemoryIndex(memReqs.memoryTypeBits, m_useHostMemory ? 0 : VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
855 allocInfo.allocationSize = memReqs.size;
856 allocInfo.memoryTypeIndex = memoryTypeNdx;
857 readImageMemory = allocateMemory(vk, *m_deviceGroup, &allocInfo);
858 }
859
860 VK_CHECK(vk.bindImageMemory(*m_deviceGroup, *renderImage, renderImageMemory.get(), 0));
861 VK_CHECK(vk.bindImageMemory(*m_deviceGroup, *readImage, readImageMemory.get(), 0));
862
863 // Create renderpass
864 {
865 const VkAttachmentDescription colorAttachmentDescription =
866 {
867 (VkAttachmentDescriptionFlags)0, // VkAttachmentDescriptionFlags flags
868 colorFormat, // VkFormat format
869 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples
870 VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp
871 VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp
872 VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp
873 VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp
874 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout
875 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // VkImageLayout finalLayout
876 };
877
878 const VkAttachmentReference colorAttachmentRef =
879 {
880 0u, // deUint32 attachment
881 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout
882 };
883
884 const VkSubpassDescription subpassDescription =
885 {
886 (VkSubpassDescriptionFlags)0, // VkSubpassDescriptionFlags flags
887 VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint
888 0u, // deUint32 inputAttachmentCount
889 DE_NULL, // const VkAttachmentReference* pInputAttachments
890 1u, // deUint32 colorAttachmentCount
891 &colorAttachmentRef, // const VkAttachmentReference* pColorAttachments
892 DE_NULL, // const VkAttachmentReference* pResolveAttachments
893 DE_NULL, // const VkAttachmentReference* pDepthStencilAttachment
894 0u, // deUint32 preserveAttachmentCount
895 DE_NULL // const deUint32* pPreserveAttachments
896 };
897
898 const VkRenderPassCreateInfo renderPassInfo =
899 {
900 VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType
901 DE_NULL, // const void* pNext
902 (VkRenderPassCreateFlags)0, // VkRenderPassCreateFlags flags
903 1, // deUint32 attachmentCount
904 &colorAttachmentDescription, // const VkAttachmentDescription* pAttachments
905 1u, // deUint32 subpassCount
906 &subpassDescription, // const VkSubpassDescription* pSubpasses
907 0u, // deUint32 dependencyCount
908 DE_NULL // const VkSubpassDependency* pDependencies
909 };
910
911 renderPass = createRenderPass(vk, *m_deviceGroup, &renderPassInfo, DE_NULL);
912 }
913
914 // Create descriptors
915 {
916 vector<VkDescriptorSetLayoutBinding> layoutBindings;
917 vector<VkDescriptorPoolSize> descriptorTypes;
918 vector<VkWriteDescriptorSet> writeDescritporSets;
919
920 const VkDescriptorSetLayoutBinding layoutBindingUBO =
921 {
922 0u, // deUint32 binding;
923 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // VkDescriptorType descriptorType;
924 1u, // deUint32 descriptorCount;
925 VK_SHADER_STAGE_FRAGMENT_BIT, // VkShaderStageFlags stageFlags;
926 DE_NULL // const VkSampler* pImmutableSamplers;
927 };
928 const VkDescriptorSetLayoutBinding layoutBindingSBO =
929 {
930 1u, // deUint32 binding;
931 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // VkDescriptorType descriptorType;
932 1u, // deUint32 descriptorCount;
933 VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT, // VkShaderStageFlags stageFlags;
934 DE_NULL // const VkSampler* pImmutableSamplers;
935 };
936
937 layoutBindings.push_back(layoutBindingUBO);
938 if (m_drawTessellatedSphere)
939 layoutBindings.push_back(layoutBindingSBO);
940
941 const VkDescriptorSetLayoutCreateInfo descriptorLayoutParams =
942 {
943 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType;
944 DE_NULL, // cost void* pNext;
945 (VkDescriptorSetLayoutCreateFlags)0, // VkDescriptorSetLayoutCreateFlags flags
946 deUint32(layoutBindings.size()), // deUint32 count;
947 layoutBindings.data() // const VkDescriptorSetLayoutBinding pBinding;
948 };
949 descriptorSetLayout = createDescriptorSetLayout(vk, *m_deviceGroup, &descriptorLayoutParams);
950
951 const VkDescriptorPoolSize descriptorTypeUBO =
952 {
953 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // VkDescriptorType type;
954 1 // deUint32 count;
955 };
956 const VkDescriptorPoolSize descriptorTypeSBO =
957 {
958 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // VkDescriptorType type;
959 1 // deUint32 count;
960 };
961 descriptorTypes.push_back(descriptorTypeUBO);
962 if (m_drawTessellatedSphere)
963 descriptorTypes.push_back(descriptorTypeSBO);
964
965 const VkDescriptorPoolCreateInfo descriptorPoolParams =
966 {
967 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType;
968 DE_NULL, // void* pNext;
969 VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, // VkDescriptorPoolCreateFlags flags;
970 1u, // deUint32 maxSets;
971 deUint32(descriptorTypes.size()), // deUint32 count;
972 descriptorTypes.data() // const VkDescriptorTypeCount* pTypeCount
973 };
974 descriptorPool = createDescriptorPool(vk, *m_deviceGroup, &descriptorPoolParams);
975
976 const VkDescriptorSetAllocateInfo descriptorSetParams =
977 {
978 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
979 DE_NULL,
980 *descriptorPool,
981 1u,
982 &descriptorSetLayout.get(),
983 };
984 descriptorSet = allocateDescriptorSet(vk, *m_deviceGroup, &descriptorSetParams);
985
986 const VkDescriptorBufferInfo uboDescriptorInfo =
987 {
988 uniformBuffer.get(),
989 0,
990 (VkDeviceSize)sizeof(drawColor)
991 };
992 const VkDescriptorBufferInfo sboDescriptorInfo =
993 {
994 sboBuffer.get(),
995 0,
996 (VkDeviceSize)sizeof(tessLevel)
997 };
998 const VkWriteDescriptorSet writeDescritporSetUBO =
999 {
1000 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
1001 DE_NULL, // const void* pNext;
1002 *descriptorSet, // VkDescriptorSet destSet;
1003 0, // deUint32 destBinding;
1004 0, // deUint32 destArrayElement;
1005 1u, // deUint32 count;
1006 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // VkDescriptorType descriptorType;
1007 (const VkDescriptorImageInfo*)DE_NULL, // VkDescriptorImageInfo* pImageInfo;
1008 &uboDescriptorInfo, // VkDescriptorBufferInfo* pBufferInfo;
1009 (const VkBufferView*)DE_NULL // VkBufferView* pTexelBufferView;
1010 };
1011
1012 const VkWriteDescriptorSet writeDescritporSetSBO =
1013 {
1014 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType;
1015 DE_NULL, // const void* pNext;
1016 *descriptorSet, // VkDescriptorSet destSet;
1017 1, // deUint32 destBinding;
1018 0, // deUint32 destArrayElement;
1019 1u, // deUint32 count;
1020 VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, // VkDescriptorType descriptorType;
1021 (const VkDescriptorImageInfo*)DE_NULL, // VkDescriptorImageInfo* pImageInfo;
1022 &sboDescriptorInfo, // VkDescriptorBufferInfo* pBufferInfo;
1023 (const VkBufferView*)DE_NULL // VkBufferView* pTexelBufferView;
1024 };
1025 writeDescritporSets.push_back(writeDescritporSetUBO);
1026 if (m_drawTessellatedSphere)
1027 writeDescritporSets.push_back(writeDescritporSetSBO);
1028
1029 vk.updateDescriptorSets(*m_deviceGroup, deUint32(writeDescritporSets.size()), writeDescritporSets.data(), 0u, DE_NULL);
1030 }
1031
1032 // Create Pipeline
1033 {
1034 Move<VkShaderModule> vertShaderModule;
1035 Move<VkShaderModule> tcssShaderModule;
1036 Move<VkShaderModule> tessShaderModule;
1037 Move<VkShaderModule> fragShaderModule;
1038
1039 const VkDescriptorSetLayout descset = descriptorSetLayout.get();
1040 const VkPipelineLayoutCreateInfo pipelineLayoutParams =
1041 {
1042 VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, // sType
1043 DE_NULL, // pNext
1044 (vk::VkPipelineLayoutCreateFlags)0, // flags
1045 1u, // setLayoutCount
1046 &descset, // pSetLayouts
1047 0u, // pushConstantRangeCount
1048 DE_NULL, // pPushConstantRanges
1049 };
1050 pipelineLayout = createPipelineLayout(vk, *m_deviceGroup, &pipelineLayoutParams);
1051
1052 // Shaders
1053 vertShaderModule = createShaderModule(vk, *m_deviceGroup, m_context.getBinaryCollection().get("vert"), 0);
1054 fragShaderModule = createShaderModule(vk, *m_deviceGroup, m_context.getBinaryCollection().get("frag"), 0);
1055
1056 if (m_drawTessellatedSphere)
1057 {
1058 tcssShaderModule = createShaderModule(vk, *m_deviceGroup, m_context.getBinaryCollection().get("tesc"), 0);
1059 tessShaderModule = createShaderModule(vk, *m_deviceGroup, m_context.getBinaryCollection().get("tese"), 0);
1060 }
1061
1062 const std::vector<VkViewport> viewports (1, makeViewport(renderSize));
1063 const std::vector<VkRect2D> scissors (1, makeRect2D(renderSize));
1064
1065 const VkPipelineRasterizationStateCreateInfo rasterParams =
1066 {
1067 VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, // sType
1068 DE_NULL, // pNext
1069 0u, // flags
1070 VK_FALSE, // depthClampEnable
1071 VK_FALSE, // rasterizerDiscardEnable
1072 m_fillModeNonSolid ? VK_POLYGON_MODE_LINE : VK_POLYGON_MODE_FILL, // polygonMode
1073 VK_CULL_MODE_NONE, // cullMode
1074 VK_FRONT_FACE_COUNTER_CLOCKWISE, // frontFace
1075 VK_FALSE, // depthBiasEnable
1076 0.0f, // depthBiasConstantFactor
1077 0.0f, // depthBiasClamp
1078 0.0f, // depthBiasSlopeFactor
1079 1.0f, // lineWidth
1080 };
1081
1082 const VkPrimitiveTopology topology = m_drawTessellatedSphere ? VK_PRIMITIVE_TOPOLOGY_PATCH_LIST : VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
1083
1084 pipeline = makeGraphicsPipeline(vk, // const DeviceInterface& vk
1085 *m_deviceGroup, // const VkDevice device
1086 *pipelineLayout, // const VkPipelineLayout pipelineLayout
1087 *vertShaderModule, // const VkShaderModule vertexShaderModule
1088 m_drawTessellatedSphere ? *tcssShaderModule : DE_NULL, // const VkShaderModule tessellationControlModule,
1089 m_drawTessellatedSphere ? *tessShaderModule : DE_NULL, // const VkShaderModule tessellationEvalModule,
1090 DE_NULL, // const VkShaderModule geometryShaderModule
1091 *fragShaderModule, // const VkShaderModule fragmentShaderModule
1092 *renderPass, // const VkRenderPass renderPass
1093 viewports, // const std::vector<VkViewport>& viewports
1094 scissors, // const std::vector<VkRect2D>& scissors
1095 topology, // const VkPrimitiveTopology topology
1096 0u, // const deUint32 subpass
1097 3u, // const deUint32 patchControlPoints
1098 DE_NULL, // const VkPipelineVertexInputStateCreateInfo* vertexInputStateCreateInfo
1099 &rasterParams); // const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
1100 }
1101
1102 // Create Framebuffer
1103 {
1104 const VkImageViewCreateInfo colorAttViewParams =
1105 {
1106 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // sType
1107 DE_NULL, // pNext
1108 0u, // flags
1109 *renderImage, // image
1110 VK_IMAGE_VIEW_TYPE_2D, // viewType
1111 colorFormat, // format
1112 {
1113 VK_COMPONENT_SWIZZLE_R,
1114 VK_COMPONENT_SWIZZLE_G,
1115 VK_COMPONENT_SWIZZLE_B,
1116 VK_COMPONENT_SWIZZLE_A
1117 }, // components
1118 {
1119 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
1120 0u, // baseMipLevel
1121 1u, // levelCount
1122 0u, // baseArrayLayer
1123 1u, // layerCount
1124 }, // subresourceRange
1125 };
1126 colorAttView = createImageView(vk, *m_deviceGroup, &colorAttViewParams);
1127
1128 const VkFramebufferCreateInfo framebufferParams =
1129 {
1130 VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // sType
1131 DE_NULL, // pNext
1132 0u, // flags
1133 *renderPass, // renderPass
1134 1u, // attachmentCount
1135 &*colorAttView, // pAttachments
1136 renderSize.x(), // width
1137 renderSize.y(), // height
1138 1u, // layers
1139 };
1140 framebuffer = createFramebuffer(vk, *m_deviceGroup, &framebufferParams);
1141 }
1142
1143 // Create Command buffer
1144 {
1145 const VkCommandPoolCreateInfo cmdPoolParams =
1146 {
1147 VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, // sType
1148 DE_NULL, // pNext
1149 VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, // flags
1150 queueFamilyIndex, // queueFamilyIndex
1151 };
1152 cmdPool = createCommandPool(vk, *m_deviceGroup, &cmdPoolParams);
1153
1154 const VkCommandBufferAllocateInfo cmdBufParams =
1155 {
1156 VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, // sType
1157 DE_NULL, // pNext
1158 *cmdPool, // pool
1159 VK_COMMAND_BUFFER_LEVEL_PRIMARY, // level
1160 1u, // bufferCount
1161 };
1162 cmdBuffer = allocateCommandBuffer(vk, *m_deviceGroup, &cmdBufParams);
1163 }
1164
1165 // Do a layout transition for renderImage
1166 {
1167 beginCommandBuffer(vk, *cmdBuffer);
1168 const VkImageMemoryBarrier colorAttBarrier =
1169 {
1170 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
1171 DE_NULL, // pNext
1172 0u, // srcAccessMask
1173 (VK_ACCESS_COLOR_ATTACHMENT_READ_BIT |
1174 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), // dstAccessMask
1175 VK_IMAGE_LAYOUT_UNDEFINED, // oldLayout
1176 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // newLayout
1177 queueFamilyIndex, // srcQueueFamilyIndex
1178 queueFamilyIndex, // dstQueueFamilyIndex
1179 *renderImage, // image
1180 {
1181 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
1182 0u, // baseMipLevel
1183 1u, // levelCount
1184 0u, // baseArrayLayer
1185 1u, // layerCount
1186 } // subresourceRange
1187 };
1188 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &colorAttBarrier);
1189
1190 endCommandBuffer(vk, *cmdBuffer);
1191 const deUint32 deviceMask = (1 << firstDeviceID) | (1 << secondDeviceID);
1192 submitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceMask);
1193 m_context.resetCommandPoolForVKSC(*m_deviceGroup, *cmdPool);
1194 }
1195
1196 // Bind renderImage across devices for SFR
1197 if ((m_testMode & TEST_MODE_SFR) && (m_physicalDeviceCount > 1))
1198 {
1199 if (m_usePeerFetch && !isPeerFetchAllowed(memoryTypeNdx, firstDeviceID, secondDeviceID))
1200 TCU_THROW(NotSupportedError, "Peer texture reads is not supported.");
1201
1202 // Check if peer memory can be used as source of a copy command in case of SFR bindings, always allowed in case of 1 device
1203 VkPeerMemoryFeatureFlags peerMemFeatures;
1204 const VkPhysicalDeviceMemoryProperties deviceMemProps = getPhysicalDeviceMemoryProperties(vki, m_physicalDevices[secondDeviceID]);
1205 vk.getDeviceGroupPeerMemoryFeatures(*m_deviceGroup, deviceMemProps.memoryTypes[memoryTypeNdx].heapIndex, firstDeviceID, secondDeviceID, &peerMemFeatures);
1206 isPeerMemAsCopySrcAllowed = (peerMemFeatures & VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT);
1207
1208 VkRect2D zeroRect = {
1209 {
1210 0, // VkOffset2D.x
1211 0, // VkOffset2D.x
1212 },
1213 {
1214 0, // VkExtent2D.x
1215 0, // VkExtent2D.x
1216 }
1217 };
1218 vector<VkRect2D> sfrRects;
1219 for (deUint32 i = 0; i < m_physicalDeviceCount*m_physicalDeviceCount; i++)
1220 sfrRects.push_back(zeroRect);
1221
1222 if (m_physicalDeviceCount == 1u)
1223 {
1224 sfrRects[0].extent.width = (deInt32)renderSize.x();
1225 sfrRects[0].extent.height = (deInt32)renderSize.y();
1226 }
1227 else
1228 {
1229 // Split into 2 vertical halves
1230 sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID].extent.width = (deInt32)renderSize.x() / 2;
1231 sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID].extent.height = (deInt32)renderSize.y();
1232 sfrRects[firstDeviceID * m_physicalDeviceCount + secondDeviceID] = sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID];
1233 sfrRects[firstDeviceID * m_physicalDeviceCount + secondDeviceID].offset.x = (deInt32)renderSize.x() / 2;
1234 sfrRects[secondDeviceID * m_physicalDeviceCount + firstDeviceID] = sfrRects[firstDeviceID * m_physicalDeviceCount + firstDeviceID];
1235 sfrRects[secondDeviceID * m_physicalDeviceCount + secondDeviceID] = sfrRects[firstDeviceID * m_physicalDeviceCount + secondDeviceID];
1236 }
1237
1238 VkBindImageMemoryDeviceGroupInfo devGroupBindInfo =
1239 {
1240 VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO, // sType
1241 DE_NULL, // pNext
1242 0u, // deviceIndexCount
1243 DE_NULL, // pDeviceIndices
1244 m_physicalDeviceCount*m_physicalDeviceCount, // SFRRectCount
1245 &sfrRects[0], // pSFRRects
1246 };
1247
1248 VkBindImageMemoryInfo bindInfo =
1249 {
1250 VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, // sType
1251 &devGroupBindInfo, // pNext
1252 *renderImage, // image
1253 renderImageMemory.get(), // memory
1254 0u, // memoryOffset
1255 };
1256 VK_CHECK(vk.bindImageMemory2(*m_deviceGroup, 1, &bindInfo));
1257 }
1258
1259 // Begin recording
1260 beginCommandBuffer(vk, *cmdBuffer);
1261
1262 // Update buffers
1263 {
1264 const VkBufferMemoryBarrier stagingVertexBufferUpdateBarrier =
1265 {
1266 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1267 DE_NULL, // const void* pNext;
1268 VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask;
1269 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1270 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1271 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1272 stagingVertexBuffer.get(), // VkBuffer buffer;
1273 0u, // VkDeviceSize offset;
1274 verticesSize // VkDeviceSize size;
1275 };
1276
1277 const VkBufferMemoryBarrier vertexBufferUpdateBarrier =
1278 {
1279 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1280 DE_NULL, // const void* pNext;
1281 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1282 VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, // VkAccessFlags dstAccessMask;
1283 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1284 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1285 vertexBuffer.get(), // VkBuffer buffer;
1286 0u, // VkDeviceSize offset;
1287 verticesSize // VkDeviceSize size;
1288 };
1289
1290 const VkBufferMemoryBarrier stagingIndexBufferUpdateBarrier =
1291 {
1292 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1293 DE_NULL, // const void* pNext;
1294 VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask;
1295 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1296 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1297 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1298 stagingIndexBuffer.get(), // VkBuffer buffer;
1299 0u, // VkDeviceSize offset;
1300 indicesSize // VkDeviceSize size;
1301 };
1302
1303 const VkBufferMemoryBarrier indexBufferUpdateBarrier =
1304 {
1305 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1306 DE_NULL, // const void* pNext;
1307 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1308 VK_ACCESS_INDEX_READ_BIT, // VkAccessFlags dstAccessMask;
1309 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1310 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1311 indexBuffer.get(), // VkBuffer buffer;
1312 0u, // VkDeviceSize offset;
1313 indicesSize // VkDeviceSize size;
1314 };
1315
1316 const VkBufferMemoryBarrier stagingUboBufferUpdateBarrier =
1317 {
1318 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1319 DE_NULL, // const void* pNext;
1320 VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask;
1321 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1322 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1323 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1324 stagingUniformBuffer.get(), // VkBuffer buffer;
1325 0u, // VkDeviceSize offset;
1326 indicesSize // VkDeviceSize size;
1327 };
1328
1329 const VkBufferMemoryBarrier uboUpdateBarrier =
1330 {
1331 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1332 DE_NULL, // const void* pNext;
1333 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1334 VK_ACCESS_UNIFORM_READ_BIT, // VkAccessFlags dstAccessMask;
1335 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1336 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1337 uniformBuffer.get(), // VkBuffer buffer;
1338 0u, // VkDeviceSize offset;
1339 sizeof(drawColor) // VkDeviceSize size;
1340 };
1341
1342
1343 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &stagingVertexBufferUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1344 VkBufferCopy vertexBufferCopy = { 0u, 0u, verticesSize };
1345 vk.cmdCopyBuffer(*cmdBuffer, stagingVertexBuffer.get(), vertexBuffer.get(), 1u, &vertexBufferCopy);
1346 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &vertexBufferUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1347
1348 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &stagingIndexBufferUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1349 VkBufferCopy indexBufferCopy = { 0u, 0u, indicesSize };
1350 vk.cmdCopyBuffer(*cmdBuffer, stagingIndexBuffer.get(), indexBuffer.get(), 1u, &indexBufferCopy);
1351 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &indexBufferUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1352
1353 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &stagingUboBufferUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1354 VkBufferCopy uboBufferCopy = { 0u, 0u, sizeof(drawColor) };
1355 vk.cmdCopyBuffer(*cmdBuffer, stagingUniformBuffer.get(), uniformBuffer.get(), 1u, &uboBufferCopy);
1356 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &uboUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1357
1358 if (m_drawTessellatedSphere)
1359 {
1360 const VkBufferMemoryBarrier stagingsboUpdateBarrier =
1361 {
1362 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1363 DE_NULL, // const void* pNext;
1364 VK_ACCESS_HOST_WRITE_BIT, // VkAccessFlags srcAccessMask;
1365 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1366 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1367 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1368 stagingSboBuffer.get(), // VkBuffer buffer;
1369 0u, // VkDeviceSize offset;
1370 sizeof(tessLevel) // VkDeviceSize size;
1371 };
1372
1373 const VkBufferMemoryBarrier sboUpdateBarrier =
1374 {
1375 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // VkStructureType sType;
1376 DE_NULL, // const void* pNext;
1377 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1378 VK_ACCESS_SHADER_READ_BIT, // VkAccessFlags dstAccessMask;
1379 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1380 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1381 sboBuffer.get(), // VkBuffer buffer;
1382 0u, // VkDeviceSize offset;
1383 sizeof(tessLevel) // VkDeviceSize size;
1384 };
1385
1386 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &stagingsboUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1387 VkBufferCopy sboBufferCopy = { 0u, 0u, sizeof(tessLevel) };
1388 vk.cmdCopyBuffer(*cmdBuffer, stagingSboBuffer.get(), sboBuffer.get(), 1u, &sboBufferCopy);
1389 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, &sboUpdateBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1390 }
1391
1392 vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1393 vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1, &*descriptorSet, 0u, DE_NULL);
1394 {
1395 const VkDeviceSize bindingOffset = 0;
1396 vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &bindingOffset);
1397 vk.cmdBindIndexBuffer(*cmdBuffer, *indexBuffer, 0, VK_INDEX_TYPE_UINT32);
1398 }
1399 }
1400
1401 // Begin renderpass
1402 {
1403 const VkClearValue clearValue = makeClearValueColorF32(
1404 clearColor[0],
1405 clearColor[1],
1406 clearColor[2],
1407 clearColor[3]);
1408
1409 VkRect2D zeroRect = { { 0, 0, },{ 0, 0, } };
1410 vector<VkRect2D> renderAreas;
1411 for (deUint32 i = 0; i < m_physicalDeviceCount; i++)
1412 renderAreas.push_back(zeroRect);
1413
1414 // Render completely if there is only 1 device
1415 if (m_physicalDeviceCount == 1u)
1416 {
1417 renderAreas[0].extent.width = (deInt32)renderSize.x();
1418 renderAreas[0].extent.height = (deInt32)renderSize.y();
1419 }
1420 else
1421 {
1422 // Split into 2 vertical halves
1423 renderAreas[firstDeviceID].extent.width = (deInt32)renderSize.x() / 2;
1424 renderAreas[firstDeviceID].extent.height = (deInt32)renderSize.y();
1425 renderAreas[secondDeviceID] = renderAreas[firstDeviceID];
1426 renderAreas[secondDeviceID].offset.x = (deInt32)renderSize.x() / 2;
1427 }
1428
1429 const VkDeviceGroupRenderPassBeginInfo deviceGroupRPBeginInfo =
1430 {
1431 VK_STRUCTURE_TYPE_DEVICE_GROUP_RENDER_PASS_BEGIN_INFO,
1432 DE_NULL,
1433 (deUint32)((1 << m_physicalDeviceCount) - 1),
1434 m_physicalDeviceCount,
1435 &renderAreas[0]
1436 };
1437
1438 const VkRenderPassBeginInfo passBeginParams =
1439 {
1440 VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, // sType
1441 (m_testMode & TEST_MODE_SFR) ? &deviceGroupRPBeginInfo : DE_NULL, // pNext
1442 *renderPass, // renderPass
1443 *framebuffer, // framebuffer
1444 {
1445 { 0, 0 },
1446 { renderSize.x(), renderSize.y() }
1447 }, // renderArea
1448 1u, // clearValueCount
1449 &clearValue, // pClearValues
1450 };
1451 vk.cmdBeginRenderPass(*cmdBuffer, &passBeginParams, VK_SUBPASS_CONTENTS_INLINE);
1452 }
1453
1454 // Draw
1455 if (m_testMode & TEST_MODE_AFR)
1456 {
1457 vk.cmdSetDeviceMask(*cmdBuffer, 1 << secondDeviceID);
1458 vk.cmdDrawIndexed(*cmdBuffer, numIndices, 1u, 0, 0, 0);
1459
1460 }
1461 else
1462 {
1463 vk.cmdSetDeviceMask(*cmdBuffer, ((1 << firstDeviceID) | (1 << secondDeviceID)));
1464 vk.cmdDrawIndexed(*cmdBuffer, numIndices, 1u, 0, 0, 0);
1465 }
1466 endRenderPass(vk, *cmdBuffer);
1467
1468 // Change image layout for copy
1469 {
1470 const VkImageMemoryBarrier renderFinishBarrier =
1471 {
1472 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // sType
1473 DE_NULL, // pNext
1474 VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, // outputMask
1475 VK_ACCESS_TRANSFER_READ_BIT, // inputMask
1476 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, // oldLayout
1477 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // newLayout
1478 queueFamilyIndex, // srcQueueFamilyIndex
1479 queueFamilyIndex, // dstQueueFamilyIndex
1480 *renderImage, // image
1481 {
1482 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
1483 0u, // baseMipLevel
1484 1u, // mipLevels
1485 0u, // baseArraySlice
1486 1u, // arraySize
1487 } // subresourceRange
1488 };
1489 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &renderFinishBarrier);
1490 }
1491
1492 endCommandBuffer(vk, *cmdBuffer);
1493
1494 // Submit & wait for completion
1495 {
1496 const deUint32 deviceMask = (1 << firstDeviceID) | (1 << secondDeviceID);
1497 submitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceMask);
1498 m_context.resetCommandPoolForVKSC(*m_deviceGroup, *cmdPool);
1499 }
1500
1501 // Copy image from secondDeviceID in case of AFR and SFR(only if Peer memory as copy source is not allowed)
1502 if ((m_physicalDeviceCount > 1) && ((m_testMode & TEST_MODE_AFR) || (!isPeerMemAsCopySrcAllowed)))
1503 {
1504 Move<VkImage> peerImage;
1505
1506 // Create and bind peer image
1507 {
1508 const VkImageCreateInfo peerImageParams =
1509 {
1510 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // sType
1511 DE_NULL, // pNext
1512 VK_IMAGE_CREATE_ALIAS_BIT, // flags
1513 VK_IMAGE_TYPE_2D, // imageType
1514 colorFormat, // format
1515 { renderSize.x(), renderSize.y(), 1 }, // extent
1516 1u, // mipLevels
1517 1u, // arraySize
1518 VK_SAMPLE_COUNT_1_BIT, // samples
1519 VK_IMAGE_TILING_OPTIMAL, // tiling
1520 imageUsageFlag, // usage
1521 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
1522 1u, // queueFamilyIndexCount
1523 &queueFamilyIndex, // pQueueFamilyIndices
1524 VK_IMAGE_LAYOUT_UNDEFINED, // initialLayout
1525 };
1526 peerImage = createImage(vk, *m_deviceGroup, &peerImageParams);
1527
1528 VkBindImageMemoryDeviceGroupInfo devGroupBindInfo =
1529 {
1530 VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_DEVICE_GROUP_INFO, // sType
1531 DE_NULL, // pNext
1532 m_physicalDeviceCount, // deviceIndexCount
1533 &deviceIndices[0], // pDeviceIndices
1534 0u, // SFRRectCount
1535 DE_NULL, // pSFRRects
1536 };
1537
1538 VkBindImageMemoryInfo bindInfo =
1539 {
1540 VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO, // sType
1541 &devGroupBindInfo, // pNext
1542 peerImage.get(), // image
1543 renderImageMemory.get(), // memory
1544 0u, // memoryOffset
1545 };
1546 VK_CHECK(vk.bindImageMemory2(*m_deviceGroup, 1, &bindInfo));
1547 }
1548
1549 // Copy peer image (only needed in SFR case when peer memory as copy source is not allowed)
1550 {
1551 // Change layout on firstDeviceID
1552 {
1553 const VkImageMemoryBarrier preCopyBarrier =
1554 {
1555 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1556 DE_NULL, // const void* pNext;
1557 0, // VkAccessFlags srcAccessMask;
1558 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags dstAccessMask;
1559 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout oldLayout;
1560 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout newLayout;
1561 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1562 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1563 *renderImage, // VkImage image;
1564 { // VkImageSubresourceRange subresourceRange;
1565 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1566 0u, // deUint32 baseMipLevel;
1567 1u, // deUint32 mipLevels;
1568 0u, // deUint32 baseArraySlice;
1569 1u // deUint32 arraySize;
1570 }
1571 };
1572
1573 beginCommandBuffer(vk, *cmdBuffer);
1574 vk.cmdSetDeviceMask(*cmdBuffer, 1 << firstDeviceID);
1575 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1u, &preCopyBarrier);
1576 endCommandBuffer(vk, *cmdBuffer);
1577
1578 const deUint32 deviceMask = 1 << firstDeviceID;
1579 submitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceMask);
1580 m_context.resetCommandPoolForVKSC(*m_deviceGroup, *cmdPool);
1581 }
1582
1583 // Copy Image from secondDeviceID to firstDeviceID
1584 {
1585 // AFR: Copy entire image from secondDeviceID
1586 // SFR: Copy the right half of image from secondDeviceID to firstDeviceID, so that the copy
1587 // to a buffer below (for checking) does not require VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT
1588 deInt32 imageOffsetX = (m_testMode & TEST_MODE_AFR) ? 0 : renderSize.x() / 2;
1589 deUint32 imageExtentX = (m_testMode & TEST_MODE_AFR) ? (deUint32)renderSize.x() : (deUint32)renderSize.x() / 2;
1590
1591 const VkImageCopy imageCopy =
1592 {
1593 {
1594 VK_IMAGE_ASPECT_COLOR_BIT,
1595 0, // mipLevel
1596 0, // arrayLayer
1597 1 // layerCount
1598 },
1599 { imageOffsetX, 0, 0 },
1600 {
1601 VK_IMAGE_ASPECT_COLOR_BIT,
1602 0, // mipLevel
1603 0, // arrayLayer
1604 1 // layerCount
1605 },
1606 { imageOffsetX, 0, 0 },
1607 {
1608 imageExtentX,
1609 (deUint32)renderSize.y(),
1610 1u
1611 }
1612 };
1613
1614 beginCommandBuffer(vk, *cmdBuffer);
1615 vk.cmdSetDeviceMask(*cmdBuffer, 1 << secondDeviceID);
1616 vk.cmdCopyImage(*cmdBuffer, *renderImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *peerImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &imageCopy);
1617 endCommandBuffer(vk, *cmdBuffer);
1618
1619 const deUint32 deviceMask = 1 << secondDeviceID;
1620 submitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceMask);
1621 m_context.resetCommandPoolForVKSC(*m_deviceGroup, *cmdPool);
1622 }
1623
1624 // Change layout back on firstDeviceID
1625 {
1626 const VkImageMemoryBarrier postCopyBarrier =
1627 {
1628 VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType;
1629 DE_NULL, // const void* pNext;
1630 VK_ACCESS_TRANSFER_WRITE_BIT, // VkAccessFlags srcAccessMask;
1631 VK_ACCESS_TRANSFER_READ_BIT, // VkAccessFlags dstAccessMask;
1632 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, // VkImageLayout oldLayout;
1633 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, // VkImageLayout newLayout;
1634 VK_QUEUE_FAMILY_IGNORED, // deUint32 srcQueueFamilyIndex;
1635 VK_QUEUE_FAMILY_IGNORED, // deUint32 dstQueueFamilyIndex;
1636 *renderImage, // VkImage image;
1637 { // VkImageSubresourceRange subresourceRange;
1638 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask;
1639 0u, // deUint32 baseMipLevel;
1640 1u, // deUint32 mipLevels;
1641 0u, // deUint32 baseArraySlice;
1642 1u // deUint32 arraySize;
1643 }
1644 };
1645
1646 beginCommandBuffer(vk, *cmdBuffer);
1647 vk.cmdSetDeviceMask(*cmdBuffer, 1 << firstDeviceID);
1648 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1u, &postCopyBarrier);
1649 endCommandBuffer(vk, *cmdBuffer);
1650
1651 const deUint32 deviceMask = 1 << firstDeviceID;
1652 submitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceMask);
1653 m_context.resetCommandPoolForVKSC(*m_deviceGroup, *cmdPool);
1654 }
1655 }
1656 }
1657
1658 // copy image to read buffer for checking
1659 {
1660 const VkDeviceSize imageSizeBytes = (VkDeviceSize)(sizeof(deUint32) * renderSize.x() * renderSize.y());
1661 const VkBufferCreateInfo readImageBufferParams =
1662 {
1663 VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // sType
1664 DE_NULL, // pNext
1665 (VkBufferCreateFlags)0u, // flags
1666 imageSizeBytes, // size
1667 VK_BUFFER_USAGE_TRANSFER_DST_BIT, // usage
1668 VK_SHARING_MODE_EXCLUSIVE, // sharingMode
1669 1u, // queueFamilyIndexCount
1670 &queueFamilyIndex, // pQueueFamilyIndices
1671 };
1672 const Unique<VkBuffer> readImageBuffer(createBuffer(vk, *m_deviceGroup, &readImageBufferParams));
1673 const UniquePtr<Allocation> readImageBufferMemory(memAlloc.allocate(getBufferMemoryRequirements(vk, *m_deviceGroup, *readImageBuffer), MemoryRequirement::HostVisible));
1674 VK_CHECK(vk.bindBufferMemory(*m_deviceGroup, *readImageBuffer, readImageBufferMemory->getMemory(), readImageBufferMemory->getOffset()));
1675
1676 beginCommandBuffer(vk, *cmdBuffer);
1677
1678 // Copy image to buffer
1679 {
1680 const VkBufferImageCopy copyParams =
1681 {
1682 (VkDeviceSize)0u, // bufferOffset
1683 renderSize.x(), // bufferRowLength
1684 renderSize.y(), // bufferImageHeight
1685 {
1686 VK_IMAGE_ASPECT_COLOR_BIT, // aspectMask
1687 0u, // mipLevel
1688 0u, // baseArrayLayer
1689 1u, // layerCount
1690 }, // imageSubresource
1691 { 0, 0, 0 }, // imageOffset
1692 {
1693 renderSize.x(),
1694 renderSize.y(),
1695 1u
1696 } // imageExtent
1697 };
1698
1699 // Use a diffferent binding in SFR when peer memory as copy source is not allowed
1700 vk.cmdCopyImageToBuffer(*cmdBuffer, isPeerMemAsCopySrcAllowed ? *renderImage : *readImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *readImageBuffer, 1u, ©Params);
1701
1702 const VkBufferMemoryBarrier copyFinishBarrier =
1703 {
1704 VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER, // sType
1705 DE_NULL, // pNext
1706 VK_ACCESS_TRANSFER_WRITE_BIT, // srcAccessMask
1707 VK_ACCESS_HOST_READ_BIT, // dstAccessMask
1708 queueFamilyIndex, // srcQueueFamilyIndex
1709 queueFamilyIndex, // dstQueueFamilyIndex
1710 *readImageBuffer, // buffer
1711 0u, // offset
1712 imageSizeBytes // size
1713 };
1714 vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 1, ©FinishBarrier, 0, (const VkImageMemoryBarrier*)DE_NULL);
1715 }
1716 endCommandBuffer(vk, *cmdBuffer);
1717
1718 // Submit & wait for completion
1719 {
1720 const deUint32 deviceMask = 1 << firstDeviceID;
1721 submitBufferAndWaitForIdle(vk, cmdBuffer.get(), deviceMask);
1722 m_context.resetCommandPoolForVKSC(*m_deviceGroup, *cmdPool);
1723 }
1724
1725 // Read results and check against reference image
1726 if (m_drawTessellatedSphere)
1727 {
1728 const tcu::TextureFormat tcuFormat = vk::mapVkFormat(colorFormat);
1729 const tcu::ConstPixelBufferAccess resultAccess(tcuFormat, renderSize.x(), renderSize.y(), 1, readImageBufferMemory->getHostPtr());
1730 invalidateAlloc(vk, *m_deviceGroup, *readImageBufferMemory);
1731
1732 tcu::TextureLevel referenceImage;
1733 string refImage = m_fillModeNonSolid ? "vulkan/data/device_group/sphere.png" : "vulkan/data/device_group/spherefilled.png";
1734 tcu::ImageIO::loadPNG(referenceImage, m_context.getTestContext().getArchive(), refImage.c_str());
1735 iterateResultSuccess = tcu::fuzzyCompare(m_context.getTestContext().getLog(), "ImageComparison", "Image Comparison",
1736 referenceImage.getAccess(), resultAccess, 0.001f, tcu::COMPARE_LOG_RESULT);
1737 }
1738 else
1739 {
1740 const tcu::TextureFormat tcuFormat = vk::mapVkFormat(colorFormat);
1741 const tcu::ConstPixelBufferAccess resultAccess(tcuFormat, renderSize.x(), renderSize.y(), 1, readImageBufferMemory->getHostPtr());
1742 invalidateAlloc(vk, *m_deviceGroup, *readImageBufferMemory);
1743
1744 // Render reference and compare
1745 {
1746 tcu::TextureLevel refImage(tcuFormat, (deInt32)renderSize.x(), (deInt32)renderSize.y());
1747 const tcu::UVec4 threshold(0u);
1748 const tcu::IVec3 posDeviation(1, 1, 0);
1749
1750 tcu::clear(refImage.getAccess(), clearColor);
1751 renderReferenceTriangle(refImage.getAccess(), triVertices, m_context.getDeviceProperties().limits.subPixelPrecisionBits);
1752
1753 iterateResultSuccess = tcu::intThresholdPositionDeviationCompare(m_context.getTestContext().getLog(),
1754 "ComparisonResult",
1755 "Image comparison result",
1756 refImage.getAccess(),
1757 resultAccess,
1758 threshold,
1759 posDeviation,
1760 false,
1761 tcu::COMPARE_LOG_RESULT);
1762 }
1763 }
1764 }
1765
1766 if (!iterateResultSuccess)
1767 return tcu::TestStatus::fail("Image comparison failed");
1768 }
1769
1770 return tcu::TestStatus(QP_TEST_RESULT_PASS, "Device group verification passed");
1771 }
1772
1773 template<class Instance>
1774 class DeviceGroupTestCase : public TestCase
1775 {
1776 public:
DeviceGroupTestCase(tcu::TestContext & context,const char * name,const char * description,deUint32 mode)1777 DeviceGroupTestCase (tcu::TestContext& context,
1778 const char* name,
1779 const char* description,
1780 deUint32 mode)
1781 : TestCase(context, name, description)
1782 , m_testMode (mode)
1783 {}
1784
1785 private:
1786
1787 deUint32 m_testMode;
1788
createInstance(Context & context) const1789 TestInstance* createInstance (Context& context) const
1790 {
1791 return new Instance(context, m_testMode);
1792 }
1793
initPrograms(vk::SourceCollections & programCollection) const1794 void initPrograms (vk::SourceCollections& programCollection) const
1795 {
1796 programCollection.glslSources.add("vert") << glu::VertexSource("#version 430\n"
1797 "layout(location = 0) in vec4 in_Position;\n"
1798 "out gl_PerVertex { vec4 gl_Position; float gl_PointSize; };\n"
1799 "void main() {\n"
1800 " gl_Position = in_Position;\n"
1801 " gl_PointSize = 1.0;\n"
1802 "}\n");
1803
1804 if (m_testMode & TEST_MODE_TESSELLATION)
1805 {
1806 programCollection.glslSources.add("tesc") << glu::TessellationControlSource("#version 450\n"
1807 "#extension GL_EXT_tessellation_shader : require\n"
1808 "layout(vertices=3) out;\n"
1809 "layout(set=0, binding=1) buffer tessLevel { \n"
1810 " float tessLvl;\n"
1811 "};\n"
1812 "void main()\n"
1813 "{\n"
1814 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1815 " if (gl_InvocationID == 0) {\n"
1816 " for (int i = 0; i < 4; i++)\n"
1817 " gl_TessLevelOuter[i] = tessLvl;\n"
1818 " for (int i = 0; i < 2; i++)\n"
1819 " gl_TessLevelInner[i] = tessLvl;\n"
1820 " }\n"
1821 "}\n");
1822
1823 programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource("#version 450\n"
1824 "#extension GL_EXT_tessellation_shader : require\n"
1825 "layout(triangles) in;\n"
1826 "layout(equal_spacing) in;\n"
1827 "layout(ccw) in;\n"
1828 "void main()\n"
1829 "{\n"
1830 " vec4 pos = vec4(0, 0, 0, 0);\n"
1831 " vec3 tessCoord = gl_TessCoord.xyz;\n"
1832 " pos += tessCoord.z * gl_in[0].gl_Position;\n"
1833 " pos += tessCoord.x * gl_in[1].gl_Position;\n"
1834 " pos += tessCoord.y * gl_in[2].gl_Position;\n"
1835 " vec3 sign = sign(pos.xyz);\n"
1836 " pos.xyz = 0.785398 - abs(pos.xyz) * 1.5707963;\n"
1837 " pos.xyz = (1 - tan(pos.xyz))/2.0;\n"
1838 " pos.xyz = (sign * pos.xyz) / length(pos.xyz);\n"
1839 " gl_Position = pos;\n"
1840 "}\n");
1841 }
1842
1843 programCollection.glslSources.add("frag") << glu::FragmentSource("#version 430\n"
1844 "layout(location = 0) out vec4 out_FragColor;\n"
1845 "layout(std140, set=0, binding=0) uniform bufferData { \n"
1846 " vec4 color;\n"
1847 "};\n"
1848 "void main()\n"
1849 "{\n"
1850 " out_FragColor = color;\n"
1851 "}\n");
1852 }
1853 };
1854
1855 } //anonymous
1856
1857 class DeviceGroupTestRendering : public tcu::TestCaseGroup
1858 {
1859 public:
1860 DeviceGroupTestRendering (tcu::TestContext& testCtx);
~DeviceGroupTestRendering(void)1861 ~DeviceGroupTestRendering (void) {}
1862 void init(void);
1863
1864 private:
1865 DeviceGroupTestRendering (const DeviceGroupTestRendering& other);
1866 DeviceGroupTestRendering& operator= (const DeviceGroupTestRendering& other);
1867 };
1868
DeviceGroupTestRendering(tcu::TestContext & testCtx)1869 DeviceGroupTestRendering::DeviceGroupTestRendering (tcu::TestContext& testCtx)
1870 : TestCaseGroup (testCtx, "device_group", "Testing device group test cases")
1871 {
1872 // Left blank on purpose
1873 }
1874
init(void)1875 void DeviceGroupTestRendering::init (void)
1876 {
1877 #ifndef CTS_USES_VULKANSC
1878 addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "sfr", "Test split frame rendering", TEST_MODE_SFR));
1879 addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "sfr_sys", "Test split frame rendering with render target in host memory", TEST_MODE_SFR | TEST_MODE_HOSTMEMORY));
1880 addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "sfr_dedicated", "Test split frame rendering with dedicated memory allocations", TEST_MODE_SFR | TEST_MODE_DEDICATED));
1881 addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "sfr_dedicated_peer", "Test split frame rendering with dedicated memory allocations and peer fetching", TEST_MODE_SFR | TEST_MODE_DEDICATED | TEST_MODE_PEER_FETCH));
1882 #endif // CTS_USES_VULKANSC
1883
1884 addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "afr", "Test alternate frame rendering", TEST_MODE_AFR));
1885 addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "afr_sys", "Test split frame rendering with render target in host memory", TEST_MODE_AFR | TEST_MODE_HOSTMEMORY));
1886 addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "afr_dedicated", "Test split frame rendering with dedicated memory allocations", TEST_MODE_AFR | TEST_MODE_DEDICATED));
1887 addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "afr_dedicated_peer", "Test split frame rendering with dedicated memory allocations and peer fetching", TEST_MODE_AFR | TEST_MODE_DEDICATED | TEST_MODE_PEER_FETCH));
1888
1889 #ifndef CTS_USES_VULKANSC
1890 addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "sfr_tessellated", "Test split frame rendering with tessellated sphere", TEST_MODE_SFR | TEST_MODE_TESSELLATION | TEST_MODE_DEDICATED | TEST_MODE_PEER_FETCH));
1891 addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "sfr_tessellated_linefill", "Test split frame rendering with tessellated sphere with line segments", TEST_MODE_SFR | TEST_MODE_TESSELLATION | TEST_MODE_LINEFILL | TEST_MODE_DEDICATED | TEST_MODE_PEER_FETCH));
1892 #endif // CTS_USES_VULKANSC
1893 addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "afr_tessellated", "Test alternate frame rendering with tesselated sphere", TEST_MODE_AFR | TEST_MODE_TESSELLATION | TEST_MODE_DEDICATED | TEST_MODE_PEER_FETCH));
1894 addChild(new DeviceGroupTestCase<DeviceGroupTestInstance>(m_testCtx, "afr_tessellated_linefill", "Test alternate frame rendering with tesselated sphere with line segments", TEST_MODE_AFR | TEST_MODE_TESSELLATION | TEST_MODE_LINEFILL | TEST_MODE_DEDICATED | TEST_MODE_PEER_FETCH));
1895 }
1896
createTests(tcu::TestContext & testCtx)1897 tcu::TestCaseGroup* createTests(tcu::TestContext& testCtx)
1898 {
1899 return new DeviceGroupTestRendering(testCtx);
1900 }
1901 } // DeviceGroup
1902 } // vkt
1903