Renderer: Add support for device-enabled features (anisotropic filtering)
This commit is contained in:
parent
0411271851
commit
86097b331b
|
|
@ -119,12 +119,12 @@ namespace Nz
|
||||||
m_commands.emplace_back(EndDebugRegionData{});
|
m_commands.emplace_back(EndDebugRegionData{});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::size_t Nz::OpenGLCommandBuffer::GetBindingIndex() const
|
inline std::size_t OpenGLCommandBuffer::GetBindingIndex() const
|
||||||
{
|
{
|
||||||
return m_bindingIndex;
|
return m_bindingIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::size_t Nz::OpenGLCommandBuffer::GetPoolIndex() const
|
inline std::size_t OpenGLCommandBuffer::GetPoolIndex() const
|
||||||
{
|
{
|
||||||
return m_poolIndex;
|
return m_poolIndex;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace Nz
|
||||||
std::unique_ptr<RenderSurface> CreateRenderSurfaceImpl() override;
|
std::unique_ptr<RenderSurface> CreateRenderSurfaceImpl() override;
|
||||||
std::unique_ptr<RenderWindowImpl> CreateRenderWindowImpl(RenderWindow& owner) override;
|
std::unique_ptr<RenderWindowImpl> CreateRenderWindowImpl(RenderWindow& owner) override;
|
||||||
|
|
||||||
std::shared_ptr<RenderDevice> InstanciateRenderDevice(std::size_t deviceIndex) override;
|
std::shared_ptr<RenderDevice> InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures) override;
|
||||||
|
|
||||||
RenderAPI QueryAPI() const override;
|
RenderAPI QueryAPI() const override;
|
||||||
std::string QueryAPIString() const override;
|
std::string QueryAPIString() const override;
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,11 @@
|
||||||
|
|
||||||
namespace Nz
|
namespace Nz
|
||||||
{
|
{
|
||||||
|
struct RenderDeviceFeatures
|
||||||
|
{
|
||||||
|
bool anisotropicFiltering = false;
|
||||||
|
};
|
||||||
|
|
||||||
struct RenderDeviceLimits
|
struct RenderDeviceLimits
|
||||||
{
|
{
|
||||||
UInt64 minUniformBufferOffsetAlignment;
|
UInt64 minUniformBufferOffsetAlignment;
|
||||||
|
|
@ -20,6 +25,7 @@ namespace Nz
|
||||||
|
|
||||||
struct RenderDeviceInfo
|
struct RenderDeviceInfo
|
||||||
{
|
{
|
||||||
|
RenderDeviceFeatures features;
|
||||||
RenderDeviceLimits limits;
|
RenderDeviceLimits limits;
|
||||||
RenderDeviceType type;
|
RenderDeviceType type;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ namespace Nz
|
||||||
|
|
||||||
inline RendererImpl* GetRendererImpl();
|
inline RendererImpl* GetRendererImpl();
|
||||||
|
|
||||||
std::shared_ptr<RenderDevice> InstanciateRenderDevice(std::size_t deviceIndex);
|
std::shared_ptr<RenderDevice> InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures = {});
|
||||||
|
|
||||||
RenderAPI QueryAPI() const;
|
RenderAPI QueryAPI() const;
|
||||||
std::string QueryAPIString() const;
|
std::string QueryAPIString() const;
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ namespace Nz
|
||||||
virtual std::unique_ptr<RenderSurface> CreateRenderSurfaceImpl() = 0;
|
virtual std::unique_ptr<RenderSurface> CreateRenderSurfaceImpl() = 0;
|
||||||
virtual std::unique_ptr<RenderWindowImpl> CreateRenderWindowImpl(RenderWindow& owner) = 0;
|
virtual std::unique_ptr<RenderWindowImpl> CreateRenderWindowImpl(RenderWindow& owner) = 0;
|
||||||
|
|
||||||
virtual std::shared_ptr<RenderDevice> InstanciateRenderDevice(std::size_t deviceIndex) = 0;
|
virtual std::shared_ptr<RenderDevice> InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures) = 0;
|
||||||
|
|
||||||
virtual RenderAPI QueryAPI() const = 0;
|
virtual RenderAPI QueryAPI() const = 0;
|
||||||
virtual std::string QueryAPIString() const = 0;
|
virtual std::string QueryAPIString() const = 0;
|
||||||
|
|
|
||||||
|
|
@ -38,9 +38,9 @@ namespace Nz
|
||||||
|
|
||||||
static RenderDeviceInfo BuildRenderDeviceInfo(const Vk::PhysicalDevice& physDevice);
|
static RenderDeviceInfo BuildRenderDeviceInfo(const Vk::PhysicalDevice& physDevice);
|
||||||
|
|
||||||
static std::shared_ptr<VulkanDevice> CreateDevice(const Vk::PhysicalDevice& deviceInfo);
|
static std::shared_ptr<VulkanDevice> CreateDevice(const Vk::PhysicalDevice& deviceInfo, const RenderDeviceFeatures& enabledFeatures);
|
||||||
static std::shared_ptr<VulkanDevice> CreateDevice(const Vk::PhysicalDevice& deviceInfo, const Vk::Surface& surface, UInt32* graphicsFamilyIndex, UInt32* presentableFamilyIndex, UInt32* transferFamilyIndex);
|
static std::shared_ptr<VulkanDevice> CreateDevice(const Vk::PhysicalDevice& deviceInfo, const RenderDeviceFeatures& enabledFeatures, const Vk::Surface& surface, UInt32* graphicsFamilyIndex, UInt32* presentableFamilyIndex, UInt32* transferFamilyIndex);
|
||||||
static std::shared_ptr<VulkanDevice> CreateDevice(const Vk::PhysicalDevice& deviceInfo, const QueueFamily* queueFamilies, std::size_t queueFamilyCount);
|
static std::shared_ptr<VulkanDevice> CreateDevice(const Vk::PhysicalDevice& deviceInfo, const RenderDeviceFeatures& enabledFeatures, const QueueFamily* queueFamilies, std::size_t queueFamilyCount);
|
||||||
|
|
||||||
static Vk::Instance& GetInstance();
|
static Vk::Instance& GetInstance();
|
||||||
|
|
||||||
|
|
@ -51,13 +51,9 @@ namespace Nz
|
||||||
|
|
||||||
static bool IsInitialized();
|
static bool IsInitialized();
|
||||||
|
|
||||||
static std::shared_ptr<VulkanDevice> SelectDevice(const Vk::PhysicalDevice& deviceInfo);
|
|
||||||
static std::shared_ptr<VulkanDevice> SelectDevice(const Vk::PhysicalDevice& deviceInfo, const Vk::Surface& surface, UInt32* graphicsFamilyIndex, UInt32* presentableFamilyIndex, UInt32* transferFamilyIndex);
|
|
||||||
|
|
||||||
static void Uninitialize();
|
static void Uninitialize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::vector<std::shared_ptr<VulkanDevice>> s_devices;
|
|
||||||
static std::vector<Vk::PhysicalDevice> s_physDevices;
|
static std::vector<Vk::PhysicalDevice> s_physDevices;
|
||||||
static Vk::Instance s_instance;
|
static Vk::Instance s_instance;
|
||||||
static ParameterList s_initializationParameters;
|
static ParameterList s_initializationParameters;
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ namespace Nz
|
||||||
std::unique_ptr<RenderSurface> CreateRenderSurfaceImpl() override;
|
std::unique_ptr<RenderSurface> CreateRenderSurfaceImpl() override;
|
||||||
std::unique_ptr<RenderWindowImpl> CreateRenderWindowImpl(RenderWindow& owner) override;
|
std::unique_ptr<RenderWindowImpl> CreateRenderWindowImpl(RenderWindow& owner) override;
|
||||||
|
|
||||||
std::shared_ptr<RenderDevice> InstanciateRenderDevice(std::size_t deviceIndex) override;
|
std::shared_ptr<RenderDevice> InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures) override;
|
||||||
|
|
||||||
RenderAPI QueryAPI() const override;
|
RenderAPI QueryAPI() const override;
|
||||||
std::string QueryAPIString() const override;
|
std::string QueryAPIString() const override;
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,10 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_renderDevice = renderer->InstanciateRenderDevice(bestRenderDeviceIndex);
|
RenderDeviceFeatures enabledFeatures;
|
||||||
|
enabledFeatures.anisotropicFiltering = renderDeviceInfo[bestRenderDeviceIndex].features.anisotropicFiltering;
|
||||||
|
|
||||||
|
m_renderDevice = renderer->InstanciateRenderDevice(bestRenderDeviceIndex, enabledFeatures);
|
||||||
if (!m_renderDevice)
|
if (!m_renderDevice)
|
||||||
throw std::runtime_error("failed to instantiate render device");
|
throw std::runtime_error("failed to instantiate render device");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,14 @@ namespace Nz
|
||||||
|
|
||||||
m_deviceInfo.type = RenderDeviceType::Unknown;
|
m_deviceInfo.type = RenderDeviceType::Unknown;
|
||||||
|
|
||||||
|
const GL::ContextParams& params = m_referenceContext->GetParams();
|
||||||
|
unsigned int glVersion = params.glMajorVersion * 100 + params.glMinorVersion;
|
||||||
|
|
||||||
|
// Features
|
||||||
|
if ((params.type == GL::ContextType::OpenGL && glVersion >= 460) || m_referenceContext->IsExtensionSupported(GL::Extension::TextureFilterAnisotropic))
|
||||||
|
m_deviceInfo.features.anisotropicFiltering = true;
|
||||||
|
|
||||||
|
// Limits
|
||||||
GLint minUboOffsetAlignment;
|
GLint minUboOffsetAlignment;
|
||||||
m_referenceContext->glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &minUboOffsetAlignment);
|
m_referenceContext->glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &minUboOffsetAlignment);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -47,7 +47,7 @@ namespace Nz
|
||||||
return std::make_unique<OpenGLRenderWindow>(owner);
|
return std::make_unique<OpenGLRenderWindow>(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<RenderDevice> OpenGLRenderer::InstanciateRenderDevice(std::size_t deviceIndex)
|
std::shared_ptr<RenderDevice> OpenGLRenderer::InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& /*enabledFeatures*/)
|
||||||
{
|
{
|
||||||
assert(deviceIndex == 0);
|
assert(deviceIndex == 0);
|
||||||
return m_device;
|
return m_device;
|
||||||
|
|
|
||||||
|
|
@ -47,9 +47,9 @@ namespace Nz
|
||||||
m_rendererImpl.reset();
|
m_rendererImpl.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<RenderDevice> Renderer::InstanciateRenderDevice(std::size_t deviceIndex)
|
std::shared_ptr<RenderDevice> Renderer::InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures)
|
||||||
{
|
{
|
||||||
return m_rendererImpl->InstanciateRenderDevice(deviceIndex);
|
return m_rendererImpl->InstanciateRenderDevice(deviceIndex, enabledFeatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderAPI Renderer::QueryAPI() const
|
RenderAPI Renderer::QueryAPI() const
|
||||||
|
|
|
||||||
|
|
@ -105,22 +105,74 @@ namespace Nz
|
||||||
|
|
||||||
bool VkRenderWindow::Create(RendererImpl* /*renderer*/, RenderSurface* surface, const RenderWindowParameters& parameters)
|
bool VkRenderWindow::Create(RendererImpl* /*renderer*/, RenderSurface* surface, const RenderWindowParameters& parameters)
|
||||||
{
|
{
|
||||||
VulkanDevice& referenceDevice = static_cast<VulkanDevice&>(*m_owner.GetRenderDevice());
|
std::shared_ptr<VulkanDevice> device = std::static_pointer_cast<VulkanDevice>(m_owner.GetRenderDevice());
|
||||||
|
|
||||||
const auto& physDeviceInfo = referenceDevice.GetPhysicalDeviceInfo();
|
const auto& physDeviceInfo = device->GetPhysicalDeviceInfo();
|
||||||
|
|
||||||
Vk::Surface& vulkanSurface = static_cast<VulkanSurface*>(surface)->GetSurface();
|
Vk::Surface& vulkanSurface = static_cast<VulkanSurface*>(surface)->GetSurface();
|
||||||
|
|
||||||
UInt32 graphicsFamilyQueueIndex;
|
const std::vector<Vk::Device::QueueFamilyInfo>& queueFamilyInfo = device->GetEnabledQueues();
|
||||||
UInt32 presentableFamilyQueueIndex;
|
UInt32 graphicsFamilyQueueIndex = UINT32_MAX;
|
||||||
UInt32 transferFamilyQueueIndex;
|
UInt32 presentableFamilyQueueIndex = UINT32_MAX;
|
||||||
m_device = Vulkan::SelectDevice(physDeviceInfo, vulkanSurface, &graphicsFamilyQueueIndex, &presentableFamilyQueueIndex, &transferFamilyQueueIndex);
|
|
||||||
if (!m_device)
|
for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo)
|
||||||
{
|
{
|
||||||
NazaraError("Failed to get compatible Vulkan device");
|
bool supported = false;
|
||||||
|
if (vulkanSurface.GetSupportPresentation(physDeviceInfo.physDevice, queueInfo.familyIndex, &supported) && supported)
|
||||||
|
{
|
||||||
|
if (presentableFamilyQueueIndex == UINT32_MAX || queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
|
||||||
|
{
|
||||||
|
presentableFamilyQueueIndex = queueInfo.familyIndex;
|
||||||
|
if (queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
|
||||||
|
{
|
||||||
|
graphicsFamilyQueueIndex = queueInfo.familyIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (presentableFamilyQueueIndex == UINT32_MAX)
|
||||||
|
{
|
||||||
|
NazaraError("device doesn't support presenting to this surface");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (graphicsFamilyQueueIndex == UINT32_MAX)
|
||||||
|
{
|
||||||
|
for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo)
|
||||||
|
{
|
||||||
|
if (queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
|
||||||
|
{
|
||||||
|
graphicsFamilyQueueIndex = queueInfo.familyIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (graphicsFamilyQueueIndex == UINT32_MAX)
|
||||||
|
{
|
||||||
|
NazaraError("device doesn't support graphics operations");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UInt32 transferFamilyQueueIndex = UINT32_MAX;
|
||||||
|
// Search for a transfer queue (first one being different to the graphics one)
|
||||||
|
for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo)
|
||||||
|
{
|
||||||
|
// Transfer bit is not mandatory if compute and graphics bits are set (as they implicitly support transfer)
|
||||||
|
if (queueInfo.flags & (VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT))
|
||||||
|
{
|
||||||
|
transferFamilyQueueIndex = queueInfo.familyIndex;
|
||||||
|
if (transferFamilyQueueIndex != graphicsFamilyQueueIndex)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(transferFamilyQueueIndex != UINT32_MAX);
|
||||||
|
|
||||||
|
m_device = std::move(device);
|
||||||
|
|
||||||
m_graphicsQueue = m_device->GetQueue(graphicsFamilyQueueIndex, 0);
|
m_graphicsQueue = m_device->GetQueue(graphicsFamilyQueueIndex, 0);
|
||||||
m_presentQueue = m_device->GetQueue(presentableFamilyQueueIndex, 0);
|
m_presentQueue = m_device->GetQueue(presentableFamilyQueueIndex, 0);
|
||||||
m_transferQueue = m_device->GetQueue(transferFamilyQueueIndex, 0);
|
m_transferQueue = m_device->GetQueue(transferFamilyQueueIndex, 0);
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,8 @@ namespace Nz
|
||||||
RenderDeviceInfo deviceInfo;
|
RenderDeviceInfo deviceInfo;
|
||||||
deviceInfo.name = physDevice.properties.deviceName;
|
deviceInfo.name = physDevice.properties.deviceName;
|
||||||
|
|
||||||
|
deviceInfo.features.anisotropicFiltering = physDevice.features.samplerAnisotropy;
|
||||||
|
|
||||||
deviceInfo.limits.minUniformBufferOffsetAlignment = physDevice.properties.limits.minUniformBufferOffsetAlignment;
|
deviceInfo.limits.minUniformBufferOffsetAlignment = physDevice.properties.limits.minUniformBufferOffsetAlignment;
|
||||||
|
|
||||||
switch (physDevice.properties.deviceType)
|
switch (physDevice.properties.deviceType)
|
||||||
|
|
@ -370,7 +372,7 @@ namespace Nz
|
||||||
return s_instance.IsValid();
|
return s_instance.IsValid();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo)
|
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo, const RenderDeviceFeatures& enabledFeatures)
|
||||||
{
|
{
|
||||||
Nz::ErrorFlags errFlags(ErrorMode::ThrowException, true);
|
Nz::ErrorFlags errFlags(ErrorMode::ThrowException, true);
|
||||||
|
|
||||||
|
|
@ -404,10 +406,10 @@ namespace Nz
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return CreateDevice(deviceInfo, queuesFamilies.data(), queuesFamilies.size());
|
return CreateDevice(deviceInfo, enabledFeatures, queuesFamilies.data(), queuesFamilies.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo, const Vk::Surface& surface, UInt32* graphicsFamilyIndex, UInt32* presentableFamilyIndex, UInt32* transferFamilyIndex)
|
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo, const RenderDeviceFeatures& enabledFeatures, const Vk::Surface& surface, UInt32* graphicsFamilyIndex, UInt32* presentableFamilyIndex, UInt32* transferFamilyIndex)
|
||||||
{
|
{
|
||||||
Nz::ErrorFlags errFlags(ErrorMode::ThrowException, true);
|
Nz::ErrorFlags errFlags(ErrorMode::ThrowException, true);
|
||||||
|
|
||||||
|
|
@ -476,10 +478,10 @@ namespace Nz
|
||||||
*presentableFamilyIndex = presentQueueNodeIndex;
|
*presentableFamilyIndex = presentQueueNodeIndex;
|
||||||
*transferFamilyIndex = transferQueueNodeFamily;
|
*transferFamilyIndex = transferQueueNodeFamily;
|
||||||
|
|
||||||
return CreateDevice(deviceInfo, queuesFamilies.data(), queuesFamilies.size());
|
return CreateDevice(deviceInfo, enabledFeatures, queuesFamilies.data(), queuesFamilies.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo, const QueueFamily* queueFamilies, std::size_t queueFamilyCount)
|
std::shared_ptr<VulkanDevice> Vulkan::CreateDevice(const Vk::PhysicalDevice& deviceInfo, const RenderDeviceFeatures& enabledFeatures, const QueueFamily* queueFamilies, std::size_t queueFamilyCount)
|
||||||
{
|
{
|
||||||
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
|
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
|
||||||
queueCreateInfos.reserve(queueFamilyCount);
|
queueCreateInfos.reserve(queueFamilyCount);
|
||||||
|
|
@ -571,6 +573,10 @@ namespace Nz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VkPhysicalDeviceFeatures deviceFeatures = {};
|
||||||
|
if (enabledFeatures.anisotropicFiltering)
|
||||||
|
deviceFeatures.samplerAnisotropy = VK_TRUE;
|
||||||
|
|
||||||
VkDeviceCreateInfo createInfo = {
|
VkDeviceCreateInfo createInfo = {
|
||||||
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
|
||||||
nullptr,
|
nullptr,
|
||||||
|
|
@ -581,7 +587,7 @@ namespace Nz
|
||||||
enabledLayers.data(),
|
enabledLayers.data(),
|
||||||
UInt32(enabledExtensions.size()),
|
UInt32(enabledExtensions.size()),
|
||||||
enabledExtensions.data(),
|
enabledExtensions.data(),
|
||||||
nullptr
|
&deviceFeatures
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<VulkanDevice> device = std::make_shared<VulkanDevice>(s_instance, BuildRenderDeviceInfo(deviceInfo));
|
std::shared_ptr<VulkanDevice> device = std::make_shared<VulkanDevice>(s_instance, BuildRenderDeviceInfo(deviceInfo));
|
||||||
|
|
@ -591,104 +597,17 @@ namespace Nz
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
s_devices.emplace_back(device);
|
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<VulkanDevice> Vulkan::SelectDevice(const Vk::PhysicalDevice& deviceInfo)
|
|
||||||
{
|
|
||||||
for (auto it = s_devices.begin(); it != s_devices.end();)
|
|
||||||
{
|
|
||||||
const auto& devicePtr = *it;
|
|
||||||
if (devicePtr->GetPhysicalDevice() == deviceInfo.physDevice)
|
|
||||||
return devicePtr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CreateDevice(deviceInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<VulkanDevice> Vulkan::SelectDevice(const Vk::PhysicalDevice& deviceInfo, const Vk::Surface& surface, UInt32* graphicsFamilyIndex, UInt32* presentableFamilyIndex, UInt32* transferFamilyIndex)
|
|
||||||
{
|
|
||||||
// First, try to find a device compatible with that surface
|
|
||||||
for (auto it = s_devices.begin(); it != s_devices.end();)
|
|
||||||
{
|
|
||||||
const auto& devicePtr = *it;
|
|
||||||
if (devicePtr->GetPhysicalDevice() == deviceInfo.physDevice)
|
|
||||||
{
|
|
||||||
const std::vector<Vk::Device::QueueFamilyInfo>& queueFamilyInfo = devicePtr->GetEnabledQueues();
|
|
||||||
UInt32 graphicsQueueFamilyIndex = UINT32_MAX;
|
|
||||||
UInt32 presentableQueueFamilyIndex = UINT32_MAX;
|
|
||||||
for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo)
|
|
||||||
{
|
|
||||||
bool supported = false;
|
|
||||||
if (surface.GetSupportPresentation(deviceInfo.physDevice, queueInfo.familyIndex, &supported) && supported)
|
|
||||||
{
|
|
||||||
if (presentableQueueFamilyIndex == UINT32_MAX || queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
|
|
||||||
{
|
|
||||||
presentableQueueFamilyIndex = queueInfo.familyIndex;
|
|
||||||
if (queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
|
|
||||||
{
|
|
||||||
*graphicsFamilyIndex = queueInfo.familyIndex;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (graphicsQueueFamilyIndex == UINT32_MAX)
|
|
||||||
{
|
|
||||||
for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo)
|
|
||||||
{
|
|
||||||
if (queueInfo.flags & VK_QUEUE_GRAPHICS_BIT)
|
|
||||||
{
|
|
||||||
*graphicsFamilyIndex = queueInfo.familyIndex;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (presentableQueueFamilyIndex != UINT32_MAX)
|
|
||||||
{
|
|
||||||
*presentableFamilyIndex = presentableQueueFamilyIndex;
|
|
||||||
|
|
||||||
UInt32 transferQueueNodeFamily = UINT32_MAX;
|
|
||||||
// Search for a transfer queue (first one being different to the graphics one)
|
|
||||||
for (const Vk::Device::QueueFamilyInfo& queueInfo : queueFamilyInfo)
|
|
||||||
{
|
|
||||||
// Transfer bit is not mandatory if compute and graphics bits are set (as they implicitly support transfer)
|
|
||||||
if (queueInfo.flags & (VK_QUEUE_COMPUTE_BIT | VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT))
|
|
||||||
{
|
|
||||||
transferQueueNodeFamily = queueInfo.familyIndex;
|
|
||||||
if (transferQueueNodeFamily != *graphicsFamilyIndex)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(transferQueueNodeFamily != UINT32_MAX);
|
|
||||||
|
|
||||||
*transferFamilyIndex = transferQueueNodeFamily;
|
|
||||||
|
|
||||||
return devicePtr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No device had support for that surface, create one
|
|
||||||
return CreateDevice(deviceInfo, surface, graphicsFamilyIndex, presentableFamilyIndex, transferFamilyIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Vulkan::Uninitialize()
|
void Vulkan::Uninitialize()
|
||||||
{
|
{
|
||||||
// Uninitialize module here
|
// Uninitialize module here
|
||||||
s_devices.clear();
|
|
||||||
s_instance.Destroy();
|
s_instance.Destroy();
|
||||||
|
|
||||||
Vk::Loader::Uninitialize();
|
Vk::Loader::Uninitialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::shared_ptr<VulkanDevice>> Vulkan::s_devices;
|
|
||||||
std::vector<Vk::PhysicalDevice> Vulkan::s_physDevices;
|
std::vector<Vk::PhysicalDevice> Vulkan::s_physDevices;
|
||||||
Vk::Instance Vulkan::s_instance;
|
Vk::Instance Vulkan::s_instance;
|
||||||
ParameterList Vulkan::s_initializationParameters;
|
ParameterList Vulkan::s_initializationParameters;
|
||||||
|
|
|
||||||
|
|
@ -30,12 +30,12 @@ namespace Nz
|
||||||
return std::make_unique<VkRenderWindow>(owner);
|
return std::make_unique<VkRenderWindow>(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<RenderDevice> VulkanRenderer::InstanciateRenderDevice(std::size_t deviceIndex)
|
std::shared_ptr<RenderDevice> VulkanRenderer::InstanciateRenderDevice(std::size_t deviceIndex, const RenderDeviceFeatures& enabledFeatures)
|
||||||
{
|
{
|
||||||
const auto& physDevices = Vulkan::GetPhysicalDevices();
|
const auto& physDevices = Vulkan::GetPhysicalDevices();
|
||||||
|
|
||||||
assert(deviceIndex < physDevices.size());
|
assert(deviceIndex < physDevices.size());
|
||||||
return Vulkan::SelectDevice(physDevices[deviceIndex]);
|
return Vulkan::CreateDevice(physDevices[deviceIndex], enabledFeatures);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VulkanRenderer::Prepare(const ParameterList& parameters)
|
bool VulkanRenderer::Prepare(const ParameterList& parameters)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue