Graphics device
Bigfoot / Sonarqube (game) (push) Skipped
Bigfoot / Sonarqube (toolmode) (push) Skipped
Bigfoot / Build & Test Debug with clang_asan (Unity Build: OFF, Variant: game) (push) Failing after 2m13s
Bigfoot / Build & Test Debug with clang_asan (Unity Build: OFF, Variant: toolmode) (push) Failing after 2m16s
Bigfoot / Build & Test Debug with clang_asan (Unity Build: ON, Variant: toolmode) (push) Failing after 1m52s
Bigfoot / Build & Test Debug with clang (Unity Build: OFF, Variant: game) (push) Successful in 1m3s
Bigfoot / Build & Test Debug with clang (Unity Build: OFF, Variant: toolmode) (push) Successful in 1m10s
Bigfoot / Build & Test Debug with clang (Unity Build: ON, Variant: game) (push) Successful in 40s
Bigfoot / Build & Test Debug with clang (Unity Build: ON, Variant: toolmode) (push) Successful in 45s
Bigfoot / Build & Test Debug with clang_asan (Unity Build: ON, Variant: game) (push) Failing after 1m42s
Bigfoot / Build & Test Release with clang (Unity Build: OFF, Variant: game) (push) Successful in 1m3s
Bigfoot / Build & Test Release with clang (Unity Build: OFF, Variant: toolmode) (push) Successful in 1m25s
Bigfoot / Build & Test Release with clang_asan (Unity Build: OFF, Variant: toolmode) (push) Failing after 1m47s
Bigfoot / Build & Test Release with clang (Unity Build: ON, Variant: game) (push) Successful in 50s
Bigfoot / Build & Test Release with clang (Unity Build: ON, Variant: toolmode) (push) Successful in 1m10s
Bigfoot / Build & Test Release with clang_asan (Unity Build: OFF, Variant: game) (push) Failing after 1m41s
Bigfoot / Build & Test Release with clang_asan (Unity Build: ON, Variant: toolmode) (push) Failing after 1m36s
Bigfoot / Build & Test RelWithDebInfo with clang (Unity Build: OFF, Variant: game) (push) Successful in 1m13s
Bigfoot / Build & Test RelWithDebInfo with clang (Unity Build: ON, Variant: toolmode) (push) Successful in 49s
Bigfoot / Build & Test RelWithDebInfo with clang_asan (Unity Build: OFF, Variant: toolmode) (push) Failing after 2m18s
Bigfoot / Build & Test RelWithDebInfo with clang_asan (Unity Build: ON, Variant: game) (push) Failing after 1m42s
Bigfoot / Build & Test RelWithDebInfo with clang_asan (Unity Build: ON, Variant: toolmode) (push) Failing after 1m50s
Bigfoot / Build & Test Release with clang_asan (Unity Build: ON, Variant: game) (push) Failing after 1m30s
Bigfoot / Build & Test RelWithDebInfo with clang (Unity Build: OFF, Variant: toolmode) (push) Successful in 1m15s
Bigfoot / Build & Test RelWithDebInfo with clang (Unity Build: ON, Variant: game) (push) Successful in 48s
Bigfoot / Build & Test RelWithDebInfo with clang_asan (Unity Build: OFF, Variant: game) (push) Failing after 2m20s
Bigfoot / Clang Format Checks (push) Successful in 10s
Bigfoot / Sonarqube (game) (push) Skipped
Bigfoot / Sonarqube (toolmode) (push) Skipped
Bigfoot / Build & Test Debug with clang_asan (Unity Build: OFF, Variant: game) (push) Failing after 2m13s
Bigfoot / Build & Test Debug with clang_asan (Unity Build: OFF, Variant: toolmode) (push) Failing after 2m16s
Bigfoot / Build & Test Debug with clang_asan (Unity Build: ON, Variant: toolmode) (push) Failing after 1m52s
Bigfoot / Build & Test Debug with clang (Unity Build: OFF, Variant: game) (push) Successful in 1m3s
Bigfoot / Build & Test Debug with clang (Unity Build: OFF, Variant: toolmode) (push) Successful in 1m10s
Bigfoot / Build & Test Debug with clang (Unity Build: ON, Variant: game) (push) Successful in 40s
Bigfoot / Build & Test Debug with clang (Unity Build: ON, Variant: toolmode) (push) Successful in 45s
Bigfoot / Build & Test Debug with clang_asan (Unity Build: ON, Variant: game) (push) Failing after 1m42s
Bigfoot / Build & Test Release with clang (Unity Build: OFF, Variant: game) (push) Successful in 1m3s
Bigfoot / Build & Test Release with clang (Unity Build: OFF, Variant: toolmode) (push) Successful in 1m25s
Bigfoot / Build & Test Release with clang_asan (Unity Build: OFF, Variant: toolmode) (push) Failing after 1m47s
Bigfoot / Build & Test Release with clang (Unity Build: ON, Variant: game) (push) Successful in 50s
Bigfoot / Build & Test Release with clang (Unity Build: ON, Variant: toolmode) (push) Successful in 1m10s
Bigfoot / Build & Test Release with clang_asan (Unity Build: OFF, Variant: game) (push) Failing after 1m41s
Bigfoot / Build & Test Release with clang_asan (Unity Build: ON, Variant: toolmode) (push) Failing after 1m36s
Bigfoot / Build & Test RelWithDebInfo with clang (Unity Build: OFF, Variant: game) (push) Successful in 1m13s
Bigfoot / Build & Test RelWithDebInfo with clang (Unity Build: ON, Variant: toolmode) (push) Successful in 49s
Bigfoot / Build & Test RelWithDebInfo with clang_asan (Unity Build: OFF, Variant: toolmode) (push) Failing after 2m18s
Bigfoot / Build & Test RelWithDebInfo with clang_asan (Unity Build: ON, Variant: game) (push) Failing after 1m42s
Bigfoot / Build & Test RelWithDebInfo with clang_asan (Unity Build: ON, Variant: toolmode) (push) Failing after 1m50s
Bigfoot / Build & Test Release with clang_asan (Unity Build: ON, Variant: game) (push) Failing after 1m30s
Bigfoot / Build & Test RelWithDebInfo with clang (Unity Build: OFF, Variant: toolmode) (push) Successful in 1m15s
Bigfoot / Build & Test RelWithDebInfo with clang (Unity Build: ON, Variant: game) (push) Successful in 48s
Bigfoot / Build & Test RelWithDebInfo with clang_asan (Unity Build: OFF, Variant: game) (push) Failing after 2m20s
Bigfoot / Clang Format Checks (push) Successful in 10s
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
/*********************************************************************
|
||||
* \file GraphicsContext.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date September 2026
|
||||
*********************************************************************/
|
||||
#include <GraphicsCore/GraphicsContext.hpp>
|
||||
|
||||
#include <GraphicsCore/GraphicsCoreAssertHandler.hpp>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
GraphicsContext::GraphicsContext(const GraphicsContextCreateInfo& p_createInfo)
|
||||
{
|
||||
m_instance = g_graphicsInstanceFactory->Create(p_createInfo.m_api,
|
||||
p_createInfo.m_applicationName,
|
||||
p_createInfo.m_applicationVersion);
|
||||
CRITICAL_ASSERT(GraphicsCoreAssertHandler,
|
||||
m_instance != nullptr,
|
||||
"No graphics instance registered for GraphicsAPI '{}'",
|
||||
EnumNameGraphicsAPI(p_createInfo.m_api));
|
||||
|
||||
m_surface = g_graphicsSurfaceFactory->Create(p_createInfo.m_api, *m_instance, p_createInfo.m_surfaceCreateInfo);
|
||||
CRITICAL_ASSERT(GraphicsCoreAssertHandler,
|
||||
m_surface != nullptr,
|
||||
"No graphics surface registered for GraphicsAPI '{}'",
|
||||
EnumNameGraphicsAPI(p_createInfo.m_api));
|
||||
|
||||
const DeviceCreateInfo deviceCreateInfo {p_createInfo.m_deviceNameHint, m_surface.get()};
|
||||
m_device = g_graphicsDeviceFactory->Create(p_createInfo.m_api, *m_instance, deviceCreateInfo);
|
||||
CRITICAL_ASSERT(GraphicsCoreAssertHandler,
|
||||
m_device != nullptr,
|
||||
"No graphics device registered for GraphicsAPI '{}'",
|
||||
EnumNameGraphicsAPI(p_createInfo.m_api));
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
GraphicsInstance& GraphicsContext::GetInstance() const
|
||||
{
|
||||
return *m_instance;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
GraphicsSurface& GraphicsContext::GetSurface() const
|
||||
{
|
||||
return *m_surface;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
GraphicsDevice& GraphicsContext::GetDevice() const
|
||||
{
|
||||
return *m_device;
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
@@ -0,0 +1,108 @@
|
||||
/*********************************************************************
|
||||
* \file GraphicsContext.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date September 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_GRAPHICSCORE_GRAPHICSCONTEXT_HPP
|
||||
#define BIGFOOT_GRAPHICSCORE_GRAPHICSCONTEXT_HPP
|
||||
#include <GraphicsInterface/GraphicsDevice.hpp>
|
||||
#include <GraphicsInterface/GraphicsInstance.hpp>
|
||||
#include <GraphicsInterface/GraphicsSurface.hpp>
|
||||
|
||||
#include <Utils/Version.hpp>
|
||||
|
||||
#include <GraphicsInterface/GraphicsAPI_generated.hpp>
|
||||
|
||||
#include <EASTL/string_view.h>
|
||||
#include <EASTL/unique_ptr.h>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
struct GraphicsContextCreateInfo
|
||||
{
|
||||
/**
|
||||
* The graphics API to use
|
||||
*/
|
||||
GraphicsAPI m_api = GraphicsAPI::Vulkan;
|
||||
|
||||
/**
|
||||
* The name of the application
|
||||
*/
|
||||
eastl::string_view m_applicationName;
|
||||
|
||||
/**
|
||||
* The version of the application
|
||||
*/
|
||||
Version m_applicationVersion;
|
||||
|
||||
/**
|
||||
* The native window handles
|
||||
*/
|
||||
SurfaceCreateInfo m_surfaceCreateInfo;
|
||||
|
||||
/**
|
||||
* Pick a specific physical device by name.
|
||||
*/
|
||||
eastl::string_view m_deviceNameHint;
|
||||
};
|
||||
|
||||
class GraphicsContext
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* \param p_createInfo The create info
|
||||
*/
|
||||
explicit GraphicsContext(const GraphicsContextCreateInfo& p_createInfo);
|
||||
|
||||
GraphicsContext(const GraphicsContext& p_context) = delete;
|
||||
GraphicsContext(GraphicsContext&& p_context) = delete;
|
||||
|
||||
GraphicsContext& operator=(const GraphicsContext& p_context) = delete;
|
||||
GraphicsContext& operator=(GraphicsContext&& p_context) = delete;
|
||||
|
||||
/**
|
||||
* Get the graphics instance
|
||||
*
|
||||
* \return The graphics instance
|
||||
*/
|
||||
[[nodiscard]]
|
||||
GraphicsInstance& GetInstance() const;
|
||||
|
||||
/**
|
||||
* Get the graphics surface
|
||||
*
|
||||
* \return The graphics surface
|
||||
*/
|
||||
[[nodiscard]]
|
||||
GraphicsSurface& GetSurface() const;
|
||||
|
||||
/**
|
||||
* Get the graphics device
|
||||
*
|
||||
* \return The graphics device
|
||||
*/
|
||||
[[nodiscard]]
|
||||
GraphicsDevice& GetDevice() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* The graphics instance.
|
||||
*/
|
||||
eastl::unique_ptr<GraphicsInstance> m_instance;
|
||||
|
||||
/**
|
||||
* The graphics surface.
|
||||
*/
|
||||
eastl::unique_ptr<GraphicsSurface> m_surface;
|
||||
|
||||
/**
|
||||
* The graphics device.
|
||||
*/
|
||||
eastl::unique_ptr<GraphicsDevice> m_device;
|
||||
};
|
||||
} // namespace Bigfoot
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
/*********************************************************************
|
||||
* \file GraphicsDevice.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date September 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_GRAPHICSINTERFACE_GRAPHICSDEVICE_HPP
|
||||
#define BIGFOOT_GRAPHICSINTERFACE_GRAPHICSDEVICE_HPP
|
||||
#include <GraphicsInterface/GraphicsInstance.hpp>
|
||||
#include <GraphicsInterface/GraphicsQueue.hpp>
|
||||
#include <GraphicsInterface/GraphicsSurface.hpp>
|
||||
|
||||
#include <Utils/Factory.hpp>
|
||||
#include <Utils/LazyGlobal.hpp>
|
||||
|
||||
#include <GraphicsInterface/GraphicsAPI_generated.hpp>
|
||||
|
||||
#include <EASTL/functional.h>
|
||||
#include <EASTL/string_view.h>
|
||||
#include <EASTL/unique_ptr.h>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
|
||||
struct DeviceCreateInfo
|
||||
{
|
||||
/**
|
||||
* When empty, the most suitable discrete GPU is preferred.
|
||||
*/
|
||||
eastl::string_view m_deviceNameHint;
|
||||
|
||||
/**
|
||||
* The surface the device must be able to present to.
|
||||
*/
|
||||
const GraphicsSurface* m_surface = nullptr;
|
||||
};
|
||||
|
||||
class GraphicsDevice
|
||||
{
|
||||
public:
|
||||
virtual ~GraphicsDevice() = default;
|
||||
|
||||
/**
|
||||
* Get a queue of the given type
|
||||
*
|
||||
* \param p_type The kind of work the queue should support
|
||||
* \return The queue, or nullptr if the device has no queue of this type
|
||||
*/
|
||||
[[nodiscard]]
|
||||
virtual const GraphicsQueue* GetQueue(GraphicsQueueType p_type) const = 0;
|
||||
|
||||
GraphicsDevice(const GraphicsDevice& p_device) = delete;
|
||||
GraphicsDevice(GraphicsDevice&& p_device) = delete;
|
||||
|
||||
GraphicsDevice& operator=(const GraphicsDevice& p_device) = delete;
|
||||
GraphicsDevice& operator=(GraphicsDevice&& p_device) = delete;
|
||||
|
||||
protected:
|
||||
GraphicsDevice() = default;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
using GraphicsDeviceFactory =
|
||||
Factory<GraphicsDevice,
|
||||
GraphicsAPI,
|
||||
eastl::function<eastl::unique_ptr<GraphicsDevice>(const GraphicsInstance&, const DeviceCreateInfo&)>>;
|
||||
|
||||
/**
|
||||
* The global factory graphics libraries register themselves into, keyed by GraphicsAPI
|
||||
*/
|
||||
inline LazyGlobal<GraphicsDeviceFactory> g_graphicsDeviceFactory;
|
||||
} // namespace Bigfoot
|
||||
|
||||
#endif
|
||||
@@ -7,6 +7,7 @@
|
||||
#ifndef BIGFOOT_GRAPHICSINTERFACE_GRAPHICSINSTANCE_HPP
|
||||
#define BIGFOOT_GRAPHICSINTERFACE_GRAPHICSINSTANCE_HPP
|
||||
#include <Utils/Factory.hpp>
|
||||
#include <Utils/LazyGlobal.hpp>
|
||||
#include <Utils/Version.hpp>
|
||||
|
||||
#include <GraphicsInterface/GraphicsAPI_generated.hpp>
|
||||
@@ -38,6 +39,10 @@ using GraphicsInstanceFactory =
|
||||
Factory<GraphicsInstance,
|
||||
GraphicsAPI,
|
||||
eastl::function<eastl::unique_ptr<GraphicsInstance>(eastl::string_view, Version)>>;
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
inline LazyGlobal<GraphicsInstanceFactory> g_graphicsInstanceFactory;
|
||||
} // namespace Bigfoot
|
||||
|
||||
#endif
|
||||
|
||||
+1
-11
@@ -6,20 +6,10 @@
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_GRAPHICSINTERFACE_GRAPHICSQUEUE_HPP
|
||||
#define BIGFOOT_GRAPHICSINTERFACE_GRAPHICSQUEUE_HPP
|
||||
#include <GraphicsInterface/GraphicsQueueType_generated.hpp>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
/**
|
||||
* The kind of work a GraphicsQueue submit
|
||||
*/
|
||||
enum class GraphicsQueueType
|
||||
{
|
||||
Graphics,
|
||||
Compute,
|
||||
Transfer,
|
||||
Present
|
||||
};
|
||||
|
||||
class GraphicsQueue
|
||||
{
|
||||
public:
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
namespace Bigfoot;
|
||||
|
||||
enum GraphicsQueueType: byte
|
||||
{
|
||||
Graphics,
|
||||
Compute,
|
||||
Transfer,
|
||||
Present
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
|
||||
#ifndef FLATBUFFERS_GENERATED_GRAPHICSQUEUETYPE_BIGFOOT_H_
|
||||
#define FLATBUFFERS_GENERATED_GRAPHICSQUEUETYPE_BIGFOOT_H_
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
|
||||
// Ensure the included flatbuffers.h is the same version as when this file was
|
||||
// generated, otherwise it may not be compatible.
|
||||
static_assert(FLATBUFFERS_VERSION_MAJOR == 25 &&
|
||||
FLATBUFFERS_VERSION_MINOR == 12 &&
|
||||
FLATBUFFERS_VERSION_REVISION == 19,
|
||||
"Non-compatible flatbuffers version included");
|
||||
// Ensure the included flatbuffers.h is Bigfoot's fork - stock
|
||||
// flatbuffers (or a differently versioned Bigfoot fork) is not compatible.
|
||||
#ifndef FLATBUFFERS_BIGFOOT_VERSION
|
||||
#error "This file requires Bigfoot's flatbuffers fork - stock flatbuffers is not compatible"
|
||||
#endif
|
||||
static_assert(FLATBUFFERS_BIGFOOT_VERSION == 1,
|
||||
"Non-compatible Bigfoot flatbuffers fork version included");
|
||||
|
||||
#include "EASTL/unique_ptr.h"
|
||||
#include "EASTL/string.h"
|
||||
#include "EASTL/vector.h"
|
||||
|
||||
namespace Bigfoot {
|
||||
|
||||
enum class GraphicsQueueType : int8_t {
|
||||
Graphics = 0,
|
||||
Compute = 1,
|
||||
Transfer = 2,
|
||||
Present = 3,
|
||||
MIN = Graphics,
|
||||
MAX = Present
|
||||
};
|
||||
|
||||
inline const GraphicsQueueType (&EnumValuesGraphicsQueueType())[4] {
|
||||
static const GraphicsQueueType values[] = {
|
||||
GraphicsQueueType::Graphics,
|
||||
GraphicsQueueType::Compute,
|
||||
GraphicsQueueType::Transfer,
|
||||
GraphicsQueueType::Present
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
inline const char * const *EnumNamesGraphicsQueueType() {
|
||||
static const char * const names[5] = {
|
||||
"Graphics",
|
||||
"Compute",
|
||||
"Transfer",
|
||||
"Present",
|
||||
nullptr
|
||||
};
|
||||
return names;
|
||||
}
|
||||
|
||||
inline const char *EnumNameGraphicsQueueType(GraphicsQueueType e) {
|
||||
if (::flatbuffers::IsOutRange(e, GraphicsQueueType::Graphics, GraphicsQueueType::Present)) return "";
|
||||
const size_t index = static_cast<size_t>(e);
|
||||
return EnumNamesGraphicsQueueType()[index];
|
||||
}
|
||||
|
||||
inline const ::flatbuffers::TypeTable *GraphicsQueueTypeTypeTable() {
|
||||
static const ::flatbuffers::TypeCode type_codes[] = {
|
||||
{ ::flatbuffers::ET_CHAR, 0, 0 },
|
||||
{ ::flatbuffers::ET_CHAR, 0, 0 },
|
||||
{ ::flatbuffers::ET_CHAR, 0, 0 },
|
||||
{ ::flatbuffers::ET_CHAR, 0, 0 }
|
||||
};
|
||||
static const ::flatbuffers::TypeFunction type_refs[] = {
|
||||
Bigfoot::GraphicsQueueTypeTypeTable
|
||||
};
|
||||
static const ::flatbuffers::TypeTable tt = {
|
||||
::flatbuffers::ST_ENUM, 4, type_codes, type_refs, nullptr, nullptr, nullptr
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
|
||||
} // namespace Bigfoot
|
||||
|
||||
#endif // FLATBUFFERS_GENERATED_GRAPHICSQUEUETYPE_BIGFOOT_H_
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <GraphicsInterface/GraphicsInstance.hpp>
|
||||
|
||||
#include <Utils/Factory.hpp>
|
||||
#include <Utils/LazyGlobal.hpp>
|
||||
#include <Utils/TargetMacros.h>
|
||||
|
||||
#include <GraphicsInterface/GraphicsAPI_generated.hpp>
|
||||
@@ -60,6 +61,10 @@ using GraphicsSurfaceFactory =
|
||||
Factory<GraphicsSurface,
|
||||
GraphicsAPI,
|
||||
eastl::function<eastl::unique_ptr<GraphicsSurface>(const GraphicsInstance&, const SurfaceCreateInfo&)>>;
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
inline LazyGlobal<GraphicsSurfaceFactory> g_graphicsSurfaceFactory;
|
||||
} // namespace Bigfoot
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*********************************************************************
|
||||
* \file VulkanDevice.hpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date September 2026
|
||||
*********************************************************************/
|
||||
#ifndef BIGFOOT_GRAPHICSVULKAN_VULKANDEVICE_HPP
|
||||
#define BIGFOOT_GRAPHICSVULKAN_VULKANDEVICE_HPP
|
||||
#include <GraphicsVulkan/VulkanInclude.hpp>
|
||||
#include <GraphicsVulkan/VulkanInstance.hpp>
|
||||
#include <GraphicsVulkan/VulkanQueue.hpp>
|
||||
#include <GraphicsVulkan/VulkanSurface.hpp>
|
||||
|
||||
#include <GraphicsInterface/GraphicsDevice.hpp>
|
||||
|
||||
#include <EASTL/array.h>
|
||||
#include <EASTL/optional.h>
|
||||
#include <EASTL/string_view.h>
|
||||
|
||||
namespace Bigfoot::Vulkan
|
||||
{
|
||||
class VulkanDevice final: public GraphicsDevice
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* \param p_instance The instance to create the device from
|
||||
* \param p_surface The surface the device must be able to present to. Can be null to create a device with no
|
||||
* present queue
|
||||
* \param p_deviceNameHint Pick a specific physical device by name.
|
||||
*/
|
||||
VulkanDevice(const VulkanInstance& p_instance, const VulkanSurface* p_surface, eastl::string_view p_deviceNameHint);
|
||||
|
||||
~VulkanDevice() override;
|
||||
|
||||
/**
|
||||
* Get a queue of the given type
|
||||
*
|
||||
* \param p_type The kind of work the queue should support
|
||||
* \return The queue, or nullptr if the device has no queue of this type
|
||||
*/
|
||||
[[nodiscard]]
|
||||
const GraphicsQueue* GetQueue(GraphicsQueueType p_type) const override;
|
||||
|
||||
/**
|
||||
* Get the underlying Vulkan physical device handle
|
||||
*
|
||||
* \return The vk::PhysicalDevice handle
|
||||
*/
|
||||
[[nodiscard]]
|
||||
vk::PhysicalDevice GetPhysicalDeviceHandle() const;
|
||||
|
||||
/**
|
||||
* Get the underlying Vulkan device handle
|
||||
*
|
||||
* \return The vk::Device handle
|
||||
*/
|
||||
[[nodiscard]]
|
||||
vk::Device GetHandle() const;
|
||||
|
||||
private:
|
||||
/**
|
||||
* The physical device this device was created from
|
||||
*/
|
||||
vk::PhysicalDevice m_physicalDevice;
|
||||
|
||||
/**
|
||||
* The logical device
|
||||
*/
|
||||
vk::Device m_device;
|
||||
|
||||
/**
|
||||
* The queues. A slot is empty if the device has no queue of that type
|
||||
*/
|
||||
eastl::array<eastl::optional<VulkanQueue>, static_cast<size_t>(GraphicsQueueType::MAX) + 1> m_queues;
|
||||
};
|
||||
} // namespace Bigfoot::Vulkan
|
||||
|
||||
#endif
|
||||
@@ -26,6 +26,12 @@ class VulkanQueue final: public GraphicsQueue
|
||||
*/
|
||||
VulkanQueue(vk::Queue p_queue, std::uint32_t p_familyIndex, GraphicsQueueType p_type);
|
||||
|
||||
VulkanQueue(const VulkanQueue& p_queue) = delete;
|
||||
VulkanQueue(VulkanQueue&& p_queue) noexcept;
|
||||
|
||||
VulkanQueue& operator=(const VulkanQueue& p_queue) = delete;
|
||||
VulkanQueue& operator=(VulkanQueue&& p_queue) noexcept;
|
||||
|
||||
/**
|
||||
* Get the kind of work this queue can be submitted
|
||||
*
|
||||
|
||||
@@ -0,0 +1,352 @@
|
||||
/*********************************************************************
|
||||
* \file VulkanDevice.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date September 2026
|
||||
*********************************************************************/
|
||||
#include <GraphicsVulkan/VulkanDevice.hpp>
|
||||
|
||||
#include <GraphicsVulkan/GraphicsVulkanAssertHandler.hpp>
|
||||
#include <GraphicsVulkan/VulkanFormatters.hpp>
|
||||
|
||||
#include <Utils/String.hpp>
|
||||
#include <Utils/TargetMacros.h>
|
||||
|
||||
#include <EASTL/algorithm.h>
|
||||
#include <EASTL/optional.h>
|
||||
#include <EASTL/span.h>
|
||||
#include <EASTL/vector.h>
|
||||
|
||||
#include <bit>
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
namespace Bigfoot::Vulkan
|
||||
{
|
||||
[[nodiscard]]
|
||||
std::uint32_t GetPhysicalDeviceTypeRank(const vk::PhysicalDeviceType p_type)
|
||||
{
|
||||
switch (p_type)
|
||||
{
|
||||
case vk::PhysicalDeviceType::eDiscreteGpu:
|
||||
return 0;
|
||||
case vk::PhysicalDeviceType::eIntegratedGpu:
|
||||
return 1;
|
||||
case vk::PhysicalDeviceType::eVirtualGpu:
|
||||
return 2;
|
||||
case vk::PhysicalDeviceType::eCpu:
|
||||
return 3;
|
||||
case vk::PhysicalDeviceType::eOther:
|
||||
default:
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
struct SelectedQueueFamilies
|
||||
{
|
||||
eastl::optional<std::uint32_t> m_graphics;
|
||||
eastl::optional<std::uint32_t> m_compute;
|
||||
eastl::optional<std::uint32_t> m_transfer;
|
||||
eastl::optional<std::uint32_t> m_present;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
[[nodiscard]]
|
||||
eastl::optional<std::uint32_t> FindQueueFamily(const std::span<const vk::QueueFamilyProperties> p_families,
|
||||
const vk::QueueFlagBits p_required)
|
||||
{
|
||||
eastl::optional<std::uint32_t> best;
|
||||
int bestBitCount = 0;
|
||||
|
||||
for (std::uint32_t index = 0; index < p_families.size(); ++index)
|
||||
{
|
||||
const vk::QueueFlags flags = p_families[index].queueFlags;
|
||||
if (!(flags & p_required))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const int bitCount = std::popcount(static_cast<vk::QueueFlags::MaskType>(flags));
|
||||
if (!best.has_value() || bitCount < bestBitCount)
|
||||
{
|
||||
best = index;
|
||||
bestBitCount = bitCount;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
[[nodiscard]]
|
||||
eastl::optional<std::uint32_t> FindPresentQueueFamily(const vk::PhysicalDevice p_physicalDevice,
|
||||
const vk::SurfaceKHR p_surface,
|
||||
const std::uint32_t p_familyCount,
|
||||
const eastl::optional<std::uint32_t> p_graphicsFamily)
|
||||
{
|
||||
if (p_graphicsFamily.has_value())
|
||||
{
|
||||
const vk::ResultValue<vk::Bool32> support = p_physicalDevice.getSurfaceSupportKHR(*p_graphicsFamily, p_surface);
|
||||
if (support.result == vk::Result::eSuccess && support.value)
|
||||
{
|
||||
return *p_graphicsFamily;
|
||||
}
|
||||
}
|
||||
|
||||
for (std::uint32_t index = 0; index < p_familyCount; ++index)
|
||||
{
|
||||
const vk::ResultValue<vk::Bool32> support = p_physicalDevice.getSurfaceSupportKHR(index, p_surface);
|
||||
if (support.result == vk::Result::eSuccess && support.value)
|
||||
{
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
return eastl::nullopt;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
[[nodiscard]]
|
||||
SelectedQueueFamilies SelectQueueFamilies(const vk::PhysicalDevice p_physicalDevice, const vk::SurfaceKHR p_surface)
|
||||
{
|
||||
const std::vector<vk::QueueFamilyProperties> families = p_physicalDevice.getQueueFamilyProperties();
|
||||
|
||||
SelectedQueueFamilies selected;
|
||||
selected.m_graphics = FindQueueFamily(families, vk::QueueFlagBits::eGraphics);
|
||||
selected.m_compute = FindQueueFamily(families, vk::QueueFlagBits::eCompute);
|
||||
selected.m_transfer = FindQueueFamily(families, vk::QueueFlagBits::eTransfer);
|
||||
if (!selected.m_transfer.has_value())
|
||||
{
|
||||
// Per the Vulkan spec, any queue family supporting Graphics or Compute implicitly supports
|
||||
// Transfer even when it doesn't explicitly report the bit, so the graphics family always works.
|
||||
selected.m_transfer = selected.m_graphics;
|
||||
}
|
||||
|
||||
if (p_surface)
|
||||
{
|
||||
selected.m_present = FindPresentQueueFamily(p_physicalDevice,
|
||||
p_surface,
|
||||
static_cast<std::uint32_t>(families.size()),
|
||||
selected.m_graphics);
|
||||
}
|
||||
|
||||
return selected;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
[[nodiscard]]
|
||||
bool IsPhysicalDeviceSuitable(const SelectedQueueFamilies& p_families, const bool p_needsPresent)
|
||||
{
|
||||
return p_families.m_graphics.has_value() && p_families.m_compute.has_value() &&
|
||||
(!p_needsPresent || p_families.m_present.has_value());
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
struct PhysicalDeviceCandidate
|
||||
{
|
||||
vk::PhysicalDevice m_handle;
|
||||
vk::PhysicalDeviceProperties m_properties;
|
||||
SelectedQueueFamilies m_queueFamilies;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
[[nodiscard]]
|
||||
const PhysicalDeviceCandidate& SelectPhysicalDevice(const eastl::span<const PhysicalDeviceCandidate> p_candidates,
|
||||
const eastl::string_view p_deviceNameHint)
|
||||
{
|
||||
if (!p_deviceNameHint.empty())
|
||||
{
|
||||
const auto it = eastl::find_if(p_candidates.begin(),
|
||||
p_candidates.end(),
|
||||
[p_deviceNameHint](const PhysicalDeviceCandidate& p_candidate)
|
||||
{
|
||||
return EqualNoCase(p_candidate.m_properties.deviceName.data(),
|
||||
p_deviceNameHint);
|
||||
});
|
||||
if (it != p_candidates.end())
|
||||
{
|
||||
return *it;
|
||||
}
|
||||
|
||||
BIGFOOT_LOG_WARN(GRAPHICSVULKAN_LOGGER,
|
||||
"No Vulkan device matching hint '{}' found, falling back to automatic selection",
|
||||
p_deviceNameHint);
|
||||
}
|
||||
|
||||
return *eastl::min_element(p_candidates.begin(),
|
||||
p_candidates.end(),
|
||||
[](const PhysicalDeviceCandidate& p_lhs, const PhysicalDeviceCandidate& p_rhs)
|
||||
{
|
||||
return GetPhysicalDeviceTypeRank(p_lhs.m_properties.deviceType) <
|
||||
GetPhysicalDeviceTypeRank(p_rhs.m_properties.deviceType);
|
||||
});
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
[[nodiscard]]
|
||||
eastl::optional<VulkanQueue> CreateQueue(const vk::Device p_device,
|
||||
const eastl::optional<std::uint32_t> p_familyIndex,
|
||||
const GraphicsQueueType p_type)
|
||||
{
|
||||
if (!p_familyIndex.has_value())
|
||||
{
|
||||
return eastl::nullopt;
|
||||
}
|
||||
|
||||
return VulkanQueue {p_device.getQueue(*p_familyIndex, 0), *p_familyIndex, p_type};
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
VulkanDevice::VulkanDevice(const VulkanInstance& p_instance,
|
||||
const VulkanSurface* p_surface,
|
||||
const eastl::string_view p_deviceNameHint)
|
||||
{
|
||||
const vk::SurfaceKHR surfaceHandle = p_surface != nullptr ? p_surface->GetHandle() : vk::SurfaceKHR {};
|
||||
|
||||
const vk::ResultValue<std::vector<vk::PhysicalDevice>> physicalDevices = p_instance.GetHandle()
|
||||
.enumeratePhysicalDevices();
|
||||
CRITICAL_ASSERT(GraphicsVulkanAssertHandler,
|
||||
physicalDevices.result == vk::Result::eSuccess,
|
||||
"({}) Failed to enumerate Vulkan physical devices",
|
||||
physicalDevices.result);
|
||||
|
||||
eastl::vector<PhysicalDeviceCandidate> candidates;
|
||||
for (const vk::PhysicalDevice physicalDevice: physicalDevices.value)
|
||||
{
|
||||
SelectedQueueFamilies queueFamilies = SelectQueueFamilies(physicalDevice, surfaceHandle);
|
||||
if (!IsPhysicalDeviceSuitable(queueFamilies, static_cast<bool>(surfaceHandle)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
candidates.push_back({physicalDevice, physicalDevice.getProperties(), eastl::move(queueFamilies)});
|
||||
}
|
||||
CRITICAL_ASSERT(GraphicsVulkanAssertHandler, !candidates.empty(), "No suitable Vulkan physical device found");
|
||||
|
||||
const PhysicalDeviceCandidate& selected = SelectPhysicalDevice(candidates, p_deviceNameHint);
|
||||
m_physicalDevice = selected.m_handle;
|
||||
|
||||
BIGFOOT_LOG_INFO(GRAPHICSVULKAN_LOGGER,
|
||||
"Selected Vulkan physical device '{}' ({})",
|
||||
selected.m_properties.deviceName.data(),
|
||||
vk::to_string(selected.m_properties.deviceType));
|
||||
|
||||
eastl::vector<std::uint32_t> uniqueFamilies;
|
||||
for (const eastl::optional<std::uint32_t> family: {selected.m_queueFamilies.m_graphics,
|
||||
selected.m_queueFamilies.m_compute,
|
||||
selected.m_queueFamilies.m_transfer,
|
||||
selected.m_queueFamilies.m_present})
|
||||
{
|
||||
if (family.has_value() &&
|
||||
eastl::find(uniqueFamilies.begin(), uniqueFamilies.end(), *family) == uniqueFamilies.end())
|
||||
{
|
||||
uniqueFamilies.push_back(*family);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr float queuePriority = 1.0f;
|
||||
eastl::vector<vk::DeviceQueueCreateInfo> queueCreateInfos;
|
||||
queueCreateInfos.reserve(uniqueFamilies.size());
|
||||
for (const std::uint32_t family: uniqueFamilies)
|
||||
{
|
||||
queueCreateInfos.push_back({{}, family, 1u, &queuePriority});
|
||||
}
|
||||
|
||||
eastl::vector<const char*> enabledExtensions;
|
||||
if (surfaceHandle)
|
||||
{
|
||||
enabledExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
const vk::DeviceCreateInfo deviceCreateInfo {{}, queueCreateInfos, {}, enabledExtensions};
|
||||
|
||||
vk::ResultValue<vk::Device> device {vk::Result::eSuccess, vk::Device {}};
|
||||
{
|
||||
BIGFOOT_LSAN_ONLY(const __lsan::ScopedDisabler lsanDisabler;)
|
||||
device = m_physicalDevice.createDevice(deviceCreateInfo);
|
||||
}
|
||||
CRITICAL_ASSERT(GraphicsVulkanAssertHandler,
|
||||
device.result == vk::Result::eSuccess,
|
||||
"({}) Failed to create Vulkan device",
|
||||
device.result);
|
||||
m_device = device.value;
|
||||
|
||||
m_queues[static_cast<size_t>(GraphicsQueueType::Graphics)] = CreateQueue(m_device,
|
||||
selected.m_queueFamilies.m_graphics,
|
||||
GraphicsQueueType::Graphics);
|
||||
m_queues[static_cast<size_t>(GraphicsQueueType::Compute)] = CreateQueue(m_device,
|
||||
selected.m_queueFamilies.m_compute,
|
||||
GraphicsQueueType::Compute);
|
||||
m_queues[static_cast<size_t>(GraphicsQueueType::Transfer)] = CreateQueue(m_device,
|
||||
selected.m_queueFamilies.m_transfer,
|
||||
GraphicsQueueType::Transfer);
|
||||
m_queues[static_cast<size_t>(GraphicsQueueType::Present)] = CreateQueue(m_device,
|
||||
selected.m_queueFamilies.m_present,
|
||||
GraphicsQueueType::Present);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
VulkanDevice::~VulkanDevice()
|
||||
{
|
||||
m_device.destroy();
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
const GraphicsQueue* VulkanDevice::GetQueue(const GraphicsQueueType p_type) const
|
||||
{
|
||||
const eastl::optional<VulkanQueue>& queue = m_queues[static_cast<size_t>(p_type)];
|
||||
return queue.has_value() ? &*queue : nullptr;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
vk::PhysicalDevice VulkanDevice::GetPhysicalDeviceHandle() const
|
||||
{
|
||||
return m_physicalDevice;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
vk::Device VulkanDevice::GetHandle() const
|
||||
{
|
||||
return m_device;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
[[nodiscard]]
|
||||
eastl::unique_ptr<GraphicsDevice> CreateVulkanDevice(const GraphicsInstance& p_instance,
|
||||
const DeviceCreateInfo& p_createInfo)
|
||||
{
|
||||
return eastl::make_unique<VulkanDevice>(static_cast<const VulkanInstance&>(p_instance),
|
||||
static_cast<const VulkanSurface*>(p_createInfo.m_surface),
|
||||
p_createInfo.m_deviceNameHint);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
[[nodiscard]]
|
||||
bool RegisterVulkanDeviceFactory()
|
||||
{
|
||||
const bool inserted = g_graphicsDeviceFactory->Register(GraphicsAPI::Vulkan, &CreateVulkanDevice);
|
||||
CRITICAL_ASSERT(GraphicsVulkanAssertHandler, inserted, "Failed to register the Vulkan graphics device factory");
|
||||
return inserted;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
const bool g_vulkanDeviceFactoryRegistered = RegisterVulkanDeviceFactory();
|
||||
} // namespace Bigfoot::Vulkan
|
||||
@@ -163,4 +163,27 @@ vk::Instance VulkanInstance::GetHandle() const
|
||||
{
|
||||
return m_instance;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
[[nodiscard]]
|
||||
eastl::unique_ptr<GraphicsInstance> CreateVulkanInstance(const eastl::string_view p_applicationName,
|
||||
const Version p_applicationVersion)
|
||||
{
|
||||
return eastl::make_unique<VulkanInstance>(p_applicationName, p_applicationVersion);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
[[nodiscard]]
|
||||
bool RegisterVulkanInstanceFactory()
|
||||
{
|
||||
const bool inserted = g_graphicsInstanceFactory->Register(GraphicsAPI::Vulkan, &CreateVulkanInstance);
|
||||
CRITICAL_ASSERT(GraphicsVulkanAssertHandler, inserted, "Failed to register the Vulkan graphics instance factory");
|
||||
return inserted;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
const bool g_vulkanInstanceFactoryRegistered = RegisterVulkanInstanceFactory();
|
||||
} // namespace Bigfoot::Vulkan
|
||||
|
||||
@@ -17,6 +17,26 @@ VulkanQueue::VulkanQueue(const vk::Queue p_queue, const std::uint32_t p_familyIn
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
VulkanQueue::VulkanQueue(VulkanQueue&& p_queue) noexcept:
|
||||
GraphicsQueue(),
|
||||
m_queue(p_queue.m_queue),
|
||||
m_familyIndex(p_queue.m_familyIndex),
|
||||
m_type(p_queue.m_type)
|
||||
{
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
VulkanQueue& VulkanQueue::operator=(VulkanQueue&& p_queue) noexcept
|
||||
{
|
||||
m_queue = p_queue.m_queue;
|
||||
m_familyIndex = p_queue.m_familyIndex;
|
||||
m_type = p_queue.m_type;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
GraphicsQueueType VulkanQueue::GetType() const
|
||||
{
|
||||
return m_type;
|
||||
|
||||
@@ -44,4 +44,27 @@ vk::SurfaceKHR VulkanSurface::GetHandle() const
|
||||
{
|
||||
return m_surface;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
[[nodiscard]]
|
||||
eastl::unique_ptr<GraphicsSurface> CreateVulkanSurface(const GraphicsInstance& p_instance,
|
||||
const SurfaceCreateInfo& p_surfaceCreateInfo)
|
||||
{
|
||||
return eastl::make_unique<VulkanSurface>(static_cast<const VulkanInstance&>(p_instance), p_surfaceCreateInfo);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
[[nodiscard]]
|
||||
bool RegisterVulkanSurfaceFactory()
|
||||
{
|
||||
const bool inserted = g_graphicsSurfaceFactory->Register(GraphicsAPI::Vulkan, &CreateVulkanSurface);
|
||||
CRITICAL_ASSERT(GraphicsVulkanAssertHandler, inserted, "Failed to register the Vulkan graphics surface factory");
|
||||
return inserted;
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
const bool g_vulkanSurfaceFactoryRegistered = RegisterVulkanSurfaceFactory();
|
||||
} // namespace Bigfoot::Vulkan
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
get_filename_component(PackageName ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
project(${PackageName}Tests)
|
||||
|
||||
set(Dependencies)
|
||||
set(Dependencies
|
||||
SDL3::SDL3)
|
||||
set(BigfootDependencies)
|
||||
|
||||
bigfoot_create_package_tests(
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*********************************************************************
|
||||
* \file GraphicsContext.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date September 2026
|
||||
*********************************************************************/
|
||||
#include <GraphicsCore/GraphicsContext.hpp>
|
||||
|
||||
#include <Utils/TargetMacros.h>
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace Bigfoot
|
||||
{
|
||||
class GraphicsContextFixture: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
m_window = SDL_CreateWindow("GraphicsContextTests", 64, 64, SDL_WINDOW_HIDDEN | SDL_WINDOW_VULKAN);
|
||||
|
||||
const SDL_PropertiesID windowProperties = SDL_GetWindowProperties(m_window);
|
||||
|
||||
m_createInfo.m_applicationName = "GraphicsContextTests";
|
||||
m_createInfo.m_applicationVersion = Version {1, 0, 0};
|
||||
#ifdef BIGFOOT_WINDOWS
|
||||
m_createInfo.m_surfaceCreateInfo.m_windowHandle = static_cast<HWND>(
|
||||
SDL_GetPointerProperty(windowProperties, SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr));
|
||||
m_createInfo.m_surfaceCreateInfo.m_windowInstance = GetModuleHandle(nullptr);
|
||||
#elif defined BIGFOOT_LINUX
|
||||
m_createInfo.m_surfaceCreateInfo.m_display = static_cast<wl_display*>(
|
||||
SDL_GetPointerProperty(windowProperties, SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, nullptr));
|
||||
m_createInfo.m_surfaceCreateInfo.m_surface = static_cast<wl_surface*>(
|
||||
SDL_GetPointerProperty(windowProperties, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr));
|
||||
#endif
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
SDL_DestroyWindow(m_window);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
SDL_Window* m_window = nullptr;
|
||||
GraphicsContextCreateInfo m_createInfo;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(GraphicsContextFixture, Constructor_ShouldCreateAValidInstanceSurfaceAndDevice)
|
||||
{
|
||||
const GraphicsContext context {m_createInfo};
|
||||
|
||||
EXPECT_NE(context.GetDevice().GetQueue(GraphicsQueueType::Graphics), nullptr);
|
||||
EXPECT_NE(context.GetDevice().GetQueue(GraphicsQueueType::Compute), nullptr);
|
||||
EXPECT_NE(context.GetDevice().GetQueue(GraphicsQueueType::Transfer), nullptr);
|
||||
EXPECT_NE(context.GetDevice().GetQueue(GraphicsQueueType::Present), nullptr);
|
||||
}
|
||||
} // namespace Bigfoot
|
||||
@@ -0,0 +1,82 @@
|
||||
/*********************************************************************
|
||||
* \file VulkanDevice.cpp
|
||||
*
|
||||
* \author Romain BOULLARD
|
||||
* \date September 2026
|
||||
*********************************************************************/
|
||||
#include <GraphicsVulkan/VulkanDevice.hpp>
|
||||
|
||||
#include <GraphicsVulkan/VulkanInstance.hpp>
|
||||
#include <GraphicsVulkan/VulkanSurface.hpp>
|
||||
|
||||
#include <Utils/TargetMacros.h>
|
||||
|
||||
#include <SDL3/SDL.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace Bigfoot::Vulkan
|
||||
{
|
||||
class VulkanDeviceFixture: public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
void SetUp() override
|
||||
{
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
|
||||
m_window = SDL_CreateWindow("VulkanDeviceTests", 64, 64, SDL_WINDOW_HIDDEN | SDL_WINDOW_VULKAN);
|
||||
|
||||
const SDL_PropertiesID windowProperties = SDL_GetWindowProperties(m_window);
|
||||
|
||||
#ifdef BIGFOOT_WINDOWS
|
||||
m_surfaceCreateInfo.m_windowHandle = static_cast<HWND>(
|
||||
SDL_GetPointerProperty(windowProperties, SDL_PROP_WINDOW_WIN32_HWND_POINTER, nullptr));
|
||||
m_surfaceCreateInfo.m_windowInstance = GetModuleHandle(nullptr);
|
||||
#elif defined BIGFOOT_LINUX
|
||||
m_surfaceCreateInfo.m_display = static_cast<wl_display*>(
|
||||
SDL_GetPointerProperty(windowProperties, SDL_PROP_WINDOW_WAYLAND_DISPLAY_POINTER, nullptr));
|
||||
m_surfaceCreateInfo.m_surface = static_cast<wl_surface*>(
|
||||
SDL_GetPointerProperty(windowProperties, SDL_PROP_WINDOW_WAYLAND_SURFACE_POINTER, nullptr));
|
||||
#endif
|
||||
}
|
||||
|
||||
void TearDown() override
|
||||
{
|
||||
SDL_DestroyWindow(m_window);
|
||||
SDL_Quit();
|
||||
}
|
||||
|
||||
VulkanInstance m_instance {"VulkanDeviceTests", Version {1, 0, 0}};
|
||||
SDL_Window* m_window = nullptr;
|
||||
SurfaceCreateInfo m_surfaceCreateInfo;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(VulkanDeviceFixture, WithoutSurface_ShouldCreateAValidDeviceWithoutAPresentQueue)
|
||||
{
|
||||
const VulkanDevice device {m_instance, nullptr, {}};
|
||||
|
||||
EXPECT_TRUE(device.GetPhysicalDeviceHandle());
|
||||
EXPECT_TRUE(device.GetHandle());
|
||||
EXPECT_NE(device.GetQueue(GraphicsQueueType::Graphics), nullptr);
|
||||
EXPECT_NE(device.GetQueue(GraphicsQueueType::Compute), nullptr);
|
||||
EXPECT_NE(device.GetQueue(GraphicsQueueType::Transfer), nullptr);
|
||||
EXPECT_EQ(device.GetQueue(GraphicsQueueType::Present), nullptr);
|
||||
}
|
||||
|
||||
/****************************************************************************************/
|
||||
|
||||
TEST_F(VulkanDeviceFixture, WithSurface_ShouldCreateAValidDeviceWithAPresentQueue)
|
||||
{
|
||||
const VulkanSurface surface {m_instance, m_surfaceCreateInfo};
|
||||
|
||||
const VulkanDevice device {m_instance, &surface, {}};
|
||||
|
||||
EXPECT_TRUE(device.GetPhysicalDeviceHandle());
|
||||
EXPECT_TRUE(device.GetHandle());
|
||||
EXPECT_NE(device.GetQueue(GraphicsQueueType::Graphics), nullptr);
|
||||
EXPECT_NE(device.GetQueue(GraphicsQueueType::Compute), nullptr);
|
||||
EXPECT_NE(device.GetQueue(GraphicsQueueType::Transfer), nullptr);
|
||||
EXPECT_NE(device.GetQueue(GraphicsQueueType::Present), nullptr);
|
||||
}
|
||||
} // namespace Bigfoot::Vulkan
|
||||
Reference in New Issue
Block a user