mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-21 03:21:28 +00:00
Update zvulkan to latest version
This commit is contained in:
parent
d354d7332f
commit
45a2cbe081
15 changed files with 12305 additions and 12372 deletions
File diff suppressed because it is too large
Load diff
|
@ -184,6 +184,7 @@ public:
|
|||
BufferBuilder& Size(size_t size);
|
||||
BufferBuilder& Usage(VkBufferUsageFlags bufferUsage, VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_GPU_ONLY, VmaAllocationCreateFlags allocFlags = 0);
|
||||
BufferBuilder& MemoryType(VkMemoryPropertyFlags requiredFlags, VkMemoryPropertyFlags preferredFlags, uint32_t memoryTypeBits = 0);
|
||||
BufferBuilder& MinAlignment(VkDeviceSize memoryAlignment);
|
||||
BufferBuilder& DebugName(const char* name) { debugName = name; return *this; }
|
||||
|
||||
std::unique_ptr<VulkanBuffer> Create(VulkanDevice *device);
|
||||
|
@ -192,6 +193,27 @@ private:
|
|||
VkBufferCreateInfo bufferInfo = {};
|
||||
VmaAllocationCreateInfo allocInfo = {};
|
||||
const char* debugName = nullptr;
|
||||
VkDeviceSize minAlignment = 0;
|
||||
};
|
||||
|
||||
enum class ShaderType
|
||||
{
|
||||
Vertex,
|
||||
TessControl,
|
||||
TessEvaluation,
|
||||
Geometry,
|
||||
Fragment,
|
||||
Compute
|
||||
};
|
||||
|
||||
class ShaderIncludeResult
|
||||
{
|
||||
public:
|
||||
ShaderIncludeResult(std::string name, std::string text) : name(std::move(name)), text(std::move(text)) { }
|
||||
ShaderIncludeResult(std::string error) : text(std::move(error)) { }
|
||||
|
||||
std::string name; // fully resolved name of the included header file
|
||||
std::string text; // the file contents - or include error message if name is empty
|
||||
};
|
||||
|
||||
class ShaderBuilder
|
||||
|
@ -202,16 +224,23 @@ public:
|
|||
static void Init();
|
||||
static void Deinit();
|
||||
|
||||
ShaderBuilder& VertexShader(const std::string &code);
|
||||
ShaderBuilder& FragmentShader(const std::string&code);
|
||||
ShaderBuilder& Type(ShaderType type);
|
||||
ShaderBuilder& AddSource(const std::string& name, const std::string& code);
|
||||
|
||||
ShaderBuilder& OnIncludeSystem(std::function<ShaderIncludeResult(std::string headerName, std::string includerName, size_t inclusionDepth)> onIncludeSystem);
|
||||
ShaderBuilder& OnIncludeLocal(std::function<ShaderIncludeResult(std::string headerName, std::string includerName, size_t inclusionDepth)> onIncludeLocal);
|
||||
|
||||
ShaderBuilder& DebugName(const char* name) { debugName = name; return *this; }
|
||||
|
||||
std::unique_ptr<VulkanShader> Create(const char *shadername, VulkanDevice *device);
|
||||
|
||||
private:
|
||||
std::string code;
|
||||
std::vector<std::pair<std::string, std::string>> sources;
|
||||
std::function<ShaderIncludeResult(std::string headerName, std::string includerName, size_t inclusionDepth)> onIncludeSystem;
|
||||
std::function<ShaderIncludeResult(std::string headerName, std::string includerName, size_t inclusionDepth)> onIncludeLocal;
|
||||
int stage = 0;
|
||||
const char* debugName = nullptr;
|
||||
friend class ShaderBuilderIncluderImpl;
|
||||
};
|
||||
|
||||
class AccelerationStructureBuilder
|
||||
|
@ -463,8 +492,8 @@ public:
|
|||
PipelineBarrier& AddMemory(VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask);
|
||||
PipelineBarrier& AddBuffer(VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask);
|
||||
PipelineBarrier& AddBuffer(VulkanBuffer *buffer, VkDeviceSize offset, VkDeviceSize size, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask);
|
||||
PipelineBarrier& AddImage(VulkanImage *image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1);
|
||||
PipelineBarrier& AddImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1);
|
||||
PipelineBarrier& AddImage(VulkanImage *image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1, int baseArrayLayer = 0, int layerCount = 1);
|
||||
PipelineBarrier& AddImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1, int baseArrayLayer = 0, int layerCount = 1);
|
||||
PipelineBarrier& AddQueueTransfer(int srcFamily, int dstFamily, VulkanBuffer *buffer, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask);
|
||||
PipelineBarrier& AddQueueTransfer(int srcFamily, int dstFamily, VulkanImage *image, VkImageLayout layout, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, int baseMipLevel = 0, int levelCount = 1);
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ public:
|
|||
int PresentFamily = -1;
|
||||
bool GraphicsTimeQueries = false;
|
||||
|
||||
bool SupportsDeviceExtension(const char* ext) const;
|
||||
bool SupportsExtension(const char* ext) const;
|
||||
|
||||
void SetObjectName(const char* name, uint64_t handle, VkObjectType type);
|
||||
|
||||
|
|
|
@ -31,14 +31,22 @@ public:
|
|||
VkPhysicalDeviceDescriptorIndexingFeatures DescriptorIndexing = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT };
|
||||
};
|
||||
|
||||
class VulkanDeviceProperties
|
||||
{
|
||||
public:
|
||||
VkPhysicalDeviceProperties Properties = {};
|
||||
VkPhysicalDeviceMemoryProperties Memory = {};
|
||||
VkPhysicalDeviceAccelerationStructurePropertiesKHR AccelerationStructure = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR };
|
||||
VkPhysicalDeviceDescriptorIndexingProperties DescriptorIndexing = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES_EXT };
|
||||
};
|
||||
|
||||
class VulkanPhysicalDevice
|
||||
{
|
||||
public:
|
||||
VkPhysicalDevice Device = VK_NULL_HANDLE;
|
||||
std::vector<VkExtensionProperties> Extensions;
|
||||
std::vector<VkQueueFamilyProperties> QueueFamilies;
|
||||
VkPhysicalDeviceProperties Properties = {};
|
||||
VkPhysicalDeviceMemoryProperties MemoryProperties = {};
|
||||
VulkanDeviceProperties Properties;
|
||||
VulkanDeviceFeatures Features;
|
||||
};
|
||||
|
||||
|
|
|
@ -569,7 +569,7 @@ inline RenderPassBegin& RenderPassBegin::Framebuffer(VulkanFramebuffer* framebuf
|
|||
inline RenderPassBegin& RenderPassBegin::AddClearColor(float r, float g, float b, float a)
|
||||
{
|
||||
VkClearValue clearValue = { };
|
||||
clearValue.color = { { r, g, b, a } };
|
||||
clearValue.color = { r, g, b, a };
|
||||
clearValues.push_back(clearValue);
|
||||
|
||||
renderPassInfo.clearValueCount = (uint32_t)clearValues.size();
|
||||
|
|
|
@ -6,6 +6,19 @@
|
|||
class VulkanSemaphore;
|
||||
class VulkanFence;
|
||||
|
||||
class VulkanSurfaceCapabilities
|
||||
{
|
||||
public:
|
||||
VkSurfaceCapabilitiesKHR Capabilites = { };
|
||||
#ifdef WIN32
|
||||
VkSurfaceCapabilitiesFullScreenExclusiveEXT FullScreenExclusive = { VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT };
|
||||
#else
|
||||
struct { void* pNext = nullptr; VkBool32 fullScreenExclusiveSupported = 0; } FullScreenExclusive;
|
||||
#endif
|
||||
std::vector<VkPresentModeKHR> PresentModes;
|
||||
std::vector<VkSurfaceFormatKHR> Formats;
|
||||
};
|
||||
|
||||
class VulkanSwapChain
|
||||
{
|
||||
public:
|
||||
|
@ -27,13 +40,11 @@ public:
|
|||
void QueuePresent(int imageIndex, VulkanSemaphore* semaphore = nullptr);
|
||||
|
||||
private:
|
||||
void SelectFormat(bool hdr);
|
||||
void SelectPresentMode(bool vsync, bool exclusivefullscreen);
|
||||
void SelectFormat(const VulkanSurfaceCapabilities& caps, bool hdr);
|
||||
|
||||
bool CreateSwapchain(int width, int height, int imageCount, bool exclusivefullscreen, VkSwapchainKHR oldSwapChain = VK_NULL_HANDLE);
|
||||
bool CreateSwapchain(int width, int height, int imageCount, bool vsync, bool hdr, bool exclusivefullscreen);
|
||||
|
||||
std::vector<VkSurfaceFormatKHR> GetSurfaceFormats();
|
||||
std::vector<VkPresentModeKHR> GetPresentModes(bool exclusivefullscreen);
|
||||
VulkanSurfaceCapabilities GetSurfaceCapabilities(bool exclusivefullscreen);
|
||||
|
||||
VulkanDevice* device = nullptr;
|
||||
bool lost = true;
|
||||
|
|
|
@ -128,29 +128,143 @@ ShaderBuilder::ShaderBuilder()
|
|||
{
|
||||
}
|
||||
|
||||
ShaderBuilder& ShaderBuilder::VertexShader(const std::string& c)
|
||||
ShaderBuilder& ShaderBuilder::Type(ShaderType type)
|
||||
{
|
||||
code = c;
|
||||
stage = EShLanguage::EShLangVertex;
|
||||
switch (type)
|
||||
{
|
||||
case ShaderType::Vertex: stage = EShLanguage::EShLangVertex; break;
|
||||
case ShaderType::TessControl: stage = EShLanguage::EShLangTessControl; break;
|
||||
case ShaderType::TessEvaluation: stage = EShLanguage::EShLangTessEvaluation; break;
|
||||
case ShaderType::Geometry: stage = EShLanguage::EShLangGeometry; break;
|
||||
case ShaderType::Fragment: stage = EShLanguage::EShLangFragment; break;
|
||||
case ShaderType::Compute: stage = EShLanguage::EShLangCompute; break;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
ShaderBuilder& ShaderBuilder::FragmentShader(const std::string& c)
|
||||
ShaderBuilder& ShaderBuilder::AddSource(const std::string& name, const std::string& code)
|
||||
{
|
||||
code = c;
|
||||
stage = EShLanguage::EShLangFragment;
|
||||
sources.push_back({ name, code });
|
||||
return *this;
|
||||
}
|
||||
|
||||
ShaderBuilder& ShaderBuilder::OnIncludeSystem(std::function<ShaderIncludeResult(std::string headerName, std::string includerName, size_t inclusionDepth)> onIncludeSystem)
|
||||
{
|
||||
this->onIncludeSystem = std::move(onIncludeSystem);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ShaderBuilder& ShaderBuilder::OnIncludeLocal(std::function<ShaderIncludeResult(std::string headerName, std::string includerName, size_t inclusionDepth)> onIncludeLocal)
|
||||
{
|
||||
this->onIncludeLocal = std::move(onIncludeLocal);
|
||||
return *this;
|
||||
}
|
||||
|
||||
class ShaderBuilderIncluderImpl : public glslang::TShader::Includer
|
||||
{
|
||||
public:
|
||||
ShaderBuilderIncluderImpl(ShaderBuilder* shaderBuilder) : shaderBuilder(shaderBuilder)
|
||||
{
|
||||
}
|
||||
|
||||
IncludeResult* includeSystem(const char* headerName, const char* includerName, size_t inclusionDepth) override
|
||||
{
|
||||
if (!shaderBuilder->onIncludeSystem)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::unique_ptr<ShaderIncludeResult> result;
|
||||
try
|
||||
{
|
||||
result = std::make_unique<ShaderIncludeResult>(shaderBuilder->onIncludeSystem(headerName, includerName, inclusionDepth));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
result = std::make_unique<ShaderIncludeResult>(e.what());
|
||||
}
|
||||
|
||||
if (!result || (result->name.empty() && result->text.empty()))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IncludeResult* outer = new IncludeResult(result->name, result->text.data(), result->text.size(), result.get());
|
||||
result.release();
|
||||
return outer;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
IncludeResult* includeLocal(const char* headerName, const char* includerName, size_t inclusionDepth) override
|
||||
{
|
||||
if (!shaderBuilder->onIncludeLocal)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
std::unique_ptr<ShaderIncludeResult> result;
|
||||
try
|
||||
{
|
||||
result = std::make_unique<ShaderIncludeResult>(shaderBuilder->onIncludeLocal(headerName, includerName, inclusionDepth));
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
result = std::make_unique<ShaderIncludeResult>(e.what());
|
||||
}
|
||||
|
||||
if (!result || (result->name.empty() && result->text.empty()))
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
IncludeResult* outer = new IncludeResult(result->name, result->text.data(), result->text.size(), result.get());
|
||||
result.release();
|
||||
return outer;
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void releaseInclude(IncludeResult* result) override
|
||||
{
|
||||
if (result)
|
||||
{
|
||||
delete (ShaderIncludeResult*)result->userData;
|
||||
delete result;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
ShaderBuilder* shaderBuilder = nullptr;
|
||||
};
|
||||
|
||||
std::unique_ptr<VulkanShader> ShaderBuilder::Create(const char *shadername, VulkanDevice *device)
|
||||
{
|
||||
EShLanguage stage = (EShLanguage)this->stage;
|
||||
const char *sources[] = { code.c_str() };
|
||||
|
||||
std::vector<const char*> namesC, sourcesC;
|
||||
std::vector<int> lengthsC;
|
||||
for (const auto& s : sources)
|
||||
{
|
||||
namesC.push_back(s.first.c_str());
|
||||
sourcesC.push_back(s.second.c_str());
|
||||
lengthsC.push_back((int)s.second.size());
|
||||
}
|
||||
|
||||
TBuiltInResource resources = DefaultTBuiltInResource;
|
||||
|
||||
glslang::TShader shader(stage);
|
||||
shader.setStrings(sources, 1);
|
||||
shader.setStringsWithLengthsAndNames(sourcesC.data(), lengthsC.data(), namesC.data(), (int)sources.size());
|
||||
shader.setEnvInput(glslang::EShSourceGlsl, stage, glslang::EShClientVulkan, 100);
|
||||
if (device->Instance->ApiVersion >= VK_API_VERSION_1_2)
|
||||
{
|
||||
|
@ -162,7 +276,9 @@ std::unique_ptr<VulkanShader> ShaderBuilder::Create(const char *shadername, Vulk
|
|||
shader.setEnvClient(glslang::EShClientVulkan, glslang::EShTargetVulkan_1_0);
|
||||
shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_0);
|
||||
}
|
||||
bool compileSuccess = shader.parse(&resources, 110, false, EShMsgVulkanRules);
|
||||
|
||||
ShaderBuilderIncluderImpl includer(this);
|
||||
bool compileSuccess = shader.parse(&resources, 110, false, EShMsgVulkanRules, includer);
|
||||
if (!compileSuccess)
|
||||
{
|
||||
throw std::runtime_error(std::string("Shader compile failed: ") + shader.getInfoLog());
|
||||
|
@ -527,13 +643,27 @@ BufferBuilder& BufferBuilder::MemoryType(VkMemoryPropertyFlags requiredFlags, Vk
|
|||
return *this;
|
||||
}
|
||||
|
||||
BufferBuilder& BufferBuilder::MinAlignment(VkDeviceSize memoryAlignment)
|
||||
{
|
||||
minAlignment = memoryAlignment;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::unique_ptr<VulkanBuffer> BufferBuilder::Create(VulkanDevice* device)
|
||||
{
|
||||
VkBuffer buffer;
|
||||
VmaAllocation allocation;
|
||||
|
||||
VkResult result = vmaCreateBuffer(device->allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
|
||||
CheckVulkanError(result, "Could not allocate memory for vulkan buffer");
|
||||
if (minAlignment == 0)
|
||||
{
|
||||
VkResult result = vmaCreateBuffer(device->allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
|
||||
CheckVulkanError(result, "Could not allocate memory for vulkan buffer");
|
||||
}
|
||||
else
|
||||
{
|
||||
VkResult result = vmaCreateBufferWithAlignment(device->allocator, &bufferInfo, &allocInfo, minAlignment, &buffer, &allocation, nullptr);
|
||||
CheckVulkanError(result, "Could not allocate memory for vulkan buffer");
|
||||
}
|
||||
|
||||
auto obj = std::make_unique<VulkanBuffer>(device, buffer, allocation, bufferInfo.size);
|
||||
if (debugName)
|
||||
|
@ -1175,9 +1305,9 @@ std::unique_ptr<VulkanPipelineCache> PipelineCacheBuilder::Create(VulkanDevice*
|
|||
{
|
||||
VkPipelineCacheHeaderVersionOne* header = (VkPipelineCacheHeaderVersionOne*)initData.data();
|
||||
if (header->headerVersion == VK_PIPELINE_CACHE_HEADER_VERSION_ONE &&
|
||||
header->vendorID == device->PhysicalDevice.Properties.vendorID &&
|
||||
header->deviceID == device->PhysicalDevice.Properties.deviceID &&
|
||||
memcmp(header->pipelineCacheUUID, device->PhysicalDevice.Properties.pipelineCacheUUID, VK_UUID_SIZE) == 0)
|
||||
header->vendorID == device->PhysicalDevice.Properties.Properties.vendorID &&
|
||||
header->deviceID == device->PhysicalDevice.Properties.Properties.deviceID &&
|
||||
memcmp(header->pipelineCacheUUID, device->PhysicalDevice.Properties.Properties.pipelineCacheUUID, VK_UUID_SIZE) == 0)
|
||||
{
|
||||
pipelineCacheInfo.pInitialData = initData.data();
|
||||
pipelineCacheInfo.initialDataSize = initData.size();
|
||||
|
@ -1329,12 +1459,12 @@ PipelineBarrier& PipelineBarrier::AddBuffer(VulkanBuffer* buffer, VkDeviceSize o
|
|||
return *this;
|
||||
}
|
||||
|
||||
PipelineBarrier& PipelineBarrier::AddImage(VulkanImage* image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount)
|
||||
PipelineBarrier& PipelineBarrier::AddImage(VulkanImage* image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount, int baseArrayLayer, int layerCount)
|
||||
{
|
||||
return AddImage(image->image, oldLayout, newLayout, srcAccessMask, dstAccessMask, aspectMask, baseMipLevel, levelCount);
|
||||
return AddImage(image->image, oldLayout, newLayout, srcAccessMask, dstAccessMask, aspectMask, baseMipLevel, levelCount, baseArrayLayer, layerCount);
|
||||
}
|
||||
|
||||
PipelineBarrier& PipelineBarrier::AddImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount)
|
||||
PipelineBarrier& PipelineBarrier::AddImage(VkImage image, VkImageLayout oldLayout, VkImageLayout newLayout, VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, VkImageAspectFlags aspectMask, int baseMipLevel, int levelCount, int baseArrayLayer, int layerCount)
|
||||
{
|
||||
VkImageMemoryBarrier barrier = { };
|
||||
barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
||||
|
@ -1348,8 +1478,8 @@ PipelineBarrier& PipelineBarrier::AddImage(VkImage image, VkImageLayout oldLayou
|
|||
barrier.subresourceRange.aspectMask = aspectMask;
|
||||
barrier.subresourceRange.baseMipLevel = baseMipLevel;
|
||||
barrier.subresourceRange.levelCount = levelCount;
|
||||
barrier.subresourceRange.baseArrayLayer = 0;
|
||||
barrier.subresourceRange.layerCount = 1;
|
||||
barrier.subresourceRange.baseArrayLayer = baseArrayLayer;
|
||||
barrier.subresourceRange.layerCount = layerCount;
|
||||
imageMemoryBarriers.push_back(barrier);
|
||||
return *this;
|
||||
}
|
||||
|
@ -1767,13 +1897,13 @@ std::vector<VulkanCompatibleDevice> VulkanDeviceBuilder::FindDevices(const std::
|
|||
{
|
||||
// Sort by GPU type first. This will ensure the "best" device is most likely to map to vk_device 0
|
||||
static const int typeSort[] = { 4, 1, 0, 2, 3 };
|
||||
int sortA = a.Device->Properties.deviceType < 5 ? typeSort[a.Device->Properties.deviceType] : (int)a.Device->Properties.deviceType;
|
||||
int sortB = b.Device->Properties.deviceType < 5 ? typeSort[b.Device->Properties.deviceType] : (int)b.Device->Properties.deviceType;
|
||||
int sortA = a.Device->Properties.Properties.deviceType < 5 ? typeSort[a.Device->Properties.Properties.deviceType] : (int)a.Device->Properties.Properties.deviceType;
|
||||
int sortB = b.Device->Properties.Properties.deviceType < 5 ? typeSort[b.Device->Properties.Properties.deviceType] : (int)b.Device->Properties.Properties.deviceType;
|
||||
if (sortA != sortB)
|
||||
return sortA < sortB;
|
||||
|
||||
// Then sort by the device's unique ID so that vk_device uses a consistent order
|
||||
int sortUUID = memcmp(a.Device->Properties.pipelineCacheUUID, b.Device->Properties.pipelineCacheUUID, VK_UUID_SIZE);
|
||||
int sortUUID = memcmp(a.Device->Properties.Properties.pipelineCacheUUID, b.Device->Properties.Properties.pipelineCacheUUID, VK_UUID_SIZE);
|
||||
return sortUUID < 0;
|
||||
};
|
||||
std::stable_sort(supportedDevices.begin(), supportedDevices.end(), sortFunc);
|
||||
|
|
|
@ -33,18 +33,20 @@ VulkanDevice::~VulkanDevice()
|
|||
ReleaseResources();
|
||||
}
|
||||
|
||||
bool VulkanDevice::SupportsDeviceExtension(const char* ext) const
|
||||
bool VulkanDevice::SupportsExtension(const char* ext) const
|
||||
{
|
||||
return EnabledDeviceExtensions.find(ext) != EnabledDeviceExtensions.end();
|
||||
return
|
||||
EnabledDeviceExtensions.find(ext) != EnabledDeviceExtensions.end() ||
|
||||
Instance->EnabledExtensions.find(ext) != Instance->EnabledExtensions.end();
|
||||
}
|
||||
|
||||
void VulkanDevice::CreateAllocator()
|
||||
{
|
||||
VmaAllocatorCreateInfo allocinfo = {};
|
||||
allocinfo.vulkanApiVersion = Instance->ApiVersion;
|
||||
if (SupportsDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) && SupportsDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME))
|
||||
if (SupportsExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) && SupportsExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME))
|
||||
allocinfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
|
||||
if (SupportsDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME))
|
||||
if (SupportsExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME))
|
||||
allocinfo.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
|
||||
allocinfo.physicalDevice = PhysicalDevice.Device;
|
||||
allocinfo.device = device;
|
||||
|
@ -91,7 +93,7 @@ void VulkanDevice::CreateDevice()
|
|||
deviceFeatures2.features = EnabledFeatures.Features;
|
||||
|
||||
void** next = const_cast<void**>(&deviceCreateInfo.pNext);
|
||||
if (SupportsDeviceExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
|
||||
if (SupportsExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
|
||||
{
|
||||
*next = &deviceFeatures2;
|
||||
next = &deviceFeatures2.pNext;
|
||||
|
@ -101,22 +103,22 @@ void VulkanDevice::CreateDevice()
|
|||
deviceCreateInfo.pEnabledFeatures = &deviceFeatures2.features;
|
||||
}
|
||||
|
||||
if (SupportsDeviceExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME))
|
||||
if (SupportsExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME))
|
||||
{
|
||||
*next = &EnabledFeatures.BufferDeviceAddress;
|
||||
next = &EnabledFeatures.BufferDeviceAddress.pNext;
|
||||
}
|
||||
if (SupportsDeviceExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME))
|
||||
if (SupportsExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME))
|
||||
{
|
||||
*next = &EnabledFeatures.AccelerationStructure;
|
||||
next = &EnabledFeatures.AccelerationStructure.pNext;
|
||||
}
|
||||
if (SupportsDeviceExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
|
||||
if (SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
|
||||
{
|
||||
*next = &EnabledFeatures.RayQuery;
|
||||
next = &EnabledFeatures.RayQuery.pNext;
|
||||
}
|
||||
if (SupportsDeviceExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME))
|
||||
if (SupportsExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME))
|
||||
{
|
||||
*next = &EnabledFeatures.DescriptorIndexing;
|
||||
next = &EnabledFeatures.DescriptorIndexing.pNext;
|
||||
|
|
|
@ -163,9 +163,6 @@ std::vector<VulkanPhysicalDevice> VulkanInstance::GetPhysicalDevices(VkInstance
|
|||
auto& dev = devinfo[i];
|
||||
dev.Device = devices[i];
|
||||
|
||||
vkGetPhysicalDeviceMemoryProperties(dev.Device, &dev.MemoryProperties);
|
||||
vkGetPhysicalDeviceProperties(dev.Device, &dev.Properties);
|
||||
|
||||
uint32_t queueFamilyCount = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(dev.Device, &queueFamilyCount, nullptr);
|
||||
dev.QueueFamilies.resize(queueFamilyCount);
|
||||
|
@ -186,11 +183,32 @@ std::vector<VulkanPhysicalDevice> VulkanInstance::GetPhysicalDevices(VkInstance
|
|||
return false;
|
||||
};
|
||||
|
||||
vkGetPhysicalDeviceMemoryProperties(dev.Device, &dev.Properties.Memory);
|
||||
|
||||
if (apiVersion != VK_API_VERSION_1_0)
|
||||
{
|
||||
VkPhysicalDeviceProperties2 deviceProperties2 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2 };
|
||||
|
||||
void** next = const_cast<void**>(&deviceProperties2.pNext);
|
||||
if (checkForExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME))
|
||||
{
|
||||
*next = &dev.Properties.AccelerationStructure;
|
||||
next = &dev.Properties.AccelerationStructure.pNext;
|
||||
}
|
||||
if (checkForExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME))
|
||||
{
|
||||
*next = &dev.Properties.DescriptorIndexing;
|
||||
next = &dev.Properties.DescriptorIndexing.pNext;
|
||||
}
|
||||
|
||||
vkGetPhysicalDeviceProperties2(dev.Device, &deviceProperties2);
|
||||
dev.Properties.Properties = deviceProperties2.properties;
|
||||
dev.Properties.AccelerationStructure.pNext = nullptr;
|
||||
dev.Properties.DescriptorIndexing.pNext = nullptr;
|
||||
|
||||
VkPhysicalDeviceFeatures2 deviceFeatures2 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 };
|
||||
|
||||
void** next = const_cast<void**>(&deviceFeatures2.pNext);
|
||||
next = const_cast<void**>(&deviceFeatures2.pNext);
|
||||
if (checkForExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME))
|
||||
{
|
||||
*next = &dev.Features.BufferDeviceAddress;
|
||||
|
@ -221,6 +239,7 @@ std::vector<VulkanPhysicalDevice> VulkanInstance::GetPhysicalDevices(VkInstance
|
|||
}
|
||||
else
|
||||
{
|
||||
vkGetPhysicalDeviceProperties(dev.Device, &dev.Properties.Properties);
|
||||
vkGetPhysicalDeviceFeatures(dev.Device, &dev.Features.Features);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#include <stdexcept>
|
||||
|
||||
#include "vulkanswapchain.h"
|
||||
#include "vulkanobjects.h"
|
||||
#include "vulkansurface.h"
|
||||
|
@ -21,26 +21,12 @@ void VulkanSwapChain::Create(int width, int height, int imageCount, bool vsync,
|
|||
views.clear();
|
||||
images.clear();
|
||||
|
||||
SelectFormat(hdr);
|
||||
SelectPresentMode(vsync, exclusivefullscreen);
|
||||
|
||||
VkSwapchainKHR oldSwapchain = swapchain;
|
||||
CreateSwapchain(width, height, imageCount, exclusivefullscreen, oldSwapchain);
|
||||
if (oldSwapchain)
|
||||
vkDestroySwapchainKHR(device->device, oldSwapchain, nullptr);
|
||||
CreateSwapchain(width, height, imageCount, vsync, hdr, exclusivefullscreen);
|
||||
|
||||
if (exclusivefullscreen && lost)
|
||||
{
|
||||
// We could not acquire exclusive fullscreen. Fall back to normal fullsceen instead.
|
||||
exclusivefullscreen = false;
|
||||
|
||||
SelectFormat(hdr);
|
||||
SelectPresentMode(vsync, exclusivefullscreen);
|
||||
|
||||
oldSwapchain = swapchain;
|
||||
CreateSwapchain(width, height, imageCount, exclusivefullscreen, oldSwapchain);
|
||||
if (oldSwapchain)
|
||||
vkDestroySwapchainKHR(device->device, oldSwapchain, nullptr);
|
||||
CreateSwapchain(width, height, imageCount, vsync, hdr, false);
|
||||
}
|
||||
|
||||
if (swapchain)
|
||||
|
@ -70,13 +56,9 @@ void VulkanSwapChain::Create(int width, int height, int imageCount, bool vsync,
|
|||
}
|
||||
}
|
||||
|
||||
void VulkanSwapChain::SelectFormat(bool hdr)
|
||||
void VulkanSwapChain::SelectFormat(const VulkanSurfaceCapabilities& caps, bool hdr)
|
||||
{
|
||||
std::vector<VkSurfaceFormatKHR> surfaceFormats = GetSurfaceFormats();
|
||||
if (surfaceFormats.empty())
|
||||
throw std::runtime_error("No surface formats supported");
|
||||
|
||||
if (surfaceFormats.size() == 1 && surfaceFormats.front().format == VK_FORMAT_UNDEFINED)
|
||||
if (caps.Formats.size() == 1 && caps.Formats.front().format == VK_FORMAT_UNDEFINED)
|
||||
{
|
||||
format.format = VK_FORMAT_B8G8R8A8_UNORM;
|
||||
format.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
|
||||
|
@ -85,7 +67,7 @@ void VulkanSwapChain::SelectFormat(bool hdr)
|
|||
|
||||
if (hdr)
|
||||
{
|
||||
for (const auto& f : surfaceFormats)
|
||||
for (const auto& f : caps.Formats)
|
||||
{
|
||||
if (f.format == VK_FORMAT_R16G16B16A16_SFLOAT && f.colorSpace == VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT)
|
||||
{
|
||||
|
@ -95,7 +77,7 @@ void VulkanSwapChain::SelectFormat(bool hdr)
|
|||
}
|
||||
}
|
||||
|
||||
for (const auto& f : surfaceFormats)
|
||||
for (const auto& f : caps.Formats)
|
||||
{
|
||||
if (f.format == VK_FORMAT_B8G8R8A8_UNORM && f.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)
|
||||
{
|
||||
|
@ -104,79 +86,58 @@ void VulkanSwapChain::SelectFormat(bool hdr)
|
|||
}
|
||||
}
|
||||
|
||||
format = surfaceFormats.front();
|
||||
format = caps.Formats.front();
|
||||
}
|
||||
|
||||
void VulkanSwapChain::SelectPresentMode(bool vsync, bool exclusivefullscreen)
|
||||
bool VulkanSwapChain::CreateSwapchain(int width, int height, int imageCount, bool vsync, bool hdr, bool exclusivefullscreen)
|
||||
{
|
||||
std::vector<VkPresentModeKHR> presentModes = GetPresentModes(exclusivefullscreen);
|
||||
if (presentModes.empty())
|
||||
lost = false;
|
||||
|
||||
VulkanSurfaceCapabilities caps = GetSurfaceCapabilities(exclusivefullscreen);
|
||||
|
||||
if (exclusivefullscreen && (caps.PresentModes.empty() || !caps.FullScreenExclusive.fullScreenExclusiveSupported))
|
||||
{
|
||||
// Try again without exclusive full screen.
|
||||
exclusivefullscreen = false;
|
||||
caps = GetSurfaceCapabilities(exclusivefullscreen);
|
||||
}
|
||||
|
||||
if (caps.PresentModes.empty())
|
||||
throw std::runtime_error("No surface present modes supported");
|
||||
|
||||
bool supportsFifoRelaxed = std::find(caps.PresentModes.begin(), caps.PresentModes.end(), VK_PRESENT_MODE_FIFO_RELAXED_KHR) != caps.PresentModes.end();
|
||||
bool supportsMailbox = std::find(caps.PresentModes.begin(), caps.PresentModes.end(), VK_PRESENT_MODE_MAILBOX_KHR) != caps.PresentModes.end();
|
||||
bool supportsImmediate = std::find(caps.PresentModes.begin(), caps.PresentModes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR) != caps.PresentModes.end();
|
||||
|
||||
presentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||
if (vsync)
|
||||
{
|
||||
bool supportsFifoRelaxed = std::find(presentModes.begin(), presentModes.end(), VK_PRESENT_MODE_FIFO_RELAXED_KHR) != presentModes.end();
|
||||
if (supportsFifoRelaxed)
|
||||
presentMode = VK_PRESENT_MODE_FIFO_RELAXED_KHR;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool supportsMailbox = std::find(presentModes.begin(), presentModes.end(), VK_PRESENT_MODE_MAILBOX_KHR) != presentModes.end();
|
||||
bool supportsImmediate = std::find(presentModes.begin(), presentModes.end(), VK_PRESENT_MODE_IMMEDIATE_KHR) != presentModes.end();
|
||||
if (supportsMailbox)
|
||||
presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
|
||||
else if (supportsImmediate)
|
||||
presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||
if (exclusivefullscreen) // Exclusive full screen doesn't seem to support mailbox for some reason, even if it is advertised
|
||||
{
|
||||
if (supportsImmediate)
|
||||
presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||
else if (supportsMailbox)
|
||||
presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (supportsMailbox)
|
||||
presentMode = VK_PRESENT_MODE_MAILBOX_KHR;
|
||||
else if (supportsImmediate)
|
||||
presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool VulkanSwapChain::CreateSwapchain(int width, int height, int imageCount, bool exclusivefullscreen, VkSwapchainKHR oldSwapChain)
|
||||
{
|
||||
lost = false;
|
||||
|
||||
VkResult result;
|
||||
VkSurfaceCapabilitiesKHR surfaceCapabilities;
|
||||
#ifdef WIN32
|
||||
if (exclusivefullscreen && device->SupportsDeviceExtension(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME))
|
||||
{
|
||||
VkPhysicalDeviceSurfaceInfo2KHR info = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR };
|
||||
VkSurfaceFullScreenExclusiveInfoEXT exclusiveInfo = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT };
|
||||
VkSurfaceFullScreenExclusiveWin32InfoEXT exclusiveWin32Info = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT };
|
||||
info.surface = device->Surface->Surface;
|
||||
info.pNext = &exclusiveInfo;
|
||||
exclusiveInfo.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT;
|
||||
exclusiveInfo.pNext = &exclusiveWin32Info;
|
||||
exclusiveWin32Info.hmonitor = MonitorFromWindow(device->Surface->Window, MONITOR_DEFAULTTONEAREST);
|
||||
|
||||
VkSurfaceCapabilities2KHR capabilites = { VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR };
|
||||
VkSurfaceCapabilitiesFullScreenExclusiveEXT exclusiveCapabilities = { VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_FULL_SCREEN_EXCLUSIVE_EXT };
|
||||
capabilites.pNext = &exclusiveCapabilities;
|
||||
|
||||
result = vkGetPhysicalDeviceSurfaceCapabilities2KHR(device->PhysicalDevice.Device, &info, &capabilites);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfaceCapabilities2EXT failed");
|
||||
|
||||
surfaceCapabilities = capabilites.surfaceCapabilities;
|
||||
exclusivefullscreen = exclusiveCapabilities.fullScreenExclusiveSupported == VK_TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->PhysicalDevice.Device, device->Surface->Surface, &surfaceCapabilities);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed");
|
||||
exclusivefullscreen = false;
|
||||
}
|
||||
#else
|
||||
result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->PhysicalDevice.Device, device->Surface->Surface, &surfaceCapabilities);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed");
|
||||
exclusivefullscreen = false;
|
||||
#endif
|
||||
SelectFormat(caps, hdr);
|
||||
|
||||
actualExtent = { static_cast<uint32_t>(width), static_cast<uint32_t>(height) };
|
||||
actualExtent.width = std::max(surfaceCapabilities.minImageExtent.width, std::min(surfaceCapabilities.maxImageExtent.width, actualExtent.width));
|
||||
actualExtent.height = std::max(surfaceCapabilities.minImageExtent.height, std::min(surfaceCapabilities.maxImageExtent.height, actualExtent.height));
|
||||
actualExtent.width = std::max(caps.Capabilites.minImageExtent.width, std::min(caps.Capabilites.maxImageExtent.width, actualExtent.width));
|
||||
actualExtent.height = std::max(caps.Capabilites.minImageExtent.height, std::min(caps.Capabilites.maxImageExtent.height, actualExtent.height));
|
||||
if (actualExtent.width == 0 || actualExtent.height == 0)
|
||||
{
|
||||
swapchain = VK_NULL_HANDLE;
|
||||
|
@ -184,9 +145,16 @@ bool VulkanSwapChain::CreateSwapchain(int width, int height, int imageCount, boo
|
|||
return false;
|
||||
}
|
||||
|
||||
imageCount = std::max(surfaceCapabilities.minImageCount, std::min(surfaceCapabilities.maxImageCount, (uint32_t)imageCount));
|
||||
if (caps.Capabilites.maxImageCount != 0)
|
||||
imageCount = std::min(caps.Capabilites.maxImageCount, (uint32_t)imageCount);
|
||||
imageCount = std::max(caps.Capabilites.minImageCount, (uint32_t)imageCount);
|
||||
|
||||
VkSwapchainCreateInfoKHR swapChainCreateInfo = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR };
|
||||
#ifdef WIN32
|
||||
VkSurfaceFullScreenExclusiveInfoEXT exclusiveInfo = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT };
|
||||
VkSurfaceFullScreenExclusiveWin32InfoEXT exclusiveWin32Info = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT };
|
||||
#endif
|
||||
|
||||
swapChainCreateInfo.surface = device->Surface->Surface;
|
||||
swapChainCreateInfo.minImageCount = imageCount;
|
||||
swapChainCreateInfo.imageFormat = format.format;
|
||||
|
@ -209,25 +177,27 @@ bool VulkanSwapChain::CreateSwapchain(int width, int height, int imageCount, boo
|
|||
swapChainCreateInfo.pQueueFamilyIndices = nullptr;
|
||||
}
|
||||
|
||||
swapChainCreateInfo.preTransform = surfaceCapabilities.currentTransform;
|
||||
swapChainCreateInfo.preTransform = caps.Capabilites.currentTransform;
|
||||
swapChainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; // If alpha channel is passed on to the DWM or not
|
||||
swapChainCreateInfo.presentMode = presentMode;
|
||||
swapChainCreateInfo.clipped = VK_FALSE;// VK_TRUE;
|
||||
swapChainCreateInfo.oldSwapchain = oldSwapChain;
|
||||
swapChainCreateInfo.clipped = VK_TRUE; // Applications SHOULD set this value to VK_TRUE if they do not expect to read back the content of presentable images before presenting them or after reacquiring them, and if their fragment shaders do not have any side effects that require them to run for all pixels in the presentable image
|
||||
swapChainCreateInfo.oldSwapchain = swapchain;
|
||||
|
||||
#ifdef WIN32
|
||||
VkSurfaceFullScreenExclusiveInfoEXT exclusiveInfo = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT };
|
||||
VkSurfaceFullScreenExclusiveWin32InfoEXT exclusiveWin32Info = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT };
|
||||
if (exclusivefullscreen && device->SupportsDeviceExtension(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME))
|
||||
if (exclusivefullscreen)
|
||||
{
|
||||
swapChainCreateInfo.pNext = &exclusiveInfo;
|
||||
exclusiveInfo.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT;
|
||||
exclusiveInfo.pNext = &exclusiveWin32Info;
|
||||
exclusiveInfo.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT;
|
||||
exclusiveWin32Info.hmonitor = MonitorFromWindow(device->Surface->Window, MONITOR_DEFAULTTONEAREST);
|
||||
}
|
||||
#endif
|
||||
|
||||
result = vkCreateSwapchainKHR(device->device, &swapChainCreateInfo, nullptr, &swapchain);
|
||||
VkResult result = vkCreateSwapchainKHR(device->device, &swapChainCreateInfo, nullptr, &swapchain);
|
||||
|
||||
if (swapChainCreateInfo.oldSwapchain)
|
||||
vkDestroySwapchainKHR(device->device, swapChainCreateInfo.oldSwapchain, nullptr);
|
||||
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
swapchain = VK_NULL_HANDLE;
|
||||
|
@ -236,7 +206,7 @@ bool VulkanSwapChain::CreateSwapchain(int width, int height, int imageCount, boo
|
|||
}
|
||||
|
||||
#ifdef WIN32
|
||||
if (exclusivefullscreen && device->SupportsDeviceExtension(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME))
|
||||
if (exclusivefullscreen)
|
||||
{
|
||||
result = vkAcquireFullScreenExclusiveModeEXT(device->device, swapchain);
|
||||
if (result != VK_SUCCESS)
|
||||
|
@ -312,45 +282,84 @@ void VulkanSwapChain::QueuePresent(int imageIndex, VulkanSemaphore* semaphore)
|
|||
}
|
||||
}
|
||||
|
||||
std::vector<VkSurfaceFormatKHR> VulkanSwapChain::GetSurfaceFormats()
|
||||
VulkanSurfaceCapabilities VulkanSwapChain::GetSurfaceCapabilities(bool exclusivefullscreen)
|
||||
{
|
||||
uint32_t surfaceFormatCount = 0;
|
||||
VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->Surface->Surface, &surfaceFormatCount, nullptr);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfaceFormatsKHR failed");
|
||||
else if (surfaceFormatCount == 0)
|
||||
return {};
|
||||
// They sure made it easy to query something that isn't even time critical. Good job guys!
|
||||
|
||||
std::vector<VkSurfaceFormatKHR> surfaceFormats(surfaceFormatCount);
|
||||
result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->Surface->Surface, &surfaceFormatCount, surfaceFormats.data());
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfaceFormatsKHR failed");
|
||||
return surfaceFormats;
|
||||
}
|
||||
VulkanSurfaceCapabilities caps;
|
||||
|
||||
std::vector<VkPresentModeKHR> VulkanSwapChain::GetPresentModes(bool exclusivefullscreen)
|
||||
{
|
||||
VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR };
|
||||
#ifdef WIN32
|
||||
if (exclusivefullscreen && device->SupportsDeviceExtension(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME))
|
||||
VkSurfaceFullScreenExclusiveInfoEXT exclusiveInfo = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT };
|
||||
VkSurfaceFullScreenExclusiveWin32InfoEXT exclusiveWin32Info = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_WIN32_INFO_EXT };
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
if (exclusivefullscreen)
|
||||
{
|
||||
VkPhysicalDeviceSurfaceInfo2KHR surfaceInfo = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR };
|
||||
VkSurfaceFullScreenExclusiveInfoEXT exclusiveInfo = { VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT };
|
||||
surfaceInfo.surface = device->Surface->Surface;
|
||||
surfaceInfo.pNext = &exclusiveInfo;
|
||||
exclusiveInfo.fullScreenExclusive = VK_FULL_SCREEN_EXCLUSIVE_APPLICATION_CONTROLLED_EXT;
|
||||
exclusiveWin32Info.hmonitor = MonitorFromWindow(device->Surface->Window, MONITOR_DEFAULTTONEAREST);
|
||||
}
|
||||
#endif
|
||||
|
||||
surfaceInfo.surface = device->Surface->Surface;
|
||||
|
||||
if (device->SupportsExtension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME))
|
||||
{
|
||||
const void** next = &surfaceInfo.pNext;
|
||||
|
||||
#ifdef WIN32
|
||||
if (exclusivefullscreen && device->SupportsExtension(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME))
|
||||
{
|
||||
*next = &exclusiveInfo;
|
||||
next = const_cast<const void**>(&exclusiveInfo.pNext);
|
||||
|
||||
*next = &exclusiveWin32Info;
|
||||
next = &exclusiveWin32Info.pNext;
|
||||
}
|
||||
#endif
|
||||
|
||||
VkSurfaceCapabilities2KHR caps2 = { VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR };
|
||||
next = const_cast<const void**>(&caps2.pNext);
|
||||
|
||||
#ifdef WIN32
|
||||
if (exclusivefullscreen && device->SupportsExtension(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME))
|
||||
{
|
||||
*next = &caps.FullScreenExclusive;
|
||||
next = const_cast<const void**>(&caps.FullScreenExclusive.pNext);
|
||||
}
|
||||
#endif
|
||||
|
||||
VkResult result = vkGetPhysicalDeviceSurfaceCapabilities2KHR(device->PhysicalDevice.Device, &surfaceInfo, &caps2);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfaceCapabilities2KHR failed");
|
||||
|
||||
caps.Capabilites = caps2.surfaceCapabilities;
|
||||
}
|
||||
else
|
||||
{
|
||||
VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->PhysicalDevice.Device, device->Surface->Surface, &caps.Capabilites);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed");
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
if (exclusivefullscreen && device->SupportsExtension(VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME))
|
||||
{
|
||||
const void** next = &surfaceInfo.pNext;
|
||||
|
||||
uint32_t presentModeCount = 0;
|
||||
VkResult result = vkGetPhysicalDeviceSurfacePresentModes2EXT(device->PhysicalDevice.Device, &surfaceInfo, &presentModeCount, nullptr);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModes2EXT failed");
|
||||
else if (presentModeCount == 0)
|
||||
return {};
|
||||
|
||||
std::vector<VkPresentModeKHR> presentModes(presentModeCount);
|
||||
result = vkGetPhysicalDeviceSurfacePresentModes2EXT(device->PhysicalDevice.Device, &surfaceInfo, &presentModeCount, presentModes.data());
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModes2EXT failed");
|
||||
return presentModes;
|
||||
if (presentModeCount > 0)
|
||||
{
|
||||
caps.PresentModes.resize(presentModeCount);
|
||||
result = vkGetPhysicalDeviceSurfacePresentModes2EXT(device->PhysicalDevice.Device, &surfaceInfo, &presentModeCount, caps.PresentModes.data());
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModes2EXT failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
|
@ -359,13 +368,51 @@ std::vector<VkPresentModeKHR> VulkanSwapChain::GetPresentModes(bool exclusiveful
|
|||
VkResult result = vkGetPhysicalDeviceSurfacePresentModesKHR(device->PhysicalDevice.Device, device->Surface->Surface, &presentModeCount, nullptr);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModesKHR failed");
|
||||
else if (presentModeCount == 0)
|
||||
return {};
|
||||
|
||||
std::vector<VkPresentModeKHR> presentModes(presentModeCount);
|
||||
result = vkGetPhysicalDeviceSurfacePresentModesKHR(device->PhysicalDevice.Device, device->Surface->Surface, &presentModeCount, presentModes.data());
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModesKHR failed");
|
||||
return presentModes;
|
||||
if (presentModeCount > 0)
|
||||
{
|
||||
caps.PresentModes.resize(presentModeCount);
|
||||
result = vkGetPhysicalDeviceSurfacePresentModesKHR(device->PhysicalDevice.Device, device->Surface->Surface, &presentModeCount, caps.PresentModes.data());
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModesKHR failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (device->SupportsExtension(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME))
|
||||
{
|
||||
uint32_t surfaceFormatCount = 0;
|
||||
VkResult result = vkGetPhysicalDeviceSurfaceFormats2KHR(device->PhysicalDevice.Device, &surfaceInfo, &surfaceFormatCount, nullptr);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfaceFormats2KHR failed");
|
||||
|
||||
if (surfaceFormatCount > 0)
|
||||
{
|
||||
std::vector<VkSurfaceFormat2KHR> formats(surfaceFormatCount, { VK_STRUCTURE_TYPE_SURFACE_FORMAT_2_KHR });
|
||||
result = vkGetPhysicalDeviceSurfaceFormats2KHR(device->PhysicalDevice.Device, &surfaceInfo, &surfaceFormatCount, formats.data());
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfaceFormats2KHR failed");
|
||||
|
||||
for (VkSurfaceFormat2KHR& fmt : formats)
|
||||
caps.Formats.push_back(fmt.surfaceFormat);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t surfaceFormatCount = 0;
|
||||
VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->Surface->Surface, &surfaceFormatCount, nullptr);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfaceFormatsKHR failed");
|
||||
|
||||
if (surfaceFormatCount > 0)
|
||||
{
|
||||
caps.Formats.resize(surfaceFormatCount);
|
||||
result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->Surface->Surface, &surfaceFormatCount, caps.Formats.data());
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfaceFormatsKHR failed");
|
||||
}
|
||||
}
|
||||
|
||||
caps.FullScreenExclusive.pNext = nullptr;
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
|
|
@ -36,12 +36,14 @@ VkPPShader::VkPPShader(VulkanRenderDevice* fb, PPShader *shader) : fb(fb)
|
|||
prolog += shader->Defines;
|
||||
|
||||
VertexShader = ShaderBuilder()
|
||||
.VertexShader(LoadShaderCode(shader->VertexShader, "", shader->Version).GetChars())
|
||||
.Type(ShaderType::Vertex)
|
||||
.AddSource(shader->VertexShader.GetChars(), LoadShaderCode(shader->VertexShader, "", shader->Version).GetChars())
|
||||
.DebugName(shader->VertexShader.GetChars())
|
||||
.Create(shader->VertexShader.GetChars(), fb->device.get());
|
||||
|
||||
FragmentShader = ShaderBuilder()
|
||||
.FragmentShader(LoadShaderCode(shader->FragmentShader, prolog, shader->Version).GetChars())
|
||||
.Type(ShaderType::Fragment)
|
||||
.AddSource(shader->FragmentShader.GetChars(), LoadShaderCode(shader->FragmentShader, prolog, shader->Version).GetChars())
|
||||
.DebugName(shader->FragmentShader.GetChars())
|
||||
.Create(shader->FragmentShader.GetChars(), fb->device.get());
|
||||
|
||||
|
|
|
@ -352,7 +352,8 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadVertShader(FString shadername
|
|||
code << LoadPrivateShaderLump(vert_lump).GetChars() << "\n";
|
||||
|
||||
return ShaderBuilder()
|
||||
.VertexShader(code.GetChars())
|
||||
.Type(ShaderType::Vertex)
|
||||
.AddSource(shadername.GetChars(), code.GetChars())
|
||||
.DebugName(shadername.GetChars())
|
||||
.Create(shadername.GetChars(), fb->device.get());
|
||||
}
|
||||
|
@ -444,7 +445,8 @@ std::unique_ptr<VulkanShader> VkShaderManager::LoadFragShader(FString shadername
|
|||
}
|
||||
|
||||
return ShaderBuilder()
|
||||
.FragmentShader(code.GetChars())
|
||||
.Type(ShaderType::Fragment)
|
||||
.AddSource(shadername.GetChars(), code.GetChars())
|
||||
.DebugName(shadername.GetChars())
|
||||
.Create(shadername.GetChars(), fb->device.get());
|
||||
}
|
||||
|
|
|
@ -241,7 +241,7 @@ void VkCommandBufferManager::UpdateGpuStats()
|
|||
if (mNextTimestampQuery > 0)
|
||||
mTimestampQueryPool->getResults(0, mNextTimestampQuery, sizeof(uint64_t) * mNextTimestampQuery, timestamps, sizeof(uint64_t), VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WAIT_BIT);
|
||||
|
||||
double timestampPeriod = fb->device->PhysicalDevice.Properties.limits.timestampPeriod;
|
||||
double timestampPeriod = fb->device->PhysicalDevice.Properties.Properties.limits.timestampPeriod;
|
||||
|
||||
gpuStatOutput = "";
|
||||
for (auto& q : timeElapsedQueries)
|
||||
|
|
|
@ -72,21 +72,6 @@ EXTERN_CVAR(Int, gl_tonemap)
|
|||
EXTERN_CVAR(Int, screenblocks)
|
||||
EXTERN_CVAR(Bool, cl_capfps)
|
||||
|
||||
CCMD(vk_memstats)
|
||||
{
|
||||
if (screen->IsVulkan())
|
||||
{
|
||||
VmaStats stats = {};
|
||||
vmaCalculateStats(static_cast<VulkanRenderDevice*>(screen)->device->allocator, &stats);
|
||||
Printf("Allocated objects: %d, used bytes: %d MB\n", (int)stats.total.allocationCount, (int)stats.total.usedBytes / (1024 * 1024));
|
||||
Printf("Unused range count: %d, unused bytes: %d MB\n", (int)stats.total.unusedRangeCount, (int)stats.total.unusedBytes / (1024 * 1024));
|
||||
}
|
||||
else
|
||||
{
|
||||
Printf("Vulkan is not the current render device\n");
|
||||
}
|
||||
}
|
||||
|
||||
CVAR(Bool, vk_raytrace, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
|
||||
// Physical device info
|
||||
|
@ -108,7 +93,7 @@ CCMD(vk_listdevices)
|
|||
{
|
||||
for (size_t i = 0; i < SupportedDevices.size(); i++)
|
||||
{
|
||||
Printf("#%d - %s\n", (int)i, SupportedDevices[i].Device->Properties.deviceName);
|
||||
Printf("#%d - %s\n", (int)i, SupportedDevices[i].Device->Properties.Properties.deviceName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,7 +164,7 @@ void VulkanRenderDevice::InitializeState()
|
|||
}
|
||||
|
||||
// Use the same names here as OpenGL returns.
|
||||
switch (device->PhysicalDevice.Properties.vendorID)
|
||||
switch (device->PhysicalDevice.Properties.Properties.vendorID)
|
||||
{
|
||||
case 0x1002: vendorstring = "ATI Technologies Inc."; break;
|
||||
case 0x10DE: vendorstring = "NVIDIA Corporation"; break;
|
||||
|
@ -189,8 +174,8 @@ void VulkanRenderDevice::InitializeState()
|
|||
|
||||
hwcaps = RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE;
|
||||
glslversion = 4.50f;
|
||||
uniformblockalignment = (unsigned int)device->PhysicalDevice.Properties.limits.minUniformBufferOffsetAlignment;
|
||||
maxuniformblock = device->PhysicalDevice.Properties.limits.maxUniformBufferRange;
|
||||
uniformblockalignment = (unsigned int)device->PhysicalDevice.Properties.Properties.limits.minUniformBufferOffsetAlignment;
|
||||
maxuniformblock = device->PhysicalDevice.Properties.Properties.limits.maxUniformBufferRange;
|
||||
|
||||
mCommands.reset(new VkCommandBufferManager(this));
|
||||
|
||||
|
@ -293,8 +278,7 @@ void VulkanRenderDevice::PostProcessScene(bool swscene, int fixedcm, float flash
|
|||
|
||||
const char* VulkanRenderDevice::DeviceName() const
|
||||
{
|
||||
const auto &props = device->PhysicalDevice.Properties;
|
||||
return props.deviceName;
|
||||
return device->PhysicalDevice.Properties.Properties.deviceName;
|
||||
}
|
||||
|
||||
void VulkanRenderDevice::SetVSync(bool vsync)
|
||||
|
@ -513,7 +497,7 @@ unsigned int VulkanRenderDevice::GetLightBufferBlockSize() const
|
|||
|
||||
void VulkanRenderDevice::PrintStartupLog()
|
||||
{
|
||||
const auto &props = device->PhysicalDevice.Properties;
|
||||
const auto &props = device->PhysicalDevice.Properties.Properties;
|
||||
|
||||
FString deviceType;
|
||||
switch (props.deviceType)
|
||||
|
@ -585,5 +569,5 @@ void VulkanRenderDevice::SetSceneRenderTarget(bool useSSAO)
|
|||
|
||||
bool VulkanRenderDevice::RaytracingEnabled()
|
||||
{
|
||||
return vk_raytrace && device->SupportsDeviceExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME);
|
||||
return vk_raytrace && device->SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME);
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ VkRenderBuffers::~VkRenderBuffers()
|
|||
|
||||
VkSampleCountFlagBits VkRenderBuffers::GetBestSampleCount()
|
||||
{
|
||||
const auto &limits = fb->device->PhysicalDevice.Properties.limits;
|
||||
const auto &limits = fb->device->PhysicalDevice.Properties.Properties.limits;
|
||||
VkSampleCountFlags deviceSampleCounts = limits.sampledImageColorSampleCounts & limits.sampledImageDepthSampleCounts & limits.sampledImageStencilSampleCounts;
|
||||
|
||||
int requestedSamples = clamp((int)gl_multisample, 0, 64);
|
||||
|
|
Loading…
Reference in a new issue