mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-19 06:09:01 +00:00
Fixes vulkan validation layer error: Vulkan validation layer: Validation Error: [ VUID-VkShaderModuleCreateInfo-pCode-08740 ] | MessageID = 0x6e224e9 | vkCreateComputePipelines(): pCreateInfos[0].stage SPIR-V Capability Int8 was declared, but one of the following requirements is required (VkPhysicalDeviceVulkan12Features::shaderInt8). The Vulkan spec states: If pCode is a pointer to SPIR-V code, and pCode declares any of the capabilities listed in the SPIR-V Environment appendix, one of the corresponding requirements must be satisfied (https://vulkan.lunarg.com/doc/view/1.3.275.0/linux/1.3-extensions/vkspec.html#VUID-VkShaderModuleCreateInfo-pCode-08740)
2615 lines
94 KiB
C++
2615 lines
94 KiB
C++
//
|
|
// Copyright (c) 2022 The Khronos Group Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
//
|
|
|
|
#ifdef _WIN32
|
|
#include <Windows.h>
|
|
#include <dxgi1_2.h>
|
|
#include <aclapi.h>
|
|
#include <algorithm>
|
|
#endif
|
|
#include <vulkan/vulkan.h>
|
|
#include "vulkan_wrapper.hpp"
|
|
#if defined(__linux__) && !defined(__ANDROID__)
|
|
#include <gnu/libc-version.h>
|
|
#include <dlfcn.h>
|
|
#elif defined(__ANDROID__)
|
|
#include <dlfcn.h>
|
|
#endif
|
|
#if defined _WIN32
|
|
#define LoadFunction GetProcAddress
|
|
#elif defined __linux
|
|
#define LoadFunction dlsym
|
|
#endif
|
|
|
|
extern "C" {
|
|
#define VK_FUNC_DECL(name) PFN_##name _##name = NULL;
|
|
VK_FUNC_LIST
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
VK_WINDOWS_FUNC_LIST
|
|
#endif
|
|
#undef VK_FUNC_DECL
|
|
}
|
|
|
|
#define WAIVED 2
|
|
#define HANDLE_ERROR -1
|
|
|
|
#define CHECK_VK(call) \
|
|
if (call != VK_SUCCESS) return call;
|
|
|
|
static VKAPI_ATTR VkBool32 VKAPI_CALL logCallback(
|
|
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
|
VkDebugUtilsMessageTypeFlagsEXT messageType,
|
|
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData)
|
|
{
|
|
switch (messageSeverity)
|
|
{
|
|
case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT:
|
|
log_error("Vulkan validation layer: %s\n", pCallbackData->pMessage);
|
|
break;
|
|
default:
|
|
log_info("Vulkan validation layer: %s\n", pCallbackData->pMessage);
|
|
break;
|
|
}
|
|
|
|
return VK_FALSE;
|
|
}
|
|
|
|
///////////////////////////////////
|
|
// VulkanInstance implementation //
|
|
///////////////////////////////////
|
|
|
|
VulkanInstance::VulkanInstance(const VulkanInstance &instance)
|
|
: m_vkInstance(instance.m_vkInstance),
|
|
m_physicalDeviceList(instance.m_physicalDeviceList),
|
|
m_useValidationLayers(instance.m_useValidationLayers),
|
|
m_validationLayers(instance.m_validationLayers)
|
|
{}
|
|
|
|
VulkanInstance::VulkanInstance(bool useValidationLayers)
|
|
: m_vkInstance(VK_NULL_HANDLE), m_useValidationLayers(useValidationLayers)
|
|
{
|
|
#if defined(__linux__) && !defined(__ANDROID__)
|
|
char *glibcVersion = strdup(gnu_get_libc_version());
|
|
int majNum = (int)atoi(strtok(glibcVersion, "."));
|
|
int minNum = (int)atoi(strtok(NULL, "."));
|
|
free(glibcVersion);
|
|
if ((majNum < 2) || (majNum == 2 && minNum < 17))
|
|
{
|
|
// WAIVE_TEST() << "Insufficient GLIBC version. Test waived!";
|
|
}
|
|
#endif
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
const char *vulkanLoaderLibraryName = "vulkan-1.dll";
|
|
#elif defined(__ANDROID__)
|
|
const char *vulkanLoaderLibraryName = "libvulkan.so";
|
|
#else
|
|
const char *vulkanLoaderLibraryName = "libvulkan.so.1";
|
|
#endif
|
|
#ifdef _WIN32
|
|
HINSTANCE hDLL;
|
|
hDLL = LoadLibrary(vulkanLoaderLibraryName);
|
|
if (hDLL == NULL)
|
|
{
|
|
throw std::runtime_error("LoadLibrary failed!");
|
|
}
|
|
vkGetInstanceProcAddr =
|
|
(PFN_vkGetInstanceProcAddr)LoadFunction(hDLL, "vkGetInstanceProcAddr");
|
|
#else
|
|
#if !defined(__APPLE__)
|
|
void *handle;
|
|
handle = dlopen(vulkanLoaderLibraryName, RTLD_LAZY);
|
|
if (!handle)
|
|
{
|
|
fputs(dlerror(), stderr);
|
|
throw std::runtime_error("dlopen failed !!!");
|
|
}
|
|
vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)LoadFunction(
|
|
handle, "vkGetInstanceProcAddr");
|
|
#endif
|
|
#endif
|
|
if ((unsigned long long)vkGetInstanceProcAddr == (unsigned long long)NULL)
|
|
{
|
|
throw std::runtime_error("vkGetInstanceProcAddr() not found!");
|
|
}
|
|
#define VK_GET_NULL_INSTANCE_PROC_ADDR(name) \
|
|
_##name = (PFN_##name)vkGetInstanceProcAddr(NULL, #name);
|
|
|
|
if ((unsigned long long)vkGetInstanceProcAddr == (unsigned long long)NULL)
|
|
{
|
|
throw std::runtime_error("Couldn't obtain address for function");
|
|
}
|
|
VK_GET_NULL_INSTANCE_PROC_ADDR(vkEnumerateInstanceExtensionProperties);
|
|
uint32_t instanceExtensionPropertiesCount;
|
|
VkResult vkStatus = VK_SUCCESS;
|
|
vkStatus = vkEnumerateInstanceExtensionProperties(
|
|
NULL, &instanceExtensionPropertiesCount, NULL);
|
|
// Something went wrong in vulkan initialization (most likely incompatible
|
|
// device/driver combination)
|
|
if (vkStatus == VK_ERROR_INCOMPATIBLE_DRIVER)
|
|
{
|
|
throw std::runtime_error(
|
|
"Waiving vulkan test because "
|
|
"vkEnumerateInstanceExtensionProperties failed.");
|
|
// return WAIVED;
|
|
}
|
|
|
|
VK_GET_NULL_INSTANCE_PROC_ADDR(vkGetPhysicalDeviceFeatures2);
|
|
VK_GET_NULL_INSTANCE_PROC_ADDR(vkEnumerateInstanceVersion);
|
|
VK_GET_NULL_INSTANCE_PROC_ADDR(vkEnumerateInstanceLayerProperties);
|
|
VK_GET_NULL_INSTANCE_PROC_ADDR(vkCreateInstance);
|
|
#undef VK_GET_NULL_INSTANCE_PROC_ADDR
|
|
|
|
if (m_useValidationLayers)
|
|
{
|
|
uint32_t layerCount = 0;
|
|
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
|
|
|
|
std::vector<VkLayerProperties> layers(layerCount);
|
|
vkEnumerateInstanceLayerProperties(&layerCount, layers.data());
|
|
|
|
for (auto it = m_validationLayers.begin();
|
|
it != m_validationLayers.end();)
|
|
{
|
|
bool found = false;
|
|
for (const auto &layerProps : layers)
|
|
if (strcmp(*it, layerProps.layerName) == 0)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
if (!found)
|
|
{
|
|
log_info("Vulkan layer not found: %s\n", *it);
|
|
it = m_validationLayers.erase(it);
|
|
}
|
|
else
|
|
++it;
|
|
}
|
|
m_useValidationLayers = !m_validationLayers.empty();
|
|
}
|
|
|
|
VkApplicationInfo vkApplicationInfo = {};
|
|
vkApplicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
|
vkApplicationInfo.pNext = NULL;
|
|
vkApplicationInfo.pApplicationName = "Default app";
|
|
vkApplicationInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
|
|
vkApplicationInfo.pEngineName = "No engine";
|
|
vkApplicationInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
|
|
vkApplicationInfo.apiVersion = VK_API_VERSION_1_1;
|
|
|
|
std::vector<const char *> enabledExtensionNameList;
|
|
enabledExtensionNameList.push_back(
|
|
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
|
enabledExtensionNameList.push_back(
|
|
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
|
|
enabledExtensionNameList.push_back(
|
|
VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
|
|
|
|
if (m_useValidationLayers)
|
|
enabledExtensionNameList.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
|
|
|
std::vector<VkExtensionProperties> vkExtensionPropertiesList(
|
|
instanceExtensionPropertiesCount);
|
|
vkEnumerateInstanceExtensionProperties(NULL,
|
|
&instanceExtensionPropertiesCount,
|
|
vkExtensionPropertiesList.data());
|
|
|
|
for (size_t eenIdx = 0; eenIdx < enabledExtensionNameList.size(); eenIdx++)
|
|
{
|
|
bool isSupported = false;
|
|
for (size_t epIdx = 0; epIdx < vkExtensionPropertiesList.size();
|
|
epIdx++)
|
|
{
|
|
if (!strcmp(enabledExtensionNameList[eenIdx],
|
|
vkExtensionPropertiesList[epIdx].extensionName))
|
|
{
|
|
isSupported = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!isSupported)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
VkInstanceCreateInfo vkInstanceCreateInfo = {};
|
|
vkInstanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
|
vkInstanceCreateInfo.flags = 0;
|
|
vkInstanceCreateInfo.pApplicationInfo = &vkApplicationInfo;
|
|
vkInstanceCreateInfo.ppEnabledLayerNames = NULL;
|
|
vkInstanceCreateInfo.enabledExtensionCount =
|
|
(uint32_t)enabledExtensionNameList.size();
|
|
vkInstanceCreateInfo.ppEnabledExtensionNames =
|
|
enabledExtensionNameList.data();
|
|
vkInstanceCreateInfo.enabledLayerCount = 0;
|
|
vkInstanceCreateInfo.pNext = NULL;
|
|
|
|
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
|
|
if (m_useValidationLayers)
|
|
{
|
|
vkInstanceCreateInfo.enabledLayerCount =
|
|
static_cast<uint32_t>(m_validationLayers.size());
|
|
vkInstanceCreateInfo.ppEnabledLayerNames = m_validationLayers.data();
|
|
|
|
debugCreateInfo.messageType =
|
|
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT
|
|
| VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT
|
|
| VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
|
|
|
debugCreateInfo.sType =
|
|
VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
|
debugCreateInfo.messageSeverity =
|
|
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT
|
|
| VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
|
debugCreateInfo.pfnUserCallback = logCallback;
|
|
|
|
vkInstanceCreateInfo.pNext =
|
|
(VkDebugUtilsMessengerCreateInfoEXT *)&debugCreateInfo;
|
|
}
|
|
|
|
vkCreateInstance(&vkInstanceCreateInfo, NULL, &m_vkInstance);
|
|
|
|
if (m_useValidationLayers)
|
|
{
|
|
_vkCreateDebugUtilsMessengerEXT =
|
|
(PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
|
|
m_vkInstance, "vkCreateDebugUtilsMessengerEXT");
|
|
if (_vkCreateDebugUtilsMessengerEXT != nullptr)
|
|
vkCreateDebugUtilsMessengerEXT(m_vkInstance, &debugCreateInfo,
|
|
nullptr, &m_debugMessenger);
|
|
}
|
|
|
|
#define VK_FUNC_DECL(name) \
|
|
_##name = (PFN_##name)vkGetInstanceProcAddr(m_vkInstance, #name); \
|
|
// ASSERT_NEQ((unsigned long long)name, 0ULL) << "Couldn't obtain address
|
|
// for function" << #name;
|
|
|
|
VK_FUNC_LIST
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
VK_WINDOWS_FUNC_LIST
|
|
#endif
|
|
#undef VK_FUNC_DECL
|
|
|
|
uint32_t physicalDeviceCount = 0;
|
|
vkEnumeratePhysicalDevices(m_vkInstance, &physicalDeviceCount, NULL);
|
|
// CHECK_NEQ(physicalDeviceCount, uint32_t(0));
|
|
|
|
if (physicalDeviceCount == uint32_t(0))
|
|
{
|
|
std::cout << "failed to find GPUs with Vulkan support!\n";
|
|
return;
|
|
}
|
|
|
|
std::vector<VkPhysicalDevice> vkPhysicalDeviceList(physicalDeviceCount,
|
|
VK_NULL_HANDLE);
|
|
vkEnumeratePhysicalDevices(m_vkInstance, &physicalDeviceCount,
|
|
vkPhysicalDeviceList.data());
|
|
|
|
for (size_t ppdIdx = 0; ppdIdx < vkPhysicalDeviceList.size(); ppdIdx++)
|
|
{
|
|
VulkanPhysicalDevice *physicalDevice =
|
|
new VulkanPhysicalDevice(vkPhysicalDeviceList[ppdIdx]);
|
|
m_physicalDeviceList.add(*physicalDevice);
|
|
}
|
|
}
|
|
|
|
VulkanInstance::~VulkanInstance()
|
|
{
|
|
for (size_t pdIdx = 0; pdIdx < m_physicalDeviceList.size(); pdIdx++)
|
|
{
|
|
const VulkanPhysicalDevice &physicalDevice =
|
|
m_physicalDeviceList[pdIdx];
|
|
delete &physicalDevice;
|
|
}
|
|
|
|
_vkDestroyDebugUtilsMessengerEXT =
|
|
(PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
|
|
m_vkInstance, "vkDestroyDebugUtilsMessengerEXT");
|
|
|
|
if (_vkDestroyDebugUtilsMessengerEXT != nullptr)
|
|
{
|
|
vkDestroyDebugUtilsMessengerEXT(m_vkInstance, m_debugMessenger,
|
|
nullptr);
|
|
}
|
|
|
|
if (m_vkInstance)
|
|
{
|
|
vkDestroyInstance(m_vkInstance, NULL);
|
|
}
|
|
}
|
|
|
|
const VulkanPhysicalDeviceList &VulkanInstance::getPhysicalDeviceList() const
|
|
{
|
|
return m_physicalDeviceList;
|
|
}
|
|
|
|
VulkanInstance::operator VkInstance() const { return m_vkInstance; }
|
|
|
|
/////////////////////////////////////////
|
|
// VulkanPhysicalDevice implementation //
|
|
/////////////////////////////////////////
|
|
|
|
VulkanPhysicalDevice::VulkanPhysicalDevice(
|
|
const VulkanPhysicalDevice &physicalDevice)
|
|
: m_vkPhysicalDevice(physicalDevice.m_vkPhysicalDevice),
|
|
m_vkPhysicalDeviceProperties(physicalDevice.m_vkPhysicalDeviceProperties),
|
|
m_vkDeviceNodeMask(physicalDevice.m_vkDeviceNodeMask),
|
|
m_vkPhysicalDeviceFeatures(physicalDevice.m_vkPhysicalDeviceFeatures),
|
|
m_vkPhysicalDeviceMemoryProperties(
|
|
physicalDevice.m_vkPhysicalDeviceMemoryProperties),
|
|
m_queueFamilyList(physicalDevice.m_queueFamilyList)
|
|
{
|
|
memcpy(m_vkDeviceUUID, physicalDevice.m_vkDeviceUUID, VK_UUID_SIZE);
|
|
}
|
|
|
|
VulkanPhysicalDevice::VulkanPhysicalDevice(VkPhysicalDevice vkPhysicalDevice)
|
|
: m_vkPhysicalDevice(vkPhysicalDevice)
|
|
{
|
|
if (m_vkPhysicalDevice == (VkPhysicalDevice)VK_NULL_HANDLE)
|
|
{
|
|
throw std::runtime_error("failed to find a suitable GPU!");
|
|
}
|
|
|
|
vkGetPhysicalDeviceProperties(m_vkPhysicalDevice,
|
|
&m_vkPhysicalDeviceProperties);
|
|
vkGetPhysicalDeviceFeatures(m_vkPhysicalDevice,
|
|
&m_vkPhysicalDeviceFeatures);
|
|
|
|
VkPhysicalDeviceIDPropertiesKHR vkPhysicalDeviceIDPropertiesKHR = {};
|
|
vkPhysicalDeviceIDPropertiesKHR.sType =
|
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES_KHR;
|
|
vkPhysicalDeviceIDPropertiesKHR.pNext = NULL;
|
|
|
|
VkPhysicalDeviceProperties2 vkPhysicalDeviceProperties2 = {};
|
|
vkPhysicalDeviceProperties2.sType =
|
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
|
|
vkPhysicalDeviceProperties2.pNext = &vkPhysicalDeviceIDPropertiesKHR;
|
|
|
|
vkGetPhysicalDeviceProperties2(m_vkPhysicalDevice,
|
|
&vkPhysicalDeviceProperties2);
|
|
|
|
memcpy(m_vkDeviceUUID, vkPhysicalDeviceIDPropertiesKHR.deviceUUID,
|
|
sizeof(m_vkDeviceUUID));
|
|
memcpy(m_vkDeviceLUID, vkPhysicalDeviceIDPropertiesKHR.deviceLUID,
|
|
sizeof(m_vkDeviceLUID));
|
|
m_vkDeviceNodeMask = vkPhysicalDeviceIDPropertiesKHR.deviceNodeMask;
|
|
|
|
uint32_t queueFamilyCount = 0;
|
|
vkGetPhysicalDeviceQueueFamilyProperties(m_vkPhysicalDevice,
|
|
&queueFamilyCount, NULL);
|
|
|
|
std::vector<VkQueueFamilyProperties> vkQueueFamilyPropertiesList(
|
|
queueFamilyCount);
|
|
vkGetPhysicalDeviceQueueFamilyProperties(
|
|
m_vkPhysicalDevice, &queueFamilyCount,
|
|
vkQueueFamilyPropertiesList.data());
|
|
|
|
for (size_t qfpIdx = 0; qfpIdx < vkQueueFamilyPropertiesList.size();
|
|
qfpIdx++)
|
|
{
|
|
VulkanQueueFamily *queueFamily = new VulkanQueueFamily(
|
|
uint32_t(qfpIdx), vkQueueFamilyPropertiesList[qfpIdx]);
|
|
m_queueFamilyList.add(*queueFamily);
|
|
}
|
|
|
|
vkGetPhysicalDeviceMemoryProperties(m_vkPhysicalDevice,
|
|
&m_vkPhysicalDeviceMemoryProperties);
|
|
|
|
for (uint32_t mhIdx = 0;
|
|
mhIdx < m_vkPhysicalDeviceMemoryProperties.memoryHeapCount; mhIdx++)
|
|
{
|
|
VulkanMemoryHeap *memoryHeap = new VulkanMemoryHeap(
|
|
mhIdx, m_vkPhysicalDeviceMemoryProperties.memoryHeaps[mhIdx].size,
|
|
(VulkanMemoryHeapFlag)m_vkPhysicalDeviceMemoryProperties
|
|
.memoryHeaps[mhIdx]
|
|
.flags);
|
|
m_memoryHeapList.add(*memoryHeap);
|
|
}
|
|
|
|
for (uint32_t mtIdx = 0;
|
|
mtIdx < m_vkPhysicalDeviceMemoryProperties.memoryTypeCount; mtIdx++)
|
|
{
|
|
const VulkanMemoryHeap &memoryHeap = m_memoryHeapList
|
|
[m_vkPhysicalDeviceMemoryProperties.memoryTypes[mtIdx].heapIndex];
|
|
VulkanMemoryType *memoryType = new VulkanMemoryType(
|
|
mtIdx,
|
|
(VulkanMemoryTypeProperty)m_vkPhysicalDeviceMemoryProperties
|
|
.memoryTypes[mtIdx]
|
|
.propertyFlags,
|
|
memoryHeap);
|
|
m_memoryTypeList.add(*memoryType);
|
|
}
|
|
|
|
uint32_t num_extensions = 0;
|
|
vkEnumerateDeviceExtensionProperties(m_vkPhysicalDevice, nullptr,
|
|
&num_extensions, nullptr);
|
|
if (num_extensions)
|
|
{
|
|
m_extensions.resize(num_extensions);
|
|
vkEnumerateDeviceExtensionProperties(
|
|
m_vkPhysicalDevice, nullptr, &num_extensions, m_extensions.data());
|
|
}
|
|
}
|
|
|
|
VulkanPhysicalDevice::~VulkanPhysicalDevice()
|
|
{
|
|
for (size_t mtIdx = 0; mtIdx < m_memoryTypeList.size(); mtIdx++)
|
|
{
|
|
const VulkanMemoryType &memoryType = m_memoryTypeList[mtIdx];
|
|
delete &memoryType;
|
|
}
|
|
|
|
for (size_t mhIdx = 0; mhIdx < m_memoryHeapList.size(); mhIdx++)
|
|
{
|
|
const VulkanMemoryHeap &memoryHeap = m_memoryHeapList[mhIdx];
|
|
delete &memoryHeap;
|
|
}
|
|
|
|
for (size_t qfIdx = 0; qfIdx < m_queueFamilyList.size(); qfIdx++)
|
|
{
|
|
const VulkanQueueFamily &queueFamily = m_queueFamilyList[qfIdx];
|
|
delete &queueFamily;
|
|
}
|
|
}
|
|
|
|
|
|
const VulkanQueueFamilyList &VulkanPhysicalDevice::getQueueFamilyList() const
|
|
{
|
|
return m_queueFamilyList;
|
|
}
|
|
|
|
const VulkanMemoryHeapList &VulkanPhysicalDevice::getMemoryHeapList() const
|
|
{
|
|
return m_memoryHeapList;
|
|
}
|
|
|
|
const VulkanMemoryTypeList &VulkanPhysicalDevice::getMemoryTypeList() const
|
|
{
|
|
return m_memoryTypeList;
|
|
}
|
|
|
|
const uint8_t *VulkanPhysicalDevice::getUUID() const { return m_vkDeviceUUID; }
|
|
|
|
const uint8_t *VulkanPhysicalDevice::getLUID() const { return m_vkDeviceLUID; }
|
|
|
|
uint32_t VulkanPhysicalDevice::getNodeMask() const
|
|
{
|
|
return m_vkDeviceNodeMask;
|
|
}
|
|
|
|
VulkanPhysicalDevice::operator VkPhysicalDevice() const
|
|
{
|
|
return m_vkPhysicalDevice;
|
|
}
|
|
|
|
bool VulkanPhysicalDevice::hasExtension(const char *extension_name) const
|
|
{
|
|
for (const auto &m_extension : m_extensions)
|
|
{
|
|
if (!strcmp(m_extension.extensionName, extension_name))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool operator<(const VulkanQueueFamily &queueFamilyA,
|
|
const VulkanQueueFamily &queueFamilyB)
|
|
{
|
|
return (uint32_t)queueFamilyA < (uint32_t)queueFamilyB;
|
|
}
|
|
|
|
/////////////////////////////////////
|
|
// VulkanMemoryHeap implementation //
|
|
/////////////////////////////////////
|
|
|
|
VulkanMemoryHeap::VulkanMemoryHeap(const VulkanMemoryHeap &memoryHeap)
|
|
: m_memoryHeapIndex(memoryHeap.m_memoryHeapIndex),
|
|
m_size(memoryHeap.m_size), m_memoryHeapFlag(memoryHeap.m_memoryHeapFlag)
|
|
{}
|
|
|
|
VulkanMemoryHeap::VulkanMemoryHeap(uint32_t memoryHeapIndex, uint64_t size,
|
|
VulkanMemoryHeapFlag memoryHeapFlag)
|
|
: m_memoryHeapIndex(memoryHeapIndex), m_size(size),
|
|
m_memoryHeapFlag(memoryHeapFlag)
|
|
{}
|
|
|
|
VulkanMemoryHeap::~VulkanMemoryHeap() {}
|
|
|
|
uint64_t VulkanMemoryHeap::getSize() const { return m_size; }
|
|
|
|
|
|
VulkanMemoryHeapFlag VulkanMemoryHeap::getMemoryHeapFlag() const
|
|
{
|
|
return m_memoryHeapFlag;
|
|
}
|
|
|
|
VulkanMemoryHeap::operator uint32_t() const { return m_memoryHeapIndex; }
|
|
|
|
/////////////////////////////////////
|
|
// VulkanMemoryType implementation //
|
|
/////////////////////////////////////
|
|
|
|
VulkanMemoryType::VulkanMemoryType(const VulkanMemoryType &memoryType)
|
|
: m_memoryTypeIndex(memoryType.m_memoryTypeIndex),
|
|
m_memoryTypeProperty(memoryType.m_memoryTypeProperty),
|
|
m_memoryHeap(memoryType.m_memoryHeap)
|
|
{}
|
|
|
|
VulkanMemoryType::VulkanMemoryType(uint32_t memoryTypeIndex,
|
|
VulkanMemoryTypeProperty memoryTypeProperty,
|
|
const VulkanMemoryHeap &memoryHeap)
|
|
: m_memoryTypeIndex(memoryTypeIndex),
|
|
m_memoryTypeProperty(memoryTypeProperty), m_memoryHeap(memoryHeap)
|
|
{}
|
|
|
|
VulkanMemoryType::~VulkanMemoryType() {}
|
|
|
|
VulkanMemoryTypeProperty VulkanMemoryType::getMemoryTypeProperty() const
|
|
{
|
|
return m_memoryTypeProperty;
|
|
}
|
|
|
|
const VulkanMemoryHeap &VulkanMemoryType::getMemoryHeap() const
|
|
{
|
|
return m_memoryHeap;
|
|
}
|
|
|
|
VulkanMemoryType::operator uint32_t() const { return m_memoryTypeIndex; }
|
|
|
|
//////////////////////////////////////
|
|
// VulkanQueueFamily implementation //
|
|
//////////////////////////////////////
|
|
|
|
VulkanQueueFamily::VulkanQueueFamily(const VulkanQueueFamily &queueFamily)
|
|
: m_queueFamilyIndex(queueFamily.m_queueFamilyIndex),
|
|
m_vkQueueFamilyProperties(queueFamily.m_vkQueueFamilyProperties)
|
|
{}
|
|
|
|
VulkanQueueFamily::VulkanQueueFamily(
|
|
uint32_t queueFamilyIndex, VkQueueFamilyProperties vkQueueFamilyProperties)
|
|
: m_queueFamilyIndex(queueFamilyIndex),
|
|
m_vkQueueFamilyProperties(vkQueueFamilyProperties)
|
|
{}
|
|
|
|
VulkanQueueFamily::~VulkanQueueFamily() {}
|
|
|
|
uint32_t VulkanQueueFamily::getQueueFlags() const
|
|
{
|
|
return m_vkQueueFamilyProperties.queueFlags
|
|
& (uint32_t)VULKAN_QUEUE_FLAG_MASK_ALL;
|
|
}
|
|
|
|
uint32_t VulkanQueueFamily::getQueueCount() const
|
|
{
|
|
return m_vkQueueFamilyProperties.queueCount;
|
|
}
|
|
|
|
VulkanQueueFamily::operator uint32_t() const { return m_queueFamilyIndex; }
|
|
|
|
/////////////////////////////////
|
|
// VulkanDevice implementation //
|
|
/////////////////////////////////
|
|
|
|
VulkanDevice::VulkanDevice(const VulkanDevice &device)
|
|
: m_physicalDevice(device.m_physicalDevice), m_vkDevice(device.m_vkDevice)
|
|
{}
|
|
|
|
VulkanDevice::VulkanDevice(
|
|
const VulkanPhysicalDevice &physicalDevice,
|
|
const VulkanQueueFamilyToQueueCountMap &queueFamilyToQueueCountMap,
|
|
bool useShaderInt8)
|
|
: m_physicalDevice(physicalDevice), m_vkDevice(NULL)
|
|
{
|
|
uint32_t maxQueueCount = 0;
|
|
for (uint32_t qfIdx = 0;
|
|
qfIdx < (uint32_t)physicalDevice.getQueueFamilyList().size(); qfIdx++)
|
|
{
|
|
maxQueueCount =
|
|
std::max(maxQueueCount, queueFamilyToQueueCountMap[qfIdx]);
|
|
}
|
|
|
|
std::vector<VkDeviceQueueCreateInfo> vkDeviceQueueCreateInfoList;
|
|
std::vector<float> queuePriorities(maxQueueCount);
|
|
for (uint32_t qfIdx = 0;
|
|
qfIdx < (uint32_t)physicalDevice.getQueueFamilyList().size(); qfIdx++)
|
|
{
|
|
if (queueFamilyToQueueCountMap[qfIdx])
|
|
{
|
|
VkDeviceQueueCreateInfo vkDeviceQueueCreateInfo = {};
|
|
vkDeviceQueueCreateInfo.sType =
|
|
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
|
vkDeviceQueueCreateInfo.pNext = NULL;
|
|
vkDeviceQueueCreateInfo.flags = 0;
|
|
vkDeviceQueueCreateInfo.queueFamilyIndex = qfIdx;
|
|
vkDeviceQueueCreateInfo.queueCount =
|
|
queueFamilyToQueueCountMap[qfIdx];
|
|
vkDeviceQueueCreateInfo.pQueuePriorities = queuePriorities.data();
|
|
|
|
vkDeviceQueueCreateInfoList.push_back(vkDeviceQueueCreateInfo);
|
|
}
|
|
}
|
|
|
|
std::vector<const char *> enabledExtensionNameList;
|
|
enabledExtensionNameList.push_back(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME);
|
|
enabledExtensionNameList.push_back(
|
|
VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
enabledExtensionNameList.push_back(
|
|
VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME);
|
|
enabledExtensionNameList.push_back(
|
|
VK_KHR_EXTERNAL_SEMAPHORE_WIN32_EXTENSION_NAME);
|
|
#else
|
|
enabledExtensionNameList.push_back(
|
|
VK_KHR_EXTERNAL_MEMORY_FD_EXTENSION_NAME);
|
|
enabledExtensionNameList.push_back(
|
|
VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
|
|
#endif
|
|
|
|
|
|
VkDeviceCreateInfo vkDeviceCreateInfo = {};
|
|
vkDeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
|
vkDeviceCreateInfo.pNext = NULL;
|
|
vkDeviceCreateInfo.flags = 0;
|
|
vkDeviceCreateInfo.queueCreateInfoCount =
|
|
(uint32_t)vkDeviceQueueCreateInfoList.size();
|
|
vkDeviceCreateInfo.pQueueCreateInfos = vkDeviceQueueCreateInfoList.data();
|
|
vkDeviceCreateInfo.enabledLayerCount = 0;
|
|
vkDeviceCreateInfo.ppEnabledLayerNames = NULL;
|
|
vkDeviceCreateInfo.enabledExtensionCount =
|
|
(uint32_t)enabledExtensionNameList.size();
|
|
vkDeviceCreateInfo.ppEnabledExtensionNames =
|
|
enabledExtensionNameList.data();
|
|
vkDeviceCreateInfo.pEnabledFeatures = NULL;
|
|
|
|
if (useShaderInt8)
|
|
{
|
|
VkPhysicalDeviceShaderFloat16Int8Features int8Features{};
|
|
int8Features.sType =
|
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES;
|
|
|
|
VkPhysicalDevice8BitStorageFeatures storage8Features{};
|
|
storage8Features.sType =
|
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES;
|
|
|
|
int8Features.pNext = &storage8Features;
|
|
|
|
VkPhysicalDeviceFeatures2 features2{};
|
|
features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
|
features2.pNext = &int8Features;
|
|
|
|
vkGetPhysicalDeviceFeatures2(physicalDevice, &features2);
|
|
|
|
if (!int8Features.shaderInt8
|
|
|| !storage8Features.storageBuffer8BitAccess)
|
|
{
|
|
throw std::runtime_error("shaderInt8 not supported!\n");
|
|
}
|
|
|
|
VkPhysicalDevice8BitStorageFeatures storage8Enable{};
|
|
storage8Enable.sType =
|
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_8BIT_STORAGE_FEATURES;
|
|
storage8Enable.storageBuffer8BitAccess = VK_TRUE;
|
|
|
|
VkPhysicalDeviceShaderFloat16Int8Features int8Enable{};
|
|
int8Enable.sType =
|
|
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES;
|
|
int8Enable.shaderInt8 = VK_TRUE;
|
|
int8Enable.pNext = &storage8Enable;
|
|
|
|
vkDeviceCreateInfo.pNext = &int8Enable;
|
|
|
|
enabledExtensionNameList.push_back(VK_KHR_8BIT_STORAGE_EXTENSION_NAME);
|
|
vkDeviceCreateInfo.ppEnabledExtensionNames =
|
|
enabledExtensionNameList.data();
|
|
vkDeviceCreateInfo.enabledExtensionCount =
|
|
(uint32_t)enabledExtensionNameList.size();
|
|
|
|
vkCreateDevice(physicalDevice, &vkDeviceCreateInfo, NULL, &m_vkDevice);
|
|
}
|
|
else
|
|
{
|
|
vkCreateDevice(physicalDevice, &vkDeviceCreateInfo, NULL, &m_vkDevice);
|
|
}
|
|
|
|
for (uint32_t qfIdx = 0;
|
|
qfIdx < (uint32_t)m_physicalDevice.getQueueFamilyList().size();
|
|
qfIdx++)
|
|
{
|
|
VulkanQueueList *queueList = new VulkanQueueList();
|
|
m_queueFamilyIndexToQueueListMap.insert(qfIdx, *queueList);
|
|
for (uint32_t qIdx = 0; qIdx < queueFamilyToQueueCountMap[qfIdx];
|
|
qIdx++)
|
|
{
|
|
VkQueue vkQueue;
|
|
vkGetDeviceQueue(m_vkDevice, qfIdx, qIdx, &vkQueue);
|
|
VulkanQueue *queue = new VulkanQueue(vkQueue);
|
|
m_queueFamilyIndexToQueueListMap[qfIdx].add(*queue);
|
|
}
|
|
}
|
|
}
|
|
|
|
VulkanDevice::~VulkanDevice()
|
|
{
|
|
for (uint32_t qfIdx = 0;
|
|
qfIdx < (uint32_t)m_physicalDevice.getQueueFamilyList().size();
|
|
qfIdx++)
|
|
{
|
|
for (size_t qIdx = 0;
|
|
qIdx < m_queueFamilyIndexToQueueListMap[qfIdx].size(); qIdx++)
|
|
{
|
|
VulkanQueue &queue = m_queueFamilyIndexToQueueListMap[qfIdx][qIdx];
|
|
delete &queue;
|
|
}
|
|
VulkanQueueList &queueList = m_queueFamilyIndexToQueueListMap[qfIdx];
|
|
delete &queueList;
|
|
}
|
|
vkDestroyDevice(m_vkDevice, NULL);
|
|
}
|
|
|
|
const VulkanPhysicalDevice &VulkanDevice::getPhysicalDevice() const
|
|
{
|
|
return m_physicalDevice;
|
|
}
|
|
|
|
VulkanQueue &VulkanDevice::getQueue(const VulkanQueueFamily &queueFamily,
|
|
uint32_t queueIndex)
|
|
{
|
|
return m_queueFamilyIndexToQueueListMap[queueFamily][queueIndex];
|
|
}
|
|
|
|
VulkanDevice::operator VkDevice() const { return m_vkDevice; }
|
|
|
|
////////////////////////////////
|
|
// VulkanFence implementation //
|
|
////////////////////////////////
|
|
|
|
VulkanFence::VulkanFence(const VulkanDevice &vkDevice)
|
|
{
|
|
|
|
device = vkDevice;
|
|
|
|
VkFenceCreateInfo fenceInfo{};
|
|
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
|
fenceInfo.pNext = nullptr;
|
|
fenceInfo.flags = 0;
|
|
|
|
VkResult vkStatus = vkCreateFence(device, &fenceInfo, nullptr, &fence);
|
|
|
|
if (vkStatus != VK_SUCCESS)
|
|
{
|
|
throw std::runtime_error("Error: Failed create fence.");
|
|
}
|
|
}
|
|
|
|
VulkanFence::~VulkanFence() { vkDestroyFence(device, fence, nullptr); }
|
|
|
|
void VulkanFence::reset() { vkResetFences(device, 1, &fence); }
|
|
|
|
void VulkanFence::wait()
|
|
{
|
|
vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX);
|
|
}
|
|
|
|
////////////////////////////////
|
|
// VulkanQueue implementation //
|
|
////////////////////////////////
|
|
|
|
VulkanQueue::VulkanQueue(const VulkanQueue &queue): m_vkQueue(queue.m_vkQueue)
|
|
{}
|
|
|
|
VulkanQueue::VulkanQueue(VkQueue vkQueue): m_vkQueue(vkQueue) {}
|
|
|
|
VulkanQueue::~VulkanQueue() {}
|
|
|
|
void VulkanQueue::submit(const VulkanCommandBuffer &commandBuffer,
|
|
const std::shared_ptr<VulkanFence> &vkFence)
|
|
{
|
|
VulkanCommandBufferList commandBufferList;
|
|
commandBufferList.add(commandBuffer);
|
|
|
|
VkSubmitInfo vkSubmitInfo = {};
|
|
vkSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
vkSubmitInfo.pNext = NULL;
|
|
vkSubmitInfo.waitSemaphoreCount = (uint32_t)0;
|
|
vkSubmitInfo.commandBufferCount = (uint32_t)commandBufferList.size();
|
|
vkSubmitInfo.pCommandBuffers = commandBufferList();
|
|
|
|
vkQueueSubmit(m_vkQueue, 1, &vkSubmitInfo, vkFence->fence);
|
|
}
|
|
|
|
void VulkanQueue::submit(const VulkanSemaphoreList &waitSemaphoreList,
|
|
const VulkanCommandBufferList &commandBufferList,
|
|
const VulkanSemaphoreList &signalSemaphoreList)
|
|
{
|
|
std::vector<VkPipelineStageFlags> vkPipelineStageFlagsList(
|
|
waitSemaphoreList.size(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
|
|
|
|
VkSubmitInfo vkSubmitInfo = {};
|
|
vkSubmitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
vkSubmitInfo.pNext = NULL;
|
|
vkSubmitInfo.waitSemaphoreCount = (uint32_t)waitSemaphoreList.size();
|
|
vkSubmitInfo.pWaitSemaphores = waitSemaphoreList();
|
|
vkSubmitInfo.pWaitDstStageMask = vkPipelineStageFlagsList.data();
|
|
vkSubmitInfo.commandBufferCount = (uint32_t)commandBufferList.size();
|
|
vkSubmitInfo.pCommandBuffers = commandBufferList();
|
|
vkSubmitInfo.signalSemaphoreCount = (uint32_t)signalSemaphoreList.size();
|
|
vkSubmitInfo.pSignalSemaphores = signalSemaphoreList();
|
|
|
|
vkQueueSubmit(m_vkQueue, 1, &vkSubmitInfo, NULL);
|
|
}
|
|
|
|
void VulkanQueue::submit(const VulkanSemaphore &waitSemaphore,
|
|
const VulkanCommandBuffer &commandBuffer,
|
|
const VulkanSemaphore &signalSemaphore)
|
|
{
|
|
VulkanSemaphoreList waitSemaphoreList;
|
|
VulkanCommandBufferList commandBufferList;
|
|
VulkanSemaphoreList signalSemaphoreList;
|
|
|
|
waitSemaphoreList.add(waitSemaphore);
|
|
commandBufferList.add(commandBuffer);
|
|
signalSemaphoreList.add(signalSemaphore);
|
|
|
|
submit(waitSemaphoreList, commandBufferList, signalSemaphoreList);
|
|
}
|
|
|
|
void VulkanQueue::submit(const VulkanCommandBuffer &commandBuffer,
|
|
const VulkanSemaphore &signalSemaphore)
|
|
{
|
|
VulkanSemaphoreList waitSemaphoreList;
|
|
VulkanCommandBufferList commandBufferList;
|
|
VulkanSemaphoreList signalSemaphoreList;
|
|
|
|
commandBufferList.add(commandBuffer);
|
|
signalSemaphoreList.add(signalSemaphore);
|
|
|
|
submit(waitSemaphoreList, commandBufferList, signalSemaphoreList);
|
|
}
|
|
|
|
void VulkanQueue::submit(const VulkanCommandBuffer &commandBuffer)
|
|
{
|
|
VulkanSemaphoreList waitSemaphoreList;
|
|
VulkanCommandBufferList commandBufferList;
|
|
VulkanSemaphoreList signalSemaphoreList;
|
|
|
|
commandBufferList.add(commandBuffer);
|
|
|
|
submit(waitSemaphoreList, commandBufferList, signalSemaphoreList);
|
|
}
|
|
|
|
void VulkanQueue::waitIdle() { vkQueueWaitIdle(m_vkQueue); }
|
|
|
|
VulkanQueue::operator VkQueue() const { return m_vkQueue; }
|
|
|
|
/////////////////////////////////////////////////////
|
|
// VulkanDescriptorSetLayoutBinding implementation //
|
|
/////////////////////////////////////////////////////
|
|
|
|
VulkanDescriptorSetLayoutBinding::VulkanDescriptorSetLayoutBinding(
|
|
const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding)
|
|
: m_vkDescriptorSetLayoutBinding(
|
|
descriptorSetLayoutBinding.m_vkDescriptorSetLayoutBinding)
|
|
{}
|
|
|
|
VulkanDescriptorSetLayoutBinding::VulkanDescriptorSetLayoutBinding(
|
|
uint32_t binding, VulkanDescriptorType descriptorType,
|
|
uint32_t descriptorCount, VulkanShaderStage shaderStage)
|
|
{
|
|
m_vkDescriptorSetLayoutBinding.binding = binding;
|
|
m_vkDescriptorSetLayoutBinding.descriptorType =
|
|
(VkDescriptorType)descriptorType;
|
|
m_vkDescriptorSetLayoutBinding.descriptorCount = descriptorCount;
|
|
m_vkDescriptorSetLayoutBinding.stageFlags =
|
|
(VkShaderStageFlags)(VkShaderStageFlagBits)shaderStage;
|
|
m_vkDescriptorSetLayoutBinding.pImmutableSamplers = NULL;
|
|
}
|
|
|
|
VulkanDescriptorSetLayoutBinding::~VulkanDescriptorSetLayoutBinding() {}
|
|
|
|
VulkanDescriptorSetLayoutBinding::operator VkDescriptorSetLayoutBinding() const
|
|
{
|
|
return m_vkDescriptorSetLayoutBinding;
|
|
}
|
|
|
|
//////////////////////////////////////////////
|
|
// VulkanDescriptorSetLayout implementation //
|
|
//////////////////////////////////////////////
|
|
|
|
VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(
|
|
const VulkanDescriptorSetLayout &descriptorSetLayout)
|
|
: m_device(descriptorSetLayout.m_device),
|
|
m_vkDescriptorSetLayout(descriptorSetLayout.m_vkDescriptorSetLayout)
|
|
{}
|
|
|
|
void VulkanDescriptorSetLayout::VulkanDescriptorSetLayoutCommon(
|
|
const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList)
|
|
{
|
|
VkDescriptorSetLayoutCreateInfo vkDescriptorSetLayoutCreateInfo = {};
|
|
vkDescriptorSetLayoutCreateInfo.sType =
|
|
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
|
vkDescriptorSetLayoutCreateInfo.pNext = NULL;
|
|
vkDescriptorSetLayoutCreateInfo.flags = 0;
|
|
vkDescriptorSetLayoutCreateInfo.bindingCount =
|
|
(uint32_t)descriptorSetLayoutBindingList.size();
|
|
vkDescriptorSetLayoutCreateInfo.pBindings =
|
|
descriptorSetLayoutBindingList();
|
|
|
|
vkCreateDescriptorSetLayout(m_device, &vkDescriptorSetLayoutCreateInfo,
|
|
NULL, &m_vkDescriptorSetLayout);
|
|
}
|
|
|
|
VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(
|
|
const VulkanDevice &device,
|
|
const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding)
|
|
: m_device(device), m_vkDescriptorSetLayout(VK_NULL_HANDLE)
|
|
{
|
|
VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList;
|
|
descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding);
|
|
|
|
VulkanDescriptorSetLayoutCommon(descriptorSetLayoutBindingList);
|
|
}
|
|
|
|
VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(
|
|
const VulkanDevice &device,
|
|
const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding0,
|
|
const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding1)
|
|
: m_device(device), m_vkDescriptorSetLayout(VK_NULL_HANDLE)
|
|
{
|
|
VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList;
|
|
descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding0);
|
|
descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding1);
|
|
|
|
VulkanDescriptorSetLayoutCommon(descriptorSetLayoutBindingList);
|
|
}
|
|
|
|
VulkanDescriptorSetLayout::VulkanDescriptorSetLayout(
|
|
const VulkanDevice &device,
|
|
const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList)
|
|
: m_device(device), m_vkDescriptorSetLayout(VK_NULL_HANDLE)
|
|
{
|
|
VulkanDescriptorSetLayoutCommon(descriptorSetLayoutBindingList);
|
|
}
|
|
|
|
VulkanDescriptorSetLayout::~VulkanDescriptorSetLayout()
|
|
{
|
|
if (m_vkDescriptorSetLayout != VK_NULL_HANDLE)
|
|
{
|
|
vkDestroyDescriptorSetLayout(m_device, m_vkDescriptorSetLayout, NULL);
|
|
}
|
|
}
|
|
|
|
VulkanDescriptorSetLayout::operator VkDescriptorSetLayout() const
|
|
{
|
|
return m_vkDescriptorSetLayout;
|
|
}
|
|
|
|
/////////////////////////////////////////
|
|
// VulkanPipelineLayout implementation //
|
|
/////////////////////////////////////////
|
|
|
|
VulkanPipelineLayout::VulkanPipelineLayout(
|
|
const VulkanPipelineLayout &pipelineLayout)
|
|
: m_device(pipelineLayout.m_device),
|
|
m_vkPipelineLayout(pipelineLayout.m_vkPipelineLayout)
|
|
{}
|
|
|
|
void VulkanPipelineLayout::VulkanPipelineLayoutCommon(
|
|
const VulkanDescriptorSetLayoutList &descriptorSetLayoutList)
|
|
{
|
|
VkPipelineLayoutCreateInfo vkPipelineLayoutCreateInfo = {};
|
|
vkPipelineLayoutCreateInfo.sType =
|
|
VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
|
vkPipelineLayoutCreateInfo.pNext = NULL;
|
|
vkPipelineLayoutCreateInfo.flags = 0;
|
|
vkPipelineLayoutCreateInfo.setLayoutCount =
|
|
(uint32_t)descriptorSetLayoutList.size();
|
|
vkPipelineLayoutCreateInfo.pSetLayouts = descriptorSetLayoutList();
|
|
vkPipelineLayoutCreateInfo.pushConstantRangeCount = 0;
|
|
vkPipelineLayoutCreateInfo.pPushConstantRanges = NULL;
|
|
|
|
vkCreatePipelineLayout(m_device, &vkPipelineLayoutCreateInfo, NULL,
|
|
&m_vkPipelineLayout);
|
|
}
|
|
|
|
VulkanPipelineLayout::VulkanPipelineLayout(
|
|
const VulkanDevice &device,
|
|
const VulkanDescriptorSetLayout &descriptorSetLayout)
|
|
: m_device(device), m_vkPipelineLayout(VK_NULL_HANDLE)
|
|
{
|
|
VulkanDescriptorSetLayoutList descriptorSetLayoutList;
|
|
descriptorSetLayoutList.add(descriptorSetLayout);
|
|
|
|
VulkanPipelineLayoutCommon(descriptorSetLayoutList);
|
|
}
|
|
|
|
VulkanPipelineLayout::VulkanPipelineLayout(
|
|
const VulkanDevice &device,
|
|
const VulkanDescriptorSetLayoutList &descriptorSetLayoutList)
|
|
: m_device(device), m_vkPipelineLayout(VK_NULL_HANDLE)
|
|
{
|
|
VulkanPipelineLayoutCommon(descriptorSetLayoutList);
|
|
}
|
|
|
|
VulkanPipelineLayout::~VulkanPipelineLayout()
|
|
{
|
|
vkDestroyPipelineLayout(m_device, m_vkPipelineLayout, NULL);
|
|
}
|
|
|
|
VulkanPipelineLayout::operator VkPipelineLayout() const
|
|
{
|
|
return m_vkPipelineLayout;
|
|
}
|
|
|
|
///////////////////////////////////////
|
|
// VulkanShaderModule implementation //
|
|
///////////////////////////////////////
|
|
|
|
VulkanShaderModule::VulkanShaderModule(const VulkanShaderModule &shaderModule)
|
|
: m_device(shaderModule.m_device),
|
|
m_vkShaderModule(shaderModule.m_vkShaderModule)
|
|
{}
|
|
|
|
VulkanShaderModule::VulkanShaderModule(const VulkanDevice &device,
|
|
const std::vector<char> &code)
|
|
: m_device(device)
|
|
{
|
|
|
|
VkShaderModuleCreateInfo vkShaderModuleCreateInfo = {};
|
|
vkShaderModuleCreateInfo.sType =
|
|
VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
|
vkShaderModuleCreateInfo.pNext = NULL;
|
|
vkShaderModuleCreateInfo.flags = 0;
|
|
vkShaderModuleCreateInfo.codeSize = code.size();
|
|
vkShaderModuleCreateInfo.pCode =
|
|
reinterpret_cast<const uint32_t *>(code.data());
|
|
|
|
vkCreateShaderModule(m_device, &vkShaderModuleCreateInfo, NULL,
|
|
&m_vkShaderModule);
|
|
}
|
|
|
|
VulkanShaderModule::~VulkanShaderModule()
|
|
{
|
|
vkDestroyShaderModule(m_device, m_vkShaderModule, NULL);
|
|
}
|
|
|
|
VulkanShaderModule::operator VkShaderModule() const { return m_vkShaderModule; }
|
|
|
|
///////////////////////////////////
|
|
// VulkanPipeline implementation //
|
|
///////////////////////////////////
|
|
|
|
VulkanPipeline::VulkanPipeline(const VulkanPipeline &pipeline)
|
|
: m_device(pipeline.m_device), m_vkPipeline(pipeline.m_vkPipeline)
|
|
{}
|
|
|
|
VulkanPipeline::VulkanPipeline(const VulkanDevice &device)
|
|
: m_device(device), m_vkPipeline(VK_NULL_HANDLE)
|
|
{}
|
|
|
|
VulkanPipeline::~VulkanPipeline()
|
|
{
|
|
vkDestroyPipeline(m_device, m_vkPipeline, NULL);
|
|
}
|
|
|
|
VulkanPipeline::operator VkPipeline() const { return m_vkPipeline; }
|
|
|
|
//////////////////////////////////////////
|
|
// VulkanComputePipeline implementation //
|
|
//////////////////////////////////////////
|
|
|
|
VulkanComputePipeline::VulkanComputePipeline(
|
|
const VulkanComputePipeline &computePipeline)
|
|
: VulkanPipeline(computePipeline)
|
|
{}
|
|
|
|
VulkanComputePipeline::VulkanComputePipeline(
|
|
const VulkanDevice &device, const VulkanPipelineLayout &pipelineLayout,
|
|
const VulkanShaderModule &shaderModule, const std::string &entryFuncName)
|
|
: VulkanPipeline(device)
|
|
{
|
|
VkPipelineShaderStageCreateInfo vkPipelineShaderStageCreateInfo = {};
|
|
vkPipelineShaderStageCreateInfo.sType =
|
|
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
|
vkPipelineShaderStageCreateInfo.pNext = NULL;
|
|
vkPipelineShaderStageCreateInfo.flags = 0;
|
|
vkPipelineShaderStageCreateInfo.stage = VK_SHADER_STAGE_COMPUTE_BIT;
|
|
vkPipelineShaderStageCreateInfo.module = shaderModule;
|
|
vkPipelineShaderStageCreateInfo.pName = entryFuncName.c_str();
|
|
vkPipelineShaderStageCreateInfo.pSpecializationInfo = NULL;
|
|
|
|
VkComputePipelineCreateInfo vkComputePipelineCreateInfo = {};
|
|
vkComputePipelineCreateInfo.sType =
|
|
VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
|
|
vkComputePipelineCreateInfo.pNext = NULL;
|
|
vkComputePipelineCreateInfo.flags = 0;
|
|
vkComputePipelineCreateInfo.stage = vkPipelineShaderStageCreateInfo;
|
|
vkComputePipelineCreateInfo.layout = pipelineLayout;
|
|
vkComputePipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
|
|
vkComputePipelineCreateInfo.basePipelineIndex = 0;
|
|
|
|
vkCreateComputePipelines(device, VK_NULL_HANDLE, 1,
|
|
&vkComputePipelineCreateInfo, NULL, &m_vkPipeline);
|
|
}
|
|
|
|
VulkanComputePipeline::~VulkanComputePipeline() {}
|
|
|
|
VulkanPipelineBindPoint VulkanComputePipeline::getPipelineBindPoint() const
|
|
{
|
|
return VULKAN_PIPELINE_BIND_POINT_COMPUTE;
|
|
}
|
|
|
|
/////////////////////////////////////////
|
|
// VulkanDescriptorPool implementation //
|
|
/////////////////////////////////////////
|
|
|
|
VulkanDescriptorPool::VulkanDescriptorPool(
|
|
const VulkanDescriptorPool &descriptorPool)
|
|
: m_device(descriptorPool.m_device),
|
|
m_vkDescriptorPool(descriptorPool.m_vkDescriptorPool)
|
|
{}
|
|
|
|
void VulkanDescriptorPool::VulkanDescriptorPoolCommon(
|
|
const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList)
|
|
{
|
|
if (descriptorSetLayoutBindingList.size())
|
|
{
|
|
std::map<VkDescriptorType, uint32_t>
|
|
vkDescriptorTypeToDescriptorCountMap;
|
|
|
|
for (size_t dslbIdx = 0;
|
|
dslbIdx < descriptorSetLayoutBindingList.size(); dslbIdx++)
|
|
{
|
|
VkDescriptorSetLayoutBinding vkDescriptorSetLayoutBinding =
|
|
descriptorSetLayoutBindingList[dslbIdx];
|
|
if (vkDescriptorTypeToDescriptorCountMap.find(
|
|
vkDescriptorSetLayoutBinding.descriptorType)
|
|
== vkDescriptorTypeToDescriptorCountMap.end())
|
|
{
|
|
vkDescriptorTypeToDescriptorCountMap
|
|
[vkDescriptorSetLayoutBinding.descriptorType] =
|
|
vkDescriptorSetLayoutBinding.descriptorCount;
|
|
}
|
|
else
|
|
{
|
|
vkDescriptorTypeToDescriptorCountMap
|
|
[vkDescriptorSetLayoutBinding.descriptorType] +=
|
|
vkDescriptorSetLayoutBinding.descriptorCount;
|
|
}
|
|
}
|
|
|
|
std::vector<VkDescriptorPoolSize> vkDescriptorPoolSizeList;
|
|
std::map<VkDescriptorType, uint32_t>::iterator dtdcIt;
|
|
for (dtdcIt = vkDescriptorTypeToDescriptorCountMap.begin();
|
|
dtdcIt != vkDescriptorTypeToDescriptorCountMap.end(); ++dtdcIt)
|
|
{
|
|
VkDescriptorPoolSize vkDescriptorPoolSize = {};
|
|
vkDescriptorPoolSize.type = dtdcIt->first;
|
|
vkDescriptorPoolSize.descriptorCount = dtdcIt->second;
|
|
|
|
vkDescriptorPoolSizeList.push_back(vkDescriptorPoolSize);
|
|
}
|
|
|
|
VkDescriptorPoolCreateInfo vkDescriptorPoolCreateInfo = {};
|
|
vkDescriptorPoolCreateInfo.sType =
|
|
VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
|
vkDescriptorPoolCreateInfo.pNext = NULL;
|
|
vkDescriptorPoolCreateInfo.flags =
|
|
VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT;
|
|
vkDescriptorPoolCreateInfo.maxSets = 1;
|
|
vkDescriptorPoolCreateInfo.poolSizeCount =
|
|
(uint32_t)vkDescriptorPoolSizeList.size();
|
|
vkDescriptorPoolCreateInfo.pPoolSizes = vkDescriptorPoolSizeList.data();
|
|
|
|
vkCreateDescriptorPool(m_device, &vkDescriptorPoolCreateInfo, NULL,
|
|
&m_vkDescriptorPool);
|
|
}
|
|
}
|
|
|
|
VulkanDescriptorPool::VulkanDescriptorPool(
|
|
const VulkanDevice &device,
|
|
const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding)
|
|
: m_device(device), m_vkDescriptorPool(VK_NULL_HANDLE)
|
|
{
|
|
VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList;
|
|
descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding);
|
|
|
|
VulkanDescriptorPoolCommon(descriptorSetLayoutBindingList);
|
|
}
|
|
|
|
VulkanDescriptorPool::VulkanDescriptorPool(
|
|
const VulkanDevice &device,
|
|
const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding0,
|
|
const VulkanDescriptorSetLayoutBinding &descriptorSetLayoutBinding1)
|
|
: m_device(device), m_vkDescriptorPool(VK_NULL_HANDLE)
|
|
{
|
|
VulkanDescriptorSetLayoutBindingList descriptorSetLayoutBindingList;
|
|
descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding0);
|
|
descriptorSetLayoutBindingList.add(descriptorSetLayoutBinding1);
|
|
|
|
VulkanDescriptorPoolCommon(descriptorSetLayoutBindingList);
|
|
}
|
|
|
|
VulkanDescriptorPool::VulkanDescriptorPool(
|
|
const VulkanDevice &device,
|
|
const VulkanDescriptorSetLayoutBindingList &descriptorSetLayoutBindingList)
|
|
: m_device(device), m_vkDescriptorPool(VK_NULL_HANDLE)
|
|
{
|
|
VulkanDescriptorPoolCommon(descriptorSetLayoutBindingList);
|
|
}
|
|
|
|
VulkanDescriptorPool::~VulkanDescriptorPool()
|
|
{
|
|
if (m_vkDescriptorPool != VK_NULL_HANDLE)
|
|
{
|
|
vkDestroyDescriptorPool(m_device, m_vkDescriptorPool, NULL);
|
|
}
|
|
}
|
|
|
|
VulkanDescriptorPool::operator VkDescriptorPool() const
|
|
{
|
|
return m_vkDescriptorPool;
|
|
}
|
|
|
|
////////////////////////////////////////
|
|
// VulkanDescriptorSet implementation //
|
|
////////////////////////////////////////
|
|
|
|
VulkanDescriptorSet::VulkanDescriptorSet(
|
|
const VulkanDescriptorSet &descriptorSet)
|
|
: m_device(descriptorSet.m_device),
|
|
m_descriptorPool(descriptorSet.m_descriptorPool),
|
|
m_vkDescriptorSet(descriptorSet.m_vkDescriptorSet)
|
|
{}
|
|
|
|
VulkanDescriptorSet::VulkanDescriptorSet(
|
|
const VulkanDevice &device, const VulkanDescriptorPool &descriptorPool,
|
|
const VulkanDescriptorSetLayout &descriptorSetLayout)
|
|
: m_device(device), m_descriptorPool(descriptorPool),
|
|
m_vkDescriptorSet(VK_NULL_HANDLE)
|
|
{
|
|
VkDescriptorSetLayout vkDescriptorSetLayout = descriptorSetLayout;
|
|
|
|
if ((VkDescriptorPool)m_descriptorPool)
|
|
{
|
|
VkDescriptorSetAllocateInfo vkDescriptorSetAllocateInfo = {};
|
|
vkDescriptorSetAllocateInfo.sType =
|
|
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
|
vkDescriptorSetAllocateInfo.pNext = NULL;
|
|
vkDescriptorSetAllocateInfo.descriptorPool = descriptorPool;
|
|
vkDescriptorSetAllocateInfo.descriptorSetCount = 1;
|
|
vkDescriptorSetAllocateInfo.pSetLayouts = &vkDescriptorSetLayout;
|
|
|
|
vkAllocateDescriptorSets(m_device, &vkDescriptorSetAllocateInfo,
|
|
&m_vkDescriptorSet);
|
|
}
|
|
}
|
|
|
|
VulkanDescriptorSet::~VulkanDescriptorSet()
|
|
{
|
|
if ((VkDescriptorPool)m_descriptorPool)
|
|
{
|
|
vkFreeDescriptorSets(m_device, m_descriptorPool, 1, &m_vkDescriptorSet);
|
|
}
|
|
}
|
|
|
|
void VulkanDescriptorSet::update(uint32_t binding, const VulkanBuffer &buffer)
|
|
{
|
|
VkDescriptorBufferInfo vkDescriptorBufferInfo = {};
|
|
vkDescriptorBufferInfo.buffer = buffer;
|
|
vkDescriptorBufferInfo.offset = 0;
|
|
vkDescriptorBufferInfo.range = VK_WHOLE_SIZE;
|
|
|
|
VkWriteDescriptorSet vkWriteDescriptorSet = {};
|
|
vkWriteDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
vkWriteDescriptorSet.pNext = NULL;
|
|
vkWriteDescriptorSet.dstSet = m_vkDescriptorSet;
|
|
vkWriteDescriptorSet.dstBinding = binding;
|
|
vkWriteDescriptorSet.dstArrayElement = 0;
|
|
vkWriteDescriptorSet.descriptorCount = 1;
|
|
vkWriteDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
vkWriteDescriptorSet.pImageInfo = NULL;
|
|
vkWriteDescriptorSet.pBufferInfo = &vkDescriptorBufferInfo;
|
|
vkWriteDescriptorSet.pTexelBufferView = NULL;
|
|
|
|
vkUpdateDescriptorSets(m_device, 1, &vkWriteDescriptorSet, 0, NULL);
|
|
}
|
|
|
|
void VulkanDescriptorSet::updateArray(uint32_t binding, unsigned numBuffers,
|
|
const VulkanBufferList &buffers)
|
|
{
|
|
VkDescriptorBufferInfo *vkDescriptorBufferInfo =
|
|
(VkDescriptorBufferInfo *)calloc(numBuffers,
|
|
sizeof(VkDescriptorBufferInfo));
|
|
for (unsigned i = 0; i < numBuffers; i++)
|
|
{
|
|
vkDescriptorBufferInfo[i].buffer = buffers[i];
|
|
vkDescriptorBufferInfo[i].offset = 0;
|
|
vkDescriptorBufferInfo[i].range = VK_WHOLE_SIZE;
|
|
}
|
|
|
|
VkWriteDescriptorSet vkWriteDescriptorSet = {};
|
|
vkWriteDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
vkWriteDescriptorSet.pNext = NULL;
|
|
vkWriteDescriptorSet.dstSet = m_vkDescriptorSet;
|
|
vkWriteDescriptorSet.dstBinding = binding;
|
|
vkWriteDescriptorSet.dstArrayElement = 0;
|
|
vkWriteDescriptorSet.descriptorCount = numBuffers;
|
|
vkWriteDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
|
vkWriteDescriptorSet.pImageInfo = NULL;
|
|
vkWriteDescriptorSet.pBufferInfo = vkDescriptorBufferInfo;
|
|
vkWriteDescriptorSet.pTexelBufferView = NULL;
|
|
|
|
vkUpdateDescriptorSets(m_device, 1, &vkWriteDescriptorSet, 0, NULL);
|
|
free(vkDescriptorBufferInfo);
|
|
}
|
|
|
|
void VulkanDescriptorSet::update(uint32_t binding,
|
|
const VulkanImageView &imageView)
|
|
{
|
|
VkDescriptorImageInfo vkDescriptorImageInfo = {};
|
|
vkDescriptorImageInfo.sampler = VK_NULL_HANDLE;
|
|
vkDescriptorImageInfo.imageView = imageView;
|
|
vkDescriptorImageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
|
|
|
VkWriteDescriptorSet vkWriteDescriptorSet = {};
|
|
vkWriteDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
vkWriteDescriptorSet.pNext = NULL;
|
|
vkWriteDescriptorSet.dstSet = m_vkDescriptorSet;
|
|
vkWriteDescriptorSet.dstBinding = binding;
|
|
vkWriteDescriptorSet.dstArrayElement = 0;
|
|
vkWriteDescriptorSet.descriptorCount = 1;
|
|
vkWriteDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
vkWriteDescriptorSet.pImageInfo = &vkDescriptorImageInfo;
|
|
vkWriteDescriptorSet.pBufferInfo = NULL;
|
|
vkWriteDescriptorSet.pTexelBufferView = NULL;
|
|
|
|
vkUpdateDescriptorSets(m_device, 1, &vkWriteDescriptorSet, 0, NULL);
|
|
}
|
|
|
|
void VulkanDescriptorSet::updateArray(uint32_t binding,
|
|
const VulkanImageViewList &imageViewList)
|
|
{
|
|
VkDescriptorImageInfo *vkDescriptorImageInfo =
|
|
new VkDescriptorImageInfo[imageViewList.size()];
|
|
for (size_t i = 0; i < imageViewList.size(); i++)
|
|
{
|
|
vkDescriptorImageInfo[i].sampler = VK_NULL_HANDLE;
|
|
vkDescriptorImageInfo[i].imageView = imageViewList[i];
|
|
vkDescriptorImageInfo[i].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
|
}
|
|
|
|
VkWriteDescriptorSet vkWriteDescriptorSet = {};
|
|
vkWriteDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
|
|
vkWriteDescriptorSet.pNext = NULL;
|
|
vkWriteDescriptorSet.dstSet = m_vkDescriptorSet;
|
|
vkWriteDescriptorSet.dstBinding = binding;
|
|
vkWriteDescriptorSet.dstArrayElement = 0;
|
|
vkWriteDescriptorSet.descriptorCount = imageViewList.size();
|
|
vkWriteDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
|
vkWriteDescriptorSet.pImageInfo = vkDescriptorImageInfo;
|
|
vkWriteDescriptorSet.pBufferInfo = NULL;
|
|
vkWriteDescriptorSet.pTexelBufferView = NULL;
|
|
|
|
vkUpdateDescriptorSets(m_device, 1, &vkWriteDescriptorSet, 0, NULL);
|
|
delete[] vkDescriptorImageInfo;
|
|
}
|
|
|
|
VulkanDescriptorSet::operator VkDescriptorSet() const
|
|
{
|
|
return m_vkDescriptorSet;
|
|
}
|
|
|
|
///////////////////////////////////
|
|
// VulkanOffset3D implementation //
|
|
///////////////////////////////////
|
|
|
|
VulkanOffset3D::VulkanOffset3D(const VulkanOffset3D &offset3D)
|
|
: m_vkOffset3D(offset3D.m_vkOffset3D)
|
|
{}
|
|
|
|
VulkanOffset3D::VulkanOffset3D(uint32_t x, uint32_t y, uint32_t z)
|
|
{
|
|
m_vkOffset3D.x = x;
|
|
m_vkOffset3D.y = y;
|
|
m_vkOffset3D.z = z;
|
|
}
|
|
|
|
VulkanOffset3D::~VulkanOffset3D() {}
|
|
|
|
uint32_t VulkanOffset3D::getX() const { return m_vkOffset3D.x; }
|
|
|
|
uint32_t VulkanOffset3D::getY() const { return m_vkOffset3D.y; }
|
|
|
|
uint32_t VulkanOffset3D::getZ() const { return m_vkOffset3D.z; }
|
|
|
|
VulkanOffset3D::operator VkOffset3D() const { return m_vkOffset3D; }
|
|
|
|
///////////////////////////////////
|
|
// VulkanExtent3D implementation //
|
|
///////////////////////////////////
|
|
|
|
VulkanExtent3D::VulkanExtent3D(const VulkanExtent3D &extent3D)
|
|
: m_vkExtent3D(extent3D.m_vkExtent3D)
|
|
{}
|
|
|
|
VulkanExtent3D::VulkanExtent3D(uint32_t width, uint32_t height, uint32_t depth)
|
|
{
|
|
m_vkExtent3D.width = width;
|
|
m_vkExtent3D.height = height;
|
|
m_vkExtent3D.depth = depth;
|
|
}
|
|
|
|
VulkanExtent3D::~VulkanExtent3D() {}
|
|
|
|
uint32_t VulkanExtent3D::getWidth() const { return m_vkExtent3D.width; }
|
|
|
|
uint32_t VulkanExtent3D::getHeight() const { return m_vkExtent3D.height; }
|
|
|
|
uint32_t VulkanExtent3D::getDepth() const { return m_vkExtent3D.depth; }
|
|
|
|
VulkanExtent3D::operator VkExtent3D() const { return m_vkExtent3D; }
|
|
|
|
//////////////////////////////////////
|
|
// VulkanCommandPool implementation //
|
|
//////////////////////////////////////
|
|
|
|
VulkanCommandPool::VulkanCommandPool(const VulkanCommandPool &commandPool)
|
|
: m_device(commandPool.m_device),
|
|
m_vkCommandPool(commandPool.m_vkCommandPool)
|
|
{}
|
|
|
|
VulkanCommandPool::VulkanCommandPool(const VulkanDevice &device,
|
|
const VulkanQueueFamily &queueFamily)
|
|
: m_device(device)
|
|
{
|
|
VkCommandPoolCreateInfo vkCommandPoolCreateInfo = {};
|
|
vkCommandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
|
vkCommandPoolCreateInfo.pNext = NULL;
|
|
vkCommandPoolCreateInfo.flags =
|
|
VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
|
vkCommandPoolCreateInfo.queueFamilyIndex = queueFamily;
|
|
|
|
vkCreateCommandPool(m_device, &vkCommandPoolCreateInfo, NULL,
|
|
&m_vkCommandPool);
|
|
}
|
|
|
|
VulkanCommandPool::~VulkanCommandPool()
|
|
{
|
|
vkDestroyCommandPool(m_device, m_vkCommandPool, NULL);
|
|
}
|
|
|
|
VulkanCommandPool::operator VkCommandPool() const { return m_vkCommandPool; }
|
|
|
|
////////////////////////////////////////
|
|
// VulkanCommandBuffer implementation //
|
|
////////////////////////////////////////
|
|
|
|
VulkanCommandBuffer::VulkanCommandBuffer(
|
|
const VulkanCommandBuffer &commandBuffer)
|
|
: m_device(commandBuffer.m_device),
|
|
m_commandPool(commandBuffer.m_commandPool),
|
|
m_vkCommandBuffer(commandBuffer.m_vkCommandBuffer)
|
|
{}
|
|
|
|
VulkanCommandBuffer::VulkanCommandBuffer(const VulkanDevice &device,
|
|
const VulkanCommandPool &commandPool)
|
|
: m_device(device), m_commandPool(commandPool)
|
|
{
|
|
VkCommandBufferAllocateInfo vkCommandBufferAllocateInfo = {};
|
|
vkCommandBufferAllocateInfo.sType =
|
|
VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
|
vkCommandBufferAllocateInfo.pNext = NULL;
|
|
vkCommandBufferAllocateInfo.commandPool = commandPool;
|
|
vkCommandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
|
vkCommandBufferAllocateInfo.commandBufferCount = 1;
|
|
|
|
vkAllocateCommandBuffers(m_device, &vkCommandBufferAllocateInfo,
|
|
&m_vkCommandBuffer);
|
|
}
|
|
|
|
VulkanCommandBuffer::~VulkanCommandBuffer()
|
|
{
|
|
vkFreeCommandBuffers(m_device, m_commandPool, 1, &m_vkCommandBuffer);
|
|
}
|
|
|
|
void VulkanCommandBuffer::begin()
|
|
{
|
|
VkCommandBufferBeginInfo vkCommandBufferBeginInfo = {};
|
|
vkCommandBufferBeginInfo.sType =
|
|
VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
|
vkCommandBufferBeginInfo.pNext = NULL;
|
|
vkCommandBufferBeginInfo.flags =
|
|
VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
|
|
vkCommandBufferBeginInfo.pInheritanceInfo = NULL;
|
|
|
|
vkBeginCommandBuffer(m_vkCommandBuffer, &vkCommandBufferBeginInfo);
|
|
}
|
|
|
|
void VulkanCommandBuffer::bindPipeline(const VulkanPipeline &pipeline)
|
|
{
|
|
VkPipelineBindPoint vkPipelineBindPoint =
|
|
(VkPipelineBindPoint)pipeline.getPipelineBindPoint();
|
|
|
|
vkCmdBindPipeline(m_vkCommandBuffer, vkPipelineBindPoint, pipeline);
|
|
}
|
|
|
|
void VulkanCommandBuffer::bindDescriptorSets(
|
|
const VulkanPipeline &pipeline, const VulkanPipelineLayout &pipelineLayout,
|
|
const VulkanDescriptorSet &descriptorSet)
|
|
{
|
|
VkPipelineBindPoint vkPipelineBindPoint =
|
|
(VkPipelineBindPoint)pipeline.getPipelineBindPoint();
|
|
VkDescriptorSet vkDescriptorSet = descriptorSet;
|
|
|
|
vkCmdBindDescriptorSets(m_vkCommandBuffer, vkPipelineBindPoint,
|
|
pipelineLayout, 0, 1, &vkDescriptorSet, 0, NULL);
|
|
}
|
|
|
|
void VulkanCommandBuffer::pipelineBarrier(const VulkanImage2DList &image2DList,
|
|
VulkanImageLayout oldImageLayout,
|
|
VulkanImageLayout newImageLayout)
|
|
{
|
|
std::vector<VkImageMemoryBarrier> vkImageMemoryBarrierList;
|
|
for (size_t i2DIdx = 0; i2DIdx < image2DList.size(); i2DIdx++)
|
|
{
|
|
VkImageSubresourceRange vkImageSubresourceRange = {};
|
|
vkImageSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
vkImageSubresourceRange.baseMipLevel = 0;
|
|
vkImageSubresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
|
|
vkImageSubresourceRange.baseArrayLayer = 0;
|
|
vkImageSubresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
|
|
|
|
VkImageMemoryBarrier vkImageMemoryBarrier = {};
|
|
vkImageMemoryBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
vkImageMemoryBarrier.pNext = NULL;
|
|
vkImageMemoryBarrier.srcAccessMask = 0;
|
|
vkImageMemoryBarrier.dstAccessMask = 0;
|
|
vkImageMemoryBarrier.oldLayout = (VkImageLayout)oldImageLayout;
|
|
vkImageMemoryBarrier.newLayout = (VkImageLayout)newImageLayout;
|
|
vkImageMemoryBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
vkImageMemoryBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
vkImageMemoryBarrier.image = image2DList[i2DIdx];
|
|
vkImageMemoryBarrier.subresourceRange = vkImageSubresourceRange;
|
|
|
|
vkImageMemoryBarrierList.push_back(vkImageMemoryBarrier);
|
|
}
|
|
|
|
vkCmdPipelineBarrier(m_vkCommandBuffer, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
|
|
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 0, NULL, 0,
|
|
NULL, (uint32_t)vkImageMemoryBarrierList.size(),
|
|
vkImageMemoryBarrierList.data());
|
|
}
|
|
|
|
void VulkanCommandBuffer::dispatch(uint32_t groupCountX, uint32_t groupCountY,
|
|
uint32_t groupCountZ)
|
|
{
|
|
vkCmdDispatch(m_vkCommandBuffer, groupCountX, groupCountY, groupCountZ);
|
|
}
|
|
|
|
void VulkanCommandBuffer::fillBuffer(const VulkanBuffer &buffer, uint32_t data,
|
|
uint64_t offset, uint64_t size)
|
|
{
|
|
vkCmdFillBuffer(m_vkCommandBuffer, buffer, offset, size, data);
|
|
}
|
|
|
|
void VulkanCommandBuffer::updateBuffer(const VulkanBuffer &buffer, void *pdata,
|
|
uint64_t offset, uint64_t size)
|
|
{
|
|
vkCmdUpdateBuffer(m_vkCommandBuffer, buffer, offset, size, pdata);
|
|
}
|
|
|
|
void VulkanCommandBuffer::copyBufferToImage(const VulkanBuffer &buffer,
|
|
const VulkanImage &image,
|
|
VulkanImageLayout imageLayout)
|
|
{
|
|
VkDeviceSize bufferOffset = 0;
|
|
|
|
std::vector<VkBufferImageCopy> vkBufferImageCopyList;
|
|
for (uint32_t mipLevel = 0; mipLevel < image.getNumMipLevels(); mipLevel++)
|
|
{
|
|
VulkanExtent3D extent3D = image.getExtent3D(mipLevel);
|
|
size_t elementSize = getVulkanFormatElementSize(image.getFormat());
|
|
|
|
VkImageSubresourceLayers vkImageSubresourceLayers = {};
|
|
vkImageSubresourceLayers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
vkImageSubresourceLayers.mipLevel = mipLevel;
|
|
vkImageSubresourceLayers.baseArrayLayer = 0;
|
|
vkImageSubresourceLayers.layerCount = image.getNumLayers();
|
|
|
|
VkBufferImageCopy vkBufferImageCopy = {};
|
|
vkBufferImageCopy.bufferOffset = bufferOffset;
|
|
vkBufferImageCopy.bufferRowLength = 0;
|
|
vkBufferImageCopy.bufferImageHeight = 0;
|
|
vkBufferImageCopy.imageSubresource = vkImageSubresourceLayers;
|
|
vkBufferImageCopy.imageOffset = VulkanOffset3D(0, 0, 0);
|
|
vkBufferImageCopy.imageExtent = extent3D;
|
|
|
|
vkBufferImageCopyList.push_back(vkBufferImageCopy);
|
|
|
|
bufferOffset += extent3D.getWidth() * extent3D.getHeight()
|
|
* extent3D.getDepth() * elementSize;
|
|
bufferOffset =
|
|
ROUND_UP(bufferOffset,
|
|
std::max(elementSize,
|
|
(size_t)VULKAN_MIN_BUFFER_OFFSET_COPY_ALIGNMENT));
|
|
}
|
|
|
|
vkCmdCopyBufferToImage(
|
|
m_vkCommandBuffer, buffer, image, (VkImageLayout)imageLayout,
|
|
(uint32_t)vkBufferImageCopyList.size(), vkBufferImageCopyList.data());
|
|
}
|
|
|
|
void VulkanCommandBuffer::copyBufferToImage(
|
|
const VulkanBuffer &buffer, const VulkanImage &image, uint64_t bufferOffset,
|
|
uint32_t mipLevel, uint32_t baseArrayLayer, uint32_t layerCount,
|
|
VulkanOffset3D offset3D, VulkanExtent3D extent3D)
|
|
{
|
|
VkImageSubresourceLayers vkImageSubresourceLayers = {};
|
|
vkImageSubresourceLayers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
vkImageSubresourceLayers.mipLevel = mipLevel;
|
|
vkImageSubresourceLayers.baseArrayLayer = baseArrayLayer;
|
|
vkImageSubresourceLayers.layerCount = layerCount;
|
|
|
|
VkExtent3D vkExtent3D = extent3D;
|
|
if ((extent3D.getWidth() == 0) && (extent3D.getHeight() == 0)
|
|
&& (extent3D.getDepth() == 0))
|
|
{
|
|
vkExtent3D = image.getExtent3D(mipLevel);
|
|
}
|
|
|
|
VkBufferImageCopy vkBufferImageCopy = {};
|
|
vkBufferImageCopy.bufferOffset = bufferOffset;
|
|
vkBufferImageCopy.bufferRowLength = 0;
|
|
vkBufferImageCopy.bufferImageHeight = 0;
|
|
vkBufferImageCopy.imageSubresource = vkImageSubresourceLayers;
|
|
vkBufferImageCopy.imageOffset = offset3D;
|
|
vkBufferImageCopy.imageExtent = vkExtent3D;
|
|
|
|
vkCmdCopyBufferToImage(m_vkCommandBuffer, buffer, image,
|
|
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1,
|
|
&vkBufferImageCopy);
|
|
}
|
|
|
|
void VulkanCommandBuffer::copyImageToBuffer(
|
|
const VulkanImage &image, const VulkanBuffer &buffer, uint64_t bufferOffset,
|
|
uint32_t mipLevel, uint32_t baseArrayLayer, uint32_t layerCount,
|
|
VulkanOffset3D offset3D, VulkanExtent3D extent3D)
|
|
{
|
|
VkImageSubresourceLayers vkImageSubresourceLayers = {};
|
|
vkImageSubresourceLayers.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
vkImageSubresourceLayers.mipLevel = mipLevel;
|
|
vkImageSubresourceLayers.baseArrayLayer = baseArrayLayer;
|
|
vkImageSubresourceLayers.layerCount = layerCount;
|
|
|
|
VkExtent3D vkExtent3D = extent3D;
|
|
if ((extent3D.getWidth() == 0) && (extent3D.getHeight() == 0)
|
|
&& (extent3D.getDepth() == 0))
|
|
{
|
|
vkExtent3D = image.getExtent3D(mipLevel);
|
|
}
|
|
|
|
VkBufferImageCopy vkBufferImageCopy = {};
|
|
vkBufferImageCopy.bufferOffset = bufferOffset;
|
|
vkBufferImageCopy.bufferRowLength = 0;
|
|
vkBufferImageCopy.bufferImageHeight = 0;
|
|
vkBufferImageCopy.imageSubresource = vkImageSubresourceLayers;
|
|
vkBufferImageCopy.imageOffset = offset3D;
|
|
vkBufferImageCopy.imageExtent = vkExtent3D;
|
|
|
|
vkCmdCopyImageToBuffer(m_vkCommandBuffer, image, VK_IMAGE_LAYOUT_GENERAL,
|
|
buffer, 1, &vkBufferImageCopy);
|
|
}
|
|
|
|
void VulkanCommandBuffer::end() { vkEndCommandBuffer(m_vkCommandBuffer); }
|
|
|
|
VulkanCommandBuffer::operator VkCommandBuffer() const
|
|
{
|
|
return m_vkCommandBuffer;
|
|
}
|
|
|
|
/////////////////////////////////
|
|
// VulkanBuffer implementation //
|
|
/////////////////////////////////
|
|
|
|
VulkanBuffer::VulkanBuffer(const VulkanBuffer &buffer)
|
|
: m_device(buffer.m_device), m_vkBuffer(buffer.m_vkBuffer),
|
|
m_size(buffer.m_size), m_alignment(buffer.m_alignment),
|
|
m_memoryTypeList(buffer.m_memoryTypeList)
|
|
{}
|
|
|
|
bool VulkanBuffer::isDedicated() const { return m_dedicated; }
|
|
|
|
VulkanBuffer::VulkanBuffer(
|
|
const VulkanDevice &device, uint64_t size,
|
|
VulkanExternalMemoryHandleType externalMemoryHandleType,
|
|
VulkanBufferUsage bufferUsage, VulkanSharingMode sharingMode,
|
|
const VulkanQueueFamilyList &queueFamilyList)
|
|
: m_device(device), m_vkBuffer(VK_NULL_HANDLE), m_dedicated(false)
|
|
{
|
|
std::vector<uint32_t> queueFamilyIndexList;
|
|
if (queueFamilyList.size() == 0)
|
|
{
|
|
for (size_t qfIdx = 0;
|
|
qfIdx < device.getPhysicalDevice().getQueueFamilyList().size();
|
|
qfIdx++)
|
|
{
|
|
queueFamilyIndexList.push_back(
|
|
device.getPhysicalDevice().getQueueFamilyList()[qfIdx]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (size_t qfIdx = 0; qfIdx < queueFamilyList.size(); qfIdx++)
|
|
{
|
|
queueFamilyIndexList.push_back(queueFamilyList[qfIdx]);
|
|
}
|
|
}
|
|
|
|
VkBufferCreateInfo vkBufferCreateInfo = {};
|
|
vkBufferCreateInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
|
vkBufferCreateInfo.pNext = NULL;
|
|
vkBufferCreateInfo.flags = 0;
|
|
vkBufferCreateInfo.size = (VkDeviceSize)size;
|
|
vkBufferCreateInfo.usage = (VkBufferUsageFlags)bufferUsage;
|
|
vkBufferCreateInfo.sharingMode = (VkSharingMode)sharingMode;
|
|
vkBufferCreateInfo.queueFamilyIndexCount =
|
|
(uint32_t)queueFamilyIndexList.size();
|
|
vkBufferCreateInfo.pQueueFamilyIndices = queueFamilyIndexList.data();
|
|
|
|
VkExternalMemoryBufferCreateInfo vkExternalMemoryBufferCreateInfo = {};
|
|
if (externalMemoryHandleType != VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE)
|
|
{
|
|
vkExternalMemoryBufferCreateInfo.sType =
|
|
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO_KHR;
|
|
vkExternalMemoryBufferCreateInfo.pNext = NULL;
|
|
vkExternalMemoryBufferCreateInfo.handleTypes =
|
|
(VkExternalMemoryHandleTypeFlags)externalMemoryHandleType;
|
|
|
|
vkBufferCreateInfo.pNext = &vkExternalMemoryBufferCreateInfo;
|
|
}
|
|
|
|
vkCreateBuffer(m_device, &vkBufferCreateInfo, NULL, &m_vkBuffer);
|
|
|
|
VkMemoryDedicatedRequirements vkMemoryDedicatedRequirements = {};
|
|
vkMemoryDedicatedRequirements.sType =
|
|
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
|
|
vkMemoryDedicatedRequirements.pNext = NULL;
|
|
|
|
VkMemoryRequirements2 vkMemoryRequirements = {};
|
|
vkMemoryRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
|
|
vkMemoryRequirements.pNext = &vkMemoryDedicatedRequirements;
|
|
|
|
VkBufferMemoryRequirementsInfo2 vkMemoryRequirementsInfo = {};
|
|
|
|
vkMemoryRequirementsInfo.sType =
|
|
VK_STRUCTURE_TYPE_BUFFER_MEMORY_REQUIREMENTS_INFO_2;
|
|
vkMemoryRequirementsInfo.buffer = m_vkBuffer;
|
|
vkMemoryRequirementsInfo.pNext = NULL;
|
|
|
|
vkGetBufferMemoryRequirements2(m_device, &vkMemoryRequirementsInfo,
|
|
&vkMemoryRequirements);
|
|
|
|
m_dedicated = vkMemoryDedicatedRequirements.requiresDedicatedAllocation;
|
|
|
|
m_size = vkMemoryRequirements.memoryRequirements.size;
|
|
m_alignment = vkMemoryRequirements.memoryRequirements.alignment;
|
|
const VulkanMemoryTypeList &memoryTypeList =
|
|
m_device.getPhysicalDevice().getMemoryTypeList();
|
|
for (size_t mtIdx = 0; mtIdx < memoryTypeList.size(); mtIdx++)
|
|
{
|
|
uint32_t memoryTypeIndex = memoryTypeList[mtIdx];
|
|
if ((1 << memoryTypeIndex)
|
|
& vkMemoryRequirements.memoryRequirements.memoryTypeBits)
|
|
{
|
|
m_memoryTypeList.add(memoryTypeList[mtIdx]);
|
|
}
|
|
}
|
|
}
|
|
|
|
VulkanBuffer::~VulkanBuffer() { vkDestroyBuffer(m_device, m_vkBuffer, NULL); }
|
|
|
|
uint64_t VulkanBuffer::getSize() const { return m_size; }
|
|
|
|
uint64_t VulkanBuffer::getAlignment() const { return m_alignment; }
|
|
|
|
const VulkanMemoryTypeList &VulkanBuffer::getMemoryTypeList() const
|
|
{
|
|
return m_memoryTypeList;
|
|
}
|
|
|
|
VulkanBuffer::operator VkBuffer() const { return m_vkBuffer; }
|
|
|
|
////////////////////////////////
|
|
// VulkanImage implementation //
|
|
////////////////////////////////
|
|
|
|
VulkanImage::VulkanImage(const VulkanImage &image)
|
|
: m_device(image.m_device), m_imageType(image.m_imageType),
|
|
m_extent3D(image.m_extent3D), m_format(image.m_format),
|
|
m_numMipLevels(image.m_numMipLevels), m_numLayers(image.m_numLayers),
|
|
m_vkImage(image.m_vkImage), m_size(image.m_size),
|
|
m_alignment(image.m_alignment), m_memoryTypeList(image.m_memoryTypeList)
|
|
{}
|
|
|
|
VulkanImage::VulkanImage(
|
|
const VulkanDevice &device, VulkanImageType imageType, VulkanFormat format,
|
|
const VulkanExtent3D &extent3D, uint32_t numMipLevels, uint32_t arrayLayers,
|
|
VulkanExternalMemoryHandleType externalMemoryHandleType,
|
|
VulkanImageCreateFlag imageCreateFlag, VulkanImageTiling imageTiling,
|
|
VulkanImageUsage imageUsage, VulkanSharingMode sharingMode)
|
|
: m_device(device), m_imageType(imageType), m_extent3D(extent3D),
|
|
m_format(format), m_numMipLevels(numMipLevels), m_numLayers(arrayLayers),
|
|
m_vkImage(VK_NULL_HANDLE)
|
|
{
|
|
VkImageCreateInfo vkImageCreateInfo = {};
|
|
vkImageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
|
|
vkImageCreateInfo.pNext = NULL;
|
|
vkImageCreateInfo.flags = (VkImageCreateFlags)imageCreateFlag;
|
|
vkImageCreateInfo.imageType = (VkImageType)imageType;
|
|
vkImageCreateInfo.format = (VkFormat)format;
|
|
vkImageCreateInfo.extent = extent3D;
|
|
vkImageCreateInfo.mipLevels = numMipLevels;
|
|
vkImageCreateInfo.arrayLayers = arrayLayers;
|
|
vkImageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
|
|
vkImageCreateInfo.tiling = (VkImageTiling)imageTiling;
|
|
vkImageCreateInfo.usage = (VkImageUsageFlags)imageUsage;
|
|
vkImageCreateInfo.sharingMode = (VkSharingMode)sharingMode;
|
|
vkImageCreateInfo.queueFamilyIndexCount =
|
|
(uint32_t)m_device.getPhysicalDevice().getQueueFamilyList().size();
|
|
vkImageCreateInfo.pQueueFamilyIndices =
|
|
m_device.getPhysicalDevice().getQueueFamilyList()();
|
|
vkImageCreateInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
|
VkExternalMemoryImageCreateInfo vkExternalMemoryImageCreateInfo = {};
|
|
if (externalMemoryHandleType != VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_NONE)
|
|
{
|
|
vkExternalMemoryImageCreateInfo.sType =
|
|
VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO;
|
|
vkExternalMemoryImageCreateInfo.pNext = NULL;
|
|
vkExternalMemoryImageCreateInfo.handleTypes =
|
|
(VkExternalMemoryHandleTypeFlags)externalMemoryHandleType;
|
|
|
|
vkImageCreateInfo.pNext = &vkExternalMemoryImageCreateInfo;
|
|
}
|
|
|
|
VkResult vkStatus =
|
|
vkCreateImage(m_device, &vkImageCreateInfo, NULL, &m_vkImage);
|
|
if (vkStatus != VK_SUCCESS)
|
|
{
|
|
throw std::runtime_error("Error: Failed create image.");
|
|
}
|
|
|
|
VulkanImageCreateInfo = vkImageCreateInfo;
|
|
|
|
VkMemoryDedicatedRequirements vkMemoryDedicatedRequirements = {};
|
|
vkMemoryDedicatedRequirements.sType =
|
|
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS;
|
|
vkMemoryDedicatedRequirements.pNext = NULL;
|
|
|
|
VkMemoryRequirements2 vkMemoryRequirements = {};
|
|
vkMemoryRequirements.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2;
|
|
vkMemoryRequirements.pNext = &vkMemoryDedicatedRequirements;
|
|
|
|
VkImageMemoryRequirementsInfo2 vkMemoryRequirementsInfo = {};
|
|
|
|
vkMemoryRequirementsInfo.sType =
|
|
VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2;
|
|
vkMemoryRequirementsInfo.image = m_vkImage;
|
|
vkMemoryRequirementsInfo.pNext = NULL;
|
|
|
|
vkGetImageMemoryRequirements2(m_device, &vkMemoryRequirementsInfo,
|
|
&vkMemoryRequirements);
|
|
m_size = vkMemoryRequirements.memoryRequirements.size;
|
|
m_alignment = vkMemoryRequirements.memoryRequirements.alignment;
|
|
m_dedicated = vkMemoryDedicatedRequirements.requiresDedicatedAllocation;
|
|
|
|
const VulkanMemoryTypeList &memoryTypeList =
|
|
m_device.getPhysicalDevice().getMemoryTypeList();
|
|
for (size_t mtIdx = 0; mtIdx < memoryTypeList.size(); mtIdx++)
|
|
{
|
|
uint32_t memoryTypeIndex = memoryTypeList[mtIdx];
|
|
if ((1 << memoryTypeIndex)
|
|
& vkMemoryRequirements.memoryRequirements.memoryTypeBits)
|
|
{
|
|
m_memoryTypeList.add(memoryTypeList[mtIdx]);
|
|
}
|
|
}
|
|
}
|
|
|
|
VulkanImage::~VulkanImage() { vkDestroyImage(m_device, m_vkImage, NULL); }
|
|
|
|
VulkanExtent3D VulkanImage::getExtent3D(uint32_t mipLevel) const
|
|
{
|
|
return VulkanExtent3D(0, 0, 0);
|
|
}
|
|
|
|
VulkanFormat VulkanImage::getFormat() const { return m_format; }
|
|
|
|
VkImageCreateInfo VulkanImage::getVkImageCreateInfo() const
|
|
{
|
|
return VulkanImageCreateInfo;
|
|
}
|
|
|
|
uint32_t VulkanImage::getNumMipLevels() const { return m_numMipLevels; }
|
|
|
|
uint32_t VulkanImage::getNumLayers() const { return m_numLayers; }
|
|
|
|
uint64_t VulkanImage::getSize() const { return m_size; }
|
|
|
|
uint64_t VulkanImage::getAlignment() const { return m_alignment; }
|
|
|
|
bool VulkanImage::isDedicated() const { return m_dedicated; }
|
|
|
|
const VulkanMemoryTypeList &VulkanImage::getMemoryTypeList() const
|
|
{
|
|
return m_memoryTypeList;
|
|
}
|
|
|
|
VulkanImage::operator VkImage() const { return m_vkImage; }
|
|
|
|
//////////////////////////////////
|
|
// VulkanImage1D implementation //
|
|
//////////////////////////////////
|
|
|
|
VulkanImage1D::VulkanImage1D(const VulkanImage1D &image1D): VulkanImage(image1D)
|
|
{}
|
|
|
|
VulkanImage1D::VulkanImage1D(
|
|
const VulkanDevice &device, VulkanFormat format, uint32_t width,
|
|
VulkanImageTiling imageTiling, uint32_t numMipLevels,
|
|
VulkanExternalMemoryHandleType externalMemoryHandleType,
|
|
VulkanImageCreateFlag imageCreateFlag, VulkanImageUsage imageUsage,
|
|
VulkanSharingMode sharingMode)
|
|
: VulkanImage(device, VULKAN_IMAGE_TYPE_1D, format,
|
|
VulkanExtent3D(width, 1, 1), numMipLevels, 1,
|
|
externalMemoryHandleType, imageCreateFlag, imageTiling,
|
|
imageUsage, sharingMode)
|
|
{}
|
|
|
|
VulkanImage1D::~VulkanImage1D() {}
|
|
|
|
VulkanExtent3D VulkanImage1D::getExtent3D(uint32_t mipLevel) const
|
|
{
|
|
uint32_t width = std::max(m_extent3D.getWidth() >> mipLevel, uint32_t(1));
|
|
uint32_t height = 1;
|
|
uint32_t depth = 1;
|
|
|
|
return VulkanExtent3D(width, height, depth);
|
|
}
|
|
|
|
//////////////////////////////////
|
|
// VulkanImage2D implementation //
|
|
//////////////////////////////////
|
|
|
|
VulkanImage2D::VulkanImage2D(const VulkanImage2D &image2D): VulkanImage(image2D)
|
|
{}
|
|
|
|
VulkanImage2D::VulkanImage2D(
|
|
const VulkanDevice &device, VulkanFormat format, uint32_t width,
|
|
uint32_t height, VulkanImageTiling imageTiling, uint32_t numMipLevels,
|
|
VulkanExternalMemoryHandleType externalMemoryHandleType,
|
|
VulkanImageCreateFlag imageCreateFlag, VulkanImageUsage imageUsage,
|
|
VulkanSharingMode sharingMode)
|
|
: VulkanImage(device, VULKAN_IMAGE_TYPE_2D, format,
|
|
VulkanExtent3D(width, height, 1), numMipLevels, 1,
|
|
externalMemoryHandleType, imageCreateFlag, imageTiling,
|
|
imageUsage, sharingMode)
|
|
{}
|
|
|
|
VulkanImage2D::~VulkanImage2D() {}
|
|
|
|
VulkanExtent3D VulkanImage2D::getExtent3D(uint32_t mipLevel) const
|
|
{
|
|
uint32_t width = std::max(m_extent3D.getWidth() >> mipLevel, uint32_t(1));
|
|
uint32_t height = std::max(m_extent3D.getHeight() >> mipLevel, uint32_t(1));
|
|
uint32_t depth = 1;
|
|
|
|
return VulkanExtent3D(width, height, depth);
|
|
}
|
|
|
|
VkSubresourceLayout VulkanImage::getSubresourceLayout() const
|
|
{
|
|
VkImageSubresource subresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0 };
|
|
|
|
VkSubresourceLayout subresourceLayout = { 0 };
|
|
vkGetImageSubresourceLayout(m_device, m_vkImage, &subresource,
|
|
&subresourceLayout);
|
|
return subresourceLayout;
|
|
}
|
|
|
|
//////////////////////////////////
|
|
// VulkanImage3D implementation //
|
|
//////////////////////////////////
|
|
|
|
VulkanImage3D::VulkanImage3D(const VulkanImage3D &image3D): VulkanImage(image3D)
|
|
{}
|
|
|
|
VulkanImage3D::VulkanImage3D(
|
|
const VulkanDevice &device, VulkanFormat format, uint32_t width,
|
|
uint32_t height, uint32_t depth, VulkanImageTiling imageTiling,
|
|
uint32_t numMipLevels,
|
|
VulkanExternalMemoryHandleType externalMemoryHandleType,
|
|
VulkanImageCreateFlag imageCreateFlag, VulkanImageUsage imageUsage,
|
|
VulkanSharingMode sharingMode)
|
|
: VulkanImage(device, VULKAN_IMAGE_TYPE_3D, format,
|
|
VulkanExtent3D(width, height, depth), numMipLevels, 1,
|
|
externalMemoryHandleType, imageCreateFlag, imageTiling,
|
|
imageUsage, sharingMode)
|
|
{}
|
|
|
|
VulkanImage3D::~VulkanImage3D() {}
|
|
|
|
VulkanExtent3D VulkanImage3D::getExtent3D(uint32_t mipLevel) const
|
|
{
|
|
uint32_t width = std::max(m_extent3D.getWidth() >> mipLevel, uint32_t(1));
|
|
uint32_t height = std::max(m_extent3D.getHeight() >> mipLevel, uint32_t(1));
|
|
uint32_t depth = std::max(m_extent3D.getDepth() >> mipLevel, uint32_t(1));
|
|
|
|
return VulkanExtent3D(width, height, depth);
|
|
}
|
|
|
|
////////////////////////////////////
|
|
// VulkanImageView implementation //
|
|
////////////////////////////////////
|
|
|
|
VulkanImageView::VulkanImageView(const VulkanImageView &imageView)
|
|
: m_device(imageView.m_device), m_vkImageView(imageView.m_vkImageView)
|
|
{}
|
|
|
|
VulkanImageView::VulkanImageView(const VulkanDevice &device,
|
|
const VulkanImage &image,
|
|
VulkanImageViewType imageViewType,
|
|
uint32_t baseMipLevel, uint32_t levelCount,
|
|
uint32_t baseArrayLayer, uint32_t layerCount)
|
|
: m_device(device), m_vkImageView(VK_NULL_HANDLE)
|
|
{
|
|
VkComponentMapping vkComponentMapping = {};
|
|
vkComponentMapping.r = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
vkComponentMapping.g = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
vkComponentMapping.b = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
vkComponentMapping.a = VK_COMPONENT_SWIZZLE_IDENTITY;
|
|
|
|
VkImageSubresourceRange vkImageSubresourceRange = {};
|
|
vkImageSubresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
vkImageSubresourceRange.baseMipLevel = baseMipLevel;
|
|
vkImageSubresourceRange.levelCount = levelCount;
|
|
vkImageSubresourceRange.baseArrayLayer = baseArrayLayer;
|
|
vkImageSubresourceRange.layerCount = layerCount;
|
|
|
|
VkImageViewCreateInfo vkImageViewCreateInfo = {};
|
|
vkImageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
|
|
vkImageViewCreateInfo.pNext = NULL;
|
|
vkImageViewCreateInfo.flags = 0;
|
|
vkImageViewCreateInfo.image = image;
|
|
vkImageViewCreateInfo.viewType = (VkImageViewType)imageViewType;
|
|
vkImageViewCreateInfo.format = (VkFormat)image.getFormat();
|
|
vkImageViewCreateInfo.components = vkComponentMapping;
|
|
vkImageViewCreateInfo.subresourceRange = vkImageSubresourceRange;
|
|
|
|
vkCreateImageView(m_device, &vkImageViewCreateInfo, NULL, &m_vkImageView);
|
|
}
|
|
|
|
VulkanImageView::~VulkanImageView()
|
|
{
|
|
vkDestroyImageView(m_device, m_vkImageView, NULL);
|
|
}
|
|
|
|
VulkanImageView::operator VkImageView() const { return m_vkImageView; }
|
|
|
|
///////////////////////////////////////
|
|
// VulkanDeviceMemory implementation //
|
|
///////////////////////////////////////
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
|
|
class WindowsSecurityAttributes {
|
|
protected:
|
|
SECURITY_ATTRIBUTES m_winSecurityAttributes;
|
|
PSECURITY_DESCRIPTOR m_winPSecurityDescriptor;
|
|
|
|
public:
|
|
WindowsSecurityAttributes();
|
|
SECURITY_ATTRIBUTES *operator&();
|
|
~WindowsSecurityAttributes();
|
|
};
|
|
|
|
WindowsSecurityAttributes::WindowsSecurityAttributes()
|
|
{
|
|
#define CHECK(ok, msg) \
|
|
if (!ok) \
|
|
{ \
|
|
throw std::runtime_error(msg); \
|
|
}
|
|
|
|
BOOL ok;
|
|
HANDLE tokenHandle;
|
|
|
|
ok = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &tokenHandle);
|
|
CHECK(ok, "Failed to open process access token");
|
|
|
|
DWORD tokenInformationLength = 0;
|
|
GetTokenInformation(tokenHandle, TokenDefaultDacl, NULL, 0,
|
|
&tokenInformationLength);
|
|
CHECK(tokenInformationLength,
|
|
"Failed to retrieve TokenDefaultDacl info buffer length");
|
|
|
|
m_winPSecurityDescriptor = (PSECURITY_DESCRIPTOR)calloc(
|
|
1, SECURITY_DESCRIPTOR_MIN_LENGTH + tokenInformationLength);
|
|
assert(m_winPSecurityDescriptor != (PSECURITY_DESCRIPTOR)NULL);
|
|
|
|
TOKEN_DEFAULT_DACL *pTokenDefaultDacl =
|
|
reinterpret_cast<TOKEN_DEFAULT_DACL *>(
|
|
(PBYTE)m_winPSecurityDescriptor + SECURITY_DESCRIPTOR_MIN_LENGTH);
|
|
ok = GetTokenInformation(tokenHandle, TokenDefaultDacl, pTokenDefaultDacl,
|
|
tokenInformationLength, &tokenInformationLength);
|
|
CHECK(ok, "Failed to retrieve TokenDefaultDacl info of access token");
|
|
|
|
ok = InitializeSecurityDescriptor(m_winPSecurityDescriptor,
|
|
SECURITY_DESCRIPTOR_REVISION);
|
|
CHECK(ok, "Failed to init security descriptor");
|
|
|
|
ok = SetSecurityDescriptorDacl(m_winPSecurityDescriptor, TRUE,
|
|
pTokenDefaultDacl->DefaultDacl, FALSE);
|
|
CHECK(ok, "Failed to set DACL info for given security descriptor");
|
|
|
|
m_winSecurityAttributes.nLength = sizeof(m_winSecurityAttributes);
|
|
m_winSecurityAttributes.lpSecurityDescriptor = m_winPSecurityDescriptor;
|
|
m_winSecurityAttributes.bInheritHandle = TRUE;
|
|
|
|
CloseHandle(tokenHandle);
|
|
#undef CHECK_WIN
|
|
}
|
|
|
|
SECURITY_ATTRIBUTES *WindowsSecurityAttributes::operator&()
|
|
{
|
|
return &m_winSecurityAttributes;
|
|
}
|
|
|
|
WindowsSecurityAttributes::~WindowsSecurityAttributes()
|
|
{
|
|
free(m_winPSecurityDescriptor);
|
|
}
|
|
|
|
#endif
|
|
|
|
VulkanDeviceMemory::VulkanDeviceMemory(const VulkanDeviceMemory &deviceMemory)
|
|
: m_device(deviceMemory.m_device),
|
|
m_vkDeviceMemory(deviceMemory.m_vkDeviceMemory),
|
|
m_size(deviceMemory.m_size), m_isDedicated(deviceMemory.m_isDedicated)
|
|
{}
|
|
|
|
VulkanDeviceMemory::VulkanDeviceMemory(
|
|
const VulkanDevice &device, uint64_t size,
|
|
const VulkanMemoryType &memoryType,
|
|
VulkanExternalMemoryHandleType externalMemoryHandleType,
|
|
const std::wstring name)
|
|
: m_device(device), m_size(size), m_isDedicated(false), m_name(name)
|
|
{
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
WindowsSecurityAttributes winSecurityAttributes;
|
|
|
|
VkExportMemoryWin32HandleInfoKHR vkExportMemoryWin32HandleInfoKHR = {};
|
|
vkExportMemoryWin32HandleInfoKHR.sType =
|
|
VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR;
|
|
vkExportMemoryWin32HandleInfoKHR.pNext = NULL;
|
|
vkExportMemoryWin32HandleInfoKHR.pAttributes = &winSecurityAttributes;
|
|
vkExportMemoryWin32HandleInfoKHR.dwAccess =
|
|
DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;
|
|
vkExportMemoryWin32HandleInfoKHR.name = NULL;
|
|
|
|
if (externalMemoryHandleType
|
|
== VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT_NAME)
|
|
{
|
|
vkExportMemoryWin32HandleInfoKHR.name = (LPCWSTR)m_name.c_str();
|
|
externalMemoryHandleType =
|
|
VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT;
|
|
}
|
|
#endif
|
|
|
|
VkExportMemoryAllocateInfoKHR vkExportMemoryAllocateInfoKHR = {};
|
|
vkExportMemoryAllocateInfoKHR.sType =
|
|
VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
vkExportMemoryAllocateInfoKHR.pNext = externalMemoryHandleType
|
|
& VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT
|
|
? &vkExportMemoryWin32HandleInfoKHR
|
|
: NULL;
|
|
#else
|
|
vkExportMemoryAllocateInfoKHR.pNext = NULL;
|
|
#endif
|
|
vkExportMemoryAllocateInfoKHR.handleTypes =
|
|
(VkExternalMemoryHandleTypeFlagsKHR)externalMemoryHandleType;
|
|
|
|
VkMemoryAllocateInfo vkMemoryAllocateInfo = {};
|
|
vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
vkMemoryAllocateInfo.pNext =
|
|
externalMemoryHandleType ? &vkExportMemoryAllocateInfoKHR : NULL;
|
|
vkMemoryAllocateInfo.allocationSize = m_size;
|
|
vkMemoryAllocateInfo.memoryTypeIndex = (uint32_t)memoryType;
|
|
|
|
vkAllocateMemory(m_device, &vkMemoryAllocateInfo, NULL, &m_vkDeviceMemory);
|
|
}
|
|
|
|
VulkanDeviceMemory::VulkanDeviceMemory(
|
|
const VulkanDevice &device, const VulkanImage &image,
|
|
const VulkanMemoryType &memoryType,
|
|
VulkanExternalMemoryHandleType externalMemoryHandleType,
|
|
const std::wstring name)
|
|
: m_device(device), m_size(image.getSize()),
|
|
m_isDedicated(image.isDedicated()), m_name(name)
|
|
{
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
WindowsSecurityAttributes winSecurityAttributes;
|
|
|
|
VkExportMemoryWin32HandleInfoKHR vkExportMemoryWin32HandleInfoKHR = {};
|
|
vkExportMemoryWin32HandleInfoKHR.sType =
|
|
VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR;
|
|
vkExportMemoryWin32HandleInfoKHR.pNext = NULL;
|
|
vkExportMemoryWin32HandleInfoKHR.pAttributes = &winSecurityAttributes;
|
|
vkExportMemoryWin32HandleInfoKHR.dwAccess =
|
|
DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;
|
|
vkExportMemoryWin32HandleInfoKHR.name = NULL;
|
|
|
|
if (externalMemoryHandleType
|
|
== VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT_NAME)
|
|
{
|
|
vkExportMemoryWin32HandleInfoKHR.name = (LPCWSTR)m_name.c_str();
|
|
externalMemoryHandleType =
|
|
VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT;
|
|
}
|
|
#endif
|
|
|
|
VkExportMemoryAllocateInfoKHR vkExportMemoryAllocateInfoKHR = {};
|
|
vkExportMemoryAllocateInfoKHR.sType =
|
|
VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
vkExportMemoryAllocateInfoKHR.pNext = externalMemoryHandleType
|
|
& VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT
|
|
? &vkExportMemoryWin32HandleInfoKHR
|
|
: NULL;
|
|
#else
|
|
vkExportMemoryAllocateInfoKHR.pNext = NULL;
|
|
#endif
|
|
vkExportMemoryAllocateInfoKHR.handleTypes =
|
|
(VkExternalMemoryHandleTypeFlagsKHR)externalMemoryHandleType;
|
|
|
|
VkMemoryDedicatedAllocateInfo vkMemoryDedicatedAllocateInfo = {};
|
|
vkMemoryDedicatedAllocateInfo.sType =
|
|
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
|
|
vkMemoryDedicatedAllocateInfo.pNext = NULL;
|
|
vkMemoryDedicatedAllocateInfo.image = image;
|
|
vkMemoryDedicatedAllocateInfo.buffer = VK_NULL_HANDLE;
|
|
|
|
VkMemoryAllocateInfo vkMemoryAllocateInfo = {};
|
|
vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
vkMemoryAllocateInfo.allocationSize = m_size;
|
|
vkMemoryAllocateInfo.memoryTypeIndex = (uint32_t)memoryType;
|
|
|
|
if (m_isDedicated)
|
|
{
|
|
vkMemoryAllocateInfo.pNext = &vkMemoryDedicatedAllocateInfo;
|
|
vkMemoryDedicatedAllocateInfo.pNext =
|
|
externalMemoryHandleType ? &vkExportMemoryAllocateInfoKHR : NULL;
|
|
}
|
|
else
|
|
{
|
|
vkMemoryAllocateInfo.pNext =
|
|
externalMemoryHandleType ? &vkExportMemoryAllocateInfoKHR : NULL;
|
|
}
|
|
|
|
vkAllocateMemory(m_device, &vkMemoryAllocateInfo, NULL, &m_vkDeviceMemory);
|
|
}
|
|
|
|
VulkanDeviceMemory::VulkanDeviceMemory(
|
|
const VulkanDevice &device, const VulkanBuffer &buffer,
|
|
const VulkanMemoryType &memoryType,
|
|
VulkanExternalMemoryHandleType externalMemoryHandleType,
|
|
const std::wstring name)
|
|
: m_device(device), m_size(buffer.getSize()),
|
|
m_isDedicated(buffer.isDedicated()), m_name(name)
|
|
{
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
WindowsSecurityAttributes winSecurityAttributes;
|
|
|
|
VkExportMemoryWin32HandleInfoKHR vkExportMemoryWin32HandleInfoKHR = {};
|
|
vkExportMemoryWin32HandleInfoKHR.sType =
|
|
VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_KHR;
|
|
vkExportMemoryWin32HandleInfoKHR.pNext = NULL;
|
|
vkExportMemoryWin32HandleInfoKHR.pAttributes = &winSecurityAttributes;
|
|
vkExportMemoryWin32HandleInfoKHR.dwAccess =
|
|
DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;
|
|
vkExportMemoryWin32HandleInfoKHR.name = NULL;
|
|
|
|
if (externalMemoryHandleType
|
|
== VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT_NAME)
|
|
{
|
|
vkExportMemoryWin32HandleInfoKHR.name = (LPCWSTR)m_name.c_str();
|
|
externalMemoryHandleType =
|
|
VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT;
|
|
}
|
|
#endif
|
|
|
|
VkExportMemoryAllocateInfoKHR vkExportMemoryAllocateInfoKHR = {};
|
|
vkExportMemoryAllocateInfoKHR.sType =
|
|
VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
vkExportMemoryAllocateInfoKHR.pNext = externalMemoryHandleType
|
|
& VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT
|
|
? &vkExportMemoryWin32HandleInfoKHR
|
|
: NULL;
|
|
#else
|
|
vkExportMemoryAllocateInfoKHR.pNext = NULL;
|
|
#endif
|
|
vkExportMemoryAllocateInfoKHR.handleTypes =
|
|
(VkExternalMemoryHandleTypeFlagsKHR)externalMemoryHandleType;
|
|
|
|
VkMemoryDedicatedAllocateInfo vkMemoryDedicatedAllocateInfo = {};
|
|
vkMemoryDedicatedAllocateInfo.sType =
|
|
VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO;
|
|
vkMemoryDedicatedAllocateInfo.pNext = NULL;
|
|
vkMemoryDedicatedAllocateInfo.image = VK_NULL_HANDLE;
|
|
vkMemoryDedicatedAllocateInfo.buffer = buffer;
|
|
|
|
VkMemoryAllocateInfo vkMemoryAllocateInfo = {};
|
|
vkMemoryAllocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
|
vkMemoryAllocateInfo.allocationSize = m_size;
|
|
vkMemoryAllocateInfo.memoryTypeIndex = (uint32_t)memoryType;
|
|
|
|
if (m_isDedicated)
|
|
{
|
|
vkMemoryAllocateInfo.pNext = &vkMemoryDedicatedAllocateInfo;
|
|
vkMemoryDedicatedAllocateInfo.pNext =
|
|
externalMemoryHandleType ? &vkExportMemoryAllocateInfoKHR : NULL;
|
|
}
|
|
else
|
|
{
|
|
vkMemoryAllocateInfo.pNext =
|
|
externalMemoryHandleType ? &vkExportMemoryAllocateInfoKHR : NULL;
|
|
}
|
|
|
|
|
|
VkResult res = vkAllocateMemory(m_device, &vkMemoryAllocateInfo, NULL,
|
|
&m_vkDeviceMemory);
|
|
ASSERT_SUCCESS(res, "Failed to allocate device memory");
|
|
}
|
|
|
|
VulkanDeviceMemory::~VulkanDeviceMemory()
|
|
{
|
|
vkFreeMemory(m_device, m_vkDeviceMemory, NULL);
|
|
}
|
|
|
|
uint64_t VulkanDeviceMemory::getSize() const { return m_size; }
|
|
|
|
#ifdef _WIN32
|
|
HANDLE VulkanDeviceMemory::getHandle(
|
|
VulkanExternalMemoryHandleType externalMemoryHandleType) const
|
|
{
|
|
HANDLE handle;
|
|
|
|
VkMemoryGetWin32HandleInfoKHR vkMemoryGetWin32HandleInfoKHR = {};
|
|
vkMemoryGetWin32HandleInfoKHR.sType =
|
|
VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
|
|
vkMemoryGetWin32HandleInfoKHR.pNext = NULL;
|
|
vkMemoryGetWin32HandleInfoKHR.memory = m_vkDeviceMemory;
|
|
vkMemoryGetWin32HandleInfoKHR.handleType =
|
|
(VkExternalMemoryHandleTypeFlagBitsKHR)externalMemoryHandleType;
|
|
|
|
vkGetMemoryWin32HandleKHR(m_device, &vkMemoryGetWin32HandleInfoKHR,
|
|
&handle);
|
|
|
|
return handle;
|
|
}
|
|
#else
|
|
int VulkanDeviceMemory::getHandle(
|
|
VulkanExternalMemoryHandleType externalMemoryHandleType) const
|
|
{
|
|
if (externalMemoryHandleType
|
|
== VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD)
|
|
{
|
|
int fd;
|
|
|
|
VkMemoryGetFdInfoKHR vkMemoryGetFdInfoKHR = {};
|
|
vkMemoryGetFdInfoKHR.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
|
|
vkMemoryGetFdInfoKHR.pNext = NULL;
|
|
vkMemoryGetFdInfoKHR.memory = m_vkDeviceMemory;
|
|
vkMemoryGetFdInfoKHR.handleType =
|
|
VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
|
|
|
|
vkGetMemoryFdKHR(m_device, &vkMemoryGetFdInfoKHR, &fd);
|
|
|
|
return fd;
|
|
}
|
|
return HANDLE_ERROR;
|
|
}
|
|
#endif
|
|
|
|
bool VulkanDeviceMemory::isDedicated() const { return m_isDedicated; }
|
|
|
|
void *VulkanDeviceMemory::map(size_t offset, size_t size)
|
|
{
|
|
void *pData;
|
|
|
|
vkMapMemory(m_device, m_vkDeviceMemory, (VkDeviceSize)offset,
|
|
(VkDeviceSize)size, 0, &pData);
|
|
|
|
return pData;
|
|
}
|
|
|
|
void VulkanDeviceMemory::unmap() { vkUnmapMemory(m_device, m_vkDeviceMemory); }
|
|
|
|
void VulkanDeviceMemory::bindBuffer(const VulkanBuffer &buffer, uint64_t offset)
|
|
{
|
|
if (buffer.isDedicated() && !m_isDedicated)
|
|
{
|
|
throw std::runtime_error(
|
|
"Buffer requires dedicated memory. Failed to bind");
|
|
}
|
|
vkBindBufferMemory(m_device, buffer, m_vkDeviceMemory, offset);
|
|
}
|
|
|
|
void VulkanDeviceMemory::bindImage(const VulkanImage &image, uint64_t offset)
|
|
{
|
|
if (image.isDedicated() && !m_isDedicated)
|
|
{
|
|
throw std::runtime_error(
|
|
"Image requires dedicated memory. Failed to bind");
|
|
}
|
|
vkBindImageMemory(m_device, image, m_vkDeviceMemory, offset);
|
|
}
|
|
|
|
const std::wstring &VulkanDeviceMemory::getName() const { return m_name; }
|
|
|
|
VulkanDeviceMemory::operator VkDeviceMemory() const { return m_vkDeviceMemory; }
|
|
|
|
////////////////////////////////////
|
|
// VulkanSemaphore implementation //
|
|
////////////////////////////////////
|
|
|
|
VulkanSemaphore::VulkanSemaphore(const VulkanSemaphore &semaphore)
|
|
: m_device(semaphore.m_device), m_vkSemaphore(semaphore.m_vkSemaphore)
|
|
{}
|
|
|
|
VulkanSemaphore::VulkanSemaphore(
|
|
const VulkanDevice &device,
|
|
VulkanExternalSemaphoreHandleType externalSemaphoreHandleType,
|
|
const std::wstring name)
|
|
: m_device(device), m_name(name)
|
|
{
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
WindowsSecurityAttributes winSecurityAttributes;
|
|
|
|
VkExportSemaphoreWin32HandleInfoKHR
|
|
vkExportSemaphoreWin32HandleInfoKHR = {};
|
|
vkExportSemaphoreWin32HandleInfoKHR.sType =
|
|
VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_WIN32_HANDLE_INFO_KHR;
|
|
vkExportSemaphoreWin32HandleInfoKHR.pNext = NULL;
|
|
vkExportSemaphoreWin32HandleInfoKHR.pAttributes = &winSecurityAttributes;
|
|
vkExportSemaphoreWin32HandleInfoKHR.dwAccess =
|
|
DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE;
|
|
vkExportSemaphoreWin32HandleInfoKHR.name = NULL;
|
|
|
|
if (externalSemaphoreHandleType
|
|
== VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT_NAME)
|
|
{
|
|
vkExportSemaphoreWin32HandleInfoKHR.name = (LPCWSTR)m_name.c_str();
|
|
externalSemaphoreHandleType =
|
|
VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_NT;
|
|
}
|
|
#endif
|
|
|
|
VkExportSemaphoreCreateInfoKHR vkExportSemaphoreCreateInfoKHR = {};
|
|
vkExportSemaphoreCreateInfoKHR.sType =
|
|
VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO_KHR;
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
vkExportSemaphoreCreateInfoKHR.pNext =
|
|
(externalSemaphoreHandleType
|
|
& VULKAN_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_NT)
|
|
? &vkExportSemaphoreWin32HandleInfoKHR
|
|
: NULL;
|
|
#else
|
|
vkExportSemaphoreCreateInfoKHR.pNext = NULL;
|
|
#endif
|
|
vkExportSemaphoreCreateInfoKHR.handleTypes =
|
|
(VkExternalSemaphoreHandleTypeFlagsKHR)externalSemaphoreHandleType;
|
|
|
|
VkSemaphoreCreateInfo vkSemaphoreCreateInfo = {};
|
|
vkSemaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
|
vkSemaphoreCreateInfo.pNext =
|
|
(externalSemaphoreHandleType
|
|
!= VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_NONE)
|
|
? &vkExportSemaphoreCreateInfoKHR
|
|
: NULL;
|
|
vkSemaphoreCreateInfo.flags = 0;
|
|
|
|
vkCreateSemaphore(m_device, &vkSemaphoreCreateInfo, NULL, &m_vkSemaphore);
|
|
}
|
|
|
|
const VulkanDevice &VulkanSemaphore::getDevice() const { return m_device; }
|
|
|
|
VulkanSemaphore::~VulkanSemaphore()
|
|
{
|
|
vkDestroySemaphore(m_device, m_vkSemaphore, NULL);
|
|
}
|
|
|
|
#if defined(_WIN32) || defined(_WIN64)
|
|
HANDLE VulkanSemaphore::getHandle(
|
|
VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) const
|
|
{
|
|
HANDLE handle;
|
|
|
|
VkSemaphoreGetWin32HandleInfoKHR vkSemaphoreGetWin32HandleInfoKHR = {};
|
|
vkSemaphoreGetWin32HandleInfoKHR.sType =
|
|
VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR;
|
|
vkSemaphoreGetWin32HandleInfoKHR.pNext = NULL;
|
|
vkSemaphoreGetWin32HandleInfoKHR.semaphore = m_vkSemaphore;
|
|
vkSemaphoreGetWin32HandleInfoKHR.handleType =
|
|
(VkExternalSemaphoreHandleTypeFlagBitsKHR)externalSemaphoreHandleType;
|
|
|
|
vkGetSemaphoreWin32HandleKHR(m_device, &vkSemaphoreGetWin32HandleInfoKHR,
|
|
&handle);
|
|
|
|
return handle;
|
|
}
|
|
#else
|
|
int VulkanSemaphore::getHandle(
|
|
VulkanExternalSemaphoreHandleType externalSemaphoreHandleType) const
|
|
{
|
|
if (externalSemaphoreHandleType
|
|
== VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD)
|
|
{
|
|
int fd;
|
|
|
|
VkSemaphoreGetFdInfoKHR vkSemaphoreGetFdInfoKHR = {};
|
|
vkSemaphoreGetFdInfoKHR.sType =
|
|
VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
|
|
vkSemaphoreGetFdInfoKHR.pNext = NULL;
|
|
vkSemaphoreGetFdInfoKHR.semaphore = m_vkSemaphore;
|
|
vkSemaphoreGetFdInfoKHR.handleType =
|
|
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;
|
|
|
|
vkGetSemaphoreFdKHR(m_device, &vkSemaphoreGetFdInfoKHR, &fd);
|
|
|
|
return fd;
|
|
}
|
|
else if (externalSemaphoreHandleType
|
|
== VULKAN_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD)
|
|
{
|
|
int fd;
|
|
|
|
VkSemaphoreGetFdInfoKHR vkSemaphoreGetFdInfoKHR = {};
|
|
vkSemaphoreGetFdInfoKHR.sType =
|
|
VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
|
|
vkSemaphoreGetFdInfoKHR.pNext = NULL;
|
|
vkSemaphoreGetFdInfoKHR.semaphore = m_vkSemaphore;
|
|
vkSemaphoreGetFdInfoKHR.handleType =
|
|
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT_KHR;
|
|
|
|
vkGetSemaphoreFdKHR(m_device, &vkSemaphoreGetFdInfoKHR, &fd);
|
|
|
|
return fd;
|
|
}
|
|
return HANDLE_ERROR;
|
|
}
|
|
#endif
|
|
|
|
const std::wstring &VulkanSemaphore::getName() const { return m_name; }
|
|
|
|
VulkanSemaphore::operator VkSemaphore() const { return m_vkSemaphore; }
|