mirror of
https://github.com/Yours3lf/rpi-vk-driver.git
synced 2024-12-10 22:24:14 +01:00
797 lines
27 KiB
C
797 lines
27 KiB
C
#include "common.h"
|
|
|
|
#include "declarations.h"
|
|
|
|
/*
|
|
* https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#devsandqueues-physical-device-enumeration
|
|
* If pPhysicalDevices is NULL, then the number of physical devices available is returned in pPhysicalDeviceCount. Otherwise, pPhysicalDeviceCount must point to a
|
|
* variable set by the user to the number of elements in the pPhysicalDevices array, and on return the variable is overwritten with the number of handles actually
|
|
* written to pPhysicalDevices. If pPhysicalDeviceCount is less than the number of physical devices available, at most pPhysicalDeviceCount structures will be written.
|
|
* If pPhysicalDeviceCount is smaller than the number of physical devices available, VK_INCOMPLETE will be returned instead of VK_SUCCESS, to indicate that not all the
|
|
* available physical devices were returned.
|
|
*/
|
|
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkEnumeratePhysicalDevices(
|
|
VkInstance instance,
|
|
uint32_t* pPhysicalDeviceCount,
|
|
VkPhysicalDevice* pPhysicalDevices)
|
|
{
|
|
assert(instance);
|
|
|
|
int numGPUs = 1;
|
|
|
|
assert(pPhysicalDeviceCount);
|
|
|
|
if(!pPhysicalDevices)
|
|
{
|
|
*pPhysicalDeviceCount = numGPUs;
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
int arraySize = *pPhysicalDeviceCount;
|
|
int elementsWritten = min(numGPUs, arraySize);
|
|
|
|
for(int c = 0; c < elementsWritten; ++c)
|
|
{
|
|
pPhysicalDevices[c] = &instance->dev;
|
|
}
|
|
|
|
*pPhysicalDeviceCount = elementsWritten;
|
|
|
|
if(arraySize < numGPUs)
|
|
{
|
|
return VK_INCOMPLETE;
|
|
}
|
|
else
|
|
{
|
|
return VK_SUCCESS;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#vkGetPhysicalDeviceProperties
|
|
*/
|
|
VKAPI_ATTR void VKAPI_CALL rpi_vkGetPhysicalDeviceProperties(
|
|
VkPhysicalDevice physicalDevice,
|
|
VkPhysicalDeviceProperties* pProperties)
|
|
{
|
|
assert(physicalDevice);
|
|
assert(pProperties);
|
|
|
|
VkPhysicalDeviceSparseProperties sparseProps =
|
|
{
|
|
.residencyStandard2DBlockShape = 1,
|
|
.residencyStandard2DMultisampleBlockShape = 1,
|
|
.residencyStandard3DBlockShape = 1,
|
|
.residencyAlignedMipSize = 1,
|
|
.residencyNonResidentStrict = 1
|
|
};
|
|
|
|
pProperties->apiVersion = VK_DRIVER_VERSION;
|
|
pProperties->driverVersion = 1; //we'll simply call this v1
|
|
pProperties->vendorID = 0x14E4; //Broadcom
|
|
pProperties->deviceID = 0x5250; //RP in HEX
|
|
pProperties->deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
|
|
strcpy(pProperties->deviceName, "VideoCore IV HW");
|
|
pProperties->limits = _limits;
|
|
pProperties->sparseProperties = sparseProps;
|
|
}
|
|
|
|
/*
|
|
* https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#vkGetPhysicalDeviceFeatures
|
|
*/
|
|
VKAPI_ATTR void VKAPI_CALL rpi_vkGetPhysicalDeviceFeatures(
|
|
VkPhysicalDevice physicalDevice,
|
|
VkPhysicalDeviceFeatures* pFeatures)
|
|
{
|
|
assert(physicalDevice);
|
|
assert(pFeatures);
|
|
|
|
*pFeatures = _features;
|
|
}
|
|
|
|
/*
|
|
* https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#vkEnumerateDeviceExtensionProperties
|
|
*/
|
|
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkEnumerateDeviceExtensionProperties(
|
|
VkPhysicalDevice physicalDevice,
|
|
const char* pLayerName,
|
|
uint32_t* pPropertyCount,
|
|
VkExtensionProperties* pProperties)
|
|
{
|
|
assert(physicalDevice);
|
|
assert(pPropertyCount);
|
|
|
|
if(!pProperties)
|
|
{
|
|
*pPropertyCount = numDeviceExtensions;
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
//TODO layers
|
|
|
|
int arraySize = *pPropertyCount;
|
|
int elementsWritten = min(numDeviceExtensions, arraySize);
|
|
|
|
for(int c = 0; c < elementsWritten; ++c)
|
|
{
|
|
pProperties[c] = deviceExtensions[c];
|
|
}
|
|
|
|
*pPropertyCount = elementsWritten;
|
|
|
|
if(arraySize < numDeviceExtensions)
|
|
{
|
|
return VK_INCOMPLETE;
|
|
}
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#vkGetPhysicalDeviceQueueFamilyProperties
|
|
* If pQueueFamilyProperties is NULL, then the number of queue families available is returned in pQueueFamilyPropertyCount.
|
|
* Otherwise, pQueueFamilyPropertyCount must point to a variable set by the user to the number of elements in the pQueueFamilyProperties array,
|
|
* and on return the variable is overwritten with the number of structures actually written to pQueueFamilyProperties. If pQueueFamilyPropertyCount
|
|
* is less than the number of queue families available, at most pQueueFamilyPropertyCount structures will be written.
|
|
*/
|
|
VKAPI_ATTR void VKAPI_CALL rpi_vkGetPhysicalDeviceQueueFamilyProperties(
|
|
VkPhysicalDevice physicalDevice,
|
|
uint32_t* pQueueFamilyPropertyCount,
|
|
VkQueueFamilyProperties* pQueueFamilyProperties)
|
|
{
|
|
assert(physicalDevice);
|
|
assert(pQueueFamilyPropertyCount);
|
|
|
|
if(!pQueueFamilyProperties)
|
|
{
|
|
*pQueueFamilyPropertyCount = 1;
|
|
return;
|
|
}
|
|
|
|
int arraySize = *pQueueFamilyPropertyCount;
|
|
int elementsWritten = min(numQueueFamilies, arraySize);
|
|
|
|
for(int c = 0; c < elementsWritten; ++c)
|
|
{
|
|
pQueueFamilyProperties[c] = _queueFamilyProperties[c];
|
|
}
|
|
|
|
*pQueueFamilyPropertyCount = elementsWritten;
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR(
|
|
VkPhysicalDevice physicalDevice,
|
|
uint32_t queueFamilyIndex,
|
|
uint32_t* pCounterCount,
|
|
VkPerformanceCounterKHR* pCounters,
|
|
VkPerformanceCounterDescriptionKHR* pCounterDescriptions)
|
|
{
|
|
assert(physicalDevice);
|
|
assert(pCounterCount);
|
|
|
|
if(!pCounters && !pCounterDescriptions)
|
|
{
|
|
*pCounterCount = numPerformanceCounterTypes;
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
int arraySize = *pCounterCount;
|
|
int elementsWritten = min(numPerformanceCounterTypes, arraySize);
|
|
|
|
for(int c = 0; c < elementsWritten; ++c)
|
|
{
|
|
pCounters[c] = performanceCounterTypes[c];
|
|
pCounterDescriptions[c] = performanceCounterDescriptions[c];
|
|
}
|
|
|
|
*pCounterCount = elementsWritten;
|
|
|
|
if(arraySize < numPerformanceCounterTypes)
|
|
{
|
|
return VK_INCOMPLETE;
|
|
}
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL rpi_vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR(
|
|
VkPhysicalDevice physicalDevice,
|
|
const VkQueryPoolPerformanceCreateInfoKHR* pPerformanceQueryCreateInfo,
|
|
uint32_t* pNumPasses)
|
|
{
|
|
assert(physicalDevice);
|
|
assert(pPerformanceQueryCreateInfo);
|
|
assert(pNumPasses);
|
|
|
|
*pNumPasses = pPerformanceQueryCreateInfo->counterIndexCount / DRM_VC4_MAX_PERF_COUNTERS + 1;
|
|
}
|
|
|
|
/*
|
|
* https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#vkCreateDevice
|
|
* vkCreateDevice verifies that extensions and features requested in the ppEnabledExtensionNames and pEnabledFeatures
|
|
* members of pCreateInfo, respectively, are supported by the implementation. If any requested extension is not supported,
|
|
* vkCreateDevice must return VK_ERROR_EXTENSION_NOT_PRESENT. If any requested feature is not supported, vkCreateDevice must return
|
|
* VK_ERROR_FEATURE_NOT_PRESENT. Support for extensions can be checked before creating a device by querying vkEnumerateDeviceExtensionProperties
|
|
* After verifying and enabling the extensions the VkDevice object is created and returned to the application.
|
|
* If a requested extension is only supported by a layer, both the layer and the extension need to be specified at vkCreateInstance
|
|
* time for the creation to succeed. Multiple logical devices can be created from the same physical device. Logical device creation may
|
|
* fail due to lack of device-specific resources (in addition to the other errors). If that occurs, vkCreateDevice will return VK_ERROR_TOO_MANY_OBJECTS.
|
|
*/
|
|
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkCreateDevice(
|
|
VkPhysicalDevice physicalDevice,
|
|
const VkDeviceCreateInfo* pCreateInfo,
|
|
const VkAllocationCallbacks* pAllocator,
|
|
VkDevice* pDevice)
|
|
{
|
|
assert(physicalDevice);
|
|
assert(pDevice);
|
|
assert(pCreateInfo);
|
|
|
|
//TODO store enabled features and extensions
|
|
//and check later on if they are enabled.
|
|
|
|
//check for enabled extensions
|
|
for(int c = 0; c < pCreateInfo->enabledExtensionCount; ++c)
|
|
{
|
|
int findres = findDeviceExtension(pCreateInfo->ppEnabledExtensionNames[c]);
|
|
if(findres == -1)
|
|
{
|
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
|
}
|
|
}
|
|
|
|
//check for enabled features
|
|
VkBool32* requestedFeatures = pCreateInfo->pEnabledFeatures;
|
|
VkBool32* supportedFeatures = &_features;
|
|
|
|
if(requestedFeatures)
|
|
{
|
|
for(int c = 0; c < numFeatures; ++c)
|
|
{
|
|
if(requestedFeatures[c] && !supportedFeatures[c])
|
|
{
|
|
return VK_ERROR_FEATURE_NOT_PRESENT;
|
|
}
|
|
}
|
|
}
|
|
|
|
*pDevice = ALLOCATE(sizeof(_device), 1, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
|
|
if(!*pDevice)
|
|
{
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
}
|
|
|
|
set_loader_magic_value(&(*pDevice)->loaderData);
|
|
|
|
(*pDevice)->dev = physicalDevice;
|
|
|
|
(*pDevice)->numEnabledExtensions = 0;
|
|
|
|
for(int c = 0; c < pCreateInfo->enabledExtensionCount; ++c)
|
|
{
|
|
int findres = findDeviceExtension(pCreateInfo->ppEnabledExtensionNames[c]);
|
|
if(findres > -1)
|
|
{
|
|
(*pDevice)->enabledExtensions[(*pDevice)->numEnabledExtensions] = findres;
|
|
(*pDevice)->numEnabledExtensions++;
|
|
}
|
|
}
|
|
|
|
if(requestedFeatures)
|
|
{
|
|
for(int c = 0; c < numFeatures; ++c)
|
|
{
|
|
if(requestedFeatures[c] && !supportedFeatures[c])
|
|
{
|
|
return VK_ERROR_FEATURE_NOT_PRESENT;
|
|
}
|
|
}
|
|
|
|
(*pDevice)->enabledFeatures = *pCreateInfo->pEnabledFeatures;
|
|
}
|
|
else
|
|
{
|
|
memset(&(*pDevice)->enabledFeatures, 0, sizeof((*pDevice)->enabledFeatures)); //just disable everything
|
|
}
|
|
|
|
//layers ignored per spec
|
|
//pCreateInfo->enabledLayerCount
|
|
|
|
for(int c = 0; c < numQueueFamilies; ++c)
|
|
{
|
|
(*pDevice)->queues[c] = 0;
|
|
}
|
|
|
|
if(pCreateInfo->queueCreateInfoCount > 0)
|
|
{
|
|
for(int c = 0; c < pCreateInfo->queueCreateInfoCount; ++c)
|
|
{
|
|
(*pDevice)->queues[pCreateInfo->pQueueCreateInfos[c].queueFamilyIndex] = ALLOCATE(sizeof(_queue)*pCreateInfo->pQueueCreateInfos[c].queueCount, 1, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
|
|
|
if(!(*pDevice)->queues[pCreateInfo->pQueueCreateInfos[c].queueFamilyIndex])
|
|
{
|
|
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
}
|
|
|
|
for(int d = 0; d < pCreateInfo->pQueueCreateInfos[c].queueCount; ++d)
|
|
{
|
|
(*pDevice)->queues[pCreateInfo->pQueueCreateInfos[c].queueFamilyIndex][d].lastEmitSeqno = 0;
|
|
(*pDevice)->queues[pCreateInfo->pQueueCreateInfos[c].queueFamilyIndex][d].dev = *pDevice;
|
|
set_loader_magic_value(&(*pDevice)->queues[pCreateInfo->pQueueCreateInfos[c].queueFamilyIndex][d].loaderData);
|
|
}
|
|
|
|
(*pDevice)->numQueues[pCreateInfo->pQueueCreateInfos[c].queueFamilyIndex] = pCreateInfo->pQueueCreateInfos[c].queueCount;
|
|
}
|
|
}
|
|
|
|
setupEmulationResources(*pDevice);
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
/*
|
|
* https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#vkGetDeviceQueue
|
|
* vkGetDeviceQueue must only be used to get queues that were created with the flags parameter of VkDeviceQueueCreateInfo set to zero.
|
|
* To get queues that were created with a non-zero flags parameter use vkGetDeviceQueue2.
|
|
*/
|
|
VKAPI_ATTR void VKAPI_CALL rpi_vkGetDeviceQueue(
|
|
VkDevice device,
|
|
uint32_t queueFamilyIndex,
|
|
uint32_t queueIndex,
|
|
VkQueue* pQueue)
|
|
{
|
|
assert(device);
|
|
assert(pQueue);
|
|
|
|
assert(queueFamilyIndex < numQueueFamilies);
|
|
assert(queueIndex < device->numQueues[queueFamilyIndex]);
|
|
|
|
*pQueue = &device->queues[queueFamilyIndex][queueIndex];
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL rpi_vkGetDeviceQueue2(
|
|
VkDevice device,
|
|
const VkDeviceQueueInfo2* pQueueInfo,
|
|
VkQueue* pQueue)
|
|
{
|
|
assert(device);
|
|
assert(pQueueInfo);
|
|
assert(pQueue);
|
|
|
|
//TODO handle pNext
|
|
|
|
rpi_vkGetDeviceQueue(device, pQueueInfo->queueFamilyIndex, pQueueInfo->queueIndex, pQueue);
|
|
}
|
|
|
|
/*
|
|
* https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#vkDestroyDevice
|
|
* To ensure that no work is active on the device, vkDeviceWaitIdle can be used to gate the destruction of the device.
|
|
* Prior to destroying a device, an application is responsible for destroying/freeing any Vulkan objects that were created using that device as the
|
|
* first parameter of the corresponding vkCreate* or vkAllocate* command
|
|
*/
|
|
VKAPI_ATTR void VKAPI_CALL rpi_vkDestroyDevice(
|
|
VkDevice device,
|
|
const VkAllocationCallbacks* pAllocator)
|
|
{
|
|
_device* dev = device;
|
|
|
|
if(dev)
|
|
{
|
|
for(int c = 0; c < numQueueFamilies; ++c)
|
|
{
|
|
for(int d = 0; d < dev->numQueues[c]; ++d)
|
|
{
|
|
FREE(dev->queues[d]);
|
|
}
|
|
}
|
|
FREE(dev);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#vkEnumeratePhysicalDeviceGroups
|
|
*/
|
|
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkEnumeratePhysicalDeviceGroups(
|
|
VkInstance instance,
|
|
uint32_t* pPhysicalDeviceGroupCount,
|
|
VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties)
|
|
{
|
|
assert(instance);
|
|
assert(pPhysicalDeviceGroupCount);
|
|
|
|
if(!pPhysicalDeviceGroupProperties)
|
|
{
|
|
*pPhysicalDeviceGroupCount = 1;
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
//we don't have any other devices...
|
|
assert(*pPhysicalDeviceGroupCount == 1);
|
|
|
|
uint32_t c = 0;
|
|
for(; c < *pPhysicalDeviceGroupCount; ++c)
|
|
{
|
|
pPhysicalDeviceGroupProperties[c].physicalDeviceCount = 1;
|
|
pPhysicalDeviceGroupProperties[c].physicalDevices[0] = &instance->dev;
|
|
pPhysicalDeviceGroupProperties[c].subsetAllocation = 0;
|
|
}
|
|
|
|
if(c < 1)
|
|
{
|
|
return VK_INCOMPLETE;
|
|
}
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
extern VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL rpi_vkGetInstanceProcAddr(VkInstance instance,
|
|
const char* pName);
|
|
|
|
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL rpi_vkGetDeviceProcAddr(
|
|
VkDevice device,
|
|
const char* pName)
|
|
{
|
|
if(
|
|
!strcmp("vkDestroyInstance", pName) ||
|
|
!strcmp("vkEnumeratePhysicalDevices", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceFeatures", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceFormatProperties", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceImageFormatProperties", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceProperties", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceQueueFamilyProperties", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceMemoryProperties", pName) ||
|
|
!strcmp("vkCreateDevice", pName) ||
|
|
!strcmp("vkEnumerateDeviceExtensionProperties", pName) ||
|
|
!strcmp("vkEnumerateDeviceLayerProperties", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceSparseImageFormatProperties", pName) ||
|
|
!strcmp("vkEnumeratePhysicalDeviceGroups", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceFeatures2", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceProperties2", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceFormatProperties2", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceImageFormatProperties2", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceQueueFamilyProperties2", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceMemoryProperties2", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceSparseImageFormatProperties2", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceExternalBufferProperties", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceExternalFenceProperties", pName) ||
|
|
!strcmp("vkGetPhysicalDeviceExternalSemaphoreProperties", pName)
|
|
)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
|
|
//there can't be any other device, so this will do fine...
|
|
_device* d = device;
|
|
return rpi_vkGetInstanceProcAddr(d->dev->instance, pName);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL rpi_vkGetPhysicalDeviceProperties2(
|
|
VkPhysicalDevice physicalDevice,
|
|
VkPhysicalDeviceProperties2* pProperties)
|
|
{
|
|
assert(physicalDevice);
|
|
assert(pProperties);
|
|
rpi_vkGetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
|
|
|
|
if(pProperties->pNext)
|
|
{
|
|
VkPhysicalDeviceDriverPropertiesKHR* ptr = pProperties->pNext;
|
|
if(ptr->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES_KHR)
|
|
{
|
|
ptr->driverID = 0x525049564b; //RPIVK in hex
|
|
const char* driverName = "RPi VK";
|
|
const char* driverInfo = ""; //TODO maybe version number, git info?
|
|
strcpy(ptr->driverName, driverName);
|
|
strcpy(ptr->driverInfo, driverInfo);
|
|
//TODO this is what we are aspiring to pass...
|
|
ptr->conformanceVersion.major = 1;
|
|
ptr->conformanceVersion.minor = 1;
|
|
ptr->conformanceVersion.subminor = 2;
|
|
ptr->conformanceVersion.patch = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL rpi_vkGetPhysicalDeviceFormatProperties(
|
|
VkPhysicalDevice physicalDevice,
|
|
VkFormat format,
|
|
VkFormatProperties* pFormatProperties)
|
|
{
|
|
assert(physicalDevice);
|
|
assert(pFormatProperties);
|
|
|
|
switch(format)
|
|
{
|
|
//TODO what formats could we pull off
|
|
//case VK_FORMAT_D16_UNORM:
|
|
case VK_FORMAT_X8_D24_UNORM_PACK32:
|
|
//case VK_FORMAT_D32_SFLOAT:
|
|
//case VK_FORMAT_S8_UINT:
|
|
//case VK_FORMAT_D16_UNORM_S8_UINT:
|
|
case VK_FORMAT_D24_UNORM_S8_UINT:
|
|
//case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
|
{
|
|
pFormatProperties->linearTilingFeatures = 0
|
|
| VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_BLIT_SRC_BIT
|
|
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
|
|
| VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
|
|
;
|
|
pFormatProperties->optimalTilingFeatures = 0
|
|
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
|
|
| VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT
|
|
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT
|
|
| VK_FORMAT_FEATURE_BLIT_SRC_BIT
|
|
| VK_FORMAT_FEATURE_BLIT_DST_BIT
|
|
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
|
|
| VK_FORMAT_FEATURE_TRANSFER_DST_BIT
|
|
| VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
|
|
|
|
;
|
|
pFormatProperties->bufferFeatures = 0
|
|
| VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
|
|
| VK_FORMAT_FEATURE_BLIT_SRC_BIT
|
|
;
|
|
break;
|
|
}
|
|
//supported texture formats
|
|
case VK_FORMAT_R8G8B8_UNORM:
|
|
case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
|
|
case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
|
|
case VK_FORMAT_R8G8_UNORM:
|
|
case VK_FORMAT_R16_SFLOAT:
|
|
case VK_FORMAT_R16_SINT:
|
|
case VK_FORMAT_R8_UNORM:
|
|
case VK_FORMAT_R8_SINT:
|
|
case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
|
|
case VK_FORMAT_G8B8G8R8_422_UNORM:
|
|
{
|
|
pFormatProperties->linearTilingFeatures = 0
|
|
| VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_BLIT_SRC_BIT
|
|
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
|
|
;
|
|
pFormatProperties->optimalTilingFeatures = 0
|
|
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
|
|
| VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT
|
|
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT
|
|
| VK_FORMAT_FEATURE_BLIT_SRC_BIT
|
|
| VK_FORMAT_FEATURE_BLIT_DST_BIT
|
|
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
|
|
| VK_FORMAT_FEATURE_TRANSFER_DST_BIT
|
|
;
|
|
pFormatProperties->bufferFeatures = 0
|
|
| VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
|
|
| VK_FORMAT_FEATURE_BLIT_SRC_BIT
|
|
;
|
|
break;
|
|
}
|
|
//supported render target formats
|
|
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
|
case VK_FORMAT_R8G8B8A8_UNORM:
|
|
case VK_FORMAT_B5G6R5_UNORM_PACK16:
|
|
{
|
|
pFormatProperties->linearTilingFeatures = 0
|
|
| VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_BLIT_SRC_BIT
|
|
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
|
|
;
|
|
pFormatProperties->optimalTilingFeatures = 0
|
|
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
|
|
| VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT
|
|
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT
|
|
| VK_FORMAT_FEATURE_BLIT_SRC_BIT
|
|
| VK_FORMAT_FEATURE_BLIT_DST_BIT
|
|
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
|
|
| VK_FORMAT_FEATURE_TRANSFER_DST_BIT
|
|
| VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
|
|
| VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT
|
|
;
|
|
pFormatProperties->bufferFeatures = 0
|
|
| VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT
|
|
| VK_FORMAT_FEATURE_TRANSFER_SRC_BIT
|
|
| VK_FORMAT_FEATURE_BLIT_SRC_BIT
|
|
;
|
|
break;
|
|
}
|
|
default:
|
|
pFormatProperties->linearTilingFeatures = 0;
|
|
pFormatProperties->optimalTilingFeatures = 0;
|
|
pFormatProperties->bufferFeatures = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL rpi_vkGetPhysicalDeviceFormatProperties2(
|
|
VkPhysicalDevice physicalDevice,
|
|
VkFormat format,
|
|
VkFormatProperties2* pFormatProperties)
|
|
{
|
|
assert(physicalDevice);
|
|
assert(pFormatProperties);
|
|
rpi_vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &pFormatProperties->formatProperties);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkGetPhysicalDeviceImageFormatProperties(
|
|
VkPhysicalDevice physicalDevice,
|
|
VkFormat format,
|
|
VkImageType type,
|
|
VkImageTiling tiling,
|
|
VkImageUsageFlags usage,
|
|
VkImageCreateFlags flags,
|
|
VkImageFormatProperties* pImageFormatProperties)
|
|
{
|
|
assert(physicalDevice);
|
|
assert(pImageFormatProperties);
|
|
|
|
//TODO usage, flags tiling etc.
|
|
//do all this per format...
|
|
|
|
|
|
VkFormat ycbcrConversionRequiredFormats[] =
|
|
{
|
|
VK_FORMAT_G8B8G8R8_422_UNORM
|
|
,VK_FORMAT_B8G8R8G8_422_UNORM
|
|
,VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM
|
|
,VK_FORMAT_G8_B8R8_2PLANE_420_UNORM
|
|
,VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM
|
|
,VK_FORMAT_G8_B8R8_2PLANE_422_UNORM
|
|
,VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM
|
|
,VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16
|
|
,VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16
|
|
,VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16
|
|
,VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16
|
|
,VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16
|
|
,VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16
|
|
,VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16
|
|
,VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16
|
|
,VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16
|
|
,VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16
|
|
,VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16
|
|
,VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16
|
|
,VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16
|
|
,VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16
|
|
,VK_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16
|
|
,VK_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16
|
|
,VK_FORMAT_G16B16G16R16_422_UNORM
|
|
,VK_FORMAT_B16G16R16G16_422_UNORM
|
|
,VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM
|
|
,VK_FORMAT_G16_B16R16_2PLANE_420_UNORM
|
|
,VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM
|
|
,VK_FORMAT_G16_B16R16_2PLANE_422_UNORM
|
|
,VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM
|
|
};
|
|
#define numYcbcrConversionRequiredFormats (sizeof(ycbcrConversionRequiredFormats)/sizeof(VkFormat))
|
|
|
|
uint32_t supported = 0;
|
|
for(uint32_t c = 0; c < numSupportedFormats; ++c)
|
|
{
|
|
if(format == supportedFormats[c])
|
|
{
|
|
supported = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!supported)
|
|
{
|
|
return VK_ERROR_FORMAT_NOT_SUPPORTED;
|
|
}
|
|
|
|
pImageFormatProperties->maxArrayLayers = _limits.maxImageArrayLayers;
|
|
|
|
pImageFormatProperties->maxExtent.width = 1;
|
|
pImageFormatProperties->maxExtent.height = 1;
|
|
pImageFormatProperties->maxExtent.depth = 1;
|
|
|
|
pImageFormatProperties->sampleCounts = _limits.framebufferColorSampleCounts;
|
|
|
|
if(type == VK_IMAGE_TYPE_1D)
|
|
{
|
|
pImageFormatProperties->maxExtent.width = _limits.maxImageDimension1D;
|
|
pImageFormatProperties->maxMipLevels = ulog2(_limits.maxImageDimension1D) + 1;
|
|
}
|
|
else if(type == VK_IMAGE_TYPE_2D)
|
|
{
|
|
pImageFormatProperties->maxExtent.width = _limits.maxImageDimension2D;
|
|
pImageFormatProperties->maxExtent.height = _limits.maxImageDimension2D;
|
|
pImageFormatProperties->maxMipLevels = ulog2(_limits.maxImageDimension2D) + 1;
|
|
}
|
|
else
|
|
{
|
|
pImageFormatProperties->maxExtent.width = _limits.maxImageDimension3D;
|
|
pImageFormatProperties->maxExtent.height = _limits.maxImageDimension3D;
|
|
pImageFormatProperties->maxExtent.depth = _limits.maxImageDimension3D;
|
|
pImageFormatProperties->maxMipLevels = ulog2(_limits.maxImageDimension3D) + 1;
|
|
}
|
|
|
|
int ycbcrConversionRequired = 0;
|
|
|
|
for(uint32_t c = 0; c < numYcbcrConversionRequiredFormats; ++c)
|
|
{
|
|
if(format == ycbcrConversionRequiredFormats[c])
|
|
{
|
|
ycbcrConversionRequired = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(ycbcrConversionRequired ||
|
|
tiling == VK_IMAGE_TILING_LINEAR ||
|
|
type != VK_IMAGE_TYPE_2D ||
|
|
flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT ||
|
|
flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT
|
|
)
|
|
{
|
|
pImageFormatProperties->sampleCounts = VK_SAMPLE_COUNT_1_BIT;
|
|
}
|
|
|
|
//TODO real max size?
|
|
//2^31
|
|
pImageFormatProperties->maxResourceSize = 1<<31;
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkGetPhysicalDeviceImageFormatProperties2(
|
|
VkPhysicalDevice physicalDevice,
|
|
const VkPhysicalDeviceImageFormatInfo2* pImageFormatInfo,
|
|
VkImageFormatProperties2* pImageFormatProperties)
|
|
{
|
|
assert(physicalDevice);
|
|
assert(pImageFormatProperties);
|
|
assert(pImageFormatInfo);
|
|
|
|
//TODO handle pNext
|
|
|
|
return rpi_vkGetPhysicalDeviceImageFormatProperties(physicalDevice,
|
|
pImageFormatInfo->format,
|
|
pImageFormatInfo->type,
|
|
pImageFormatInfo->tiling,
|
|
pImageFormatInfo->usage,
|
|
pImageFormatInfo->flags,
|
|
&pImageFormatProperties->imageFormatProperties);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL rpi_vkEnumerateDeviceLayerProperties(
|
|
VkPhysicalDevice physicalDevice,
|
|
uint32_t* pPropertyCount,
|
|
VkLayerProperties* pProperties)
|
|
{
|
|
//deprecated, just return instance layers
|
|
return rpi_vkEnumerateInstanceLayerProperties(pPropertyCount, pProperties);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL rpi_vkGetPhysicalDeviceFeatures2(
|
|
VkPhysicalDevice physicalDevice,
|
|
VkPhysicalDeviceFeatures2* pFeatures)
|
|
{
|
|
assert(physicalDevice);
|
|
assert(pFeatures);
|
|
rpi_vkGetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL rpi_vkGetPhysicalDeviceQueueFamilyProperties2(
|
|
VkPhysicalDevice physicalDevice,
|
|
uint32_t* pQueueFamilyPropertyCount,
|
|
VkQueueFamilyProperties2* pQueueFamilyProperties)
|
|
{
|
|
assert(physicalDevice);
|
|
rpi_vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
|
|
}
|