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