+
+// Class to wrap singleton devices used by private_data tests
+class SingletonDevice
+{
+ Move<VkDevice> createPrivateDataDevice(const Context &context, int idx)
+ {
+ const int requestedSlots[NUM_DEVICES][2] =
+ {
+ {0, 0},
+ {1, 0},
+ {1, 1},
+ {4, 4},
+ {1, 100},
+ };
+
+ const float queuePriority = 1.0;
+ const VkDeviceQueueCreateInfo queues[] =
+ {
+ {
+ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+ DE_NULL,
+ (VkDeviceQueueCreateFlags)0,
+ context.getUniversalQueueFamilyIndex(),
+ 1u, // queueCount
+ &queuePriority, // pQueuePriorities
+ }
+ };
+
+ VkDevicePrivateDataCreateInfoEXT pdci0 =
+ {
+ VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // uint32_t privateDataSlotRequestCount;
+ };
+ VkDevicePrivateDataCreateInfoEXT pdci1 =
+ {
+ VK_STRUCTURE_TYPE_DEVICE_PRIVATE_DATA_CREATE_INFO_EXT, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // uint32_t privateDataSlotRequestCount;
+ };
+ void *pNext = DE_NULL;
+
+ if (requestedSlots[idx][0])
+ {
+ pNext = &pdci0;
+ pdci0.privateDataSlotRequestCount = requestedSlots[idx][0];
+ if (requestedSlots[idx][1])
+ {
+ pdci0.pNext = &pdci1;
+ pdci1.privateDataSlotRequestCount = requestedSlots[idx][1];
+ }
+ }
+
+ VkPhysicalDevicePrivateDataFeaturesEXT privateDataFeatures =
+ {
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT, // VkStructureType sType;
+ pNext, // void* pNext;
+ VK_TRUE, // VkBool32 privateData;
+ };
+ pNext = &privateDataFeatures;
+
+ const char *extName = "VK_EXT_private_data";
+
+ const VkDeviceCreateInfo deviceInfo =
+ {
+ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+ pNext,
+ (VkDeviceCreateFlags)0,
+ DE_LENGTH_OF_ARRAY(queues),
+ queues,
+ 0u, // enabledLayerNameCount
+ DE_NULL, // ppEnabledLayerNames
+ 1u, // enabledExtensionNameCount
+ &extName, // ppEnabledExtensionNames
+ DE_NULL, // pEnabledFeatures
+ };
+
+ Move<VkDevice> device = createCustomDevice(context.getTestContext().getCommandLine().isValidationEnabled(),
+ context.getPlatformInterface(), context.getInstance(), context.getInstanceInterface(), context.getPhysicalDevice(), &deviceInfo, DE_NULL);
+ return device;
+ }
+
+ SingletonDevice (const Context& context, int idx)
+ : m_logicalDevice (createPrivateDataDevice(context, idx))
+ {
+ }
+
+
+public:
+
+ static const int NUM_DEVICES = 5;
+
+ static const Unique<vk::VkDevice>& getDevice(const Context& context, int idx)
+ {
+ if (!m_singletonDevice[idx])
+ m_singletonDevice[idx] = SharedPtr<SingletonDevice>(new SingletonDevice(context, idx));
+
+ DE_ASSERT(m_singletonDevice[idx]);
+ return m_singletonDevice[idx]->m_logicalDevice;
+ }
+
+ static void destroy()
+ {
+ for (int idx = 0; idx < NUM_DEVICES; ++idx)
+ m_singletonDevice[idx].clear();
+ }
+
+private:
+ const Unique<vk::VkDevice> m_logicalDevice;
+ static SharedPtr<SingletonDevice> m_singletonDevice[NUM_DEVICES];
+};
+
+SharedPtr<SingletonDevice> SingletonDevice::m_singletonDevice[NUM_DEVICES];
+
+template<typename T> static deUint64 HandleToInt(T t) { return t.getInternal(); }
+template<typename T> static deUint64 HandleToInt(T *t) { return (deUint64)(deUintptr)(t); }
+
+template<typename Object>
+tcu::TestStatus createPrivateDataTest (Context& context, typename Object::Parameters params)
+{
+ if (!context.getPrivateDataFeaturesEXT().privateData)
+ TCU_THROW(NotSupportedError, "privateData not supported");
+
+ for (int d = 0; d < SingletonDevice::NUM_DEVICES; ++d)
+ {
+ const Unique<vk::VkDevice>& device = SingletonDevice::getDevice(context, d);
+ const Environment env (context.getPlatformInterface(),
+ context.getUsedApiVersion(),
+ context.getInstanceInterface(),
+ context.getInstance(),
+ context.getDeviceInterface(),
+ *device,
+ context.getUniversalQueueFamilyIndex(),
+ context.getBinaryCollection(),
+ DE_NULL,
+ 4u,
+ context.getTestContext().getCommandLine());
+
+ const typename Object::Resources res (env, params);
+
+ const VkPrivateDataSlotCreateInfoEXT createInfo =
+ {
+ VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT, // VkStructureType sType;
+ DE_NULL, // const void* pNext;
+ 0u, // VkPrivateDataSlotCreateFlagsEXT flags;
+ };
+
+ const int numSlots = 100;
+
+ typedef Unique<VkPrivateDataSlotEXT> PrivateDataSlotUp;
+ typedef SharedPtr<PrivateDataSlotUp> PrivateDataSlotSp;
+ vector<PrivateDataSlotSp> slots;
+
+ // interleave allocating objects and slots
+ for (int i = 0; i < numSlots / 2; ++i)
+ {
+ Move<VkPrivateDataSlotEXT> s = createPrivateDataSlotEXT(env.vkd, *device, &createInfo, DE_NULL);
+ slots.push_back(PrivateDataSlotSp(new PrivateDataSlotUp(s)));
+ }
+
+ Unique<typename Object::Type> obj0 (Object::create(env, res, params));
+ Unique<typename Object::Type> obj1 (Object::create(env, res, params));
+
+ for (int i = numSlots / 2; i < numSlots; ++i)
+ {
+ Move<VkPrivateDataSlotEXT> s = createPrivateDataSlotEXT(env.vkd, *device, &createInfo, DE_NULL);
+ slots.push_back(PrivateDataSlotSp(new PrivateDataSlotUp(s)));
+ }
+
+ Unique<typename Object::Type> obj2 (Object::create(env, res, params));
+ Unique<typename Object::Type> obj3 (Object::create(env, res, params));
+
+ Unique<typename Object::Type> *objs[4] = { &obj0, &obj1, &obj2, &obj3 };
+
+ for (int r = 0; r < 3; ++r)
+ {
+ deUint64 data;
+
+ // Test private data for the objects
+ for (int o = 0; o < 4; ++o)
+ {
+ auto &obj = *objs[o];
+ for (int i = 0; i < numSlots; ++i)
+ {
+ data = 1234;
+ env.vkd.getPrivateDataEXT(*device, getObjectType<typename Object::Type>(), HandleToInt(obj.get()), **slots[i], &data);
+ if (data != 0)
+ return tcu::TestStatus::fail("Expected initial value of zero");
+ }
+ }
+ for (int o = 0; o < 4; ++o)
+ {
+ auto &obj = *objs[o];
+ for (int i = 0; i < numSlots; ++i)
+ VK_CHECK(env.vkd.setPrivateDataEXT(*device, getObjectType<typename Object::Type>(), HandleToInt(obj.get()), **slots[i], i*i*i + o*o + 1));
+ }
+ for (int o = 0; o < 4; ++o)
+ {
+ auto &obj = *objs[o];
+ for (int i = 0; i < numSlots; ++i)
+ {
+ data = 1234;
+ env.vkd.getPrivateDataEXT(*device, getObjectType<typename Object::Type>(), HandleToInt(obj.get()), **slots[i], &data);
+ if (data != (deUint64)(i*i*i + o*o + 1))
+ return tcu::TestStatus::fail("Didn't read back set value");
+ }
+ }
+
+
+ // Test private data for the private data objects
+ for (int o = 0; o < numSlots; ++o)
+ {
+ auto &obj = **slots[o];
+ for (int i = 0; i < numSlots; ++i)
+ {
+ data = 1234;
+ env.vkd.getPrivateDataEXT(*device, VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT, HandleToInt<VkPrivateDataSlotEXT>(obj), **slots[i], &data);
+ if (data != 0)
+ return tcu::TestStatus::fail("Expected initial value of zero");
+ }
+ }
+ for (int o = 0; o < numSlots; ++o)
+ {
+ auto &obj = **slots[o];
+ for (int i = 0; i < numSlots; ++i)
+ VK_CHECK(env.vkd.setPrivateDataEXT(*device, VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT, HandleToInt<VkPrivateDataSlotEXT>(obj), **slots[i], i*i*i + o*o + 1));
+ }
+ for (int o = 0; o < numSlots; ++o)
+ {
+ auto &obj = **slots[o];
+ for (int i = 0; i < numSlots; ++i)
+ {
+ data = 1234;
+ env.vkd.getPrivateDataEXT(*device, VK_OBJECT_TYPE_PRIVATE_DATA_SLOT_EXT, HandleToInt<VkPrivateDataSlotEXT>(obj), **slots[i], &data);
+ if (data != (deUint64)(i*i*i + o*o + 1))
+ return tcu::TestStatus::fail("Didn't read back set value");
+ }
+ }
+
+ // Test private data for the device
+ for (int i = 0; i < numSlots; ++i)
+ {
+ data = 1234;
+ env.vkd.getPrivateDataEXT(*device, VK_OBJECT_TYPE_DEVICE, (deUint64)(deUintptr)(*device), **slots[i], &data);
+ if (data != 0)
+ return tcu::TestStatus::fail("Expected initial value of zero for device");
+ }
+ for (int i = 0; i < numSlots; ++i)
+ VK_CHECK(env.vkd.setPrivateDataEXT(*device, VK_OBJECT_TYPE_DEVICE, (deUint64)(deUintptr)(*device), **slots[i], i*i*i + r*r + 1));
+ for (int i = 0; i < numSlots; ++i)
+ {
+ data = 1234;
+ env.vkd.getPrivateDataEXT(*device, VK_OBJECT_TYPE_DEVICE, (deUint64)(deUintptr)(*device), **slots[i], &data);
+ if (data != (deUint64)(i*i*i + r*r + 1))
+ return tcu::TestStatus::fail("Didn't read back set value from device");
+ }
+
+ // Destroy and realloc slots for the next iteration
+ slots.clear();
+ for (int i = 0; i < numSlots; ++i)
+ {
+ Move<VkPrivateDataSlotEXT> s = createPrivateDataSlotEXT(env.vkd, *device, &createInfo, DE_NULL);
+ slots.push_back(PrivateDataSlotSp(new PrivateDataSlotUp(s)));
+ }
+ }
+ }
+
+ return tcu::TestStatus::pass("Ok");
+}
+