diff --git a/CMakeLists.txt b/CMakeLists.txt index 55acf303a..db4c05a90 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -693,10 +693,10 @@ if(NOT SERVER_ONLY) ${OGGVORBIS_LIBRARIES} ${FREETYPE_LIBRARIES} ${HARFBUZZ_LIBRARY} - ${SDL2_LIBRARY} ${SHEENBIDI_LIBRARY} graphics_utils graphics_engine + ${SDL2_LIBRARY} tinygettext) endif() diff --git a/android/Android.mk b/android/Android.mk index de9fed69d..7a0b92f0b 100644 --- a/android/Android.mk +++ b/android/Android.mk @@ -147,10 +147,11 @@ include $(CLEAR_VARS) # Graphics engine LOCAL_MODULE := graphics_engine LOCAL_PATH := . -LOCAL_CPP_FEATURES += rtti +LOCAL_CPP_FEATURES += rtti exceptions LOCAL_SRC_FILES := $(wildcard ../lib/graphics_engine/src/*.c) \ $(wildcard ../lib/graphics_engine/src/*.cpp) LOCAL_CFLAGS := -I../lib/graphics_engine/include \ + -I../lib/sdl2/include/ \ -I../lib/irrlicht/include/ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) @@ -189,7 +190,7 @@ include $(CLEAR_VARS) # Irrlicht LOCAL_MODULE := irrlicht LOCAL_PATH := . -LOCAL_CPP_FEATURES += rtti +LOCAL_CPP_FEATURES += rtti exceptions LOCAL_SRC_FILES := $(wildcard ../lib/irrlicht/source/Irrlicht/*.cpp) LOCAL_CFLAGS := -I../lib/irrlicht/source/Irrlicht/ \ -I../lib/irrlicht/include/ \ diff --git a/lib/graphics_engine/CMakeLists.txt b/lib/graphics_engine/CMakeLists.txt index e24ba2a17..dd34ed733 100644 --- a/lib/graphics_engine/CMakeLists.txt +++ b/lib/graphics_engine/CMakeLists.txt @@ -1,5 +1,12 @@ include_directories("${PROJECT_SOURCE_DIR}/lib/graphics_engine/include") include_directories("${PROJECT_SOURCE_DIR}/lib/irrlicht/include") +find_path(SDL2_INCLUDEDIR NAMES SDL.h PATH_SUFFIXES SDL2 include/SDL2 include PATHS) +if (NOT SDL2_INCLUDEDIR) + message(FATAL_ERROR "SDL2 not found.") +else() + include_directories("${SDL2_INCLUDEDIR}") +endif() + if(UNIX OR MINGW) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++0x") endif() @@ -9,5 +16,6 @@ add_library(graphics_engine STATIC src/ge_main.cpp src/ge_texture.cpp src/ge_dx9_texture.cpp + src/ge_vulkan_driver.cpp src/ge_gl_texture.cpp ) diff --git a/lib/graphics_engine/include/ge_vulkan_driver.hpp b/lib/graphics_engine/include/ge_vulkan_driver.hpp new file mode 100644 index 000000000..7c7a53855 --- /dev/null +++ b/lib/graphics_engine/include/ge_vulkan_driver.hpp @@ -0,0 +1,350 @@ +#ifndef __VULKAN_DRIVER_INCLUDED__ +#define __VULKAN_DRIVER_INCLUDED__ + +#include "IrrCompileConfig.h" + +#ifdef _IRR_COMPILE_WITH_VULKAN_ + +#include "glad/vulkan.h" +#include "SDL_video.h" + +#include "../source/Irrlicht/CNullDriver.h" +#include "SIrrCreationParameters.h" +#include "SColor.h" +#include +#include + +using namespace irr; +using namespace video; + +namespace GE +{ + class GEVulkanDriver : public video::CNullDriver + { + public: + + //! constructor + GEVulkanDriver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, SDL_Window* window); + + //! destructor + virtual ~GEVulkanDriver(); + + //! applications must call this method before performing any rendering. returns false if failed. + virtual bool beginScene(bool backBuffer=true, bool zBuffer=true, + SColor color=SColor(255,0,0,0), + const SExposedVideoData& videoData=SExposedVideoData(), + core::rect* sourceRect=0) { return true; } + + //! applications must call this method after performing any rendering. returns false if failed. + virtual bool endScene() { return true; } + + //! queries the features of the driver, returns true if feature is available + virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const { return true; } + + //! sets transformation + virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat) {} + + //! sets a material + virtual void setMaterial(const SMaterial& material) {} + + //! sets a render target + virtual bool setRenderTarget(video::ITexture* texture, + bool clearBackBuffer=true, bool clearZBuffer=true, + SColor color=video::SColor(0,0,0,0)) { return true; } + + //! Sets multiple render targets + virtual bool setRenderTarget(const core::array& texture, + bool clearBackBuffer=true, bool clearZBuffer=true, + SColor color=video::SColor(0,0,0,0)) { return true; } + + //! sets a viewport + virtual void setViewPort(const core::rect& area) {} + + //! gets the area of the current viewport + virtual const core::rect& getViewPort() const + { + static core::rect unused; + return unused; + } + + //! updates hardware buffer if needed + virtual bool updateHardwareBuffer(SHWBufferLink *HWBuffer) { return false; } + + //! Create hardware buffer from mesh + virtual SHWBufferLink *createHardwareBuffer(const scene::IMeshBuffer* mb) { return NULL; } + + //! Delete hardware buffer (only some drivers can) + virtual void deleteHardwareBuffer(SHWBufferLink *HWBuffer) {} + + //! Draw hardware buffer + virtual void drawHardwareBuffer(SHWBufferLink *HWBuffer) {} + + //! Create occlusion query. + /** Use node for identification and mesh for occlusion test. */ + virtual void addOcclusionQuery(scene::ISceneNode* node, + const scene::IMesh* mesh=0) {} + + //! Remove occlusion query. + virtual void removeOcclusionQuery(scene::ISceneNode* node) {} + + //! Run occlusion query. Draws mesh stored in query. + /** If the mesh shall not be rendered visible, use + overrideMaterial to disable the color and depth buffer. */ + virtual void runOcclusionQuery(scene::ISceneNode* node, bool visible=false) {} + + //! Update occlusion query. Retrieves results from GPU. + /** If the query shall not block, set the flag to false. + Update might not occur in this case, though */ + virtual void updateOcclusionQuery(scene::ISceneNode* node, bool block=true) {} + + //! Return query result. + /** Return value is the number of visible pixels/fragments. + The value is a safe approximation, i.e. can be larger then the + actual value of pixels. */ + virtual u32 getOcclusionQueryResult(scene::ISceneNode* node) const { return 0; } + + //! draws a vertex primitive list + virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount, + const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType) {} + + //! draws a vertex primitive list in 2d + virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount, + const void* indexList, u32 primitiveCount, + E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType, + E_INDEX_TYPE iType) {} + + //! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted. + virtual void draw2DImage(const video::ITexture* texture, const core::position2d& destPos, + const core::rect& sourceRect, const core::rect* clipRect = 0, + SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false) {} + + //! Draws a part of the texture into the rectangle. + virtual void draw2DImage(const video::ITexture* texture, const core::rect& destRect, + const core::rect& sourceRect, const core::rect* clipRect = 0, + const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false) {} + + //! Draws a set of 2d images, using a color and the alpha channel of the texture. + virtual void draw2DImageBatch(const video::ITexture* texture, + const core::array >& positions, + const core::array >& sourceRects, + const core::rect* clipRect=0, + SColor color=SColor(255,255,255,255), + bool useAlphaChannelOfTexture=false) {} + + //!Draws an 2d rectangle with a gradient. + virtual void draw2DRectangle(const core::rect& pos, + SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown, + const core::rect* clip) {} + + //! Draws a 2d line. + virtual void draw2DLine(const core::position2d& start, + const core::position2d& end, + SColor color=SColor(255,255,255,255)) {} + + //! Draws a pixel. + virtual void drawPixel(u32 x, u32 y, const SColor & color) {} + + //! Draws a 3d line. + virtual void draw3DLine(const core::vector3df& start, + const core::vector3df& end, SColor color = SColor(255,255,255,255)) {} + + //! \return Returns the name of the video driver. Example: In case of the DIRECT3D8 + //! driver, it would return "Direct3D8.1". + virtual const wchar_t* getName() const { return L""; } + + //! deletes all dynamic lights there are + virtual void deleteAllDynamicLights() {} + + //! adds a dynamic light, returning an index to the light + //! \param light: the light data to use to create the light + //! \return An index to the light, or -1 if an error occurs + virtual s32 addDynamicLight(const SLight& light) { return -1; } + + //! Turns a dynamic light on or off + //! \param lightIndex: the index returned by addDynamicLight + //! \param turnOn: true to turn the light on, false to turn it off + virtual void turnLightOn(s32 lightIndex, bool turnOn) {} + + //! returns the maximal amount of dynamic lights the device can handle + virtual u32 getMaximalDynamicLightAmount() const { return (u32)-1; } + + //! Sets the dynamic ambient light color. The default color is + //! (0,0,0,0) which means it is dark. + //! \param color: New color of the ambient light. + virtual void setAmbientLight(const SColorf& color) {} + + //! Draws a shadow volume into the stencil buffer. + virtual void drawStencilShadowVolume(const core::array& triangles, bool zfail=true, u32 debugDataVisible=0) {} + + //! Fills the stencil shadow with color. + virtual void drawStencilShadow(bool clearStencilBuffer=false, + video::SColor leftUpEdge = video::SColor(0,0,0,0), + video::SColor rightUpEdge = video::SColor(0,0,0,0), + video::SColor leftDownEdge = video::SColor(0,0,0,0), + video::SColor rightDownEdge = video::SColor(0,0,0,0)) {} + + //! Returns the maximum amount of primitives (mostly vertices) which + //! the device is able to render with one drawIndexedTriangleList + //! call. + virtual u32 getMaximalPrimitiveCount() const { return (u32)-1; } + + //! Enables or disables a texture creation flag. + virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled) {} + + //! Sets the fog mode. + virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start, + f32 end, f32 density, bool pixelFog, bool rangeFog) {} + + //! Only used by the internal engine. Used to notify the driver that + //! the window was resized. + virtual void OnResize(const core::dimension2d& size) {} + + //! Returns type of video driver + virtual E_DRIVER_TYPE getDriverType() const { return video::EDT_VULKAN; } + + //! Returns the transformation set by setTransform + virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const + { + static core::matrix4 unused; + return unused; + } + + //! Creates a render target texture. + virtual ITexture* addRenderTargetTexture(const core::dimension2d& size, + const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN, const bool useStencil = false) { return NULL; } + + //! Clears the ZBuffer. + virtual void clearZBuffer() {} + + //! Returns an image created from the last rendered frame. + virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER) { return NULL; } + + //! Set/unset a clipping plane. + virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false) { return true; } + + //! Enable/disable a clipping plane. + virtual void enableClipPlane(u32 index, bool enable) {} + + //! Returns the graphics card vendor name. + virtual core::stringc getVendorInfo() + { + switch (m_properties.vendorID) + { + case 0x1002: return "AMD"; + case 0x1010: return "ImgTec"; + case 0x106B: return "Apple"; + case 0x10DE: return "NVIDIA"; + case 0x13B5: return "ARM"; + case 0x14e4: return "Broadcom"; + case 0x5143: return "Qualcomm"; + case 0x8086: return "INTEL"; + // llvmpipe + case 0x10005: return "Mesa"; + default: return "Unknown"; + } + } + + //! Enable the 2d override material + virtual void enableMaterial2D(bool enable=true) {} + + //! Check if the driver was recently reset. + virtual bool checkDriverReset() { return false; } + + //! Get the current color format of the color buffer + /** \return Color format of the color buffer. */ + virtual ECOLOR_FORMAT getColorFormat() const { return ECF_A8R8G8B8; } + + //! Returns the maximum texture size supported. + virtual core::dimension2du getMaxTextureSize() const { return core::dimension2du(16384, 16384); } + + virtual void enableScissorTest(const core::rect& r) {} + virtual void disableScissorTest() {} + + private: + //! returns a device dependent texture from a software surface (IImage) + //! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES + virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0) { return NULL; } + + //! returns the current size of the screen or rendertarget + virtual const core::dimension2d& getCurrentRenderTargetSize() const + { + static core::dimension2d unused; + return unused; + } + + //! Adds a new material renderer to the VideoDriver, based on a high level shading + //! language. + virtual s32 addHighLevelShaderMaterial( + const c8* vertexShaderProgram, + const c8* vertexShaderEntryPointName, + E_VERTEX_SHADER_TYPE vsCompileTarget, + const c8* pixelShaderProgram, + const c8* pixelShaderEntryPointName, + E_PIXEL_SHADER_TYPE psCompileTarget, + const c8* geometryShaderProgram, + const c8* geometryShaderEntryPointName = "main", + E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0, + scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES, + scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP, + u32 verticesOut = 0, + IShaderConstantSetCallBack* callback = 0, + E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID, + s32 userData = 0, + E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT) { return 0; } + + // RAII to auto cleanup + struct VK + { + VkInstance instance; + VkSurfaceKHR surface; + VkDevice device; + VK() + { + instance = VK_NULL_HANDLE; + surface = VK_NULL_HANDLE; + device = VK_NULL_HANDLE; + } + ~VK() + { + if (device != VK_NULL_HANDLE) + vkDestroyDevice(device, NULL); + if (surface != VK_NULL_HANDLE) + vkDestroySurfaceKHR(instance, surface, NULL); + if (instance != VK_NULL_HANDLE) + vkDestroyInstance(instance, NULL); + } + }; + VK m_vk; + VkPhysicalDevice m_physical_device; + std::vector m_device_extensions; + VkSurfaceCapabilitiesKHR m_surface_capabilities; + std::vector m_surface_formats; + std::vector m_present_modes; + VkQueue m_graphics_queue; + VkQueue m_present_queue; + + uint32_t m_graphics_family; + uint32_t m_present_family; + VkPhysicalDeviceProperties m_properties; + VkPhysicalDeviceFeatures m_features; + + void createInstance(SDL_Window* window); + void findPhysicalDevice(); + bool checkDeviceExtensions(VkPhysicalDevice device); + bool findQueueFamilies(VkPhysicalDevice device, uint32_t* graphics_family, uint32_t* present_family); + bool updateSurfaceInformation(VkPhysicalDevice device, + VkSurfaceCapabilitiesKHR* surface_capabilities, + std::vector* surface_formats, + std::vector* present_modes); + void createDevice(); + std::string getVulkanVersionString() const; + std::string getDriverVersionString() const; + }; + +} + +#endif // _IRR_COMPILE_WITH_VULKAN_ +#endif // __VULKAN_DRIVER_INCLUDED__ + diff --git a/lib/graphics_engine/src/ge_vulkan_driver.cpp b/lib/graphics_engine/src/ge_vulkan_driver.cpp new file mode 100644 index 000000000..1d6853765 --- /dev/null +++ b/lib/graphics_engine/src/ge_vulkan_driver.cpp @@ -0,0 +1,748 @@ +#include "ge_vulkan_driver.hpp" + +#ifdef _IRR_COMPILE_WITH_VULKAN_ +#include "SDL_vulkan.h" +#include +#include +#include + +#include "../source/Irrlicht/os.h" + +struct GE_VK_UserPointer +{ + VkInstance instance; + VkDevice device; + PFN_vkGetDeviceProcAddr get_device_proc_addr; + PFN_vkGetInstanceProcAddr get_instance_proc_addr; +}; + +extern "C" PFN_vkVoidFunction loader(void* user_ptr, const char* name) +{ + VkInstance instance = VK_NULL_HANDLE; + VkDevice device = VK_NULL_HANDLE; + PFN_vkGetDeviceProcAddr get_device_proc_addr = NULL; + PFN_vkGetInstanceProcAddr get_instance_proc_addr = NULL; + + if (user_ptr) + { + instance = ((GE_VK_UserPointer*)user_ptr)->instance; + device = ((GE_VK_UserPointer*)user_ptr)->device; + get_device_proc_addr = + ((GE_VK_UserPointer*)user_ptr)->get_device_proc_addr; + get_instance_proc_addr = + ((GE_VK_UserPointer*)user_ptr)->get_instance_proc_addr; + } + + if (get_instance_proc_addr == NULL) + { + get_instance_proc_addr = + (PFN_vkGetInstanceProcAddr)SDL_Vulkan_GetVkGetInstanceProcAddr(); + if (user_ptr) + { + ((GE_VK_UserPointer*)user_ptr)->get_instance_proc_addr = + get_instance_proc_addr; + } + } + + // From vulkan.c glad2 with loader enabled + static std::set device_function = + {{ + "vkAcquireFullScreenExclusiveModeEXT", + "vkAcquireNextImage2KHR", + "vkAcquireNextImageKHR", + "vkAcquirePerformanceConfigurationINTEL", + "vkAcquireProfilingLockKHR", + "vkAllocateCommandBuffers", + "vkAllocateDescriptorSets", + "vkAllocateMemory", + "vkBeginCommandBuffer", + "vkBindAccelerationStructureMemoryKHR", + "vkBindAccelerationStructureMemoryNV", + "vkBindBufferMemory", + "vkBindBufferMemory2", + "vkBindBufferMemory2KHR", + "vkBindImageMemory", + "vkBindImageMemory2", + "vkBindImageMemory2KHR", + "vkBuildAccelerationStructureKHR", + "vkCmdBeginConditionalRenderingEXT", + "vkCmdBeginDebugUtilsLabelEXT", + "vkCmdBeginQuery", + "vkCmdBeginQueryIndexedEXT", + "vkCmdBeginRenderPass", + "vkCmdBeginRenderPass2", + "vkCmdBeginRenderPass2KHR", + "vkCmdBeginTransformFeedbackEXT", + "vkCmdBindDescriptorSets", + "vkCmdBindIndexBuffer", + "vkCmdBindPipeline", + "vkCmdBindPipelineShaderGroupNV", + "vkCmdBindShadingRateImageNV", + "vkCmdBindTransformFeedbackBuffersEXT", + "vkCmdBindVertexBuffers", + "vkCmdBindVertexBuffers2EXT", + "vkCmdBlitImage", + "vkCmdBuildAccelerationStructureIndirectKHR", + "vkCmdBuildAccelerationStructureKHR", + "vkCmdBuildAccelerationStructureNV", + "vkCmdClearAttachments", + "vkCmdClearColorImage", + "vkCmdClearDepthStencilImage", + "vkCmdCopyAccelerationStructureKHR", + "vkCmdCopyAccelerationStructureNV", + "vkCmdCopyAccelerationStructureToMemoryKHR", + "vkCmdCopyBuffer", + "vkCmdCopyBufferToImage", + "vkCmdCopyImage", + "vkCmdCopyImageToBuffer", + "vkCmdCopyMemoryToAccelerationStructureKHR", + "vkCmdCopyQueryPoolResults", + "vkCmdDebugMarkerBeginEXT", + "vkCmdDebugMarkerEndEXT", + "vkCmdDebugMarkerInsertEXT", + "vkCmdDispatch", + "vkCmdDispatchBase", + "vkCmdDispatchBaseKHR", + "vkCmdDispatchIndirect", + "vkCmdDraw", + "vkCmdDrawIndexed", + "vkCmdDrawIndexedIndirect", + "vkCmdDrawIndexedIndirectCount", + "vkCmdDrawIndexedIndirectCountAMD", + "vkCmdDrawIndexedIndirectCountKHR", + "vkCmdDrawIndirect", + "vkCmdDrawIndirectByteCountEXT", + "vkCmdDrawIndirectCount", + "vkCmdDrawIndirectCountAMD", + "vkCmdDrawIndirectCountKHR", + "vkCmdDrawMeshTasksIndirectCountNV", + "vkCmdDrawMeshTasksIndirectNV", + "vkCmdDrawMeshTasksNV", + "vkCmdEndConditionalRenderingEXT", + "vkCmdEndDebugUtilsLabelEXT", + "vkCmdEndQuery", + "vkCmdEndQueryIndexedEXT", + "vkCmdEndRenderPass", + "vkCmdEndRenderPass2", + "vkCmdEndRenderPass2KHR", + "vkCmdEndTransformFeedbackEXT", + "vkCmdExecuteCommands", + "vkCmdExecuteGeneratedCommandsNV", + "vkCmdFillBuffer", + "vkCmdInsertDebugUtilsLabelEXT", + "vkCmdNextSubpass", + "vkCmdNextSubpass2", + "vkCmdNextSubpass2KHR", + "vkCmdPipelineBarrier", + "vkCmdPreprocessGeneratedCommandsNV", + "vkCmdPushConstants", + "vkCmdPushDescriptorSetKHR", + "vkCmdPushDescriptorSetWithTemplateKHR", + "vkCmdResetEvent", + "vkCmdResetQueryPool", + "vkCmdResolveImage", + "vkCmdSetBlendConstants", + "vkCmdSetCheckpointNV", + "vkCmdSetCoarseSampleOrderNV", + "vkCmdSetCullModeEXT", + "vkCmdSetDepthBias", + "vkCmdSetDepthBounds", + "vkCmdSetDepthBoundsTestEnableEXT", + "vkCmdSetDepthCompareOpEXT", + "vkCmdSetDepthTestEnableEXT", + "vkCmdSetDepthWriteEnableEXT", + "vkCmdSetDeviceMask", + "vkCmdSetDeviceMaskKHR", + "vkCmdSetDiscardRectangleEXT", + "vkCmdSetEvent", + "vkCmdSetExclusiveScissorNV", + "vkCmdSetFrontFaceEXT", + "vkCmdSetLineStippleEXT", + "vkCmdSetLineWidth", + "vkCmdSetPerformanceMarkerINTEL", + "vkCmdSetPerformanceOverrideINTEL", + "vkCmdSetPerformanceStreamMarkerINTEL", + "vkCmdSetPrimitiveTopologyEXT", + "vkCmdSetSampleLocationsEXT", + "vkCmdSetScissor", + "vkCmdSetScissorWithCountEXT", + "vkCmdSetStencilCompareMask", + "vkCmdSetStencilOpEXT", + "vkCmdSetStencilReference", + "vkCmdSetStencilTestEnableEXT", + "vkCmdSetStencilWriteMask", + "vkCmdSetViewport", + "vkCmdSetViewportShadingRatePaletteNV", + "vkCmdSetViewportWScalingNV", + "vkCmdSetViewportWithCountEXT", + "vkCmdTraceRaysIndirectKHR", + "vkCmdTraceRaysKHR", + "vkCmdTraceRaysNV", + "vkCmdUpdateBuffer", + "vkCmdWaitEvents", + "vkCmdWriteAccelerationStructuresPropertiesKHR", + "vkCmdWriteAccelerationStructuresPropertiesNV", + "vkCmdWriteBufferMarkerAMD", + "vkCmdWriteTimestamp", + "vkCompileDeferredNV", + "vkCopyAccelerationStructureKHR", + "vkCopyAccelerationStructureToMemoryKHR", + "vkCopyMemoryToAccelerationStructureKHR", + "vkCreateAccelerationStructureKHR", + "vkCreateAccelerationStructureNV", + "vkCreateBuffer", + "vkCreateBufferView", + "vkCreateCommandPool", + "vkCreateComputePipelines", + "vkCreateDeferredOperationKHR", + "vkCreateDescriptorPool", + "vkCreateDescriptorSetLayout", + "vkCreateDescriptorUpdateTemplate", + "vkCreateDescriptorUpdateTemplateKHR", + "vkCreateEvent", + "vkCreateFence", + "vkCreateFramebuffer", + "vkCreateGraphicsPipelines", + "vkCreateImage", + "vkCreateImageView", + "vkCreateIndirectCommandsLayoutNV", + "vkCreatePipelineCache", + "vkCreatePipelineLayout", + "vkCreatePrivateDataSlotEXT", + "vkCreateQueryPool", + "vkCreateRayTracingPipelinesKHR", + "vkCreateRayTracingPipelinesNV", + "vkCreateRenderPass", + "vkCreateRenderPass2", + "vkCreateRenderPass2KHR", + "vkCreateSampler", + "vkCreateSamplerYcbcrConversion", + "vkCreateSamplerYcbcrConversionKHR", + "vkCreateSemaphore", + "vkCreateShaderModule", + "vkCreateSharedSwapchainsKHR", + "vkCreateSwapchainKHR", + "vkCreateValidationCacheEXT", + "vkDebugMarkerSetObjectNameEXT", + "vkDebugMarkerSetObjectTagEXT", + "vkDeferredOperationJoinKHR", + "vkDestroyAccelerationStructureKHR", + "vkDestroyAccelerationStructureNV", + "vkDestroyBuffer", + "vkDestroyBufferView", + "vkDestroyCommandPool", + "vkDestroyDeferredOperationKHR", + "vkDestroyDescriptorPool", + "vkDestroyDescriptorSetLayout", + "vkDestroyDescriptorUpdateTemplate", + "vkDestroyDescriptorUpdateTemplateKHR", + "vkDestroyDevice", + "vkDestroyEvent", + "vkDestroyFence", + "vkDestroyFramebuffer", + "vkDestroyImage", + "vkDestroyImageView", + "vkDestroyIndirectCommandsLayoutNV", + "vkDestroyPipeline", + "vkDestroyPipelineCache", + "vkDestroyPipelineLayout", + "vkDestroyPrivateDataSlotEXT", + "vkDestroyQueryPool", + "vkDestroyRenderPass", + "vkDestroySampler", + "vkDestroySamplerYcbcrConversion", + "vkDestroySamplerYcbcrConversionKHR", + "vkDestroySemaphore", + "vkDestroyShaderModule", + "vkDestroySwapchainKHR", + "vkDestroyValidationCacheEXT", + "vkDeviceWaitIdle", + "vkDisplayPowerControlEXT", + "vkEndCommandBuffer", + "vkFlushMappedMemoryRanges", + "vkFreeCommandBuffers", + "vkFreeDescriptorSets", + "vkFreeMemory", + "vkGetAccelerationStructureDeviceAddressKHR", + "vkGetAccelerationStructureHandleNV", + "vkGetAccelerationStructureMemoryRequirementsKHR", + "vkGetAccelerationStructureMemoryRequirementsNV", + "vkGetAndroidHardwareBufferPropertiesANDROID", + "vkGetBufferDeviceAddress", + "vkGetBufferDeviceAddressEXT", + "vkGetBufferDeviceAddressKHR", + "vkGetBufferMemoryRequirements", + "vkGetBufferMemoryRequirements2", + "vkGetBufferMemoryRequirements2KHR", + "vkGetBufferOpaqueCaptureAddress", + "vkGetBufferOpaqueCaptureAddressKHR", + "vkGetCalibratedTimestampsEXT", + "vkGetDeferredOperationMaxConcurrencyKHR", + "vkGetDeferredOperationResultKHR", + "vkGetDescriptorSetLayoutSupport", + "vkGetDescriptorSetLayoutSupportKHR", + "vkGetDeviceAccelerationStructureCompatibilityKHR", + "vkGetDeviceGroupPeerMemoryFeatures", + "vkGetDeviceGroupPeerMemoryFeaturesKHR", + "vkGetDeviceGroupPresentCapabilitiesKHR", + "vkGetDeviceGroupSurfacePresentModes2EXT", + "vkGetDeviceGroupSurfacePresentModesKHR", + "vkGetDeviceMemoryCommitment", + "vkGetDeviceMemoryOpaqueCaptureAddress", + "vkGetDeviceMemoryOpaqueCaptureAddressKHR", + "vkGetDeviceProcAddr", + "vkGetDeviceQueue", + "vkGetDeviceQueue2", + "vkGetEventStatus", + "vkGetFenceFdKHR", + "vkGetFenceStatus", + "vkGetFenceWin32HandleKHR", + "vkGetGeneratedCommandsMemoryRequirementsNV", + "vkGetImageDrmFormatModifierPropertiesEXT", + "vkGetImageMemoryRequirements", + "vkGetImageMemoryRequirements2", + "vkGetImageMemoryRequirements2KHR", + "vkGetImageSparseMemoryRequirements", + "vkGetImageSparseMemoryRequirements2", + "vkGetImageSparseMemoryRequirements2KHR", + "vkGetImageSubresourceLayout", + "vkGetImageViewAddressNVX", + "vkGetImageViewHandleNVX", + "vkGetMemoryAndroidHardwareBufferANDROID", + "vkGetMemoryFdKHR", + "vkGetMemoryFdPropertiesKHR", + "vkGetMemoryHostPointerPropertiesEXT", + "vkGetMemoryWin32HandleKHR", + "vkGetMemoryWin32HandleNV", + "vkGetMemoryWin32HandlePropertiesKHR", + "vkGetPastPresentationTimingGOOGLE", + "vkGetPerformanceParameterINTEL", + "vkGetPipelineCacheData", + "vkGetPipelineExecutableInternalRepresentationsKHR", + "vkGetPipelineExecutablePropertiesKHR", + "vkGetPipelineExecutableStatisticsKHR", + "vkGetPrivateDataEXT", + "vkGetQueryPoolResults", + "vkGetQueueCheckpointDataNV", + "vkGetRayTracingCaptureReplayShaderGroupHandlesKHR", + "vkGetRayTracingShaderGroupHandlesKHR", + "vkGetRayTracingShaderGroupHandlesNV", + "vkGetRefreshCycleDurationGOOGLE", + "vkGetRenderAreaGranularity", + "vkGetSemaphoreCounterValue", + "vkGetSemaphoreCounterValueKHR", + "vkGetSemaphoreFdKHR", + "vkGetSemaphoreWin32HandleKHR", + "vkGetShaderInfoAMD", + "vkGetSwapchainCounterEXT", + "vkGetSwapchainImagesKHR", + "vkGetSwapchainStatusKHR", + "vkGetValidationCacheDataEXT", + "vkImportFenceFdKHR", + "vkImportFenceWin32HandleKHR", + "vkImportSemaphoreFdKHR", + "vkImportSemaphoreWin32HandleKHR", + "vkInitializePerformanceApiINTEL", + "vkInvalidateMappedMemoryRanges", + "vkMapMemory", + "vkMergePipelineCaches", + "vkMergeValidationCachesEXT", + "vkQueueBeginDebugUtilsLabelEXT", + "vkQueueBindSparse", + "vkQueueEndDebugUtilsLabelEXT", + "vkQueueInsertDebugUtilsLabelEXT", + "vkQueuePresentKHR", + "vkQueueSetPerformanceConfigurationINTEL", + "vkQueueSubmit", + "vkQueueWaitIdle", + "vkRegisterDeviceEventEXT", + "vkRegisterDisplayEventEXT", + "vkReleaseFullScreenExclusiveModeEXT", + "vkReleasePerformanceConfigurationINTEL", + "vkReleaseProfilingLockKHR", + "vkResetCommandBuffer", + "vkResetCommandPool", + "vkResetDescriptorPool", + "vkResetEvent", + "vkResetFences", + "vkResetQueryPool", + "vkResetQueryPoolEXT", + "vkSetDebugUtilsObjectNameEXT", + "vkSetDebugUtilsObjectTagEXT", + "vkSetEvent", + "vkSetHdrMetadataEXT", + "vkSetLocalDimmingAMD", + "vkSetPrivateDataEXT", + "vkSignalSemaphore", + "vkSignalSemaphoreKHR", + "vkTrimCommandPool", + "vkTrimCommandPoolKHR", + "vkUninitializePerformanceApiINTEL", + "vkUnmapMemory", + "vkUpdateDescriptorSetWithTemplate", + "vkUpdateDescriptorSetWithTemplateKHR", + "vkUpdateDescriptorSets", + "vkWaitForFences", + "vkWaitSemaphores", + "vkWaitSemaphoresKHR", + "vkWriteAccelerationStructuresPropertiesKHR", + }}; + /* Exists as a workaround for: + * https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/issues/2323 + * + * `vkGetDeviceProcAddr` does not return NULL for non-device functions. + */ + if (!get_device_proc_addr && instance) + { + get_device_proc_addr = (PFN_vkGetDeviceProcAddr) + get_instance_proc_addr(instance, "vkGetDeviceProcAddr"); + if (user_ptr) + { + ((GE_VK_UserPointer*)user_ptr)->get_device_proc_addr = + get_device_proc_addr; + } + } + if (device && get_device_proc_addr && + device_function.find(name) != device_function.end()) + { + PFN_vkVoidFunction ret = get_device_proc_addr(device, name); + if (ret) + return ret; + } + + // Workaround for android vulkan driver return NULL function pointer with + // non-NULL instance + // See https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetInstanceProcAddr.html + // Also slient the warnings when loading with NULL instance in android + if (strcmp(name, "vkGetInstanceProcAddr") == 0) + return (PFN_vkVoidFunction)get_instance_proc_addr; + static std::set instance_function = + {{ + "vkEnumerateInstanceVersion", + "vkEnumerateInstanceExtensionProperties", + "vkEnumerateInstanceLayerProperties", + "vkCreateInstance", + }}; + if (instance_function.find(name) != instance_function.end()) + return get_instance_proc_addr(NULL, name); + else if (instance == VK_NULL_HANDLE && + instance_function.find(name) == instance_function.end()) + return NULL; + return get_instance_proc_addr(instance, name); +} // loader + +namespace GE +{ +GEVulkanDriver::GEVulkanDriver(const SIrrlichtCreationParameters& params, + io::IFileSystem* io, SDL_Window* window) + : CNullDriver(io, core::dimension2d(0, 0)) +{ + m_physical_device = VK_NULL_HANDLE; + m_graphics_queue = VK_NULL_HANDLE; + m_present_queue = VK_NULL_HANDLE; + m_graphics_family = m_present_family = 0; + m_properties = {}; + m_features = {}; + + createInstance(window); + + GE_VK_UserPointer user_ptr = {}; + user_ptr.instance = m_vk.instance; + if (gladLoadVulkanUserPtr(NULL, + (GLADuserptrloadfunc)loader, &user_ptr) == 0) + { + throw std::runtime_error("gladLoadVulkanUserPtr failed " + "with non-NULL instance"); + } + if (SDL_Vulkan_CreateSurface(window, m_vk.instance, &m_vk.surface) == SDL_FALSE) + throw std::runtime_error("SDL_Vulkan_CreateSurface failed"); + m_device_extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + findPhysicalDevice(); + createDevice(); + + user_ptr.device = m_vk.device; + if (gladLoadVulkanUserPtr(m_physical_device, + (GLADuserptrloadfunc)loader, &user_ptr) == 0) + { + throw std::runtime_error("gladLoadVulkanUserPtr failed with " + "non-NULL instance and non-NULL m_physical_device"); + } + + vkGetPhysicalDeviceProperties(m_physical_device, &m_properties); + os::Printer::log("Vulkan version", getVulkanVersionString().c_str()); + os::Printer::log("Vulkan vendor", getVendorInfo().c_str()); + os::Printer::log("Vulkan renderer", m_properties.deviceName); + os::Printer::log("Vulkan driver version", getDriverVersionString().c_str()); + for (const char* ext : m_device_extensions) + os::Printer::log("Vulkan enabled extension", ext); +} // GEVulkanDriver + +// ---------------------------------------------------------------------------- +GEVulkanDriver::~GEVulkanDriver() +{ +} // ~GEVulkanDriver + +// ---------------------------------------------------------------------------- +void GEVulkanDriver::createInstance(SDL_Window* window) +{ + if (gladLoadVulkanUserPtr(NULL, (GLADuserptrloadfunc)loader, NULL) == 0) + { + throw std::runtime_error("gladLoadVulkanUserPtr failed 1st time"); + } + unsigned int count = 0; + if (!SDL_Vulkan_GetInstanceExtensions(window, &count, NULL)) + throw std::runtime_error("SDL_Vulkan_GetInstanceExtensions failed with NULL extensions"); + std::vector extensions(count, NULL); + if (!SDL_Vulkan_GetInstanceExtensions(window, &count, extensions.data())) + throw std::runtime_error("SDL_Vulkan_GetInstanceExtensions failed with extensions vector"); + VkInstanceCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + create_info.enabledExtensionCount = extensions.size(); + create_info.ppEnabledExtensionNames = extensions.data(); + VkResult result = vkCreateInstance(&create_info, NULL, &m_vk.instance); + if (result != VK_SUCCESS) + throw std::runtime_error("vkCreateInstance failed"); +} // createInstance + +// ---------------------------------------------------------------------------- +void GEVulkanDriver::findPhysicalDevice() +{ + uint32_t device_count = 0; + vkEnumeratePhysicalDevices(m_vk.instance, &device_count, NULL); + + if (device_count < 1) + throw std::runtime_error("findPhysicalDevice has < 1 device_count"); + + std::vector devices(device_count); + vkEnumeratePhysicalDevices(m_vk.instance, &device_count, &devices[0]); + + for (VkPhysicalDevice& device : devices) + { + uint32_t graphics_family = 0; + uint32_t present_family = 0; + + bool success = findQueueFamilies(device, &graphics_family, &present_family); + + if (!success) + continue; + + success = checkDeviceExtensions(device); + + if (!success) + continue; + + VkSurfaceCapabilitiesKHR surface_capabilities; + std::vector surface_formats; + std::vector present_modes; + + success = updateSurfaceInformation(device, &surface_capabilities, + &surface_formats, &present_modes); + + if (!success) + continue; + + vkGetPhysicalDeviceFeatures(device, &m_features); + m_graphics_family = graphics_family; + m_present_family = present_family; + m_surface_capabilities = surface_capabilities; + m_surface_formats = surface_formats; + m_present_modes = present_modes; + m_physical_device = device; + break; + } + + if (m_physical_device == VK_NULL_HANDLE) + throw std::runtime_error("findPhysicalDevice m_physical_device is VK_NULL_HANDLE"); +} // findPhysicalDevice + +// ---------------------------------------------------------------------------- +bool GEVulkanDriver::checkDeviceExtensions(VkPhysicalDevice device) +{ + uint32_t extension_count; + vkEnumerateDeviceExtensionProperties(device, NULL, &extension_count, NULL); + + std::vector extensions(extension_count); + vkEnumerateDeviceExtensionProperties(device, NULL, &extension_count, + &extensions[0]); + + std::set required_extensions(m_device_extensions.begin(), + m_device_extensions.end()); + + for (VkExtensionProperties& extension : extensions) + required_extensions.erase(extension.extensionName); + + return required_extensions.empty(); +} // checkDeviceExtensions + +// ---------------------------------------------------------------------------- +bool GEVulkanDriver::updateSurfaceInformation(VkPhysicalDevice device, + VkSurfaceCapabilitiesKHR* surface_capabilities, + std::vector* surface_formats, + std::vector* present_modes) +{ + uint32_t format_count; + vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_vk.surface, &format_count, NULL); + + if (format_count < 1) + return false; + + uint32_t mode_count; + vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_vk.surface, &mode_count, NULL); + + if (mode_count < 1) + return false; + + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, m_vk.surface, surface_capabilities); + + (*surface_formats).resize(format_count); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, m_vk.surface, &format_count, + &(*surface_formats)[0]); + + (*present_modes).resize(mode_count); + vkGetPhysicalDeviceSurfacePresentModesKHR(device, m_vk.surface, &mode_count, + &(*present_modes)[0]); + + return true; +} // updateSurfaceInformation + +// ---------------------------------------------------------------------------- +bool GEVulkanDriver::findQueueFamilies(VkPhysicalDevice device, + uint32_t* graphics_family, + uint32_t* present_family) +{ + uint32_t queue_family_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, NULL); + if (queue_family_count == 0) + return false; + + std::vector queue_families(queue_family_count); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, + &queue_families[0]); + + bool found_graphics_family = false; + bool found_present_family = false; + + for (unsigned int i = 0; i < queue_families.size(); i++) + { + if (queue_families[i].queueCount > 0 && + queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) + { + *graphics_family = i; + found_graphics_family = true; + break; + } + } + + for (unsigned int i = 0; i < queue_families.size(); i++) + { + VkBool32 present_support = false; + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, m_vk.surface, &present_support); + + if (queue_families[i].queueCount > 0 && present_support) + { + *present_family = i; + found_present_family = true; + break; + } + } + + return found_graphics_family && found_present_family; +} // findQueueFamilies + +// ---------------------------------------------------------------------------- +void GEVulkanDriver::createDevice() +{ + std::vector queue_create_infos; + float queue_priority = 1.0f; + + VkDeviceQueueCreateInfo queue_create_info = {}; + queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_info.queueFamilyIndex = m_graphics_family; + queue_create_info.queueCount = 1; + queue_create_info.pQueuePriorities = &queue_priority; + queue_create_infos.push_back(queue_create_info); + + queue_create_info.queueFamilyIndex = m_present_family; + queue_create_infos.push_back(queue_create_info); + + VkPhysicalDeviceFeatures device_features = {}; + if (m_features.samplerAnisotropy == VK_TRUE) + device_features.samplerAnisotropy = VK_TRUE; + + VkDeviceCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + create_info.queueCreateInfoCount = queue_create_infos.size(); + create_info.pQueueCreateInfos = &queue_create_infos[0]; + create_info.pEnabledFeatures = &device_features; + create_info.enabledExtensionCount = m_device_extensions.size(); + create_info.ppEnabledExtensionNames = &m_device_extensions[0]; + create_info.enabledLayerCount = 0; + + VkResult result = vkCreateDevice(m_physical_device, &create_info, NULL, &m_vk.device); + + if (result != VK_SUCCESS) + throw std::runtime_error("vkCreateDevice failed"); + + vkGetDeviceQueue(m_vk.device, m_graphics_family, 0, &m_graphics_queue); + vkGetDeviceQueue(m_vk.device, m_present_family, 0, &m_present_queue); +} // createDevice + +// ---------------------------------------------------------------------------- +std::string GEVulkanDriver::getVulkanVersionString() const +{ + std::stringstream vk_version; + vk_version << VK_VERSION_MAJOR(m_properties.apiVersion) << "." << + VK_VERSION_MINOR(m_properties.apiVersion) << "." << + VK_VERSION_PATCH(m_properties.apiVersion); + return vk_version.str(); +} // getVulkanVersionString + +// ---------------------------------------------------------------------------- +std::string GEVulkanDriver::getDriverVersionString() const +{ +#ifdef WIN32 + bool is_win = true; +#else + bool is_win = false; +#endif + + std::stringstream driver_version; + // Following https://github.com/SaschaWillems/vulkan.gpuinfo.org/blob/master/includes/functions.php + if (m_properties.vendorID == 0x10DE) + { + // NVIDIA + driver_version << ((m_properties.driverVersion >> 22) & 0x3ff) << "." << + ((m_properties.driverVersion >> 14) & 0xff) << "." << + ((m_properties.driverVersion >> 6) & 0xff) << "." << + (m_properties.driverVersion & 0x3f); + } + else if (m_properties.vendorID == 0x8086 && is_win) + { + // Intel on Windows + driver_version << (m_properties.driverVersion >> 14) << "." << + (m_properties.driverVersion & 0x3fff); + } + else + { + // Use Vulkan version conventions if vendor mapping is not available + driver_version << VK_VERSION_MAJOR(m_properties.driverVersion) << "." << + VK_VERSION_MINOR(m_properties.driverVersion) << "." << + VK_VERSION_PATCH(m_properties.driverVersion); + } + return driver_version.str(); +} // getDriverVersionString + +} + +namespace irr +{ +namespace video +{ + IVideoDriver* createVulkanDriver(const SIrrlichtCreationParameters& params, + io::IFileSystem* io, SDL_Window* window) + { + return new GE::GEVulkanDriver(params, io, window); + } // createVulkanDriver +} +} +#endif diff --git a/lib/irrlicht/CMakeLists.txt b/lib/irrlicht/CMakeLists.txt index 6a70dc33a..bbcb96a94 100644 --- a/lib/irrlicht/CMakeLists.txt +++ b/lib/irrlicht/CMakeLists.txt @@ -7,7 +7,8 @@ if(NOT SERVER_ONLY) "${JPEG_INCLUDE_DIR}" "${PNG_INCLUDE_DIRS}" "${ZLIB_INCLUDE_DIR}" - "${CMAKE_CURRENT_SOURCE_DIR}/../../src") + "${CMAKE_CURRENT_SOURCE_DIR}/../../src" + "${CMAKE_CURRENT_SOURCE_DIR}/../graphics_engine/include") else() include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include/" "${CMAKE_CURRENT_SOURCE_DIR}/../../src") @@ -25,6 +26,8 @@ else() add_definitions(-DNO_IRR_COMPILE_WITH_X11_) add_definitions(-DNO_IRR_COMPILE_WITH_WAYLAND_DEVICE_) add_definitions(-DNO_IRR_COMPILE_WITH_SDL_DEVICE_) + add_definitions(-DNO_IRR_COMPILE_WITH_DIRECT3D_9_) + add_definitions(-DNO_IRR_COMPILE_WITH_VULKAN_) endif() if(APPLE AND NOT IOS) diff --git a/lib/irrlicht/include/EDriverTypes.h b/lib/irrlicht/include/EDriverTypes.h index c6df53458..2815c5534 100644 --- a/lib/irrlicht/include/EDriverTypes.h +++ b/lib/irrlicht/include/EDriverTypes.h @@ -56,6 +56,9 @@ namespace video /** Supports shaders etc. */ EDT_OGLES2, + //! A driver using vulkan coded by STK + EDT_VULKAN, + //! No driver, just for counting the elements EDT_COUNT }; diff --git a/lib/irrlicht/include/IrrCompileConfig.h b/lib/irrlicht/include/IrrCompileConfig.h index ea9097045..384c6836e 100644 --- a/lib/irrlicht/include/IrrCompileConfig.h +++ b/lib/irrlicht/include/IrrCompileConfig.h @@ -43,6 +43,11 @@ //! different library versions without having to change the sources. //! Example: NO_IRR_COMPILE_WITH_X11_ would disable X11 +#if defined(NO_IRR_COMPILE_WITH_VULKAN_) +#undef _IRR_COMPILE_WITH_VULKAN_ +#else +#define _IRR_COMPILE_WITH_VULKAN_ +#endif //! Uncomment this line to compile with the SDL device //#define _IRR_COMPILE_WITH_SDL_DEVICE_ diff --git a/lib/irrlicht/include/IrrlichtDevice.h b/lib/irrlicht/include/IrrlichtDevice.h index 6bf2a2d27..983990eb1 100644 --- a/lib/irrlicht/include/IrrlichtDevice.h +++ b/lib/irrlicht/include/IrrlichtDevice.h @@ -362,6 +362,12 @@ namespace irr return true; #else return false; +#endif + case video::EDT_VULKAN: +#ifdef _IRR_COMPILE_WITH_VULKAN_ + return true; +#else + return false; #endif default: return false; diff --git a/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp b/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp index e0a9d4988..1adf2bcb2 100644 --- a/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp +++ b/lib/irrlicht/source/Irrlicht/CIrrDeviceSDL.cpp @@ -36,6 +36,10 @@ namespace irr #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ IVideoDriver* createDirectX9Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io, HWND window); +#endif +#ifdef _IRR_COMPILE_WITH_VULKAN_ + IVideoDriver* createVulkanDriver(const SIrrlichtCreationParameters& params, + io::IFileSystem* io, SDL_Window* win); #endif } // end namespace video @@ -354,6 +358,8 @@ bool CIrrDeviceSDL::createWindow() if (CreationParams.DriverType == video::EDT_OPENGL || CreationParams.DriverType == video::EDT_OGLES2) flags |= SDL_WINDOW_OPENGL; + else if (CreationParams.DriverType == video::EDT_VULKAN) + flags |= SDL_WINDOW_VULKAN; #ifdef MOBILE_STK flags |= SDL_WINDOW_BORDERLESS | SDL_WINDOW_MAXIMIZED; @@ -580,6 +586,23 @@ void CIrrDeviceSDL::createDriver() break; } + case video::EDT_VULKAN: + { + #ifdef _IRR_COMPILE_WITH_VULKAN_ + try + { + VideoDriver = video::createVulkanDriver(CreationParams, FileSystem, Window); + } + catch (std::exception& e) + { + os::Printer::log("createVulkanDriver failed", e.what(), ELL_ERROR); + } + #else + os::Printer::log("No Vulkan support compiled in.", ELL_ERROR); + #endif + break; + } + case video::EDT_DIRECT3D9: { #ifdef _IRR_COMPILE_WITH_DIRECT3D_9_ diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index 422ebadc1..ec6fa2d6f 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -402,6 +402,10 @@ void IrrDriver::initDevice() { driver_created = video::EDT_DIRECT3D9; } + else if (std::string(UserConfigParams::m_render_driver) == "vulkan") + { + driver_created = video::EDT_VULKAN; + } else { Log::warn("IrrDriver", "Unknown driver %s, revert to gl", @@ -414,6 +418,7 @@ void IrrDriver::initDevice() #endif } + m_logger_level = irr::ELL_INFORMATION; #ifndef __SWITCH__ // If --no-graphics option was used, the null device can still be used. if (!GUIEngine::isNoGraphics()) @@ -633,6 +638,7 @@ void IrrDriver::initDevice() CVS->init(); } #endif + m_logger_level = irr::ELL_WARNING; m_scene_manager = m_device->getSceneManager(); m_gui_env = m_device->getGUIEnvironment();