diff --git a/build/scripts/tools/vulkanrenderer.lua b/build/scripts/tools/vulkanrenderer.lua new file mode 100644 index 000000000..8ecca1f2b --- /dev/null +++ b/build/scripts/tools/vulkanrenderer.lua @@ -0,0 +1,50 @@ +TOOL.Name = "VulkanRenderer" + +TOOL.ClientOnly = true + +TOOL.Kind = "Library" +TOOL.TargetDirectory = "../lib" + +TOOL.Defines = { + "NAZARA_BUILD", + "NAZARA_VULKANRENDERER_BUILD" +} + +TOOL.Includes = { + "../include", + "../src/", + "../extlibs/include" +} + +TOOL.Files = { + "../include/Nazara/VulkanRenderer/**.hpp", + "../include/Nazara/VulkanRenderer/**.inl", + "../src/Nazara/VulkanRenderer/**.hpp", + "../src/Nazara/VulkanRenderer/**.inl", + "../src/Nazara/VulkanRenderer/**.cpp" +} + +TOOL.Libraries = { + "NazaraCore", + "NazaraRenderer", + "NazaraUtility" +} + +TOOL.OsDefines.Linux = { +-- "VK_USE_PLATFORM_MIR_KHR", + "VK_USE_PLATFORM_XCB_KHR" +-- "VK_USE_PLATFORM_XLIB_KHR", +-- "VK_USE_PLATFORM_WAYLAND_KHR" +} + +TOOL.OsDefines.BSD = TOOL.OsDefines.Linux +TOOL.OsDefines.Solaris = TOOL.OsDefines.Linux + +TOOL.OsDefines.Windows = { + "VK_USE_PLATFORM_WIN32_KHR" +} + +TOOL.OsFiles.Windows = { + "../src/Nazara/VulkanRenderer/Win32/**.hpp", + "../src/Nazara/VulkanRenderer/Win32/**.cpp" +} diff --git a/include/Nazara/Renderer/Context.hpp b/include/Nazara/Renderer/Context.hpp deleted file mode 100644 index 4bfb7b1b0..000000000 --- a/include/Nazara/Renderer/Context.hpp +++ /dev/null @@ -1,80 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_CONTEXT_HPP -#define NAZARA_CONTEXT_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - class Context; - - using ContextConstRef = ObjectRef; - using ContextLibrary = ObjectLibrary; - using ContextRef = ObjectRef; - - class ContextImpl; - - class NAZARA_RENDERER_API Context : public RefCounted - { - friend ContextImpl; - friend ContextLibrary; - friend class OpenGL; - - public: - Context() = default; - Context(const Context&) = delete; - Context(Context&&) = delete; - ~Context(); - - bool Create(const ContextParameters& parameters = ContextParameters()); - - void Destroy(); - - void EnableVerticalSync(bool enabled); - - const ContextParameters& GetParameters() const; - - bool IsActive() const; - - bool SetActive(bool active) const; - void SwapBuffers(); - - Context& operator=(const Context&) = delete; - Context& operator=(Context&&) = delete; - - static bool EnsureContext(); - - static const Context* GetCurrent(); - static const Context* GetReference(); - static const Context* GetThreadContext(); - - // Signals: - NazaraSignal(OnContextDestroy, const Context* /*context*/); - NazaraSignal(OnContextRelease, const Context* /*context*/); - - private: - static bool Initialize(); - static void Uninitialize(); - - ContextParameters m_parameters; - ContextImpl* m_impl = nullptr; - - static std::unique_ptr s_reference; - static std::vector> s_contexts; - static ContextLibrary::LibraryMap s_library; - }; -} - -#endif // NAZARA_CONTEXT_HPP diff --git a/include/Nazara/Renderer/ContextParameters.hpp b/include/Nazara/Renderer/ContextParameters.hpp deleted file mode 100644 index ddfc76ea3..000000000 --- a/include/Nazara/Renderer/ContextParameters.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_CONTEXTPARAMETERS_HPP -#define NAZARA_CONTEXTPARAMETERS_HPP - -#include -#include -#include -#include - -namespace Nz -{ - class Context; - - struct NAZARA_RENDERER_API ContextParameters - { - ContextParameters(const RenderTargetParameters& parameters = RenderTargetParameters()) : - antialiasingLevel(parameters.antialiasingLevel), - bitsPerPixel(VideoMode::GetDesktopMode().bitsPerPixel), - depthBits(parameters.depthBits), - majorVersion(defaultMajorVersion), - minorVersion(defaultMinorVersion), - stencilBits(parameters.stencilBits), - shareContext(defaultShareContext), - window(0), - compatibilityProfile(defaultCompatibilityProfile), - debugMode(defaultDebugMode), - doubleBuffered(defaultDoubleBuffered), - shared(defaultShared) - { - } - - UInt8 antialiasingLevel; - UInt8 bitsPerPixel; - UInt8 depthBits; - UInt8 majorVersion; - UInt8 minorVersion; - UInt8 stencilBits; - const Context* shareContext; - WindowHandle window; - bool compatibilityProfile; - bool debugMode; - bool doubleBuffered; - bool shared; - - static UInt8 defaultMajorVersion; - static UInt8 defaultMinorVersion; - static const Context* defaultShareContext; - static bool defaultCompatibilityProfile; - static bool defaultDebugMode; - static bool defaultDoubleBuffered; - static bool defaultShared; - }; -} - -#endif // NAZARA_CONTEXTPARAMETERS_HPP diff --git a/include/Nazara/Renderer/DebugDrawer.hpp b/include/Nazara/Renderer/DebugDrawer.hpp deleted file mode 100644 index 7880a1ae4..000000000 --- a/include/Nazara/Renderer/DebugDrawer.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_DEBUGDRAWER_HPP -#define NAZARA_DEBUGDRAWER_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - class Skeleton; - - class NAZARA_RENDERER_API DebugDrawer - { - public: - static void Draw(const BoundingVolumef& volume); - static void Draw(const Boxf& box); - static void Draw(const Boxi& box); - static void Draw(const Boxui& box); - static void Draw(const Frustumf& frustum); - static void Draw(const OrientedBoxf& orientedBox); - static void Draw(const Skeleton* skeleton); - static void Draw(const Vector3f& position, float size = 0.1f); - static void DrawAxes(const Vector3f& position = Vector3f::Zero(), float size = 1.f); - static void DrawBinormals(const StaticMesh* subMesh); - static void DrawCone(const Vector3f& origin, const Quaternionf& rotation, float angle, float length); - static void DrawLine(const Vector3f& p1, const Vector3f& p2); - static void DrawPoints(const Vector3f* ptr, unsigned int pointCount); - static void DrawNormals(const StaticMesh* subMesh); - static void DrawTangents(const StaticMesh* subMesh); - - static void EnableDepthBuffer(bool depthBuffer); - - static float GetLineWidth(); - static float GetPointSize(); - static Color GetPrimaryColor(); - static Color GetSecondaryColor(); - - static bool Initialize(); - static bool IsDepthBufferEnabled(); - - static void SetLineWidth(float width); - static void SetPointSize(float size); - static void SetPrimaryColor(const Color& color); - static void SetSecondaryColor(const Color& color); - - static void Uninitialize(); - }; -} - -#endif // NAZARA_DEBUG_DRAWER_HPP diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp index 2d0e6d3a7..b610d43b3 100644 --- a/include/Nazara/Renderer/Enums.hpp +++ b/include/Nazara/Renderer/Enums.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2015 Jérôme Leclercq +// Copyright (C) 2016 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -9,114 +9,29 @@ namespace Nz { - enum AttachmentPoint + enum RenderAPI { - AttachmentPoint_Color, - AttachmentPoint_Depth, - AttachmentPoint_DepthStencil, - AttachmentPoint_Stencil, + RenderAPI_Direct3D, ///< Microsoft Render API, only works on MS platforms + RenderAPI_Mantle, ///< AMD Render API, Vulkan predecessor, only works on AMD GPUs + RenderAPI_Metal, ///< Apple Render API, only works on OS X platforms + RenderAPI_OpenGL, ///< Khronos Render API, works on Web/Desktop/Mobile and some consoles + RenderAPI_Vulkan, ///< New Khronos Render API, made to replace OpenGL, works on desktop (Windows/Linux) and mobile (Android) - AttachmentPoint_Max = AttachmentPoint_Stencil + RenderAPI_Other, ///< RenderAPI not corresponding to an entry of the enum, or result of a failed query + + RenderAPI_Max = RenderAPI_Other }; - enum GpuQueryCondition + enum RenderDeviceType { - GpuQueryCondition_Region_NoWait, - GpuQueryCondition_Region_Wait, - GpuQueryCondition_NoWait, - GpuQueryCondition_Wait, + RenderDeviceType_Integrated, ///< Hardware-accelerated chipset integrated to a CPU (ex: Intel Graphics HD 4000) + RenderDeviceType_Dedicated, ///< Hardware-accelerated GPU (ex: AMD R9 390) + RenderDeviceType_Software, ///< Software-renderer + RenderDeviceType_Virtual, ///< Proxy renderer relaying instructions to another unknown device - GpuQueryCondition_Max = GpuQueryCondition_Wait - }; + RenderDeviceType_Unknown, ///< Device type not corresponding to an entry of the enum, or result of a failed query - enum GpuQueryMode - { - GpuQueryMode_AnySamplesPassed, - GpuQueryMode_AnySamplesPassedConservative, - GpuQueryMode_PrimitiveGenerated, - GpuQueryMode_SamplesPassed, - GpuQueryMode_TimeElapsed, - GpuQueryMode_TransformFeedbackPrimitivesWritten, - - GpuQueryMode_Max = GpuQueryMode_TransformFeedbackPrimitivesWritten - }; - - enum MatrixType - { - // Matrices de base - MatrixType_Projection, - MatrixType_View, - MatrixType_World, - - // Matrices combinées - MatrixType_ViewProj, - MatrixType_WorldView, - MatrixType_WorldViewProj, - - // Matrice inversées - MatrixType_InvProjection, - MatrixType_InvView, - MatrixType_InvViewProj, - MatrixType_InvWorld, - MatrixType_InvWorldView, - MatrixType_InvWorldViewProj, - - MatrixType_Max = MatrixType_InvWorldViewProj - }; - - enum PixelBufferType - { - PixelBufferType_Pack, - PixelBufferType_Unpack, - - PixelBufferType_Max = PixelBufferType_Unpack - }; - - enum RendererCap - { - RendererCap_AnisotropicFilter, - RendererCap_FP64, - RendererCap_Instancing, - - RendererCap_Max = RendererCap_Instancing - }; - - enum RendererBufferFlags - { - RendererBuffer_Color = 0x1, - RendererBuffer_Depth = 0x2, - RendererBuffer_Stencil = 0x4, - - RendererBuffer_Max = RendererBuffer_Stencil*2-1 - }; - - enum ShaderUniform - { - ShaderUniform_InvProjMatrix, - ShaderUniform_InvTargetSize, - ShaderUniform_InvViewMatrix, - ShaderUniform_InvViewProjMatrix, - ShaderUniform_InvWorldMatrix, - ShaderUniform_InvWorldViewMatrix, - ShaderUniform_InvWorldViewProjMatrix, - ShaderUniform_ProjMatrix, - ShaderUniform_TargetSize, - ShaderUniform_ViewMatrix, - ShaderUniform_ViewProjMatrix, - ShaderUniform_WorldMatrix, - ShaderUniform_WorldViewMatrix, - ShaderUniform_WorldViewProjMatrix, - - ShaderUniform_Max = ShaderUniform_WorldViewProjMatrix - }; - - enum ShaderStageType - { - ShaderStageType_Fragment, - ShaderStageType_Geometry, - ShaderStageType_Vertex, - - ShaderStageType_Max = ShaderStageType_Vertex + RenderDeviceType_Max = RenderDeviceType_Unknown }; } diff --git a/include/Nazara/Renderer/GpuQuery.hpp b/include/Nazara/Renderer/GpuQuery.hpp deleted file mode 100644 index 87b758966..000000000 --- a/include/Nazara/Renderer/GpuQuery.hpp +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_GPUQUERY_HPP -#define NAZARA_GPUQUERY_HPP - -#include -#include -#include - -namespace Nz -{ - class NAZARA_RENDERER_API GpuQuery - { - public: - GpuQuery(); - GpuQuery(const GpuQuery&) = delete; - GpuQuery(GpuQuery&&) = delete; ///TODO - ~GpuQuery(); - - void Begin(GpuQueryMode mode); - void End(); - - unsigned int GetResult() const; - - bool IsResultAvailable() const; - - // Fonctions OpenGL - unsigned int GetOpenGLID() const; - - GpuQuery& operator=(const GpuQuery&) = delete; - GpuQuery& operator=(GpuQuery&&) = delete; ///TODO - - static bool IsModeSupported(GpuQueryMode mode); - static bool IsSupported(); - - private: - GpuQueryMode m_mode; - unsigned int m_id; - }; -} - -#endif // NAZARA_GPUQUERY_HPP diff --git a/include/Nazara/Renderer/OpenGL.hpp b/include/Nazara/Renderer/OpenGL.hpp deleted file mode 100644 index d008b52f4..000000000 --- a/include/Nazara/Renderer/OpenGL.hpp +++ /dev/null @@ -1,346 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_OPENGL_HPP -#define NAZARA_OPENGL_HPP - -#ifdef NAZARA_RENDERER_OPENGL - -#include -#include -#include -#include -#include -#include - -// Inclusion des headers OpenGL -#include -#include -#if defined(NAZARA_PLATFORM_WINDOWS) - #include -#elif defined(NAZARA_PLATFORM_GLX) -namespace GLX -{ - #include // Defined in a namespace to avoid conflict -} - #include -#endif - -namespace Nz -{ - enum OpenGLExtension - { - OpenGLExtension_AnisotropicFilter, - OpenGLExtension_DebugOutput, - OpenGLExtension_FP64, - OpenGLExtension_GetProgramBinary, - OpenGLExtension_SeparateShaderObjects, - OpenGLExtension_Shader_ImageLoadStore, - OpenGLExtension_TextureCompression_s3tc, - OpenGLExtension_TextureStorage, - - OpenGLExtension_Max = OpenGLExtension_TextureStorage - }; - - class Context; - class RenderTarget; - - using OpenGLFunc = void (*)(); - - class NAZARA_RENDERER_API OpenGL - { - friend Context; - - public: - enum FormatType - { - FormatType_RenderBuffer, -// FormatType_MultisampleTexture, - FormatType_Texture - }; - - struct Format - { - GLenum dataFormat; - GLenum dataType; - GLint internalFormat; - GLint swizzle[4]; - }; - - OpenGL() = delete; - ~OpenGL() = delete; - - static void ApplyStates(const RenderStates& states); - - static void BindBuffer(BufferType type, GLuint id); - static void BindProgram(GLuint id); - static void BindSampler(GLuint unit, GLuint id); - static void BindScissorBox(const Recti& scissorBox); - static void BindTexture(ImageType type, GLuint id); - static void BindTexture(unsigned int textureUnit, ImageType type, GLuint id); - static void BindTextureUnit(unsigned int textureUnit); - static void BindViewport(const Recti& viewport); - - static void DeleteBuffer(BufferType type, GLuint id); - static void DeleteFrameBuffer(const Context* context, GLuint id); - static void DeleteProgram(GLuint id); - static void DeleteSampler(GLuint id); - static void DeleteTexture(GLuint id); - static void DeleteVertexArray(const Context* context, GLuint id); - - static GLuint GetCurrentBuffer(BufferType type); - static GLuint GetCurrentProgram(); - static Recti GetCurrentScissorBox(); - static const RenderTarget* GetCurrentTarget(); - static GLuint GetCurrentTexture(); - static GLuint GetCurrentTexture(unsigned int textureUnit); - static unsigned int GetCurrentTextureUnit(); - static Recti GetCurrentViewport(); - - static OpenGLFunc GetEntry(const String& entryPoint); - static unsigned int GetGLSLVersion(); - static String GetRendererName(); - static String GetVendorName(); - static unsigned int GetVersion(); - - static bool Initialize(); - - static bool IsInitialized(); - static bool IsSupported(OpenGLExtension extension); - static bool IsSupported(const String& string); - - static void SetBuffer(BufferType type, GLuint id); - static void SetProgram(GLuint id); - static void SetScissorBox(const Recti& scissorBox); - static void SetTarget(const RenderTarget* renderTarget); - static void SetTexture(GLuint id); - static void SetTexture(unsigned int textureUnit, GLuint id); - static void SetTextureUnit(unsigned int textureUnit); - static void SetViewport(const Recti& viewport); - - static bool TranslateFormat(PixelFormatType pixelFormat, Format* format, FormatType target); - - static void Uninitialize(); - - static GLenum Attachment[AttachmentPoint_Max+1]; - static GLenum BlendFunc[BlendFunc_Max+1]; - static GLenum BufferLock[BufferAccess_Max+1]; - static GLenum BufferLockRange[BufferAccess_Max+1]; - static GLenum BufferTarget[BufferType_Max+1]; - static GLenum BufferTargetBinding[BufferType_Max+1]; - static GLenum BufferUsage[BufferUsage_Max+1]; - static GLenum ComponentType[ComponentType_Max+1]; - static GLenum CubemapFace[6]; // Un cube possède six faces et ça n'est pas près de changer - static GLenum FaceFilling[FaceFilling_Max+1]; - static GLenum FaceSide[FaceSide_Max+1]; - static GLenum PrimitiveMode[PrimitiveMode_Max+1]; - static GLenum QueryCondition[GpuQueryCondition_Max+1]; - static GLenum QueryMode[GpuQueryMode_Max+1]; - static GLenum RendererComparison[RendererComparison_Max+1]; - static GLenum RendererParameter[RendererParameter_Max+1]; - static GLenum SamplerWrapMode[SamplerWrap_Max+1]; - static GLenum ShaderStage[ShaderStageType_Max+1]; - static GLenum StencilOperation[StencilOperation_Max+1]; - static GLenum TextureTarget[ImageType_Max+1]; - static GLenum TextureTargetBinding[ImageType_Max+1]; - static GLenum TextureTargetProxy[ImageType_Max+1]; - static UInt8 VertexComponentIndex[VertexComponent_Max+1]; - - private: - static void OnContextChanged(const Context* newContext); - static void OnContextDestruction(const Context* context); - }; - -NAZARA_RENDERER_API extern PFNGLACTIVETEXTUREPROC glActiveTexture; -NAZARA_RENDERER_API extern PFNGLATTACHSHADERPROC glAttachShader; -NAZARA_RENDERER_API extern PFNGLBEGINCONDITIONALRENDERPROC glBeginConditionalRender; -NAZARA_RENDERER_API extern PFNGLBEGINQUERYPROC glBeginQuery; -NAZARA_RENDERER_API extern PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation; -NAZARA_RENDERER_API extern PFNGLBINDBUFFERPROC glBindBuffer; -NAZARA_RENDERER_API extern PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer; -NAZARA_RENDERER_API extern PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation; -NAZARA_RENDERER_API extern PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer; -NAZARA_RENDERER_API extern PFNGLBINDSAMPLERPROC glBindSampler; -NAZARA_RENDERER_API extern PFNGLBINDTEXTUREPROC glBindTexture; -NAZARA_RENDERER_API extern PFNGLBINDVERTEXARRAYPROC glBindVertexArray; -NAZARA_RENDERER_API extern PFNGLBLENDFUNCPROC glBlendFunc; -NAZARA_RENDERER_API extern PFNGLBLENDFUNCSEPARATEPROC glBlendFuncSeparate; -NAZARA_RENDERER_API extern PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer; -NAZARA_RENDERER_API extern PFNGLBUFFERDATAPROC glBufferData; -NAZARA_RENDERER_API extern PFNGLBUFFERSUBDATAPROC glBufferSubData; -NAZARA_RENDERER_API extern PFNGLCLEARPROC glClear; -NAZARA_RENDERER_API extern PFNGLCLEARCOLORPROC glClearColor; -NAZARA_RENDERER_API extern PFNGLCLEARDEPTHPROC glClearDepth; -NAZARA_RENDERER_API extern PFNGLCLEARSTENCILPROC glClearStencil; -NAZARA_RENDERER_API extern PFNGLCREATEPROGRAMPROC glCreateProgram; -NAZARA_RENDERER_API extern PFNGLCREATESHADERPROC glCreateShader; -NAZARA_RENDERER_API extern PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus; -NAZARA_RENDERER_API extern PFNGLCOLORMASKPROC glColorMask; -NAZARA_RENDERER_API extern PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glCompressedTexSubImage1D; -NAZARA_RENDERER_API extern PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glCompressedTexSubImage2D; -NAZARA_RENDERER_API extern PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glCompressedTexSubImage3D; -NAZARA_RENDERER_API extern PFNGLCULLFACEPROC glCullFace; -NAZARA_RENDERER_API extern PFNGLCOMPILESHADERPROC glCompileShader; -NAZARA_RENDERER_API extern PFNGLCOPYTEXSUBIMAGE2DPROC glCopyTexSubImage2D; -NAZARA_RENDERER_API extern PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback; -NAZARA_RENDERER_API extern PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl; -NAZARA_RENDERER_API extern PFNGLDEBUGMESSAGEINSERTPROC glDebugMessageInsert; -NAZARA_RENDERER_API extern PFNGLDELETEBUFFERSPROC glDeleteBuffers; -NAZARA_RENDERER_API extern PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers; -NAZARA_RENDERER_API extern PFNGLDELETEPROGRAMPROC glDeleteProgram; -NAZARA_RENDERER_API extern PFNGLDELETEQUERIESPROC glDeleteQueries; -NAZARA_RENDERER_API extern PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers; -NAZARA_RENDERER_API extern PFNGLDELETESAMPLERSPROC glDeleteSamplers; -NAZARA_RENDERER_API extern PFNGLDELETESHADERPROC glDeleteShader; -NAZARA_RENDERER_API extern PFNGLDELETETEXTURESPROC glDeleteTextures; -NAZARA_RENDERER_API extern PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays; -NAZARA_RENDERER_API extern PFNGLDEPTHFUNCPROC glDepthFunc; -NAZARA_RENDERER_API extern PFNGLDEPTHMASKPROC glDepthMask; -NAZARA_RENDERER_API extern PFNGLDISABLEPROC glDisable; -NAZARA_RENDERER_API extern PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray; -NAZARA_RENDERER_API extern PFNGLDRAWARRAYSPROC glDrawArrays; -NAZARA_RENDERER_API extern PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced; -NAZARA_RENDERER_API extern PFNGLDRAWBUFFERPROC glDrawBuffer; -NAZARA_RENDERER_API extern PFNGLDRAWBUFFERSPROC glDrawBuffers; -NAZARA_RENDERER_API extern PFNGLDRAWELEMENTSPROC glDrawElements; -NAZARA_RENDERER_API extern PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced; -NAZARA_RENDERER_API extern PFNGLDRAWTEXTURENVPROC glDrawTexture; -NAZARA_RENDERER_API extern PFNGLENABLEPROC glEnable; -NAZARA_RENDERER_API extern PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray; -NAZARA_RENDERER_API extern PFNGLENDCONDITIONALRENDERPROC glEndConditionalRender; -NAZARA_RENDERER_API extern PFNGLENDQUERYPROC glEndQuery; -NAZARA_RENDERER_API extern PFNGLFLUSHPROC glFlush; -NAZARA_RENDERER_API extern PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer; -NAZARA_RENDERER_API extern PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture; -NAZARA_RENDERER_API extern PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D; -NAZARA_RENDERER_API extern PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D; -NAZARA_RENDERER_API extern PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D; -NAZARA_RENDERER_API extern PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer; -NAZARA_RENDERER_API extern PFNGLGENERATEMIPMAPPROC glGenerateMipmap; -NAZARA_RENDERER_API extern PFNGLGENBUFFERSPROC glGenBuffers; -NAZARA_RENDERER_API extern PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers; -NAZARA_RENDERER_API extern PFNGLGENQUERIESPROC glGenQueries; -NAZARA_RENDERER_API extern PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers; -NAZARA_RENDERER_API extern PFNGLGENSAMPLERSPROC glGenSamplers; -NAZARA_RENDERER_API extern PFNGLGENTEXTURESPROC glGenTextures; -NAZARA_RENDERER_API extern PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; -NAZARA_RENDERER_API extern PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform; -NAZARA_RENDERER_API extern PFNGLGETBOOLEANVPROC glGetBooleanv; -NAZARA_RENDERER_API extern PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv; -NAZARA_RENDERER_API extern PFNGLGETDEBUGMESSAGELOGPROC glGetDebugMessageLog; -NAZARA_RENDERER_API extern PFNGLGETERRORPROC glGetError; -NAZARA_RENDERER_API extern PFNGLGETFLOATVPROC glGetFloatv; -NAZARA_RENDERER_API extern PFNGLGETINTEGERVPROC glGetIntegerv; -NAZARA_RENDERER_API extern PFNGLGETPROGRAMBINARYPROC glGetProgramBinary; -NAZARA_RENDERER_API extern PFNGLGETPROGRAMIVPROC glGetProgramiv; -NAZARA_RENDERER_API extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; -NAZARA_RENDERER_API extern PFNGLGETQUERYIVPROC glGetQueryiv; -NAZARA_RENDERER_API extern PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv; -NAZARA_RENDERER_API extern PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv; -NAZARA_RENDERER_API extern PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog; -NAZARA_RENDERER_API extern PFNGLGETSHADERIVPROC glGetShaderiv; -NAZARA_RENDERER_API extern PFNGLGETSHADERSOURCEPROC glGetShaderSource; -NAZARA_RENDERER_API extern PFNGLGETSTRINGPROC glGetString; -NAZARA_RENDERER_API extern PFNGLGETSTRINGIPROC glGetStringi; -NAZARA_RENDERER_API extern PFNGLGETTEXIMAGEPROC glGetTexImage; -NAZARA_RENDERER_API extern PFNGLGETTEXLEVELPARAMETERFVPROC glGetTexLevelParameterfv; -NAZARA_RENDERER_API extern PFNGLGETTEXLEVELPARAMETERIVPROC glGetTexLevelParameteriv; -NAZARA_RENDERER_API extern PFNGLGETTEXPARAMETERFVPROC glGetTexParameterfv; -NAZARA_RENDERER_API extern PFNGLGETTEXPARAMETERIVPROC glGetTexParameteriv; -NAZARA_RENDERER_API extern PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation; -NAZARA_RENDERER_API extern PFNGLINVALIDATEBUFFERDATAPROC glInvalidateBufferData; -NAZARA_RENDERER_API extern PFNGLISENABLEDPROC glIsEnabled; -NAZARA_RENDERER_API extern PFNGLLINEWIDTHPROC glLineWidth; -NAZARA_RENDERER_API extern PFNGLLINKPROGRAMPROC glLinkProgram; -NAZARA_RENDERER_API extern PFNGLMAPBUFFERPROC glMapBuffer; -NAZARA_RENDERER_API extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; -NAZARA_RENDERER_API extern PFNGLPIXELSTOREIPROC glPixelStorei; -NAZARA_RENDERER_API extern PFNGLPOINTSIZEPROC glPointSize; -NAZARA_RENDERER_API extern PFNGLPOLYGONMODEPROC glPolygonMode; -NAZARA_RENDERER_API extern PFNGLPROGRAMBINARYPROC glProgramBinary; -NAZARA_RENDERER_API extern PFNGLPROGRAMPARAMETERIPROC glProgramParameteri; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM1DPROC glProgramUniform1d; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM1FPROC glProgramUniform1f; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM1DVPROC glProgramUniform1dv; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM1FVPROC glProgramUniform1fv; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM1IVPROC glProgramUniform1iv; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM2DVPROC glProgramUniform2dv; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM2FVPROC glProgramUniform2fv; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM2IVPROC glProgramUniform2iv; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM3DVPROC glProgramUniform3dv; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM3FVPROC glProgramUniform3fv; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM3IVPROC glProgramUniform3iv; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM4DVPROC glProgramUniform4dv; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM4FVPROC glProgramUniform4fv; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORM4IVPROC glProgramUniform4iv; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORMMATRIX4DVPROC glProgramUniformMatrix4dv; -NAZARA_RENDERER_API extern PFNGLPROGRAMUNIFORMMATRIX4FVPROC glProgramUniformMatrix4fv; -NAZARA_RENDERER_API extern PFNGLREADPIXELSPROC glReadPixels; -NAZARA_RENDERER_API extern PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage; -NAZARA_RENDERER_API extern PFNGLSAMPLERPARAMETERFPROC glSamplerParameterf; -NAZARA_RENDERER_API extern PFNGLSAMPLERPARAMETERIPROC glSamplerParameteri; -NAZARA_RENDERER_API extern PFNGLSCISSORPROC glScissor; -NAZARA_RENDERER_API extern PFNGLSHADERSOURCEPROC glShaderSource; -NAZARA_RENDERER_API extern PFNGLSTENCILFUNCPROC glStencilFunc; -NAZARA_RENDERER_API extern PFNGLSTENCILFUNCSEPARATEPROC glStencilFuncSeparate; -NAZARA_RENDERER_API extern PFNGLSTENCILOPPROC glStencilOp; -NAZARA_RENDERER_API extern PFNGLSTENCILOPSEPARATEPROC glStencilOpSeparate; -NAZARA_RENDERER_API extern PFNGLTEXIMAGE1DPROC glTexImage1D; -NAZARA_RENDERER_API extern PFNGLTEXIMAGE2DPROC glTexImage2D; -NAZARA_RENDERER_API extern PFNGLTEXIMAGE3DPROC glTexImage3D; -NAZARA_RENDERER_API extern PFNGLTEXPARAMETERFPROC glTexParameterf; -NAZARA_RENDERER_API extern PFNGLTEXPARAMETERIPROC glTexParameteri; -NAZARA_RENDERER_API extern PFNGLTEXSTORAGE1DPROC glTexStorage1D; -NAZARA_RENDERER_API extern PFNGLTEXSTORAGE2DPROC glTexStorage2D; -NAZARA_RENDERER_API extern PFNGLTEXSTORAGE3DPROC glTexStorage3D; -NAZARA_RENDERER_API extern PFNGLTEXSUBIMAGE1DPROC glTexSubImage1D; -NAZARA_RENDERER_API extern PFNGLTEXSUBIMAGE2DPROC glTexSubImage2D; -NAZARA_RENDERER_API extern PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D; -NAZARA_RENDERER_API extern PFNGLUNIFORM1DPROC glUniform1d; -NAZARA_RENDERER_API extern PFNGLUNIFORM1FPROC glUniform1f; -NAZARA_RENDERER_API extern PFNGLUNIFORM1IPROC glUniform1i; -NAZARA_RENDERER_API extern PFNGLUNIFORM1DVPROC glUniform1dv; -NAZARA_RENDERER_API extern PFNGLUNIFORM1FVPROC glUniform1fv; -NAZARA_RENDERER_API extern PFNGLUNIFORM1IVPROC glUniform1iv; -NAZARA_RENDERER_API extern PFNGLUNIFORM2DVPROC glUniform2dv; -NAZARA_RENDERER_API extern PFNGLUNIFORM2FVPROC glUniform2fv; -NAZARA_RENDERER_API extern PFNGLUNIFORM2IVPROC glUniform2iv; -NAZARA_RENDERER_API extern PFNGLUNIFORM3DVPROC glUniform3dv; -NAZARA_RENDERER_API extern PFNGLUNIFORM3FVPROC glUniform3fv; -NAZARA_RENDERER_API extern PFNGLUNIFORM3IVPROC glUniform3iv; -NAZARA_RENDERER_API extern PFNGLUNIFORM4DVPROC glUniform4dv; -NAZARA_RENDERER_API extern PFNGLUNIFORM4FVPROC glUniform4fv; -NAZARA_RENDERER_API extern PFNGLUNIFORM4IVPROC glUniform4iv; -NAZARA_RENDERER_API extern PFNGLUNIFORMMATRIX4DVPROC glUniformMatrix4dv; -NAZARA_RENDERER_API extern PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv; -NAZARA_RENDERER_API extern PFNGLUNMAPBUFFERPROC glUnmapBuffer; -NAZARA_RENDERER_API extern PFNGLUSEPROGRAMPROC glUseProgram; -NAZARA_RENDERER_API extern PFNGLVALIDATEPROGRAMPROC glValidateProgram; -NAZARA_RENDERER_API extern PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f; -NAZARA_RENDERER_API extern PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor; -NAZARA_RENDERER_API extern PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer; -NAZARA_RENDERER_API extern PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer; -NAZARA_RENDERER_API extern PFNGLVERTEXATTRIBLPOINTERPROC glVertexAttribLPointer; -NAZARA_RENDERER_API extern PFNGLVIEWPORTPROC glViewport; -#if defined(NAZARA_PLATFORM_WINDOWS) -NAZARA_RENDERER_API extern PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat; -NAZARA_RENDERER_API extern PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs; -NAZARA_RENDERER_API extern PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB; -NAZARA_RENDERER_API extern PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT; -NAZARA_RENDERER_API extern PFNWGLSWAPINTERVALEXTPROC wglSwapInterval; -#elif defined(NAZARA_PLATFORM_GLX) -NAZARA_RENDERER_API extern GLX::PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs; -NAZARA_RENDERER_API extern GLX::PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT; -NAZARA_RENDERER_API extern GLX::PFNGLXSWAPINTERVALMESAPROC NzglXSwapIntervalMESA; -NAZARA_RENDERER_API extern GLX::PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI; -#endif - -} - -#endif // NAZARA_RENDERER_OPENGL - -#endif // NAZARA_OPENGL_HPP diff --git a/include/Nazara/Renderer/RenderBuffer.hpp b/include/Nazara/Renderer/RenderBuffer.hpp deleted file mode 100644 index cfe66651e..000000000 --- a/include/Nazara/Renderer/RenderBuffer.hpp +++ /dev/null @@ -1,73 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_RENDERBUFFER_HPP -#define NAZARA_RENDERBUFFER_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - class RenderBuffer; - - using RenderBufferConstRef = ObjectRef; - using RenderBufferLibrary = ObjectLibrary; - using RenderBufferRef = ObjectRef; - - class NAZARA_RENDERER_API RenderBuffer : public RefCounted - { - friend RenderBufferLibrary; - friend class Renderer; - - public: - RenderBuffer(); - RenderBuffer(const RenderBuffer&) = delete; - RenderBuffer(RenderBuffer&&) = delete; - ~RenderBuffer(); - - bool Create(PixelFormatType format, unsigned int width, unsigned int height); - void Destroy(); - - unsigned int GetHeight() const; - PixelFormatType GetFormat() const; - unsigned int GetWidth() const; - - // Fonctions OpenGL - unsigned int GetOpenGLID() const; - - bool IsValid() const; - - RenderBuffer& operator=(const RenderBuffer&) = delete; - RenderBuffer& operator=(RenderBuffer&&) = delete; - - template static RenderBufferRef New(Args&&... args); - - // Signals: - NazaraSignal(OnRenderBufferDestroy, const RenderBuffer* /*renderBuffer*/); - NazaraSignal(OnRenderBufferRelease, const RenderBuffer* /*renderBuffer*/); - - private: - static bool Initialize(); - static void Uninitialize(); - - PixelFormatType m_pixelFormat; - unsigned int m_height; - unsigned int m_id; - unsigned int m_width; - - static RenderBufferLibrary::LibraryMap s_library; - }; -} - -#include - -#endif // NAZARA_RENDERBUFFER_HPP diff --git a/include/Nazara/Renderer/RenderBuffer.inl b/include/Nazara/Renderer/RenderBuffer.inl deleted file mode 100644 index bd81e7a17..000000000 --- a/include/Nazara/Renderer/RenderBuffer.inl +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include - -namespace Nz -{ - template - RenderBufferRef RenderBuffer::New(Args&&... args) - { - std::unique_ptr object(new RenderBuffer(std::forward(args)...)); - object->SetPersistent(false); - - return object.release(); - } -} - -#include diff --git a/include/Nazara/Renderer/RenderDevice.hpp b/include/Nazara/Renderer/RenderDevice.hpp new file mode 100644 index 000000000..4b1991085 --- /dev/null +++ b/include/Nazara/Renderer/RenderDevice.hpp @@ -0,0 +1,23 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_RENDERDEVICE_HPP +#define NAZARA_RENDERDEVICE_HPP + +#include +#include +#include + +namespace Nz +{ + struct RenderDevice + { + RenderDeviceType type; + String name; + }; +} + +#endif // NAZARA_RENDERER_HPP diff --git a/include/Nazara/Renderer/RenderPipeline.hpp b/include/Nazara/Renderer/RenderPipeline.hpp deleted file mode 100644 index aee5584b7..000000000 --- a/include/Nazara/Renderer/RenderPipeline.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (C) 2016 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_RENDERPIPELINE_HPP -#define NAZARA_RENDERPIPELINE_HPP - -#include -#include -#include - -namespace Nz -{ - struct RenderPipelineInfo : RenderStates - { - ShaderConstRef shader; - }; - - class RenderPipeline - { - public: - inline RenderPipeline(); - inline ~RenderPipeline(); - - inline bool Create(const RenderPipelineInfo& pipelineInfo); - inline void Destroy(); - - inline const RenderPipelineInfo& GetInfo() const; - - inline bool IsValid() const; - - private: - RenderPipelineInfo m_pipelineInfo; - bool m_valid; - }; -} - -#include - -#endif // NAZARA_RENDERPIPELINE_HPP diff --git a/include/Nazara/Renderer/RenderPipeline.inl b/include/Nazara/Renderer/RenderPipeline.inl deleted file mode 100644 index 5982b0562..000000000 --- a/include/Nazara/Renderer/RenderPipeline.inl +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright (C) 2016 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include - -namespace Nz -{ - inline RenderPipeline::RenderPipeline() : - m_valid(false) - { - } - - inline RenderPipeline::~RenderPipeline() - { - } - - inline bool RenderPipeline::Create(const RenderPipelineInfo& pipelineInfo) - { - NazaraAssert(pipelineInfo.shader, "Invalid shader"); - - m_pipelineInfo = pipelineInfo; - m_valid = true; - - return true; - } - - inline void RenderPipeline::Destroy() - { - m_valid = false; - } - - inline const RenderPipelineInfo& RenderPipeline::GetInfo() const - { - NazaraAssert(m_valid, "Invalid pipeline info"); - - return m_pipelineInfo; - } - - inline bool RenderPipeline::IsValid() const - { - return m_valid; - } -} - -#include diff --git a/include/Nazara/Renderer/RenderStates.hpp b/include/Nazara/Renderer/RenderStates.hpp deleted file mode 100644 index fc4d10eeb..000000000 --- a/include/Nazara/Renderer/RenderStates.hpp +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_RENDERSTATES_HPP -#define NAZARA_RENDERSTATES_HPP - -#include -#include - -namespace Nz -{ - struct RenderStates - { - BlendFunc dstBlend = BlendFunc_Zero; - BlendFunc srcBlend = BlendFunc_One; - FaceFilling faceFilling = FaceFilling_Fill; - FaceSide cullingSide = FaceSide_Back; - RendererComparison depthFunc = RendererComparison_Less; - - struct - { - RendererComparison back = RendererComparison_Always; - RendererComparison front = RendererComparison_Always; - } stencilCompare; - - struct - { - UInt32 back = 0xFFFFFFFF; - UInt32 front = 0xFFFFFFFF; - } stencilCompareMask; - - struct - { - StencilOperation back = StencilOperation_Keep; - StencilOperation front = StencilOperation_Keep; - } stencilDepthFail; - - struct - { - StencilOperation back = StencilOperation_Keep; - StencilOperation front = StencilOperation_Keep; - } stencilFail; - - struct - { - StencilOperation back = StencilOperation_Keep; - StencilOperation front = StencilOperation_Keep; - } stencilPass; - - struct - { - UInt32 back = 0U; - UInt32 front = 0U; - } stencilReference; - - struct - { - UInt32 back = 0xFFFFFFFF; - UInt32 front = 0xFFFFFFFF; - } stencilWriteMask; - - bool blending = false; - bool colorWrite = true; - bool depthBuffer = false; - bool depthWrite = true; - bool faceCulling = false; - bool scissorTest = false; - bool stencilTest = false; - - float lineWidth = 1.f; - float pointSize = 1.f; - }; - - inline bool operator==(const RenderStates& lhs, const RenderStates& rhs); -} - -#include - -#endif // NAZARA_RENDERSTATES_HPP diff --git a/include/Nazara/Renderer/RenderStates.inl b/include/Nazara/Renderer/RenderStates.inl deleted file mode 100644 index 525491162..000000000 --- a/include/Nazara/Renderer/RenderStates.inl +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include - -namespace Nz -{ - bool operator==(const RenderStates& lhs, const RenderStates& rhs) - { - #define NazaraRenderStateMember(field) if (lhs.field != rhs.field) return false - #define NazaraRenderStateBoolMember NazaraRenderStateMember - #define NazaraRenderStateFloatMember(field, maxDiff) if (!NumberEquals(lhs.field, rhs.field, maxDiff)) return false - - NazaraRenderStateBoolMember(blending); - NazaraRenderStateBoolMember(colorWrite); - NazaraRenderStateBoolMember(depthBuffer); - NazaraRenderStateBoolMember(faceCulling); - NazaraRenderStateBoolMember(scissorTest); - NazaraRenderStateBoolMember(stencilTest); - - if (lhs.depthBuffer) - NazaraRenderStateBoolMember(depthWrite); - - NazaraRenderStateMember(faceFilling); - - if (lhs.blending) //< Remember, at this time we know lhs.blending == rhs.blending - { - NazaraRenderStateMember(dstBlend); - NazaraRenderStateMember(srcBlend); - } - - if (lhs.depthBuffer) - NazaraRenderStateMember(depthFunc); - - if (lhs.faceCulling) - NazaraRenderStateMember(cullingSide); - - if (lhs.stencilTest) - { - NazaraRenderStateMember(stencilCompare.back); - NazaraRenderStateMember(stencilCompare.front); - NazaraRenderStateMember(stencilCompareMask.back); - NazaraRenderStateMember(stencilCompareMask.front); - NazaraRenderStateMember(stencilDepthFail.back); - NazaraRenderStateMember(stencilDepthFail.front); - NazaraRenderStateMember(stencilFail.back); - NazaraRenderStateMember(stencilFail.front); - NazaraRenderStateMember(stencilPass.back); - NazaraRenderStateMember(stencilPass.front); - NazaraRenderStateMember(stencilReference.back); - NazaraRenderStateMember(stencilReference.front); - NazaraRenderStateMember(stencilWriteMask.back); - NazaraRenderStateMember(stencilWriteMask.front); - } - - NazaraRenderStateFloatMember(lineWidth, 0.001f); - NazaraRenderStateFloatMember(pointSize, 0.001f); - - #undef NazaraRenderStateMember - #undef NazaraRenderStateBoolMember - #undef NazaraRenderStateFloatMember - - return true; - } -} - -namespace std -{ - template<> - struct hash - { - size_t operator()(const Nz::RenderStates& pipelineInfo) const - { - std::size_t seed = 0; - - Nz::UInt8 parameterHash = 0; - Nz::UInt8 parameterIndex = 0; - - #define NazaraRenderStateBool(member) parameterHash |= ((pipelineInfo.member) ? 1U : 0U) << (parameterIndex++) - #define NazaraRenderStateBoolDep(dependency, member) parameterHash |= ((pipelineInfo.dependency && pipelineInfo.member) ? 1U : 0U) << (parameterIndex++) - #define NazaraRenderStateEnum(member) Nz::HashCombine(seed, static_cast(pipelineInfo.member)) - #define NazaraRenderStateFloat(member, maxDiff) Nz::HashCombine(seed, std::floor(pipelineInfo.member / maxDiff) * maxDiff) - - NazaraRenderStateBool(blending); - NazaraRenderStateBool(colorWrite); - NazaraRenderStateBool(depthBuffer); - NazaraRenderStateBool(faceCulling); - NazaraRenderStateBool(scissorTest); - NazaraRenderStateBool(stencilTest); - - NazaraRenderStateBoolDep(depthBuffer, depthWrite); - - NazaraRenderStateEnum(faceFilling); - - if (pipelineInfo.blending) //< Remember, at this time we know lhs.blending == rhs.blending - { - NazaraRenderStateEnum(dstBlend); - NazaraRenderStateEnum(srcBlend); - } - - if (pipelineInfo.depthBuffer) - NazaraRenderStateEnum(depthFunc); - - if (pipelineInfo.faceCulling) - NazaraRenderStateEnum(cullingSide); - - if (pipelineInfo.stencilTest) - { - NazaraRenderStateEnum(stencilCompare.back); - NazaraRenderStateEnum(stencilCompare.front); - NazaraRenderStateEnum(stencilCompareMask.back); - NazaraRenderStateEnum(stencilCompareMask.front); - NazaraRenderStateEnum(stencilDepthFail.back); - NazaraRenderStateEnum(stencilDepthFail.front); - NazaraRenderStateEnum(stencilFail.back); - NazaraRenderStateEnum(stencilFail.front); - NazaraRenderStateEnum(stencilPass.back); - NazaraRenderStateEnum(stencilPass.front); - NazaraRenderStateEnum(stencilReference.back); - NazaraRenderStateEnum(stencilReference.front); - NazaraRenderStateEnum(stencilWriteMask.back); - NazaraRenderStateEnum(stencilWriteMask.front); - } - - NazaraRenderStateFloat(lineWidth, 0.001f); - NazaraRenderStateFloat(pointSize, 0.001f); - - #undef NazaraRenderStateBool - #undef NazaraRenderStateBoolDep - #undef NazaraRenderStateEnum - #undef NazaraRenderStateFloat - - Nz::HashCombine(seed, parameterHash); - - return seed; - } - }; -} - -#include diff --git a/include/Nazara/Renderer/RenderTarget.hpp b/include/Nazara/Renderer/RenderTarget.hpp deleted file mode 100644 index d018cb952..000000000 --- a/include/Nazara/Renderer/RenderTarget.hpp +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_RENDERTARGET_HPP -#define NAZARA_RENDERTARGET_HPP - -#include -#include -#include -#include -#include - -namespace Nz -{ - class Renderer; - - class NAZARA_RENDERER_API RenderTarget - { - friend class Renderer; - - public: - RenderTarget() = default; - RenderTarget(const RenderTarget&) = delete; - RenderTarget(RenderTarget&&) = delete; ///TOOD? - virtual ~RenderTarget(); - - virtual unsigned int GetHeight() const = 0; - virtual RenderTargetParameters GetParameters() const = 0; - virtual unsigned int GetWidth() const = 0; - - bool IsActive() const; - virtual bool IsRenderable() const = 0; - - bool SetActive(bool active); - - // Fonctions OpenGL - virtual bool HasContext() const = 0; - - RenderTarget& operator=(const RenderTarget&) = delete; - RenderTarget& operator=(RenderTarget&&) = delete; ///TOOD? - - // Signals: - NazaraSignal(OnRenderTargetParametersChange, const RenderTarget* /*renderTarget*/); - NazaraSignal(OnRenderTargetRelease, const RenderTarget* /*renderTarget*/); - NazaraSignal(OnRenderTargetSizeChange, const RenderTarget* /*renderTarget*/); - - protected: - virtual bool Activate() const = 0; - virtual void Desactivate() const; - virtual void EnsureTargetUpdated() const = 0; - }; -} - -#endif // NAZARA_RENDERTARGET_HPP diff --git a/include/Nazara/Renderer/RenderTargetParameters.hpp b/include/Nazara/Renderer/RenderTargetParameters.hpp deleted file mode 100644 index 990848c53..000000000 --- a/include/Nazara/Renderer/RenderTargetParameters.hpp +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_RENDERTARGETPARAMETERS_HPP -#define NAZARA_RENDERTARGETPARAMETERS_HPP - -#include - -namespace Nz -{ - struct RenderTargetParameters - { - RenderTargetParameters(UInt8 antialiasing = 0, UInt8 depth = 24, UInt8 stencil = 0) : - antialiasingLevel(antialiasing), - depthBits(depth), - stencilBits(stencil) - { - } - - UInt8 antialiasingLevel; - UInt8 depthBits; - UInt8 stencilBits; - }; -} - -#endif // NAZARA_RENDERTARGETPARAMETERS_HPP diff --git a/include/Nazara/Renderer/RenderTexture.hpp b/include/Nazara/Renderer/RenderTexture.hpp deleted file mode 100644 index 798e441ee..000000000 --- a/include/Nazara/Renderer/RenderTexture.hpp +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_RENDERTEXTURE_HPP -#define NAZARA_RENDERTEXTURE_HPP - -#include -#include -#include -#include -#include -#include - -///TODO: Faire fonctionner les RenderTexture indépendamment du contexte (un FBO par instance et par contexte l'utilisant) - -namespace Nz -{ - - class Context; - class RenderBuffer; - class Texture; - - struct RenderTextureImpl; - - class NAZARA_RENDERER_API RenderTexture : public RenderTarget - { - public: - inline RenderTexture(); - RenderTexture(const RenderTexture&) = delete; - RenderTexture(RenderTexture&&) = delete; ///TODO? - inline ~RenderTexture(); - - bool AttachBuffer(AttachmentPoint attachmentPoint, UInt8 index, RenderBuffer* buffer); - bool AttachBuffer(AttachmentPoint attachmentPoint, UInt8 index, PixelFormatType format, unsigned int width, unsigned int height); - bool AttachTexture(AttachmentPoint attachmentPoint, UInt8 index, Texture* texture, unsigned int z = 0); - - bool Create(bool lock = false); - void Destroy(); - - void Detach(AttachmentPoint attachmentPoint, UInt8 index); - - unsigned int GetHeight() const override; - RenderTargetParameters GetParameters() const override; - Vector2ui GetSize() const; - unsigned int GetWidth() const override; - - bool IsComplete() const; - bool IsRenderable() const override; - inline bool IsValid() const; - - bool Lock() const; - - inline void SetColorTarget(UInt8 target) const; - void SetColorTargets(const UInt8* targets, unsigned int targetCount) const; - void SetColorTargets(const std::initializer_list& targets) const; - - void Unlock() const; - - // Fonctions OpenGL - unsigned int GetOpenGLID() const; - bool HasContext() const override; - - RenderTexture& operator=(const RenderTexture&) = delete; - RenderTexture& operator=(RenderTexture&&) = delete; ///TODO? - - static inline void Blit(RenderTexture* src, RenderTexture* dst, UInt32 buffers = RendererBuffer_Color | RendererBuffer_Depth | RendererBuffer_Stencil, bool bilinearFilter = false); - static void Blit(RenderTexture* src, Rectui srcRect, RenderTexture* dst, Rectui dstRect, UInt32 buffers = RendererBuffer_Color | RendererBuffer_Depth | RendererBuffer_Stencil, bool bilinearFilter = false); - - protected: - bool Activate() const override; - void Desactivate() const override; - void EnsureTargetUpdated() const override; - - private: - inline void InvalidateDrawBuffers() const; - inline void InvalidateSize() const; - inline void InvalidateTargets() const; - void OnContextDestroy(const Context* context); - void OnRenderBufferDestroy(const RenderBuffer* renderBuffer, unsigned int attachmentIndex); - void OnTextureDestroy(const Texture* texture, unsigned int attachmentIndex); - void UpdateDrawBuffers() const; - void UpdateSize() const; - void UpdateTargets() const; - - RenderTextureImpl* m_impl; - mutable bool m_checked ; - mutable bool m_drawBuffersUpdated; - mutable bool m_sizeUpdated; - mutable bool m_targetsUpdated; - }; -} - -#include - -#endif // NAZARA_RENDERTEXTURE_HPP diff --git a/include/Nazara/Renderer/RenderTexture.inl b/include/Nazara/Renderer/RenderTexture.inl deleted file mode 100644 index 7b8c32c68..000000000 --- a/include/Nazara/Renderer/RenderTexture.inl +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include - -namespace Nz -{ - inline RenderTexture::RenderTexture() : - m_impl(nullptr) - { - } - - inline RenderTexture::~RenderTexture() - { - Destroy(); - } - - inline bool RenderTexture::IsValid() const - { - return m_impl != nullptr; - } - - inline void RenderTexture::SetColorTarget(UInt8 target) const - { - SetColorTargets(&target, 1); - } - - inline void RenderTexture::Blit(RenderTexture* src, RenderTexture* dst, UInt32 buffers, bool bilinearFilter) - { - Blit(src, src->GetSize(), dst, dst->GetSize(), buffers, bilinearFilter); - } - - inline void RenderTexture::InvalidateDrawBuffers() const - { - m_drawBuffersUpdated = false; - } - - inline void RenderTexture::InvalidateSize() const - { - m_sizeUpdated = false; - - OnRenderTargetSizeChange(this); - } - - inline void RenderTexture::InvalidateTargets() const - { - m_checked = false; - m_drawBuffersUpdated = false; - m_targetsUpdated = false; - } -} - -#include diff --git a/include/Nazara/Renderer/RenderWindow.hpp b/include/Nazara/Renderer/RenderWindow.hpp index 1cda9d63d..5435cebaf 100644 --- a/include/Nazara/Renderer/RenderWindow.hpp +++ b/include/Nazara/Renderer/RenderWindow.hpp @@ -13,9 +13,6 @@ #include #include #include -#include -#include -#include #include #include diff --git a/include/Nazara/Renderer/RenderWindow.inl b/include/Nazara/Renderer/RenderWindow.inl new file mode 100644 index 000000000..1cda9d63d --- /dev/null +++ b/include/Nazara/Renderer/RenderWindow.inl @@ -0,0 +1,81 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +// Interface inspirée de la SFML par Laurent Gomila + +#pragma once + +#ifndef NAZARA_RENDERWINDOW_HPP +#define NAZARA_RENDERWINDOW_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class AbstractImage; + class Context; + class Texture; + struct ContextParameters; + + class NAZARA_RENDERER_API RenderWindow : public RenderTarget, public Window + { + public: + RenderWindow() = default; + RenderWindow(VideoMode mode, const String& title, UInt32 style = WindowStyle_Default, const ContextParameters& parameters = ContextParameters()); + RenderWindow(WindowHandle handle, const ContextParameters& parameters = ContextParameters()); + RenderWindow(const RenderWindow&) = delete; + RenderWindow(RenderWindow&&) = delete; ///TODO + virtual ~RenderWindow(); + + bool CopyToImage(AbstractImage* image, const Vector3ui& dstPos = Vector3ui(0U)) const; + bool CopyToImage(AbstractImage* image, const Rectui& rect, const Vector3ui& dstPos = Vector3ui(0U)) const; + + bool Create(VideoMode mode, const String& title, UInt32 style = WindowStyle_Default, const ContextParameters& parameters = ContextParameters()); + bool Create(WindowHandle handle, const ContextParameters& parameters = ContextParameters()); + + void Display(); + + void EnableVerticalSync(bool enabled); + + unsigned int GetHeight() const override; + RenderTargetParameters GetParameters() const override; + unsigned int GetWidth() const override; + + bool IsRenderable() const override; + bool IsValid() const; + + void SetFramerateLimit(unsigned int limit); + + // Fonctions OpenGL + ContextParameters GetContextParameters() const; + bool HasContext() const override; + + RenderWindow& operator=(const RenderWindow&) = delete; + RenderWindow& operator=(RenderWindow&&) = delete; ///TODO + + protected: + bool Activate() const override; + void EnsureTargetUpdated() const override; + bool OnWindowCreated() override; + void OnWindowDestroy() override; + void OnWindowResized() override; + + private: + mutable std::vector m_buffer; + Clock m_clock; + ContextParameters m_parameters; + mutable Context* m_context = nullptr; + unsigned int m_framerateLimit = 0; + }; +} + +#endif // NAZARA_RENDERWINDOW_HPP diff --git a/include/Nazara/Renderer/RenderWindowImpl.hpp b/include/Nazara/Renderer/RenderWindowImpl.hpp new file mode 100644 index 000000000..1cda9d63d --- /dev/null +++ b/include/Nazara/Renderer/RenderWindowImpl.hpp @@ -0,0 +1,81 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +// Interface inspirée de la SFML par Laurent Gomila + +#pragma once + +#ifndef NAZARA_RENDERWINDOW_HPP +#define NAZARA_RENDERWINDOW_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class AbstractImage; + class Context; + class Texture; + struct ContextParameters; + + class NAZARA_RENDERER_API RenderWindow : public RenderTarget, public Window + { + public: + RenderWindow() = default; + RenderWindow(VideoMode mode, const String& title, UInt32 style = WindowStyle_Default, const ContextParameters& parameters = ContextParameters()); + RenderWindow(WindowHandle handle, const ContextParameters& parameters = ContextParameters()); + RenderWindow(const RenderWindow&) = delete; + RenderWindow(RenderWindow&&) = delete; ///TODO + virtual ~RenderWindow(); + + bool CopyToImage(AbstractImage* image, const Vector3ui& dstPos = Vector3ui(0U)) const; + bool CopyToImage(AbstractImage* image, const Rectui& rect, const Vector3ui& dstPos = Vector3ui(0U)) const; + + bool Create(VideoMode mode, const String& title, UInt32 style = WindowStyle_Default, const ContextParameters& parameters = ContextParameters()); + bool Create(WindowHandle handle, const ContextParameters& parameters = ContextParameters()); + + void Display(); + + void EnableVerticalSync(bool enabled); + + unsigned int GetHeight() const override; + RenderTargetParameters GetParameters() const override; + unsigned int GetWidth() const override; + + bool IsRenderable() const override; + bool IsValid() const; + + void SetFramerateLimit(unsigned int limit); + + // Fonctions OpenGL + ContextParameters GetContextParameters() const; + bool HasContext() const override; + + RenderWindow& operator=(const RenderWindow&) = delete; + RenderWindow& operator=(RenderWindow&&) = delete; ///TODO + + protected: + bool Activate() const override; + void EnsureTargetUpdated() const override; + bool OnWindowCreated() override; + void OnWindowDestroy() override; + void OnWindowResized() override; + + private: + mutable std::vector m_buffer; + Clock m_clock; + ContextParameters m_parameters; + mutable Context* m_context = nullptr; + unsigned int m_framerateLimit = 0; + }; +} + +#endif // NAZARA_RENDERWINDOW_HPP diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index f93fe47e3..b23a5b284 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2015 Jérôme Leclercq +// Copyright (C) 2016 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp @@ -8,120 +8,33 @@ #define NAZARA_RENDERER_HPP #include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include namespace Nz { - class Color; - class Context; - class IndexBuffer; - class RenderTarget; - class Shader; - class Texture; - class VertexBuffer; - class NAZARA_RENDERER_API Renderer { - friend Texture; - public: - using DrawCall = void (*)(PrimitiveMode, unsigned int, unsigned int); - using DrawCallInstanced = void (*)(unsigned int, PrimitiveMode, unsigned int, unsigned int); - Renderer() = delete; ~Renderer() = delete; - - static void BeginCondition(const GpuQuery& query, GpuQueryCondition condition); - - static void Clear(UInt32 flags = RendererBuffer_Color | RendererBuffer_Depth); - - static void DrawFullscreenQuad(); - static void DrawIndexedPrimitives(PrimitiveMode mode, unsigned int firstIndex, unsigned int indexCount); - static void DrawIndexedPrimitivesInstanced(unsigned int instanceCount, PrimitiveMode mode, unsigned int firstIndex, unsigned int indexCount); - static void DrawPrimitives(PrimitiveMode mode, unsigned int firstVertex, unsigned int vertexCount); - static void DrawPrimitivesInstanced(unsigned int instanceCount, PrimitiveMode mode, unsigned int firstVertex, unsigned int vertexCount); - - static void Enable(RendererParameter parameter, bool enable); - - static void EndCondition(); - - static void Flush(); - - static RendererComparison GetDepthFunc(); - static VertexBuffer* GetInstanceBuffer(); - static float GetLineWidth(); - static Matrix4f GetMatrix(MatrixType type); - static UInt8 GetMaxAnisotropyLevel(); - static unsigned int GetMaxColorAttachments(); - static unsigned int GetMaxRenderTargets(); - static unsigned int GetMaxTextureSize(); - static unsigned int GetMaxTextureUnits(); - static unsigned int GetMaxVertexAttribs(); - static float GetPointSize(); - static const RenderStates& GetRenderStates(); - static Recti GetScissorRect(); - static const Shader* GetShader(); - static const RenderTarget* GetTarget(); - static Recti GetViewport(); - - static bool HasCapability(RendererCap capability); + + static inline RendererImpl* GetRendererImpl(); static bool Initialize(); - static bool IsComponentTypeSupported(ComponentType type); - static bool IsEnabled(RendererParameter parameter); - static bool IsInitialized(); - - static void SetBlendFunc(BlendFunc srcBlend, BlendFunc dstBlend); - static void SetClearColor(const Color& color); - static void SetClearColor(UInt8 r, UInt8 g, UInt8 b, UInt8 a = 255); - static void SetClearDepth(double depth); - static void SetClearStencil(unsigned int value); - static void SetDepthFunc(RendererComparison compareFunc); - static void SetFaceCulling(FaceSide faceSide); - static void SetFaceFilling(FaceFilling fillingMode); - static void SetIndexBuffer(const IndexBuffer* indexBuffer); - static void SetLineWidth(float size); - static void SetMatrix(MatrixType type, const Matrix4f& matrix); - static void SetPointSize(float size); - static void SetRenderStates(const RenderStates& states); - static void SetScissorRect(const Recti& rect); - static void SetShader(const Shader* shader); - static void SetStencilCompareFunction(RendererComparison compareFunc, FaceSide faceSide = FaceSide_FrontAndBack); - static void SetStencilFailOperation(StencilOperation failOperation, FaceSide faceSide = FaceSide_FrontAndBack); - static void SetStencilMask(UInt32 mask, FaceSide faceSide = FaceSide_FrontAndBack); - static void SetStencilPassOperation(StencilOperation passOperation, FaceSide faceSide = FaceSide_FrontAndBack); - static void SetStencilReferenceValue(unsigned int refValue, FaceSide faceSide = FaceSide_FrontAndBack); - static void SetStencilZFailOperation(StencilOperation zfailOperation, FaceSide faceSide = FaceSide_FrontAndBack); - static bool SetTarget(const RenderTarget* target); - static void SetTexture(UInt8 unit, const Texture* texture); - static void SetTextureSampler(UInt8 textureUnit, const TextureSampler& sampler); - static void SetVertexBuffer(const VertexBuffer* vertexBuffer); - static void SetViewport(const Recti& viewport); + static inline bool IsInitialized(); static void Uninitialize(); private: - static void EnableInstancing(bool instancing); - static bool EnsureStateUpdate(); - static void OnContextRelease(const Context* context); - static void OnIndexBufferRelease(const IndexBuffer* indexBuffer); - static void OnShaderReleased(const Shader* shader); - static void OnTextureReleased(const Texture* texture); - static void OnVertexBufferRelease(const VertexBuffer* vertexBuffer); - static void OnVertexDeclarationRelease(const VertexDeclaration* vertexDeclaration); - static void UpdateMatrix(MatrixType type); - + static DynLib s_rendererLib; + static std::unique_ptr s_rendererImpl; static unsigned int s_moduleReferenceCounter; }; } +#include + #endif // NAZARA_RENDERER_HPP diff --git a/include/Nazara/Renderer/Renderer.inl b/include/Nazara/Renderer/Renderer.inl new file mode 100644 index 000000000..16c3746db --- /dev/null +++ b/include/Nazara/Renderer/Renderer.inl @@ -0,0 +1,21 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + inline RendererImpl* Renderer::GetRendererImpl() + { + return s_rendererImpl.get(); + } + + inline bool Renderer::IsInitialized() + { + return s_moduleReferenceCounter != 0; + } +} + +#include diff --git a/include/Nazara/Renderer/RendererImpl.hpp b/include/Nazara/Renderer/RendererImpl.hpp new file mode 100644 index 000000000..f3f70d892 --- /dev/null +++ b/include/Nazara/Renderer/RendererImpl.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_RENDERER_RENDERERIMPL_HPP +#define NAZARA_RENDERER_RENDERERIMPL_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class RendererImpl; + + using CreateRendererImplFunc = RendererImpl*(*)(); + + class NAZARA_RENDERER_API RendererImpl + { + public: + RendererImpl() = default; + virtual ~RendererImpl(); + + virtual bool IsBetterThan(const RendererImpl* other) const = 0; + + virtual RenderAPI QueryAPI() const = 0; + virtual String QueryAPIString() const = 0; + virtual UInt32 QueryAPIVersion() const = 0; + + virtual std::vector QueryRenderDevices() const = 0; + + virtual bool Prepare(const ParameterList& parameters) = 0; + }; +} + +#endif // NAZARA_RENDERER_RENDERERIMPL_HPP diff --git a/include/Nazara/Renderer/Shader.hpp b/include/Nazara/Renderer/Shader.hpp deleted file mode 100644 index aa9dabba8..000000000 --- a/include/Nazara/Renderer/Shader.hpp +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_SHADER_HPP -#define NAZARA_SHADER_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - class Shader; - class ShaderStage; - - using ShaderConstRef = ObjectRef; - using ShaderLibrary = ObjectLibrary; - using ShaderRef = ObjectRef; - - class NAZARA_RENDERER_API Shader : public RefCounted - { - friend ShaderLibrary; - friend class Renderer; - - public: - Shader(); - Shader(const Shader&) = delete; - Shader(Shader&&) = delete; - ~Shader(); - - void AttachStage(ShaderStageType stage, const ShaderStage& shaderStage); - bool AttachStageFromFile(ShaderStageType stage, const String& filePath); - bool AttachStageFromSource(ShaderStageType stage, const char* source, unsigned int length); - bool AttachStageFromSource(ShaderStageType stage, const String& source); - - void Bind() const; - - bool Create(); - void Destroy(); - - ByteArray GetBinary() const; - String GetLog() const; - String GetSourceCode(ShaderStageType stage) const; - int GetUniformLocation(const String& name) const; - int GetUniformLocation(ShaderUniform shaderUniform) const; - - bool HasStage(ShaderStageType stage) const; - - bool IsBinaryRetrievable() const; - bool IsLinked() const; - bool IsValid() const; - - bool Link(); - - bool LoadFromBinary(const void* buffer, unsigned int size); - bool LoadFromBinary(const ByteArray& byteArray); - - void SendBoolean(int location, bool value) const; - void SendColor(int location, const Color& color) const; - void SendDouble(int location, double value) const; - void SendDoubleArray(int location, const double* values, unsigned int count) const; - void SendFloat(int location, float value) const; - void SendFloatArray(int location, const float* values, unsigned int count) const; - void SendInteger(int location, int value) const; - void SendIntegerArray(int location, const int* values, unsigned int count) const; - void SendMatrix(int location, const Matrix4d& matrix) const; - void SendMatrix(int location, const Matrix4f& matrix) const; - void SendVector(int location, const Vector2d& vector) const; - void SendVector(int location, const Vector2f& vector) const; - void SendVector(int location, const Vector2i& vector) const; - void SendVector(int location, const Vector3d& vector) const; - void SendVector(int location, const Vector3f& vector) const; - void SendVector(int location, const Vector3i& vector) const; - void SendVector(int location, const Vector4d& vector) const; - void SendVector(int location, const Vector4f& vector) const; - void SendVector(int location, const Vector4i& vector) const; - void SendVectorArray(int location, const Vector2d* vectors, unsigned int count) const; - void SendVectorArray(int location, const Vector2f* vectors, unsigned int count) const; - void SendVectorArray(int location, const Vector2i* vectors, unsigned int count) const; - void SendVectorArray(int location, const Vector3d* vectors, unsigned int count) const; - void SendVectorArray(int location, const Vector3f* vectors, unsigned int count) const; - void SendVectorArray(int location, const Vector3i* vectors, unsigned int count) const; - void SendVectorArray(int location, const Vector4d* vectors, unsigned int count) const; - void SendVectorArray(int location, const Vector4f* vectors, unsigned int count) const; - void SendVectorArray(int location, const Vector4i* vectors, unsigned int count) const; - - bool Validate() const; - - // Fonctions OpenGL - unsigned int GetOpenGLID() const; - - Shader& operator=(const Shader&) = delete; - Shader& operator=(Shader&&) = delete; - - static bool IsStageSupported(ShaderStageType stage); - template static ShaderRef New(Args&&... args); - - // Signals: - NazaraSignal(OnShaderDestroy, const Shader* /*shader*/); - NazaraSignal(OnShaderRelease, const Shader* /*shader*/); - NazaraSignal(OnShaderUniformInvalidated, const Shader* /*shader*/); - - private: - bool PostLinkage(); - - static bool Initialize(); - static void Uninitialize(); - - std::vector m_attachedShaders[ShaderStageType_Max+1]; - bool m_linked; - int m_uniformLocations[ShaderUniform_Max+1]; - unsigned int m_program; - - static ShaderLibrary::LibraryMap s_library; - }; -} - -#include - -#endif // NAZARA_SHADER_HPP diff --git a/include/Nazara/Renderer/Shader.inl b/include/Nazara/Renderer/Shader.inl deleted file mode 100644 index b868c540e..000000000 --- a/include/Nazara/Renderer/Shader.inl +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include - -namespace Nz -{ - template - ShaderRef Shader::New(Args&&... args) - { - std::unique_ptr object(new Shader(std::forward(args)...)); - object->SetPersistent(false); - - return object.release(); - } -} - -#include diff --git a/include/Nazara/Renderer/ShaderStage.hpp b/include/Nazara/Renderer/ShaderStage.hpp deleted file mode 100644 index 1dfce1f51..000000000 --- a/include/Nazara/Renderer/ShaderStage.hpp +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_SHADERSTAGE_HPP -#define NAZARA_SHADERSTAGE_HPP - -#include -#include -#include -#include - -namespace Nz -{ - class NAZARA_RENDERER_API ShaderStage - { - public: - ShaderStage(); - ShaderStage(ShaderStageType stage); - ShaderStage(const ShaderStage&) = delete; - ShaderStage(ShaderStage&& stage); - ~ShaderStage(); - - bool Compile(); - - bool Create(ShaderStageType stage); - void Destroy(); - - String GetLog() const; - String GetSource() const; - - bool IsCompiled() const; - bool IsValid() const; - - void SetSource(const char* source, unsigned int length); - void SetSource(const String& source); - bool SetSourceFromFile(const String& filePath); - - ShaderStage& operator=(const ShaderStage&) = delete; - ShaderStage& operator=(ShaderStage&& shader); - - // Fonctions OpenGL - unsigned int GetOpenGLID() const; - - static bool IsSupported(ShaderStageType stage); - - private: - ShaderStageType m_stage; - bool m_compiled; - unsigned int m_id; - }; -} - -#endif // NAZARA_SHADERSTAGE_HPP diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp deleted file mode 100644 index 2fd368b53..000000000 --- a/include/Nazara/Renderer/Texture.hpp +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_TEXTURE_HPP -#define NAZARA_TEXTURE_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - class Texture; - - using TextureConstRef = ObjectRef; - using TextureLibrary = ObjectLibrary; - using TextureManager = ResourceManager; - using TextureRef = ObjectRef; - - struct TextureImpl; - - class NAZARA_RENDERER_API Texture : public AbstractImage, public RefCounted, public Resource - { - friend TextureLibrary; - friend TextureManager; - friend class Renderer; - - public: - Texture() = default; - Texture(ImageType type, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth = 1, UInt8 levelCount = 1); - explicit Texture(const Image& image); - Texture(const Texture&) = delete; - Texture(Texture&&) = delete; - ~Texture(); - - bool Create(ImageType type, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth = 1, UInt8 levelCount = 1); - void Destroy(); - - bool Download(Image* image) const; - - bool EnableMipmapping(bool enable); - - void EnsureMipmapsUpdate() const; - - unsigned int GetDepth(UInt8 level = 0) const; - PixelFormatType GetFormat() const; - unsigned int GetHeight(UInt8 level = 0) const; - UInt8 GetLevelCount() const; - UInt8 GetMaxLevel() const; - std::size_t GetMemoryUsage() const; - std::size_t GetMemoryUsage(UInt8 level) const; - Vector3ui GetSize(UInt8 level = 0) const; - ImageType GetType() const; - unsigned int GetWidth(UInt8 level = 0) const; - - bool HasMipmaps() const; - - void InvalidateMipmaps(); - bool IsValid() const; - - // Load - bool LoadFromFile(const String& filePath, const ImageParams& params = ImageParams(), bool generateMipmaps = true); - bool LoadFromImage(const Image& image, bool generateMipmaps = true); - bool LoadFromMemory(const void* data, std::size_t size, const ImageParams& params = ImageParams(), bool generateMipmaps = true); - bool LoadFromStream(Stream& stream, const ImageParams& params = ImageParams(), bool generateMipmaps = true); - - // LoadArray - bool LoadArrayFromFile(const String& filePath, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2)); - bool LoadArrayFromImage(const Image& image, bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2)); - bool LoadArrayFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2)); - bool LoadArrayFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const Vector2ui& atlasSize = Vector2ui(2, 2)); - - // LoadCubemap - bool LoadCubemapFromFile(const String& filePath, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams()); - bool LoadCubemapFromImage(const Image& image, bool generateMipmaps = true, const CubemapParams& params = CubemapParams()); - bool LoadCubemapFromMemory(const void* data, std::size_t size, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams()); - bool LoadCubemapFromStream(Stream& stream, const ImageParams& imageParams = ImageParams(), bool generateMipmaps = true, const CubemapParams& cubemapParams = CubemapParams()); - - // LoadFace - bool LoadFaceFromFile(CubemapFace face, const String& filePath, const ImageParams& params = ImageParams()); - bool LoadFaceFromMemory(CubemapFace face, const void* data, std::size_t size, const ImageParams& params = ImageParams()); - bool LoadFaceFromStream(CubemapFace face, Stream& stream, const ImageParams& params = ImageParams()); - - // Save - bool SaveToFile(const String& filePath, const ImageParams& params = ImageParams()); - bool SaveToStream(Stream& stream, const String& format, const ImageParams& params = ImageParams()); - - bool SetMipmapRange(UInt8 minLevel, UInt8 maxLevel); - - bool Update(const Image& image, UInt8 level = 0); - bool Update(const Image& image, const Boxui& box, UInt8 level = 0); - bool Update(const Image& image, const Rectui& rect, unsigned int z = 0, UInt8 level = 0); - bool Update(const UInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0); - bool Update(const UInt8* pixels, const Boxui& box, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0); - bool Update(const UInt8* pixels, const Rectui& rect, unsigned int z = 0, unsigned int srcWidth = 0, unsigned int srcHeight = 0, UInt8 level = 0); - - // Fonctions OpenGL - unsigned int GetOpenGLID() const; - - Texture& operator=(const Texture&) = delete; - Texture& operator=(Texture&&) = delete; - - static bool IsFormatSupported(PixelFormatType format); - static bool IsMipmappingSupported(); - static bool IsTypeSupported(ImageType type); - template static TextureRef New(Args&&... args); - - // Signals: - NazaraSignal(OnTextureDestroy, const Texture* /*texture*/); - NazaraSignal(OnTextureRelease, const Texture* /*texture*/); - - private: - bool CreateTexture(bool proxy); - - static bool Initialize(); - static void Uninitialize(); - - TextureImpl* m_impl = nullptr; - - static TextureLibrary::LibraryMap s_library; - static TextureManager::ManagerMap s_managerMap; - static TextureManager::ManagerParams s_managerParameters; - }; -} - -#include - -#endif // NAZARA_TEXTURE_HPP diff --git a/include/Nazara/Renderer/Texture.inl b/include/Nazara/Renderer/Texture.inl deleted file mode 100644 index 4dc53464b..000000000 --- a/include/Nazara/Renderer/Texture.inl +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include - -namespace Nz -{ - template - TextureRef Texture::New(Args&&... args) - { - std::unique_ptr object(new Texture(std::forward(args)...)); - object->SetPersistent(false); - - return object.release(); - } - -} -#include diff --git a/include/Nazara/Renderer/TextureSampler.hpp b/include/Nazara/Renderer/TextureSampler.hpp deleted file mode 100644 index 21675e6c9..000000000 --- a/include/Nazara/Renderer/TextureSampler.hpp +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_TEXTURESAMPLER_HPP -#define NAZARA_TEXTURESAMPLER_HPP - -#include -#include -#include - -namespace Nz -{ - class Texture; - - class NAZARA_RENDERER_API TextureSampler - { - friend class Renderer; - - public: - TextureSampler(); - TextureSampler(const TextureSampler& sampler) = default; - - UInt8 GetAnisotropicLevel() const; - SamplerFilter GetFilterMode() const; - SamplerWrap GetWrapMode() const; - - void SetAnisotropyLevel(UInt8 anisotropyLevel); - void SetFilterMode(SamplerFilter filterMode); - void SetWrapMode(SamplerWrap wrapMode); - - TextureSampler& operator=(const TextureSampler& sampler) = default; - - static UInt8 GetDefaultAnisotropicLevel(); - static SamplerFilter GetDefaultFilterMode(); - static SamplerWrap GetDefaultWrapMode(); - - static void SetDefaultAnisotropyLevel(UInt8 anisotropyLevel); - static void SetDefaultFilterMode(SamplerFilter filterMode); - static void SetDefaultWrapMode(SamplerWrap wrapMode); - - private: - void Apply(const Texture* texture) const; - void Bind(unsigned int unit) const; - unsigned int GetOpenGLID() const; - void UpdateSamplerId() const; - bool UseMipmaps(bool mipmaps); - - static bool Initialize(); - static void Uninitialize(); - - SamplerFilter m_filterMode; - SamplerWrap m_wrapMode; - UInt8 m_anisotropicLevel; - bool m_mipmaps; - mutable unsigned int m_samplerId; - - static SamplerFilter s_defaultFilterMode; - static SamplerWrap s_defaultWrapMode; - static UInt8 s_defaultAnisotropyLevel; - }; -} - -#endif // NAZARA_TEXTURESAMPLER_HPP diff --git a/include/Nazara/Renderer/UberShader.hpp b/include/Nazara/Renderer/UberShader.hpp deleted file mode 100644 index 541715895..000000000 --- a/include/Nazara/Renderer/UberShader.hpp +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_UBERSHADER_HPP -#define NAZARA_UBERSHADER_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - class UberShader; - - using UberShaderConstRef = ObjectRef; - using UberShaderLibrary = ObjectLibrary; - using UberShaderRef = ObjectRef; - - class NAZARA_RENDERER_API UberShader : public RefCounted - { - friend UberShaderLibrary; - friend class Renderer; - - public: - UberShader() = default; - UberShader(const UberShader&) = delete; - UberShader(UberShader&&) = delete; - virtual ~UberShader(); - - virtual UberShaderInstance* Get(const ParameterList& parameters) const = 0; - - UberShader& operator=(const UberShader&) = delete; - UberShader& operator=(UberShader&&) = delete; - - // Signals: - NazaraSignal(OnUberShaderRelease, const UberShader* /*uberShader*/); - - private: - static bool Initialize(); - static void Uninitialize(); - - static UberShaderLibrary::LibraryMap s_library; - }; -} - -#endif // NAZARA_UBERSHADER_HPP diff --git a/include/Nazara/Renderer/UberShaderInstance.hpp b/include/Nazara/Renderer/UberShaderInstance.hpp deleted file mode 100644 index 080cb8294..000000000 --- a/include/Nazara/Renderer/UberShaderInstance.hpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_UBERSHADERINSTANCE_HPP -#define NAZARA_UBERSHADERINSTANCE_HPP - -#include -#include - -namespace Nz -{ - class NAZARA_RENDERER_API UberShaderInstance - { - public: - UberShaderInstance(const Shader* shader); - virtual ~UberShaderInstance(); - - virtual bool Activate() const = 0; - - const Shader* GetShader() const; - - protected: - ShaderConstRef m_shader; - }; -} - -#endif // NAZARA_UBERSHADERINSTANCE_HPP diff --git a/include/Nazara/Renderer/UberShaderInstancePreprocessor.hpp b/include/Nazara/Renderer/UberShaderInstancePreprocessor.hpp deleted file mode 100644 index 9a0c8a6f9..000000000 --- a/include/Nazara/Renderer/UberShaderInstancePreprocessor.hpp +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_UBERSHADERINSTANCEPREPROCESSOR_HPP -#define NAZARA_UBERSHADERINSTANCEPREPROCESSOR_HPP - -#include -#include - -namespace Nz -{ - class NAZARA_RENDERER_API UberShaderInstancePreprocessor : public UberShaderInstance - { - public: - UberShaderInstancePreprocessor(const Shader* shader); - virtual ~UberShaderInstancePreprocessor(); - - bool Activate() const; - }; -} - -#endif // NAZARA_UBERSHADERINSTANCEPREPROCESSOR_HPP diff --git a/include/Nazara/Renderer/UberShaderPreprocessor.hpp b/include/Nazara/Renderer/UberShaderPreprocessor.hpp deleted file mode 100644 index 1411b731c..000000000 --- a/include/Nazara/Renderer/UberShaderPreprocessor.hpp +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_UBERSHADERPREPROCESSOR_HPP -#define NAZARA_UBERSHADERPREPROCESSOR_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - class UberShaderPreprocessor; - - using UberShaderPreprocessorConstRef = ObjectRef; - using UberShaderPreprocessorRef = ObjectRef; - - class NAZARA_RENDERER_API UberShaderPreprocessor : public UberShader - { - public: - UberShaderPreprocessor() = default; - ~UberShaderPreprocessor(); - - UberShaderInstance* Get(const ParameterList& parameters) const; - - void SetShader(ShaderStageType stage, const String& source, const String& shaderFlags, const String& requiredFlags = String()); - bool SetShaderFromFile(ShaderStageType stage, const String& filePath, const String& shaderFlags, const String& requiredFlags = String()); - - static bool IsSupported(); - template static UberShaderPreprocessorRef New(Args&&... args); - - // Signals: - NazaraSignal(OnUberShaderPreprocessorRelease, const UberShaderPreprocessor* /*uberShaderPreprocessor*/); - - private: - struct CachedShader - { - mutable std::unordered_map cache; - std::unordered_map flags; - UInt32 requiredFlags; - String source; - bool present = false; - }; - - mutable std::unordered_map m_cache; - std::unordered_map m_flags; - CachedShader m_shaders[ShaderStageType_Max+1]; - }; -} - -#include - -#endif // NAZARA_UBERSHADERPREPROCESSOR_HPP diff --git a/include/Nazara/Renderer/UberShaderPreprocessor.inl b/include/Nazara/Renderer/UberShaderPreprocessor.inl deleted file mode 100644 index 1e6528775..000000000 --- a/include/Nazara/Renderer/UberShaderPreprocessor.inl +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include - -namespace Nz -{ - template - UberShaderPreprocessorRef UberShaderPreprocessor::New(Args&&... args) - { - std::unique_ptr object(new UberShaderPreprocessor(std::forward(args)...)); - object->SetPersistent(false); - - return object.release(); - } -} - -#include diff --git a/include/Nazara/Vulkan.hpp b/include/Nazara/Vulkan.hpp deleted file mode 100644 index a19279f89..000000000 --- a/include/Nazara/Vulkan.hpp +++ /dev/null @@ -1,60 +0,0 @@ -// This file was automatically generated on 20 Jul 2016 at 13:49:17 - -/* - Nazara Engine - Vulkan - - Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) - - Permission is hereby granted, free of charge, to any person obtaining a copy of - this software and associated documentation files (the "Software"), to deal in - the Software without restriction, including without limitation the rights to - use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is furnished to do - so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. -*/ - -#pragma once - -#ifndef NAZARA_GLOBAL_VULKAN_HPP -#define NAZARA_GLOBAL_VULKAN_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#endif // NAZARA_GLOBAL_VULKAN_HPP diff --git a/include/Nazara/VulkanRenderer.hpp b/include/Nazara/VulkanRenderer.hpp new file mode 100644 index 000000000..a2973a5fc --- /dev/null +++ b/include/Nazara/VulkanRenderer.hpp @@ -0,0 +1,61 @@ +// This file was automatically generated on 17 Aug 2016 at 14:07:55 + +/* + Nazara Engine - Vulkan + + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#pragma once + +#ifndef NAZARA_GLOBAL_VULKANRENDERER_HPP +#define NAZARA_GLOBAL_VULKANRENDERER_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // NAZARA_GLOBAL_VULKANRENDERER_HPP diff --git a/include/Nazara/VulkanRenderer/Config.hpp b/include/Nazara/VulkanRenderer/Config.hpp new file mode 100644 index 000000000..12d6c6663 --- /dev/null +++ b/include/Nazara/VulkanRenderer/Config.hpp @@ -0,0 +1,53 @@ +/* + Nazara Engine - Vulkan + + Copyright (C) 2015 Jérôme "Lynix" Leclercq (Lynix680@gmail.com) + + Permission is hereby granted, free of charge, to any person obtaining a copy of + this software and associated documentation files (the "Software"), to deal in + the Software without restriction, including without limitation the rights to + use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies + of the Software, and to permit persons to whom the Software is furnished to do + so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + +#pragma once + +#ifndef NAZARA_CONFIG_VULKANRENDERER_HPP +#define NAZARA_CONFIG_VULKANRENDERER_HPP + +/// Chaque modification d'un paramètre du module nécessite une recompilation de celui-ci + +// Utilise le MemoryManager pour gérer les allocations dynamiques (détecte les leaks au prix d'allocations/libérations dynamiques plus lentes) +#define NAZARA_VULKANRENDERER_MANAGE_MEMORY 0 + +// Active les tests de sécurité basés sur le code (Conseillé pour le développement) +#define NAZARA_VULKANRENDERER_SAFE 1 + +/// Chaque modification d'un paramètre ci-dessous implique une modification (souvent mineure) du code + +/// Vérification des valeurs et types de certaines constantes +#include + +#if !defined(NAZARA_STATIC) + #ifdef NAZARA_VULKANRENDERER_BUILD + #define NAZARA_VULKANRENDERER_API NAZARA_EXPORT + #else + #define NAZARA_VULKANRENDERER_API NAZARA_IMPORT + #endif +#else + #define NAZARA_VULKANRENDERER_API +#endif + +#endif // NAZARA_CONFIG_MODULENAME_HPP diff --git a/include/Nazara/VulkanRenderer/ConfigCheck.hpp b/include/Nazara/VulkanRenderer/ConfigCheck.hpp new file mode 100644 index 000000000..600d214dd --- /dev/null +++ b/include/Nazara/VulkanRenderer/ConfigCheck.hpp @@ -0,0 +1,22 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_CONFIG_CHECK_VULKANE_HPP +#define NAZARA_CONFIG_CHECK_VULKANE_HPP + +/// Ce fichier sert à vérifier la valeur des constantes du fichier Config.hpp + +#include +#define CheckType(name, type, err) static_assert(std::is_ ##type ::value, #type err) +#define CheckTypeAndVal(name, type, op, val, err) static_assert(std::is_ ##type ::value && name op val, #type err) + +// On force la valeur de MANAGE_MEMORY en mode debug +#if defined(NAZARA_DEBUG) && !NAZARA_VULKANRENDERER_MANAGE_MEMORY + #undef NAZARA_MODULENAME_MANAGE_MEMORY + #define NAZARA_MODULENAME_MANAGE_MEMORY 0 +#endif + +#endif // NAZARA_CONFIG_CHECK_VULKANRENDERER_HPP diff --git a/include/Nazara/VulkanRenderer/Debug.hpp b/include/Nazara/VulkanRenderer/Debug.hpp new file mode 100644 index 000000000..795aa7c7d --- /dev/null +++ b/include/Nazara/VulkanRenderer/Debug.hpp @@ -0,0 +1,8 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#if NAZARA_MODULENAME_MANAGE_MEMORY + #include +#endif diff --git a/include/Nazara/VulkanRenderer/DebugOff.hpp b/include/Nazara/VulkanRenderer/DebugOff.hpp new file mode 100644 index 000000000..a2e247323 --- /dev/null +++ b/include/Nazara/VulkanRenderer/DebugOff.hpp @@ -0,0 +1,9 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +// On suppose que Debug.hpp a déjà été inclus, tout comme Config.hpp +#if NAZARA_MODULENAME_MANAGE_MEMORY + #undef delete + #undef new +#endif diff --git a/include/Nazara/VulkanRenderer/RenderTarget.hpp b/include/Nazara/VulkanRenderer/RenderTarget.hpp new file mode 100644 index 000000000..c8e6b27fa --- /dev/null +++ b/include/Nazara/VulkanRenderer/RenderTarget.hpp @@ -0,0 +1,60 @@ +// Copyright (C) 201 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_RENDERTARGET_HPP +#define NAZARA_RENDERTARGET_HPP + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class Renderer; + + class NAZARA_VULKANRENDERER_API RenderTarget + { + friend Renderer; + + public: + RenderTarget() = default; + RenderTarget(const RenderTarget&) = delete; + RenderTarget(RenderTarget&&) = delete; ///TOOD? + virtual ~RenderTarget(); + + virtual bool Acquire(UInt32* imageIndex) const = 0; + + virtual void BuildPreRenderCommands(UInt32 imageIndex, Vk::CommandBuffer& commandBuffer) = 0; + virtual void BuildPostRenderCommands(UInt32 imageIndex, Vk::CommandBuffer& commandBuffer) = 0; + + virtual const Vk::Framebuffer& GetFrameBuffer(UInt32 imageIndex) const = 0; + virtual UInt32 GetFramebufferCount() const = 0; + + const Vk::RenderPass& GetRenderPass() const { return m_renderPass; } + + const Vk::Semaphore& GetRenderSemaphore() const { return m_imageReadySemaphore; } + + virtual void Present(UInt32 imageIndex) = 0; + + RenderTarget& operator=(const RenderTarget&) = delete; + RenderTarget& operator=(RenderTarget&&) = delete; ///TOOD? + + // Signals: + NazaraSignal(OnRenderTargetRelease, const RenderTarget* /*renderTarget*/); + NazaraSignal(OnRenderTargetSizeChange, const RenderTarget* /*renderTarget*/); + + protected: + Vk::RenderPass m_renderPass; + Vk::Semaphore m_imageReadySemaphore; + }; +} + +#endif // NAZARA_RENDERTARGET_HPP diff --git a/include/Nazara/VulkanRenderer/RenderWindow.hpp b/include/Nazara/VulkanRenderer/RenderWindow.hpp new file mode 100644 index 000000000..0b7f0878e --- /dev/null +++ b/include/Nazara/VulkanRenderer/RenderWindow.hpp @@ -0,0 +1,91 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_RENDERWINDOW_HPP +#define NAZARA_RENDERWINDOW_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_VULKANRENDERER_API RenderWindow : public RenderTarget, public Window + { + public: + RenderWindow(); + RenderWindow(VideoMode mode, const String& title, UInt32 style = WindowStyle_Default); + RenderWindow(WindowHandle handle); + RenderWindow(const RenderWindow&) = delete; + RenderWindow(RenderWindow&&) = delete; ///TODO + virtual ~RenderWindow(); + + bool Acquire(UInt32* index) const override; + + void BuildPreRenderCommands(UInt32 imageIndex, Vk::CommandBuffer& commandBuffer) override; + void BuildPostRenderCommands(UInt32 imageIndex, Vk::CommandBuffer& commandBuffer) override; + + bool Create(VideoMode mode, const String& title, UInt32 style = WindowStyle_Default); + bool Create(WindowHandle handle); + + const Vk::Framebuffer& GetFrameBuffer(UInt32 imageIndex) const override; + UInt32 GetFramebufferCount() const; + const Vk::DeviceHandle& GetDevice() const; + UInt32 GetPresentableFamilyQueue() const; + const Vk::Surface& GetSurface() const; + const Vk::Swapchain& GetSwapchain() const; + + void Present(UInt32 imageIndex) override; + + bool IsValid() const; + + void SetDepthStencilFormats(std::vector pixelFormat); + void SetPhysicalDevice(VkPhysicalDevice device); + + RenderWindow& operator=(const RenderWindow&) = delete; + RenderWindow& operator=(RenderWindow&&) = delete; ///TODO + + private: + bool OnWindowCreated() override; + void OnWindowDestroy() override; + void OnWindowResized() override; + + bool SetupDepthBuffer(); + bool SetupRenderPass(); + bool SetupSwapchain(); + + Clock m_clock; + VkColorSpaceKHR m_colorSpace; + VkFormat m_colorFormat; + VkFormat m_depthStencilFormat; + VkPhysicalDevice m_forcedPhysicalDevice; + std::vector m_wantedDepthStencilFormats; + std::vector m_frameBuffers; + Vk::DeviceHandle m_device; + Vk::DeviceMemory m_depthBufferMemory; + Vk::Image m_depthBuffer; + Vk::ImageView m_depthBufferView; + Vk::Queue m_presentQueue; + Vk::Surface m_surface; + Vk::Swapchain m_swapchain; + UInt32 m_presentableFamilyQueue; + }; +} + +#endif // NAZARA_RENDERWINDOW_HPP diff --git a/include/Nazara/VulkanRenderer/VkBuffer.hpp b/include/Nazara/VulkanRenderer/VkBuffer.hpp new file mode 100644 index 000000000..9f280f655 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkBuffer.hpp @@ -0,0 +1,46 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKBUFFER_HPP +#define NAZARA_VULKANRENDERER_VKBUFFER_HPP + +#include +#include + +namespace Nz +{ + namespace Vk + { + class Buffer : public DeviceObject + { + friend DeviceObject; + + public: + Buffer() = default; + Buffer(const Buffer&) = delete; + Buffer(Buffer&&) = default; + ~Buffer() = default; + + bool BindBufferMemory(VkDeviceMemory memory, VkDeviceSize offset = 0); + + using DeviceObject::Create; + inline bool Create(const DeviceHandle& device, VkBufferCreateFlags flags, VkDeviceSize size, VkBufferUsageFlags usage, const VkAllocationCallbacks* allocator = nullptr); + + VkMemoryRequirements GetMemoryRequirements() const; + + Buffer& operator=(const Buffer&) = delete; + Buffer& operator=(Buffer&&) = delete; + + private: + static inline VkResult CreateHelper(const DeviceHandle& device, const VkBufferCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkBuffer* handle); + static inline void DestroyHelper(const DeviceHandle& device, VkBuffer handle, const VkAllocationCallbacks* allocator); + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKBUFFER_HPP diff --git a/include/Nazara/VulkanRenderer/VkBuffer.inl b/include/Nazara/VulkanRenderer/VkBuffer.inl new file mode 100644 index 000000000..2ac598738 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkBuffer.inl @@ -0,0 +1,62 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + inline bool Buffer::BindBufferMemory(VkDeviceMemory memory, VkDeviceSize offset) + { + m_lastErrorCode = m_device->vkBindBufferMemory(*m_device, m_handle, memory, offset); + if (m_lastErrorCode != VK_SUCCESS) + { + NazaraError("Failed to bind buffer memory"); + return false; + } + + return true; + } + + inline bool Buffer::Create(const DeviceHandle& device, VkBufferCreateFlags flags, VkDeviceSize size, VkBufferUsageFlags usage, const VkAllocationCallbacks* allocator) + { + VkBufferCreateInfo createInfo = { + VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + flags, // VkBufferCreateFlags flags; + size, // VkDeviceSize size; + usage, // VkBufferUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 0, // uint32_t queueFamilyIndexCount; + nullptr // const uint32_t* pQueueFamilyIndices; + }; + + return Create(device, createInfo, allocator); + } + + inline VkMemoryRequirements Buffer::GetMemoryRequirements() const + { + NazaraAssert(IsValid(), "Invalid buffer"); + + VkMemoryRequirements memoryRequirements; + m_device->vkGetBufferMemoryRequirements(*m_device, m_handle, &memoryRequirements); + + return memoryRequirements; + } + + inline VkResult Buffer::CreateHelper(const DeviceHandle& device, const VkBufferCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkBuffer* handle) + { + return device->vkCreateBuffer(*device, createInfo, allocator, handle); + } + + inline void Buffer::DestroyHelper(const DeviceHandle& device, VkBuffer handle, const VkAllocationCallbacks* allocator) + { + return device->vkDestroyBuffer(*device, handle, allocator); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkCommandBuffer.hpp b/include/Nazara/VulkanRenderer/VkCommandBuffer.hpp new file mode 100644 index 000000000..dc88f13da --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkCommandBuffer.hpp @@ -0,0 +1,100 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKCOMMANDBUFFER_HPP +#define NAZARA_VULKANRENDERER_VKCOMMANDBUFFER_HPP + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + class CommandBuffer + { + friend CommandPool; + + public: + inline CommandBuffer(); + CommandBuffer(const CommandBuffer&) = delete; + inline CommandBuffer(CommandBuffer&& commandBuffer); + inline ~CommandBuffer(); + + inline bool Begin(const VkCommandBufferBeginInfo& info); + inline bool Begin(VkCommandBufferUsageFlags flags); + inline bool Begin(VkCommandBufferUsageFlags flags, const VkCommandBufferInheritanceInfo& inheritanceInfo); + inline bool Begin(VkCommandBufferUsageFlags flags, VkRenderPass renderPass, UInt32 subpass, VkFramebuffer framebuffer, bool occlusionQueryEnable, VkQueryControlFlags queryFlags, VkQueryPipelineStatisticFlags pipelineStatistics); + inline bool Begin(VkCommandBufferUsageFlags flags, bool occlusionQueryEnable, VkQueryControlFlags queryFlags, VkQueryPipelineStatisticFlags pipelineStatistics); + + inline void BeginRenderPass(const VkRenderPassBeginInfo& beginInfo, VkSubpassContents contents = VK_SUBPASS_CONTENTS_INLINE); + + inline void BindDescriptorSet(VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, UInt32 firstSet, const VkDescriptorSet& descriptorSets); + inline void BindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, UInt32 firstSet, UInt32 descriptorSetCount, const VkDescriptorSet* descriptorSets); + inline void BindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, UInt32 firstSet, UInt32 descriptorSetCount, const VkDescriptorSet* descriptorSets, UInt32 dynamicOffsetCount, const UInt32* dynamicOffsets); + inline void BindIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType); + inline void BindPipeline(VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline); + inline void BindVertexBuffer(UInt32 binding, const VkBuffer buffer, const VkDeviceSize offset); + inline void BindVertexBuffers(UInt32 firstBinding, UInt32 bindingCount, const VkBuffer* buffer, const VkDeviceSize* offset); + + inline void ClearAttachment(const VkClearAttachment& attachment, const VkClearRect& rect); + inline void ClearAttachments(UInt32 attachmentCount, const VkClearAttachment* attachments, UInt32 rectCount, const VkClearRect* rects); + + inline void ClearColorImage(VkImage image, VkImageLayout imageLayout, const VkClearColorValue& color, const VkImageSubresourceRange& range); + inline void ClearColorImage(VkImage image, VkImageLayout imageLayout, const VkClearColorValue& color, UInt32 rangeCount, const VkImageSubresourceRange* ranges); + + inline void ClearDepthStencilImage(VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue& depthStencil, const VkImageSubresourceRange& range); + inline void ClearDepthStencilImage(VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue& depthStencil, UInt32 rangeCount, const VkImageSubresourceRange* ranges); + + inline void Draw(UInt32 vertexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, UInt32 firstInstance = 0); + inline void DrawIndexed(UInt32 indexCount, UInt32 instanceCount = 1, UInt32 firstVertex = 0, Int32 vertexOffset = 0, UInt32 firstInstance = 0); + + inline bool End(); + + inline void EndRenderPass(); + + inline void Free(); + + inline void PipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, const VkImageMemoryBarrier& imageMemoryBarrier); + inline void PipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, const VkMemoryBarrier& memoryBarrier, const VkBufferMemoryBarrier& bufferMemoryBarrier, const VkImageMemoryBarrier& imageMemoryBarrier); + inline void PipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, UInt32 memoryBarrierCount, const VkMemoryBarrier* memoryBarriers, UInt32 bufferMemoryBarrierCount, const VkBufferMemoryBarrier* bufferMemoryBarriers, UInt32 imageMemoryBarrierCount, const VkImageMemoryBarrier* imageMemoryBarriers); + + inline void SetScissor(const Recti& scissorRegion); + inline void SetScissor(const VkRect2D& scissorRegion); + inline void SetScissor(UInt32 firstScissor, UInt32 scissorCount, const VkRect2D* scissors); + inline void SetViewport(const Rectf& viewport, float minDepth, float maxDepth); + inline void SetViewport(const VkViewport& viewport); + inline void SetViewport(UInt32 firstViewport, UInt32 viewportCount, const VkViewport* viewports); + + inline void SetImageLayout(VkImage image, VkImageLayout oldImageLayout, VkImageLayout newImageLayout); + inline void SetImageLayout(VkImage image, VkImageLayout oldImageLayout, VkImageLayout newImageLayout, const VkImageSubresourceRange& subresourceRange); + inline void SetImageLayout(VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkImageLayout oldImageLayout, VkImageLayout newImageLayout); + inline void SetImageLayout(VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkImageLayout oldImageLayout, VkImageLayout newImageLayout, const VkImageSubresourceRange& subresourceRange); + + inline VkResult GetLastErrorCode() const; + + CommandBuffer& operator=(const CommandBuffer&) = delete; + CommandBuffer& operator=(CommandBuffer&& commandBuffer); + + inline operator VkCommandBuffer() const; + + private: + inline CommandBuffer(CommandPool& pool, VkCommandBuffer handle); + + CommandPoolHandle m_pool; + VkAllocationCallbacks m_allocator; + VkCommandBuffer m_handle; + VkResult m_lastErrorCode; + + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKCOMMANDBUFFER_HPP diff --git a/include/Nazara/VulkanRenderer/VkCommandBuffer.inl b/include/Nazara/VulkanRenderer/VkCommandBuffer.inl new file mode 100644 index 000000000..1e425f114 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkCommandBuffer.inl @@ -0,0 +1,419 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + inline CommandBuffer::CommandBuffer() : + m_pool(), + m_handle(VK_NULL_HANDLE) + { + } + + inline CommandBuffer::CommandBuffer(CommandPool& pool, VkCommandBuffer handle) : + m_pool(&pool), + m_handle(handle) + { + } + + inline CommandBuffer::CommandBuffer(CommandBuffer&& commandBuffer) : + m_pool(std::move(commandBuffer.m_pool)), + m_allocator(commandBuffer.m_allocator), + m_handle(commandBuffer.m_handle), + m_lastErrorCode(commandBuffer.m_lastErrorCode) + { + commandBuffer.m_handle = VK_NULL_HANDLE; + } + + inline CommandBuffer::~CommandBuffer() + { + Free(); + } + + inline bool CommandBuffer::Begin(const VkCommandBufferBeginInfo& info) + { + m_lastErrorCode = m_pool->GetDevice()->vkBeginCommandBuffer(m_handle, &info); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to begin command buffer"); + return false; + } + + return true; + } + + inline bool CommandBuffer::Begin(VkCommandBufferUsageFlags flags) + { + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + nullptr, + flags, + nullptr + }; + + return Begin(beginInfo); + } + + inline bool CommandBuffer::Begin(VkCommandBufferUsageFlags flags, const VkCommandBufferInheritanceInfo& inheritanceInfo) + { + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + nullptr, + flags, + &inheritanceInfo + }; + + return Begin(beginInfo); + } + + inline bool CommandBuffer::Begin(VkCommandBufferUsageFlags flags, VkRenderPass renderPass, UInt32 subpass, VkFramebuffer framebuffer, bool occlusionQueryEnable, VkQueryControlFlags queryFlags, VkQueryPipelineStatisticFlags pipelineStatistics) + { + NazaraAssert(flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, "Continue bit is required to ignore renderPass, subpass and framebuffer"); + + VkCommandBufferInheritanceInfo inheritanceInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, + nullptr, + renderPass, + subpass, + framebuffer, + VkBool32((occlusionQueryEnable) ? VK_TRUE : VK_FALSE), + queryFlags, + pipelineStatistics + }; + + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + nullptr, + flags, + &inheritanceInfo + }; + + return Begin(beginInfo); + } + + inline bool CommandBuffer::Begin(VkCommandBufferUsageFlags flags, bool occlusionQueryEnable, VkQueryControlFlags queryFlags, VkQueryPipelineStatisticFlags pipelineStatistics) + { + NazaraAssert(flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT, "Continue bit is required to ignore renderPass, subpass and framebuffer"); + + VkCommandBufferInheritanceInfo inheritanceInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, + nullptr, + VK_NULL_HANDLE, + 0, + VK_NULL_HANDLE, + VkBool32((occlusionQueryEnable) ? VK_TRUE : VK_FALSE), + queryFlags, + pipelineStatistics + }; + + VkCommandBufferBeginInfo beginInfo = { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + nullptr, + flags, + &inheritanceInfo + }; + + return Begin(beginInfo); + } + + inline void CommandBuffer::BeginRenderPass(const VkRenderPassBeginInfo& beginInfo, VkSubpassContents contents) + { + return m_pool->GetDevice()->vkCmdBeginRenderPass(m_handle, &beginInfo, contents); + } + + inline void CommandBuffer::BindDescriptorSet(VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, UInt32 firstSet, const VkDescriptorSet& descriptorSets) + { + return BindDescriptorSets(pipelineBindPoint, layout, firstSet, 1U, &descriptorSets); + } + + inline void CommandBuffer::BindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, UInt32 firstSet, UInt32 descriptorSetCount, const VkDescriptorSet* descriptorSets) + { + return BindDescriptorSets(pipelineBindPoint, layout, firstSet, descriptorSetCount, descriptorSets, 0U, nullptr); + } + + inline void CommandBuffer::BindDescriptorSets(VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, UInt32 firstSet, UInt32 descriptorSetCount, const VkDescriptorSet* descriptorSets, UInt32 dynamicOffsetCount, const UInt32* dynamicOffsets) + { + return m_pool->GetDevice()->vkCmdBindDescriptorSets(m_handle, pipelineBindPoint, layout, firstSet, descriptorSetCount, descriptorSets, dynamicOffsetCount, dynamicOffsets); + } + + inline void CommandBuffer::BindIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) + { + return m_pool->GetDevice()->vkCmdBindIndexBuffer(m_handle, buffer, offset, indexType); + } + + inline void CommandBuffer::BindPipeline(VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) + { + return m_pool->GetDevice()->vkCmdBindPipeline(m_handle, pipelineBindPoint, pipeline); + } + + inline void CommandBuffer::BindVertexBuffer(UInt32 binding, const VkBuffer buffer, const VkDeviceSize offset) + { + return BindVertexBuffers(binding, 1, &buffer, &offset); + } + + inline void CommandBuffer::BindVertexBuffers(UInt32 firstBinding, UInt32 bindingCount, const VkBuffer* buffer, const VkDeviceSize* offset) + { + return m_pool->GetDevice()->vkCmdBindVertexBuffers(m_handle, firstBinding, bindingCount, buffer, offset); + } + + inline void CommandBuffer::ClearAttachment(const VkClearAttachment& attachment, const VkClearRect& rect) + { + return ClearAttachments(1U, &attachment, 1U, &rect); + } + + inline void CommandBuffer::ClearAttachments(UInt32 attachmentCount, const VkClearAttachment* attachments, UInt32 rectCount, const VkClearRect* rects) + { + return m_pool->GetDevice()->vkCmdClearAttachments(m_handle, attachmentCount, attachments, rectCount, rects); + } + + inline void CommandBuffer::ClearColorImage(VkImage image, VkImageLayout imageLayout, const VkClearColorValue& color, const VkImageSubresourceRange& range) + { + return ClearColorImage(image, imageLayout, color, 1U, &range); + } + + inline void CommandBuffer::ClearColorImage(VkImage image, VkImageLayout imageLayout, const VkClearColorValue& color, UInt32 rangeCount, const VkImageSubresourceRange* ranges) + { + return m_pool->GetDevice()->vkCmdClearColorImage(m_handle, image, imageLayout, &color, rangeCount, ranges); + } + + inline void CommandBuffer::ClearDepthStencilImage(VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue& depthStencil, const VkImageSubresourceRange& range) + { + return ClearDepthStencilImage(image, imageLayout, depthStencil, 1U, &range); + } + + inline void CommandBuffer::ClearDepthStencilImage(VkImage image, VkImageLayout imageLayout, const VkClearDepthStencilValue& depthStencil, UInt32 rangeCount, const VkImageSubresourceRange * ranges) + { + return m_pool->GetDevice()->vkCmdClearDepthStencilImage(m_handle, image, imageLayout, &depthStencil, rangeCount, ranges); + } + + inline void CommandBuffer::Draw(UInt32 vertexCount, UInt32 instanceCount, UInt32 firstVertex, UInt32 firstInstance) + { + return m_pool->GetDevice()->vkCmdDraw(m_handle, vertexCount, instanceCount, firstVertex, firstInstance); + } + + inline void CommandBuffer::DrawIndexed(UInt32 indexCount, UInt32 instanceCount, UInt32 firstVertex, Int32 vertexOffset, UInt32 firstInstance) + { + return m_pool->GetDevice()->vkCmdDrawIndexed(m_handle, indexCount, instanceCount, firstVertex, vertexOffset, firstInstance); + } + + inline bool CommandBuffer::End() + { + m_lastErrorCode = m_pool->GetDevice()->vkEndCommandBuffer(m_handle); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to end command buffer"); + return false; + } + + return true; + } + + inline void CommandBuffer::EndRenderPass() + { + return m_pool->GetDevice()->vkCmdEndRenderPass(m_handle); + } + + inline void CommandBuffer::Free() + { + if (m_handle) + m_pool->GetDevice()->vkFreeCommandBuffers(*m_pool->GetDevice(), *m_pool, 1, &m_handle); + } + + inline void CommandBuffer::PipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, const VkImageMemoryBarrier& imageMemoryBarrier) + { + return PipelineBarrier(srcStageMask, dstStageMask, dependencyFlags, 0, nullptr, 0, nullptr, 1, &imageMemoryBarrier); + } + + inline void CommandBuffer::PipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, const VkMemoryBarrier& memoryBarrier, const VkBufferMemoryBarrier& bufferMemoryBarrier, const VkImageMemoryBarrier& imageMemoryBarrier) + { + return PipelineBarrier(srcStageMask, dstStageMask, dependencyFlags, 1, &memoryBarrier, 1, &bufferMemoryBarrier, 1, &imageMemoryBarrier); + } + + inline void CommandBuffer::PipelineBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, UInt32 memoryBarrierCount, const VkMemoryBarrier* memoryBarriers, UInt32 bufferMemoryBarrierCount, const VkBufferMemoryBarrier* bufferMemoryBarriers, UInt32 imageMemoryBarrierCount, const VkImageMemoryBarrier* imageMemoryBarriers) + { + return m_pool->GetDevice()->vkCmdPipelineBarrier(m_handle, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, memoryBarriers, bufferMemoryBarrierCount, bufferMemoryBarriers, imageMemoryBarrierCount, imageMemoryBarriers); + } + + inline void CommandBuffer::SetScissor(const Recti& scissorRegion) + { + VkRect2D rect = { + {scissorRegion.x, scissorRegion.y}, // VkOffset2D offset + {UInt32(scissorRegion.width), UInt32(scissorRegion.height)} // VkExtent2D extent + }; + + SetScissor(rect); + } + + inline void CommandBuffer::SetScissor(const VkRect2D& scissorRegion) + { + return SetScissor(0, 1, &scissorRegion); + } + + inline void CommandBuffer::SetScissor(UInt32 firstScissor, UInt32 scissorCount, const VkRect2D* scissors) + { + return m_pool->GetDevice()->vkCmdSetScissor(m_handle, firstScissor, scissorCount, scissors); + } + + inline void CommandBuffer::SetImageLayout(VkImage image, VkImageLayout oldImageLayout, VkImageLayout newImageLayout) + { + return SetImageLayout(image, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, oldImageLayout, newImageLayout); + } + + inline void CommandBuffer::SetImageLayout(VkImage image, VkImageLayout oldImageLayout, VkImageLayout newImageLayout, const VkImageSubresourceRange& subresourceRange) + { + return SetImageLayout(image, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, oldImageLayout, newImageLayout, subresourceRange); + } + + inline void CommandBuffer::SetImageLayout(VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkImageLayout oldImageLayout, VkImageLayout newImageLayout) + { + VkImageSubresourceRange imageRange = { + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask + 0, // uint32_t baseMipLevel + 1, // uint32_t levelCount + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + }; + + return SetImageLayout(image, srcStageMask, dstStageMask, oldImageLayout, newImageLayout, imageRange); + } + + inline void CommandBuffer::SetImageLayout(VkImage image, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkImageLayout oldImageLayout, VkImageLayout newImageLayout, const VkImageSubresourceRange& subresourceRange) + { + VkAccessFlags srcAccessMask; + switch (oldImageLayout) + { + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + break; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + break; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL: + srcAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; + break; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + srcAccessMask = VK_ACCESS_SHADER_READ_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + break; + case VK_IMAGE_LAYOUT_PREINITIALIZED: + srcAccessMask = VK_ACCESS_HOST_WRITE_BIT; + break; + case VK_IMAGE_LAYOUT_GENERAL: + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: + case VK_IMAGE_LAYOUT_UNDEFINED: + default: + srcAccessMask = 0; + break; + } + + VkAccessFlags dstAccessMask; + switch (newImageLayout) + { + case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: + if (oldImageLayout != VK_IMAGE_LAYOUT_UNDEFINED) + srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + + dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + break; + case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: + dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + break; + case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: + if (srcAccessMask == 0) + srcAccessMask = VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_TRANSFER_WRITE_BIT; + + dstAccessMask = VK_ACCESS_SHADER_READ_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: + dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; + break; + case VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: + srcAccessMask |= VK_ACCESS_TRANSFER_READ_BIT; + dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; + break; + case VK_IMAGE_LAYOUT_GENERAL: + case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR: + case VK_IMAGE_LAYOUT_UNDEFINED: + default: + dstAccessMask = 0; + break; + } + + VkImageMemoryBarrier imageBarrier = { + VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, // VkStructureType sType + nullptr, // const void* pNext + srcAccessMask, // VkAccessFlags srcAccessMask + dstAccessMask, // VkAccessFlags dstAccessMask + oldImageLayout, // VkImageLayout oldLayout + newImageLayout, // VkImageLayout newLayout + VK_QUEUE_FAMILY_IGNORED, // uint32_t srcQueueFamilyIndex + VK_QUEUE_FAMILY_IGNORED, // uint32_t dstQueueFamilyIndex + image, // VkImage image + subresourceRange // VkImageSubresourceRange subresourceRange + }; + + return PipelineBarrier(srcStageMask, dstStageMask, 0, imageBarrier); + } + + inline void CommandBuffer::SetViewport(const Rectf& viewport, float minDepth, float maxDepth) + { + VkViewport rect = { + viewport.x, // float x; + viewport.y, // float y; + viewport.width, // float width; + viewport.height, // float height; + minDepth, // float minDepth; + maxDepth // float maxDepth; + }; + + SetViewport(rect); + } + + inline void CommandBuffer::SetViewport(const VkViewport& viewport) + { + return SetViewport(0, 1, &viewport); + } + + inline void CommandBuffer::SetViewport(UInt32 firstViewport, UInt32 viewportCount, const VkViewport* viewports) + { + return m_pool->GetDevice()->vkCmdSetViewport(m_handle, firstViewport, viewportCount, viewports); + } + + inline VkResult CommandBuffer::GetLastErrorCode() const + { + return m_lastErrorCode; + } + + inline CommandBuffer& CommandBuffer::operator=(CommandBuffer&& commandBuffer) + { + m_allocator = commandBuffer.m_allocator; + m_handle = commandBuffer.m_handle; + m_lastErrorCode = commandBuffer.m_lastErrorCode; + m_pool = std::move(commandBuffer.m_pool); + m_handle = commandBuffer.m_handle; + + commandBuffer.m_handle = VK_NULL_HANDLE; + + return *this; + } + + inline CommandBuffer::operator VkCommandBuffer() const + { + return m_handle; + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkCommandPool.hpp b/include/Nazara/VulkanRenderer/VkCommandPool.hpp new file mode 100644 index 000000000..178ec1fec --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkCommandPool.hpp @@ -0,0 +1,53 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKCOMMANDPOOL_HPP +#define NAZARA_VULKANRENDERER_VKCOMMANDPOOL_HPP + +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + class CommandBuffer; + class CommandPool; + + using CommandPoolHandle = ObjectHandle; + + class NAZARA_VULKANRENDERER_API CommandPool : public DeviceObject, public HandledObject + { + friend DeviceObject; + + public: + CommandPool() = default; + CommandPool(const CommandPool&) = delete; + CommandPool(CommandPool&&) = default; + ~CommandPool() = default; + + CommandBuffer AllocateCommandBuffer(VkCommandBufferLevel level); + std::vector AllocateCommandBuffers(UInt32 commandBufferCount, VkCommandBufferLevel level); + + using DeviceObject::Create; + inline bool Create(const DeviceHandle& device, UInt32 queueFamilyIndex, VkCommandPoolCreateFlags flags = 0, const VkAllocationCallbacks* allocator = nullptr); + + inline bool Reset(VkCommandPoolResetFlags flags); + + CommandPool& operator=(const CommandPool&) = delete; + CommandPool& operator=(CommandPool&&) = delete; + + private: + static inline VkResult CreateHelper(const DeviceHandle& device, const VkCommandPoolCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkCommandPool* handle); + static inline void DestroyHelper(const DeviceHandle& device, VkCommandPool handle, const VkAllocationCallbacks* allocator); + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKCOMMANDPOOL_HPP diff --git a/include/Nazara/VulkanRenderer/VkCommandPool.inl b/include/Nazara/VulkanRenderer/VkCommandPool.inl new file mode 100644 index 000000000..cba47f66b --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkCommandPool.inl @@ -0,0 +1,48 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + inline bool CommandPool::Create(const DeviceHandle& device, UInt32 queueFamilyIndex, VkCommandPoolCreateFlags flags, const VkAllocationCallbacks* allocator) + { + VkCommandPoolCreateInfo createInfo = + { + VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, + nullptr, + flags, + queueFamilyIndex + }; + + return Create(device, createInfo, allocator); + } + + inline bool CommandPool::Reset(VkCommandPoolResetFlags flags) + { + m_lastErrorCode = m_device->vkResetCommandPool(*m_device, m_handle, flags); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + return false; + + return true; + } + + inline VkResult CommandPool::CreateHelper(const DeviceHandle& device, const VkCommandPoolCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkCommandPool* handle) + { + return device->vkCreateCommandPool(*device, createInfo, allocator, handle); + } + + inline void CommandPool::DestroyHelper(const DeviceHandle& device, VkCommandPool handle, const VkAllocationCallbacks* allocator) + { + return device->vkDestroyCommandPool(*device, handle, allocator); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkDescriptorPool.hpp b/include/Nazara/VulkanRenderer/VkDescriptorPool.hpp new file mode 100644 index 000000000..b5c862ffe --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkDescriptorPool.hpp @@ -0,0 +1,52 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKDESCRIPTORPOOL_HPP +#define NAZARA_VULKANRENDERER_VKDESCRIPTORPOOL_HPP + +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + class DescriptorPool; + class DescriptorSet; + + using DescriptorPoolHandle = ObjectHandle; + + class NAZARA_VULKANRENDERER_API DescriptorPool : public DeviceObject, public HandledObject + { + friend DeviceObject; + + public: + DescriptorPool() = default; + DescriptorPool(const DescriptorPool&) = delete; + DescriptorPool(DescriptorPool&&) = default; + ~DescriptorPool() = default; + + DescriptorSet AllocateDescriptorSet(const VkDescriptorSetLayout& setLayouts); + std::vector AllocateDescriptorSets(UInt32 descriptorSetCount, const VkDescriptorSetLayout* setLayouts); + + using DeviceObject::Create; + inline bool Create(const DeviceHandle& device, UInt32 maxSets, const VkDescriptorPoolSize& poolSize, VkDescriptorPoolCreateFlags flags = 0, const VkAllocationCallbacks* allocator = nullptr); + inline bool Create(const DeviceHandle& device, UInt32 maxSets, UInt32 poolSizeCount, const VkDescriptorPoolSize* poolSize, VkDescriptorPoolCreateFlags flags = 0, const VkAllocationCallbacks* allocator = nullptr); + + DescriptorPool& operator=(const DescriptorPool&) = delete; + DescriptorPool& operator=(DescriptorPool&&) = delete; + + private: + static inline VkResult CreateHelper(const DeviceHandle& device, const VkDescriptorPoolCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkDescriptorPool* handle); + static inline void DestroyHelper(const DeviceHandle& device, VkDescriptorPool handle, const VkAllocationCallbacks* allocator); + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKDESCRIPTORPOOL_HPP diff --git a/include/Nazara/VulkanRenderer/VkDescriptorPool.inl b/include/Nazara/VulkanRenderer/VkDescriptorPool.inl new file mode 100644 index 000000000..dc41a2ce8 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkDescriptorPool.inl @@ -0,0 +1,54 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + inline bool DescriptorPool::Create(const DeviceHandle& device, UInt32 maxSets, const VkDescriptorPoolSize& poolSize, VkDescriptorPoolCreateFlags flags, const VkAllocationCallbacks* allocator) + { + VkDescriptorPoolCreateInfo createInfo = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + flags, // VkDescriptorPoolCreateFlags flags; + maxSets, // uint32_t maxSets; + 1U, // uint32_t poolSizeCount; + &poolSize // const VkDescriptorPoolSize* pPoolSizes; + }; + + return Create(device, createInfo, allocator); + } + + inline bool DescriptorPool::Create(const DeviceHandle& device, UInt32 maxSets, UInt32 poolSizeCount, const VkDescriptorPoolSize* poolSize, VkDescriptorPoolCreateFlags flags, const VkAllocationCallbacks* allocator) + { + VkDescriptorPoolCreateInfo createInfo = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + flags, // VkDescriptorPoolCreateFlags flags; + maxSets, // uint32_t maxSets; + poolSizeCount, // uint32_t poolSizeCount; + poolSize // const VkDescriptorPoolSize* pPoolSizes; + }; + + return Create(device, createInfo, allocator); + } + + inline VkResult DescriptorPool::CreateHelper(const DeviceHandle& device, const VkDescriptorPoolCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkDescriptorPool* handle) + { + return device->vkCreateDescriptorPool(*device, createInfo, allocator, handle); + } + + inline void DescriptorPool::DestroyHelper(const DeviceHandle& device, VkDescriptorPool handle, const VkAllocationCallbacks* allocator) + { + return device->vkDestroyDescriptorPool(*device, handle, allocator); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkDescriptorSet.hpp b/include/Nazara/VulkanRenderer/VkDescriptorSet.hpp new file mode 100644 index 000000000..3a4fba9dc --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkDescriptorSet.hpp @@ -0,0 +1,59 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKDESCRIPTORSET_HPP +#define NAZARA_VULKANRENDERER_VKDESCRIPTORSET_HPP + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + class DescriptorSet + { + friend DescriptorPool; + + public: + inline DescriptorSet(); + DescriptorSet(const DescriptorSet&) = delete; + inline DescriptorSet(DescriptorSet&& descriptorSet); + inline ~DescriptorSet(); + + inline void Free(); + + inline VkResult GetLastErrorCode() const; + + inline void WriteUniformDescriptor(UInt32 binding, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range); + inline void WriteUniformDescriptor(UInt32 binding, const VkDescriptorBufferInfo& bufferInfo); + inline void WriteUniformDescriptor(UInt32 binding, UInt32 arrayElement, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range); + inline void WriteUniformDescriptor(UInt32 binding, UInt32 arrayElement, const VkDescriptorBufferInfo& bufferInfo); + inline void WriteUniformDescriptors(UInt32 binding, UInt32 descriptorCount, const VkDescriptorBufferInfo* bufferInfo); + inline void WriteUniformDescriptors(UInt32 binding, UInt32 arrayElement, UInt32 descriptorCount, const VkDescriptorBufferInfo* bufferInfo); + + DescriptorSet& operator=(const DescriptorSet&) = delete; + DescriptorSet& operator=(DescriptorSet&& descriptorSet); + + inline operator VkDescriptorSet() const; + + private: + inline DescriptorSet(DescriptorPool& pool, VkDescriptorSet handle); + + DescriptorPoolHandle m_pool; + VkAllocationCallbacks m_allocator; + VkDescriptorSet m_handle; + VkResult m_lastErrorCode; + + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKDESCRIPTORSET_HPP diff --git a/include/Nazara/VulkanRenderer/VkDescriptorSet.inl b/include/Nazara/VulkanRenderer/VkDescriptorSet.inl new file mode 100644 index 000000000..bc011005c --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkDescriptorSet.inl @@ -0,0 +1,122 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + inline DescriptorSet::DescriptorSet() : + m_pool(), + m_handle(VK_NULL_HANDLE) + { + } + + inline DescriptorSet::DescriptorSet(DescriptorPool& pool, VkDescriptorSet handle) : + m_pool(&pool), + m_handle(handle) + { + } + + inline DescriptorSet::DescriptorSet(DescriptorSet&& descriptorSet) : + m_pool(std::move(descriptorSet.m_pool)), + m_allocator(descriptorSet.m_allocator), + m_handle(descriptorSet.m_handle), + m_lastErrorCode(descriptorSet.m_lastErrorCode) + { + descriptorSet.m_handle = VK_NULL_HANDLE; + } + + inline DescriptorSet::~DescriptorSet() + { + Free(); + } + + inline void DescriptorSet::Free() + { + if (m_handle) + m_pool->GetDevice()->vkFreeDescriptorSets(*m_pool->GetDevice(), *m_pool, 1, &m_handle); + } + + inline VkResult DescriptorSet::GetLastErrorCode() const + { + return m_lastErrorCode; + } + + inline void DescriptorSet::WriteUniformDescriptor(UInt32 binding, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range) + { + return WriteUniformDescriptor(binding, 0U, buffer, offset, range); + } + + inline void DescriptorSet::WriteUniformDescriptor(UInt32 binding, const VkDescriptorBufferInfo& bufferInfo) + { + return WriteUniformDescriptors(binding, 0U, 1U, &bufferInfo); + } + + inline void DescriptorSet::WriteUniformDescriptor(UInt32 binding, UInt32 arrayElement, VkBuffer buffer, VkDeviceSize offset, VkDeviceSize range) + { + VkDescriptorBufferInfo bufferInfo = + { + buffer, // VkBuffer buffer; + offset, // VkDeviceSize offset; + range // VkDeviceSize range; + }; + + return WriteUniformDescriptor(binding, arrayElement, bufferInfo); + } + + inline void DescriptorSet::WriteUniformDescriptor(UInt32 binding, UInt32 arrayElement, const VkDescriptorBufferInfo& bufferInfo) + { + return WriteUniformDescriptors(binding, arrayElement, 1U, &bufferInfo); + } + + inline void DescriptorSet::WriteUniformDescriptors(UInt32 binding, UInt32 descriptorCount, const VkDescriptorBufferInfo* bufferInfo) + { + return WriteUniformDescriptors(binding, 0U, descriptorCount, bufferInfo); + } + + inline void DescriptorSet::WriteUniformDescriptors(UInt32 binding, UInt32 arrayElement, UInt32 descriptorCount, const VkDescriptorBufferInfo* bufferInfo) + { + VkWriteDescriptorSet writeDescriptorSet = + { + VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, // VkStructureType sType; + nullptr, // const void* pNext; + m_handle, // VkDescriptorSet dstSet; + binding, // uint32_t dstBinding; + arrayElement, // uint32_t dstArrayElement; + descriptorCount, // uint32_t descriptorCount; + VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, // VkDescriptorType descriptorType; + nullptr, // const VkDescriptorImageInfo* pImageInfo; + bufferInfo, // const VkDescriptorBufferInfo* pBufferInfo; + nullptr // const VkBufferView* pTexelBufferView; + }; + + return m_pool->GetDevice()->vkUpdateDescriptorSets(*m_pool->GetDevice(), 1U, &writeDescriptorSet, 0U, nullptr); + } + + inline DescriptorSet& DescriptorSet::operator=(DescriptorSet&& descriptorSet) + { + m_allocator = descriptorSet.m_allocator; + m_handle = descriptorSet.m_handle; + m_lastErrorCode = descriptorSet.m_lastErrorCode; + m_pool = std::move(descriptorSet.m_pool); + m_handle = descriptorSet.m_handle; + + descriptorSet.m_handle = VK_NULL_HANDLE; + + return *this; + } + + inline DescriptorSet::operator VkDescriptorSet() const + { + return m_handle; + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkDescriptorSetLayout.hpp b/include/Nazara/VulkanRenderer/VkDescriptorSetLayout.hpp new file mode 100644 index 000000000..6aff14fbe --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkDescriptorSetLayout.hpp @@ -0,0 +1,43 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKDESCRIPTORSETLAYOUT_HPP +#define NAZARA_VULKANRENDERER_VKDESCRIPTORSETLAYOUT_HPP + +#include +#include + +namespace Nz +{ + namespace Vk + { + class DescriptorSetLayout : public DeviceObject + { + friend DeviceObject; + + public: + DescriptorSetLayout() = default; + DescriptorSetLayout(const DescriptorSetLayout&) = delete; + DescriptorSetLayout(DescriptorSetLayout&&) = default; + ~DescriptorSetLayout() = default; + + using DeviceObject::Create; + inline bool Create(const DeviceHandle& device, const VkDescriptorSetLayoutBinding& binding, VkDescriptorSetLayoutCreateFlags flags = 0, const VkAllocationCallbacks* allocator = nullptr); + inline bool Create(const DeviceHandle& device, UInt32 bindingCount, const VkDescriptorSetLayoutBinding* binding, VkDescriptorSetLayoutCreateFlags flags = 0, const VkAllocationCallbacks* allocator = nullptr); + + DescriptorSetLayout& operator=(const DescriptorSetLayout&) = delete; + DescriptorSetLayout& operator=(DescriptorSetLayout&&) = delete; + + private: + static inline VkResult CreateHelper(const DeviceHandle& device, const VkDescriptorSetLayoutCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkDescriptorSetLayout* handle); + static inline void DestroyHelper(const DeviceHandle& device, VkDescriptorSetLayout handle, const VkAllocationCallbacks* allocator); + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKDESCRIPTORSETLAYOUT_HPP diff --git a/include/Nazara/VulkanRenderer/VkDescriptorSetLayout.inl b/include/Nazara/VulkanRenderer/VkDescriptorSetLayout.inl new file mode 100644 index 000000000..a53956b64 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkDescriptorSetLayout.inl @@ -0,0 +1,43 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + inline bool DescriptorSetLayout::Create(const DeviceHandle& device, const VkDescriptorSetLayoutBinding& binding, VkDescriptorSetLayoutCreateFlags flags, const VkAllocationCallbacks* allocator) + { + return Create(device, 1U, &binding, flags, allocator); + } + + inline bool DescriptorSetLayout::Create(const DeviceHandle& device, UInt32 bindingCount, const VkDescriptorSetLayoutBinding* binding, VkDescriptorSetLayoutCreateFlags flags, const VkAllocationCallbacks* allocator) + { + VkDescriptorSetLayoutCreateInfo createInfo = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + flags, // VkDescriptorSetLayoutCreateFlags flags; + bindingCount, // uint32_t bindingCount; + binding // const VkDescriptorSetLayoutBinding* pBindings; + }; + + return Create(device, createInfo, allocator); + } + + inline VkResult DescriptorSetLayout::CreateHelper(const DeviceHandle& device, const VkDescriptorSetLayoutCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkDescriptorSetLayout* handle) + { + return device->vkCreateDescriptorSetLayout(*device, createInfo, allocator, handle); + } + + inline void DescriptorSetLayout::DestroyHelper(const DeviceHandle& device, VkDescriptorSetLayout handle, const VkAllocationCallbacks* allocator) + { + return device->vkDestroyDescriptorSetLayout(*device, handle, allocator); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkDevice.hpp b/include/Nazara/VulkanRenderer/VkDevice.hpp new file mode 100644 index 000000000..32928338c --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkDevice.hpp @@ -0,0 +1,232 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKDEVICE_HPP +#define NAZARA_VULKANRENDERER_VKDEVICE_HPP + +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + class Device; + class Queue; + class Instance; + + using DeviceHandle = ObjectHandle; + + class NAZARA_VULKANRENDERER_API Device : public HandledObject + { + public: + struct QueueFamilyInfo; + struct QueueInfo; + using QueueList = std::vector; + + inline Device(Instance& instance); + Device(const Device&) = delete; + Device(Device&&) = delete; + inline ~Device(); + + bool Create(VkPhysicalDevice device, const VkDeviceCreateInfo& createInfo, const VkAllocationCallbacks* allocator = nullptr); + inline void Destroy(); + + inline const std::vector& GetEnabledQueues() const; + inline const QueueList& GetEnabledQueues(UInt32 familyQueue) const; + + inline Queue GetQueue(UInt32 queueFamilyIndex, UInt32 queueIndex); + inline Instance& GetInstance(); + inline const Instance& GetInstance() const; + inline VkResult GetLastErrorCode() const; + inline VkPhysicalDevice GetPhysicalDevice() const; + + inline bool IsExtensionLoaded(const String& extensionName); + inline bool IsLayerLoaded(const String& layerName); + + inline bool WaitForIdle(); + + Device& operator=(const Device&) = delete; + Device& operator=(Device&&) = delete; + + inline operator VkDevice(); + + // Vulkan functions + #define NAZARA_VULKANRENDERER_DEVICE_FUNCTION(func) PFN_##func func + + // Vulkan core + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkAllocateCommandBuffers); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkAllocateDescriptorSets); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkAllocateMemory); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkBeginCommandBuffer); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkBindBufferMemory); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkBindImageMemory); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdBeginQuery); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdBeginRenderPass); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdBindDescriptorSets); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdBindIndexBuffer); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdBindPipeline); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdBindVertexBuffers); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdBlitImage); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdClearAttachments); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdClearColorImage); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdClearDepthStencilImage); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdCopyBuffer); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdCopyBufferToImage); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdCopyImage); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdCopyImageToBuffer); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdCopyQueryPoolResults); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdDispatch); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdDispatchIndirect); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdDraw); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdDrawIndexed); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdDrawIndexedIndirect); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdDrawIndirect); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdEndQuery); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdEndRenderPass); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdExecuteCommands); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdFillBuffer); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdNextSubpass); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdPipelineBarrier); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdPushConstants); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdResetEvent); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdResetQueryPool); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdResolveImage); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdSetBlendConstants); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdSetDepthBias); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdSetDepthBounds); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdSetEvent); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdSetLineWidth); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdSetScissor); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdSetStencilCompareMask); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdSetStencilReference); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdSetStencilWriteMask); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdSetViewport); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdUpdateBuffer); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdWaitEvents); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCmdWriteTimestamp); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateBuffer); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateBufferView); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateCommandPool); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateComputePipelines); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateDescriptorPool); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateDescriptorSetLayout); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateEvent); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateFramebuffer); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateGraphicsPipelines); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateImage); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateImageView); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreatePipelineCache); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreatePipelineLayout); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateRenderPass); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateSampler); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateSemaphore); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateShaderModule); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyBuffer); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyBufferView); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyCommandPool); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyDescriptorPool); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyDescriptorSetLayout); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyDevice); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyEvent); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyFramebuffer); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyImage); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyImageView); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyPipeline); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyPipelineCache); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyPipelineLayout); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyRenderPass); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroySampler); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroySemaphore); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroyShaderModule); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDeviceWaitIdle); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkEndCommandBuffer); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkFreeCommandBuffers); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkFreeDescriptorSets); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkFreeMemory); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkFlushMappedMemoryRanges); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkGetBufferMemoryRequirements); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkGetDeviceMemoryCommitment); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkGetDeviceQueue); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkGetEventStatus); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkGetFenceStatus); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkGetImageMemoryRequirements); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkGetImageSparseMemoryRequirements); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkGetImageSubresourceLayout); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkGetRenderAreaGranularity); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkInvalidateMappedMemoryRanges); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkMapMemory); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkMergePipelineCaches); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkQueueSubmit); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkQueueWaitIdle); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkResetCommandBuffer); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkResetCommandPool); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkResetDescriptorPool); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkResetFences); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkResetEvent); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkSetEvent); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkUnmapMemory); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkUpdateDescriptorSets); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkWaitForFences); + + // VK_KHR_display_swapchain + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateSharedSwapchainsKHR); + + // VK_KHR_surface + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroySurfaceKHR); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkGetPhysicalDeviceSurfaceFormatsKHR); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkGetPhysicalDeviceSurfaceSupportKHR); + + // VK_KHR_swapchain + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkAcquireNextImageKHR); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkCreateSwapchainKHR); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkDestroySwapchainKHR); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkGetSwapchainImagesKHR); + NAZARA_VULKANRENDERER_DEVICE_FUNCTION(vkQueuePresentKHR); + + #undef NAZARA_VULKANRENDERER_DEVICE_FUNCTION + + struct QueueInfo + { + QueueFamilyInfo* familyInfo; + VkQueue queue; + float priority; + }; + + struct QueueFamilyInfo + { + QueueList queues; + VkExtent3D minImageTransferGranularity; + VkQueueFlags flags; + UInt32 familyIndex; + UInt32 timestampValidBits; + }; + + private: + inline PFN_vkVoidFunction GetProcAddr(const char* name); + + Instance& m_instance; + VkAllocationCallbacks m_allocator; + VkDevice m_device; + VkPhysicalDevice m_physicalDevice; + VkResult m_lastErrorCode; + std::unordered_set m_loadedExtensions; + std::unordered_set m_loadedLayers; + std::vector m_enabledQueuesInfos; + std::vector m_queuesByFamily; + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKDEVICE_HPP diff --git a/include/Nazara/VulkanRenderer/VkDevice.inl b/include/Nazara/VulkanRenderer/VkDevice.inl new file mode 100644 index 000000000..f18fde6a7 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkDevice.inl @@ -0,0 +1,117 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + inline Device::Device(Instance& instance) : + m_instance(instance), + m_device(VK_NULL_HANDLE), + m_physicalDevice(VK_NULL_HANDLE) + { + } + + inline Device::~Device() + { + Destroy(); + } + + inline void Device::Destroy() + { + if (m_device != VK_NULL_HANDLE) + { + vkDeviceWaitIdle(m_device); + vkDestroyDevice(m_device, (m_allocator.pfnAllocation) ? &m_allocator : nullptr); + + m_device = VK_NULL_HANDLE; + m_physicalDevice = VK_NULL_HANDLE; + } + } + + inline const std::vector& Device::GetEnabledQueues() const + { + return m_enabledQueuesInfos; + } + + inline const Device::QueueList& Device::GetEnabledQueues(UInt32 familyQueue) const + { + NazaraAssert(familyQueue < m_enabledQueuesInfos.size(), "Invalid family queue"); + + return *m_queuesByFamily[familyQueue]; + } + + inline Queue Device::GetQueue(UInt32 queueFamilyIndex, UInt32 queueIndex) + { + VkQueue queue; + vkGetDeviceQueue(m_device, queueFamilyIndex, queueIndex, &queue); + + return Queue(CreateHandle(), queue); + } + + inline Instance& Device::GetInstance() + { + return m_instance; + } + + inline const Instance& Device::GetInstance() const + { + return m_instance; + } + + inline VkResult Device::GetLastErrorCode() const + { + return m_lastErrorCode; + } + + inline VkPhysicalDevice Device::GetPhysicalDevice() const + { + return m_physicalDevice; + } + + inline bool Device::IsExtensionLoaded(const String& extensionName) + { + return m_loadedExtensions.count(extensionName) > 0; + } + + inline bool Device::IsLayerLoaded(const String& layerName) + { + return m_loadedLayers.count(layerName) > 0; + } + + inline bool Device::WaitForIdle() + { + m_lastErrorCode = vkDeviceWaitIdle(m_device); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to wait for device idle"); + return false; + } + + return true; + } + + inline Device::operator VkDevice() + { + return m_device; + } + + inline PFN_vkVoidFunction Device::GetProcAddr(const char* name) + { + PFN_vkVoidFunction func = m_instance.GetDeviceProcAddr(m_device, name); + if (!func) + NazaraError("Failed to get " + String(name) + " address"); + + return func; + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkDeviceMemory.hpp b/include/Nazara/VulkanRenderer/VkDeviceMemory.hpp new file mode 100644 index 000000000..c2a5b72c5 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkDeviceMemory.hpp @@ -0,0 +1,51 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKDEVICEMEMORY_HPP +#define NAZARA_VULKANRENDERER_VKDEVICEMEMORY_HPP + +#include +#include + +namespace Nz +{ + namespace Vk + { + class DeviceMemory : public DeviceObject + { + friend DeviceObject; + + public: + DeviceMemory(); + DeviceMemory(const DeviceMemory&) = delete; + DeviceMemory(DeviceMemory&& memory); + ~DeviceMemory() = default; + + using DeviceObject::Create; + inline bool Create(const DeviceHandle& device, VkDeviceSize size, UInt32 memoryType, const VkAllocationCallbacks* allocator = nullptr); + inline bool Create(const DeviceHandle& device, VkDeviceSize size, UInt32 typeBits, VkFlags properties, const VkAllocationCallbacks* allocator = nullptr); + + inline void* GetMappedPointer(); + + inline bool Map(VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags = 0); + + inline void Unmap(); + + DeviceMemory& operator=(const DeviceMemory&) = delete; + DeviceMemory& operator=(DeviceMemory&&) = delete; + + private: + static inline VkResult CreateHelper(const DeviceHandle& device, const VkMemoryAllocateInfo* allocInfo, const VkAllocationCallbacks* allocator, VkDeviceMemory* handle); + static inline void DestroyHelper(const DeviceHandle& device, VkDeviceMemory handle, const VkAllocationCallbacks* allocator); + + void* m_mappedPtr; + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKDEVICEMEMORY_HPP diff --git a/include/Nazara/VulkanRenderer/VkDeviceMemory.inl b/include/Nazara/VulkanRenderer/VkDeviceMemory.inl new file mode 100644 index 000000000..2e0c26b30 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkDeviceMemory.inl @@ -0,0 +1,96 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + inline DeviceMemory::DeviceMemory() : + m_mappedPtr(nullptr) + { + } + + DeviceMemory::DeviceMemory(DeviceMemory&& memory) : + DeviceObject(std::move(memory)) + { + m_mappedPtr = memory.m_mappedPtr; + memory.m_mappedPtr = nullptr; + } + + inline bool DeviceMemory::Create(const DeviceHandle& device, VkDeviceSize size, UInt32 memoryType, const VkAllocationCallbacks* allocator) + { + VkMemoryAllocateInfo allocInfo = + { + VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + size, // VkDeviceSize allocationSize; + memoryType // uint32_t memoryTypeIndex; + }; + + return Create(device, allocInfo, allocator); + } + + inline bool DeviceMemory::Create(const DeviceHandle& device, VkDeviceSize size, UInt32 typeBits, VkFlags properties, const VkAllocationCallbacks* allocator) + { + const Vk::PhysicalDevice& deviceInfo = Vulkan::GetPhysicalDeviceInfo(device->GetPhysicalDevice()); + + UInt32 typeMask = 1; + for (UInt32 i = 0; i < VK_MAX_MEMORY_TYPES; ++i) + { + if (typeBits & typeMask) + { + if ((deviceInfo.memoryProperties.memoryTypes[i].propertyFlags & properties) == properties) + return Create(device, size, i, allocator); + } + + typeMask <<= 1; + } + + NazaraError("Failed to find a memory type suitable for typeBits: " + String::Number(typeBits) + " and properties: 0x" + String::Number(properties, 16)); + return false; + } + + inline void* DeviceMemory::GetMappedPointer() + { + return m_mappedPtr; + } + + inline bool DeviceMemory::Map(VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags) + { + m_lastErrorCode = m_device->vkMapMemory(*m_device, m_handle, offset, size, flags, &m_mappedPtr); + if (m_lastErrorCode != VK_SUCCESS) + { + NazaraError("Failed to map device memory"); + return false; + } + + return true; + } + + inline void DeviceMemory::Unmap() + { + NazaraAssert(m_mappedPtr != nullptr, "Memory is not mapped"); + + m_device->vkUnmapMemory(*m_device, m_handle); + m_mappedPtr = nullptr; + } + + inline VkResult DeviceMemory::CreateHelper(const DeviceHandle& device, const VkMemoryAllocateInfo* allocInfo, const VkAllocationCallbacks* allocator, VkDeviceMemory* handle) + { + return device->vkAllocateMemory(*device, allocInfo, allocator, handle); + } + + inline void DeviceMemory::DestroyHelper(const DeviceHandle& device, VkDeviceMemory handle, const VkAllocationCallbacks* allocator) + { + return device->vkFreeMemory(*device, handle, allocator); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkDeviceObject.hpp b/include/Nazara/VulkanRenderer/VkDeviceObject.hpp new file mode 100644 index 000000000..3778a73ea --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkDeviceObject.hpp @@ -0,0 +1,51 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKDEVICEOBJECT_HPP +#define NAZARA_VULKANRENDERER_VKDEVICEOBJECT_HPP + +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + template + class DeviceObject + { + public: + inline DeviceObject(); + DeviceObject(const DeviceObject&) = delete; + DeviceObject(DeviceObject&&); + inline ~DeviceObject(); + + inline bool Create(const DeviceHandle& device, const CreateInfo& createInfo, const VkAllocationCallbacks* allocator = nullptr); + inline void Destroy(); + + inline bool IsValid() const; + + inline const DeviceHandle& GetDevice() const; + inline VkResult GetLastErrorCode() const; + + DeviceObject& operator=(const DeviceObject&) = delete; + DeviceObject& operator=(DeviceObject&&) = delete; + + inline operator VkType() const; + + protected: + DeviceHandle m_device; + VkAllocationCallbacks m_allocator; + VkType m_handle; + mutable VkResult m_lastErrorCode; + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKDEVICEOBJECT_HPP diff --git a/include/Nazara/VulkanRenderer/VkDeviceObject.inl b/include/Nazara/VulkanRenderer/VkDeviceObject.inl new file mode 100644 index 000000000..f238d199a --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkDeviceObject.inl @@ -0,0 +1,93 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + template + inline DeviceObject::DeviceObject() : + m_handle(VK_NULL_HANDLE) + { + } + + template + inline DeviceObject::DeviceObject(DeviceObject&& object) : + m_device(std::move(object.m_device)), + m_allocator(object.m_allocator), + m_handle(object.m_handle), + m_lastErrorCode(object.m_lastErrorCode) + { + object.m_handle = VK_NULL_HANDLE; + } + + template + inline DeviceObject::~DeviceObject() + { + Destroy(); + } + + template + inline bool DeviceObject::Create(const DeviceHandle& device, const CreateInfo& createInfo, const VkAllocationCallbacks* allocator) + { + m_device = device; + m_lastErrorCode = C::CreateHelper(m_device, &createInfo, allocator, &m_handle); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to create Vulkan object"); + return false; + } + + // Store the allocator to access them when needed + if (allocator) + m_allocator = *allocator; + else + m_allocator.pfnAllocation = nullptr; + + return true; + } + + template + inline void DeviceObject::Destroy() + { + if (IsValid()) + { + C::DestroyHelper(m_device, m_handle, (m_allocator.pfnAllocation) ? &m_allocator : nullptr); + m_handle = VK_NULL_HANDLE; + } + } + + template + inline bool DeviceObject::IsValid() const + { + return m_handle != VK_NULL_HANDLE; + } + + template + inline const DeviceHandle& DeviceObject::GetDevice() const + { + return m_device; + } + + template + inline VkResult DeviceObject::GetLastErrorCode() const + { + return m_lastErrorCode; + } + + template + inline DeviceObject::operator VkType() const + { + return m_handle; + } + } +} + +#include +#include "VkDeviceObject.hpp" diff --git a/include/Nazara/VulkanRenderer/VkFramebuffer.hpp b/include/Nazara/VulkanRenderer/VkFramebuffer.hpp new file mode 100644 index 000000000..606042371 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkFramebuffer.hpp @@ -0,0 +1,39 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKFRAMEBUFFER_HPP +#define NAZARA_VULKANRENDERER_VKFRAMEBUFFER_HPP + +#include +#include + +namespace Nz +{ + namespace Vk + { + class Framebuffer : public DeviceObject + { + friend DeviceObject; + + public: + Framebuffer() = default; + Framebuffer(const Framebuffer&) = delete; + Framebuffer(Framebuffer&&) = default; + ~Framebuffer() = default; + + Framebuffer& operator=(const Framebuffer&) = delete; + Framebuffer& operator=(Framebuffer&&) = delete; + + private: + static inline VkResult CreateHelper(const DeviceHandle& device, const VkFramebufferCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkFramebuffer* handle); + static inline void DestroyHelper(const DeviceHandle& device, VkFramebuffer handle, const VkAllocationCallbacks* allocator); + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKFRAMEBUFFER_HPP diff --git a/include/Nazara/VulkanRenderer/VkFramebuffer.inl b/include/Nazara/VulkanRenderer/VkFramebuffer.inl new file mode 100644 index 000000000..961f3e0c6 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkFramebuffer.inl @@ -0,0 +1,24 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + inline VkResult Framebuffer::CreateHelper(const DeviceHandle& device, const VkFramebufferCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkFramebuffer* handle) + { + return device->vkCreateFramebuffer(*device, createInfo, allocator, handle); + } + + inline void Framebuffer::DestroyHelper(const DeviceHandle& device, VkFramebuffer handle, const VkAllocationCallbacks* allocator) + { + return device->vkDestroyFramebuffer(*device, handle, allocator); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkImage.hpp b/include/Nazara/VulkanRenderer/VkImage.hpp new file mode 100644 index 000000000..578662600 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkImage.hpp @@ -0,0 +1,43 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKIMAGE_HPP +#define NAZARA_VULKANRENDERER_VKIMAGE_HPP + +#include +#include + +namespace Nz +{ + namespace Vk + { + class Image : public DeviceObject + { + friend DeviceObject; + + public: + Image() = default; + Image(const Image&) = delete; + Image(Image&&) = default; + ~Image() = default; + + bool BindImageMemory(VkDeviceMemory memory, VkDeviceSize offset = 0); + + VkMemoryRequirements GetMemoryRequirements() const; + + Image& operator=(const Image&) = delete; + Image& operator=(Image&&) = delete; + + private: + static inline VkResult CreateHelper(const DeviceHandle& device, const VkImageCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkImage* handle); + static inline void DestroyHelper(const DeviceHandle& device, VkImage handle, const VkAllocationCallbacks* allocator); + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKIMAGE_HPP diff --git a/include/Nazara/VulkanRenderer/VkImage.inl b/include/Nazara/VulkanRenderer/VkImage.inl new file mode 100644 index 000000000..b4e0332cb --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkImage.inl @@ -0,0 +1,46 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + inline bool Image::BindImageMemory(VkDeviceMemory memory, VkDeviceSize offset) + { + m_lastErrorCode = m_device->vkBindImageMemory(*m_device, m_handle, memory, offset); + if (m_lastErrorCode != VK_SUCCESS) + { + NazaraError("Failed to bind buffer memory"); + return false; + } + + return true; + } + + inline VkMemoryRequirements Image::GetMemoryRequirements() const + { + NazaraAssert(IsValid(), "Invalid image"); + + VkMemoryRequirements memoryRequirements; + m_device->vkGetImageMemoryRequirements(*m_device, m_handle, &memoryRequirements); + + return memoryRequirements; + } + + inline VkResult Image::CreateHelper(const DeviceHandle& device, const VkImageCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkImage* handle) + { + return device->vkCreateImage(*device, createInfo, allocator, handle); + } + + inline void Image::DestroyHelper(const DeviceHandle& device, VkImage handle, const VkAllocationCallbacks* allocator) + { + return device->vkDestroyImage(*device, handle, allocator); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkImageView.hpp b/include/Nazara/VulkanRenderer/VkImageView.hpp new file mode 100644 index 000000000..8362859cc --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkImageView.hpp @@ -0,0 +1,39 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKIMAGEVIEW_HPP +#define NAZARA_VULKANRENDERER_VKIMAGEVIEW_HPP + +#include +#include + +namespace Nz +{ + namespace Vk + { + class ImageView : public DeviceObject + { + friend DeviceObject; + + public: + ImageView() = default; + ImageView(const ImageView&) = delete; + ImageView(ImageView&&) = default; + ~ImageView() = default; + + ImageView& operator=(const ImageView&) = delete; + ImageView& operator=(ImageView&&) = delete; + + private: + static inline VkResult CreateHelper(const DeviceHandle& device, const VkImageViewCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkImageView* handle); + static inline void DestroyHelper(const DeviceHandle& device, VkImageView handle, const VkAllocationCallbacks* allocator); + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKIMAGEVIEW_HPP diff --git a/include/Nazara/VulkanRenderer/VkImageView.inl b/include/Nazara/VulkanRenderer/VkImageView.inl new file mode 100644 index 000000000..8bf522c9e --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkImageView.inl @@ -0,0 +1,24 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + inline VkResult ImageView::CreateHelper(const DeviceHandle& device, const VkImageViewCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkImageView* handle) + { + return device->vkCreateImageView(*device, createInfo, allocator, handle); + } + + inline void ImageView::DestroyHelper(const DeviceHandle& device, VkImageView handle, const VkAllocationCallbacks* allocator) + { + return device->vkDestroyImageView(*device, handle, allocator); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkInstance.hpp b/include/Nazara/VulkanRenderer/VkInstance.hpp new file mode 100644 index 000000000..0e9f52f87 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkInstance.hpp @@ -0,0 +1,141 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKINSTANCE_HPP +#define NAZARA_VULKANRENDERER_VKINSTANCE_HPP + +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + class NAZARA_VULKANRENDERER_API Instance + { + public: + inline Instance(); + Instance(const Instance&) = delete; + Instance(Instance&&) = delete; + inline ~Instance(); + + bool Create(const VkInstanceCreateInfo& createInfo, const VkAllocationCallbacks* allocator = nullptr); + inline bool Create(const String& appName, UInt32 appVersion, const String& engineName, UInt32 engineVersion, const std::vector& layers, const std::vector& extensions, const VkAllocationCallbacks* allocator = nullptr); + inline void Destroy(); + + bool EnumeratePhysicalDevices(std::vector* physicalDevices); + + inline PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* name); + + inline VkPhysicalDeviceFeatures GetPhysicalDeviceFeatures(VkPhysicalDevice device); + inline VkFormatProperties GetPhysicalDeviceFormatProperties(VkPhysicalDevice device, VkFormat format); + inline bool GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* imageFormatProperties); + inline VkPhysicalDeviceMemoryProperties GetPhysicalDeviceMemoryProperties(VkPhysicalDevice device); + inline VkPhysicalDeviceProperties GetPhysicalDeviceProperties(VkPhysicalDevice device); + bool GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice device, std::vector* queueFamilyProperties); + + inline VkResult GetLastErrorCode() const; + + inline bool IsExtensionLoaded(const String& extensionName); + inline bool IsLayerLoaded(const String& layerName); + + Instance& operator=(const Instance&) = delete; + Instance& operator=(Instance&&) = delete; + + inline operator VkInstance(); + + // Vulkan functions + #define NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(func) PFN_##func func + + // Vulkan core + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateDevice); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkDestroyInstance); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkEnumeratePhysicalDevices); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetDeviceProcAddr); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceFormatProperties); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceImageFormatProperties); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceMemoryProperties); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties); + + // VK_KHR_display + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateDisplayModeKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateDisplayPlaneSurfaceKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetDisplayModePropertiesKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetDisplayPlaneCapabilitiesKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetDisplayPlaneSupportedDisplaysKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceDisplayPlanePropertiesKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceDisplayPropertiesKHR); + + // VK_KHR_surface + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkDestroySurfaceKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceFormatsKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceSurfaceSupportKHR); + + // VK_EXT_debug_report + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateDebugReportCallbackEXT); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkDestroyDebugReportCallbackEXT); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkDebugReportMessageEXT); + + #ifdef VK_USE_PLATFORM_ANDROID_KHR + // VK_KHR_android_surface + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateAndroidSurfaceKHR); + #endif + + #ifdef VK_USE_PLATFORM_MIR_KHR + // VK_KHR_mir_surface + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateMirSurfaceKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceMirPresentationSupportKHR); + #endif + + #ifdef VK_USE_PLATFORM_XCB_KHR + // VK_KHR_xcb_surface + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateXcbSurfaceKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceXcbPresentationSupportKHR); + #endif + + #ifdef VK_USE_PLATFORM_XLIB_KHR + // VK_KHR_xlib_surface + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateXlibSurfaceKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceXlibPresentationSupportKHR); + #endif + + #ifdef VK_USE_PLATFORM_WAYLAND_KHR + // VK_KHR_wayland_surface + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateWaylandSurfaceKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceWaylandPresentationSupportKHR); + #endif + + #ifdef VK_USE_PLATFORM_WIN32_KHR + // VK_KHR_win32_surface + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkCreateWin32SurfaceKHR); + NAZARA_VULKANRENDERER_INSTANCE_FUNCTION(vkGetPhysicalDeviceWin32PresentationSupportKHR); + #endif + + #undef NAZARA_VULKANRENDERER_INSTANCE_FUNCTION + + private: + inline PFN_vkVoidFunction GetProcAddr(const char* name); + + VkAllocationCallbacks m_allocator; + VkInstance m_instance; + VkResult m_lastErrorCode; + std::unordered_set m_loadedExtensions; + std::unordered_set m_loadedLayers; + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKINSTANCE_HPP diff --git a/include/Nazara/VulkanRenderer/VkInstance.inl b/include/Nazara/VulkanRenderer/VkInstance.inl new file mode 100644 index 000000000..6de0929e9 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkInstance.inl @@ -0,0 +1,143 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + inline Instance::Instance() : + m_instance(nullptr) + { + } + + inline Instance::~Instance() + { + Destroy(); + } + + inline bool Instance::Create(const String& appName, UInt32 appVersion, const String& engineName, UInt32 engineVersion, const std::vector& layers, const std::vector& extensions, const VkAllocationCallbacks* allocator) + { + VkApplicationInfo appInfo = + { + VK_STRUCTURE_TYPE_APPLICATION_INFO, + nullptr, + appName.GetConstBuffer(), + appVersion, + engineName.GetConstBuffer(), + engineVersion + }; + + VkInstanceCreateInfo instanceInfo = + { + VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + nullptr, + 0, + &appInfo, + static_cast(layers.size()), + (!layers.empty()) ? layers.data() : nullptr, + static_cast(extensions.size()), + (!extensions.empty()) ? extensions.data() : nullptr + }; + + return Create(instanceInfo, allocator); + } + + inline void Instance::Destroy() + { + if (m_instance) + { + vkDestroyInstance(m_instance, (m_allocator.pfnAllocation) ? &m_allocator : nullptr); + m_instance = nullptr; + } + } + + inline PFN_vkVoidFunction Instance::GetDeviceProcAddr(VkDevice device, const char* name) + { + PFN_vkVoidFunction func = vkGetDeviceProcAddr(device, name); + if (!func) + NazaraError("Failed to get " + String(name) + " address"); + + return func; + } + + inline VkResult Instance::GetLastErrorCode() const + { + return m_lastErrorCode; + } + + inline bool Instance::IsExtensionLoaded(const String& extensionName) + { + return m_loadedExtensions.count(extensionName) > 0; + } + + inline bool Instance::IsLayerLoaded(const String& layerName) + { + return m_loadedLayers.count(layerName) > 0; + } + + inline Instance::operator VkInstance() + { + return m_instance; + } + + inline VkPhysicalDeviceFeatures Instance::GetPhysicalDeviceFeatures(VkPhysicalDevice device) + { + VkPhysicalDeviceFeatures features; + vkGetPhysicalDeviceFeatures(device, &features); + + return features; + } + + inline VkFormatProperties Instance::GetPhysicalDeviceFormatProperties(VkPhysicalDevice device, VkFormat format) + { + VkFormatProperties formatProperties; + vkGetPhysicalDeviceFormatProperties(device, format, &formatProperties); + + return formatProperties; + } + + inline bool Instance::GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags, VkImageFormatProperties* imageFormatProperties) + { + m_lastErrorCode = vkGetPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags, imageFormatProperties); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to get physical device image format properties"); + return false; + } + + return true; + } + + inline VkPhysicalDeviceMemoryProperties Instance::GetPhysicalDeviceMemoryProperties(VkPhysicalDevice device) + { + VkPhysicalDeviceMemoryProperties memoryProperties; + vkGetPhysicalDeviceMemoryProperties(device, &memoryProperties); + + return memoryProperties; + } + + inline VkPhysicalDeviceProperties Instance::GetPhysicalDeviceProperties(VkPhysicalDevice device) + { + VkPhysicalDeviceProperties properties; + vkGetPhysicalDeviceProperties(device, &properties); + + return properties; + } + + inline PFN_vkVoidFunction Instance::GetProcAddr(const char* name) + { + PFN_vkVoidFunction func = Loader::GetInstanceProcAddr(m_instance, name); + if (!func) + NazaraError("Failed to get " + String(name) + " address"); + + return func; + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkLoader.hpp b/include/Nazara/VulkanRenderer/VkLoader.hpp new file mode 100644 index 000000000..a83eb58e1 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkLoader.hpp @@ -0,0 +1,52 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKLOADER_HPP +#define NAZARA_VULKANRENDERER_VKLOADER_HPP + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + class NAZARA_VULKANRENDERER_API Loader + { + public: + Loader() = delete; + ~Loader() = delete; + + static bool EnumerateInstanceExtensionProperties(std::vector* properties, const char* layerName = nullptr); + static bool EnumerateInstanceLayerProperties(std::vector* properties); + + static inline PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* name); + + static bool Initialize(); + static void Uninitialize(); + + // Vulkan functions + #define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(func) static PFN_##func func + + NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkCreateInstance); + NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkEnumerateInstanceExtensionProperties); + NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkEnumerateInstanceLayerProperties); + NAZARA_VULKANRENDERER_GLOBAL_FUNCTION(vkGetInstanceProcAddr); + + #undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION + + private: + static DynLib s_vulkanLib; + static VkResult s_lastErrorCode; + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKLOADER_HPP diff --git a/include/Nazara/VulkanRenderer/VkLoader.inl b/include/Nazara/VulkanRenderer/VkLoader.inl new file mode 100644 index 000000000..caad2bab3 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkLoader.inl @@ -0,0 +1,19 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + inline PFN_vkVoidFunction Loader::GetInstanceProcAddr(VkInstance instance, const char* name) + { + return vkGetInstanceProcAddr(instance, name); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkPhysicalDevice.hpp b/include/Nazara/VulkanRenderer/VkPhysicalDevice.hpp new file mode 100644 index 000000000..3caa8a179 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkPhysicalDevice.hpp @@ -0,0 +1,28 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKPHYSICALDEVICE_HPP +#define NAZARA_VULKANRENDERER_VKPHYSICALDEVICE_HPP + +#include +#include + +namespace Nz +{ + namespace Vk + { + struct PhysicalDevice + { + VkPhysicalDevice device; + VkPhysicalDeviceFeatures features; + VkPhysicalDeviceMemoryProperties memoryProperties; + VkPhysicalDeviceProperties properties; + std::vector queues; + }; + } +} + +#endif // NAZARA_VULKANRENDERER_VKPHYSICALDEVICE_HPP diff --git a/include/Nazara/VulkanRenderer/VkPipeline.hpp b/include/Nazara/VulkanRenderer/VkPipeline.hpp new file mode 100644 index 000000000..ec18dd416 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkPipeline.hpp @@ -0,0 +1,50 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKPIPELINE_HPP +#define NAZARA_VULKANRENDERER_VKPIPELINE_HPP + +#include +#include + +namespace Nz +{ + namespace Vk + { + class Pipeline + { + public: + inline Pipeline(); + Pipeline(const Pipeline&) = delete; + Pipeline(Pipeline&&); + inline ~Pipeline(); + + inline bool CreateCompute(const DeviceHandle& device, const VkComputePipelineCreateInfo& createInfo, VkPipelineCache cache = VK_NULL_HANDLE, const VkAllocationCallbacks* allocator = nullptr); + inline bool CreateGraphics(const DeviceHandle& device, const VkGraphicsPipelineCreateInfo& createInfo, VkPipelineCache cache = VK_NULL_HANDLE, const VkAllocationCallbacks* allocator = nullptr); + inline void Destroy(); + + inline const DeviceHandle& GetDevice() const; + inline VkResult GetLastErrorCode() const; + + Pipeline& operator=(const Pipeline&) = delete; + Pipeline& operator=(Pipeline&&) = delete; + + inline operator VkPipeline() const; + + protected: + inline bool Create(const DeviceHandle& device, VkResult result, const VkAllocationCallbacks* allocator); + + DeviceHandle m_device; + VkAllocationCallbacks m_allocator; + VkPipeline m_handle; + mutable VkResult m_lastErrorCode; + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKPIPELINE_HPP diff --git a/include/Nazara/VulkanRenderer/VkPipeline.inl b/include/Nazara/VulkanRenderer/VkPipeline.inl new file mode 100644 index 000000000..42c758f46 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkPipeline.inl @@ -0,0 +1,86 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + inline Pipeline::Pipeline() : + m_handle(VK_NULL_HANDLE) + { + } + + inline Pipeline::Pipeline(Pipeline&& object) : + m_device(std::move(object.m_device)), + m_allocator(object.m_allocator), + m_handle(object.m_handle), + m_lastErrorCode(object.m_lastErrorCode) + { + object.m_handle = VK_NULL_HANDLE; + } + + inline Pipeline::~Pipeline() + { + Destroy(); + } + + inline bool Pipeline::CreateCompute(const DeviceHandle& device, const VkComputePipelineCreateInfo& createInfo, VkPipelineCache cache, const VkAllocationCallbacks* allocator) + { + return Create(device, device->vkCreateComputePipelines(*device, cache, 1U, &createInfo, allocator, &m_handle), allocator); + } + + inline bool Pipeline::CreateGraphics(const DeviceHandle& device, const VkGraphicsPipelineCreateInfo& createInfo, VkPipelineCache cache, const VkAllocationCallbacks* allocator) + { + return Create(device, device->vkCreateGraphicsPipelines(*device, cache, 1U, &createInfo, allocator, &m_handle), allocator); + } + + inline void Pipeline::Destroy() + { + if (m_handle != VK_NULL_HANDLE) + { + m_device->vkDestroyPipeline(*m_device, m_handle, (m_allocator.pfnAllocation) ? &m_allocator : nullptr); + m_handle = VK_NULL_HANDLE; + } + } + + inline const DeviceHandle& Pipeline::GetDevice() const + { + return m_device; + } + + inline VkResult Pipeline::GetLastErrorCode() const + { + return m_lastErrorCode; + } + + inline Pipeline::operator VkPipeline() const + { + return m_handle; + } + + inline bool Pipeline::Create(const DeviceHandle& device, VkResult result, const VkAllocationCallbacks* allocator) + { + m_device = device; + m_lastErrorCode = result; + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to create Vulkan object"); + return false; + } + + // Store the allocator to access them when needed + if (allocator) + m_allocator = *allocator; + else + m_allocator.pfnAllocation = nullptr; + + return true; + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkPipelineCache.hpp b/include/Nazara/VulkanRenderer/VkPipelineCache.hpp new file mode 100644 index 000000000..cb60321b9 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkPipelineCache.hpp @@ -0,0 +1,39 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKPIPELINECACHE_HPP +#define NAZARA_VULKANRENDERER_VKPIPELINECACHE_HPP + +#include +#include + +namespace Nz +{ + namespace Vk + { + class PipelineCache : public DeviceObject + { + friend DeviceObject; + + public: + PipelineCache() = default; + PipelineCache(const PipelineCache&) = delete; + PipelineCache(PipelineCache&&) = default; + ~PipelineCache() = default; + + PipelineCache& operator=(const PipelineCache&) = delete; + PipelineCache& operator=(PipelineCache&&) = delete; + + private: + static inline VkResult CreateHelper(const DeviceHandle& device, const VkPipelineCacheCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkPipelineCache* handle); + static inline void DestroyHelper(const DeviceHandle& device, VkPipelineCache handle, const VkAllocationCallbacks* allocator); + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKPIPELINECACHE_HPP diff --git a/include/Nazara/VulkanRenderer/VkPipelineCache.inl b/include/Nazara/VulkanRenderer/VkPipelineCache.inl new file mode 100644 index 000000000..d37f5c8c0 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkPipelineCache.inl @@ -0,0 +1,24 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + inline VkResult PipelineCache::CreateHelper(const DeviceHandle& device, const VkPipelineCacheCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkPipelineCache* handle) + { + return device->vkCreatePipelineCache(*device, createInfo, allocator, handle); + } + + inline void PipelineCache::DestroyHelper(const DeviceHandle& device, VkPipelineCache handle, const VkAllocationCallbacks* allocator) + { + return device->vkDestroyPipelineCache(*device, handle, allocator); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkPipelineLayout.hpp b/include/Nazara/VulkanRenderer/VkPipelineLayout.hpp new file mode 100644 index 000000000..4abb54e0a --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkPipelineLayout.hpp @@ -0,0 +1,39 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKPIPELINELAYOUT_HPP +#define NAZARA_VULKANRENDERER_VKPIPELINELAYOUT_HPP + +#include +#include + +namespace Nz +{ + namespace Vk + { + class PipelineLayout : public DeviceObject + { + friend DeviceObject; + + public: + PipelineLayout() = default; + PipelineLayout(const PipelineLayout&) = delete; + PipelineLayout(PipelineLayout&&) = default; + ~PipelineLayout() = default; + + PipelineLayout& operator=(const PipelineLayout&) = delete; + PipelineLayout& operator=(PipelineLayout&&) = delete; + + private: + static inline VkResult CreateHelper(const DeviceHandle& device, const VkPipelineLayoutCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkPipelineLayout* handle); + static inline void DestroyHelper(const DeviceHandle& device, VkPipelineLayout handle, const VkAllocationCallbacks* allocator); + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKPIPELINELAYOUT_HPP diff --git a/include/Nazara/VulkanRenderer/VkPipelineLayout.inl b/include/Nazara/VulkanRenderer/VkPipelineLayout.inl new file mode 100644 index 000000000..22ceb988b --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkPipelineLayout.inl @@ -0,0 +1,24 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + inline VkResult PipelineLayout::CreateHelper(const DeviceHandle& device, const VkPipelineLayoutCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkPipelineLayout* handle) + { + return device->vkCreatePipelineLayout(*device, createInfo, allocator, handle); + } + + inline void PipelineLayout::DestroyHelper(const DeviceHandle& device, VkPipelineLayout handle, const VkAllocationCallbacks* allocator) + { + return device->vkDestroyPipelineLayout(*device, handle, allocator); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkQueue.hpp b/include/Nazara/VulkanRenderer/VkQueue.hpp new file mode 100644 index 000000000..59cf74e17 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkQueue.hpp @@ -0,0 +1,53 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKQUEUE_HPP +#define NAZARA_VULKANRENDERER_VKQUEUE_HPP + +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + class Queue + { + public: + inline Queue(); + inline Queue(const DeviceHandle& device, VkQueue queue); + inline Queue(const Queue& queue); + inline Queue(Queue&& queue); + inline ~Queue() = default; + + inline const DeviceHandle& GetDevice() const; + inline VkResult GetLastErrorCode() const; + + inline bool Present(const VkPresentInfoKHR& presentInfo) const; + inline bool Present(VkSwapchainKHR swapchain, UInt32 imageIndex, VkSemaphore waitSemaphore = VK_NULL_HANDLE) const; + + inline bool Submit(const VkSubmitInfo& submit, VkFence fence = VK_NULL_HANDLE) const; + inline bool Submit(UInt32 submitCount, const VkSubmitInfo* submits, VkFence fence = VK_NULL_HANDLE) const; + + inline bool WaitIdle() const; + + Queue& operator=(const Queue& queue) = delete; + inline Queue& operator=(Queue&&); + + inline operator VkQueue(); + + protected: + DeviceHandle m_device; + VkQueue m_handle; + mutable VkResult m_lastErrorCode; + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKQUEUE_HPP diff --git a/include/Nazara/VulkanRenderer/VkQueue.inl b/include/Nazara/VulkanRenderer/VkQueue.inl new file mode 100644 index 000000000..62b0c7984 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkQueue.inl @@ -0,0 +1,115 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + inline Queue::Queue() : + Queue(DeviceHandle(), VK_NULL_HANDLE) + { + } + + inline Queue::Queue(const DeviceHandle& device, VkQueue queue) : + m_device(device), + m_handle(queue), + m_lastErrorCode(VkResult::VK_SUCCESS) + { + } + + inline Queue::Queue(const Queue& queue) : + m_device(queue.m_device), + m_handle(queue.m_handle), + m_lastErrorCode(queue.m_lastErrorCode) + { + } + + inline Queue::Queue(Queue&& queue) : + m_device(queue.m_device), + m_handle(queue.m_handle), + m_lastErrorCode(queue.m_lastErrorCode) + { + } + + inline const DeviceHandle& Queue::GetDevice() const + { + return m_device; + } + + inline VkResult Queue::GetLastErrorCode() const + { + return m_lastErrorCode; + } + + inline bool Queue::Present(const VkPresentInfoKHR& presentInfo) const + { + m_lastErrorCode = m_device->vkQueuePresentKHR(m_handle, &presentInfo); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + return false; + + return true; + } + + inline bool Queue::Present(VkSwapchainKHR swapchain, UInt32 imageIndex, VkSemaphore waitSemaphore) const + { + VkPresentInfoKHR presentInfo = + { + VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, + nullptr, + (waitSemaphore) ? 1U : 0U, + &waitSemaphore, + 1U, + &swapchain, + &imageIndex, + nullptr + }; + + return Present(presentInfo); + } + + inline bool Queue::Submit(const VkSubmitInfo& submit, VkFence fence) const + { + return Submit(1, &submit, fence); + } + + inline bool Queue::Submit(UInt32 submitCount, const VkSubmitInfo* submits, VkFence fence) const + { + m_lastErrorCode = m_device->vkQueueSubmit(m_handle, submitCount, submits, fence); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + return false; + + return true; + } + + inline bool Queue::WaitIdle() const + { + m_lastErrorCode = m_device->vkQueueWaitIdle(m_handle); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + return false; + + return true; + } + + inline Queue& Queue::operator=(Queue&& queue) + { + m_device = std::move(queue.m_device); + m_handle = queue.m_handle; + m_lastErrorCode = queue.m_lastErrorCode; + + return *this; + } + + inline Queue::operator VkQueue() + { + return m_handle; + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkRenderPass.hpp b/include/Nazara/VulkanRenderer/VkRenderPass.hpp new file mode 100644 index 000000000..2ea70a316 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkRenderPass.hpp @@ -0,0 +1,39 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKRENDERPASS_HPP +#define NAZARA_VULKANRENDERER_VKRENDERPASS_HPP + +#include +#include + +namespace Nz +{ + namespace Vk + { + class RenderPass : public DeviceObject + { + friend DeviceObject; + + public: + RenderPass() = default; + RenderPass(const RenderPass&) = delete; + RenderPass(RenderPass&&) = default; + ~RenderPass() = default; + + RenderPass& operator=(const RenderPass&) = delete; + RenderPass& operator=(RenderPass&&) = delete; + + private: + static inline VkResult CreateHelper(const DeviceHandle& device, const VkRenderPassCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkRenderPass* handle); + static inline void DestroyHelper(const DeviceHandle& device, VkRenderPass handle, const VkAllocationCallbacks* allocator); + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKRENDERPASS_HPP diff --git a/include/Nazara/VulkanRenderer/VkRenderPass.inl b/include/Nazara/VulkanRenderer/VkRenderPass.inl new file mode 100644 index 000000000..7fde52a75 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkRenderPass.inl @@ -0,0 +1,24 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + inline VkResult RenderPass::CreateHelper(const DeviceHandle& device, const VkRenderPassCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkRenderPass* handle) + { + return device->vkCreateRenderPass(*device, createInfo, allocator, handle); + } + + inline void RenderPass::DestroyHelper(const DeviceHandle& device, VkRenderPass handle, const VkAllocationCallbacks* allocator) + { + return device->vkDestroyRenderPass(*device, handle, allocator); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkSemaphore.hpp b/include/Nazara/VulkanRenderer/VkSemaphore.hpp new file mode 100644 index 000000000..0f5e09d59 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkSemaphore.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKSEMAPHORE_HPP +#define NAZARA_VULKANRENDERER_VKSEMAPHORE_HPP + +#include +#include + +namespace Nz +{ + namespace Vk + { + class Semaphore : public DeviceObject + { + friend DeviceObject; + + public: + Semaphore() = default; + Semaphore(const Semaphore&) = delete; + Semaphore(Semaphore&&) = default; + ~Semaphore() = default; + + using DeviceObject::Create; + inline bool Create(const DeviceHandle& device, VkSemaphoreCreateFlags flags = 0, const VkAllocationCallbacks* allocator = nullptr); + + Semaphore& operator=(const Semaphore&) = delete; + Semaphore& operator=(Semaphore&&) = delete; + + private: + static inline VkResult CreateHelper(const DeviceHandle& device, const VkSemaphoreCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkSemaphore* handle); + static inline void DestroyHelper(const DeviceHandle& device, VkSemaphore handle, const VkAllocationCallbacks* allocator); + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKSEMAPHORE_HPP diff --git a/include/Nazara/VulkanRenderer/VkSemaphore.inl b/include/Nazara/VulkanRenderer/VkSemaphore.inl new file mode 100644 index 000000000..7220cfeb9 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkSemaphore.inl @@ -0,0 +1,36 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + inline bool Semaphore::Create(const DeviceHandle& device, VkSemaphoreCreateFlags flags, const VkAllocationCallbacks* allocator) + { + VkSemaphoreCreateInfo createInfo = + { + VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + nullptr, + flags + }; + + return Create(device, createInfo, allocator); + } + + inline VkResult Semaphore::CreateHelper(const DeviceHandle& device, const VkSemaphoreCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkSemaphore* handle) + { + return device->vkCreateSemaphore(*device, createInfo, allocator, handle); + } + + inline void Semaphore::DestroyHelper(const DeviceHandle& device, VkSemaphore handle, const VkAllocationCallbacks* allocator) + { + return device->vkDestroySemaphore(*device, handle, allocator); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkShaderModule.hpp b/include/Nazara/VulkanRenderer/VkShaderModule.hpp new file mode 100644 index 000000000..e8b5f8fd1 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkShaderModule.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKSHADERMODULE_HPP +#define NAZARA_VULKANRENDERER_VKSHADERMODULE_HPP + +#include +#include + +namespace Nz +{ + namespace Vk + { + class ShaderModule : public DeviceObject + { + friend DeviceObject; + + public: + ShaderModule() = default; + ShaderModule(const ShaderModule&) = delete; + ShaderModule(ShaderModule&&) = default; + ~ShaderModule() = default; + + using DeviceObject::Create; + inline bool Create(const DeviceHandle& device, const UInt32* code, std::size_t size, VkShaderModuleCreateFlags flags = 0, const VkAllocationCallbacks* allocator = nullptr); + + ShaderModule& operator=(const ShaderModule&) = delete; + ShaderModule& operator=(ShaderModule&&) = delete; + + private: + static inline VkResult CreateHelper(const DeviceHandle& device, const VkShaderModuleCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkShaderModule* handle); + static inline void DestroyHelper(const DeviceHandle& device, VkShaderModule handle, const VkAllocationCallbacks* allocator); + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKSHADERMODULE_HPP diff --git a/include/Nazara/VulkanRenderer/VkShaderModule.inl b/include/Nazara/VulkanRenderer/VkShaderModule.inl new file mode 100644 index 000000000..81f5177fc --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkShaderModule.inl @@ -0,0 +1,38 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + inline bool ShaderModule::Create(const DeviceHandle& device, const UInt32* code, std::size_t size, VkShaderModuleCreateFlags flags, const VkAllocationCallbacks* allocator) + { + VkShaderModuleCreateInfo createInfo = + { + VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + nullptr, + flags, + size, + code + }; + + return Create(device, createInfo, allocator); + } + + inline VkResult ShaderModule::CreateHelper(const DeviceHandle& device, const VkShaderModuleCreateInfo* createInfo, const VkAllocationCallbacks* allocator, VkShaderModule* handle) + { + return device->vkCreateShaderModule(*device, createInfo, allocator, handle); + } + + inline void ShaderModule::DestroyHelper(const DeviceHandle& device, VkShaderModule handle, const VkAllocationCallbacks* allocator) + { + return device->vkDestroyShaderModule(*device, handle, allocator); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkSurface.hpp b/include/Nazara/VulkanRenderer/VkSurface.hpp new file mode 100644 index 000000000..1f4db956f --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkSurface.hpp @@ -0,0 +1,94 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKSURFACE_HPP +#define NAZARA_VULKANRENDERER_VKSURFACE_HPP + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + class Instance; + + class Surface + { + public: + inline Surface(Instance& instance); + Surface(const Surface&) = delete; + Surface(Surface&& surface); + inline ~Surface(); + + #ifdef VK_USE_PLATFORM_ANDROID_KHR + // VK_KHR_android_surface + inline bool Create(const VkAndroidSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr); + inline bool Create(ANativeWindow* window, VkAndroidSurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr); + #endif + + #ifdef VK_USE_PLATFORM_MIR_KHR + // VK_KHR_mir_surface + inline bool Create(const VkMirSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr); + inline bool Create(MirConnection* connection, MirSurface* surface, VkMirSurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr); + #endif + + #ifdef VK_USE_PLATFORM_XCB_KHR + // VK_KHR_xcb_surface + inline bool Create(const VkXcbSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr); + inline bool Create(xcb_connection_t* connection, xcb_window_t window, VkXcbSurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr); + #endif + + #ifdef VK_USE_PLATFORM_XLIB_KHR + // VK_KHR_xlib_surface + inline bool Create(const VkXlibSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr); + inline bool Create(Display* display, Window window, VkXlibSurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr); + #endif + + #ifdef VK_USE_PLATFORM_WAYLAND_KHR + // VK_KHR_wayland_surface + inline bool Create(const VkWaylandSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr); + inline bool Create(wl_display* display, wl_surface* surface, VkWaylandSurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr); + #endif + + #ifdef VK_USE_PLATFORM_WIN32_KHR + // VK_KHR_win32_surface + inline bool Create(const VkWin32SurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr); + inline bool Create(HINSTANCE instance, HWND handle, VkWin32SurfaceCreateFlagsKHR flags = 0, const VkAllocationCallbacks* allocator = nullptr); + #endif + + inline void Destroy(); + + bool GetCapabilities(VkPhysicalDevice physicalDevice, VkSurfaceCapabilitiesKHR* surfaceCapabilities) const; + bool GetFormats(VkPhysicalDevice physicalDevice, std::vector* surfaceFormats) const; + bool GetPresentModes(VkPhysicalDevice physicalDevice, std::vector* presentModes) const; + bool GetSupportPresentation(VkPhysicalDevice physicalDevice, UInt32 queueFamilyIndex, bool* supported) const; + + inline bool IsSupported() const; + + inline VkResult GetLastErrorCode() const; + + Surface& operator=(const Surface&) = delete; + Surface& operator=(Surface&&) = delete; + + inline operator VkSurfaceKHR() const; + + private: + inline bool Create(const VkAllocationCallbacks* allocator); + + Instance& m_instance; + VkAllocationCallbacks m_allocator; + VkSurfaceKHR m_surface; + mutable VkResult m_lastErrorCode; + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKSURFACE_HPP diff --git a/include/Nazara/VulkanRenderer/VkSurface.inl b/include/Nazara/VulkanRenderer/VkSurface.inl new file mode 100644 index 000000000..efec9a34c --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkSurface.inl @@ -0,0 +1,314 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + inline Surface::Surface(Instance& instance) : + m_instance(instance), + m_surface(VK_NULL_HANDLE) + { + } + + inline Surface::Surface(Surface&& surface) : + m_instance(surface.m_instance), + m_allocator(surface.m_allocator), + m_surface(surface.m_surface), + m_lastErrorCode(surface.m_lastErrorCode) + { + surface.m_surface = VK_NULL_HANDLE; + } + + inline Surface::~Surface() + { + Destroy(); + } + + #ifdef VK_USE_PLATFORM_ANDROID_KHR + inline bool Surface::Create(const VkAndroidSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator) + { + m_lastErrorCode = m_instance.vkCreateAndroidSurfaceKHR(m_instance, &createInfo, allocator, &m_surface); + return Create(allocator); + } + + inline bool Surface::Create(ANativeWindow* window, VkAndroidSurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator) + { + VkAndroidSurfaceCreateInfoKHR createInfo = + { + VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR, + nullptr, + flags, + window + }; + + return Create(createInfo, allocator); + } + #endif + + #ifdef VK_USE_PLATFORM_MIR_KHR + inline bool Surface::Create(const VkMirSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator) + { + m_lastErrorCode = m_instance.vkCreateMirSurfaceKHR(m_instance, &createInfo, allocator, &m_surface); + return Create(allocator); + } + + inline bool Surface::Create(MirConnection* connection, MirSurface* surface, VkMirSurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator) + { + VkMirSurfaceCreateInfoKHR createInfo = + { + VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR, + nullptr, + flags, + connection, + surface + }; + + return Create(createInfo, allocator); + } + #endif + + #ifdef VK_USE_PLATFORM_XCB_KHR + inline bool Surface::Create(const VkXcbSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator) + { + m_lastErrorCode = m_instance.vkCreateXcbSurfaceKHR(m_instance, &createInfo, allocator, &m_surface); + return Create(allocator); + } + + inline bool Surface::Create(xcb_connection_t* connection, xcb_window_t window, VkXcbSurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator) + { + VkXcbSurfaceCreateInfoKHR createInfo = + { + VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, + nullptr, + flags, + connection, + window + }; + + return Create(createInfo, allocator); + } + #endif + + #ifdef VK_USE_PLATFORM_XLIB_KHR + inline bool Surface::Create(const VkXlibSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator) + { + m_lastErrorCode = m_instance.vkCreateXlibSurfaceKHR(m_instance, &createInfo, allocator, &m_surface); + return Create(allocator); + } + + inline bool Surface::Create(Display* display, Window window, VkXlibSurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator) + { + VkXlibSurfaceCreateInfoKHR createInfo = + { + VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, + nullptr, + flags, + display, + window + }; + + return Create(createInfo, allocator); + } + #endif + + #ifdef VK_USE_PLATFORM_WAYLAND_KHR + inline bool Surface::Create(const VkWaylandSurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator) + { + m_lastErrorCode = m_instance.vkCreateWaylandSurfaceKHR(m_instance, &createInfo, allocator, &m_surface); + return Create(allocator); + } + + inline bool Surface::Create(wl_display* display, wl_surface* surface, VkWaylandSurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator) + { + VkWaylandSurfaceCreateInfoKHR createInfo = + { + VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR, + nullptr, + flags, + display, + surface + }; + + return Create(createInfo, allocator); + } + #endif + + #ifdef VK_USE_PLATFORM_WIN32_KHR + inline bool Surface::Create(const VkWin32SurfaceCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator) + { + m_lastErrorCode = m_instance.vkCreateWin32SurfaceKHR(m_instance, &createInfo, allocator, &m_surface); + return Create(allocator); + } + + inline bool Surface::Create(HINSTANCE instance, HWND handle, VkWin32SurfaceCreateFlagsKHR flags, const VkAllocationCallbacks* allocator) + { + VkWin32SurfaceCreateInfoKHR createInfo = + { + VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR, + nullptr, + flags, + instance, + handle + }; + + return Create(createInfo, allocator); + } + #endif + + inline void Surface::Destroy() + { + if (m_surface != VK_NULL_HANDLE) + { + m_instance.vkDestroySurfaceKHR(m_instance, m_surface, (m_allocator.pfnAllocation) ? &m_allocator : nullptr); + m_surface = VK_NULL_HANDLE; + } + } + + inline VkResult Surface::GetLastErrorCode() const + { + return m_lastErrorCode; + } + + inline bool Surface::GetCapabilities(VkPhysicalDevice physicalDevice, VkSurfaceCapabilitiesKHR* surfaceCapabilities) const + { + m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, m_surface, surfaceCapabilities); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to query surface capabilities"); + return false; + } + + return true; + } + + inline bool Surface::GetFormats(VkPhysicalDevice physicalDevice, std::vector* surfaceFormats) const + { + // First, query format count + UInt32 surfaceCount = 0; // Remember, Nz::UInt32 is a typedef on uint32_t + m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, m_surface, &surfaceCount, nullptr); + if (m_lastErrorCode != VkResult::VK_SUCCESS || surfaceCount == 0) + { + NazaraError("Failed to query format count"); + return false; + } + + // Now we can get the list of the available physical device + surfaceFormats->resize(surfaceCount); + m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, m_surface, &surfaceCount, surfaceFormats->data()); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to query formats"); + return false; + } + + return true; + } + + inline bool Surface::GetPresentModes(VkPhysicalDevice physicalDevice, std::vector* presentModes) const + { + // First, query present modes count + UInt32 presentModeCount = 0; // Remember, Nz::UInt32 is a typedef on uint32_t + m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, m_surface, &presentModeCount, nullptr); + if (m_lastErrorCode != VkResult::VK_SUCCESS || presentModeCount == 0) + { + NazaraError("Failed to query present mode count"); + return false; + } + + // Now we can get the list of the available physical device + presentModes->resize(presentModeCount); + m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDevice, m_surface, &presentModeCount, presentModes->data()); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to query present modes"); + return false; + } + + return true; + } + + inline bool Surface::GetSupportPresentation(VkPhysicalDevice physicalDevice, UInt32 queueFamilyIndex, bool* supported) const + { + VkBool32 presentationSupported = VK_FALSE; + m_lastErrorCode = m_instance.vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice, queueFamilyIndex, m_surface, &presentationSupported); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to query surface capabilities"); + return false; + } + + *supported = (presentationSupported == VK_TRUE); + + return true; + } + + inline bool Surface::IsSupported() const + { + if (!m_instance.IsExtensionLoaded("VK_KHR_surface")) + return false; + + #ifdef VK_USE_PLATFORM_ANDROID_KHR + if (m_instance.IsExtensionLoaded("VK_KHR_android_surface")) + return true; + #endif + + #ifdef VK_USE_PLATFORM_MIR_KHR + if (m_instance.IsExtensionLoaded("VK_KHR_mir_surface")) + return true; + #endif + + #ifdef VK_USE_PLATFORM_XCB_KHR + if (m_instance.IsExtensionLoaded("VK_KHR_xcb_surface")) + return true; + #endif + + #ifdef VK_USE_PLATFORM_XLIB_KHR + if (m_instance.IsExtensionLoaded("VK_KHR_xlib_surface")) + return true; + #endif + + #ifdef VK_USE_PLATFORM_WAYLAND_KHR + if (m_instance.IsExtensionLoaded("VK_KHR_wayland_surface")) + return true; + #endif + + #ifdef VK_USE_PLATFORM_WIN32_KHR + if (m_instance.IsExtensionLoaded("VK_KHR_win32_surface")) + return true; + #endif + + return false; + } + + inline Surface::operator VkSurfaceKHR() const + { + return m_surface; + } + + inline bool Surface::Create(const VkAllocationCallbacks* allocator) + { + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to create Vulkan surface"); + return false; + } + + // Store the allocator to access them when needed + if (allocator) + m_allocator = *allocator; + else + m_allocator.pfnAllocation = nullptr; + + return true; + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/VkSwapchain.hpp b/include/Nazara/VulkanRenderer/VkSwapchain.hpp new file mode 100644 index 000000000..b896c6c58 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkSwapchain.hpp @@ -0,0 +1,60 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_VKSWAPCHAIN_HPP +#define NAZARA_VULKANRENDERER_VKSWAPCHAIN_HPP + +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + class Swapchain : public DeviceObject + { + friend DeviceObject; + + public: + struct Buffer; + + Swapchain() = default; + Swapchain(const Swapchain&) = delete; + Swapchain(Swapchain&&) = default; + ~Swapchain() = default; + + inline bool AcquireNextImage(Nz::UInt64 timeout, VkSemaphore semaphore, VkFence fence, UInt32* imageIndex) const; + + inline bool Create(const DeviceHandle& device, const VkSwapchainCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator = nullptr); + + inline const Buffer& GetBuffer(UInt32 index) const; + inline const std::vector& GetBuffers() const; + inline UInt32 GetBufferCount() const; + + inline bool IsSupported() const; + + Swapchain& operator=(const Swapchain&) = delete; + Swapchain& operator=(Swapchain&&) = delete; + + struct Buffer + { + VkImage image; + ImageView view; + }; + + private: + static inline VkResult CreateHelper(const DeviceHandle& device, const VkSwapchainCreateInfoKHR* createInfo, const VkAllocationCallbacks* allocator, VkSwapchainKHR* handle); + static inline void DestroyHelper(const DeviceHandle& device, VkSwapchainKHR handle, const VkAllocationCallbacks* allocator); + + std::vector m_buffers; + }; + } +} + +#include + +#endif // NAZARA_VULKANRENDERER_VKSWAPCHAIN_HPP diff --git a/include/Nazara/VulkanRenderer/VkSwapchain.inl b/include/Nazara/VulkanRenderer/VkSwapchain.inl new file mode 100644 index 000000000..a8e0ead36 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VkSwapchain.inl @@ -0,0 +1,121 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + inline bool Swapchain::AcquireNextImage(Nz::UInt64 timeout, VkSemaphore semaphore, VkFence fence, UInt32* imageIndex) const + { + m_lastErrorCode = m_device->vkAcquireNextImageKHR(*m_device, m_handle, timeout, semaphore, fence, imageIndex); + switch (m_lastErrorCode) + { + case VkResult::VK_SUBOPTIMAL_KHR: + case VkResult::VK_SUCCESS: + return true; + + default: + return false; + } + } + + inline bool Swapchain::Create(const DeviceHandle& device, const VkSwapchainCreateInfoKHR& createInfo, const VkAllocationCallbacks* allocator) + { + if (!DeviceObject::Create(device, createInfo, allocator)) + return false; + + UInt32 imageCount = 0; + m_lastErrorCode = m_device->vkGetSwapchainImagesKHR(*m_device, m_handle, &imageCount, nullptr); + if (m_lastErrorCode != VkResult::VK_SUCCESS || imageCount == 0) + { + NazaraError("Failed to query swapchain image count"); + return false; + } + + std::vector images(imageCount); + m_lastErrorCode = m_device->vkGetSwapchainImagesKHR(*m_device, m_handle, &imageCount, images.data()); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to query swapchain images"); + return false; + } + + m_buffers.resize(imageCount); + for (UInt32 i = 0; i < imageCount; ++i) + { + m_buffers[i].image = images[i]; + + VkImageViewCreateInfo imageViewCreateInfo = { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkImageViewCreateFlags flags; + m_buffers[i].image, // VkImage image; + VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; + createInfo.imageFormat, // VkFormat format; + { // VkComponentMapping components; + VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle .r; + VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle .g; + VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle .b; + VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle .a; + }, + { // VkImageSubresourceRange subresourceRange; + VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags .aspectMask; + 0, // uint32_t .baseMipLevel; + 1, // uint32_t .levelCount; + 0, // uint32_t .baseArrayLayer; + 1 // uint32_t .layerCount; + } + }; + + if (!m_buffers[i].view.Create(m_device, imageViewCreateInfo)) + { + NazaraError("Failed to create image view for image #" + String::Number(i)); + return false; + } + } + + return true; + } + + inline const Swapchain::Buffer& Swapchain::GetBuffer(UInt32 index) const + { + return m_buffers[index]; + } + + inline const std::vector& Swapchain::GetBuffers() const + { + return m_buffers; + } + + inline UInt32 Swapchain::GetBufferCount() const + { + return static_cast(m_buffers.size()); + } + + inline bool Swapchain::IsSupported() const + { + if (!m_device->IsExtensionLoaded("VK_KHR_swapchain")) + return false; + + return true; + } + + inline VkResult Swapchain::CreateHelper(const DeviceHandle& device, const VkSwapchainCreateInfoKHR* createInfo, const VkAllocationCallbacks* allocator, VkSwapchainKHR* handle) + { + return device->vkCreateSwapchainKHR(*device, createInfo, allocator, handle); + } + + inline void Swapchain::DestroyHelper(const DeviceHandle& device, VkSwapchainKHR handle, const VkAllocationCallbacks* allocator) + { + return device->vkDestroySwapchainKHR(*device, handle, allocator); + } + } +} + +#include diff --git a/include/Nazara/VulkanRenderer/Vulkan.hpp b/include/Nazara/VulkanRenderer/Vulkan.hpp new file mode 100644 index 000000000..619774e0f --- /dev/null +++ b/include/Nazara/VulkanRenderer/Vulkan.hpp @@ -0,0 +1,55 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKAN_HPP +#define NAZARA_VULKAN_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_VULKANRENDERER_API Vulkan + { + public: + Vulkan() = delete; + ~Vulkan() = delete; + + static Vk::DeviceHandle CreateDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue); + + static Vk::Instance& GetInstance(); + + static const std::vector& GetPhysicalDevices(); + static const Vk::PhysicalDevice& GetPhysicalDeviceInfo(VkPhysicalDevice physDevice); + + static bool Initialize(); + + static bool IsInitialized(); + + static Vk::DeviceHandle SelectDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue); + + static void SetParameters(const ParameterList& parameters); + + static void Uninitialize(); + + private: + static std::list s_devices; + static std::vector s_physDevices; + static Vk::Instance s_instance; + static ParameterList s_initializationParameters; + static unsigned int s_moduleReferenceCounter; + }; +} + +#endif // NAZARA_VULKAN_HPP diff --git a/include/Nazara/VulkanRenderer/VulkanRenderer.hpp b/include/Nazara/VulkanRenderer/VulkanRenderer.hpp new file mode 100644 index 000000000..b77cb6935 --- /dev/null +++ b/include/Nazara/VulkanRenderer/VulkanRenderer.hpp @@ -0,0 +1,42 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_VULKANRENDERER_HPP +#define NAZARA_VULKANRENDERER_HPP + +#include +#include +#include +#include +#include + +namespace Nz +{ + class NAZARA_VULKANRENDERER_API VulkanRenderer : public RendererImpl + { + public: + VulkanRenderer() = default; + ~VulkanRenderer() = default; + + bool IsBetterThan(const RendererImpl* other) const override; + + RenderAPI QueryAPI() const override; + String QueryAPIString() const override; + UInt32 QueryAPIVersion() const override; + std::vector QueryRenderDevices() const override; + + bool Prepare(const ParameterList& parameters) override; + + static constexpr UInt32 APIVersion = VK_API_VERSION_1_0; + + private: + Vk::Instance m_instance; + std::vector m_physDevices; + UInt32 m_apiVersion; + }; +} + +#endif // NAZARA_VULKANRENDERER_HPP diff --git a/src/Nazara/Renderer/Context.cpp b/src/Nazara/Renderer/Context.cpp deleted file mode 100644 index 69919d094..000000000 --- a/src/Nazara/Renderer/Context.cpp +++ /dev/null @@ -1,376 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(NAZARA_PLATFORM_WINDOWS) - #include -#elif defined(NAZARA_PLATFORM_GLX) - #include - #define CALLBACK -#else - #error Lack of implementation: Context -#endif - -#include - -namespace Nz -{ - namespace - { - thread_local const Context* s_currentContext = nullptr; - thread_local const Context* s_threadContext = nullptr; - - void CALLBACK DebugCallback(unsigned int source, unsigned int type, unsigned int id, unsigned int severity, int length, const char* message, const void* userParam) - { - NazaraUnused(length); - - StringStream ss; - ss << "OpenGL debug message (ID: 0x" << String::Number(id, 16) << "):\n"; - ss << "Sent by context: " << userParam; - ss << "\n-Source: "; - switch (source) - { - case GL_DEBUG_SOURCE_API: - ss << "OpenGL API"; - break; - - case GL_DEBUG_SOURCE_WINDOW_SYSTEM: - ss << "Operating system"; - break; - - case GL_DEBUG_SOURCE_SHADER_COMPILER: - ss << "Shader compiler"; - break; - - case GL_DEBUG_SOURCE_THIRD_PARTY: - ss << "Third party"; - break; - - case GL_DEBUG_SOURCE_APPLICATION: - ss << "Application"; - break; - - case GL_DEBUG_SOURCE_OTHER: - ss << "Other"; - break; - - default: - // Peut être rajouté par une extension - ss << "Unknown"; - break; - } - ss << '\n'; - - ss << "-Type: "; - switch (type) - { - case GL_DEBUG_TYPE_ERROR: - ss << "Error"; - break; - - case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: - ss << "Deprecated behavior"; - break; - - case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: - ss << "Undefined behavior"; - break; - - case GL_DEBUG_TYPE_PORTABILITY: - ss << "Portability"; - break; - - case GL_DEBUG_TYPE_PERFORMANCE: - ss << "Performance"; - break; - - case GL_DEBUG_TYPE_OTHER: - ss << "Other"; - break; - - default: - // Peut être rajouté par une extension - ss << "Unknown"; - break; - } - ss << '\n'; - - ss << "-Severity: "; - switch (severity) - { - case GL_DEBUG_SEVERITY_HIGH: - ss << "High"; - break; - - case GL_DEBUG_SEVERITY_MEDIUM: - ss << "Medium"; - break; - - case GL_DEBUG_SEVERITY_LOW: - ss << "Low"; - break; - - default: - // Peut être rajouté par une extension - ss << "Unknown"; - break; - } - ss << '\n'; - - ss << "Message: " << message << '\n'; - - NazaraNotice(ss); - } - } - - Context::~Context() - { - OnContextRelease(this); - - Destroy(); - } - - bool Context::Create(const ContextParameters& parameters) - { - Destroy(); - - m_parameters = parameters; - if (m_parameters.shared && !m_parameters.shareContext) - m_parameters.shareContext = s_reference.get(); - - std::unique_ptr impl(new ContextImpl); - if (!impl->Create(m_parameters)) - { - NazaraError("Failed to create context implementation"); - return false; - } - - m_impl = impl.release(); - - CallOnExit onExit([this] () { Destroy(); }); - - if (!SetActive(true)) - { - NazaraError("Failed to activate context"); - return false; - } - - if (m_parameters.antialiasingLevel > 0) - glEnable(GL_MULTISAMPLE); - - if (m_parameters.debugMode && OpenGL::IsSupported(OpenGLExtension_DebugOutput)) - { - glDebugMessageCallback(&DebugCallback, this); - - #ifdef NAZARA_DEBUG - glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); - #endif - } - - onExit.Reset(); - - return true; - } - - void Context::Destroy() - { - if (m_impl) - { - OnContextDestroy(this); - - OpenGL::OnContextDestruction(this); - SetActive(false); - - m_impl->Destroy(); - delete m_impl; - m_impl = nullptr; - } - } - - void Context::EnableVerticalSync(bool enabled) - { - #ifdef NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("No context has been created"); - return; - } - #endif - - m_impl->EnableVerticalSync(enabled); - } - - const ContextParameters& Context::GetParameters() const - { - #ifdef NAZARA_RENDERER_SAFE - if (!m_impl) - NazaraError("No context has been created"); - #endif - - return m_parameters; - } - - bool Context::IsActive() const - { - #ifdef NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("No context has been created"); - return false; - } - #endif - - return s_currentContext == this; - } - - bool Context::SetActive(bool active) const - { - #ifdef NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("No context has been created"); - return false; - } - #endif - - // Si le contexte est déjà activé/désactivé - if ((s_currentContext == this) == active) - return true; - - if (active) - { - if (!m_impl->Activate()) - return false; - - s_currentContext = this; - } - else - { - if (!ContextImpl::Desactivate()) - return false; - - s_currentContext = nullptr; - } - - OpenGL::OnContextChanged(s_currentContext); - - return true; - } - - void Context::SwapBuffers() - { - #ifdef NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("No context has been created"); - return; - } - - if (!m_parameters.doubleBuffered) - { - NazaraError("Context is not double buffered"); - return; - } - #endif - - m_impl->SwapBuffers(); - } - - bool Context::EnsureContext() - { - if (!s_currentContext) - { - if (!s_threadContext) - { - std::unique_ptr context(new Context); - if (!context->Create()) - { - NazaraError("Failed to create context"); - return false; - } - - s_threadContext = context.get(); - - s_contexts.emplace_back(std::move(context)); - } - - if (!s_threadContext->SetActive(true)) - { - NazaraError("Failed to active thread context"); - return false; - } - } - - return true; - } - - const Context* Context::GetCurrent() - { - return s_currentContext; - } - - const Context* Context::GetReference() - { - return s_reference.get(); - } - - const Context* Context::GetThreadContext() - { - EnsureContext(); - - return s_threadContext; - } - - bool Context::Initialize() - { - if (!ContextLibrary::Initialize()) - { - NazaraError("Failed to initialise library"); - return false; - } - - ContextParameters parameters; - parameters.shared = false; // Difficile de partager le contexte de référence avec lui-même - - std::unique_ptr reference(new Context); - if (!reference->Create(parameters)) - { - NazaraError("Failed to create reference context"); - return false; - } - - // Le contexte de référence doit rester désactivé pour le partage - if (!reference->SetActive(false)) - { - NazaraError("Failed to desactive reference context"); - return false; - } - - s_reference = std::move(reference); - - // Le contexte de référence est partagé par défaut avec les autres contextes - ContextParameters::defaultShareContext = s_reference.get(); - return true; - } - - void Context::Uninitialize() - { - ContextLibrary::Uninitialize(); - s_contexts.clear(); // On supprime tous les contextes créés - s_reference.reset(); - } - - std::unique_ptr Context::s_reference; - std::vector> Context::s_contexts; - ContextLibrary::LibraryMap Context::s_library; -} diff --git a/src/Nazara/Renderer/ContextParameters.cpp b/src/Nazara/Renderer/ContextParameters.cpp deleted file mode 100644 index 9f85bc662..000000000 --- a/src/Nazara/Renderer/ContextParameters.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include - -namespace Nz -{ - // Version majeure d'OpenGL, initialisé par OpenGL::Initialize() - UInt8 ContextParameters::defaultMajorVersion; - - // Version majeure d'OpenGL, initialisé par OpenGL::Initialize() - UInt8 ContextParameters::defaultMinorVersion; - - // Contexte de partage par défaut, initialisé par OpenGL::Initialize() - const Context* ContextParameters::defaultShareContext = nullptr; - - // Si possible, garder la compatibilité avec les fonctionnalités dépréciées - bool ContextParameters::defaultCompatibilityProfile = false; - - // Mode debug d'OpenGL par défaut - #if NAZARA_RENDERER_OPENGL_DEBUG || defined(NAZARA_DEBUG) - bool ContextParameters::defaultDebugMode = true; - #else - bool ContextParameters::defaultDebugMode = false; - #endif - - // Active le double-buffering sur les contextes - bool ContextParameters::defaultDoubleBuffered = false; - - // Active le partage des ressources entre contextes (Via le defaultShareContext) - bool ContextParameters::defaultShared = true; -} diff --git a/src/Nazara/Renderer/DebugDrawer.cpp b/src/Nazara/Renderer/DebugDrawer.cpp deleted file mode 100644 index 9f06c880f..000000000 --- a/src/Nazara/Renderer/DebugDrawer.cpp +++ /dev/null @@ -1,741 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -///TODO: Améliorer - -namespace Nz -{ - namespace - { - static Shader* s_shader = nullptr; - static Color s_primaryColor; - static Color s_secondaryColor; - static RenderStates s_renderStates; - static VertexBuffer s_vertexBuffer; - static bool s_initialized = false; - static int s_colorLocation = -1; - } - - void DebugDrawer::Draw(const BoundingVolumef& volume) - { - if (!Initialize()) - { - NazaraError("Failed to initialize Debug Drawer"); - return; - } - - if (!volume.IsFinite()) - return; - - Color oldPrimaryColor = s_primaryColor; - - Draw(volume.aabb); - - s_primaryColor = s_secondaryColor; - Draw(volume.obb); - - s_primaryColor = oldPrimaryColor; - } - - void DebugDrawer::Draw(const Boxi& box) - { - Draw(Boxf(box)); - } - - void DebugDrawer::Draw(const Boxf& box) - { - if (!Initialize()) - { - NazaraError("Failed to initialize Debug Drawer"); - return; - } - - BufferMapper mapper(s_vertexBuffer, BufferAccess_DiscardAndWrite, 0, 24); - VertexStruct_XYZ* vertex = static_cast(mapper.GetPointer()); - - Vector3f max, min; - max = box.GetMaximum(); - min = box.GetMinimum(); - - vertex->position.Set(min.x, min.y, min.z); - vertex++; - vertex->position.Set(max.x, min.y, min.z); - vertex++; - - vertex->position.Set(min.x, min.y, min.z); - vertex++; - vertex->position.Set(min.x, max.y, min.z); - vertex++; - - vertex->position.Set(min.x, min.y, min.z); - vertex++; - vertex->position.Set(min.x, min.y, max.z); - vertex++; - - vertex->position.Set(max.x, max.y, max.z); - vertex++; - vertex->position.Set(min.x, max.y, max.z); - vertex++; - - vertex->position.Set(max.x, max.y, max.z); - vertex++; - vertex->position.Set(max.x, min.y, max.z); - vertex++; - - vertex->position.Set(max.x, max.y, max.z); - vertex++; - vertex->position.Set(max.x, max.y, min.z); - vertex++; - - vertex->position.Set(min.x, min.y, max.z); - vertex++; - vertex->position.Set(max.x, min.y, max.z); - vertex++; - - vertex->position.Set(min.x, min.y, max.z); - vertex++; - vertex->position.Set(min.x, max.y, max.z); - vertex++; - - vertex->position.Set(min.x, max.y, min.z); - vertex++; - vertex->position.Set(max.x, max.y, min.z); - vertex++; - - vertex->position.Set(min.x, max.y, min.z); - vertex++; - vertex->position.Set(min.x, max.y, max.z); - vertex++; - - vertex->position.Set(max.x, min.y, min.z); - vertex++; - vertex->position.Set(max.x, max.y, min.z); - vertex++; - - vertex->position.Set(max.x, min.y, min.z); - vertex++; - vertex->position.Set(max.x, min.y, max.z); - vertex++; - - mapper.Unmap(); - - Renderer::SetRenderStates(s_renderStates); - Renderer::SetShader(s_shader); - Renderer::SetVertexBuffer(&s_vertexBuffer); - - s_shader->SendColor(s_colorLocation, s_primaryColor); - - Renderer::DrawPrimitives(PrimitiveMode_LineList, 0, 24); - } - - void DebugDrawer::Draw(const Boxui& box) - { - Draw(Boxf(box)); - } - - void DebugDrawer::Draw(const Frustumf& frustum) - { - if (!Initialize()) - { - NazaraError("Failed to initialize Debug Drawer"); - return; - } - - BufferMapper mapper(s_vertexBuffer, BufferAccess_DiscardAndWrite, 0, 24); - VertexStruct_XYZ* vertex = static_cast(mapper.GetPointer()); - - vertex->position.Set(frustum.GetCorner(BoxCorner_NearLeftBottom)); - vertex++; - vertex->position.Set(frustum.GetCorner(BoxCorner_NearRightBottom)); - vertex++; - - vertex->position.Set(frustum.GetCorner(BoxCorner_NearLeftBottom)); - vertex++; - vertex->position.Set(frustum.GetCorner(BoxCorner_NearLeftTop)); - vertex++; - - vertex->position.Set(frustum.GetCorner(BoxCorner_NearLeftBottom)); - vertex++; - vertex->position.Set(frustum.GetCorner(BoxCorner_FarLeftBottom)); - vertex++; - - vertex->position.Set(frustum.GetCorner(BoxCorner_FarRightTop)); - vertex++; - vertex->position.Set(frustum.GetCorner(BoxCorner_FarLeftTop)); - vertex++; - - vertex->position.Set(frustum.GetCorner(BoxCorner_FarRightTop)); - vertex++; - vertex->position.Set(frustum.GetCorner(BoxCorner_FarRightBottom)); - vertex++; - - vertex->position.Set(frustum.GetCorner(BoxCorner_FarRightTop)); - vertex++; - vertex->position.Set(frustum.GetCorner(BoxCorner_NearRightTop)); - vertex++; - - vertex->position.Set(frustum.GetCorner(BoxCorner_FarLeftBottom)); - vertex++; - vertex->position.Set(frustum.GetCorner(BoxCorner_FarRightBottom)); - vertex++; - - vertex->position.Set(frustum.GetCorner(BoxCorner_FarLeftBottom)); - vertex++; - vertex->position.Set(frustum.GetCorner(BoxCorner_FarLeftTop)); - vertex++; - - vertex->position.Set(frustum.GetCorner(BoxCorner_NearLeftTop)); - vertex++; - vertex->position.Set(frustum.GetCorner(BoxCorner_NearRightTop)); - vertex++; - - vertex->position.Set(frustum.GetCorner(BoxCorner_NearLeftTop)); - vertex++; - vertex->position.Set(frustum.GetCorner(BoxCorner_FarLeftTop)); - vertex++; - - vertex->position.Set(frustum.GetCorner(BoxCorner_NearRightBottom)); - vertex++; - vertex->position.Set(frustum.GetCorner(BoxCorner_NearRightTop)); - vertex++; - - vertex->position.Set(frustum.GetCorner(BoxCorner_NearRightBottom)); - vertex++; - vertex->position.Set(frustum.GetCorner(BoxCorner_FarRightBottom)); - vertex++; - - mapper.Unmap(); - - Renderer::SetRenderStates(s_renderStates); - Renderer::SetShader(s_shader); - Renderer::SetVertexBuffer(&s_vertexBuffer); - - s_shader->SendColor(s_colorLocation, s_primaryColor); - - Renderer::DrawPrimitives(PrimitiveMode_LineList, 0, 24); - } - - void DebugDrawer::Draw(const OrientedBoxf& orientedBox) - { - if (!Initialize()) - { - NazaraError("Failed to initialize Debug Drawer"); - return; - } - - BufferMapper mapper(s_vertexBuffer, BufferAccess_DiscardAndWrite, 0, 24); - VertexStruct_XYZ* vertex = static_cast(mapper.GetPointer()); - - vertex->position.Set(orientedBox.GetCorner(BoxCorner_NearLeftBottom)); - vertex++; - vertex->position.Set(orientedBox.GetCorner(BoxCorner_NearRightBottom)); - vertex++; - - vertex->position.Set(orientedBox.GetCorner(BoxCorner_NearLeftBottom)); - vertex++; - vertex->position.Set(orientedBox.GetCorner(BoxCorner_NearLeftTop)); - vertex++; - - vertex->position.Set(orientedBox.GetCorner(BoxCorner_NearLeftBottom)); - vertex++; - vertex->position.Set(orientedBox.GetCorner(BoxCorner_FarLeftBottom)); - vertex++; - - vertex->position.Set(orientedBox.GetCorner(BoxCorner_FarRightTop)); - vertex++; - vertex->position.Set(orientedBox.GetCorner(BoxCorner_FarLeftTop)); - vertex++; - - vertex->position.Set(orientedBox.GetCorner(BoxCorner_FarRightTop)); - vertex++; - vertex->position.Set(orientedBox.GetCorner(BoxCorner_FarRightBottom)); - vertex++; - - vertex->position.Set(orientedBox.GetCorner(BoxCorner_FarRightTop)); - vertex++; - vertex->position.Set(orientedBox.GetCorner(BoxCorner_NearRightTop)); - vertex++; - - vertex->position.Set(orientedBox.GetCorner(BoxCorner_FarLeftBottom)); - vertex++; - vertex->position.Set(orientedBox.GetCorner(BoxCorner_FarRightBottom)); - vertex++; - - vertex->position.Set(orientedBox.GetCorner(BoxCorner_FarLeftBottom)); - vertex++; - vertex->position.Set(orientedBox.GetCorner(BoxCorner_FarLeftTop)); - vertex++; - - vertex->position.Set(orientedBox.GetCorner(BoxCorner_NearLeftTop)); - vertex++; - vertex->position.Set(orientedBox.GetCorner(BoxCorner_NearRightTop)); - vertex++; - - vertex->position.Set(orientedBox.GetCorner(BoxCorner_NearLeftTop)); - vertex++; - vertex->position.Set(orientedBox.GetCorner(BoxCorner_FarLeftTop)); - vertex++; - - vertex->position.Set(orientedBox.GetCorner(BoxCorner_NearRightBottom)); - vertex++; - vertex->position.Set(orientedBox.GetCorner(BoxCorner_NearRightTop)); - vertex++; - - vertex->position.Set(orientedBox.GetCorner(BoxCorner_NearRightBottom)); - vertex++; - vertex->position.Set(orientedBox.GetCorner(BoxCorner_FarRightBottom)); - vertex++; - - mapper.Unmap(); - - Renderer::SetRenderStates(s_renderStates); - Renderer::SetShader(s_shader); - Renderer::SetVertexBuffer(&s_vertexBuffer); - - s_shader->SendColor(s_colorLocation, s_primaryColor); - - Renderer::DrawPrimitives(PrimitiveMode_LineList, 0, 24); - } - - void DebugDrawer::Draw(const Skeleton* skeleton) - { - if (!Initialize()) - { - NazaraError("Failed to initialize Debug Drawer"); - return; - } - - unsigned int jointCount = skeleton->GetJointCount(); - if (s_vertexBuffer.GetVertexCount() < jointCount*2) - { - NazaraError("Debug buffer not large enougth to draw object"); - return; - } - - BufferMapper mapper(s_vertexBuffer, BufferAccess_DiscardAndWrite, 0, jointCount*2); - VertexStruct_XYZ* vertex = static_cast(mapper.GetPointer()); - - unsigned int vertexCount = 0; - for (unsigned int i = 0; i < jointCount; ++i) - { - const Node* joint = skeleton->GetJoint(i); - const Node* parent = joint->GetParent(); - if (parent) - { - vertex->position = joint->GetPosition(); - vertex++; - - vertex->position = parent->GetPosition(); - vertex++; - - vertexCount += 2; - } - } - - mapper.Unmap(); - - if (vertexCount > 0) - { - Renderer::SetRenderStates(s_renderStates); - Renderer::SetShader(s_shader); - Renderer::SetVertexBuffer(&s_vertexBuffer); - - s_shader->SendColor(s_colorLocation, s_primaryColor); - Renderer::DrawPrimitives(PrimitiveMode_LineList, 0, vertexCount); - - s_shader->SendColor(s_colorLocation, s_secondaryColor); - Renderer::DrawPrimitives(PrimitiveMode_PointList, 0, vertexCount); - } - } - - void DebugDrawer::Draw(const Vector3f& position, float size) - { - Draw(Boxf(position.x - size*0.5f, position.y - size*0.5f, position.z - size*0.5f, size, size, size)); - } - - void DebugDrawer::DrawAxes(const Vector3f& position, float size) - { - Color oldPrimaryColor = s_primaryColor; - s_primaryColor = Color::Red; - DrawLine(position, position + Vector3f::UnitX() * 3.f * size / 4.f); - s_primaryColor = Color::Green; - DrawLine(position, position + Vector3f::UnitY() * 3.f * size / 4.f); - s_primaryColor = Color::Blue; - DrawLine(position, position + Vector3f::UnitZ() * 3.f * size / 4.f); - - s_primaryColor = Color::Red; - DrawCone(position + Vector3f::UnitX() * size, EulerAnglesf(0.f, 90.f, 0.f), 15, size / 4.f); - s_primaryColor = Color::Green; - DrawCone(position + Vector3f::UnitY() * size, EulerAnglesf(-90.f, 0.f, 0.f), 15, size / 4.f); - s_primaryColor = Color::Blue; - DrawCone(position + Vector3f::UnitZ() * size, EulerAnglesf(0.f, 0.f, 0.f), 15, size / 4.f); - s_primaryColor = oldPrimaryColor; - } - - void DebugDrawer::DrawBinormals(const StaticMesh* subMesh) - { - if (!Initialize()) - { - NazaraError("Failed to initialize Debug Drawer"); - return; - } - - unsigned int normalCount = subMesh->GetVertexCount(); - unsigned int vertexCount = normalCount*2; - if (s_vertexBuffer.GetVertexCount() < vertexCount) - { - NazaraError("Debug buffer not large enougth to draw object"); - return; - } - - BufferMapper inputMapper(subMesh->GetVertexBuffer(), BufferAccess_ReadOnly); - BufferMapper outputMapper(s_vertexBuffer, BufferAccess_DiscardAndWrite, 0, vertexCount); - - MeshVertex* inputVertex = static_cast(inputMapper.GetPointer()); - VertexStruct_XYZ* outputVertex = static_cast(outputMapper.GetPointer()); - - for (unsigned int i = 0; i < normalCount; ++i) - { - outputVertex->position = inputVertex->position; - outputVertex++; - - outputVertex->position = inputVertex->position + Vector3f::CrossProduct(inputVertex->normal, inputVertex->tangent)*0.01f; - outputVertex++; - - inputVertex++; - } - - inputMapper.Unmap(); - outputMapper.Unmap(); - - if (vertexCount > 0) - { - Renderer::SetRenderStates(s_renderStates); - Renderer::SetShader(s_shader); - Renderer::SetVertexBuffer(&s_vertexBuffer); - - s_shader->SendColor(s_colorLocation, s_primaryColor); - Renderer::DrawPrimitives(PrimitiveMode_LineList, 0, vertexCount); - } - } - - void DebugDrawer::DrawCone(const Vector3f& origin, const Quaternionf& rotation, float angle, float length) - { - if (!Initialize()) - { - NazaraError("Failed to initialize Debug Drawer"); - return; - } - - Matrix4f transformMatrix; - transformMatrix.MakeIdentity(); - transformMatrix.SetRotation(rotation); - transformMatrix.SetTranslation(origin); - - BufferMapper mapper(s_vertexBuffer, BufferAccess_DiscardAndWrite, 0, 16); - VertexStruct_XYZ* vertex = static_cast(mapper.GetPointer()); - - // On calcule le reste des points - Vector3f base(Vector3f::Forward()*length); - - // Il nous faut maintenant le rayon du cercle projeté à cette distance - // Tangente = Opposé/Adjaçent <=> Opposé = Adjaçent*Tangente - float radius = length*std::tan(DegreeToRadian(angle)); - Vector3f lExtend = Vector3f::Left()*radius; - Vector3f uExtend = Vector3f::Up()*radius; - - vertex->position.Set(transformMatrix * Vector3f::Zero()); - vertex++; - vertex->position.Set(transformMatrix * (base + lExtend + uExtend)); - vertex++; - - vertex->position.Set(transformMatrix * (base + lExtend + uExtend)); - vertex++; - vertex->position.Set(transformMatrix * (base + lExtend - uExtend)); - vertex++; - - vertex->position.Set(transformMatrix * Vector3f::Zero()); - vertex++; - vertex->position.Set(transformMatrix * (base + lExtend - uExtend)); - vertex++; - - vertex->position.Set(transformMatrix * (base + lExtend - uExtend)); - vertex++; - vertex->position.Set(transformMatrix * (base - lExtend - uExtend)); - vertex++; - - vertex->position.Set(transformMatrix * Vector3f::Zero()); - vertex++; - vertex->position.Set(transformMatrix * (base - lExtend + uExtend)); - vertex++; - - vertex->position.Set(transformMatrix * (base - lExtend + uExtend)); - vertex++; - vertex->position.Set(transformMatrix * (base - lExtend - uExtend)); - vertex++; - - vertex->position.Set(transformMatrix * Vector3f::Zero()); - vertex++; - vertex->position.Set(transformMatrix * (base - lExtend - uExtend)); - vertex++; - - vertex->position.Set(transformMatrix * (base - lExtend + uExtend)); - vertex++; - vertex->position.Set(transformMatrix * (base + lExtend + uExtend)); - vertex++; - - mapper.Unmap(); - - Renderer::SetRenderStates(s_renderStates); - Renderer::SetShader(s_shader); - Renderer::SetVertexBuffer(&s_vertexBuffer); - - s_shader->SendColor(s_colorLocation, s_primaryColor); - - Renderer::DrawPrimitives(PrimitiveMode_LineList, 0, 16); - } - - void DebugDrawer::DrawLine(const Vector3f& p1, const Vector3f& p2) - { - if (!s_initialized && !Initialize()) - { - NazaraError("Failed to initialize Debug Drawer"); - return; - } - - VertexStruct_XYZ buffer[2]; - buffer[0].position = p1; - buffer[1].position = p2; - - s_vertexBuffer.Fill(&buffer[0], 0, 2); - - Renderer::SetRenderStates(s_renderStates); - Renderer::SetShader(s_shader); - Renderer::SetVertexBuffer(&s_vertexBuffer); - - s_shader->SendColor(s_colorLocation, s_primaryColor); - Renderer::DrawPrimitives(PrimitiveMode_LineList, 0, 2); - } - - void DebugDrawer::DrawPoints(const Vector3f* ptr, unsigned int pointCount) - { - static_assert(sizeof(VertexStruct_XYZ) == sizeof(Vector3f), "VertexStruct_XYZ is no longer equal to Vector3f, please rewrite this"); - - if (!s_initialized && !Initialize()) - { - NazaraError("Failed to initialize Debug Drawer"); - return; - } - - if (pointCount > 0) - { - s_vertexBuffer.Fill(ptr, 0, pointCount); - - Renderer::SetRenderStates(s_renderStates); - Renderer::SetShader(s_shader); - Renderer::SetVertexBuffer(&s_vertexBuffer); - - s_shader->SendColor(s_colorLocation, s_primaryColor); - Renderer::DrawPrimitives(PrimitiveMode_PointList, 0, pointCount); - } - } - - void DebugDrawer::DrawNormals(const StaticMesh* subMesh) - { - if (!s_initialized && !Initialize()) - { - NazaraError("Failed to initialize Debug Drawer"); - return; - } - - unsigned int normalCount = subMesh->GetVertexCount(); - unsigned int vertexCount = normalCount*2; - if (s_vertexBuffer.GetVertexCount() < vertexCount) - { - NazaraError("Debug buffer not large enougth to draw object"); - return; - } - - BufferMapper inputMapper(subMesh->GetVertexBuffer(), BufferAccess_ReadOnly); - BufferMapper outputMapper(s_vertexBuffer, BufferAccess_DiscardAndWrite, 0, vertexCount); - - MeshVertex* inputVertex = static_cast(inputMapper.GetPointer()); - VertexStruct_XYZ* outputVertex = static_cast(outputMapper.GetPointer()); - - for (unsigned int i = 0; i < normalCount; ++i) - { - outputVertex->position = inputVertex->position; - outputVertex++; - - outputVertex->position = inputVertex->position + inputVertex->normal*0.01f; - outputVertex++; - - inputVertex++; - } - - inputMapper.Unmap(); - outputMapper.Unmap(); - - if (vertexCount > 0) - { - Renderer::SetRenderStates(s_renderStates); - Renderer::SetShader(s_shader); - Renderer::SetVertexBuffer(&s_vertexBuffer); - - s_shader->SendColor(s_colorLocation, s_primaryColor); - Renderer::DrawPrimitives(PrimitiveMode_LineList, 0, vertexCount); - } - } - - void DebugDrawer::DrawTangents(const StaticMesh* subMesh) - { - if (!s_initialized && !Initialize()) - { - NazaraError("Failed to initialize Debug Drawer"); - return; - } - - unsigned int tangentCount = subMesh->GetVertexCount(); - unsigned int vertexCount = tangentCount*2; - if (s_vertexBuffer.GetVertexCount() < vertexCount) - { - NazaraError("Debug buffer not large enougth to draw object"); - return; - } - - BufferMapper inputMapper(subMesh->GetVertexBuffer(), BufferAccess_ReadOnly); - BufferMapper outputMapper(s_vertexBuffer, BufferAccess_DiscardAndWrite, 0, vertexCount); - - MeshVertex* inputVertex = static_cast(inputMapper.GetPointer()); - VertexStruct_XYZ* outputVertex = static_cast(outputMapper.GetPointer()); - - for (unsigned int i = 0; i < tangentCount; ++i) - { - outputVertex->position = inputVertex->position; - outputVertex++; - - outputVertex->position = inputVertex->position + inputVertex->tangent*0.01f; - outputVertex++; - - inputVertex++; - } - - inputMapper.Unmap(); - outputMapper.Unmap(); - - if (vertexCount > 0) - { - Renderer::SetRenderStates(s_renderStates); - Renderer::SetShader(s_shader); - Renderer::SetVertexBuffer(&s_vertexBuffer); - - s_shader->SendColor(s_colorLocation, s_primaryColor); - Renderer::DrawPrimitives(PrimitiveMode_LineList, 0, vertexCount); - } - } - - void DebugDrawer::EnableDepthBuffer(bool depthBuffer) - { - s_renderStates.depthBuffer = depthBuffer; - } - - float DebugDrawer::GetLineWidth() - { - return s_renderStates.lineWidth; - } - - float DebugDrawer::GetPointSize() - { - return s_renderStates.pointSize; - } - - Color DebugDrawer::GetPrimaryColor() - { - return s_primaryColor; - } - - Color DebugDrawer::GetSecondaryColor() - { - return s_secondaryColor; - } - - bool DebugDrawer::Initialize() - { - if (!s_initialized) - { - // s_shader - s_shader = ShaderLibrary::Get("DebugSimple"); - s_colorLocation = s_shader->GetUniformLocation("Color"); - - // s_vertexBuffer - try - { - ErrorFlags flags(ErrorFlag_ThrowException, true); - s_vertexBuffer.Reset(VertexDeclaration::Get(VertexLayout_XYZ), 65365, DataStorage_Hardware, BufferUsage_Dynamic); - } - catch (const std::exception& e) - { - NazaraError("Failed to create buffer: " + String(e.what())); - - Uninitialize(); - return false; - } - - s_primaryColor = Color::Red; - s_renderStates.depthBuffer = true; - s_secondaryColor = Color::Green; - - s_initialized = true; - } - - return true; - } - - bool DebugDrawer::IsDepthBufferEnabled() - { - return s_renderStates.depthBuffer; - } - - void DebugDrawer::SetLineWidth(float width) - { - s_renderStates.lineWidth = width; - } - - void DebugDrawer::SetPointSize(float size) - { - s_renderStates.pointSize = size; - } - - void DebugDrawer::SetPrimaryColor(const Color& color) - { - s_primaryColor = color; - } - - void DebugDrawer::SetSecondaryColor(const Color& color) - { - s_secondaryColor = color; - } - - void DebugDrawer::Uninitialize() - { - s_shader = nullptr; - s_vertexBuffer.Reset(); - s_initialized = false; - } -} diff --git a/src/Nazara/Renderer/GLX/ContextImpl.cpp b/src/Nazara/Renderer/GLX/ContextImpl.cpp deleted file mode 100644 index 8bff9793a..000000000 --- a/src/Nazara/Renderer/GLX/ContextImpl.cpp +++ /dev/null @@ -1,300 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -// Code inspiré de NeHe (Lesson1) et de la SFML par Laurent Gomila - -#include -#include -#include -#include -#include - -using namespace GLX; - -namespace Nz -{ - namespace - { - Display* m_display; - int m_sharedDisplay = 0; - - bool ctxErrorOccurred = false; - int ctxErrorHandler( Display* /*dpy*/, XErrorEvent* /*ev*/ ) - { - ctxErrorOccurred = true; - return 0; - } - } - - ContextImpl::ContextImpl() : - m_colormap(0), - m_context(0), - m_window(0), - m_ownsWindow(false) - { - if (m_sharedDisplay == 0) - m_display = XOpenDisplay(nullptr); - - ++m_sharedDisplay; - } - - ContextImpl::~ContextImpl() - { - Destroy(); - - if (--m_sharedDisplay == 0) - { - XCloseDisplay(m_display); - m_display = nullptr; - } - } - - bool ContextImpl::Activate() - { - return glXMakeCurrent(m_display, m_window, m_context) == true; - } - - bool ContextImpl::Create(ContextParameters& parameters) - { - // En cas d'exception, la ressource sera quand même libérée - CallOnExit onExit([this] () - { - Destroy(); - }); - - // Get a matching FB config - static int visual_attribs[] = - { - GLX_X_RENDERABLE, True, - GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, - GLX_BUFFER_SIZE, parameters.bitsPerPixel, - GLX_ALPHA_SIZE, (parameters.bitsPerPixel == 32) ? 8 : 0, - GLX_DEPTH_SIZE, parameters.depthBits, - GLX_STENCIL_SIZE, parameters.stencilBits, - GLX_DOUBLEBUFFER, True, - GLX_SAMPLE_BUFFERS, (parameters.antialiasingLevel > 0) ? True : False, - GLX_SAMPLES, parameters.antialiasingLevel, - None - }; - - int glx_major = 0; - int glx_minor = 0; - // FBConfigs were added in GLX version 1.3. - if (!glXQueryVersion(m_display, &glx_major, &glx_minor) || ((glx_major == 1) && (glx_minor < 3)) || (glx_major < 1)) - { - NazaraError("Invalid GLX version, version > 1.3 is required."); - return false; - } - - int fbcount; - GLXFBConfig* fbc = glXChooseFBConfig(m_display, XDefaultScreen(m_display), visual_attribs, &fbcount); - if (!fbc) - { - NazaraError("Failed to retrieve a framebuffer config"); - return false; - } - - // Pick the FB config/visual with the most samples per pixel - int best_fbc = -1; - int worst_fbc = -1; - int best_num_samp = -1; - int worst_num_samp = 999; - - for (int i = 0; i < fbcount; ++i) - { - XVisualInfo* vi = glXGetVisualFromFBConfig(m_display, fbc[i]); - - if (vi) - { - int samp_buf = 0, samples = 0; - glXGetFBConfigAttrib(m_display, fbc[i], GLX_SAMPLE_BUFFERS, &samp_buf); - glXGetFBConfigAttrib(m_display, fbc[i], GLX_SAMPLES , &samples ); - - if ((best_fbc < 0) || (samp_buf && (samples > best_num_samp))) - { - best_fbc = i; - best_num_samp = samples; - } - if ((worst_fbc < 0) || !samp_buf || (samples < worst_num_samp)) - { - worst_fbc = i; - worst_num_samp = samples; - } - } - XFree(vi); - } - - GLXFBConfig bestFbc = fbc[best_fbc]; - - // Be sure to free the FBConfig list allocated by glXChooseFBConfig() - XFree(fbc); - - // Get a visual - XVisualInfo* vi = glXGetVisualFromFBConfig(m_display, bestFbc); - if (!vi) - { - NazaraError("Failed to get best VisualInfo"); - return false; - } - - // If context is shared by multiple windows - if (parameters.window) - { - m_window = parameters.window; - m_ownsWindow = false; - } - else - { - XSetWindowAttributes swa; - swa.colormap = m_colormap = XCreateColormap( - m_display, - XRootWindow( - m_display, - vi->screen), - vi->visual, - AllocNone - ); - - swa.background_pixmap = None; - swa.border_pixel = 0; - swa.event_mask = StructureNotifyMask; - - if (!m_colormap) - { - NazaraError("Failed to create colormap for context"); - return false; - } - - m_window = XCreateWindow( - m_display, - XRootWindow( - m_display, - vi->screen), - 0, 0, // X, Y - 1, 1, // W H - 0, - vi->depth, - InputOutput, - vi->visual, - CWBorderPixel | CWColormap | CWEventMask, - &swa - ); - - m_ownsWindow = true; - } - - if (!m_window) - { - NazaraError("Failed to create window"); - return false; - } - - // Done with the visual info data - XFree(vi); - - // Install an X error handler so the application won't exit if GL 3.0 - // context allocation fails. - // - // Note this error handler is global. All display connections in all threads - // of a process use the same error handler, so be sure to guard against other - // threads issuing X commands while this code is running. - ctxErrorOccurred = false; - int (*oldHandler)(Display*, XErrorEvent*) = - XSetErrorHandler(&ctxErrorHandler); - - // Check for the GLX_ARB_create_context extension string and the function. - // If either is not present, use GLX 1.3 context creation method. - if (!glXCreateContextAttribs) - { - NazaraWarning("glXCreateContextAttribs() not found. Using old-style GLX context"); - m_context = glXCreateNewContext(m_display, bestFbc, GLX_RGBA_TYPE, parameters.shared ? parameters.shareContext->m_impl->m_context : 0, True); - } - // If it does, try to get a GL 3.0 context! - else - { - int profile = parameters.compatibilityProfile ? GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : GLX_CONTEXT_CORE_PROFILE_BIT_ARB; - int debug = parameters.debugMode ? GLX_CONTEXT_DEBUG_BIT_ARB : 0; - - int major = 3;//parameters.majorVersion; - int minor = 3;//parameters.minorVersion; - - int context_attribs[] = - { - GLX_CONTEXT_MAJOR_VERSION_ARB, major, - GLX_CONTEXT_MINOR_VERSION_ARB, minor, - GLX_CONTEXT_PROFILE_MASK_ARB, profile, - GLX_CONTEXT_FLAGS_ARB, debug, - None, None - }; - - m_context = glXCreateContextAttribs( - m_display, - bestFbc, - parameters.shared ? parameters.shareContext->m_impl->m_context : 0, - True, - context_attribs - ); - } - - // Sync to ensure any errors generated are processed. - XSync(m_display, False); - XSetErrorHandler(oldHandler); - if (ctxErrorOccurred || !m_context) - { - NazaraError("Failed to create context, check the version"); - return false; - } - - onExit.Reset(); - - return true; - } - - void ContextImpl::Destroy() - { - // Destroy the context - if (m_context) - { - if (glXGetCurrentContext() == m_context) - glXMakeCurrent(m_display, None, nullptr); - glXDestroyContext(m_display, m_context); - m_context = nullptr; - } - - // Destroy the window if we own it - if (m_ownsWindow && m_window) - { - XFreeColormap(m_display, m_colormap); - XDestroyWindow(m_display, m_window); - m_ownsWindow = false; - m_window = 0; - XFlush(m_display); - } - } - - void ContextImpl::EnableVerticalSync(bool enabled) - { - if (glXSwapIntervalEXT) - glXSwapIntervalEXT(m_display, glXGetCurrentDrawable(), enabled ? 1 : 0); - else if (NzglXSwapIntervalMESA) - NzglXSwapIntervalMESA(enabled ? 1 : 0); - else if (glXSwapIntervalSGI) - glXSwapIntervalSGI(enabled ? 1 : 0); - else - NazaraError("Vertical sync not supported"); - } - - void ContextImpl::SwapBuffers() - { - if (m_window) - glXSwapBuffers(m_display, m_window); - } - - bool ContextImpl::Desactivate() - { - return glXMakeCurrent(m_display, None, nullptr) == true; - } -} diff --git a/src/Nazara/Renderer/GLX/ContextImpl.hpp b/src/Nazara/Renderer/GLX/ContextImpl.hpp deleted file mode 100644 index 40bbd5fc7..000000000 --- a/src/Nazara/Renderer/GLX/ContextImpl.hpp +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine". -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_CONTEXTIMPL_HPP -#define NAZARA_CONTEXTIMPL_HPP - -#include - -namespace Nz -{ - class ContextParameters; - - class ContextImpl - { - public: - ContextImpl(); - ~ContextImpl(); - - bool Activate(); - - bool Create(ContextParameters& parameters); - - void Destroy(); - - void EnableVerticalSync(bool enabled); - - void SwapBuffers(); - - static bool Desactivate(); - - private: - GLX::Colormap m_colormap; - GLX::GLXContext m_context; - GLX::Window m_window; - bool m_ownsWindow; - }; -} - -#endif // NAZARA_CONTEXTIMPL_HPP diff --git a/src/Nazara/Renderer/GpuQuery.cpp b/src/Nazara/Renderer/GpuQuery.cpp deleted file mode 100644 index 4e7ff228f..000000000 --- a/src/Nazara/Renderer/GpuQuery.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - GpuQuery::GpuQuery() : - m_id(0) - { - Context::EnsureContext(); - - m_id = 0; - glGenQueries(1, static_cast(&m_id)); - - #ifdef NAZARA_DEBUG - if (!m_id) - { - NazaraError("Failed to create occlusion query"); - throw std::runtime_error("Constructor failed"); - } - #endif - } - - GpuQuery::~GpuQuery() - { - if (m_id) - { - Context::EnsureContext(); - - GLuint query = static_cast(m_id); - glDeleteQueries(1, &query); - } - } - - void GpuQuery::Begin(GpuQueryMode mode) - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - #if NAZARA_RENDERER_SAFE - if (!IsModeSupported(mode)) - { - NazaraError("Mode (0x" + String::Number(mode, 16) + ") not supported"); - return; - } - #endif - - m_mode = mode; - glBeginQuery(OpenGL::QueryMode[mode], m_id); - } - - void GpuQuery::End() - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - glEndQuery(OpenGL::QueryMode[m_mode]); - } - - unsigned int GpuQuery::GetResult() const - { - Context::EnsureContext(); - - GLuint result; - glGetQueryObjectuiv(m_id, GL_QUERY_RESULT, &result); - - return result; - } - - bool GpuQuery::IsResultAvailable() const - { - Context::EnsureContext(); - - GLint available; - glGetQueryObjectiv(m_id, GL_QUERY_RESULT_AVAILABLE, &available); - - return available == GL_TRUE; - } - - unsigned int GpuQuery::GetOpenGLID() const - { - return m_id; - } - - bool GpuQuery::IsModeSupported(GpuQueryMode mode) - { - switch (mode) - { - case GpuQueryMode_AnySamplesPassedConservative: - return OpenGL::GetVersion() >= 430; - - case GpuQueryMode_AnySamplesPassed: - case GpuQueryMode_PrimitiveGenerated: - case GpuQueryMode_SamplesPassed: - case GpuQueryMode_TimeElapsed: - case GpuQueryMode_TransformFeedbackPrimitivesWritten: - return true; - } - - NazaraError("Gpu Query mode not handled (0x" + String::Number(mode, 16) + ')'); - return false; - } -} diff --git a/src/Nazara/Renderer/HardwareBuffer.cpp b/src/Nazara/Renderer/HardwareBuffer.cpp deleted file mode 100644 index 4005b47a5..000000000 --- a/src/Nazara/Renderer/HardwareBuffer.cpp +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - HardwareBuffer::HardwareBuffer(Buffer* parent, BufferType type) : - m_type(type), - m_parent(parent) - { - } - - HardwareBuffer::~HardwareBuffer() = default; - - bool HardwareBuffer::Create(unsigned int size, BufferUsage usage) - { - Context::EnsureContext(); - - m_buffer = 0; - glGenBuffers(1, &m_buffer); - - OpenGL::BindBuffer(m_type, m_buffer); - - glBufferData(OpenGL::BufferTarget[m_type], size, nullptr, OpenGL::BufferUsage[usage]); - - return true; - } - - void HardwareBuffer::Destroy() - { - Context::EnsureContext(); - - OpenGL::DeleteBuffer(m_type, m_buffer); - } - - bool HardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard) - { - Context::EnsureContext(); - - unsigned int totalSize = m_parent->GetSize(); - - if (!forceDiscard) - forceDiscard = (size == totalSize); - - OpenGL::BindBuffer(m_type, m_buffer); - - // Il semblerait que glBuffer(Sub)Data soit plus performant que glMapBuffer(Range) en dessous d'un certain seuil - // http://www.stevestreeting.com/2007/03/17/glmapbuffer-vs-glbuffersubdata-the-return/ - if (size < 32*1024) - { - // http://www.opengl.org/wiki/Buffer_Object_Streaming - if (forceDiscard) - glBufferData(OpenGL::BufferTarget[m_type], totalSize, nullptr, OpenGL::BufferUsage[m_parent->GetUsage()]); // Discard - - glBufferSubData(OpenGL::BufferTarget[m_type], offset, size, data); - } - else - { - void* ptr = Map((forceDiscard) ? BufferAccess_DiscardAndWrite : BufferAccess_WriteOnly, offset, size); - if (!ptr) - { - NazaraError("Failed to map buffer"); - return false; - } - - std::memcpy(ptr, data, size); - - Unmap(); - } - - return true; - } - - bool HardwareBuffer::IsHardware() const - { - return true; - } - - void* HardwareBuffer::Map(BufferAccess access, unsigned int offset, unsigned int size) - { - Context::EnsureContext(); - - OpenGL::BindBuffer(m_type, m_buffer); - - if (glMapBufferRange) - return glMapBufferRange(OpenGL::BufferTarget[m_type], offset, size, OpenGL::BufferLockRange[access]); - else - { - // http://www.opengl.org/wiki/Buffer_Object_Streaming - if (access == BufferAccess_DiscardAndWrite) - glBufferData(OpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, OpenGL::BufferUsage[m_parent->GetUsage()]); // Discard - - UInt8* ptr = static_cast(glMapBuffer(OpenGL::BufferTarget[m_type], OpenGL::BufferLock[access])); - if (ptr) - ptr += offset; - - return ptr; - } - } - - bool HardwareBuffer::Unmap() - { - Context::EnsureContext(); - - OpenGL::BindBuffer(m_type, m_buffer); - - if (glUnmapBuffer(OpenGL::BufferTarget[m_type]) != GL_TRUE) - { - glBufferData(OpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, OpenGL::BufferUsage[m_parent->GetUsage()]); - - // Une erreur rare est survenue, nous devons réinitialiser le buffer - NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + String::Number(glGetError(), 16) + ')'); - return false; - } - - return true; - } - - void HardwareBuffer::Bind() const - { - OpenGL::BindBuffer(m_type, m_buffer); - } - - unsigned int HardwareBuffer::GetOpenGLID() const - { - return m_buffer; -} -} diff --git a/src/Nazara/Renderer/HardwareBuffer.hpp b/src/Nazara/Renderer/HardwareBuffer.hpp deleted file mode 100644 index 608a1598d..000000000 --- a/src/Nazara/Renderer/HardwareBuffer.hpp +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_HARDWAREBUFFER_HPP -#define NAZARA_HARDWAREBUFFER_HPP - -#include -#include -#include - -namespace Nz -{ - class HardwareBuffer : public AbstractBuffer - { - public: - HardwareBuffer(Buffer* parent, BufferType type); - ~HardwareBuffer(); - - bool Create(unsigned int size, BufferUsage usage = BufferUsage_Static); - void Destroy(); - - bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard); - - bool IsHardware() const; - - void* Map(BufferAccess access, unsigned int offset = 0, unsigned int size = 0); - bool Unmap(); - - // Fonctions OpenGL - void Bind() const; - unsigned int GetOpenGLID() const; - - private: - GLuint m_buffer; - BufferType m_type; - Buffer* m_parent; - }; -} - -#endif // NAZARA_HARDWAREBUFFER_HPP diff --git a/src/Nazara/Renderer/OpenGL.cpp b/src/Nazara/Renderer/OpenGL.cpp deleted file mode 100644 index ba17fe015..000000000 --- a/src/Nazara/Renderer/OpenGL.cpp +++ /dev/null @@ -1,2306 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include -#include -#include -#if defined(NAZARA_PLATFORM_GLX) -#include -#endif // NAZARA_PLATFORM_GLX -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - namespace - { - #ifdef NAZARA_PLATFORM_WINDOWS - HMODULE openGLlibrary; - #endif - - OpenGLFunc LoadEntry(const char* name, bool launchException = true) - { - #if defined(NAZARA_PLATFORM_WINDOWS) - OpenGLFunc entry = reinterpret_cast(wglGetProcAddress(name)); - if (!entry) // wglGetProcAddress ne fonctionne pas sur les fonctions OpenGL <= 1.1 - entry = reinterpret_cast(GetProcAddress(openGLlibrary, name)); - #elif defined(NAZARA_PLATFORM_GLX) - OpenGLFunc entry = reinterpret_cast(GLX::glXGetProcAddress(reinterpret_cast(name))); - #else - #error OS not handled - #endif - - if (!entry && launchException) - { - std::ostringstream oss; - oss << "failed to load \"" << name << '"'; - - throw std::runtime_error(oss.str()); - } - - return entry; - } - - bool LoadLibrary() - { - #ifdef NAZARA_PLATFORM_WINDOWS - openGLlibrary = ::LoadLibraryA("opengl32.dll"); - - return openGLlibrary != nullptr; - #else - return true; - #endif - } - - void UnloadLibrary() - { - #ifdef NAZARA_PLATFORM_WINDOWS - FreeLibrary(openGLlibrary); - #endif - } - - enum GarbageResourceType - { - GarbageResourceType_FrameBuffer, - GarbageResourceType_VertexArray - }; - - struct ContextStates - { - std::vector> garbage; // Les ressources à supprimer dès que possible - GLuint buffersBinding[BufferType_Max + 1] = {0}; - GLuint currentProgram = 0; - GLuint samplers[32] = {0}; // 32 est pour l'instant la plus haute limite (GL_TEXTURE31) - GLuint texturesBinding[32] = {0}; // 32 est pour l'instant la plus haute limite (GL_TEXTURE31) - Recti currentScissorBox = Recti(0, 0, 0, 0); - Recti currentViewport = Recti(0, 0, 0, 0); - RenderStates renderStates; // Toujours synchronisé avec OpenGL - const RenderTarget* currentTarget = nullptr; - bool scissorBoxUpdated = true; - bool viewportUpdated = true; - unsigned int textureUnit = 0; - }; - - std::set s_openGLextensionSet; - std::unordered_map s_contexts; - thread_local ContextStates* s_contextStates = nullptr; - String s_rendererName; - String s_vendorName; - bool s_initialized = false; - bool s_openGLextensions[OpenGLExtension_Max + 1] = {false}; - unsigned int s_glslVersion = 0; - unsigned int s_openglVersion = 0; - - bool LoadExtensionsString(const String& extensionString) - { - if (extensionString.IsEmpty()) - { - NazaraError("Unable to get extension string"); - return false; - } - - // On peut sûrement faire plus rapide mais comme ça ne se fait qu'une fois et que String implémente le COW... - std::vector ext; - extensionString.Split(ext); - - for (std::vector::iterator it = ext.begin(); it != ext.end(); ++it) - s_openGLextensionSet.insert(*it); - - return true; - } - - bool LoadExtensions3() - { - GLint extensionCount = 0; - glGetIntegerv(GL_NUM_EXTENSIONS, &extensionCount); - - if (extensionCount <= 0) - { - NazaraError("Unable to get extension count"); - return false; - } - - for (int i = 0; i < extensionCount; ++i) - { - String extension(reinterpret_cast(glGetStringi(GL_EXTENSIONS, i))); - if (extension.IsEmpty()) - { - NazaraWarning("Unable to get extension #" + String::Number(i)); - continue; - } - - s_openGLextensionSet.insert(extension); - } - - return true; - } - } - - void OpenGL::ApplyStates(const RenderStates& states) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - RenderStates& currentRenderStates = s_contextStates->renderStates; - - // Les fonctions de blend n'a aucun intérêt sans blending - if (states.blending) - { - if (currentRenderStates.dstBlend != states.dstBlend || - currentRenderStates.srcBlend != states.srcBlend) - { - glBlendFunc(BlendFunc[states.srcBlend], BlendFunc[states.dstBlend]); - currentRenderStates.dstBlend = states.dstBlend; - currentRenderStates.srcBlend = states.srcBlend; - } - } - - if (states.depthBuffer) - { - // La comparaison de profondeur n'a aucun intérêt sans depth buffer - if (currentRenderStates.depthFunc != states.depthFunc) - { - glDepthFunc(RendererComparison[states.depthFunc]); - currentRenderStates.depthFunc = states.depthFunc; - } - - // Le DepthWrite n'a aucune importance si le DepthBuffer est désactivé - if (currentRenderStates.depthWrite != states.depthWrite) - { - glDepthMask((states.depthWrite) ? GL_TRUE : GL_FALSE); - currentRenderStates.depthWrite = states.depthWrite; - } - } - - // Inutile de changer le mode de face culling s'il n'est pas actif - if (states.faceCulling) - { - if (currentRenderStates.cullingSide != states.cullingSide) - { - glCullFace(FaceSide[states.cullingSide]); - currentRenderStates.cullingSide = states.cullingSide; - } - } - - if (currentRenderStates.faceFilling != states.faceFilling) - { - glPolygonMode(GL_FRONT_AND_BACK, FaceFilling[states.faceFilling]); - currentRenderStates.faceFilling = states.faceFilling; - } - - // Ici encore, ça ne sert à rien de se soucier des fonctions de stencil sans qu'il soit activé - if (states.stencilTest) - { - if (currentRenderStates.stencilCompare.back != states.stencilCompare.back || - currentRenderStates.stencilReference.back != states.stencilReference.back || - currentRenderStates.stencilWriteMask.back != states.stencilWriteMask.back) - { - glStencilFuncSeparate(GL_BACK, RendererComparison[states.stencilCompare.back], states.stencilReference.back, states.stencilWriteMask.back); - currentRenderStates.stencilCompare.back = states.stencilCompare.back; - currentRenderStates.stencilReference.back = states.stencilReference.back; - currentRenderStates.stencilWriteMask.back = states.stencilWriteMask.back; - } - - if (currentRenderStates.stencilDepthFail.back != states.stencilDepthFail.back || - currentRenderStates.stencilFail.back != states.stencilFail.back || - currentRenderStates.stencilPass.back != states.stencilPass.back) - { - glStencilOpSeparate(GL_BACK, StencilOperation[states.stencilFail.back], StencilOperation[states.stencilDepthFail.back], StencilOperation[states.stencilPass.back]); - currentRenderStates.stencilDepthFail.back = states.stencilDepthFail.back; - currentRenderStates.stencilFail.back = states.stencilFail.back; - currentRenderStates.stencilPass.back = states.stencilPass.back; - } - - if (currentRenderStates.stencilCompare.front != states.stencilCompare.front || - currentRenderStates.stencilReference.front != states.stencilReference.front || - currentRenderStates.stencilWriteMask.front != states.stencilWriteMask.front) - { - glStencilFuncSeparate(GL_FRONT, RendererComparison[states.stencilCompare.front], states.stencilReference.front, states.stencilWriteMask.front); - currentRenderStates.stencilCompare.front = states.stencilCompare.front; - currentRenderStates.stencilReference.front = states.stencilReference.front; - currentRenderStates.stencilWriteMask.front = states.stencilWriteMask.front; - } - - if (currentRenderStates.stencilDepthFail.front != states.stencilDepthFail.front || - currentRenderStates.stencilFail.front != states.stencilFail.front || - currentRenderStates.stencilPass.front != states.stencilPass.front) - { - glStencilOpSeparate(GL_FRONT, StencilOperation[states.stencilFail.front], StencilOperation[states.stencilDepthFail.front], StencilOperation[states.stencilPass.front]); - currentRenderStates.stencilDepthFail.front = states.stencilDepthFail.front; - currentRenderStates.stencilFail.front = states.stencilFail.front; - currentRenderStates.stencilPass.front = states.stencilPass.front; - } - } - - if (!NumberEquals(currentRenderStates.lineWidth, states.lineWidth, 0.001f)) - { - glLineWidth(states.lineWidth); - currentRenderStates.lineWidth = states.lineWidth; - } - - if (!NumberEquals(currentRenderStates.pointSize, states.pointSize, 0.001f)) - { - glPointSize(states.pointSize); - currentRenderStates.pointSize = states.pointSize; - } - - // Paramètres de rendu - if (currentRenderStates.blending != states.blending) - { - if (states.blending) - glEnable(GL_BLEND); - else - glDisable(GL_BLEND); - - currentRenderStates.blending = states.blending; - } - - if (currentRenderStates.colorWrite != states.colorWrite) - { - GLboolean param = (states.colorWrite) ? GL_TRUE : GL_FALSE; - glColorMask(param, param, param, param); - - currentRenderStates.colorWrite = states.colorWrite; - } - - if (currentRenderStates.depthBuffer != states.depthBuffer) - { - if (states.depthBuffer) - glEnable(GL_DEPTH_TEST); - else - glDisable(GL_DEPTH_TEST); - - currentRenderStates.depthBuffer = states.depthBuffer; - } - - if (currentRenderStates.faceCulling != states.faceCulling) - { - if (states.faceCulling) - glEnable(GL_CULL_FACE); - else - glDisable(GL_CULL_FACE); - - currentRenderStates.faceCulling = states.faceCulling; - } - - if (currentRenderStates.scissorTest != states.scissorTest) - { - if (states.scissorTest) - glEnable(GL_SCISSOR_TEST); - else - glDisable(GL_SCISSOR_TEST); - - currentRenderStates.scissorTest = states.scissorTest; - } - - if (currentRenderStates.stencilTest != states.stencilTest) - { - if (states.stencilTest) - glEnable(GL_STENCIL_TEST); - else - glDisable(GL_STENCIL_TEST); - - currentRenderStates.stencilTest = states.stencilTest; - } - } - - void OpenGL::BindBuffer(BufferType type, GLuint id) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - if (s_contextStates->buffersBinding[type] != id) - { - glBindBuffer(BufferTarget[type], id); - s_contextStates->buffersBinding[type] = id; - } - } - - void OpenGL::BindProgram(GLuint id) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - if (s_contextStates->currentProgram != id) - { - glUseProgram(id); - s_contextStates->currentProgram = id; - } - } - - void OpenGL::BindSampler(GLuint unit, GLuint id) - { - #ifdef NAZARA_DEBUG - if (!glBindSampler) - { - NazaraError("Sampler are not supported"); - return; - } - - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - if (s_contextStates->samplers[unit] != id) - { - glBindSampler(unit, id); - s_contextStates->samplers[unit] = id; - } - } - - void OpenGL::BindScissorBox(const Recti& scissorBox) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - #if NAZARA_RENDERER_SAFE - if (scissorBox.width < 0) - { - NazaraError("Scissor box width must be positive"); - return; - } - - if (scissorBox.height < 0) - { - NazaraError("Scissor box height must be positive"); - return; - } - #endif - - if (s_contextStates->currentScissorBox != scissorBox) - { - if (s_contextStates->currentTarget) - { - unsigned int height = s_contextStates->currentTarget->GetHeight(); - glScissor(scissorBox.x, height - scissorBox.height - scissorBox.y, scissorBox.width, scissorBox.height); - s_contextStates->scissorBoxUpdated = true; - } - else - s_contextStates->scissorBoxUpdated = false; // Sinon on attend d'avoir un target - - s_contextStates->currentScissorBox = scissorBox; - } - } - - void OpenGL::BindTexture(ImageType type, GLuint id) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - if (s_contextStates->texturesBinding[s_contextStates->textureUnit] != id) - { - glBindTexture(TextureTarget[type], id); - s_contextStates->texturesBinding[s_contextStates->textureUnit] = id; - } - } - - void OpenGL::BindTexture(unsigned int textureUnit, ImageType type, GLuint id) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - if (s_contextStates->texturesBinding[textureUnit] != id) - { - BindTextureUnit(textureUnit); - - glBindTexture(TextureTarget[type], id); - s_contextStates->texturesBinding[textureUnit] = id; - } - } - - void OpenGL::BindTextureUnit(unsigned int textureUnit) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - if (s_contextStates->textureUnit != textureUnit) - { - glActiveTexture(GL_TEXTURE0 + textureUnit); - s_contextStates->textureUnit = textureUnit; - } - } - - void OpenGL::BindViewport(const Recti& viewport) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - #if NAZARA_RENDERER_SAFE - if (viewport.width < 0) - { - NazaraError("Viewport width must be positive"); - return; - } - - if (viewport.height < 0) - { - NazaraError("Viewport height must be positive"); - return; - } - #endif - - if (s_contextStates->currentViewport != viewport) - { - if (s_contextStates->currentTarget) - { - unsigned int height = s_contextStates->currentTarget->GetHeight(); - glViewport(viewport.x, height - viewport.height - viewport.y, viewport.width, viewport.height); - s_contextStates->viewportUpdated = true; - } - else - s_contextStates->viewportUpdated = false; // Sinon on attend d'avoir un target - - s_contextStates->currentViewport = viewport; - } - } - - void OpenGL::DeleteBuffer(BufferType type, GLuint id) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - glDeleteBuffers(1, &id); - if (s_contextStates->buffersBinding[type] == id) - s_contextStates->buffersBinding[type] = 0; - } - - void OpenGL::DeleteFrameBuffer(const Context* context, GLuint id) - { - // Si le contexte est actif, ne nous privons pas - if (Context::GetCurrent() == context) - glDeleteFramebuffers(1, &id); - else - s_contexts[context].garbage.emplace_back(GarbageResourceType_FrameBuffer, id); - } - - void OpenGL::DeleteProgram(GLuint id) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - glDeleteProgram(id); - if (s_contextStates->currentProgram == id) - s_contextStates->currentProgram = 0; - } - - void OpenGL::DeleteSampler(GLuint id) - { - #ifdef NAZARA_DEBUG - if (!glDeleteSamplers) - { - NazaraError("Sampler are not supported"); - return; - } - - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - glDeleteSamplers(1, &id); - - for (GLuint& binding : s_contextStates->samplers) - { - if (binding == id) - binding = 0; - } - } - - void OpenGL::DeleteTexture(GLuint id) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - glDeleteTextures(1, &id); - - for (GLuint& binding : s_contextStates->texturesBinding) - { - if (binding == id) - binding = 0; - } - } - - void OpenGL::DeleteVertexArray(const Context* context, GLuint id) - { - // Si le contexte est actif, ne nous privons pas - if (Context::GetCurrent() == context) - glDeleteFramebuffers(1, &id); - else - s_contexts[context].garbage.emplace_back(GarbageResourceType_VertexArray, id); - } - - GLuint OpenGL::GetCurrentBuffer(BufferType type) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return 0; - } - #endif - - return s_contextStates->buffersBinding[type]; - } - - GLuint OpenGL::GetCurrentProgram() - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return 0; - } - #endif - - return s_contextStates->currentProgram; - } - - Recti OpenGL::GetCurrentScissorBox() - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return Recti(); - } - #endif - - return s_contextStates->currentScissorBox; - } - - const RenderTarget* OpenGL::GetCurrentTarget() - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return nullptr; - } - #endif - - return s_contextStates->currentTarget; - } - - GLuint OpenGL::GetCurrentTexture() - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return 0; - } - #endif - - return s_contextStates->texturesBinding[s_contextStates->textureUnit]; - } - - GLuint OpenGL::GetCurrentTexture(unsigned int textureUnit) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return 0; - } - #endif - - return s_contextStates->texturesBinding[textureUnit]; - } - - unsigned int OpenGL::GetCurrentTextureUnit() - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return 0; - } - #endif - - return s_contextStates->textureUnit; - } - - Recti OpenGL::GetCurrentViewport() - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return Recti(); - } - #endif - - return s_contextStates->currentViewport; - } - - OpenGLFunc OpenGL::GetEntry(const String& entryPoint) - { - return LoadEntry(entryPoint.GetConstBuffer(), false); - } - - unsigned int OpenGL::GetGLSLVersion() - { - return s_glslVersion; - } - - String OpenGL::GetRendererName() - { - return s_rendererName; - } - - String OpenGL::GetVendorName() - { - return s_vendorName; - } - - unsigned int OpenGL::GetVersion() - { - return s_openglVersion; - } - - bool OpenGL::Initialize() - { - if (s_initialized) - return true; - - #if defined(NAZARA_PLATFORM_GLX) - Initializer display; - if (!display) - { - NazaraError("Failed to load display library"); - return false; - } - #endif - - if (!LoadLibrary()) - { - NazaraError("Failed to load OpenGL library"); - return false; - } - - s_initialized = true; - - // En cas d'erreur, on libèrera OpenGL - CallOnExit onExit(OpenGL::Uninitialize); - - // Le chargement des fonctions OpenGL nécessite un contexte OpenGL - ContextParameters parameters; - parameters.majorVersion = 2; - parameters.minorVersion = 0; - parameters.shared = false; - - /* - Note: Même le contexte de chargement nécessite quelques fonctions de base pour correctement s'initialiser - Pour cette raison, deux contextes sont créés, le premier sert à récupérer les fonctions permetttant - de créer le second avec les bons paramètres. - - Non sérieusement si vous avez une meilleure idée, contactez-moi - */ - - /****************************Chargement OpenGL****************************/ - - ///FIXME: I'm really thinking this is a mistake and GLX has no need to be initialized differently (Lynix) - #if defined(NAZARA_PLATFORM_LINUX) - glXCreateContextAttribs = reinterpret_cast(LoadEntry("glXCreateContextAttribsARB", false)); - #endif - - Context loadContext; - if (!loadContext.Create(parameters)) - { - NazaraError("Failed to create load context"); - return false; - } - - #if defined(NAZARA_PLATFORM_WINDOWS) - wglCreateContextAttribs = reinterpret_cast(LoadEntry("wglCreateContextAttribsARB", false)); - wglChoosePixelFormat = reinterpret_cast(LoadEntry("wglChoosePixelFormatARB", false)); - if (!wglChoosePixelFormat) - wglChoosePixelFormat = reinterpret_cast(LoadEntry("wglChoosePixelFormatEXT", false)); - #endif - - // Récupération de la version d'OpenGL et du GLSL - // Ce code se base sur le fait que la carte graphique renverra un contexte de compatibilité avec la plus haute version supportée - // Ce qui semble vrai chez AMD, NVidia et Intel, mais j'aimerai une preuve que ça sera toujours le cas... - glGetString = reinterpret_cast(LoadEntry("glGetString", false)); - if (!glGetString) - { - NazaraError("Unable to load OpenGL: failed to load glGetString"); - return false; - } - - const GLubyte* version; - unsigned int major; - unsigned int minor; - - version = glGetString(GL_VERSION); - if (!version) - { - NazaraError("Unable to retrieve OpenGL version"); - return false; - } - - major = version[0] - '0'; - minor = version[2] - '0'; - - if (major == 0 || major > 9) - { - NazaraError("Unable to retrieve OpenGL major version"); - return false; - } - - if (minor > 9) // 0 est une valeur correcte ici (ex: OpenGL 3.0) - { - NazaraWarning("Unable to retrieve OpenGL minor version (assuming 0)"); - minor = 0; - } - - s_openglVersion = major * 100 + minor * 10; // Donnera 330 pour OpenGL 3.3, 410 pour OpenGL 4.1, bien plus facile à comparer - - NazaraDebug("OpenGL version: " + String::Number(major) + '.' + String::Number(minor)); - - // Le moteur nécessite OpenGL 3.3, autant s'arrêter là si ce n'est pas le cas - if (s_openglVersion < 330) - { - NazaraError("OpenGL " + String::Number(major) + '.' + String::Number(minor) + " detected (3.3 required). Please upgrade your drivers or your video card"); - return false; - } - - // Récupération de la version du GLSL, même technique - version = glGetString(GL_SHADING_LANGUAGE_VERSION); - if (!version) - { - NazaraError("Unable to retrieve GLSL version"); - return false; - } - - major = version[0] - '0'; - minor = version[2] - '0'; - - if (major == 0 || major > 9) - { - NazaraError("Unable to retrieve GLSL major version"); - return false; - } - - if (minor > 9) // 0 est une valeur correcte ici (ex: GLSL 4.0) - { - NazaraWarning("Unable to retrieve GLSL minor version (using 0)"); - minor = 0; - } - - s_glslVersion = major * 100 + minor * 10; // GLSL 3.3 => 330 - - // Normalement rejeté il y a un moment déjà, mais on doit s'attendre à tout de la part d'un driver... - if (s_glslVersion < 330) - { - NazaraError("GLSL version is too low, please upgrade your drivers or your video card"); - return false; - } - - parameters.debugMode = true; // Certaines extensions n'apparaissent qu'avec un contexte de debug (e.g. ARB_debug_output) - parameters.majorVersion = ContextParameters::defaultMajorVersion = major; - parameters.minorVersion = ContextParameters::defaultMinorVersion = minor; - - if (!loadContext.Create(parameters)) // Destruction implicite du premier contexte - { - NazaraError("Failed to create load context"); - return false; - } - - /****************************************Noyau****************************************/ - - try - { - glActiveTexture = reinterpret_cast(LoadEntry("glActiveTexture")); - glAttachShader = reinterpret_cast(LoadEntry("glAttachShader")); - glBeginConditionalRender = reinterpret_cast(LoadEntry("glBeginConditionalRender")); - glBeginQuery = reinterpret_cast(LoadEntry("glBeginQuery")); - glBindAttribLocation = reinterpret_cast(LoadEntry("glBindAttribLocation")); - glBindBuffer = reinterpret_cast(LoadEntry("glBindBuffer")); - glBindFragDataLocation = reinterpret_cast(LoadEntry("glBindFragDataLocation")); - glBindFramebuffer = reinterpret_cast(LoadEntry("glBindFramebuffer")); - glBindRenderbuffer = reinterpret_cast(LoadEntry("glBindRenderbuffer")); - glBindSampler = reinterpret_cast(LoadEntry("glBindSampler")); - glBindTexture = reinterpret_cast(LoadEntry("glBindTexture")); - glBindVertexArray = reinterpret_cast(LoadEntry("glBindVertexArray")); - glBlendFunc = reinterpret_cast(LoadEntry("glBlendFunc")); - glBlendFuncSeparate = reinterpret_cast(LoadEntry("glBlendFuncSeparate")); - glBlitFramebuffer = reinterpret_cast(LoadEntry("glBlitFramebuffer")); - glBufferData = reinterpret_cast(LoadEntry("glBufferData")); - glBufferSubData = reinterpret_cast(LoadEntry("glBufferSubData")); - glClear = reinterpret_cast(LoadEntry("glClear")); - glClearColor = reinterpret_cast(LoadEntry("glClearColor")); - glClearDepth = reinterpret_cast(LoadEntry("glClearDepth")); - glClearStencil = reinterpret_cast(LoadEntry("glClearStencil")); - glCheckFramebufferStatus = reinterpret_cast(LoadEntry("glCheckFramebufferStatus")); - glCreateProgram = reinterpret_cast(LoadEntry("glCreateProgram")); - glCreateShader = reinterpret_cast(LoadEntry("glCreateShader")); - glColorMask = reinterpret_cast(LoadEntry("glColorMask")); - glCompressedTexSubImage1D = reinterpret_cast(LoadEntry("glCompressedTexSubImage1D")); - glCompressedTexSubImage2D = reinterpret_cast(LoadEntry("glCompressedTexSubImage2D")); - glCompressedTexSubImage3D = reinterpret_cast(LoadEntry("glCompressedTexSubImage3D")); - glCullFace = reinterpret_cast(LoadEntry("glCullFace")); - glCompileShader = reinterpret_cast(LoadEntry("glCompileShader")); - glCopyTexSubImage2D = reinterpret_cast(LoadEntry("glCopyTexSubImage2D")); - glDeleteBuffers = reinterpret_cast(LoadEntry("glDeleteBuffers")); - glDeleteFramebuffers = reinterpret_cast(LoadEntry("glDeleteFramebuffers")); - glDeleteQueries = reinterpret_cast(LoadEntry("glDeleteQueries")); - glDeleteProgram = reinterpret_cast(LoadEntry("glDeleteProgram")); - glDeleteRenderbuffers = reinterpret_cast(LoadEntry("glDeleteRenderbuffers")); - glDeleteSamplers = reinterpret_cast(LoadEntry("glDeleteSamplers")); - glDeleteShader = reinterpret_cast(LoadEntry("glDeleteShader")); - glDeleteTextures = reinterpret_cast(LoadEntry("glDeleteTextures")); - glDeleteVertexArrays = reinterpret_cast(LoadEntry("glDeleteVertexArrays")); - glDepthFunc = reinterpret_cast(LoadEntry("glDepthFunc")); - glDepthMask = reinterpret_cast(LoadEntry("glDepthMask")); - glDisable = reinterpret_cast(LoadEntry("glDisable")); - glDisableVertexAttribArray = reinterpret_cast(LoadEntry("glDisableVertexAttribArray")); - glDrawArrays = reinterpret_cast(LoadEntry("glDrawArrays")); - glDrawArraysInstanced = reinterpret_cast(LoadEntry("glDrawArraysInstanced")); - glDrawBuffer = reinterpret_cast(LoadEntry("glDrawBuffer")); - glDrawBuffers = reinterpret_cast(LoadEntry("glDrawBuffers")); - glDrawElements = reinterpret_cast(LoadEntry("glDrawElements")); - glDrawElementsInstanced = reinterpret_cast(LoadEntry("glDrawElementsInstanced")); - glEnable = reinterpret_cast(LoadEntry("glEnable")); - glEnableVertexAttribArray = reinterpret_cast(LoadEntry("glEnableVertexAttribArray")); - glEndConditionalRender = reinterpret_cast(LoadEntry("glEndConditionalRender")); - glEndQuery = reinterpret_cast(LoadEntry("glEndQuery")); - glFlush = reinterpret_cast(LoadEntry("glFlush")); - glFramebufferRenderbuffer = reinterpret_cast(LoadEntry("glFramebufferRenderbuffer")); - glFramebufferTexture = reinterpret_cast(LoadEntry("glFramebufferTexture")); - glFramebufferTexture1D = reinterpret_cast(LoadEntry("glFramebufferTexture1D")); - glFramebufferTexture2D = reinterpret_cast(LoadEntry("glFramebufferTexture2D")); - glFramebufferTexture3D = reinterpret_cast(LoadEntry("glFramebufferTexture3D")); - glFramebufferTextureLayer = reinterpret_cast(LoadEntry("glFramebufferTextureLayer")); - glGenerateMipmap = reinterpret_cast(LoadEntry("glGenerateMipmap")); - glGenBuffers = reinterpret_cast(LoadEntry("glGenBuffers")); - glGenFramebuffers = reinterpret_cast(LoadEntry("glGenFramebuffers")); - glGenQueries = reinterpret_cast(LoadEntry("glGenQueries")); - glGenRenderbuffers = reinterpret_cast(LoadEntry("glGenRenderbuffers")); - glGenSamplers = reinterpret_cast(LoadEntry("glGenSamplers")); - glGenTextures = reinterpret_cast(LoadEntry("glGenTextures")); - glGenVertexArrays = reinterpret_cast(LoadEntry("glGenVertexArrays")); - glGetActiveUniform = reinterpret_cast(LoadEntry("glGetActiveUniform")); - glGetBooleanv = reinterpret_cast(LoadEntry("glGetBooleanv")); - glGetBufferParameteriv = reinterpret_cast(LoadEntry("glGetBufferParameteriv")); - glGetError = reinterpret_cast(LoadEntry("glGetError")); - glGetFloatv = reinterpret_cast(LoadEntry("glGetFloatv")); - glGetIntegerv = reinterpret_cast(LoadEntry("glGetIntegerv")); - glGetQueryiv = reinterpret_cast(LoadEntry("glGetQueryiv")); - glGetQueryObjectiv = reinterpret_cast(LoadEntry("glGetQueryObjectiv")); - glGetQueryObjectuiv = reinterpret_cast(LoadEntry("glGetQueryObjectuiv")); - glGetProgramiv = reinterpret_cast(LoadEntry("glGetProgramiv")); - glGetProgramInfoLog = reinterpret_cast(LoadEntry("glGetProgramInfoLog")); - glGetShaderInfoLog = reinterpret_cast(LoadEntry("glGetShaderInfoLog")); - glGetShaderiv = reinterpret_cast(LoadEntry("glGetShaderiv")); - glGetShaderSource = reinterpret_cast(LoadEntry("glGetShaderSource")); - glGetStringi = reinterpret_cast(LoadEntry("glGetStringi")); - glGetTexImage = reinterpret_cast(LoadEntry("glGetTexImage")); - glGetTexLevelParameterfv = reinterpret_cast(LoadEntry("glGetTexLevelParameterfv")); - glGetTexLevelParameteriv = reinterpret_cast(LoadEntry("glGetTexLevelParameteriv")); - glGetTexParameterfv = reinterpret_cast(LoadEntry("glGetTexParameterfv")); - glGetTexParameteriv = reinterpret_cast(LoadEntry("glGetTexParameteriv")); - glGetUniformLocation = reinterpret_cast(LoadEntry("glGetUniformLocation")); - glIsEnabled = reinterpret_cast(LoadEntry("glIsEnabled")); - glLineWidth = reinterpret_cast(LoadEntry("glLineWidth")); - glLinkProgram = reinterpret_cast(LoadEntry("glLinkProgram")); - glMapBuffer = reinterpret_cast(LoadEntry("glMapBuffer")); - glMapBufferRange = reinterpret_cast(LoadEntry("glMapBufferRange")); - glPixelStorei = reinterpret_cast(LoadEntry("glPixelStorei")); - glPointSize = reinterpret_cast(LoadEntry("glPointSize")); - glPolygonMode = reinterpret_cast(LoadEntry("glPolygonMode")); - glReadPixels = reinterpret_cast(LoadEntry("glReadPixels")); - glRenderbufferStorage = reinterpret_cast(LoadEntry("glRenderbufferStorage")); - glSamplerParameterf = reinterpret_cast(LoadEntry("glSamplerParameterf")); - glSamplerParameteri = reinterpret_cast(LoadEntry("glSamplerParameteri")); - glScissor = reinterpret_cast(LoadEntry("glScissor")); - glShaderSource = reinterpret_cast(LoadEntry("glShaderSource")); - glStencilFunc = reinterpret_cast(LoadEntry("glStencilFunc")); - glStencilFuncSeparate = reinterpret_cast(LoadEntry("glStencilFuncSeparate")); - glStencilOp = reinterpret_cast(LoadEntry("glStencilOp")); - glStencilOpSeparate = reinterpret_cast(LoadEntry("glStencilOpSeparate")); - glTexImage2D = reinterpret_cast(LoadEntry("glTexImage2D")); - glTexImage3D = reinterpret_cast(LoadEntry("glTexImage3D")); - glTexParameterf = reinterpret_cast(LoadEntry("glTexParameterf")); - glTexParameteri = reinterpret_cast(LoadEntry("glTexParameteri")); - glTexSubImage1D = reinterpret_cast(LoadEntry("glTexSubImage1D")); - glTexSubImage2D = reinterpret_cast(LoadEntry("glTexSubImage2D")); - glTexSubImage3D = reinterpret_cast(LoadEntry("glTexSubImage3D")); - glUniform1f = reinterpret_cast(LoadEntry("glUniform1f")); - glUniform1i = reinterpret_cast(LoadEntry("glUniform1i")); - glUniform1fv = reinterpret_cast(LoadEntry("glUniform1fv")); - glUniform1iv = reinterpret_cast(LoadEntry("glUniform1iv")); - glUniform2fv = reinterpret_cast(LoadEntry("glUniform2fv")); - glUniform2iv = reinterpret_cast(LoadEntry("glUniform2iv")); - glUniform3fv = reinterpret_cast(LoadEntry("glUniform3fv")); - glUniform3iv = reinterpret_cast(LoadEntry("glUniform3iv")); - glUniform4fv = reinterpret_cast(LoadEntry("glUniform4fv")); - glUniform4iv = reinterpret_cast(LoadEntry("glUniform4iv")); - glUniformMatrix4fv = reinterpret_cast(LoadEntry("glUniformMatrix4fv")); - glUnmapBuffer = reinterpret_cast(LoadEntry("glUnmapBuffer")); - glUseProgram = reinterpret_cast(LoadEntry("glUseProgram")); - glValidateProgram = reinterpret_cast(LoadEntry("glValidateProgram")); - glVertexAttrib4f = reinterpret_cast(LoadEntry("glVertexAttrib4f")); - glVertexAttribDivisor = reinterpret_cast(LoadEntry("glVertexAttribDivisor")); - glVertexAttribPointer = reinterpret_cast(LoadEntry("glVertexAttribPointer")); - glVertexAttribIPointer = reinterpret_cast(LoadEntry("glVertexAttribIPointer")); - glViewport = reinterpret_cast(LoadEntry("glViewport")); - } - catch (const std::exception& e) - { - NazaraError("Unable to load OpenGL: " + String(e.what())); - return false; - } - - /****************************************Extensions****************************************/ - - // Fonctions optionnelles - glBindFragDataLocation = reinterpret_cast(LoadEntry("glBindFragDataLocation")); - - glDrawTexture = reinterpret_cast(LoadEntry("glDrawTextureNV", false)); - glInvalidateBufferData = reinterpret_cast(LoadEntry("glInvalidateBufferData", false)); - glVertexAttribLPointer = reinterpret_cast(LoadEntry("glVertexAttribLPointer", false)); - - #if defined(NAZARA_PLATFORM_WINDOWS) - wglGetExtensionsStringARB = reinterpret_cast(LoadEntry("wglGetExtensionsStringARB", false)); - wglGetExtensionsStringEXT = reinterpret_cast(LoadEntry("wglGetExtensionsStringEXT", false)); - wglSwapInterval = reinterpret_cast(LoadEntry("wglSwapIntervalEXT", false)); - #elif defined(NAZARA_PLATFORM_GLX) - glXSwapIntervalEXT = reinterpret_cast(LoadEntry("glXSwapIntervalEXT", false)); - NzglXSwapIntervalMESA = reinterpret_cast(LoadEntry("glXSwapIntervalMESA", false)); - glXSwapIntervalSGI = reinterpret_cast(LoadEntry("glXSwapIntervalSGI", false)); - #endif - - if (!glGetStringi || !LoadExtensions3()) - { - NazaraWarning("Failed to load OpenGL 3 extension system, falling back to OpenGL 2 extension system..."); - - if (!LoadExtensionsString(reinterpret_cast(glGetString(GL_EXTENSIONS)))) - NazaraWarning("Failed to load extension system"); - } - - #ifdef NAZARA_PLATFORM_WINDOWS - { - bool loaded; - if (wglGetExtensionsStringARB) - loaded = LoadExtensionsString(reinterpret_cast(wglGetExtensionsStringARB(wglGetCurrentDC()))); - else if (wglGetExtensionsStringEXT) - loaded = LoadExtensionsString(reinterpret_cast(wglGetExtensionsStringEXT())); - else - loaded = false; - - if (!loaded) - NazaraWarning("Failed to load wgl extension string"); - } - #endif - - // AnisotropicFilter - s_openGLextensions[OpenGLExtension_AnisotropicFilter] = IsSupported("GL_EXT_texture_filter_anisotropic"); - - // DebugOutput - if (s_openglVersion >= 430 || IsSupported("GL_KHR_debug")) - { - try - { - glDebugMessageCallback = reinterpret_cast(LoadEntry("glDebugMessageCallback")); - glDebugMessageControl = reinterpret_cast(LoadEntry("glDebugMessageControl")); - glDebugMessageInsert = reinterpret_cast(LoadEntry("glDebugMessageInsert")); - glGetDebugMessageLog = reinterpret_cast(LoadEntry("glGetDebugMessageLog")); - - s_openGLextensions[OpenGLExtension_DebugOutput] = true; - } - catch (const std::exception& e) - { - NazaraWarning("Failed to load GL_KHR_debug: " + String(e.what())); - } - } - - if (!s_openGLextensions[OpenGLExtension_DebugOutput] && IsSupported("GL_ARB_debug_output")) - { - try - { - glDebugMessageCallback = reinterpret_cast(LoadEntry("glDebugMessageCallbackARB")); - glDebugMessageControl = reinterpret_cast(LoadEntry("glDebugMessageControlARB")); - glDebugMessageInsert = reinterpret_cast(LoadEntry("glDebugMessageInsertARB")); - glGetDebugMessageLog = reinterpret_cast(LoadEntry("glGetDebugMessageLogARB")); - - s_openGLextensions[OpenGLExtension_DebugOutput] = true; - } - catch (const std::exception& e) - { - NazaraWarning("Failed to load GL_ARB_debug_output: " + String(e.what())); - } - } - - // FP64 - if (s_openglVersion >= 400 || IsSupported("GL_ARB_gpu_shader_fp64")) - { - try - { - glUniform1d = reinterpret_cast(LoadEntry("glUniform1d")); - glUniform1dv = reinterpret_cast(LoadEntry("glUniform1dv")); - glUniform2dv = reinterpret_cast(LoadEntry("glUniform2dv")); - glUniform3dv = reinterpret_cast(LoadEntry("glUniform3dv")); - glUniform4dv = reinterpret_cast(LoadEntry("glUniform4dv")); - - s_openGLextensions[OpenGLExtension_FP64] = true; - } - catch (const std::exception& e) - { - NazaraWarning("Failed to load ARB_gpu_shader_fp64: " + String(e.what())); - } - } - - // GetProgramBinary - if (s_openglVersion >= 410 || IsSupported("GL_ARB_get_program_binary")) - { - try - { - glGetProgramBinary = reinterpret_cast(LoadEntry("glGetProgramBinary")); - glProgramBinary = reinterpret_cast(LoadEntry("glProgramBinary")); - glProgramParameteri = reinterpret_cast(LoadEntry("glProgramParameteri")); - - s_openGLextensions[OpenGLExtension_GetProgramBinary] = true; - } - catch (const std::exception& e) - { - NazaraWarning("Failed to load ARB_get_program_binary: (" + String(e.what()) + ")"); - } - } - - // SeparateShaderObjects - if (s_openglVersion >= 400 || IsSupported("GL_ARB_separate_shader_objects")) - { - try - { - glProgramUniform1f = reinterpret_cast(LoadEntry("glProgramUniform1f")); - glProgramUniform1i = reinterpret_cast(LoadEntry("glProgramUniform1i")); - glProgramUniform1fv = reinterpret_cast(LoadEntry("glProgramUniform1fv")); - glProgramUniform1iv = reinterpret_cast(LoadEntry("glProgramUniform1iv")); - glProgramUniform2fv = reinterpret_cast(LoadEntry("glProgramUniform2fv")); - glProgramUniform2iv = reinterpret_cast(LoadEntry("glProgramUniform2iv")); - glProgramUniform3fv = reinterpret_cast(LoadEntry("glProgramUniform3fv")); - glProgramUniform3iv = reinterpret_cast(LoadEntry("glProgramUniform3iv")); - glProgramUniform4fv = reinterpret_cast(LoadEntry("glProgramUniform4fv")); - glProgramUniform4iv = reinterpret_cast(LoadEntry("glProgramUniform4iv")); - glProgramUniformMatrix4fv = reinterpret_cast(LoadEntry("glProgramUniformMatrix4fv")); - - // Si ARB_gpu_shader_fp64 est supporté, alors cette extension donne également accès aux fonctions utilisant des double - if (s_openGLextensions[OpenGLExtension_FP64]) - { - glProgramUniform1d = reinterpret_cast(LoadEntry("glProgramUniform1d")); - glProgramUniform1dv = reinterpret_cast(LoadEntry("glProgramUniform1dv")); - glProgramUniform2dv = reinterpret_cast(LoadEntry("glProgramUniform2dv")); - glProgramUniform3dv = reinterpret_cast(LoadEntry("glProgramUniform3dv")); - glProgramUniform4dv = reinterpret_cast(LoadEntry("glProgramUniform4dv")); - glProgramUniformMatrix4dv = reinterpret_cast(LoadEntry("glProgramUniformMatrix4dv")); - } - - s_openGLextensions[OpenGLExtension_SeparateShaderObjects] = true; - } - catch (const std::exception& e) - { - NazaraWarning("Failed to load ARB_separate_shader_objects: (" + String(e.what()) + ")"); - } - } - - // Shader_ImageLoadStore - s_openGLextensions[OpenGLExtension_Shader_ImageLoadStore] = (s_openglVersion >= 420 || IsSupported("GL_ARB_shader_image_load_store")); - - // TextureCompression_s3tc - s_openGLextensions[OpenGLExtension_TextureCompression_s3tc] = IsSupported("GL_EXT_texture_compression_s3tc"); - - // TextureStorage - if (s_openglVersion >= 420 || IsSupported("GL_ARB_texture_storage")) - { - try - { - glTexStorage1D = reinterpret_cast(LoadEntry("glTexStorage1D")); - glTexStorage2D = reinterpret_cast(LoadEntry("glTexStorage2D")); - glTexStorage3D = reinterpret_cast(LoadEntry("glTexStorage3D")); - - s_openGLextensions[OpenGLExtension_TextureStorage] = true; - } - catch (const std::exception& e) - { - NazaraWarning("Failed to load ARB_texture_storage: " + String(e.what())); - } - } - - /******************************Initialisation*****************************/ - - s_contextStates = nullptr; - s_rendererName = reinterpret_cast(glGetString(GL_RENDERER)); - s_vendorName = reinterpret_cast(glGetString(GL_VENDOR)); - - // On initialise les vrais contextes OpenGL - if (!Context::Initialize()) - { - NazaraError("Failed to initialize contexts"); - return false; - } - - // Le contexte OpenGL n'est plus assuré à partir d'ici - onExit.Reset(); - - return true; - } - - bool OpenGL::IsInitialized() - { - return s_initialized; - } - - bool OpenGL::IsSupported(OpenGLExtension extension) - { - return s_openGLextensions[extension]; - } - - bool OpenGL::IsSupported(const String& string) - { - return s_openGLextensionSet.find(string) != s_openGLextensionSet.end(); - } - - void OpenGL::SetBuffer(BufferType type, GLuint id) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - s_contextStates->buffersBinding[type] = id; - } - - void OpenGL::SetScissorBox(const Recti& scissorBox) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - s_contextStates->currentScissorBox = scissorBox; - } - - void OpenGL::SetProgram(GLuint id) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - s_contextStates->currentProgram = id; - } - - void OpenGL::SetTarget(const RenderTarget* renderTarget) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - s_contextStates->currentTarget = renderTarget; - if (renderTarget) - { - if (!s_contextStates->scissorBoxUpdated) - { - const Recti& scissorBox = s_contextStates->currentViewport; - - unsigned int height = s_contextStates->currentTarget->GetHeight(); - glScissor(scissorBox.x, height - scissorBox.height - scissorBox.y, scissorBox.width, scissorBox.height); - - s_contextStates->scissorBoxUpdated = true; - } - - if (!s_contextStates->viewportUpdated) - { - const Recti& viewport = s_contextStates->currentViewport; - - unsigned int height = s_contextStates->currentTarget->GetHeight(); - glViewport(viewport.x, height - viewport.height - viewport.y, viewport.width, viewport.height); - - s_contextStates->viewportUpdated = true; - } - } - } - - void OpenGL::SetTexture(GLuint id) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - s_contextStates->texturesBinding[s_contextStates->textureUnit] = id; - } - - void OpenGL::SetTexture(unsigned int textureUnit, GLuint id) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - s_contextStates->texturesBinding[textureUnit] = id; - } - - void OpenGL::SetTextureUnit(unsigned int textureUnit) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - s_contextStates->textureUnit = textureUnit; - } - - void OpenGL::SetViewport(const Recti& viewport) - { - #ifdef NAZARA_DEBUG - if (!s_contextStates) - { - NazaraError("No context activated"); - return; - } - #endif - - s_contextStates->currentViewport = viewport; - } - - bool OpenGL::TranslateFormat(PixelFormatType pixelFormat, Format* format, FormatType type) - { - // Par défaut - format->swizzle[0] = GL_RED; - format->swizzle[1] = GL_GREEN; - format->swizzle[2] = GL_BLUE; - format->swizzle[3] = GL_ALPHA; - - switch (pixelFormat) - { - case PixelFormatType_A8: - if (type == FormatType_Texture) // Format supporté uniquement par les textures - { - if (GetVersion() >= 300) - { - format->dataFormat = GL_RED; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_R8; - - // Simulation du format - format->swizzle[0] = GL_ONE; - format->swizzle[1] = GL_ONE; - format->swizzle[2] = GL_ONE; - format->swizzle[3] = GL_RED; - } - else - { - // Le bon vieux format GL_ALPHA - format->dataFormat = GL_ALPHA; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_ALPHA; - } - - return true; - } - else - return false; - - case PixelFormatType_BGR8: - format->dataFormat = GL_BGR; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_RGB8; - return true; - - case PixelFormatType_BGRA8: - format->dataFormat = GL_BGRA; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_RGBA8; - return true; - - case PixelFormatType_DXT1: - format->dataFormat = GL_RGB; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; - return true; - - case PixelFormatType_DXT3: - format->dataFormat = GL_RGBA; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT3_EXT; - return true; - - case PixelFormatType_DXT5: - format->dataFormat = GL_RGBA; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; - return true; - - case PixelFormatType_L8: - if (type == FormatType_Texture) // Format supporté uniquement par les textures - { - if (GetVersion() >= 300) - { - format->dataFormat = GL_RED; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_R8; - - // Simulation du format - format->swizzle[0] = GL_RED; - format->swizzle[1] = GL_RED; - format->swizzle[2] = GL_RED; - format->swizzle[3] = GL_ONE; - } - else - { - format->dataFormat = 0x1909; // GL_LUMINANCE - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = 0x1909; // GL_LUMINANCE - } - - return true; - } - else - return false; - - case PixelFormatType_LA8: - if (type == FormatType_Texture) // Format supporté uniquement par les textures - { - if (GetVersion() >= 300) - { - format->dataFormat = GL_RG; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_RG8; - - // Simulation du format - format->swizzle[0] = GL_RED; - format->swizzle[1] = GL_RED; - format->swizzle[2] = GL_RED; - format->swizzle[3] = GL_GREEN; - } - else - { - format->dataFormat = 0x190A; // GL_LUMINANCE_ALPHA - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = 0x190A; // GL_LUMINANCE_ALPHA; - } - - return true; - } - else - return false; - - case PixelFormatType_R8: - format->dataFormat = GL_RED; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_R8; - return true; - - case PixelFormatType_R8I: - format->dataFormat = GL_RED; - format->dataType = GL_BYTE; - format->internalFormat = GL_R8I; - return true; - - case PixelFormatType_R8UI: - format->dataFormat = GL_RED; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_R8UI; - return true; - - case PixelFormatType_R16: - format->dataFormat = GL_RED; - format->dataType = GL_UNSIGNED_SHORT; - format->internalFormat = GL_R16; - return true; - - case PixelFormatType_R16F: - format->dataFormat = GL_RED; - format->dataType = GL_HALF_FLOAT; - format->internalFormat = GL_R16F; - return true; - - case PixelFormatType_R16I: - format->dataFormat = GL_RED; - format->dataType = GL_SHORT; - format->internalFormat = GL_R16I; - return true; - - case PixelFormatType_R16UI: - format->dataFormat = GL_RED; - format->dataType = GL_UNSIGNED_SHORT; - format->internalFormat = GL_R16UI; - return true; - - case PixelFormatType_R32F: - format->dataFormat = GL_RED; - format->dataType = GL_FLOAT; - format->internalFormat = GL_R32F; - return true; - - case PixelFormatType_R32I: - format->dataFormat = GL_RED; - format->dataType = GL_INT; - format->internalFormat = GL_R32I; - return true; - - case PixelFormatType_R32UI: - format->dataFormat = GL_RED; - format->dataType = GL_UNSIGNED_INT; - format->internalFormat = GL_R32UI; - return true; - - case PixelFormatType_RG8: - format->dataFormat = GL_RG; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_RG8; - return true; - - case PixelFormatType_RG8I: - format->dataFormat = GL_RG; - format->dataType = GL_BYTE; - format->internalFormat = GL_RG8I; - return true; - - case PixelFormatType_RG8UI: - format->dataFormat = GL_RG; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_RG8UI; - return true; - - case PixelFormatType_RG16: - format->dataFormat = GL_RG; - format->dataType = GL_UNSIGNED_SHORT; - format->internalFormat = GL_RG16; - return true; - - case PixelFormatType_RG16F: - format->dataFormat = GL_RG; - format->dataType = GL_HALF_FLOAT; - format->internalFormat = GL_RG16F; - return true; - - case PixelFormatType_RG16I: - format->dataFormat = GL_RG; - format->dataType = GL_SHORT; - format->internalFormat = GL_RG16I; - return true; - - case PixelFormatType_RG16UI: - format->dataFormat = GL_RG; - format->dataType = GL_UNSIGNED_SHORT; - format->internalFormat = GL_RG16UI; - return true; - - case PixelFormatType_RG32F: - format->dataFormat = GL_RG; - format->dataType = GL_FLOAT; - format->internalFormat = GL_RG32F; - return true; - - case PixelFormatType_RG32I: - format->dataFormat = GL_RG; - format->dataType = GL_INT; - format->internalFormat = GL_RG32I; - return true; - - case PixelFormatType_RG32UI: - format->dataFormat = GL_RG; - format->dataType = GL_UNSIGNED_INT; - format->internalFormat = GL_RG32UI; - return true; - - case PixelFormatType_RGB5A1: - format->dataFormat = GL_RGBA; - format->dataType = GL_UNSIGNED_SHORT_5_5_5_1; - format->internalFormat = GL_RGB5_A1; - return true; - - case PixelFormatType_RGB8: - format->dataFormat = GL_RGB; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_RGB8; - return true; - - case PixelFormatType_RGB16F: - format->dataFormat = GL_RGB; - format->dataType = GL_HALF_FLOAT; - format->internalFormat = GL_RGB16F; - return true; - - case PixelFormatType_RGB16I: - format->dataFormat = GL_RGB; - format->dataType = GL_SHORT; - format->internalFormat = GL_RGB16I; - return true; - - case PixelFormatType_RGB16UI: - format->dataFormat = GL_RGB; - format->dataType = GL_UNSIGNED_SHORT; - format->internalFormat = GL_RGB16UI; - return true; - - case PixelFormatType_RGB32F: - format->dataFormat = GL_RGB; - format->dataType = GL_FLOAT; - format->internalFormat = GL_RGB32F; - return true; - - case PixelFormatType_RGB32I: - format->dataFormat = GL_RGB; - format->dataType = GL_INT; - format->internalFormat = GL_RGB32I; - return true; - - case PixelFormatType_RGB32UI: - format->dataFormat = GL_RGB; - format->dataType = GL_UNSIGNED_INT; - format->internalFormat = GL_RGB32UI; - return true; - - case PixelFormatType_RGBA4: - format->dataFormat = GL_RGBA; - format->dataType = GL_UNSIGNED_SHORT_4_4_4_4; - format->internalFormat = GL_RGBA4; - return true; - - case PixelFormatType_RGBA8: - format->dataFormat = GL_RGBA; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_RGBA8; - return true; - - case PixelFormatType_RGBA16F: - format->dataFormat = GL_RGBA; - format->dataType = GL_HALF_FLOAT; - format->internalFormat = GL_RGBA16F; - return true; - - case PixelFormatType_RGBA16I: - format->dataFormat = GL_RGBA; - format->dataType = GL_SHORT; - format->internalFormat = GL_RGBA16I; - return true; - - case PixelFormatType_RGBA16UI: - format->dataFormat = GL_RGBA; - format->dataType = GL_INT; - format->internalFormat = GL_RGBA16UI; - return true; - - case PixelFormatType_RGBA32F: - format->dataFormat = GL_RGBA; - format->dataType = GL_FLOAT; - format->internalFormat = GL_RGBA32F; - return true; - - case PixelFormatType_RGBA32I: - format->dataFormat = GL_RGB; - format->dataType = GL_INT; - format->internalFormat = GL_RGB32I; - return true; - - case PixelFormatType_RGBA32UI: - format->dataFormat = GL_RGB; - format->dataType = GL_UNSIGNED_INT; - format->internalFormat = GL_RGB32UI; - return true; - - case PixelFormatType_Depth16: - format->dataFormat = GL_DEPTH_COMPONENT; - format->dataType = GL_UNSIGNED_SHORT; - format->internalFormat = GL_DEPTH_COMPONENT16; - - format->swizzle[0] = GL_RED; - format->swizzle[1] = GL_RED; - format->swizzle[2] = GL_RED; - format->swizzle[3] = GL_ONE; - return true; - - case PixelFormatType_Depth24: - format->dataFormat = GL_DEPTH_COMPONENT; - format->dataType = GL_UNSIGNED_INT; - format->internalFormat = GL_DEPTH_COMPONENT24; - - format->swizzle[0] = GL_RED; - format->swizzle[1] = GL_RED; - format->swizzle[2] = GL_RED; - format->swizzle[3] = GL_ONE; - return true; - - case PixelFormatType_Depth24Stencil8: - format->dataFormat = GL_DEPTH_STENCIL; - format->dataType = GL_UNSIGNED_INT_24_8; - format->internalFormat = GL_DEPTH24_STENCIL8; - - format->swizzle[0] = GL_RED; - format->swizzle[1] = GL_RED; - format->swizzle[2] = GL_RED; - format->swizzle[3] = GL_GREEN; - return true; - - case PixelFormatType_Depth32: - format->dataFormat = GL_DEPTH_COMPONENT; - format->dataType = GL_UNSIGNED_BYTE; - format->internalFormat = GL_DEPTH_COMPONENT32; - - format->swizzle[0] = GL_RED; - format->swizzle[1] = GL_RED; - format->swizzle[2] = GL_RED; - format->swizzle[3] = GL_ONE; - return true; - - case PixelFormatType_Stencil1: - if (type == FormatType_Texture) // Les formats de stencil ne sont pas supportés par les textures - return false; - else - { - format->dataFormat = GL_NONE; - format->dataType = GL_NONE; - format->internalFormat = GL_STENCIL_INDEX1; - return true; - } - - case PixelFormatType_Stencil4: - if (type == FormatType_Texture) - return false; - else - { - format->dataFormat = GL_NONE; - format->dataType = GL_NONE; - format->internalFormat = GL_STENCIL_INDEX4; - return true; - } - - case PixelFormatType_Stencil8: - if (type == FormatType_Texture) - return false; - else - { - format->dataFormat = GL_NONE; - format->dataType = GL_NONE; - format->internalFormat = GL_STENCIL_INDEX8; - return true; - } - - case PixelFormatType_Stencil16: - if (type == FormatType_Texture) - return false; - else - { - format->dataFormat = GL_NONE; - format->dataType = GL_NONE; - format->internalFormat = GL_STENCIL_INDEX16; - return true; - } - - case PixelFormatType_Undefined: - break; - } - - NazaraError("Invalid pixel format"); - return false; - } - - void OpenGL::Uninitialize() - { - if (s_initialized) - { - s_initialized = false; - - Context::Uninitialize(); - - for (bool& ext : s_openGLextensions) - ext = false; - - s_glslVersion = 0; - s_openGLextensionSet.clear(); - s_openglVersion = 0; - s_rendererName.Clear(false); - s_vendorName.Clear(false); - - UnloadLibrary(); - } - } - - void OpenGL::OnContextChanged(const Context* newContext) - { - s_contextStates = (newContext) ? &s_contexts[newContext] : nullptr; - if (s_contextStates) - { - // On supprime les éventuelles ressources mortes-vivantes (Qui ne peuvent être libérées que dans notre contexte) - for (std::pair& pair : s_contextStates->garbage) - { - switch (pair.first) - { - case GarbageResourceType_FrameBuffer: - glDeleteFramebuffers(1, &pair.second); - break; - - case GarbageResourceType_VertexArray: - glDeleteVertexArrays(1, &pair.second); - break; - } - } - s_contextStates->garbage.clear(); - } - } - - void OpenGL::OnContextDestruction(const Context* context) - { - /* - ** Il serait possible d'activer le contexte avant sa destruction afin de libérer les éventuelles ressources mortes-vivantes, - ** mais un driver bien conçu va libérer ces ressources de lui-même. - */ - s_contexts.erase(context); - } - - GLenum OpenGL::Attachment[] = - { - GL_COLOR_ATTACHMENT0, // AttachmentPoint_Color - GL_DEPTH_ATTACHMENT, // AttachmentPoint_Depth - GL_DEPTH_STENCIL_ATTACHMENT, // AttachmentPoint_DepthStencil - GL_STENCIL_ATTACHMENT // AttachmentPoint_Stencil - }; - - static_assert(AttachmentPoint_Max + 1 == 4, "Attachment array is incomplete"); - - GLenum OpenGL::BlendFunc[] = - { - GL_DST_ALPHA, // BlendFunc_DestAlpha - GL_DST_COLOR, // BlendFunc_DestColor - GL_SRC_ALPHA, // BlendFunc_SrcAlpha - GL_SRC_COLOR, // BlendFunc_SrcColor - GL_ONE_MINUS_DST_ALPHA, // BlendFunc_InvDestAlpha - GL_ONE_MINUS_DST_COLOR, // BlendFunc_InvDestColor - GL_ONE_MINUS_SRC_ALPHA, // BlendFunc_InvSrcAlpha - GL_ONE_MINUS_SRC_COLOR, // BlendFunc_InvSrcColor - GL_ONE, // BlendFunc_One - GL_ZERO // BlendFunc_Zero - }; - - static_assert(BlendFunc_Max + 1 == 10, "Blend func array is incomplete"); - - GLenum OpenGL::BufferLock[] = - { - GL_WRITE_ONLY, // BufferAccess_DiscardAndWrite - GL_READ_ONLY, // BufferAccess_ReadOnly - GL_READ_WRITE, // BufferAccess_ReadWrite - GL_WRITE_ONLY // BufferAccess_WriteOnly - }; - - static_assert(BufferAccess_Max + 1 == 4, "Buffer lock array is incomplete"); - - GLenum OpenGL::BufferLockRange[] = - { - // http://www.opengl.org/discussion_boards/showthread.php/170118-VBOs-strangely-slow?p=1198118#post1198118 - GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_WRITE_BIT, // BufferAccess_DiscardAndWrite - GL_MAP_READ_BIT, // BufferAccess_ReadOnly - GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, // BufferAccess_ReadWrite - GL_MAP_WRITE_BIT // BufferAccess_WriteOnly - }; - - static_assert(BufferAccess_Max + 1 == 4, "Buffer lock range array is incomplete"); - - GLenum OpenGL::BufferTarget[] = - { - GL_ELEMENT_ARRAY_BUFFER, // BufferType_Index, - GL_ARRAY_BUFFER, // BufferType_Vertex - }; - - static_assert(BufferType_Max + 1 == 2, "Buffer target array is incomplete"); - - GLenum OpenGL::BufferTargetBinding[] = - { - GL_ELEMENT_ARRAY_BUFFER_BINDING, // BufferType_Index, - GL_ARRAY_BUFFER_BINDING, // BufferType_Vertex - }; - - static_assert(BufferType_Max + 1 == 2, "Buffer target binding array is incomplete"); - - GLenum OpenGL::BufferUsage[] = - { - // D'après la documentation, GL_STREAM_DRAW semble être plus adapté à notre cas (ratio modification/rendu 1:2-3) - // Source: http://www.opengl.org/sdk/docs/man/html/glBufferData.xhtml - GL_STREAM_DRAW, // BufferUsage_Dynamic - GL_STATIC_DRAW // BufferUsage_Static - }; - - static_assert(BufferUsage_Max + 1 == 2, "Buffer usage array is incomplete"); - - GLenum OpenGL::ComponentType[] = - { - GL_UNSIGNED_BYTE, // ComponentType_Color - GL_DOUBLE, // ComponentType_Double1 - GL_DOUBLE, // ComponentType_Double2 - GL_DOUBLE, // ComponentType_Double3 - GL_DOUBLE, // ComponentType_Double4 - GL_FLOAT, // ComponentType_Float1 - GL_FLOAT, // ComponentType_Float2 - GL_FLOAT, // ComponentType_Float3 - GL_FLOAT, // ComponentType_Float4 - GL_INT, // ComponentType_Int1 - GL_INT, // ComponentType_Int2 - GL_INT, // ComponentType_Int3 - GL_INT, // ComponentType_Int4 - GL_FLOAT // ComponentType_Quaternion - }; - - static_assert(ComponentType_Max + 1 == 14, "Attribute type array is incomplete"); - - GLenum OpenGL::CubemapFace[] = - { - GL_TEXTURE_CUBE_MAP_POSITIVE_X, // CubemapFace_PositiveX - GL_TEXTURE_CUBE_MAP_NEGATIVE_X, // CubemapFace_NegativeX - GL_TEXTURE_CUBE_MAP_POSITIVE_Y, // CubemapFace_PositiveY - GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, // CubemapFace_NegativeY - GL_TEXTURE_CUBE_MAP_POSITIVE_Z, // CubemapFace_PositiveZ - GL_TEXTURE_CUBE_MAP_NEGATIVE_Z // CubemapFace_NegativeZ - }; - - static_assert(CubemapFace_Max + 1 == 6, "Cubemap face array is incomplete"); - - GLenum OpenGL::FaceFilling[] = - { - GL_FILL, // FaceFilling_Fill - GL_LINE, // FaceFilling_Line - GL_POINT // FaceFilling_Point - }; - - static_assert(FaceFilling_Max + 1 == 3, "Face filling array is incomplete"); - - GLenum OpenGL::FaceSide[] = - { - GL_BACK, // FaceSide_Back - GL_FRONT, // FaceSide_Front - GL_FRONT_AND_BACK // FaceSide_FrontAndBack - }; - - static_assert(FaceSide_Max + 1 == 3, "Face side array is incomplete"); - - GLenum OpenGL::PrimitiveMode[] = - { - GL_LINES, // PrimitiveMode_LineList - GL_LINE_STRIP, // PrimitiveMode_LineStrip - GL_POINTS, // PrimitiveMode_PointList - GL_TRIANGLES, // PrimitiveMode_TriangleList - GL_TRIANGLE_STRIP, // PrimitiveMode_TriangleStrip - GL_TRIANGLE_FAN // PrimitiveMode_TriangleFan - }; - - static_assert(PrimitiveMode_Max + 1 == 6, "Primitive mode array is incomplete"); - - GLenum OpenGL::QueryCondition[] = - { - GL_QUERY_WAIT, // GpuQueryCondition_NoWait - GL_QUERY_BY_REGION_NO_WAIT, // GpuQueryCondition_Region_NoWait - GL_QUERY_BY_REGION_WAIT, // GpuQueryCondition_Region_Wait - GL_QUERY_WAIT // GpuQueryCondition_Wait - }; - - static_assert(GpuQueryCondition_Max + 1 == 4, "Query condition array is incomplete"); - - GLenum OpenGL::QueryMode[] = - { - GL_ANY_SAMPLES_PASSED, // GpuQueryMode_AnySamplesPassed - GL_ANY_SAMPLES_PASSED_CONSERVATIVE, // GpuQueryMode_AnySamplesPassedConservative - GL_PRIMITIVES_GENERATED, // GpuQueryMode_PrimitiveGenerated - GL_SAMPLES_PASSED, // GpuQueryMode_SamplesPassed - GL_TIME_ELAPSED, // GpuQueryMode_TimeElapsed - GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN // GpuQueryMode_TransformFeedbackPrimitivesWritten - }; - - static_assert(GpuQueryMode_Max + 1 == 6, "Query mode array is incomplete"); - - GLenum OpenGL::RendererComparison[] = - { - GL_ALWAYS, // RendererComparison_Always - GL_EQUAL, // RendererComparison_Equal - GL_GREATER, // RendererComparison_Greater - GL_GEQUAL, // RendererComparison_GreaterOrEqual - GL_LESS, // RendererComparison_Less - GL_LEQUAL, // RendererComparison_LessOrEqual - GL_NEVER, // RendererComparison_Never - GL_NOTEQUAL // RendererComparison_NotEqual - }; - - static_assert(RendererComparison_Max + 1 == 8, "Renderer comparison array is incomplete"); - - GLenum OpenGL::RendererParameter[] = - { - GL_BLEND, // RendererParameter_Blend - GL_NONE, // RendererParameter_ColorWrite - GL_DEPTH_TEST, // RendererParameter_DepthBuffer - GL_NONE, // RendererParameter_DepthWrite - GL_CULL_FACE, // RendererParameter_FaceCulling - GL_SCISSOR_TEST, // RendererParameter_ScissorTest - GL_STENCIL_TEST // RendererParameter_StencilTest - }; - - static_assert(RendererParameter_Max + 1 == 7, "Renderer parameter array is incomplete"); - - GLenum OpenGL::SamplerWrapMode[] = - { - GL_CLAMP_TO_EDGE, // TextureWrap_Clamp - GL_MIRRORED_REPEAT, // SamplerWrap_MirroredRepeat - GL_REPEAT // TextureWrap_Repeat - }; - - static_assert(SamplerWrap_Max + 1 == 3, "Sampler wrap mode array is incomplete"); - - GLenum OpenGL::ShaderStage[] = - { - GL_FRAGMENT_SHADER, // ShaderStage_Fragment - GL_GEOMETRY_SHADER, // ShaderStage_Geometry - GL_VERTEX_SHADER // ShaderStage_Vertex - }; - - static_assert(ShaderStageType_Max + 1 == 3, "Shader stage array is incomplete"); - - GLenum OpenGL::StencilOperation[] = - { - GL_DECR, // StencilOperation_Decrement - GL_DECR_WRAP, // StencilOperation_DecrementNoClamp - GL_INCR, // StencilOperation_Increment - GL_INCR_WRAP, // StencilOperation_IncrementNoClamp - GL_INVERT, // StencilOperation_Invert - GL_KEEP, // StencilOperation_Keep - GL_REPLACE, // StencilOperation_Replace - GL_ZERO // StencilOperation_Zero - }; - - static_assert(StencilOperation_Max + 1 == 8, "Stencil operation array is incomplete"); - - GLenum OpenGL::TextureTarget[] = - { - GL_TEXTURE_1D, // ImageType_1D - GL_TEXTURE_1D_ARRAY, // ImageType_1D_Array - GL_TEXTURE_2D, // ImageType_2D - GL_TEXTURE_2D_ARRAY, // ImageType_2D_Array - GL_TEXTURE_3D, // ImageType_3D - GL_TEXTURE_CUBE_MAP // ImageType_Cubemap - }; - - static_assert(ImageType_Max + 1 == 6, "Texture target array is incomplete"); - - GLenum OpenGL::TextureTargetBinding[] = - { - GL_TEXTURE_BINDING_1D, // ImageType_1D - GL_TEXTURE_BINDING_1D_ARRAY, // ImageType_1D_Array - GL_TEXTURE_BINDING_2D, // ImageType_2D - GL_TEXTURE_BINDING_2D_ARRAY, // ImageType_2D_Array - GL_TEXTURE_BINDING_3D, // ImageType_3D - GL_TEXTURE_BINDING_CUBE_MAP // ImageType_Cubemap - }; - - static_assert(ImageType_Max + 1 == 6, "Texture target binding array is incomplete"); - - GLenum OpenGL::TextureTargetProxy[] = - { - GL_PROXY_TEXTURE_1D, // ImageType_1D - GL_PROXY_TEXTURE_1D_ARRAY, // ImageType_1D_Array - GL_PROXY_TEXTURE_2D, // ImageType_2D - GL_PROXY_TEXTURE_2D_ARRAY, // ImageType_2D_Array - GL_PROXY_TEXTURE_3D, // ImageType_3D - GL_PROXY_TEXTURE_CUBE_MAP // ImageType_Cubemap - }; - - static_assert(ImageType_Max + 1 == 6, "Texture target proxy array is incomplete"); - - UInt8 OpenGL::VertexComponentIndex[] = - { - 10, // VertexComponent_InstanceData0 - 11, // VertexComponent_InstanceData1 - 12, // VertexComponent_InstanceData2 - 13, // VertexComponent_InstanceData3 - 14, // VertexComponent_InstanceData4 - 15, // VertexComponent_InstanceData5 - 4, // VertexComponent_Color - 2, // VertexComponent_Normal - 0, // VertexComponent_Position - 3, // VertexComponent_Tangent - 1, // VertexComponent_TexCoord - 5, // VertexComponent_Userdata0 - 6, // VertexComponent_Userdata1 - 7, // VertexComponent_Userdata2 - 8, // VertexComponent_Userdata3 - 9 // VertexComponent_Userdata4 - }; - - static_assert(VertexComponent_Max + 1 == 16, "Attribute index array is incomplete"); - -PFNGLACTIVETEXTUREPROC glActiveTexture = nullptr; -PFNGLATTACHSHADERPROC glAttachShader = nullptr; -PFNGLBEGINCONDITIONALRENDERPROC glBeginConditionalRender = nullptr; -PFNGLBEGINQUERYPROC glBeginQuery = nullptr; -PFNGLBINDATTRIBLOCATIONPROC glBindAttribLocation = nullptr; -PFNGLBINDBUFFERPROC glBindBuffer = nullptr; -PFNGLBINDFRAMEBUFFERPROC glBindFramebuffer = nullptr; -PFNGLBINDFRAGDATALOCATIONPROC glBindFragDataLocation = nullptr; -PFNGLBINDRENDERBUFFERPROC glBindRenderbuffer = nullptr; -PFNGLBINDSAMPLERPROC glBindSampler = nullptr; -PFNGLBINDTEXTUREPROC glBindTexture = nullptr; -PFNGLBINDVERTEXARRAYPROC glBindVertexArray = nullptr; -PFNGLBLENDFUNCPROC glBlendFunc = nullptr; -PFNGLBLENDFUNCSEPARATEPROC glBlendFuncSeparate = nullptr; -PFNGLBLITFRAMEBUFFERPROC glBlitFramebuffer = nullptr; -PFNGLBUFFERDATAPROC glBufferData = nullptr; -PFNGLBUFFERSUBDATAPROC glBufferSubData = nullptr; -PFNGLCLEARPROC glClear = nullptr; -PFNGLCLEARCOLORPROC glClearColor = nullptr; -PFNGLCLEARDEPTHPROC glClearDepth = nullptr; -PFNGLCLEARSTENCILPROC glClearStencil = nullptr; -PFNGLCREATEPROGRAMPROC glCreateProgram = nullptr; -PFNGLCREATESHADERPROC glCreateShader = nullptr; -PFNGLCHECKFRAMEBUFFERSTATUSPROC glCheckFramebufferStatus = nullptr; -PFNGLCOLORMASKPROC glColorMask = nullptr; -PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glCompressedTexSubImage1D = nullptr; -PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glCompressedTexSubImage2D = nullptr; -PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glCompressedTexSubImage3D = nullptr; -PFNGLCULLFACEPROC glCullFace = nullptr; -PFNGLCOMPILESHADERPROC glCompileShader = nullptr; -PFNGLCOPYTEXSUBIMAGE2DPROC glCopyTexSubImage2D = nullptr; -PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback = nullptr; -PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl = nullptr; -PFNGLDEBUGMESSAGEINSERTPROC glDebugMessageInsert = nullptr; -PFNGLDELETEBUFFERSPROC glDeleteBuffers = nullptr; -PFNGLDELETEFRAMEBUFFERSPROC glDeleteFramebuffers = nullptr; -PFNGLDELETEPROGRAMPROC glDeleteProgram = nullptr; -PFNGLDELETEQUERIESPROC glDeleteQueries = nullptr; -PFNGLDELETERENDERBUFFERSPROC glDeleteRenderbuffers = nullptr; -PFNGLDELETESAMPLERSPROC glDeleteSamplers = nullptr; -PFNGLDELETESHADERPROC glDeleteShader = nullptr; -PFNGLDELETETEXTURESPROC glDeleteTextures = nullptr; -PFNGLDELETEVERTEXARRAYSPROC glDeleteVertexArrays = nullptr; -PFNGLDEPTHFUNCPROC glDepthFunc = nullptr; -PFNGLDEPTHMASKPROC glDepthMask = nullptr; -PFNGLDISABLEPROC glDisable = nullptr; -PFNGLDISABLEVERTEXATTRIBARRAYPROC glDisableVertexAttribArray = nullptr; -PFNGLDRAWARRAYSPROC glDrawArrays = nullptr; -PFNGLDRAWARRAYSINSTANCEDPROC glDrawArraysInstanced = nullptr; -PFNGLDRAWBUFFERPROC glDrawBuffer = nullptr; -PFNGLDRAWBUFFERSPROC glDrawBuffers = nullptr; -PFNGLDRAWELEMENTSPROC glDrawElements = nullptr; -PFNGLDRAWELEMENTSINSTANCEDPROC glDrawElementsInstanced = nullptr; -PFNGLDRAWTEXTURENVPROC glDrawTexture = nullptr; -PFNGLENABLEPROC glEnable = nullptr; -PFNGLENABLEVERTEXATTRIBARRAYPROC glEnableVertexAttribArray = nullptr; -PFNGLENDCONDITIONALRENDERPROC glEndConditionalRender = nullptr; -PFNGLENDQUERYPROC glEndQuery = nullptr; -PFNGLFLUSHPROC glFlush = nullptr; -PFNGLFRAMEBUFFERRENDERBUFFERPROC glFramebufferRenderbuffer = nullptr; -PFNGLFRAMEBUFFERTEXTUREPROC glFramebufferTexture = nullptr; -PFNGLFRAMEBUFFERTEXTURE1DPROC glFramebufferTexture1D = nullptr; -PFNGLFRAMEBUFFERTEXTURE2DPROC glFramebufferTexture2D = nullptr; -PFNGLFRAMEBUFFERTEXTURE3DPROC glFramebufferTexture3D = nullptr; -PFNGLFRAMEBUFFERTEXTURELAYERPROC glFramebufferTextureLayer = nullptr; -PFNGLGENERATEMIPMAPPROC glGenerateMipmap = nullptr; -PFNGLGENBUFFERSPROC glGenBuffers = nullptr; -PFNGLGENFRAMEBUFFERSPROC glGenFramebuffers = nullptr; -PFNGLGENRENDERBUFFERSPROC glGenRenderbuffers = nullptr; -PFNGLGENQUERIESPROC glGenQueries = nullptr; -PFNGLGENSAMPLERSPROC glGenSamplers = nullptr; -PFNGLGENTEXTURESPROC glGenTextures = nullptr; -PFNGLGENVERTEXARRAYSPROC glGenVertexArrays = nullptr; -PFNGLGETACTIVEUNIFORMPROC glGetActiveUniform = nullptr; -PFNGLGETBOOLEANVPROC glGetBooleanv = nullptr; -PFNGLGETBUFFERPARAMETERIVPROC glGetBufferParameteriv = nullptr; -PFNGLGETDEBUGMESSAGELOGPROC glGetDebugMessageLog = nullptr; -PFNGLGETERRORPROC glGetError = nullptr; -PFNGLGETFLOATVPROC glGetFloatv = nullptr; -PFNGLGETINTEGERVPROC glGetIntegerv = nullptr; -PFNGLGETPROGRAMBINARYPROC glGetProgramBinary = nullptr; -PFNGLGETPROGRAMIVPROC glGetProgramiv = nullptr; -PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = nullptr; -PFNGLGETQUERYIVPROC glGetQueryiv = nullptr; -PFNGLGETQUERYOBJECTIVPROC glGetQueryObjectiv = nullptr; -PFNGLGETQUERYOBJECTUIVPROC glGetQueryObjectuiv = nullptr; -PFNGLGETSHADERINFOLOGPROC glGetShaderInfoLog = nullptr; -PFNGLGETSHADERIVPROC glGetShaderiv = nullptr; -PFNGLGETSHADERSOURCEPROC glGetShaderSource = nullptr; -PFNGLGETSTRINGPROC glGetString = nullptr; -PFNGLGETSTRINGIPROC glGetStringi = nullptr; -PFNGLGETTEXIMAGEPROC glGetTexImage = nullptr; -PFNGLGETTEXLEVELPARAMETERFVPROC glGetTexLevelParameterfv = nullptr; -PFNGLGETTEXLEVELPARAMETERIVPROC glGetTexLevelParameteriv = nullptr; -PFNGLGETTEXPARAMETERFVPROC glGetTexParameterfv = nullptr; -PFNGLGETTEXPARAMETERIVPROC glGetTexParameteriv = nullptr; -PFNGLGETUNIFORMLOCATIONPROC glGetUniformLocation = nullptr; -PFNGLINVALIDATEBUFFERDATAPROC glInvalidateBufferData = nullptr; -PFNGLISENABLEDPROC glIsEnabled = nullptr; -PFNGLLINEWIDTHPROC glLineWidth = nullptr; -PFNGLLINKPROGRAMPROC glLinkProgram = nullptr; -PFNGLMAPBUFFERPROC glMapBuffer = nullptr; -PFNGLMAPBUFFERRANGEPROC glMapBufferRange = nullptr; -PFNGLPIXELSTOREIPROC glPixelStorei = nullptr; -PFNGLPOINTSIZEPROC glPointSize = nullptr; -PFNGLPOLYGONMODEPROC glPolygonMode = nullptr; -PFNGLPROGRAMBINARYPROC glProgramBinary = nullptr; -PFNGLPROGRAMPARAMETERIPROC glProgramParameteri = nullptr; -PFNGLPROGRAMUNIFORM1DPROC glProgramUniform1d = nullptr; -PFNGLPROGRAMUNIFORM1FPROC glProgramUniform1f = nullptr; -PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i = nullptr; -PFNGLPROGRAMUNIFORM1DVPROC glProgramUniform1dv = nullptr; -PFNGLPROGRAMUNIFORM1FVPROC glProgramUniform1fv = nullptr; -PFNGLPROGRAMUNIFORM1IVPROC glProgramUniform1iv = nullptr; -PFNGLPROGRAMUNIFORM2DVPROC glProgramUniform2dv = nullptr; -PFNGLPROGRAMUNIFORM2FVPROC glProgramUniform2fv = nullptr; -PFNGLPROGRAMUNIFORM2IVPROC glProgramUniform2iv = nullptr; -PFNGLPROGRAMUNIFORM3DVPROC glProgramUniform3dv = nullptr; -PFNGLPROGRAMUNIFORM3FVPROC glProgramUniform3fv = nullptr; -PFNGLPROGRAMUNIFORM3IVPROC glProgramUniform3iv = nullptr; -PFNGLPROGRAMUNIFORM4DVPROC glProgramUniform4dv = nullptr; -PFNGLPROGRAMUNIFORM4FVPROC glProgramUniform4fv = nullptr; -PFNGLPROGRAMUNIFORM4IVPROC glProgramUniform4iv = nullptr; -PFNGLPROGRAMUNIFORMMATRIX4DVPROC glProgramUniformMatrix4dv = nullptr; -PFNGLPROGRAMUNIFORMMATRIX4FVPROC glProgramUniformMatrix4fv = nullptr; -PFNGLREADPIXELSPROC glReadPixels = nullptr; -PFNGLRENDERBUFFERSTORAGEPROC glRenderbufferStorage = nullptr; -PFNGLSAMPLERPARAMETERFPROC glSamplerParameterf = nullptr; -PFNGLSAMPLERPARAMETERIPROC glSamplerParameteri = nullptr; -PFNGLSCISSORPROC glScissor = nullptr; -PFNGLSHADERSOURCEPROC glShaderSource = nullptr; -PFNGLSTENCILFUNCPROC glStencilFunc = nullptr; -PFNGLSTENCILFUNCSEPARATEPROC glStencilFuncSeparate = nullptr; -PFNGLSTENCILOPPROC glStencilOp = nullptr; -PFNGLSTENCILOPSEPARATEPROC glStencilOpSeparate = nullptr; -PFNGLTEXIMAGE1DPROC glTexImage1D = nullptr; -PFNGLTEXIMAGE2DPROC glTexImage2D = nullptr; -PFNGLTEXIMAGE3DPROC glTexImage3D = nullptr; -PFNGLTEXPARAMETERFPROC glTexParameterf = nullptr; -PFNGLTEXPARAMETERIPROC glTexParameteri = nullptr; -PFNGLTEXSTORAGE1DPROC glTexStorage1D = nullptr; -PFNGLTEXSTORAGE2DPROC glTexStorage2D = nullptr; -PFNGLTEXSTORAGE3DPROC glTexStorage3D = nullptr; -PFNGLTEXSUBIMAGE1DPROC glTexSubImage1D = nullptr; -PFNGLTEXSUBIMAGE2DPROC glTexSubImage2D = nullptr; -PFNGLTEXSUBIMAGE3DPROC glTexSubImage3D = nullptr; -PFNGLUNIFORM1DPROC glUniform1d = nullptr; -PFNGLUNIFORM1FPROC glUniform1f = nullptr; -PFNGLUNIFORM1IPROC glUniform1i = nullptr; -PFNGLUNIFORM1DVPROC glUniform1dv = nullptr; -PFNGLUNIFORM1FVPROC glUniform1fv = nullptr; -PFNGLUNIFORM1IVPROC glUniform1iv = nullptr; -PFNGLUNIFORM2DVPROC glUniform2dv = nullptr; -PFNGLUNIFORM2FVPROC glUniform2fv = nullptr; -PFNGLUNIFORM2IVPROC glUniform2iv = nullptr; -PFNGLUNIFORM3DVPROC glUniform3dv = nullptr; -PFNGLUNIFORM3FVPROC glUniform3fv = nullptr; -PFNGLUNIFORM3IVPROC glUniform3iv = nullptr; -PFNGLUNIFORM4DVPROC glUniform4dv = nullptr; -PFNGLUNIFORM4FVPROC glUniform4fv = nullptr; -PFNGLUNIFORM4IVPROC glUniform4iv = nullptr; -PFNGLUNIFORMMATRIX4DVPROC glUniformMatrix4dv = nullptr; -PFNGLUNIFORMMATRIX4FVPROC glUniformMatrix4fv = nullptr; -PFNGLUNMAPBUFFERPROC glUnmapBuffer = nullptr; -PFNGLUSEPROGRAMPROC glUseProgram = nullptr; -PFNGLVALIDATEPROGRAMPROC glValidateProgram = nullptr; -PFNGLVERTEXATTRIB4FPROC glVertexAttrib4f = nullptr; -PFNGLVERTEXATTRIBDIVISORPROC glVertexAttribDivisor = nullptr; -PFNGLVERTEXATTRIBPOINTERPROC glVertexAttribPointer = nullptr; -PFNGLVERTEXATTRIBIPOINTERPROC glVertexAttribIPointer = nullptr; -PFNGLVERTEXATTRIBLPOINTERPROC glVertexAttribLPointer = nullptr; -PFNGLVIEWPORTPROC glViewport = nullptr; - -#if defined(NAZARA_PLATFORM_WINDOWS) -PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormat = nullptr; -PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs = nullptr; -PFNWGLGETEXTENSIONSSTRINGARBPROC wglGetExtensionsStringARB = nullptr; -PFNWGLGETEXTENSIONSSTRINGEXTPROC wglGetExtensionsStringEXT = nullptr; -PFNWGLSWAPINTERVALEXTPROC wglSwapInterval = nullptr; -#elif defined(NAZARA_PLATFORM_GLX) -GLX::PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribs = nullptr; -GLX::PFNGLXSWAPINTERVALEXTPROC glXSwapIntervalEXT = nullptr; -GLX::PFNGLXSWAPINTERVALMESAPROC NzglXSwapIntervalMESA = nullptr; -GLX::PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = nullptr; -#endif - -} diff --git a/src/Nazara/Renderer/RenderBuffer.cpp b/src/Nazara/Renderer/RenderBuffer.cpp deleted file mode 100644 index b6b182ab8..000000000 --- a/src/Nazara/Renderer/RenderBuffer.cpp +++ /dev/null @@ -1,133 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - RenderBuffer::RenderBuffer() : - m_id(0) - { - } - - RenderBuffer::~RenderBuffer() - { - OnRenderBufferRelease(this); - - Destroy(); - } - - bool RenderBuffer::Create(PixelFormatType format, unsigned int width, unsigned int height) - { - Destroy(); - - #if NAZARA_RENDERER_SAFE - if (width == 0 || height == 0) - { - NazaraError("Invalid size"); - return false; - } - - if (!PixelFormat::IsValid(format)) - { - NazaraError("Invalid pixel format"); - return false; - } - #endif - - OpenGL::Format openglFormat; - if (!OpenGL::TranslateFormat(format, &openglFormat, OpenGL::FormatType_RenderBuffer)) - { - NazaraError("Failed to translate pixel format \"" + PixelFormat::GetName(format) + "\" into OpenGL format"); - return false; - } - - GLuint renderBuffer = 0; - - glGenRenderbuffers(1, &renderBuffer); - if (!renderBuffer) - { - NazaraError("Failed to create renderbuffer"); - return false; - } - - GLint previous; - glGetIntegerv(GL_RENDERBUFFER_BINDING, &previous); - - glBindRenderbuffer(GL_RENDERBUFFER, renderBuffer); - glRenderbufferStorage(GL_RENDERBUFFER, openglFormat.internalFormat, width, height); - - if (previous != 0) - glBindRenderbuffer(GL_RENDERBUFFER, previous); - - m_pixelFormat = format; - m_height = height; - m_id = renderBuffer; - m_width = width; - - return true; - } - - void RenderBuffer::Destroy() - { - if (m_id) - { - OnRenderBufferDestroy(this); - - Context::EnsureContext(); - - GLuint renderBuffer = m_id; - glDeleteRenderbuffers(1, &renderBuffer); // Les Renderbuffers sont partagés entre les contextes: Ne posera pas de problème - m_id = 0; - } - } - - unsigned int RenderBuffer::GetHeight() const - { - return m_height; - } - - PixelFormatType RenderBuffer::GetFormat() const - { - return m_pixelFormat; - } - - unsigned int RenderBuffer::GetWidth() const - { - return m_width; - } - - unsigned int RenderBuffer::GetOpenGLID() const - { - return m_id; - } - - bool RenderBuffer::IsValid() const - { - return m_id != 0; - } - - bool RenderBuffer::Initialize() - { - if (!RenderBufferLibrary::Initialize()) - { - NazaraError("Failed to initialise library"); - return false; - } - - return true; - } - - void RenderBuffer::Uninitialize() - { - RenderBufferLibrary::Uninitialize(); - } - - RenderBufferLibrary::LibraryMap RenderBuffer::s_library; -} diff --git a/src/Nazara/Renderer/RenderTarget.cpp b/src/Nazara/Renderer/RenderTarget.cpp deleted file mode 100644 index 717c7497a..000000000 --- a/src/Nazara/Renderer/RenderTarget.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include - -namespace Nz -{ - RenderTarget::~RenderTarget() - { - OnRenderTargetRelease(this); - } - - bool RenderTarget::IsActive() const - { - return Renderer::GetTarget() == this; - } - - bool RenderTarget::SetActive(bool active) - { - if (active) - return Renderer::SetTarget(this); - else if (Renderer::GetTarget() == this) - return Renderer::SetTarget(nullptr); - - return true; - } - - void RenderTarget::Desactivate() const - { - // Seuls les target sans contextes (ex: RenderTexture) nécessitent une désactivation - } -} diff --git a/src/Nazara/Renderer/RenderTexture.cpp b/src/Nazara/Renderer/RenderTexture.cpp deleted file mode 100644 index 647b8ff91..000000000 --- a/src/Nazara/Renderer/RenderTexture.cpp +++ /dev/null @@ -1,854 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - namespace - { - struct Attachment - { - NazaraSlot(RenderBuffer, OnRenderBufferDestroy, renderBufferDestroySlot); - NazaraSlot(Texture, OnTextureDestroy, textureDestroySlot); - - RenderBufferRef buffer; - TextureRef texture; - - AttachmentPoint attachmentPoint; - bool isBuffer; - bool isUsed = false; - unsigned int height; - unsigned int width; - }; - - unsigned int attachmentIndex[AttachmentPoint_Max+1] = - { - 3, // AttachmentPoint_Color - 0, // AttachmentPoint_Depth - 1, // AttachmentPoint_DepthStencil - 2 // AttachmentPoint_Stencil - }; - - AttachmentPoint FormatTypeToAttachment(PixelFormatType format) - { - const PixelFormatInfo& info = PixelFormat::GetInfo(format); - switch (info.content) - { - case PixelFormatContent_ColorRGBA: - return AttachmentPoint_Color; - - case PixelFormatContent_DepthStencil: - return (!info.greenMask.TestAny()) ? AttachmentPoint_Depth : AttachmentPoint_DepthStencil; - - case PixelFormatContent_Stencil: - return AttachmentPoint_Stencil; - - case PixelFormatContent_Undefined: - break; - } - - NazaraInternalError("Unexpected pixel format content: 0x" + String::Number(info.content, 16)); - return AttachmentPoint_Max; - } - - GLuint lockedPrevious = 0; - UInt8 lockedLevel = 0; - } - - struct RenderTextureImpl - { - NazaraSlot(Context, OnContextDestroy, contextDestroySlot); - - GLuint fbo; - std::vector attachments; - std::vector colorTargets; - mutable std::vector drawBuffers; - const Context* context; - bool complete = false; - bool userDefinedTargets = false; - unsigned int height; - unsigned int width; - }; - - bool RenderTexture::AttachBuffer(AttachmentPoint attachmentPoint, UInt8 index, RenderBuffer* buffer) - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Render texture not created"); - return false; - } - - if (attachmentPoint != AttachmentPoint_Color) - { - if (index > 0) - { - NazaraError("Index must be 0 for non-color attachments"); - return false; - } - } - else - { - if (index >= Renderer::GetMaxColorAttachments()) - { - NazaraError("Color index is over max color attachments (" + String::Number(index) + " >= " + String::Number(Renderer::GetMaxColorAttachments()) + ")"); - return false; - } - } - - if (!buffer || !buffer->IsValid()) - { - NazaraError("Invalid render buffer"); - return false; - } - - unsigned int depthStencilIndex = attachmentIndex[AttachmentPoint_DepthStencil]; - if (m_impl->attachments.size() > depthStencilIndex && m_impl->attachments[depthStencilIndex].isUsed) - { - if (attachmentPoint == AttachmentPoint_Depth) - { - NazaraError("Depth target already attached by DepthStencil attachment"); - return false; - } - else if (attachmentPoint == AttachmentPoint_Stencil) - { - NazaraError("Stencil target already attached by DepthStencil attachment"); - return false; - } - } - - AttachmentPoint targetAttachmentPoint = FormatTypeToAttachment(buffer->GetFormat()); - if (targetAttachmentPoint != attachmentPoint && targetAttachmentPoint != AttachmentPoint_DepthStencil && - attachmentPoint != AttachmentPoint_Depth && attachmentPoint != AttachmentPoint_Stencil) - { - NazaraError("Pixel format type does not match attachment point type"); - return false; - } - #endif - - if (!Lock()) - { - NazaraError("Failed to lock render texture"); - return false; - } - - // Détachement de l'attache précédente (Si il y a) - Detach(attachmentPoint, index); - - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, GL_RENDERBUFFER, buffer->GetOpenGLID()); - - Unlock(); - - unsigned int attachIndex = attachmentIndex[attachmentPoint] + index; - if (attachIndex >= m_impl->attachments.size()) - m_impl->attachments.resize(attachIndex+1); - - Attachment& attachment = m_impl->attachments[attachIndex]; - attachment.attachmentPoint = attachmentPoint; - attachment.buffer = buffer; - attachment.renderBufferDestroySlot.Connect(buffer->OnRenderBufferDestroy, std::bind(&RenderTexture::OnRenderBufferDestroy, this, std::placeholders::_1, attachIndex)); - attachment.isBuffer = true; - attachment.isUsed = true; - attachment.height = buffer->GetHeight(); - attachment.width = buffer->GetWidth(); - - InvalidateSize(); - InvalidateTargets(); - - return true; - } - - bool RenderTexture::AttachBuffer(AttachmentPoint attachmentPoint, UInt8 index, PixelFormatType format, unsigned int width, unsigned int height) - { - RenderBufferRef renderBuffer = RenderBuffer::New(); - if (!renderBuffer->Create(format, width, height)) - { - NazaraError("Failed to create RenderBuffer"); - return false; - } - - if (!AttachBuffer(attachmentPoint, index, renderBuffer)) - { - NazaraError("Failed to attach buffer"); - return false; - } - - return true; - } - - bool RenderTexture::AttachTexture(AttachmentPoint attachmentPoint, UInt8 index, Texture* texture, unsigned int z) - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Render texture not created"); - return false; - } - - if (attachmentPoint != AttachmentPoint_Color) - { - if (index > 0) - { - NazaraError("Index must be 0 for non-color attachments"); - return false; - } - } - else - { - if (index >= Renderer::GetMaxColorAttachments()) - { - NazaraError("Color index is over max color attachments (" + String::Number(index) + " >= " + String::Number(Renderer::GetMaxColorAttachments()) + ")"); - return false; - } - } - - if (attachmentPoint == AttachmentPoint_Stencil) - { - NazaraError("Targeting stencil-only textures is not supported"); - return false; - } - - unsigned int depthStencilIndex = attachmentIndex[AttachmentPoint_DepthStencil]; - if (attachmentPoint == AttachmentPoint_Depth && m_impl->attachments.size() > depthStencilIndex && - m_impl->attachments[depthStencilIndex].isUsed) - { - NazaraError("Depth target already attached by DepthStencil attachment"); - return false; - } - - if (!texture || !texture->IsValid()) - { - NazaraError("Invalid texture"); - return false; - } - - unsigned int depth = (texture->GetType() == ImageType_Cubemap) ? 6 : texture->GetDepth(); - if (z >= depth) - { - NazaraError("Z value exceeds depth (" + String::Number(z) + " >= (" + String::Number(depth) + ')'); - return false; - } - - AttachmentPoint targetAttachmentPoint = FormatTypeToAttachment(texture->GetFormat()); - if (targetAttachmentPoint != attachmentPoint && targetAttachmentPoint != AttachmentPoint_DepthStencil && - attachmentPoint != AttachmentPoint_Depth && attachmentPoint != AttachmentPoint_Stencil) - { - NazaraError("Pixel format type does not match attachment point type"); - return false; - } - #endif - - if (!Lock()) - { - NazaraError("Failed to lock render texture"); - return false; - } - - // Détachement de l'attache précédente (Si il y a) - Detach(attachmentPoint, index); - - switch (texture->GetType()) - { - case ImageType_1D: - glFramebufferTexture1D(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, GL_TEXTURE_1D, texture->GetOpenGLID(), 0); - break; - - case ImageType_1D_Array: - case ImageType_2D_Array: - glFramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, texture->GetOpenGLID(), 0, z); - break; - - case ImageType_2D: - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, GL_TEXTURE_2D, texture->GetOpenGLID(), 0); - break; - - case ImageType_3D: - glFramebufferTexture3D(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, GL_TEXTURE_3D, texture->GetOpenGLID(), 0, z); - break; - - case ImageType_Cubemap: - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, OpenGL::CubemapFace[z], texture->GetOpenGLID(), 0); - break; - } - - Unlock(); - - unsigned int attachIndex = attachmentIndex[attachmentPoint] + index; - if (attachIndex >= m_impl->attachments.size()) - m_impl->attachments.resize(attachIndex+1); - - Attachment& attachment = m_impl->attachments[attachIndex]; - attachment.attachmentPoint = attachmentPoint; - attachment.isBuffer = false; - attachment.isUsed = true; - attachment.height = texture->GetHeight(); - attachment.texture = texture; - attachment.textureDestroySlot.Connect(texture->OnTextureDestroy, std::bind(&RenderTexture::OnTextureDestroy, this, std::placeholders::_1, attachIndex)); - attachment.width = texture->GetWidth(); - - InvalidateSize(); - InvalidateTargets(); - - return true; - } - - bool RenderTexture::Create(bool lock) - { - Destroy(); - - #if NAZARA_RENDERER_SAFE - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return false; - } - #endif - - std::unique_ptr impl(new RenderTextureImpl); - - impl->fbo = 0; - glGenFramebuffers(1, &impl->fbo); - - if (!impl->fbo) - { - NazaraError("Failed to create framebuffer"); - return false; - } - - m_impl = impl.release(); - m_impl->context = Context::GetCurrent(); - m_impl->contextDestroySlot.Connect(m_impl->context->OnContextDestroy, this, &RenderTexture::OnContextDestroy); - - m_checked = false; - m_drawBuffersUpdated = true; - m_sizeUpdated = false; - m_targetsUpdated = true; - - if (lock) - { - // En cas d'exception, la ressource sera quand même libérée - CallOnExit onExit([this] () - { - Destroy(); - }); - - if (!Lock()) - { - NazaraError("Failed to lock render texture"); - return false; - } - - onExit.Reset(); - } - - OnRenderTargetParametersChange(this); - OnRenderTargetSizeChange(this); - - return true; - } - - void RenderTexture::Destroy() - { - if (m_impl) - { - if (IsActive()) - Renderer::SetTarget(nullptr); - - // Le FBO devant être supprimé dans son contexte d'origine, nous déléguons sa suppression à la classe OpenGL - // Celle-ci va libérer le FBO dès que possible (la prochaine fois que son contexte d'origine sera actif) - OpenGL::DeleteFrameBuffer(m_impl->context, m_impl->fbo); - - delete m_impl; // Enlève également une références sur les Texture/RenderBuffer - m_impl = nullptr; - } - } - - void RenderTexture::Detach(AttachmentPoint attachmentPoint, UInt8 index) - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Render texture not created"); - return; - } - - if (attachmentPoint != AttachmentPoint_Color && index > 0) - { - NazaraError("Index must be 0 for non-color attachments"); - return; - } - #endif - - unsigned int attachIndex = attachmentIndex[attachmentPoint] + index; - if (attachIndex >= m_impl->attachments.size()) - return; - - Attachment& attachement = m_impl->attachments[attachIndex]; - if (!attachement.isUsed) - return; - - if (!Lock()) - { - NazaraError("Failed to lock render texture"); - return; - } - - attachement.isUsed = false; - - if (attachement.isBuffer) - { - glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, GL_RENDERBUFFER, 0); - - attachement.buffer = nullptr; - attachement.renderBufferDestroySlot.Disconnect(); - } - else - { - if (glFramebufferTexture) - glFramebufferTexture(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, 0, 0); - else - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, OpenGL::Attachment[attachmentPoint]+index, 0, 0, 0); - - attachement.texture = nullptr; - attachement.textureDestroySlot.Disconnect(); - } - - InvalidateSize(); - - if (attachement.attachmentPoint == AttachmentPoint_Color) - InvalidateTargets(); - - Unlock(); - - m_checked = false; - } - - unsigned int RenderTexture::GetHeight() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - if (!m_sizeUpdated) - UpdateSize(); - - return m_impl->height; - } - - RenderTargetParameters RenderTexture::GetParameters() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - ///TODO - return RenderTargetParameters(); - } - - Vector2ui RenderTexture::GetSize() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - if (!m_sizeUpdated) - UpdateSize(); - - return Vector2ui(m_impl->width, m_impl->height); - } - - unsigned int RenderTexture::GetWidth() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - if (!m_sizeUpdated) - UpdateSize(); - - return m_impl->width; - } - - bool RenderTexture::IsComplete() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - if (!m_checked) - { - if (!Lock()) - { - NazaraError("Failed to lock render texture"); - return false; - } - - GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER); - Unlock(); - - m_impl->complete = false; - - switch (status) - { - case GL_FRAMEBUFFER_COMPLETE: - m_impl->complete = true; - break; - - case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - NazaraError("Incomplete attachment"); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: - NazaraInternalError("Incomplete draw buffer"); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: - NazaraInternalError("Incomplete read buffer"); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - NazaraError("Incomplete missing attachment"); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: - NazaraError("Incomplete multisample"); - break; - - case GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: - NazaraError("Incomplete layer targets"); - break; - - case GL_FRAMEBUFFER_UNSUPPORTED: - NazaraError("Render texture has unsupported attachments"); - break; - - default: - NazaraInternalError("Unknown error"); - } - - m_checked = true; - } - - return m_impl->complete; - } - - bool RenderTexture::IsRenderable() const - { - return IsComplete() && !m_impl->attachments.empty(); - } - - bool RenderTexture::Lock() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - #if NAZARA_RENDERER_SAFE - if (Context::GetCurrent() != m_impl->context) - { - NazaraError("RenderTexture cannot be used with this context"); - return false; - } - #endif - - if (lockedLevel++ == 0) - { - GLint previous; - glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &previous); - - lockedPrevious = previous; - - if (lockedPrevious != m_impl->fbo) - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_impl->fbo); - } - - return true; - } - - void RenderTexture::SetColorTargets(const UInt8* targets, unsigned int targetCount) const - { - NazaraAssert(m_impl, "Invalid render texture"); - - #if NAZARA_RENDERER_SAFE - for (unsigned int i = 0; i < targetCount; ++i) - { - unsigned int index = attachmentIndex[AttachmentPoint_Color] + targets[i]; - if (index >= m_impl->attachments.size() || !m_impl->attachments[index].isUsed) - { - NazaraError("Target " + String::Number(targets[i]) + " not attached"); - return; - } - } - #endif - - m_impl->colorTargets.resize(targetCount); - std::memcpy(&m_impl->colorTargets[0], targets, targetCount*sizeof(UInt8)); - - m_impl->userDefinedTargets = true; - InvalidateTargets(); - } - - void RenderTexture::SetColorTargets(const std::initializer_list& targets) const - { - NazaraAssert(m_impl, "Invalid render texture"); - - #if NAZARA_RENDERER_SAFE - for (UInt8 target : targets) - { - unsigned int index = attachmentIndex[AttachmentPoint_Color] + target; - if (index >= m_impl->attachments.size() || !m_impl->attachments[index].isUsed) - { - NazaraError("Target " + String::Number(target) + " not attached"); - return; - } - } - #endif - - m_impl->colorTargets.resize(targets.size()); - - UInt8* ptr = &m_impl->colorTargets[0]; - for (UInt8 index : targets) - *ptr++ = index; - - m_impl->userDefinedTargets = true; - InvalidateTargets(); - } - - void RenderTexture::Unlock() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - #if NAZARA_RENDERER_SAFE - if (Context::GetCurrent() != m_impl->context) - { - NazaraError("RenderTexture cannot be used with this context"); - return; - } - - if (lockedLevel == 0) - { - NazaraWarning("Unlock called on non-locked texture"); - return; - } - #endif - - if (--lockedLevel == 0 && lockedPrevious != m_impl->fbo) // Ici, il est important qu'un FBO soit débindé si l'ancien était 0 - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, lockedPrevious); - } - - unsigned int RenderTexture::GetOpenGLID() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - #if NAZARA_RENDERER_SAFE - if (Context::GetCurrent() != m_impl->context) - { - NazaraError("RenderTexture cannot be used with this context"); - return 0; - } - #endif - - return m_impl->fbo; - } - - bool RenderTexture::HasContext() const - { - return false; - } - - void RenderTexture::Blit(RenderTexture* src, Rectui srcRect, RenderTexture* dst, Rectui dstRect, UInt32 buffers, bool bilinearFilter) - { - NazaraAssert(src && src->IsValid(), "Invalid source render texture"); - NazaraAssert(dst && dst->IsValid(), "Invalid destination render texture"); - - #if NAZARA_RENDERER_SAFE - if (srcRect.x+srcRect.width > src->GetWidth() || srcRect.y+srcRect.height > src->GetHeight()) - { - NazaraError("Source rectangle dimensions are out of bounds"); - return; - } - - if (dstRect.x+dstRect.width > dst->GetWidth() || dstRect.y+dstRect.height > dst->GetHeight()) - { - NazaraError("Destination rectangle dimensions are out of bounds"); - return; - } - - if (bilinearFilter && (buffers & RendererBuffer_Depth || buffers & RendererBuffer_Stencil)) - { - NazaraError("Filter cannot be bilinear when blitting depth/stencil buffers"); - return; - } - #endif - - GLbitfield mask = 0; - if (buffers & RendererBuffer_Color) - mask |= GL_COLOR_BUFFER_BIT; - - if (buffers & RendererBuffer_Depth) - mask |= GL_DEPTH_BUFFER_BIT; - - if (buffers & RendererBuffer_Stencil) - mask |= GL_STENCIL_BUFFER_BIT; - - GLint previousDrawBuffer, previousReadBuffer; - glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &previousDrawBuffer); - glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &previousReadBuffer); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dst->GetOpenGLID()); - glBindFramebuffer(GL_READ_FRAMEBUFFER, src->GetOpenGLID()); - - glBlitFramebuffer(srcRect.x, srcRect.y, srcRect.x + srcRect.width, srcRect.y + srcRect.height, - dstRect.x, dstRect.y, dstRect.x + dstRect.width, dstRect.y + dstRect.height, - mask, (bilinearFilter) ? GL_LINEAR : GL_NEAREST); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, previousDrawBuffer); - glBindFramebuffer(GL_READ_FRAMEBUFFER, previousReadBuffer); - } - - bool RenderTexture::Activate() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - #if NAZARA_RENDERER_SAFE - if (Context::GetCurrent() != m_impl->context) - { - NazaraError("RenderTexture cannot be used with this context"); - return false; - } - #endif - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_impl->fbo); - - m_drawBuffersUpdated = false; - - return true; - } - - void RenderTexture::Desactivate() const - { - NazaraAssert(m_impl, "Invalid render texture"); - - #if NAZARA_RENDERER_SAFE - if (Context::GetCurrent() != m_impl->context) - { - NazaraError("RenderTexture cannot be used with this context"); - return; - } - #endif - - glFlush(); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - } - - void RenderTexture::EnsureTargetUpdated() const - { - if (!m_drawBuffersUpdated) - UpdateDrawBuffers(); - - for (UInt8 index : m_impl->colorTargets) - { - Attachment& attachment = m_impl->attachments[attachmentIndex[AttachmentPoint_Color] + index]; - if (!attachment.isBuffer) - attachment.texture->InvalidateMipmaps(); - } - } - - void RenderTexture::OnContextDestroy(const Context* context) - { - NazaraAssert(m_impl, "Invalid internal state"); - NazaraUnused(context); - - #ifdef NAZARA_DEBUG - if (m_impl->context != context) - { - NazaraInternalError("Not listening to " + String::Pointer(context)); - return; - } - #endif - - Destroy(); - } - - void RenderTexture::OnRenderBufferDestroy(const RenderBuffer* renderBuffer, unsigned int attachmentIndex) - { - NazaraAssert(m_impl, "Invalid internal state"); - NazaraAssert(attachmentIndex < m_impl->attachments.size(), "Invalid attachment index"); - NazaraAssert(m_impl->attachments[attachmentIndex].isBuffer, "Invalid attachment state"); - NazaraUnused(renderBuffer); - - Attachment& attachment = m_impl->attachments[attachmentIndex]; - attachment.buffer = nullptr; - attachment.isUsed = false; - attachment.renderBufferDestroySlot.Disconnect(); - - InvalidateTargets(); - } - - void RenderTexture::OnTextureDestroy(const Texture* texture, unsigned int attachmentIndex) - { - NazaraAssert(m_impl, "Invalid internal state"); - NazaraAssert(attachmentIndex < m_impl->attachments.size(), "Invalid attachment index"); - NazaraAssert(!m_impl->attachments[attachmentIndex].isBuffer, "Invalid attachment state"); - NazaraUnused(texture); - - InvalidateTargets(); - } - - void RenderTexture::UpdateDrawBuffers() const - { - if (!m_targetsUpdated) - UpdateTargets(); - - glDrawBuffers(m_impl->drawBuffers.size(), &m_impl->drawBuffers[0]); - - m_drawBuffersUpdated = true; - } - - void RenderTexture::UpdateSize() const - { - m_impl->width = 0; - m_impl->height = 0; - for (Attachment& attachment : m_impl->attachments) - { - if (attachment.isUsed) - { - m_impl->height = std::max(m_impl->height, attachment.height); - m_impl->width = std::max(m_impl->width, attachment.width); - } - } - - m_sizeUpdated = true; - } - - void RenderTexture::UpdateTargets() const - { - if (!m_impl->userDefinedTargets) - { - m_impl->colorTargets.clear(); - - unsigned int colorIndex = 0; - for (unsigned int index = attachmentIndex[AttachmentPoint_Color]; index < m_impl->attachments.size(); ++index) - m_impl->colorTargets.push_back(colorIndex++); - } - - if (m_impl->colorTargets.empty()) - { - m_impl->drawBuffers.resize(1); - m_impl->drawBuffers[0] = GL_NONE; - } - else - { - m_impl->drawBuffers.resize(m_impl->colorTargets.size()); - GLenum* ptr = &m_impl->drawBuffers[0]; - for (UInt8 index : m_impl->colorTargets) - *ptr++ = GL_COLOR_ATTACHMENT0 + index; - } - - m_targetsUpdated = true; - } -} diff --git a/src/Nazara/Renderer/RenderWindow.cpp b/src/Nazara/Renderer/RenderWindow.cpp index a9effa622..078c28f2b 100644 --- a/src/Nazara/Renderer/RenderWindow.cpp +++ b/src/Nazara/Renderer/RenderWindow.cpp @@ -1,7 +1,7 @@ // Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Engine - Renderer module" // For conditions of distribution and use, see copyright notice in Config.hpp - +/* #include #include #include @@ -289,3 +289,4 @@ namespace Nz OnRenderTargetSizeChange(this); } } +*/ \ No newline at end of file diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 028f7513f..74a50d481 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -4,580 +4,23 @@ #include #include -#include -#include -#include +#include +#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -///TODO: Manager les VAO (permettre plusieurs draw calls sans rebinder le VAO) - namespace Nz { - namespace - { - const UInt8 r_coreFragmentShader[] = { - #include - }; - - const UInt8 r_coreVertexShader[] = { - #include - }; - - enum ObjectType - { - ObjectType_Context, - ObjectType_IndexBuffer, - ObjectType_VertexBuffer, - ObjectType_VertexDeclaration - }; - - enum UpdateFlags - { - Update_None = 0, - - Update_Matrices = 0x1, - Update_Shader = 0x2, - Update_Textures = 0x4, - Update_VAO = 0x8 - }; - - struct MatrixUnit - { - Matrix4f matrix; - bool updated; - int location; - }; - - struct TextureUnit - { - TextureSampler sampler; - const Texture* texture = nullptr; - bool samplerUpdated = false; - }; - - struct VAO_Entry - { - GLuint vao; - - NazaraSlot(IndexBuffer, OnIndexBufferRelease, onIndexBufferReleaseSlot); - NazaraSlot(VertexBuffer, OnVertexBufferRelease, onVertexBufferReleaseSlot); - NazaraSlot(VertexDeclaration, OnVertexDeclarationRelease, onInstancingDeclarationReleaseSlot); - NazaraSlot(VertexDeclaration, OnVertexDeclarationRelease, onVertexDeclarationReleaseSlot); - }; - - using VAO_Key = std::tuple; - using VAO_Map = std::map; - - struct Context_Entry - { - VAO_Map vaoMap; - - NazaraSlot(Context, OnContextRelease, onReleaseSlot); - }; - - using Context_Map = std::unordered_map; - - Context_Map s_vaos; - std::vector s_dirtyTextureUnits; - std::vector s_textureUnits; - GLuint s_currentVAO = 0; - VertexBuffer s_instanceBuffer; - VertexBuffer s_fullscreenQuadBuffer; - MatrixUnit s_matrices[MatrixType_Max + 1]; - RenderStates s_states; - Vector2ui s_targetSize; - UInt8 s_maxAnisotropyLevel; - UInt32 s_updateFlags; - const IndexBuffer* s_indexBuffer; - const RenderTarget* s_target; - const Shader* s_shader; - const VertexBuffer* s_vertexBuffer; - bool s_capabilities[RendererCap_Max + 1]; - bool s_instancing; - unsigned int s_maxColorAttachments; - unsigned int s_maxRenderTarget; - unsigned int s_maxTextureSize; - unsigned int s_maxTextureUnit; - unsigned int s_maxVertexAttribs; - } - - void Renderer::BeginCondition(const GpuQuery& query, GpuQueryCondition condition) - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - glBeginConditionalRender(query.GetOpenGLID(), OpenGL::QueryCondition[condition]); - } - - void Renderer::Clear(UInt32 flags) - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - if (flags) - { - // On n'oublie pas de mettre à jour la cible - s_target->EnsureTargetUpdated(); - // Les états du rendu sont suceptibles d'influencer glClear - OpenGL::ApplyStates(s_states); - - GLenum mask = 0; - - if (flags & RendererBuffer_Color) - mask |= GL_COLOR_BUFFER_BIT; - - if (flags & RendererBuffer_Depth) - mask |= GL_DEPTH_BUFFER_BIT; - - if (flags & RendererBuffer_Stencil) - mask |= GL_STENCIL_BUFFER_BIT; - - glClear(mask); - } - } - - void Renderer::DrawFullscreenQuad() - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - EnableInstancing(false); - SetIndexBuffer(nullptr); - SetVertexBuffer(&s_fullscreenQuadBuffer); - - if (!EnsureStateUpdate()) - { - NazaraError("Failed to update states: " + Error::GetLastError()); - return; - } - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glBindVertexArray(0); - } - - void Renderer::DrawIndexedPrimitives(PrimitiveMode mode, unsigned int firstIndex, unsigned int indexCount) - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - - if (mode > PrimitiveMode_Max) - { - NazaraError("Primitive mode out of enum"); - return; - } - #endif - - #if NAZARA_RENDERER_SAFE - if (!s_indexBuffer) - { - NazaraError("No index buffer"); - return; - } - #endif - - EnableInstancing(false); - - if (!EnsureStateUpdate()) - { - NazaraError("Failed to update states: " + Error::GetLastError()); - return; - } - - GLenum type; - UInt8* offset = nullptr; - offset += s_indexBuffer->GetStartOffset(); - - if (s_indexBuffer->HasLargeIndices()) - { - offset += firstIndex*sizeof(UInt32); - type = GL_UNSIGNED_INT; - } - else - { - offset += firstIndex*sizeof(UInt16); - type = GL_UNSIGNED_SHORT; - } - - glDrawElements(OpenGL::PrimitiveMode[mode], indexCount, type, offset); - glBindVertexArray(0); - } - - void Renderer::DrawIndexedPrimitivesInstanced(unsigned int instanceCount, PrimitiveMode mode, unsigned int firstIndex, unsigned int indexCount) - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - - if (mode > PrimitiveMode_Max) - { - NazaraError("Primitive mode out of enum"); - return; - } - #endif - - #if NAZARA_RENDERER_SAFE - if (!s_indexBuffer) - { - NazaraError("No index buffer"); - return; - } - - if (instanceCount == 0) - { - NazaraError("Instance count must be over zero"); - return; - } - - unsigned int maxInstanceCount = s_instanceBuffer.GetVertexCount(); - if (instanceCount > maxInstanceCount) - { - NazaraError("Instance count is over maximum instance count (" + String::Number(instanceCount) + " >= " NazaraStringifyMacro(NAZARA_RENDERER_MAX_INSTANCES) ")"); - return; - } - #endif - - EnableInstancing(true); - - if (!EnsureStateUpdate()) - { - NazaraError("Failed to update states: " + Error::GetLastError()); - return; - } - - GLenum type; - UInt8* offset = nullptr; - offset += s_indexBuffer->GetStartOffset(); - - if (s_indexBuffer->HasLargeIndices()) - { - offset += firstIndex*sizeof(UInt32); - type = GL_UNSIGNED_INT; - } - else - { - offset += firstIndex*sizeof(UInt16); - type = GL_UNSIGNED_SHORT; - } - - glDrawElementsInstanced(OpenGL::PrimitiveMode[mode], indexCount, type, offset, instanceCount); - glBindVertexArray(0); - } - - void Renderer::DrawPrimitives(PrimitiveMode mode, unsigned int firstVertex, unsigned int vertexCount) - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - - if (mode > PrimitiveMode_Max) - { - NazaraError("Primitive mode out of enum"); - return; - } - #endif - - EnableInstancing(false); - - if (!EnsureStateUpdate()) - { - NazaraError("Failed to update states: " + Error::GetLastError()); - return; - } - - glDrawArrays(OpenGL::PrimitiveMode[mode], firstVertex, vertexCount); - glBindVertexArray(0); - } - - void Renderer::DrawPrimitivesInstanced(unsigned int instanceCount, PrimitiveMode mode, unsigned int firstVertex, unsigned int vertexCount) - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - - if (mode > PrimitiveMode_Max) - { - NazaraError("Primitive mode out of enum"); - return; - } - #endif - - #if NAZARA_RENDERER_SAFE - if (instanceCount == 0) - { - NazaraError("Instance count must be over zero"); - return; - } - - unsigned int maxInstanceCount = s_instanceBuffer.GetVertexCount(); - if (instanceCount > maxInstanceCount) - { - NazaraError("Instance count is over maximum instance count (" + String::Number(instanceCount) + " >= " NazaraStringifyMacro(NAZARA_RENDERER_MAX_INSTANCES) ")"); - return; - } - #endif - - EnableInstancing(true); - - if (!EnsureStateUpdate()) - { - NazaraError("Failed to update states: " + Error::GetLastError()); - return; - } - - glDrawArraysInstanced(OpenGL::PrimitiveMode[mode], firstVertex, vertexCount, instanceCount); - glBindVertexArray(0); - } - - void Renderer::Enable(RendererParameter parameter, bool enable) - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - - if (parameter > RendererParameter_Max) - { - NazaraError("Renderer parameter out of enum"); - return; - } - #endif - - switch (parameter) - { - case RendererParameter_Blend: - s_states.blending = enable; - return; - - case RendererParameter_ColorWrite: - s_states.colorWrite = enable; - return; - - case RendererParameter_DepthBuffer: - s_states.depthBuffer = enable; - return; - - case RendererParameter_DepthWrite: - s_states.depthWrite = enable; - return; - - case RendererParameter_FaceCulling: - s_states.faceCulling = enable; - return; - - case RendererParameter_ScissorTest: - s_states.scissorTest = enable; - return; - - case RendererParameter_StencilTest: - s_states.stencilTest = enable; - return; - } - - NazaraInternalError("Unhandled renderer parameter: 0x" + String::Number(parameter, 16)); - } - - void Renderer::EndCondition() - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - glEndConditionalRender(); - } - - void Renderer::Flush() - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - glFlush(); - } - - RendererComparison Renderer::GetDepthFunc() - { - return s_states.depthFunc; - } - - VertexBuffer* Renderer::GetInstanceBuffer() - { - s_updateFlags |= Update_VAO; - return &s_instanceBuffer; - } - - float Renderer::GetLineWidth() - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return 0.f; - } - #endif - - return s_states.lineWidth; - } - - Matrix4f Renderer::GetMatrix(MatrixType type) - { - #ifdef NAZARA_DEBUG - if (type > MatrixType_Max) - { - NazaraError("Matrix type out of enum"); - return Matrix4f(); - } - #endif - - if (!s_matrices[type].updated) - UpdateMatrix(type); - - return s_matrices[type].matrix; - } - - UInt8 Renderer::GetMaxAnisotropyLevel() - { - return s_maxAnisotropyLevel; - } - - unsigned int Renderer::GetMaxColorAttachments() - { - return s_maxColorAttachments; - } - - unsigned int Renderer::GetMaxRenderTargets() - { - return s_maxRenderTarget; - } - - unsigned int Renderer::GetMaxTextureSize() - { - return s_maxTextureSize; - } - - unsigned int Renderer::GetMaxTextureUnits() - { - return s_maxTextureUnit; - } - - unsigned int Renderer::GetMaxVertexAttribs() - { - return s_maxVertexAttribs; - } - - float Renderer::GetPointSize() - { - return s_states.pointSize; - } - - const RenderStates& Renderer::GetRenderStates() - { - return s_states; - } - - Recti Renderer::GetScissorRect() - { - return OpenGL::GetCurrentScissorBox(); - } - - const Shader* Renderer::GetShader() - { - return s_shader; - } - - const RenderTarget* Renderer::GetTarget() - { - return s_target; - } - - Recti Renderer::GetViewport() - { - return OpenGL::GetCurrentViewport(); - } - - bool Renderer::HasCapability(RendererCap capability) - { - #ifdef NAZARA_DEBUG - if (capability > RendererCap_Max) - { - NazaraError("Renderer capability out of enum"); - return false; - } - #endif - - return s_capabilities[capability]; - } - bool Renderer::Initialize() { if (s_moduleReferenceCounter > 0) { s_moduleReferenceCounter++; - return true; // Déjà initialisé + return true; // Already initialized } - // Initialisation des dépendances + // Initialize module dependencies if (!Utility::Initialize()) { NazaraError("Failed to initialize Utility module"); @@ -586,165 +29,62 @@ namespace Nz s_moduleReferenceCounter++; - // Initialisation du module CallOnExit onExit(Renderer::Uninitialize); - // Initialisation d'OpenGL - if (!OpenGL::Initialize()) // Initialise également Context + NazaraDebug("Searching for renderer implementation"); + + Directory dir("."); + dir.SetPattern("Nazara?*Renderer*" NAZARA_DYNLIB_EXTENSION); //< Ex: NazaraVulkanRenderer.dll + + if (!dir.Open()) { - NazaraError("Failed to initialize OpenGL"); + NazaraError("Failed to open directory"); return false; } - Buffer::SetBufferFactory(DataStorage_Hardware, [] (Buffer* parent, BufferType type) -> AbstractBuffer* + DynLib chosenLib; + std::unique_ptr chosenImpl; + while (dir.NextResult()) { - return new HardwareBuffer(parent, type); - }); + NazaraDebug("Trying to load " + dir.GetResultName()); - for (unsigned int i = 0; i <= MatrixType_Max; ++i) - { - MatrixUnit& unit = s_matrices[i]; - unit.location = -1; - unit.matrix.MakeIdentity(); - unit.updated = true; - } - - // Récupération des capacités d'OpenGL - s_capabilities[RendererCap_AnisotropicFilter] = OpenGL::IsSupported(OpenGLExtension_AnisotropicFilter); - s_capabilities[RendererCap_FP64] = OpenGL::IsSupported(OpenGLExtension_FP64); - s_capabilities[RendererCap_Instancing] = true; // Supporté par OpenGL 3.3 - - Context::EnsureContext(); - - if (s_capabilities[RendererCap_AnisotropicFilter]) - { - GLfloat maxAnisotropy; - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy); - - s_maxAnisotropyLevel = static_cast(maxAnisotropy); - } - else - s_maxAnisotropyLevel = 1; - - GLint maxColorAttachments; - glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxColorAttachments); - s_maxColorAttachments = static_cast(maxColorAttachments); - - GLint maxDrawBuffers; - glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); - s_maxRenderTarget = static_cast(maxDrawBuffers); - - GLint maxTextureUnits; - glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits); - s_maxTextureUnit = static_cast(maxTextureUnits); - - GLint maxTextureSize; - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize); - s_maxTextureSize = static_cast(maxTextureSize); - - GLint maxVertexAttribs; - glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs); - s_maxVertexAttribs = static_cast(maxVertexAttribs); - - s_states = RenderStates(); - - s_indexBuffer = nullptr; - s_shader = nullptr; - s_target = nullptr; - s_targetSize.Set(0U); - s_textureUnits.resize(s_maxTextureUnit); - s_updateFlags = Update_Matrices | Update_Shader | Update_VAO; - s_vertexBuffer = nullptr; - - s_fullscreenQuadBuffer.Reset(VertexDeclaration::Get(VertexLayout_XY_UV), 4, DataStorage_Hardware, BufferUsage_Static); - - float vertices[4 * 2 * 2] = - { - -1.f, -1.f, 0.f, 1.f, - 1.f, -1.f, 1.f, 1.f, - -1.f, 1.f, 0.f, 0.f, - 1.f, 1.f, 1.f, 0.f - }; - - if (!s_fullscreenQuadBuffer.Fill(vertices, 0, 4)) - { - NazaraError("Failed to fill fullscreen quad buffer"); - return false; - } - - if (s_capabilities[RendererCap_Instancing]) - { - try + DynLib implLib; + if (!implLib.Load(dir.GetResultPath())) { - ErrorFlags errFlags(ErrorFlag_ThrowException, true); - s_instanceBuffer.Reset(nullptr, NAZARA_RENDERER_INSTANCE_BUFFER_SIZE, DataStorage_Hardware, BufferUsage_Dynamic); + NazaraWarning("Failed to load " + dir.GetResultName() + ": " + implLib.GetLastError()); + continue; } - catch (const std::exception& e) - { - s_capabilities[RendererCap_Instancing] = false; - ErrorFlags flags(ErrorFlag_ThrowExceptionDisabled); - NazaraError("Failed to create instancing buffer: " + String(e.what())); + CreateRendererImplFunc createRenderer = reinterpret_cast(implLib.GetSymbol("NazaraRenderer_Instantiate")); + if (!createRenderer) + { + NazaraDebug("Skipped " + dir.GetResultName() + " (symbol not found)"); + continue; + } + + std::unique_ptr impl(createRenderer()); + if (!impl || !impl->Prepare(Nz::ParameterList())) + { + NazaraError("Failed to create renderer implementation"); + continue; + } + + NazaraDebug("Loaded " + impl->QueryAPIString()); + + if (!chosenImpl || impl->IsBetterThan(chosenImpl.get())) + { + if (chosenImpl) + NazaraDebug("Choose " + impl->QueryAPIString() + " over " + chosenImpl->QueryAPIString()); + + chosenLib = std::move(implLib); + chosenImpl = std::move(impl); } } - if (!RenderBuffer::Initialize()) - { - NazaraError("Failed to initialize render buffers"); - return false; - } + s_rendererImpl = std::move(chosenImpl); + s_rendererLib = std::move(chosenLib); - if (!Shader::Initialize()) - { - NazaraError("Failed to initialize shaders"); - return false; - } - - if (!Texture::Initialize()) - { - NazaraError("Failed to initialize textures"); - return false; - } - - if (!TextureSampler::Initialize()) - { - NazaraError("Failed to initialize texture samplers"); - return false; - } - - if (!UberShader::Initialize()) - { - NazaraError("Failed to initialize uber shaders"); - return false; - } - - // Création du shader de Debug - ShaderRef debugShader = Shader::New(); - if (!debugShader->Create()) - { - NazaraError("Failed to create debug shader"); - return false; - } - - if (!debugShader->AttachStageFromSource(ShaderStageType_Fragment, reinterpret_cast(r_coreFragmentShader), sizeof(r_coreFragmentShader))) - { - NazaraError("Failed to attach fragment stage"); - return false; - } - - if (!debugShader->AttachStageFromSource(ShaderStageType_Vertex, reinterpret_cast(r_coreVertexShader), sizeof(r_coreVertexShader))) - { - NazaraError("Failed to attach vertex stage"); - return false; - } - - if (!debugShader->Link()) - { - NazaraError("Failed to link shader"); - return false; - } - - ShaderLibrary::Register("DebugSimple", debugShader); + NazaraDebug("Using " + s_rendererImpl->QueryAPIString() + " as renderer"); onExit.Reset(); @@ -752,1252 +92,28 @@ namespace Nz return true; } - bool Renderer::IsComponentTypeSupported(ComponentType type) - { - switch (type) - { - case ComponentType_Color: - case ComponentType_Float1: - case ComponentType_Float2: - case ComponentType_Float3: - case ComponentType_Float4: - return true; // Supportés nativement - - case ComponentType_Double1: - case ComponentType_Double2: - case ComponentType_Double3: - case ComponentType_Double4: - return glVertexAttribLPointer != nullptr; // Fonction requise pour envoyer des doubles - - case ComponentType_Int1: - case ComponentType_Int2: - case ComponentType_Int3: - case ComponentType_Int4: - return glVertexAttribIPointer != nullptr; // Fonction requise pour envoyer des entiers - - case ComponentType_Quaternion: - return false; - } - - NazaraError("Attribute type not handled (0x" + String::Number(type, 16) + ')'); - return false; - } - - bool Renderer::IsEnabled(RendererParameter parameter) - { - #ifdef NAZARA_DEBUG - if (parameter > RendererParameter_Max) - { - NazaraError("Renderer parameter out of enum"); - return false; - } - #endif - - switch (parameter) - { - case RendererParameter_Blend: - return s_states.blending; - - case RendererParameter_ColorWrite: - return s_states.colorWrite; - - case RendererParameter_DepthBuffer: - return s_states.depthBuffer; - - case RendererParameter_DepthWrite: - return s_states.depthWrite; - - case RendererParameter_FaceCulling: - return s_states.faceCulling; - - case RendererParameter_ScissorTest: - return s_states.scissorTest; - - case RendererParameter_StencilTest: - return s_states.stencilTest; - } - - NazaraInternalError("Unhandled renderer parameter: 0x" + String::Number(parameter, 16)); - return false; - } - - bool Renderer::IsInitialized() - { - return s_moduleReferenceCounter != 0; - } - - void Renderer::SetBlendFunc(BlendFunc srcBlend, BlendFunc dstBlend) - { - #ifdef NAZARA_DEBUG - if (srcBlend > BlendFunc_Max) - { - NazaraError("Blend func out of enum"); - return; - } - - if (dstBlend > BlendFunc_Max) - { - NazaraError("Blend func out of enum"); - return; - } - #endif - - s_states.srcBlend = srcBlend; - s_states.dstBlend = dstBlend; - } - - void Renderer::SetClearColor(const Color& color) - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - glClearColor(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f); - } - - void Renderer::SetClearColor(UInt8 r, UInt8 g, UInt8 b, UInt8 a) - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - glClearColor(r / 255.f, g / 255.f, b / 255.f, a / 255.f); - } - - void Renderer::SetClearDepth(double depth) - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - glClearDepth(depth); - } - - void Renderer::SetClearStencil(unsigned int value) - { - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - glClearStencil(value); - } - - void Renderer::SetDepthFunc(RendererComparison compareFunc) - { - #ifdef NAZARA_DEBUG - if (compareFunc > RendererComparison_Max) - { - NazaraError("Renderer comparison out of enum"); - return; - } - #endif - - s_states.depthFunc = compareFunc; - } - - void Renderer::SetFaceCulling(FaceSide faceSide) - { - #ifdef NAZARA_DEBUG - if (faceSide > FaceSide_Max) - { - NazaraError("Face side out of enum"); - return; - } - #endif - - s_states.cullingSide = faceSide; - } - - void Renderer::SetFaceFilling(FaceFilling fillingMode) - { - #ifdef NAZARA_DEBUG - if (fillingMode > FaceFilling_Max) - { - NazaraError("Face filling out of enum"); - return; - } - #endif - - s_states.faceFilling = fillingMode; - } - - void Renderer::SetIndexBuffer(const IndexBuffer* indexBuffer) - { - #if NAZARA_RENDERER_SAFE - if (indexBuffer && !indexBuffer->IsHardware()) - { - NazaraError("Buffer must be hardware"); - return; - } - #endif - - if (s_indexBuffer != indexBuffer) - { - s_indexBuffer = indexBuffer; - s_updateFlags |= Update_VAO; - } - } - - void Renderer::SetLineWidth(float width) - { - #if NAZARA_RENDERER_SAFE - if (width <= 0.f) - { - NazaraError("Width must be over zero"); - return; - } - #endif - - s_states.lineWidth = width; - } - - void Renderer::SetMatrix(MatrixType type, const Matrix4f& matrix) - { - #ifdef NAZARA_DEBUG - if (type > MatrixType_Max) - { - NazaraError("Matrix type out of enum"); - return; - } - #endif - - s_matrices[type].matrix = matrix; - s_matrices[type].updated = true; - - // Invalidation des combinaisons - switch (type) - { - // Matrices de base - case MatrixType_Projection: - s_matrices[MatrixType_InvProjection].updated = false; - s_matrices[MatrixType_InvViewProj].updated = false; - s_matrices[MatrixType_InvWorldViewProj].updated = false; - s_matrices[MatrixType_ViewProj].updated = false; - s_matrices[MatrixType_WorldViewProj].updated = false; - break; - - case MatrixType_View: - s_matrices[MatrixType_InvView].updated = false; - s_matrices[MatrixType_InvViewProj].updated = false; - s_matrices[MatrixType_InvWorld].updated = false; - s_matrices[MatrixType_InvWorldViewProj].updated = false; - s_matrices[MatrixType_ViewProj].updated = false; - s_matrices[MatrixType_World].updated = false; - s_matrices[MatrixType_WorldViewProj].updated = false; - break; - - case MatrixType_World: - s_matrices[MatrixType_InvWorld].updated = false; - s_matrices[MatrixType_InvWorldView].updated = false; - s_matrices[MatrixType_InvWorldViewProj].updated = false; - s_matrices[MatrixType_WorldView].updated = false; - s_matrices[MatrixType_WorldViewProj].updated = false; - break; - - // Matrices combinées - case MatrixType_ViewProj: - s_matrices[MatrixType_InvViewProj].updated = false; - break; - - case MatrixType_WorldView: - s_matrices[MatrixType_InvWorldView].updated = false; - s_matrices[MatrixType_WorldViewProj].updated = false; - break; - - case MatrixType_WorldViewProj: - s_matrices[MatrixType_InvWorldViewProj].updated = false; - break; - - case MatrixType_InvProjection: - case MatrixType_InvView: - case MatrixType_InvViewProj: - case MatrixType_InvWorld: - case MatrixType_InvWorldView: - case MatrixType_InvWorldViewProj: - break; - } - - s_updateFlags |= Update_Matrices; - } - - void Renderer::SetPointSize(float size) - { - #if NAZARA_RENDERER_SAFE - if (size <= 0.f) - { - NazaraError("Size must be over zero"); - return; - } - #endif - - s_states.pointSize = size; - } - - void Renderer::SetRenderStates(const RenderStates& states) - { - s_states = states; - } - - void Renderer::SetScissorRect(const Recti& rect) - { - OpenGL::BindScissorBox(rect); - } - - void Renderer::SetShader(const Shader* shader) - { - #if NAZARA_RENDERER_SAFE - if (shader) - { - if (!shader->IsValid() || !shader->IsLinked()) - { - NazaraError("Invalid shader"); - return; - } - } - #endif - - if (s_shader != shader) - { - s_shader = shader; - s_updateFlags |= Update_Shader; - } - } - - void Renderer::SetStencilCompareFunction(RendererComparison compareFunc, FaceSide faceSide) - { - #ifdef NAZARA_DEBUG - if (compareFunc > RendererComparison_Max) - { - NazaraError("Renderer comparison out of enum"); - return; - } - - if (faceSide > FaceSide_Max) - { - NazaraError("Face side out of enum"); - return; - } - #endif - - switch (faceSide) - { - case FaceSide_Back: - s_states.stencilCompare.back = compareFunc; - break; - - case FaceSide_Front: - s_states.stencilCompare.front = compareFunc; - break; - - case FaceSide_FrontAndBack: - s_states.stencilCompare.back = compareFunc; - s_states.stencilCompare.front = compareFunc; - break; - } - } - - void Renderer::SetStencilFailOperation(StencilOperation failOperation, FaceSide faceSide) - { - #ifdef NAZARA_DEBUG - if (failOperation > StencilOperation_Max) - { - NazaraError("Stencil fail operation out of enum"); - return; - } - - if (faceSide > FaceSide_Max) - { - NazaraError("Face side out of enum"); - return; - } - #endif - - switch (faceSide) - { - case FaceSide_Back: - s_states.stencilFail.back = failOperation; - break; - - case FaceSide_Front: - s_states.stencilFail.front = failOperation; - break; - - case FaceSide_FrontAndBack: - s_states.stencilFail.back = failOperation; - s_states.stencilFail.front = failOperation; - break; - } - } - - void Renderer::SetStencilMask(UInt32 mask, FaceSide faceSide) - { - #ifdef NAZARA_DEBUG - if (faceSide > FaceSide_Max) - { - NazaraError("Face side out of enum"); - return; - } - #endif - - switch (faceSide) - { - case FaceSide_Back: - s_states.stencilWriteMask.back = mask; - break; - - case FaceSide_Front: - s_states.stencilWriteMask.front = mask; - break; - - case FaceSide_FrontAndBack: - s_states.stencilWriteMask.back = mask; - s_states.stencilWriteMask.front = mask; - break; - } - } - - void Renderer::SetStencilPassOperation(StencilOperation passOperation, FaceSide faceSide) - { - #ifdef NAZARA_DEBUG - if (passOperation > StencilOperation_Max) - { - NazaraError("Stencil pass operation out of enum"); - return; - } - - if (faceSide > FaceSide_Max) - { - NazaraError("Face side out of enum"); - return; - } - #endif - - switch (faceSide) - { - case FaceSide_Back: - s_states.stencilPass.back = passOperation; - break; - - case FaceSide_Front: - s_states.stencilPass.front = passOperation; - break; - - case FaceSide_FrontAndBack: - s_states.stencilPass.back = passOperation; - s_states.stencilPass.front = passOperation; - break; - } - } - - void Renderer::SetStencilReferenceValue(unsigned int refValue, FaceSide faceSide) - { - #ifdef NAZARA_DEBUG - if (faceSide > FaceSide_Max) - { - NazaraError("Face side out of enum"); - return; - } - #endif - - switch (faceSide) - { - case FaceSide_Back: - s_states.stencilReference.back = refValue; - break; - - case FaceSide_Front: - s_states.stencilReference.front = refValue; - break; - - case FaceSide_FrontAndBack: - s_states.stencilReference.back = refValue; - s_states.stencilReference.front = refValue; - break; - } - } - - void Renderer::SetStencilZFailOperation(StencilOperation zfailOperation, FaceSide faceSide) - { - #ifdef NAZARA_DEBUG - if (zfailOperation > StencilOperation_Max) - { - NazaraError("Stencil pass operation out of enum"); - return; - } - - if (faceSide > FaceSide_Max) - { - NazaraError("Face side out of enum"); - return; - } - #endif - - switch (faceSide) - { - case FaceSide_Back: - s_states.stencilDepthFail.back = zfailOperation; - break; - - case FaceSide_Front: - s_states.stencilDepthFail.front = zfailOperation; - break; - - case FaceSide_FrontAndBack: - s_states.stencilDepthFail.back = zfailOperation; - s_states.stencilDepthFail.front = zfailOperation; - break; - } - } - - bool Renderer::SetTarget(const RenderTarget* target) - { - if (s_target == target) - return true; - - if (s_target) - { - if (!s_target->HasContext()) - s_target->Desactivate(); - - s_target = nullptr; - } - - if (target) - { - #if NAZARA_RENDERER_SAFE - if (!target->IsRenderable()) - { - NazaraError("Target not renderable"); - return false; - } - #endif - - if (!target->Activate()) - { - NazaraError("Failed to activate target"); - return false; - } - - s_target = target; - } - - OpenGL::SetTarget(s_target); - - return true; - } - - void Renderer::SetTexture(UInt8 unit, const Texture* texture) - { - #if NAZARA_RENDERER_SAFE - if (unit >= s_maxTextureUnit) - { - NazaraError("Texture unit out of range (" + String::Number(unit) + " >= " + String::Number(s_maxTextureUnit) + ')'); - return; - } - #endif - - if (s_textureUnits[unit].texture != texture) - { - s_textureUnits[unit].texture = texture; - - if (texture) - { - if (s_textureUnits[unit].sampler.UseMipmaps(texture->HasMipmaps())) - s_textureUnits[unit].samplerUpdated = false; - } - - s_dirtyTextureUnits.push_back(unit); - s_updateFlags |= Update_Textures; - } - } - - void Renderer::SetTextureSampler(UInt8 unit, const TextureSampler& sampler) - { - #if NAZARA_RENDERER_SAFE - if (unit >= s_maxTextureUnit) - { - NazaraError("Texture unit out of range (" + String::Number(unit) + " >= " + String::Number(s_maxTextureUnit) + ')'); - return; - } - #endif - - s_textureUnits[unit].sampler = sampler; - s_textureUnits[unit].samplerUpdated = false; - - if (s_textureUnits[unit].texture) - s_textureUnits[unit].sampler.UseMipmaps(s_textureUnits[unit].texture->HasMipmaps()); - - s_dirtyTextureUnits.push_back(unit); - s_updateFlags |= Update_Textures; - } - - void Renderer::SetVertexBuffer(const VertexBuffer* vertexBuffer) - { - #if NAZARA_RENDERER_SAFE - if (vertexBuffer && !vertexBuffer->IsHardware()) - { - NazaraError("Buffer must be hardware"); - return; - } - #endif - - if (vertexBuffer && s_vertexBuffer != vertexBuffer) - { - s_vertexBuffer = vertexBuffer; - s_updateFlags |= Update_VAO; - } - } - - void Renderer::SetViewport(const Recti& viewport) - { - OpenGL::BindViewport(viewport); - } - void Renderer::Uninitialize() { if (s_moduleReferenceCounter != 1) { - // Le module est soit encore utilisé, soit pas initialisé + // Either the module is not initialized, either it was initialized multiple times if (s_moduleReferenceCounter > 1) s_moduleReferenceCounter--; return; } - // Libération du module s_moduleReferenceCounter = 0; - ShaderLibrary::Unregister("DebugSimple"); - - UberShader::Uninitialize(); - TextureSampler::Uninitialize(); - Texture::Uninitialize(); - Shader::Uninitialize(); - RenderBuffer::Uninitialize(); - DebugDrawer::Uninitialize(); - - s_textureUnits.clear(); - - // Libération des buffers - s_fullscreenQuadBuffer.Reset(); - s_instanceBuffer.Reset(); - - // Libération des VAOs - for (auto& pair : s_vaos) - { - const Context* context = pair.first; - const Context_Entry& contextEntry = pair.second; - - for (auto& pair2 : contextEntry.vaoMap) - { - const VAO_Entry& entry = pair2.second; - OpenGL::DeleteVertexArray(context, entry.vao); - } - } - s_vaos.clear(); - - OpenGL::Uninitialize(); + // Uninitialize module here NazaraNotice("Uninitialized: Renderer module"); - // Libération des dépendances + // Free module dependencies Utility::Uninitialize(); } - void Renderer::EnableInstancing(bool instancing) - { - if (s_instancing != instancing) - { - s_updateFlags |= Update_VAO; - s_instancing = instancing; - } - } - - bool Renderer::EnsureStateUpdate() - { - // Toutes les erreurs sont silencieuses car l'erreur est gérée par la fonction appelante - ErrorFlags flags(ErrorFlag_Silent | ErrorFlag_ThrowExceptionDisabled); - - #ifdef NAZARA_DEBUG - if (Context::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return false; - } - #endif - - #if NAZARA_RENDERER_SAFE - if (!s_shader) - { - NazaraError("No shader"); - return false; - } - - if (!s_target) - { - NazaraError("No target"); - return false; - } - #endif - - s_target->EnsureTargetUpdated(); - - s_shader->Bind(); // Active le programme si ce n'est pas déjà le cas - - // Si le programme a été changé depuis la dernière fois - if (s_updateFlags & Update_Shader) - { - // Récupération des indices des variables uniformes (-1 si la variable n'existe pas) - s_matrices[MatrixType_Projection].location = s_shader->GetUniformLocation(ShaderUniform_ProjMatrix); - s_matrices[MatrixType_View].location = s_shader->GetUniformLocation(ShaderUniform_ViewMatrix); - s_matrices[MatrixType_World].location = s_shader->GetUniformLocation(ShaderUniform_WorldMatrix); - - s_matrices[MatrixType_ViewProj].location = s_shader->GetUniformLocation(ShaderUniform_ViewProjMatrix); - s_matrices[MatrixType_WorldView].location = s_shader->GetUniformLocation(ShaderUniform_WorldViewMatrix); - s_matrices[MatrixType_WorldViewProj].location = s_shader->GetUniformLocation(ShaderUniform_WorldViewProjMatrix); - - s_matrices[MatrixType_InvProjection].location = s_shader->GetUniformLocation(ShaderUniform_InvProjMatrix); - s_matrices[MatrixType_InvView].location = s_shader->GetUniformLocation(ShaderUniform_InvViewMatrix); - s_matrices[MatrixType_InvViewProj].location = s_shader->GetUniformLocation(ShaderUniform_InvViewProjMatrix); - s_matrices[MatrixType_InvWorld].location = s_shader->GetUniformLocation(ShaderUniform_InvWorldMatrix); - s_matrices[MatrixType_InvWorldView].location = s_shader->GetUniformLocation(ShaderUniform_InvWorldViewMatrix); - s_matrices[MatrixType_InvWorldViewProj].location = s_shader->GetUniformLocation(ShaderUniform_InvWorldViewProjMatrix); - - s_targetSize.Set(0U); // On force l'envoi des uniformes - s_updateFlags |= Update_Matrices; // Changement de programme, on renvoie toutes les matrices demandées - - s_updateFlags &= ~Update_Shader; - } - - // Envoi des uniformes liées au Renderer - Vector2ui targetSize(s_target->GetWidth(), s_target->GetHeight()); - if (s_targetSize != targetSize) - { - int location; - - location = s_shader->GetUniformLocation(ShaderUniform_InvTargetSize); - if (location != -1) - s_shader->SendVector(location, 1.f / Vector2f(targetSize)); - - location = s_shader->GetUniformLocation(ShaderUniform_TargetSize); - if (location != -1) - s_shader->SendVector(location, Vector2f(targetSize)); - - s_targetSize.Set(targetSize); - } - - if (s_updateFlags != Update_None) - { - if (s_updateFlags & Update_Textures) - { - for (unsigned int i : s_dirtyTextureUnits) - { - TextureUnit& unit = s_textureUnits[i]; - - if (unit.texture && !unit.samplerUpdated) - { - unit.sampler.Bind(i); - unit.samplerUpdated = true; - } - } - - s_dirtyTextureUnits.clear(); // Ne change pas la capacité - s_updateFlags &= ~Update_Textures; - } - - if (s_updateFlags & Update_Matrices) - { - for (unsigned int i = 0; i <= MatrixType_Max; ++i) - { - MatrixUnit& unit = s_matrices[i]; - if (unit.location != -1) // On ne traite que les matrices existant dans le programme - { - if (!unit.updated) - UpdateMatrix(static_cast(i)); - - s_shader->SendMatrix(unit.location, unit.matrix); - } - } - - s_updateFlags &= ~Update_Matrices; - } - - if (s_updateFlags & Update_VAO) - { - #if NAZARA_RENDERER_SAFE - if (!s_vertexBuffer) - { - NazaraError("No vertex buffer"); - return false; - } - #endif - - // Note: Les VAOs ne sont pas partagés entre les contextes, nous avons donc un tableau de VAOs par contexte - const Context* context = Context::GetCurrent(); - - auto it = s_vaos.find(context); - if (it == s_vaos.end()) - { - Context_Entry entry; - entry.onReleaseSlot.Connect(context->OnContextRelease, OnContextRelease); - - it = s_vaos.insert(std::make_pair(context, std::move(entry))).first; - } - - VAO_Map& vaoMap = it->second.vaoMap; - - // Notre clé est composée de ce qui définit un VAO - const VertexDeclaration* vertexDeclaration = s_vertexBuffer->GetVertexDeclaration(); - const VertexDeclaration* instancingDeclaration = (s_instancing) ? s_instanceBuffer.GetVertexDeclaration() : nullptr; - VAO_Key key(s_indexBuffer, s_vertexBuffer, vertexDeclaration, instancingDeclaration); - - // On recherche un VAO existant avec notre configuration - auto vaoIt = vaoMap.find(key); - if (vaoIt == vaoMap.end()) - { - // On créé notre VAO - glGenVertexArrays(1, &s_currentVAO); - glBindVertexArray(s_currentVAO); - - // On l'ajoute à notre liste - VAO_Entry entry; - entry.vao = s_currentVAO; - - // Connect the slots - if (s_indexBuffer) - entry.onIndexBufferReleaseSlot.Connect(s_indexBuffer->OnIndexBufferRelease, OnIndexBufferRelease); - - if (instancingDeclaration) - entry.onInstancingDeclarationReleaseSlot.Connect(instancingDeclaration->OnVertexDeclarationRelease, OnVertexDeclarationRelease); - - entry.onVertexBufferReleaseSlot.Connect(s_vertexBuffer->OnVertexBufferRelease, OnVertexBufferRelease); - entry.onVertexDeclarationReleaseSlot.Connect(vertexDeclaration->OnVertexDeclarationRelease, OnVertexDeclarationRelease); - - vaoIt = vaoMap.insert(std::make_pair(key, std::move(entry))).first; - - // And begin to program it - bool updateFailed = false; - - // Pour éviter la duplication de code, on va utiliser une astuce via une boucle for - for (unsigned int i = 0; i < (s_instancing ? 2U : 1U); ++i) - { - // Selon l'itération nous choisissons un buffer différent - const VertexBuffer* vertexBuffer = (i == 0) ? s_vertexBuffer : &s_instanceBuffer; - - HardwareBuffer* vertexBufferImpl = static_cast(vertexBuffer->GetBuffer()->GetImpl()); - glBindBuffer(OpenGL::BufferTarget[BufferType_Vertex], vertexBufferImpl->GetOpenGLID()); - - unsigned int bufferOffset = vertexBuffer->GetStartOffset(); - vertexDeclaration = vertexBuffer->GetVertexDeclaration(); - unsigned int stride = vertexDeclaration->GetStride(); - - // On définit les bornes (une fois de plus selon l'itération) - unsigned int start = (i == 0) ? VertexComponent_FirstVertexData : VertexComponent_FirstInstanceData; - unsigned int end = (i == 0) ? VertexComponent_LastVertexData : VertexComponent_LastInstanceData; - for (unsigned int j = start; j <= end; ++j) - { - ComponentType type; - bool enabled; - std::size_t offset; - vertexDeclaration->GetComponent(static_cast(j), &enabled, &type, &offset); - - if (enabled) - { - if (!IsComponentTypeSupported(type)) - { - NazaraError("Invalid vertex declaration " + String::Pointer(vertexDeclaration) + ": Vertex component 0x" + String::Number(j, 16) + " (type: 0x" + String::Number(type, 16) + ") is not supported"); - updateFailed = true; - break; - } - - glEnableVertexAttribArray(OpenGL::VertexComponentIndex[j]); - - switch (type) - { - case ComponentType_Color: - { - glVertexAttribPointer(OpenGL::VertexComponentIndex[j], - Utility::ComponentCount[type], - OpenGL::ComponentType[type], - GL_TRUE, - stride, - reinterpret_cast(bufferOffset + offset)); - - break; - } - - case ComponentType_Double1: - case ComponentType_Double2: - case ComponentType_Double3: - case ComponentType_Double4: - { - glVertexAttribLPointer(OpenGL::VertexComponentIndex[j], - Utility::ComponentCount[type], - OpenGL::ComponentType[type], - stride, - reinterpret_cast(bufferOffset + offset)); - - break; - } - - case ComponentType_Float1: - case ComponentType_Float2: - case ComponentType_Float3: - case ComponentType_Float4: - { - glVertexAttribPointer(OpenGL::VertexComponentIndex[j], - Utility::ComponentCount[type], - OpenGL::ComponentType[type], - GL_FALSE, - stride, - reinterpret_cast(bufferOffset + offset)); - - break; - } - - case ComponentType_Int1: - case ComponentType_Int2: - case ComponentType_Int3: - case ComponentType_Int4: - { - glVertexAttribIPointer(OpenGL::VertexComponentIndex[j], - Utility::ComponentCount[type], - OpenGL::ComponentType[type], - stride, - reinterpret_cast(bufferOffset + offset)); - - break; - } - - default: - { - NazaraInternalError("Unsupported component type (0x" + String::Number(type, 16) + ')'); - break; - } - } - - // Les attributs d'instancing ont un diviseur spécifique (pour dépendre de l'instance en cours) - if (i == 1) - glVertexAttribDivisor(OpenGL::VertexComponentIndex[j], 1); - } - else - glDisableVertexAttribArray(OpenGL::VertexComponentIndex[j]); - } - } - - if (!s_instancing) - { - // Je ne sais pas si c'est vraiment nécessaire de désactiver les attributs, sur mon ordinateur ça ne pose aucun problème - // mais dans le doute, je laisse ça comme ça. - for (unsigned int i = VertexComponent_FirstInstanceData; i <= VertexComponent_LastInstanceData; ++i) - glDisableVertexAttribArray(OpenGL::VertexComponentIndex[i]); - } - - // Et on active l'index buffer (Un seul index buffer par VAO) - if (s_indexBuffer) - { - HardwareBuffer* indexBufferImpl = static_cast(s_indexBuffer->GetBuffer()->GetImpl()); - glBindBuffer(OpenGL::BufferTarget[BufferType_Index], indexBufferImpl->GetOpenGLID()); - } - else - glBindBuffer(OpenGL::BufferTarget[BufferType_Index], 0); - - // On invalide les bindings des buffers (car nous les avons défini manuellement) - OpenGL::SetBuffer(BufferType_Index, 0); - OpenGL::SetBuffer(BufferType_Vertex, 0); - - if (updateFailed) - { - // La création de notre VAO a échoué, libérons-le et marquons-le comme problématique - glDeleteVertexArrays(1, &vaoIt->second.vao); - vaoIt->second.vao = 0; - s_currentVAO = 0; - } - else - glBindVertexArray(0); // On marque la fin de la construction du VAO en le débindant - } - else - // Notre VAO existe déjà, il est donc inutile de le reprogrammer - s_currentVAO = vaoIt->second.vao; - - // En cas de non-support des VAOs, les attributs doivent être respécifiés à chaque frame - s_updateFlags &= ~Update_VAO; - } - - #ifdef NAZARA_DEBUG - if (s_updateFlags != Update_None && s_updateFlags != Update_VAO) - NazaraWarning("Update flags not fully cleared"); - #endif - } - - // On bind notre VAO - if (!s_currentVAO) - { - NazaraError("Failed to create VAO"); - return false; - } - - glBindVertexArray(s_currentVAO); - - // On vérifie que les textures actuellement bindées sont bien nos textures - // Ceci à cause du fait qu'il est possible que des opérations sur les textures aient eu lieu - // entre le dernier rendu et maintenant - for (unsigned int i = 0; i < s_maxTextureUnit; ++i) - { - const Texture* texture = s_textureUnits[i].texture; - if (texture) - { - OpenGL::BindTexture(i, texture->GetType(), texture->GetOpenGLID()); - texture->EnsureMipmapsUpdate(); - } - } - - // Et on termine par envoyer nos états au driver - OpenGL::ApplyStates(s_states); - - #ifdef NAZARA_DEBUG - if (!s_shader->Validate()) - { - NazaraError(Error::GetLastError()); - return false; - } - #endif - - return true; - } - - void Renderer::OnContextRelease(const Context* context) - { - s_vaos.erase(context); - } - - void Renderer::OnIndexBufferRelease(const IndexBuffer* indexBuffer) - { - for (auto& pair : s_vaos) - { - const Context* context = pair.first; - VAO_Map& vaos = pair.second.vaoMap; - - auto it = vaos.begin(); - while (it != vaos.end()) - { - const VAO_Key& key = it->first; - const IndexBuffer* vaoIndexBuffer = std::get<0>(key); - - if (vaoIndexBuffer == indexBuffer) - { - // Suppression du VAO: - // Comme celui-ci est local à son contexte de création, sa suppression n'est possible que si - // son contexte d'origine est actif, sinon il faudra le mettre en file d'attente - // Ceci est géré par la méthode OpenGL::DeleteVertexArray - - OpenGL::DeleteVertexArray(context, it->second.vao); - vaos.erase(it++); - } - else - ++it; - } - } - } - - void Renderer::OnShaderReleased(const Shader* shader) - { - if (s_shader == shader) - { - s_shader = nullptr; - s_updateFlags |= Update_Shader; - } - } - - void Renderer::OnTextureReleased(const Texture* texture) - { - for (TextureUnit& unit : s_textureUnits) - { - if (unit.texture == texture) - unit.texture = nullptr; - - // Inutile de changer le flag pour une texture désactivée - } - } - - void Renderer::OnVertexBufferRelease(const VertexBuffer* vertexBuffer) - { - for (auto& pair : s_vaos) - { - const Context* context = pair.first; - VAO_Map& vaos = pair.second.vaoMap; - - auto it = vaos.begin(); - while (it != vaos.end()) - { - const VAO_Key& key = it->first; - const VertexBuffer* vaoVertexBuffer = std::get<1>(key); - - if (vaoVertexBuffer == vertexBuffer) - { - // Suppression du VAO: - // Comme celui-ci est local à son contexte de création, sa suppression n'est possible que si - // son contexte d'origine est actif, sinon il faudra le mettre en file d'attente - // Ceci est géré par la méthode OpenGL::DeleteVertexArray - - OpenGL::DeleteVertexArray(context, it->second.vao); - vaos.erase(it++); - } - else - ++it; - } - } - } - - void Renderer::OnVertexDeclarationRelease(const VertexDeclaration* vertexDeclaration) - { - for (auto& pair : s_vaos) - { - const Context* context = pair.first; - VAO_Map& vaos = pair.second.vaoMap; - - auto it = vaos.begin(); - while (it != vaos.end()) - { - const VAO_Key& key = it->first; - const VertexDeclaration* vaoVertexDeclaration = std::get<2>(key); - const VertexDeclaration* vaoInstancingDeclaration = std::get<3>(key); - - if (vaoVertexDeclaration == vertexDeclaration || vaoInstancingDeclaration == vertexDeclaration) - { - // Suppression du VAO: - // Comme celui-ci est local à son contexte de création, sa suppression n'est possible que si - // son contexte d'origine est actif, sinon il faudra le mettre en file d'attente - // Ceci est géré par la méthode OpenGL::DeleteVertexArray - - OpenGL::DeleteVertexArray(context, it->second.vao); - vaos.erase(it++); - } - else - ++it; - } - } - } - - void Renderer::UpdateMatrix(MatrixType type) - { - #ifdef NAZARA_DEBUG - if (type > MatrixType_Max) - { - NazaraError("Matrix type out of enum"); - return; - } - #endif - - switch (type) - { - // Matrices de base - case MatrixType_Projection: - case MatrixType_View: - case MatrixType_World: - s_matrices[type].updated = true; - break; - - // Matrices combinées - case MatrixType_ViewProj: - s_matrices[MatrixType_ViewProj].matrix = s_matrices[MatrixType_View].matrix; - s_matrices[MatrixType_ViewProj].matrix.Concatenate(s_matrices[MatrixType_Projection].matrix); - s_matrices[MatrixType_ViewProj].updated = true; - break; - - case MatrixType_WorldView: - s_matrices[MatrixType_WorldView].matrix = s_matrices[MatrixType_World].matrix; - s_matrices[MatrixType_WorldView].matrix.ConcatenateAffine(s_matrices[MatrixType_View].matrix); - s_matrices[MatrixType_WorldView].updated = true; - break; - - case MatrixType_WorldViewProj: - if (!s_matrices[MatrixType_WorldView].updated) - UpdateMatrix(MatrixType_WorldView); - - s_matrices[MatrixType_WorldViewProj].matrix = s_matrices[MatrixType_WorldView].matrix; - s_matrices[MatrixType_WorldViewProj].matrix.Concatenate(s_matrices[MatrixType_Projection].matrix); - s_matrices[MatrixType_WorldViewProj].updated = true; - break; - - // Matrices inversées - case MatrixType_InvProjection: - if (!s_matrices[MatrixType_Projection].updated) - UpdateMatrix(MatrixType_Projection); - - if (!s_matrices[MatrixType_Projection].matrix.GetInverse(&s_matrices[MatrixType_InvProjection].matrix)) - NazaraWarning("Failed to inverse Proj matrix"); - - s_matrices[MatrixType_InvProjection].updated = true; - break; - - case MatrixType_InvView: - if (!s_matrices[MatrixType_View].updated) - UpdateMatrix(MatrixType_View); - - if (!s_matrices[MatrixType_View].matrix.GetInverse(&s_matrices[MatrixType_InvView].matrix)) - NazaraWarning("Failed to inverse View matrix"); - - s_matrices[MatrixType_InvView].updated = true; - break; - - case MatrixType_InvViewProj: - if (!s_matrices[MatrixType_ViewProj].updated) - UpdateMatrix(MatrixType_ViewProj); - - if (!s_matrices[MatrixType_ViewProj].matrix.GetInverse(&s_matrices[MatrixType_InvViewProj].matrix)) - NazaraWarning("Failed to inverse ViewProj matrix"); - - s_matrices[MatrixType_InvViewProj].updated = true; - break; - - case MatrixType_InvWorld: - if (!s_matrices[MatrixType_World].updated) - UpdateMatrix(MatrixType_World); - - if (!s_matrices[MatrixType_World].matrix.GetInverse(&s_matrices[MatrixType_InvWorld].matrix)) - NazaraWarning("Failed to inverse World matrix"); - - s_matrices[MatrixType_InvWorld].updated = true; - break; - - case MatrixType_InvWorldView: - if (!s_matrices[MatrixType_WorldView].updated) - UpdateMatrix(MatrixType_WorldView); - - if (!s_matrices[MatrixType_WorldView].matrix.GetInverse(&s_matrices[MatrixType_InvWorldView].matrix)) - NazaraWarning("Failed to inverse WorldView matrix"); - - s_matrices[MatrixType_InvWorldView].updated = true; - break; - - case MatrixType_InvWorldViewProj: - if (!s_matrices[MatrixType_WorldViewProj].updated) - UpdateMatrix(MatrixType_WorldViewProj); - - if (!s_matrices[MatrixType_WorldViewProj].matrix.GetInverse(&s_matrices[MatrixType_InvWorldViewProj].matrix)) - NazaraWarning("Failed to inverse WorldViewProj matrix"); - - s_matrices[MatrixType_InvWorldViewProj].updated = true; - break; - } - } - + DynLib Renderer::s_rendererLib; + std::unique_ptr Renderer::s_rendererImpl; unsigned int Renderer::s_moduleReferenceCounter = 0; } diff --git a/src/Nazara/Renderer/RendererImpl.cpp b/src/Nazara/Renderer/RendererImpl.cpp new file mode 100644 index 000000000..f674e1098 --- /dev/null +++ b/src/Nazara/Renderer/RendererImpl.cpp @@ -0,0 +1,11 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + RendererImpl::~RendererImpl() = default; +} diff --git a/src/Nazara/Renderer/Resources/Shaders/Debug/core.frag b/src/Nazara/Renderer/Resources/Shaders/Debug/core.frag deleted file mode 100644 index 4bb28b00c..000000000 --- a/src/Nazara/Renderer/Resources/Shaders/Debug/core.frag +++ /dev/null @@ -1,13 +0,0 @@ -#version 140 - -/********************Sortant********************/ -out vec4 RenderTarget0; - -/********************Uniformes********************/ -uniform vec4 Color; - -/********************Fonctions********************/ -void main() -{ - RenderTarget0 = Color; -} \ No newline at end of file diff --git a/src/Nazara/Renderer/Resources/Shaders/Debug/core.frag.h b/src/Nazara/Renderer/Resources/Shaders/Debug/core.frag.h deleted file mode 100644 index bbb324c3c..000000000 --- a/src/Nazara/Renderer/Resources/Shaders/Debug/core.frag.h +++ /dev/null @@ -1 +0,0 @@ -35,118,101,114,115,105,111,110,32,49,52,48,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,83,111,114,116,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,111,117,116,32,118,101,99,52,32,82,101,110,100,101,114,84,97,114,103,101,116,48,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,118,101,99,52,32,67,111,108,111,114,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,82,101,110,100,101,114,84,97,114,103,101,116,48,32,61,32,67,111,108,111,114,59,13,10,125, \ No newline at end of file diff --git a/src/Nazara/Renderer/Resources/Shaders/Debug/core.vert b/src/Nazara/Renderer/Resources/Shaders/Debug/core.vert deleted file mode 100644 index e7806ffdf..000000000 --- a/src/Nazara/Renderer/Resources/Shaders/Debug/core.vert +++ /dev/null @@ -1,13 +0,0 @@ -#version 140 - -/********************Entrant********************/ -in vec3 VertexPosition; - -/********************Uniformes********************/ -uniform mat4 WorldViewProjMatrix; - -/********************Fonctions********************/ -void main() -{ - gl_Position = WorldViewProjMatrix * vec4(VertexPosition, 1.0); -} diff --git a/src/Nazara/Renderer/Resources/Shaders/Debug/core.vert.h b/src/Nazara/Renderer/Resources/Shaders/Debug/core.vert.h deleted file mode 100644 index 48c552e2d..000000000 --- a/src/Nazara/Renderer/Resources/Shaders/Debug/core.vert.h +++ /dev/null @@ -1 +0,0 @@ -35,118,101,114,115,105,111,110,32,49,52,48,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,69,110,116,114,97,110,116,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,105,110,32,118,101,99,51,32,86,101,114,116,101,120,80,111,115,105,116,105,111,110,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,85,110,105,102,111,114,109,101,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,117,110,105,102,111,114,109,32,109,97,116,52,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,59,13,10,13,10,47,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,70,111,110,99,116,105,111,110,115,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,42,47,13,10,118,111,105,100,32,109,97,105,110,40,41,13,10,123,13,10,9,103,108,95,80,111,115,105,116,105,111,110,32,61,32,87,111,114,108,100,86,105,101,119,80,114,111,106,77,97,116,114,105,120,32,42,32,118,101,99,52,40,86,101,114,116,101,120,80,111,115,105,116,105,111,110,44,32,49,46,48,41,59,13,10,125,13,10, \ No newline at end of file diff --git a/src/Nazara/Renderer/Shader.cpp b/src/Nazara/Renderer/Shader.cpp deleted file mode 100644 index 65deb8b3b..000000000 --- a/src/Nazara/Renderer/Shader.cpp +++ /dev/null @@ -1,841 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - Shader::Shader() : - m_linked(false), - m_program(0) - { - } - - Shader::~Shader() - { - OnShaderRelease(this); - - Destroy(); - } - - void Shader::AttachStage(ShaderStageType stage, const ShaderStage& shaderStage) - { - #if NAZARA_RENDERER_SAFE - if (!m_program) - { - NazaraError("Invalid program"); - return; - } - - if (!shaderStage.IsValid()) - { - NazaraError("Invalid shader stage"); - return; - } - - if (!shaderStage.IsCompiled()) - { - NazaraError("Shader stage must be compiled"); - return; - } - #endif - - unsigned int shader = shaderStage.GetOpenGLID(); - - #if NAZARA_RENDERER_SAFE - if (std::find(m_attachedShaders[stage].begin(), m_attachedShaders[stage].end(), shader) != m_attachedShaders[stage].end()) - { - NazaraError("Shader stage is already attached"); - return; - } - #endif - - glAttachShader(m_program, shader); - m_attachedShaders[stage].push_back(shader); - } - - bool Shader::AttachStageFromFile(ShaderStageType stage, const String& filePath) - { - ShaderStage shaderStage(stage); - if (!shaderStage.IsValid()) - { - NazaraError("Failed to create shader stage"); - return false; - } - - shaderStage.SetSourceFromFile(filePath); - - if (!shaderStage.Compile()) - { - NazaraError("Failed to compile stage: " + shaderStage.GetLog()); - return false; - } - - AttachStage(stage, shaderStage); - return true; - } - - bool Shader::AttachStageFromSource(ShaderStageType stage, const char* source, unsigned int length) - { - ShaderStage shaderStage(stage); - if (!shaderStage.IsValid()) - { - NazaraError("Failed to create shader stage"); - return false; - } - - shaderStage.SetSource(source, length); - - if (!shaderStage.Compile()) - { - NazaraError("Failed to compile stage: " + shaderStage.GetLog()); - return false; - } - - AttachStage(stage, shaderStage); - return true; - } - - bool Shader::AttachStageFromSource(ShaderStageType stage, const String& source) - { - ShaderStage shaderStage(stage); - if (!shaderStage.IsValid()) - { - NazaraError("Failed to create shader stage"); - return false; - } - - shaderStage.SetSource(source); - - if (!shaderStage.Compile()) - { - NazaraError("Failed to compile stage: " + shaderStage.GetLog()); - return false; - } - - AttachStage(stage, shaderStage); - return true; - } - - void Shader::Bind() const - { - OpenGL::BindProgram(m_program); - } - - bool Shader::Create() - { - Context::EnsureContext(); - - m_program = glCreateProgram(); - if (!m_program) - { - NazaraError("Failed to create program"); - return false; - } - - m_linked = false; - - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_InstanceData0], "InstanceData0"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_InstanceData1], "InstanceData1"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_InstanceData2], "InstanceData2"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_InstanceData3], "InstanceData3"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_InstanceData4], "InstanceData4"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_InstanceData5], "InstanceData5"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_Color], "VertexColor"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_Normal], "VertexNormal"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_Position], "VertexPosition"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_Tangent], "VertexTangent"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_TexCoord], "VertexTexCoord"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_Userdata0], "VertexUserdata0"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_Userdata1], "VertexUserdata1"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_Userdata2], "VertexUserdata2"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_Userdata3], "VertexUserdata3"); - glBindAttribLocation(m_program, OpenGL::VertexComponentIndex[VertexComponent_Userdata4], "VertexUserdata4"); - - String uniform; - uniform = "RenderTarget"; - - unsigned int maxRenderTargets = Renderer::GetMaxRenderTargets(); - for (unsigned int i = 0; i < maxRenderTargets; ++i) - { - String uniformName = uniform + String::Number(i); - glBindFragDataLocation(m_program, i, uniformName.GetConstBuffer()); - } - - if (OpenGL::IsSupported(OpenGLExtension_GetProgramBinary)) - glProgramParameteri(m_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); - - return true; - } - - void Shader::Destroy() - { - if (m_program) - { - OnShaderDestroy(this); - - Context::EnsureContext(); - OpenGL::DeleteProgram(m_program); - m_program = 0; - } - } - - ByteArray Shader::GetBinary() const - { - ByteArray byteArray; - - Context::EnsureContext(); - - GLint binaryLength = 0; - glGetProgramiv(m_program, GL_PROGRAM_BINARY_LENGTH, &binaryLength); - - if (binaryLength > 0) - { - byteArray.Reserve(sizeof(UInt64) + binaryLength); - - UInt8* buffer = byteArray.GetBuffer(); - - GLenum binaryFormat; - glGetProgramBinary(m_program, binaryLength, nullptr, &binaryFormat, &buffer[sizeof(UInt64)]); - - // On stocke le format au début du binaire - *reinterpret_cast(&buffer[0]) = binaryFormat; - } - - return byteArray; - } - - String Shader::GetLog() const - { - #if NAZARA_RENDERER_SAFE - if (!m_program) - { - NazaraError("Shader is not initialized"); - return String(); - } - #endif - - String log; - - GLint length = 0; - glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &length); - if (length > 1) // Le caractère de fin faisant partie du compte - { - log.Set(length - 1, '\0'); // La taille retournée est celle du buffer (Avec caractère de fin) - glGetProgramInfoLog(m_program, length, nullptr, &log[0]); - } - else - log = "No log."; - - return log; - } - - String Shader::GetSourceCode(ShaderStageType stage) const - { - if (!HasStage(stage)) - return String(); - - Context::EnsureContext(); - - static const char sep[] = "\n////////////////////////////////////////////////////////////////////////////////\n\n"; - - unsigned int totalLength = 0; - for (unsigned int shader : m_attachedShaders[stage]) - { - GLint length; - glGetShaderiv(shader, GL_SHADER_SOURCE_LENGTH, &length); - - totalLength += length - 1; - } - - totalLength += (m_attachedShaders[stage].size()-1) * (sizeof(sep)/sizeof(char)); - - String source(totalLength, '\0'); - - unsigned int offset = 0; - for (unsigned int shader : m_attachedShaders[stage]) - { - if (offset > 0) - { - std::memcpy(&source[offset], sep, sizeof(sep)); - offset += sizeof(sep)/sizeof(char); - } - - GLint length; - glGetShaderSource(shader, totalLength, &length, &source[offset]); - - offset += length; - } - - return source; - } - - int Shader::GetUniformLocation(const String& name) const - { - Context::EnsureContext(); - - return glGetUniformLocation(m_program, name.GetConstBuffer()); - } - - int Shader::GetUniformLocation(ShaderUniform shaderUniform) const - { - return m_uniformLocations[shaderUniform]; - } - - bool Shader::HasStage(ShaderStageType stage) const - { - return !m_attachedShaders[stage].empty(); - } - - bool Shader::IsBinaryRetrievable() const - { - return OpenGL::IsSupported(OpenGLExtension_GetProgramBinary); - } - - bool Shader::IsLinked() const - { - return m_linked; - } - - bool Shader::IsValid() const - { - return m_program != 0; - } - - bool Shader::Link() - { - Context::EnsureContext(); - - glLinkProgram(m_program); - - return PostLinkage(); - } - - bool Shader::LoadFromBinary(const void* buffer, unsigned int size) - { - #if NAZARA_RENDERER_SAFE - if (!glProgramBinary) - { - NazaraError("GL_ARB_get_program_binary not supported"); - return false; - } - - if (!buffer || size < sizeof(UInt64)) - { - NazaraError("Invalid buffer"); - return false; - } - #endif - - Context::EnsureContext(); - - const UInt8* ptr = reinterpret_cast(buffer); - - // On récupère le format au début du binaire - ///TODO: ByteStream ? - GLenum binaryFormat = static_cast(*reinterpret_cast(&ptr[0])); - ptr += sizeof(UInt64); - - glProgramBinary(m_program, binaryFormat, ptr, size - sizeof(UInt64)); - - return PostLinkage(); - } - - bool Shader::LoadFromBinary(const ByteArray& byteArray) - { - return LoadFromBinary(byteArray.GetConstBuffer(), byteArray.GetSize()); - } - - void Shader::SendBoolean(int location, bool value) const - { - if (location == -1) - return; - - if (glProgramUniform1i) - glProgramUniform1i(m_program, location, value); - else - { - OpenGL::BindProgram(m_program); - glUniform1i(location, value); - } - } - - void Shader::SendColor(int location, const Color& color) const - { - if (location == -1) - return; - - Vector4f vecColor(color.r/255.f, color.g/255.f, color.b/255.f, color.a/255.f); - - if (glProgramUniform4fv) - glProgramUniform4fv(m_program, location, 1, vecColor); - else - { - OpenGL::BindProgram(m_program); - glUniform4fv(location, 1, vecColor); - } - } - - void Shader::SendDouble(int location, double value) const - { - if (location == -1) - return; - - if (glProgramUniform1d) - glProgramUniform1d(m_program, location, value); - else - { - OpenGL::BindProgram(m_program); - glUniform1d(location, value); - } - } - - void Shader::SendDoubleArray(int location, const double* values, unsigned int count) const - { - if (location == -1) - return; - - if (glProgramUniform1dv) - glProgramUniform1dv(m_program, location, count, values); - else - { - OpenGL::BindProgram(m_program); - glUniform1dv(location, count, values); - } - } - - void Shader::SendFloat(int location, float value) const - { - if (location == -1) - return; - - if (glProgramUniform1f) - glProgramUniform1f(m_program, location, value); - else - { - OpenGL::BindProgram(m_program); - glUniform1f(location, value); - } - } - - void Shader::SendFloatArray(int location, const float* values, unsigned int count) const - { - if (location == -1) - return; - - if (glProgramUniform1fv) - glProgramUniform1fv(m_program, location, count, values); - else - { - OpenGL::BindProgram(m_program); - glUniform1fv(location, count, values); - } - } - - void Shader::SendInteger(int location, int value) const - { - if (location == -1) - return; - - if (glProgramUniform1i) - glProgramUniform1i(m_program, location, value); - else - { - OpenGL::BindProgram(m_program); - glUniform1i(location, value); - } - } - - void Shader::SendIntegerArray(int location, const int* values, unsigned int count) const - { - if (location == -1) - return; - - if (glProgramUniform1iv) - glProgramUniform1iv(m_program, location, count, values); - else - { - OpenGL::BindProgram(m_program); - glUniform1iv(location, count, values); - } - } - - void Shader::SendMatrix(int location, const Matrix4d& matrix) const - { - if (location == -1) - return; - - if (glProgramUniformMatrix4dv) - glProgramUniformMatrix4dv(m_program, location, 1, GL_FALSE, matrix); - else - { - OpenGL::BindProgram(m_program); - glUniformMatrix4dv(location, 1, GL_FALSE, matrix); - } - } - - void Shader::SendMatrix(int location, const Matrix4f& matrix) const - { - if (location == -1) - return; - - if (glProgramUniformMatrix4fv) - glProgramUniformMatrix4fv(m_program, location, 1, GL_FALSE, matrix); - else - { - OpenGL::BindProgram(m_program); - glUniformMatrix4fv(location, 1, GL_FALSE, matrix); - } - } - - void Shader::SendVector(int location, const Vector2d& vector) const - { - if (location == -1) - return; - - if (glProgramUniform2dv) - glProgramUniform2dv(m_program, location, 1, vector); - else - { - OpenGL::BindProgram(m_program); - glUniform2dv(location, 1, vector); - } - } - - void Shader::SendVector(int location, const Vector2f& vector) const - { - if (location == -1) - return; - - if (glProgramUniform2fv) - glProgramUniform2fv(m_program, location, 1, vector); - else - { - OpenGL::BindProgram(m_program); - glUniform2fv(location, 1, vector); - } - } - - void Shader::SendVector(int location, const Vector2i& vector) const - { - if (location == -1) - return; - - if (glProgramUniform2fv) - glProgramUniform2iv(m_program, location, 1, vector); - else - { - OpenGL::BindProgram(m_program); - glUniform2iv(location, 1, vector); - } - } - - void Shader::SendVector(int location, const Vector3d& vector) const - { - if (location == -1) - return; - - if (glProgramUniform3dv) - glProgramUniform3dv(m_program, location, 1, vector); - else - { - OpenGL::BindProgram(m_program); - glUniform3dv(location, 1, vector); - } - } - - void Shader::SendVector(int location, const Vector3f& vector) const - { - if (location == -1) - return; - - if (glProgramUniform3fv) - glProgramUniform3fv(m_program, location, 1, vector); - else - { - OpenGL::BindProgram(m_program); - glUniform3fv(location, 1, vector); - } - } - - void Shader::SendVector(int location, const Vector3i& vector) const - { - if (location == -1) - return; - - if (glProgramUniform3iv) - glProgramUniform3iv(m_program, location, 1, vector); - else - { - OpenGL::BindProgram(m_program); - glUniform3iv(location, 1, vector); - } - } - - void Shader::SendVector(int location, const Vector4d& vector) const - { - if (location == -1) - return; - - if (glProgramUniform4dv) - glProgramUniform4dv(m_program, location, 1, vector); - else - { - OpenGL::BindProgram(m_program); - glUniform4dv(location, 1, vector); - } - } - - void Shader::SendVector(int location, const Vector4f& vector) const - { - if (location == -1) - return; - - if (glProgramUniform4fv) - glProgramUniform4fv(m_program, location, 1, vector); - else - { - OpenGL::BindProgram(m_program); - glUniform4fv(location, 1, vector); - } - } - - void Shader::SendVector(int location, const Vector4i& vector) const - { - if (location == -1) - return; - - if (glProgramUniform4iv) - glProgramUniform4iv(m_program, location, 1, vector); - else - { - OpenGL::BindProgram(m_program); - glUniform4iv(location, 1, vector); - } - } - - void Shader::SendVectorArray(int location, const Vector2d* vectors, unsigned int count) const - { - if (location == -1) - return; - - if (glProgramUniform2dv) - glProgramUniform2dv(m_program, location, count, reinterpret_cast(vectors)); - else - { - OpenGL::BindProgram(m_program); - glUniform2dv(location, count, reinterpret_cast(vectors)); - } - } - - void Shader::SendVectorArray(int location, const Vector2f* vectors, unsigned int count) const - { - if (location == -1) - return; - - if (glProgramUniform2fv) - glProgramUniform2fv(m_program, location, count, reinterpret_cast(vectors)); - else - { - OpenGL::BindProgram(m_program); - glUniform2fv(location, count, reinterpret_cast(vectors)); - } - } - - void Shader::SendVectorArray(int location, const Vector2i* vectors, unsigned int count) const - { - if (location == -1) - return; - - if (glProgramUniform2iv) - glProgramUniform2iv(m_program, location, count, reinterpret_cast(vectors)); - else - { - OpenGL::BindProgram(m_program); - glUniform2iv(location, count, reinterpret_cast(vectors)); - } - } - - void Shader::SendVectorArray(int location, const Vector3d* vectors, unsigned int count) const - { - if (location == -1) - return; - - if (glProgramUniform3dv) - glProgramUniform3dv(m_program, location, count, reinterpret_cast(vectors)); - else - { - OpenGL::BindProgram(m_program); - glUniform3dv(location, count, reinterpret_cast(vectors)); - } - } - - void Shader::SendVectorArray(int location, const Vector3f* vectors, unsigned int count) const - { - if (location == -1) - return; - - if (glProgramUniform3fv) - glProgramUniform3fv(m_program, location, count, reinterpret_cast(vectors)); - else - { - OpenGL::BindProgram(m_program); - glUniform3fv(location, count, reinterpret_cast(vectors)); - } - } - - void Shader::SendVectorArray(int location, const Vector3i* vectors, unsigned int count) const - { - if (location == -1) - return; - - if (glProgramUniform3iv) - glProgramUniform3iv(m_program, location, count, reinterpret_cast(vectors)); - else - { - OpenGL::BindProgram(m_program); - glUniform3iv(location, count, reinterpret_cast(vectors)); - } - } - - void Shader::SendVectorArray(int location, const Vector4d* vectors, unsigned int count) const - { - if (location == -1) - return; - - if (glProgramUniform4dv) - glProgramUniform4dv(m_program, location, count, reinterpret_cast(vectors)); - else - { - OpenGL::BindProgram(m_program); - glUniform4dv(location, count, reinterpret_cast(vectors)); - } - } - - void Shader::SendVectorArray(int location, const Vector4f* vectors, unsigned int count) const - { - if (location == -1) - return; - - if (glProgramUniform4fv) - glProgramUniform4fv(m_program, location, count, reinterpret_cast(vectors)); - else - { - OpenGL::BindProgram(m_program); - glUniform4fv(location, count, reinterpret_cast(vectors)); - } - } - - void Shader::SendVectorArray(int location, const Vector4i* vectors, unsigned int count) const - { - if (location == -1) - return; - - if (glProgramUniform4iv) - glProgramUniform4iv(m_program, location, count, reinterpret_cast(vectors)); - else - { - OpenGL::BindProgram(m_program); - glUniform4iv(location, count, reinterpret_cast(vectors)); - } - } - - bool Shader::Validate() const - { - #if NAZARA_RENDERER_SAFE - if (!m_program) - { - NazaraError("Shader is not initialized"); - return false; - } - #endif - - glValidateProgram(m_program); - - GLint success; - glGetProgramiv(m_program, GL_VALIDATE_STATUS, &success); - - if (success == GL_TRUE) - return true; - else - { - NazaraError("Failed to validate shader: " + GetLog()); - return false; - } - } - - - unsigned int Shader::GetOpenGLID() const - { - return m_program; - } - - bool Shader::IsStageSupported(ShaderStageType stage) - { - return ShaderStage::IsSupported(stage); - } - - bool Shader::PostLinkage() - { - GLint success; - glGetProgramiv(m_program, GL_LINK_STATUS, &success); - - m_linked = (success == GL_TRUE); - if (m_linked) - { - // Pour éviter de se tromper entre le nom et la constante - #define CacheUniform(name) m_uniformLocations[ShaderUniform_##name] = glGetUniformLocation(m_program, #name) - - CacheUniform(InvProjMatrix); - CacheUniform(InvTargetSize); - CacheUniform(InvViewMatrix); - CacheUniform(InvViewProjMatrix); - CacheUniform(InvWorldMatrix); - CacheUniform(InvWorldViewMatrix); - CacheUniform(InvWorldViewProjMatrix); - CacheUniform(ProjMatrix); - CacheUniform(TargetSize); - CacheUniform(ViewMatrix); - CacheUniform(ViewProjMatrix); - CacheUniform(WorldMatrix); - CacheUniform(WorldViewMatrix); - CacheUniform(WorldViewProjMatrix); - - #undef CacheUniform - - OnShaderUniformInvalidated(this); - - return true; - } - else - { - NazaraError("Failed to link shader: " + GetLog()); - return false; - } - } - - bool Shader::Initialize() - { - if (!ShaderLibrary::Initialize()) - { - NazaraError("Failed to initialise library"); - return false; - } - - return true; - } - - void Shader::Uninitialize() - { - ShaderLibrary::Uninitialize(); - } - - ShaderLibrary::LibraryMap Shader::s_library; -} diff --git a/src/Nazara/Renderer/ShaderStage.cpp b/src/Nazara/Renderer/ShaderStage.cpp deleted file mode 100644 index 771a2ced1..000000000 --- a/src/Nazara/Renderer/ShaderStage.cpp +++ /dev/null @@ -1,234 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include - -namespace Nz -{ - ShaderStage::ShaderStage() : - m_compiled(false), - m_id(0) - { - } - - ShaderStage::ShaderStage(ShaderStageType stage) : - ShaderStage() - { - Create(stage); - } - - ShaderStage::ShaderStage(ShaderStage&& stage) : - m_stage(stage.m_stage), - m_compiled(stage.m_compiled), - m_id(stage.m_id) - { - stage.m_id = 0; - } - - ShaderStage::~ShaderStage() - { - Destroy(); - } - - bool ShaderStage::Compile() - { - #if NAZARA_RENDERER_SAFE - if (!m_id) - { - NazaraError("Shader stage is not initialized"); - return false; - } - #endif - - glCompileShader(m_id); - - GLint success; - glGetShaderiv(m_id, GL_COMPILE_STATUS, &success); - - m_compiled = (success == GL_TRUE); - if (m_compiled) - return true; - else - { - NazaraError("Failed to compile shader stage: " + GetLog()); - return false; - } - } - - bool ShaderStage::Create(ShaderStageType stage) - { - Destroy(); - - m_id = glCreateShader(OpenGL::ShaderStage[stage]); - m_stage = stage; - - return (m_id != 0); - } - - void ShaderStage::Destroy() - { - m_compiled = false; - if (m_id) - { - glDeleteShader(m_id); - m_id = 0; - } - } - - String ShaderStage::GetLog() const - { - #if NAZARA_RENDERER_SAFE - if (!m_id) - { - NazaraError("Shader stage is not initialized"); - return String(); - } - #endif - - String log; - - GLint length = 0; - glGetShaderiv(m_id, GL_INFO_LOG_LENGTH, &length); - if (length > 1) // Le caractère de fin faisant partie du compte - { - log.Set(length - 1, '\0'); // La taille retournée est celle du buffer (Avec caractère de fin) - glGetShaderInfoLog(m_id, length, nullptr, &log[0]); - } - else - log = "No log."; - - return log; - } - - String ShaderStage::GetSource() const - { - #if NAZARA_RENDERER_SAFE - if (!m_id) - { - NazaraError("Shader stage is not initialized"); - return String(); - } - #endif - - String source; - - GLint length = 0; - glGetShaderiv(m_id, GL_SHADER_SOURCE_LENGTH, &length); - if (length > 1) // Le caractère de fin compte - { - source.Set(length - 1, '\0'); // La taille retournée est celle du buffer (Avec caractère de fin) - glGetShaderSource(m_id, length, nullptr, &source[0]); - } - - return source; - } - - bool ShaderStage::IsCompiled() const - { - return m_compiled; - } - - bool ShaderStage::IsValid() const - { - return m_id != 0; - } - - void ShaderStage::SetSource(const char* source, unsigned int length) - { - #if NAZARA_RENDERER_SAFE - if (!m_id) - { - NazaraError("Shader stage is not initialized"); - return; - } - #endif - - glShaderSource(m_id, 1, &source, reinterpret_cast(&length)); - } - - void ShaderStage::SetSource(const String& source) - { - #if NAZARA_RENDERER_SAFE - if (!m_id) - { - NazaraError("Shader stage is not initialized"); - return; - } - #endif - - const char* tmp = source.GetConstBuffer(); - GLint length = source.GetSize(); - glShaderSource(m_id, 1, &tmp, &length); - } - - bool ShaderStage::SetSourceFromFile(const String& filePath) - { - #if NAZARA_RENDERER_SAFE - if (!m_id) - { - NazaraError("Shader stage is not initialized"); - return false; - } - #endif - - File file(filePath); - if (!file.Open(OpenMode_ReadOnly | OpenMode_Text)) - { - NazaraError("Failed to open \"" + filePath + '"'); - return false; - } - - unsigned int length = static_cast(file.GetSize()); - - String source(length, '\0'); - - if (file.Read(&source[0], length) != length) - { - NazaraError("Failed to read program file"); - return false; - } - - file.Close(); - - SetSource(source); - return true; - } - - ShaderStage& ShaderStage::operator=(ShaderStage&& shader) - { - Destroy(); - - m_compiled = shader.m_compiled; - m_id = shader.m_id; - m_stage = shader.m_stage; - - shader.m_id = 0; - - return *this; - } - - // Fonctions OpenGL - unsigned int ShaderStage::GetOpenGLID() const - { - return m_id; - } - - bool ShaderStage::IsSupported(ShaderStageType stage) - { - switch (stage) - { - case ShaderStageType_Fragment: - case ShaderStageType_Geometry: - case ShaderStageType_Vertex: - return true; - - default: - NazaraError("Shader stage not handled (0x" + String::Number(stage, 16) + ')'); - return false; - } - } -} diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp deleted file mode 100644 index 458fb9992..000000000 --- a/src/Nazara/Renderer/Texture.cpp +++ /dev/null @@ -1,1347 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - struct TextureImpl - { - GLuint id; - ImageType type; - PixelFormatType format; - UInt8 levelCount; - bool mipmapping = false; - bool mipmapsUpdated = true; - unsigned int depth; - unsigned int height; - unsigned int width; - }; - - namespace - { - inline unsigned int GetLevelSize(unsigned int size, UInt8 level) - { - // Contrairement à la classe Image, un appel à GetLevelSize(0, level) n'est pas possible - return std::max(size >> level, 1U); - } - - inline void SetUnpackAlignement(UInt8 bpp) - { - if (bpp % 8 == 0) - glPixelStorei(GL_UNPACK_ALIGNMENT, 8); - else if (bpp % 4 == 0) - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - else if (bpp % 2 == 0) - glPixelStorei(GL_UNPACK_ALIGNMENT, 2); - else - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - } - } - - Texture::Texture(ImageType type, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth, UInt8 levelCount) - { - ErrorFlags flags(ErrorFlag_ThrowException); - Create(type, format, width, height, depth, levelCount); - } - - Texture::Texture(const Image& image) - { - ErrorFlags flags(ErrorFlag_ThrowException); - LoadFromImage(image); - } - - Texture::~Texture() - { - OnTextureRelease(this); - - Destroy(); - Renderer::OnTextureReleased(this); ///TODO: Gets rid of this - } - - bool Texture::Create(ImageType type, PixelFormatType format, unsigned int width, unsigned int height, unsigned int depth, UInt8 levelCount) - { - Destroy(); - - #if NAZARA_RENDERER_SAFE - if (!IsTypeSupported(type)) - { - NazaraError("Texture's type not supported"); - return false; - } - - if (!PixelFormat::IsValid(format)) - { - NazaraError("Invalid pixel format"); - return false; - } - - if (!IsFormatSupported(format)) - { - NazaraError("Texture's format not supported"); - return false; - } - - if (width == 0) - { - NazaraError("Width must be at least 1 (0)"); - return false; - } - - if (height == 0) - { - NazaraError("Height must be at least 1 (0)"); - return false; - } - - if (depth == 0) - { - NazaraError("Depth must be at least 1 (0)"); - return false; - } - - switch (type) - { - case ImageType_1D: - if (height > 1) - { - NazaraError("One dimensional texture's height must be 1"); - return false; - } - - if (depth > 1) - { - NazaraError("1D textures must be 1 deep"); - return false; - } - break; - - case ImageType_1D_Array: - case ImageType_2D: - if (depth > 1) - { - NazaraError("2D textures must be 1 deep"); - return false; - } - break; - - case ImageType_2D_Array: - case ImageType_3D: - break; - - case ImageType_Cubemap: - if (depth > 1) - { - NazaraError("Cubemaps must be 1 deep"); - return false; - } - - if (width != height) - { - NazaraError("Cubemaps must have square dimensions"); - return false; - } - break; - } - #endif - - Context::EnsureContext(); - - if (IsMipmappingSupported()) - levelCount = std::min(levelCount, Image::GetMaxLevel(width, height, depth)); - else if (levelCount > 1) - { - NazaraWarning("Mipmapping not supported, reducing level count to 1"); - levelCount = 1; - } - - m_impl = new TextureImpl; - m_impl->depth = depth; - m_impl->format = format; - m_impl->height = height; - m_impl->levelCount = levelCount; - m_impl->type = type; - m_impl->width = width; - - glGenTextures(1, &m_impl->id); - OpenGL::BindTexture(m_impl->type, m_impl->id); - - // En cas d'erreur (sortie prématurée), on détruit la texture - CallOnExit onExit([this]() - { - Destroy(); - }); - - // On précise le nombre de mipmaps avant la spécification de la texture - // https://www.opengl.org/wiki/Hardware_specifics:_NVidia - SetMipmapRange(0, m_impl->levelCount-1); - if (m_impl->levelCount > 1U) - EnableMipmapping(true); - - // Vérification du support par la carte graphique (texture proxy) - if (!CreateTexture(true)) - { - NazaraError("Texture's parameters not supported by driver"); - return false; - } - - // Création de la texture - if (!CreateTexture(false)) - { - NazaraError("Failed to create texture"); - return false; - } - - onExit.Reset(); - return true; - } - - void Texture::Destroy() - { - if (m_impl) - { - OnTextureDestroy(this); - - Context::EnsureContext(); - OpenGL::DeleteTexture(m_impl->id); - - delete m_impl; - m_impl = nullptr; - } - } - - bool Texture::Download(Image* image) const - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return false; - } - - if (!image) - { - NazaraError("Image must be valid"); - return false; - } - #endif - - OpenGL::Format format; - if (!OpenGL::TranslateFormat(m_impl->format, &format, OpenGL::FormatType_Texture)) - { - NazaraError("Failed to get OpenGL format"); - return false; - } - - if (!image->Create(m_impl->type, m_impl->format, m_impl->width, m_impl->height, m_impl->depth, m_impl->levelCount)) - { - NazaraError("Failed to create image"); - return false; - } - - // Téléchargement... - OpenGL::BindTexture(m_impl->type, m_impl->id); - for (UInt8 level = 0; level < m_impl->levelCount; ++level) - glGetTexImage(OpenGL::TextureTarget[m_impl->type], level, format.dataFormat, format.dataType, image->GetPixels(0, 0, 0, level)); - - return true; - } - - bool Texture::EnableMipmapping(bool enable) - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return false; - } - #endif - - if (!IsMipmappingSupported()) - { - NazaraError("Mipmapping not supported"); - return false; - } - - if (m_impl->levelCount == 1) // Transformation d'une texture sans mipmaps vers une texture avec mipmaps - { - ///FIXME: Est-ce que cette opération est seulement possible ? - m_impl->levelCount = Image::GetMaxLevel(m_impl->width, m_impl->height, m_impl->depth); - SetMipmapRange(0, m_impl->levelCount-1); - } - - if (!m_impl->mipmapping && enable) - m_impl->mipmapsUpdated = false; - - m_impl->mipmapping = enable; - - return true; - } - - void Texture::EnsureMipmapsUpdate() const - { - if (m_impl->mipmapping && !m_impl->mipmapsUpdated) - { - OpenGL::BindTexture(m_impl->type, m_impl->id); - glGenerateMipmap(OpenGL::TextureTarget[m_impl->type]); - m_impl->mipmapsUpdated = true; - } - } - - unsigned int Texture::GetDepth(UInt8 level) const - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return 0; - } - #endif - - return GetLevelSize(m_impl->depth, level); - } - - PixelFormatType Texture::GetFormat() const - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return PixelFormatType_Undefined; - } - #endif - - return m_impl->format; - } - - unsigned int Texture::GetHeight(UInt8 level) const - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return 0; - } - #endif - - return GetLevelSize(m_impl->height, level); - } - - UInt8 Texture::GetLevelCount() const - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return 0; - } - #endif - - return m_impl->levelCount; - } - - UInt8 Texture::GetMaxLevel() const - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return 0; - } - #endif - - return Image::GetMaxLevel(m_impl->type, m_impl->width, m_impl->height, m_impl->depth); - } - - std::size_t Texture::GetMemoryUsage() const - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return 0; - } - #endif - - unsigned int width = m_impl->width; - unsigned int height = m_impl->height; - unsigned int depth = m_impl->depth; - - unsigned int size = 0; - for (unsigned int i = 0; i < m_impl->levelCount; ++i) - { - size += width * height * depth; - - if (width > 1) - width >>= 1; - - if (height > 1) - height >>= 1; - - if (depth > 1) - depth >>= 1; - } - - if (m_impl->type == ImageType_Cubemap) - size *= 6; - - return size * PixelFormat::GetBytesPerPixel(m_impl->format); - } - - std::size_t Texture::GetMemoryUsage(UInt8 level) const - { - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return 0; - } - - if (level >= m_impl->levelCount) - { - NazaraError("Level out of bounds (" + String::Number(level) + " >= " + String::Number(m_impl->levelCount) + ')'); - return 0; - } - #endif - - return (GetLevelSize(m_impl->width, level)) * - (GetLevelSize(m_impl->height, level)) * - ((m_impl->type == ImageType_Cubemap) ? 6 : GetLevelSize(m_impl->depth, level)) * - PixelFormat::GetBytesPerPixel(m_impl->format); - } - - Vector3ui Texture::GetSize(UInt8 level) const - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return Vector3ui(0, 0, 0); - } - #endif - - return Vector3ui(GetLevelSize(m_impl->width, level), GetLevelSize(m_impl->height, level), GetLevelSize(m_impl->depth, level)); - } - - ImageType Texture::GetType() const - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return ImageType_2D; - } - #endif - - return m_impl->type; - } - - unsigned int Texture::GetWidth(UInt8 level) const - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return 0; - } - #endif - - return GetLevelSize(m_impl->width, level); - } - - bool Texture::HasMipmaps() const - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return false; - } - #endif - - return m_impl->levelCount > 1; - } - - void Texture::InvalidateMipmaps() - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraInternalError("Texture must be valid"); - return; - } - #endif - - m_impl->mipmapsUpdated = false; - } - - bool Texture::IsValid() const - { - return m_impl != nullptr; - } - - bool Texture::LoadFromFile(const String& filePath, const ImageParams& params, bool generateMipmaps) - { - Image image; - if (!image.LoadFromFile(filePath, params)) - { - NazaraError("Failed to load image"); - return false; - } - - return LoadFromImage(image, generateMipmaps); - } - - bool Texture::LoadFromImage(const Image& image, bool generateMipmaps) - { - #if NAZARA_RENDERER_SAFE - if (!image.IsValid()) - { - NazaraError("Image must be valid"); - return false; - } - #endif - - // Vive le Copy-On-Write - Image newImage(image); - - PixelFormatType format = newImage.GetFormat(); - if (!IsFormatSupported(format)) - { - ///TODO: Sélectionner le format le plus adapté selon les composantes présentes dans le premier format - PixelFormatType newFormat = (PixelFormat::HasAlpha(format)) ? PixelFormatType_BGRA8 : PixelFormatType_BGR8; - NazaraWarning("Format " + PixelFormat::GetName(format) + " not supported, trying to convert it to " + PixelFormat::GetName(newFormat) + "..."); - - if (PixelFormat::IsConversionSupported(format, newFormat)) - { - if (newImage.Convert(newFormat)) - { - NazaraWarning("Conversion succeed"); - format = newFormat; - } - else - { - NazaraError("Conversion failed"); - return false; - } - } - else - { - NazaraError("Conversion not supported"); - return false; - } - } - - ImageType type = newImage.GetType(); - UInt8 levelCount = newImage.GetLevelCount(); - if (!Create(type, format, newImage.GetWidth(), newImage.GetHeight(), newImage.GetDepth(), (generateMipmaps) ? 0xFF : levelCount)) - { - NazaraError("Failed to create texture"); - return false; - } - - CallOnExit destroyOnExit([this]() - { - Destroy(); - }); - - if (type == ImageType_Cubemap) - { - for (UInt8 level = 0; level < levelCount; ++level) - { - for (unsigned int i = 0; i <= CubemapFace_Max; ++i) - { - if (!Update(newImage.GetConstPixels(0, 0, i, level), Rectui(0, 0, newImage.GetWidth(level), newImage.GetHeight(level)), i, level)) - { - NazaraError("Failed to update texture"); - return false; - } - } - } - } - else - { - for (UInt8 level = 0; level < levelCount; ++level) - { - if (!Update(newImage.GetConstPixels(0, 0, 0, level), level)) - { - NazaraError("Failed to update texture"); - return false; - } - } - } - - // Keep resource path info - SetFilePath(image.GetFilePath()); - - destroyOnExit.Reset(); - - return true; - } - - bool Texture::LoadFromMemory(const void* data, std::size_t size, const ImageParams& params, bool generateMipmaps) - { - Image image; - if (!image.LoadFromMemory(data, size, params)) - { - NazaraError("Failed to load image"); - return false; - } - - return LoadFromImage(image, generateMipmaps); - } - - bool Texture::LoadFromStream(Stream& stream, const ImageParams& params, bool generateMipmaps) - { - Image image; - if (!image.LoadFromStream(stream, params)) - { - NazaraError("Failed to load image"); - return false; - } - - return LoadFromImage(image, generateMipmaps); - } - - bool Texture::LoadArrayFromFile(const String& filePath, const ImageParams& imageParams, bool generateMipmaps, const Vector2ui& atlasSize) - { - Image cubemap; - if (!cubemap.LoadArrayFromFile(filePath, imageParams, atlasSize)) - { - NazaraError("Failed to load cubemap"); - return false; - } - - return LoadFromImage(cubemap, generateMipmaps); - } - - bool Texture::LoadArrayFromImage(const Image& image, bool generateMipmaps, const Vector2ui& atlasSize) - { - Image cubemap; - if (!cubemap.LoadArrayFromImage(image, atlasSize)) - { - NazaraError("Failed to load cubemap"); - return false; - } - - return LoadFromImage(cubemap, generateMipmaps); - } - - bool Texture::LoadArrayFromMemory(const void* data, std::size_t size, const ImageParams& imageParams, bool generateMipmaps, const Vector2ui& atlasSize) - { - Image cubemap; - if (!cubemap.LoadArrayFromMemory(data, size, imageParams, atlasSize)) - { - NazaraError("Failed to load cubemap"); - return false; - } - - return LoadFromImage(cubemap, generateMipmaps); - } - - bool Texture::LoadArrayFromStream(Stream& stream, const ImageParams& imageParams, bool generateMipmaps, const Vector2ui& atlasSize) - { - Image cubemap; - if (!cubemap.LoadArrayFromStream(stream, imageParams, atlasSize)) - { - NazaraError("Failed to load cubemap"); - return false; - } - - return LoadFromImage(cubemap, generateMipmaps); - } - - bool Texture::LoadCubemapFromFile(const String& filePath, const ImageParams& imageParams, bool generateMipmaps, const CubemapParams& cubemapParams) - { - Image cubemap; - if (!cubemap.LoadCubemapFromFile(filePath, imageParams, cubemapParams)) - { - NazaraError("Failed to load cubemap"); - return false; - } - - return LoadFromImage(cubemap, generateMipmaps); - } - - bool Texture::LoadCubemapFromImage(const Image& image, bool generateMipmaps, const CubemapParams& params) - { - Image cubemap; - if (!cubemap.LoadCubemapFromImage(image, params)) - { - NazaraError("Failed to load cubemap"); - return false; - } - - return LoadFromImage(cubemap, generateMipmaps); - } - - bool Texture::LoadCubemapFromMemory(const void* data, std::size_t size, const ImageParams& imageParams, bool generateMipmaps, const CubemapParams& cubemapParams) - { - Image cubemap; - if (!cubemap.LoadCubemapFromMemory(data, size, imageParams, cubemapParams)) - { - NazaraError("Failed to load cubemap"); - return false; - } - - return LoadFromImage(cubemap, generateMipmaps); - } - - bool Texture::LoadCubemapFromStream(Stream& stream, const ImageParams& imageParams, bool generateMipmaps, const CubemapParams& cubemapParams) - { - Image cubemap; - if (!cubemap.LoadCubemapFromStream(stream, imageParams, cubemapParams)) - { - NazaraError("Failed to load cubemap"); - return false; - } - - return LoadFromImage(cubemap, generateMipmaps); - } - - bool Texture::LoadFaceFromFile(CubemapFace face, const String& filePath, const ImageParams& params) - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return false; - } - - if (m_impl->type != ImageType_Cubemap) - { - NazaraError("Texture must be a cubemap"); - return false; - } - #endif - - Image image; - if (!image.LoadFromFile(filePath, params)) - { - NazaraError("Failed to load image"); - return false; - } - - if (!image.Convert(m_impl->format)) - { - NazaraError("Failed to convert image to texture format"); - return false; - } - - unsigned int faceSize = m_impl->width; - if (image.GetWidth() != faceSize || image.GetHeight() != faceSize) - { - NazaraError("Image size must match texture face size"); - return false; - } - - return Update(image, Rectui(0, 0, faceSize, faceSize), face); - } - - bool Texture::LoadFaceFromMemory(CubemapFace face, const void* data, std::size_t size, const ImageParams& params) - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return false; - } - - if (m_impl->type != ImageType_Cubemap) - { - NazaraError("Texture must be a cubemap"); - return false; - } - #endif - - Image image; - if (!image.LoadFromMemory(data, size, params)) - { - NazaraError("Failed to load image"); - return false; - } - - if (!image.Convert(m_impl->format)) - { - NazaraError("Failed to convert image to texture format"); - return false; - } - - unsigned int faceSize = m_impl->width; - if (image.GetWidth() != faceSize || image.GetHeight() != faceSize) - { - NazaraError("Image size must match texture face size"); - return false; - } - - return Update(image, Rectui(0, 0, faceSize, faceSize), face); - } - - bool Texture::LoadFaceFromStream(CubemapFace face, Stream& stream, const ImageParams& params) - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return false; - } - - if (m_impl->type != ImageType_Cubemap) - { - NazaraError("Texture must be a cubemap"); - return false; - } - #endif - - Image image; - if (!image.LoadFromStream(stream, params)) - { - NazaraError("Failed to load image"); - return false; - } - - if (!image.Convert(m_impl->format)) - { - NazaraError("Failed to convert image to texture format"); - return false; - } - - unsigned int faceSize = m_impl->width; - - if (image.GetWidth() != faceSize || image.GetHeight() != faceSize) - { - NazaraError("Image size must match texture face size"); - return false; - } - - return Update(image, Rectui(0, 0, faceSize, faceSize), face); - } - - bool Texture::SaveToFile(const String& filePath, const ImageParams& params) - { - Image image; - if (!Download(&image)) - { - NazaraError("Failed to download texture"); - return false; - } - - return image.SaveToFile(filePath, params); - } - - bool Texture::SaveToStream(Stream& stream, const String& format, const ImageParams& params) - { - Image image; - if (!Download(&image)) - { - NazaraError("Failed to download texture"); - return false; - } - - return image.SaveToStream(stream, format, params); - } - - bool Texture::SetMipmapRange(UInt8 minLevel, UInt8 maxLevel) - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return false; - } - - if (minLevel >= m_impl->levelCount) - { - NazaraError("Minimum level cannot be greater or equal than level count (" + String::Number(minLevel) + " >= " + String::Number(m_impl->levelCount) + ')'); - return false; - } - - if (maxLevel < minLevel) - { - NazaraError("Minimum level cannot be greater than maximum level (" + String::Number(minLevel) + " < " + String::Number(maxLevel) + ')'); - return false; - } - #endif - - OpenGL::BindTexture(m_impl->type, m_impl->id); - glTexParameteri(OpenGL::TextureTarget[m_impl->type], GL_TEXTURE_BASE_LEVEL, minLevel); - glTexParameteri(OpenGL::TextureTarget[m_impl->type], GL_TEXTURE_MAX_LEVEL, maxLevel); - - return true; - } - - bool Texture::Update(const Image& image, UInt8 level) - { - #if NAZARA_RENDERER_SAFE - if (!image.IsValid()) - { - NazaraError("Image must be valid"); - return false; - } - - if (image.GetFormat() != m_impl->format) - { - NazaraError("Image format does not match texture format"); - return false; - } - #endif - - const UInt8* pixels = image.GetConstPixels(0, 0, 0, level); - if (!pixels) - { - NazaraError("Failed to access image's pixels"); - return false; - } - - return Update(pixels, image.GetWidth(level), image.GetHeight(level), level); - } - - bool Texture::Update(const Image& image, const Boxui& box, UInt8 level) - { - #if NAZARA_RENDERER_SAFE - if (!image.IsValid()) - { - NazaraError("Image must be valid"); - return false; - } - - if (image.GetFormat() != m_impl->format) - { - NazaraError("Image format does not match texture format"); - return false; - } - #endif - - const UInt8* pixels = image.GetConstPixels(0, 0, 0, level); - if (!pixels) - { - NazaraError("Failed to access image's pixels"); - return false; - } - - return Update(pixels, box, image.GetWidth(level), image.GetHeight(level), level); - } - - bool Texture::Update(const Image& image, const Rectui& rect, unsigned int z, UInt8 level) - { - #if NAZARA_RENDERER_SAFE - if (!image.IsValid()) - { - NazaraError("Image must be valid"); - return false; - } - - if (image.GetFormat() != m_impl->format) - { - NazaraError("Image format does not match texture format"); - return false; - } - #endif - - const UInt8* pixels = image.GetConstPixels(0, 0, 0, level); - if (!pixels) - { - NazaraError("Failed to access image's pixels"); - return false; - } - - return Update(pixels, rect, z, image.GetWidth(level), image.GetHeight(level), level); - } - - bool Texture::Update(const UInt8* pixels, unsigned int srcWidth, unsigned int srcHeight, UInt8 level) - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return false; - } - #endif - - return Update(pixels, Boxui(GetLevelSize(m_impl->width, level), GetLevelSize(m_impl->height, level), GetLevelSize(m_impl->depth, level)), srcWidth, srcHeight, level); - } - - bool Texture::Update(const UInt8* pixels, const Boxui& box, unsigned int srcWidth, unsigned int srcHeight, UInt8 level) - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return false; - } - - if (!pixels) - { - NazaraError("Invalid pixel source"); - return false; - } - - if (!box.IsValid()) - { - NazaraError("Invalid box"); - return false; - } - - unsigned int width = GetLevelSize(m_impl->width, level); - unsigned int height = GetLevelSize(m_impl->height, level); - unsigned int depth = (m_impl->type == ImageType_Cubemap) ? 6 : GetLevelSize(m_impl->depth, level); - if (box.x+box.width > width || box.y+box.height > height || box.z+box.depth > depth || - (m_impl->type == ImageType_Cubemap && box.depth > 1)) // Nous n'autorisons pas de modifier plus d'une face du cubemap à la fois - { - NazaraError("Cube dimensions are out of bounds"); - return false; - } - - if (level >= m_impl->levelCount) - { - NazaraError("Level out of bounds (" + String::Number(level) + " >= " + String::Number(m_impl->levelCount) + ')'); - return false; - } - #endif - - OpenGL::Format format; - if (!OpenGL::TranslateFormat(m_impl->format, &format, OpenGL::FormatType_Texture)) - { - NazaraError("Failed to get OpenGL format"); - return false; - } - - SetUnpackAlignement(PixelFormat::GetBytesPerPixel(m_impl->format)); - glPixelStorei(GL_UNPACK_ROW_LENGTH, srcWidth); - glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, srcHeight); - - OpenGL::BindTexture(m_impl->type, m_impl->id); - - if (PixelFormat::IsCompressed(m_impl->format)) - { - switch (m_impl->type) - { - case ImageType_1D: - glCompressedTexSubImage1D(GL_TEXTURE_1D, level, box.x, box.width, format.internalFormat, PixelFormat::ComputeSize(m_impl->format, box.width, 1, 1), pixels); - break; - - case ImageType_1D_Array: - case ImageType_2D: - glCompressedTexSubImage2D(OpenGL::TextureTarget[m_impl->type], level, box.x, box.y, box.width, box.height, format.internalFormat, PixelFormat::ComputeSize(m_impl->format, box.width, box.height, 1), pixels); - break; - - case ImageType_2D_Array: - case ImageType_3D: - glCompressedTexSubImage3D(OpenGL::TextureTarget[m_impl->type], level, box.x, box.y, box.z, box.width, box.height, box.depth, format.internalFormat, PixelFormat::ComputeSize(m_impl->format, box.width, box.height, box.depth), pixels); - break; - - case ImageType_Cubemap: - glCompressedTexSubImage2D(OpenGL::CubemapFace[box.z], level, box.x, box.y, box.width, box.height, format.internalFormat, PixelFormat::ComputeSize(m_impl->format, box.width, box.height, box.depth), pixels); - break; - } - } - else - { - switch (m_impl->type) - { - case ImageType_1D: - glTexSubImage1D(GL_TEXTURE_1D, level, box.x, box.width, format.dataFormat, format.dataType, pixels); - break; - - case ImageType_1D_Array: - case ImageType_2D: - glTexSubImage2D(OpenGL::TextureTarget[m_impl->type], level, box.x, box.y, box.width, box.height, format.dataFormat, format.dataType, pixels); - break; - - case ImageType_2D_Array: - case ImageType_3D: - glTexSubImage3D(OpenGL::TextureTarget[m_impl->type], level, box.x, box.y, box.z, box.width, box.height, box.depth, format.dataFormat, format.dataType, pixels); - break; - - case ImageType_Cubemap: - glTexSubImage2D(OpenGL::CubemapFace[box.z], level, box.x, box.y, box.width, box.height, format.dataFormat, format.dataType, pixels); - break; - } - } - - return true; - } - - bool Texture::Update(const UInt8* pixels, const Rectui& rect, unsigned int z, unsigned int srcWidth, unsigned int srcHeight, UInt8 level) - { - return Update(pixels, Boxui(rect.x, rect.y, z, rect.width, rect.height, 1), srcWidth, srcHeight, level); - } - - unsigned int Texture::GetOpenGLID() const - { - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return 0; - } - #endif - - return m_impl->id; - } - - bool Texture::IsFormatSupported(PixelFormatType format) - { - switch (format) - { - // Formats de base - case PixelFormatType_A8: - case PixelFormatType_BGR8: - case PixelFormatType_BGRA8: - case PixelFormatType_L8: - case PixelFormatType_LA8: - case PixelFormatType_RGB8: - case PixelFormatType_RGBA8: - return true; - - // Packed formats supportés depuis OpenGL 1.2 - case PixelFormatType_RGB5A1: - case PixelFormatType_RGBA4: - return true; - - // Formats supportés depuis OpenGL 3 - case PixelFormatType_R8: - case PixelFormatType_R8I: - case PixelFormatType_R8UI: - case PixelFormatType_R16: - case PixelFormatType_R16F: - case PixelFormatType_R16I: - case PixelFormatType_R16UI: - case PixelFormatType_R32F: - case PixelFormatType_R32I: - case PixelFormatType_R32UI: - case PixelFormatType_RG8: - case PixelFormatType_RG8I: - case PixelFormatType_RG8UI: - case PixelFormatType_RG16: - case PixelFormatType_RG16F: - case PixelFormatType_RG16I: - case PixelFormatType_RG16UI: - case PixelFormatType_RG32F: - case PixelFormatType_RG32I: - case PixelFormatType_RG32UI: - case PixelFormatType_RGB16F: - case PixelFormatType_RGB16I: - case PixelFormatType_RGB16UI: - case PixelFormatType_RGB32F: - case PixelFormatType_RGB32I: - case PixelFormatType_RGB32UI: - case PixelFormatType_RGBA16F: - case PixelFormatType_RGBA16I: - case PixelFormatType_RGBA16UI: - case PixelFormatType_RGBA32F: - case PixelFormatType_RGBA32I: - case PixelFormatType_RGBA32UI: - return true; - - // Formats de profondeur (Supportés avec les FBOs) - case PixelFormatType_Depth16: - case PixelFormatType_Depth24: - case PixelFormatType_Depth32: - case PixelFormatType_Depth24Stencil8: - return true; - - // Formats de stencil (Non supportés pour les textures) - case PixelFormatType_Stencil1: - case PixelFormatType_Stencil4: - case PixelFormatType_Stencil8: - case PixelFormatType_Stencil16: - return false; - - // Formats compressés - case PixelFormatType_DXT1: - case PixelFormatType_DXT3: - case PixelFormatType_DXT5: - return OpenGL::IsSupported(OpenGLExtension_TextureCompression_s3tc); - - case PixelFormatType_Undefined: - break; - } - - NazaraError("Invalid pixel format"); - return false; - } - - bool Texture::IsMipmappingSupported() - { - return glGenerateMipmap != nullptr; - } - - bool Texture::IsTypeSupported(ImageType type) - { - switch (type) - { - case ImageType_1D: - case ImageType_1D_Array: - case ImageType_2D: - case ImageType_2D_Array: - case ImageType_3D: - case ImageType_Cubemap: - return true; // Tous supportés nativement dans OpenGL 3 - } - - NazaraError("Image type not handled (0x" + String::Number(type, 16) + ')'); - return false; - } - - bool Texture::CreateTexture(bool proxy) - { - OpenGL::Format openGLFormat; - if (!OpenGL::TranslateFormat(m_impl->format, &openGLFormat, OpenGL::FormatType_Texture)) - { - NazaraError("Format " + PixelFormat::GetName(m_impl->format) + " not supported by OpenGL"); - return false; - } - - GLenum target = (proxy) ? OpenGL::TextureTargetProxy[m_impl->type] : OpenGL::TextureTarget[m_impl->type]; - switch (m_impl->type) - { - case ImageType_1D: - { - if (glTexStorage1D && !proxy) // Les drivers AMD semblent ne pas aimer glTexStorage avec un format proxy - glTexStorage1D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width); - else - { - unsigned int w = m_impl->width; - for (UInt8 level = 0; level < m_impl->levelCount; ++level) - { - glTexImage1D(target, level, openGLFormat.internalFormat, w, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); - if (w > 1U) - w >>= 1; - } - } - break; - } - - case ImageType_1D_Array: - case ImageType_2D: - { - if (glTexStorage2D && !proxy) - glTexStorage2D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width, m_impl->height); - else - { - unsigned int w = m_impl->width; - unsigned int h = m_impl->height; - for (UInt8 level = 0; level < m_impl->levelCount; ++level) - { - glTexImage2D(target, level, openGLFormat.internalFormat, w, h, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); - if (w > 1U) - w >>= 1; - - if (h > 1U) - h >>= 1; - } - } - break; - } - - case ImageType_2D_Array: - case ImageType_3D: - { - if (glTexStorage3D && !proxy) - glTexStorage3D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width, m_impl->height, m_impl->depth); - else - { - unsigned int w = m_impl->width; - unsigned int h = m_impl->height; - unsigned int d = m_impl->depth; - for (UInt8 level = 0; level < m_impl->levelCount; ++level) - { - glTexImage3D(target, level, openGLFormat.internalFormat, w, h, d, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); - if (w > 1U) - w >>= 1; - - if (h > 1U) - h >>= 1; - - if (d > 1U) - d >>= 1; - } - } - break; - } - - case ImageType_Cubemap: - { - if (glTexStorage2D && !proxy) - glTexStorage2D(target, m_impl->levelCount, openGLFormat.internalFormat, m_impl->width, m_impl->height); - else - { - unsigned int size = m_impl->width; // Les cubemaps ont une longueur et largeur identique - for (UInt8 level = 0; level < m_impl->levelCount; ++level) - { - for (GLenum face : OpenGL::CubemapFace) - glTexImage2D(face, level, openGLFormat.internalFormat, size, size, 0, openGLFormat.dataFormat, openGLFormat.dataType, nullptr); - - if (size > 1U) - size >>= 1; - } - } - break; - } - } - - if (proxy) - { - GLint internalFormat = 0; - glGetTexLevelParameteriv(target, 0, GL_TEXTURE_INTERNAL_FORMAT, &internalFormat); - if (internalFormat == 0) - return false; - } - - // Application du swizzle - if (!proxy && OpenGL::GetVersion() >= 300) - { - glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, openGLFormat.swizzle[0]); - glTexParameteri(target, GL_TEXTURE_SWIZZLE_G, openGLFormat.swizzle[1]); - glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, openGLFormat.swizzle[2]); - glTexParameteri(target, GL_TEXTURE_SWIZZLE_A, openGLFormat.swizzle[3]); - } - - if (!proxy && PixelFormat::GetContent(m_impl->format) == PixelFormatContent_DepthStencil) - { - glTexParameteri(target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); - glTexParameteri(target, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL); - } - - return true; - } - - bool Texture::Initialize() - { - if (!TextureLibrary::Initialize()) - { - NazaraError("Failed to initialise library"); - return false; - } - - if (!TextureManager::Initialize()) - { - NazaraError("Failed to initialise manager"); - return false; - } - - return true; - } - - void Texture::Uninitialize() - { - TextureManager::Uninitialize(); - TextureLibrary::Uninitialize(); - } - - TextureLibrary::LibraryMap Texture::s_library; - TextureManager::ManagerMap Texture::s_managerMap; - TextureManager::ManagerParams Texture::s_managerParameters; -} diff --git a/src/Nazara/Renderer/TextureSampler.cpp b/src/Nazara/Renderer/TextureSampler.cpp deleted file mode 100644 index bd09a943f..000000000 --- a/src/Nazara/Renderer/TextureSampler.cpp +++ /dev/null @@ -1,393 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - namespace - { - std::unordered_map s_samplers; - UInt8 s_maxAnisotropyLevel; - bool s_useAnisotropicFilter; - } - - TextureSampler::TextureSampler() : - m_filterMode(SamplerFilter_Default), - m_wrapMode(SamplerWrap_Default), - m_anisotropicLevel(0), - m_mipmaps(true), - m_samplerId(0) - { - } - - UInt8 TextureSampler::GetAnisotropicLevel() const - { - return m_anisotropicLevel; - } - - SamplerFilter TextureSampler::GetFilterMode() const - { - return m_filterMode; - } - - SamplerWrap TextureSampler::GetWrapMode() const - { - return m_wrapMode; - } - - void TextureSampler::SetAnisotropyLevel(UInt8 anisotropyLevel) - { - #ifdef NAZARA_DEBUG - if (!Renderer::IsInitialized()) - { - NazaraError("Renderer module must be initialized"); - return; - } - #endif - - if (m_anisotropicLevel != anisotropyLevel) - { - if (anisotropyLevel > s_maxAnisotropyLevel) - { - NazaraWarning("Anisotropy level is over maximum anisotropy level (" + String::Number(anisotropyLevel) + " > " + String::Number(s_maxAnisotropyLevel) + ')'); - anisotropyLevel = s_maxAnisotropyLevel; - } - - m_anisotropicLevel = anisotropyLevel; - m_samplerId = 0; - } - } - - void TextureSampler::SetFilterMode(SamplerFilter filterMode) - { - if (m_filterMode != filterMode) - { - m_filterMode = filterMode; - m_samplerId = 0; - } - } - - void TextureSampler::SetWrapMode(SamplerWrap wrapMode) - { - if (m_wrapMode != wrapMode) - { - m_wrapMode = wrapMode; - m_samplerId = 0; - } - } - - UInt8 TextureSampler::GetDefaultAnisotropicLevel() - { - return s_defaultAnisotropyLevel; - } - - SamplerFilter TextureSampler::GetDefaultFilterMode() - { - return s_defaultFilterMode; - } - - SamplerWrap TextureSampler::GetDefaultWrapMode() - { - return s_defaultWrapMode; - } - - void TextureSampler::SetDefaultAnisotropyLevel(UInt8 anisotropyLevel) - { - #if NAZARA_RENDERER_SAFE - if (anisotropyLevel == 0) - { - NazaraError("Default anisotropy level mode cannot be set to default value (0)"); - return; - } - #endif - - #ifdef NAZARA_DEBUG - if (!Renderer::IsInitialized()) - { - NazaraError("Renderer module must be initialized"); - return; - } - #endif - - if (anisotropyLevel > s_maxAnisotropyLevel) - { - NazaraWarning("Anisotropy level is over maximum anisotropy level (" + String::Number(anisotropyLevel) + " > " + String::Number(s_maxAnisotropyLevel)); - anisotropyLevel = s_maxAnisotropyLevel; - } - - s_defaultAnisotropyLevel = anisotropyLevel; - - if (s_useAnisotropicFilter) - { - for (const std::pair& pair : s_samplers) - { - if (((pair.first >> 5) & 0xFF) == 0) - glSamplerParameterf(pair.second, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast(anisotropyLevel)); - } - } - } - - void TextureSampler::SetDefaultFilterMode(SamplerFilter filterMode) - { - #if NAZARA_RENDERER_SAFE - if (filterMode == SamplerFilter_Default) - { - NazaraError("Default filter mode cannot be set to default enum value (SamplerFilter_Default)"); - return; - } - #endif - - s_defaultFilterMode = filterMode; - - for (const std::pair& pair : s_samplers) - { - if (((pair.first >> 1) & 0x3) == SamplerFilter_Default) - { - bool mipmaps = pair.first & 0x1; - switch (filterMode) - { - case SamplerFilter_Bilinear: - if (mipmaps) - glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - else - glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glSamplerParameteri(pair.second, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; - - case SamplerFilter_Nearest: - if (mipmaps) - glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); - else - glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glSamplerParameteri(pair.second, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - break; - - case SamplerFilter_Trilinear: - if (mipmaps) - glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - else - glSamplerParameteri(pair.second, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Filtrage bilinéaire - - glSamplerParameteri(pair.second, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; - - default: - NazaraError("Texture filter not handled (0x" + String::Number(filterMode, 16) + ')'); - break; - } - } - } - } - - void TextureSampler::SetDefaultWrapMode(SamplerWrap wrapMode) - { - #if NAZARA_RENDERER_SAFE - if (wrapMode == SamplerWrap_Default) - { - NazaraError("Default wrap mode cannot be set to default enum value (SamplerWrap_Default)"); - return; - } - #endif - - s_defaultWrapMode = wrapMode; - - GLenum wrapEnum = OpenGL::SamplerWrapMode[wrapMode]; - for (const std::pair& pair : s_samplers) - { - if (((pair.first >> 3) & 0x3) == SamplerWrap_Default) - { - glSamplerParameteri(pair.second, GL_TEXTURE_WRAP_R, wrapEnum); - glSamplerParameteri(pair.second, GL_TEXTURE_WRAP_T, wrapEnum); - glSamplerParameteri(pair.second, GL_TEXTURE_WRAP_S, wrapEnum); - } - } - } - - void TextureSampler::Apply(const Texture* texture) const - { - ImageType type = texture->GetType(); - GLenum target = OpenGL::TextureTarget[type]; - - OpenGL::BindTexture(type, texture->GetOpenGLID()); - - if (s_useAnisotropicFilter) - { - UInt8 anisotropyLevel = (m_anisotropicLevel == 0) ? s_defaultAnisotropyLevel : m_anisotropicLevel; - glTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast(anisotropyLevel)); - } - - SamplerFilter filterMode = (m_filterMode == SamplerFilter_Default) ? s_defaultFilterMode : m_filterMode; - switch (filterMode) - { - case SamplerFilter_Bilinear: - if (m_mipmaps) - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - else - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; - - case SamplerFilter_Nearest: - if (m_mipmaps) - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); - else - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - break; - - case SamplerFilter_Trilinear: - if (m_mipmaps) - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - else - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // Filtrage bilinéaire - - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; - - default: - NazaraError("Texture filter not handled (0x" + String::Number(filterMode, 16) + ')'); - break; - } - - GLenum wrapMode = OpenGL::SamplerWrapMode[(m_wrapMode == SamplerWrap_Default) ? s_defaultWrapMode : m_wrapMode]; - switch (type) - { - // Notez l'absence de "break" ici - case ImageType_3D: - glTexParameteri(target, GL_TEXTURE_WRAP_R, wrapMode); - case ImageType_2D: - case ImageType_2D_Array: - case ImageType_Cubemap: - glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapMode); - case ImageType_1D: - case ImageType_1D_Array: - glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapMode); - break; - } - } - - void TextureSampler::Bind(unsigned int unit) const - { - static_assert(SamplerFilter_Max < 0x4, "Maximum sampler filter mode takes more than 2 bits"); - static_assert(SamplerWrap_Max < 0x4, "Maximum sampler wrap mode takes more than 2 bits"); - - if (!m_samplerId) - UpdateSamplerId(); - - OpenGL::BindSampler(unit, m_samplerId); - } - - unsigned int TextureSampler::GetOpenGLID() const - { - if (!m_samplerId) - UpdateSamplerId(); - - return m_samplerId; - } - - void TextureSampler::UpdateSamplerId() const - { - UInt32 key = (((m_mipmaps) ? 1 : 0) << 0) | // 1 bit - (m_filterMode << 1) | // 2 bits - (m_wrapMode << 3) | // 2 bits - (m_anisotropicLevel << 5); // 8 bits - - auto it = s_samplers.find(key); - if (it == s_samplers.end()) - { - GLuint sampler; - glGenSamplers(1, &sampler); - - if (s_useAnisotropicFilter) - { - UInt8 anisotropyLevel = (m_anisotropicLevel == 0) ? s_defaultAnisotropyLevel : m_anisotropicLevel; - glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, static_cast(anisotropyLevel)); - } - - SamplerFilter filterMode = (m_filterMode == SamplerFilter_Default) ? s_defaultFilterMode : m_filterMode; - switch (filterMode) - { - case SamplerFilter_Bilinear: - glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, (m_mipmaps) ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR); - glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; - - case SamplerFilter_Nearest: - glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, (m_mipmaps) ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST); - glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - break; - - case SamplerFilter_Trilinear: - // Équivalent au filtrage bilinéaire si les mipmaps sont absentes - glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, (m_mipmaps) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR); - glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - break; - - default: - NazaraError("Texture filter not handled (0x" + String::Number(filterMode, 16) + ')'); - break; - } - - GLenum wrapMode = OpenGL::SamplerWrapMode[(m_wrapMode == SamplerWrap_Default) ? s_defaultWrapMode : m_wrapMode]; - glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, wrapMode); - glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, wrapMode); - glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, wrapMode); - - s_samplers[key] = sampler; - m_samplerId = sampler; - } - else - m_samplerId = it->second; - } - - bool TextureSampler::UseMipmaps(bool mipmaps) - { - if (m_mipmaps != mipmaps) - { - m_mipmaps = mipmaps; - m_samplerId = 0; - - return true; // Renvoie true si la valeur a été changée (Donc s'il faut réappliquer le sampler) - } - else - return false; - } - - bool TextureSampler::Initialize() - { - s_maxAnisotropyLevel = Renderer::GetMaxAnisotropyLevel(); - s_useAnisotropicFilter = OpenGL::IsSupported(OpenGLExtension_AnisotropicFilter); - - return true; - } - - void TextureSampler::Uninitialize() - { - if (!s_samplers.empty()) - { - Context::EnsureContext(); - for (const std::pair& pair : s_samplers) - OpenGL::DeleteSampler(pair.second); - - s_samplers.clear(); - } - } - - UInt8 TextureSampler::s_defaultAnisotropyLevel = 1; - SamplerFilter TextureSampler::s_defaultFilterMode = SamplerFilter_Trilinear; - SamplerWrap TextureSampler::s_defaultWrapMode = SamplerWrap_Repeat; -} diff --git a/src/Nazara/Renderer/UberShader.cpp b/src/Nazara/Renderer/UberShader.cpp deleted file mode 100644 index 18a3c11fe..000000000 --- a/src/Nazara/Renderer/UberShader.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include - -namespace Nz -{ - UberShader::~UberShader() - { - OnUberShaderRelease(this); - } - - bool UberShader::Initialize() - { - if (!UberShaderLibrary::Initialize()) - { - NazaraError("Failed to initialise library"); - return false; - } - - return true; - } - - void UberShader::Uninitialize() - { - UberShaderLibrary::Uninitialize(); - } - - UberShaderLibrary::LibraryMap UberShader::s_library; -} diff --git a/src/Nazara/Renderer/UberShaderInstance.cpp b/src/Nazara/Renderer/UberShaderInstance.cpp deleted file mode 100644 index ec7043542..000000000 --- a/src/Nazara/Renderer/UberShaderInstance.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include - -namespace Nz -{ - UberShaderInstance::UberShaderInstance(const Shader* shader) : - m_shader(shader) - { - } - - UberShaderInstance::~UberShaderInstance() = default; - - const Shader* UberShaderInstance::GetShader() const - { - return m_shader; - } -} diff --git a/src/Nazara/Renderer/UberShaderInstancePreprocessor.cpp b/src/Nazara/Renderer/UberShaderInstancePreprocessor.cpp deleted file mode 100644 index 166645528..000000000 --- a/src/Nazara/Renderer/UberShaderInstancePreprocessor.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include - -namespace Nz -{ - UberShaderInstancePreprocessor::UberShaderInstancePreprocessor(const Shader* shader) : - UberShaderInstance(shader) - { - } - - UberShaderInstancePreprocessor::~UberShaderInstancePreprocessor() = default; - - bool UberShaderInstancePreprocessor::Activate() const - { - Renderer::SetShader(m_shader); - - return true; - } -} diff --git a/src/Nazara/Renderer/UberShaderPreprocessor.cpp b/src/Nazara/Renderer/UberShaderPreprocessor.cpp deleted file mode 100644 index 2a08088f5..000000000 --- a/src/Nazara/Renderer/UberShaderPreprocessor.cpp +++ /dev/null @@ -1,187 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - UberShaderPreprocessor::~UberShaderPreprocessor() - { - OnUberShaderPreprocessorRelease(this); - } - - UberShaderInstance* UberShaderPreprocessor::Get(const ParameterList& parameters) const - { - // Première étape, transformer les paramètres en un flag - UInt32 flags = 0; - for (auto it = m_flags.begin(); it != m_flags.end(); ++it) - { - if (parameters.HasParameter(it->first)) - { - bool value; - if (parameters.GetBooleanParameter(it->first, &value) && value) - flags |= it->second; - } - } - - // Le shader fait-il partie du cache ? - auto shaderIt = m_cache.find(flags); - - // Si non, il nous faut le construire - if (shaderIt == m_cache.end()) - { - try - { - // Une exception sera lancée à la moindre erreur et celle-ci ne sera pas enregistrée dans le log (car traitée dans le bloc catch) - ErrorFlags errFlags(ErrorFlag_Silent | ErrorFlag_ThrowException, true); - - ShaderRef shader = Shader::New(); - shader->Create(); - - for (unsigned int i = 0; i <= ShaderStageType_Max; ++i) - { - const CachedShader& shaderStage = m_shaders[i]; - - // Le shader stage est-il activé dans cette version du shader ? - if (shaderStage.present && (flags & shaderStage.requiredFlags) == shaderStage.requiredFlags) - { - UInt32 stageFlags = 0; - for (auto it = shaderStage.flags.begin(); it != shaderStage.flags.end(); ++it) - { - if (parameters.HasParameter(it->first)) - { - bool value; - if (parameters.GetBooleanParameter(it->first, &value) && value) - stageFlags |= it->second; - } - } - - auto stageIt = shaderStage.cache.find(stageFlags); - if (stageIt == shaderStage.cache.end()) - { - ShaderStage stage; - stage.Create(static_cast(i)); - - unsigned int glslVersion = OpenGL::GetGLSLVersion(); - - StringStream code; - code << "#version " << glslVersion << "\n\n"; - - code << "#define GLSL_VERSION " << glslVersion << "\n\n"; - - code << "#define EARLY_FRAGMENT_TEST " << (glslVersion >= 420 || OpenGL::IsSupported(OpenGLExtension_Shader_ImageLoadStore)) << "\n\n"; - - for (auto it = shaderStage.flags.begin(); it != shaderStage.flags.end(); ++it) - code << "#define " << it->first << ' ' << ((stageFlags & it->second) ? '1' : '0') << '\n'; - - code << "\n#line 1\n"; // Pour que les éventuelles erreurs du shader se réfèrent à la bonne ligne - code << shaderStage.source; - - stage.SetSource(code); - stage.Compile(); - - stageIt = shaderStage.cache.emplace(flags, std::move(stage)).first; - } - - shader->AttachStage(static_cast(i), stageIt->second); - } - } - - shader->Link(); - - // On construit l'instant - shaderIt = m_cache.emplace(flags, shader.Get()).first; - } - catch (const std::exception&) - { - ErrorFlags errFlags(ErrorFlag_ThrowExceptionDisabled); - - NazaraError("Failed to build UberShader instance: " + Error::GetLastError()); - throw; - } - } - - return &shaderIt->second; - } - - void UberShaderPreprocessor::SetShader(ShaderStageType stage, const String& source, const String& shaderFlags, const String& requiredFlags) - { - CachedShader& shader = m_shaders[stage]; - shader.present = true; - shader.source = source; - - // On extrait les flags de la chaîne - std::vector flags; - shaderFlags.Split(flags, ' '); - - for (String& flag : flags) - { - auto it = m_flags.find(flag); - if (it == m_flags.end()) - m_flags[flag] = 1U << m_flags.size(); - - auto it2 = shader.flags.find(flag); - if (it2 == shader.flags.end()) - shader.flags[flag] = 1U << shader.flags.size(); - } - - // On construit les flags requis pour l'activation du shader - shader.requiredFlags = 0; - - flags.clear(); - requiredFlags.Split(flags, ' '); - - for (String& flag : flags) - { - UInt32 flagVal; - - auto it = m_flags.find(flag); - if (it == m_flags.end()) - { - flagVal = 1U << m_flags.size(); - m_flags[flag] = flagVal; - } - else - flagVal = it->second; - - shader.requiredFlags |= flagVal; - } - } - - bool UberShaderPreprocessor::SetShaderFromFile(ShaderStageType stage, const String& filePath, const String& shaderFlags, const String& requiredFlags) - { - File file(filePath); - if (!file.Open(OpenMode_ReadOnly | OpenMode_Text)) - { - NazaraError("Failed to open \"" + filePath + '"'); - return false; - } - - unsigned int length = static_cast(file.GetSize()); - - String source(length, '\0'); - - if (file.Read(&source[0], length) != length) - { - NazaraError("Failed to read program file"); - return false; - } - - file.Close(); - - SetShader(stage, source, shaderFlags, requiredFlags); - return true; - } - - bool UberShaderPreprocessor::IsSupported() - { - return true; // Forcément supporté - } -} diff --git a/src/Nazara/Renderer/Win32/ContextImpl.cpp b/src/Nazara/Renderer/Win32/ContextImpl.cpp deleted file mode 100644 index 2f7094f70..000000000 --- a/src/Nazara/Renderer/Win32/ContextImpl.cpp +++ /dev/null @@ -1,248 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine - Renderer module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -// Code inspiré de NeHe (Lesson1) et de la SFML par Laurent Gomila - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Nz -{ - ContextImpl::ContextImpl() - { - } - - bool ContextImpl::Activate() - { - return wglMakeCurrent(m_deviceContext, m_context) == TRUE; - } - - bool ContextImpl::Create(ContextParameters& parameters) - { - if (parameters.window) - { - m_window = static_cast(parameters.window); - m_ownsWindow = false; - } - else - { - m_window = CreateWindowA("STATIC", nullptr, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, nullptr, nullptr, GetModuleHandle(nullptr), nullptr); - if (!m_window) - { - NazaraError("Failed to create window"); - return false; - } - - ShowWindow(m_window, SW_HIDE); - m_ownsWindow = true; - } - - // En cas d'exception, la ressource sera quand même libérée - CallOnExit onExit([this] () - { - Destroy(); - }); - - m_deviceContext = GetDC(m_window); - if (!m_deviceContext) - { - NazaraError("Failed to get device context"); - return false; - } - - int pixelFormat = 0; - if (parameters.antialiasingLevel > 0) - { - if (wglChoosePixelFormat) - { - bool valid; - UINT numFormats; - - int attributes[] = { - WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, - WGL_SUPPORT_OPENGL_ARB, GL_TRUE, - WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, - WGL_COLOR_BITS_ARB, (parameters.bitsPerPixel == 32) ? 24 : parameters.bitsPerPixel, - WGL_ALPHA_BITS_ARB, (parameters.bitsPerPixel == 32) ? 8 : 0, - WGL_DEPTH_BITS_ARB, parameters.depthBits, - WGL_STENCIL_BITS_ARB, parameters.stencilBits, - WGL_DOUBLE_BUFFER_ARB, (parameters.doubleBuffered) ? GL_TRUE : GL_FALSE, - WGL_SAMPLE_BUFFERS_ARB, GL_TRUE, - WGL_SAMPLES_ARB, parameters.antialiasingLevel, - 0, 0 - }; - - do - { - valid = (wglChoosePixelFormat(m_deviceContext, attributes, nullptr, 1, &pixelFormat, &numFormats) == TRUE); - } - while ((!valid || numFormats == 0) && --attributes[19] > 0); - - if (!valid) - { - NazaraWarning("Could not find a format matching requirements, disabling antialiasing..."); - pixelFormat = 0; - } - - parameters.antialiasingLevel = attributes[19]; - } - else - { - NazaraWarning("Antialiasing is not supported"); - parameters.antialiasingLevel = 0; - } - } - - PIXELFORMATDESCRIPTOR descriptor; - ZeroMemory(&descriptor, sizeof(PIXELFORMATDESCRIPTOR)); - descriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR); - descriptor.nVersion = 1; - - if (pixelFormat == 0) - { - descriptor.cColorBits = parameters.bitsPerPixel; - descriptor.cDepthBits = parameters.depthBits; - descriptor.cStencilBits = parameters.stencilBits; - descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; - descriptor.iPixelType = PFD_TYPE_RGBA; - - if (parameters.bitsPerPixel == 32) - descriptor.cAlphaBits = 8; - - if (parameters.doubleBuffered) - descriptor.dwFlags |= PFD_DOUBLEBUFFER; - - pixelFormat = ChoosePixelFormat(m_deviceContext, &descriptor); - if (pixelFormat == 0) - { - NazaraError("Failed to choose pixel format"); - return false; - } - } - - if (!SetPixelFormat(m_deviceContext, pixelFormat, &descriptor)) - { - NazaraError("Failed to set pixel format"); - return false; - } - - // Arrivé ici, le format de pixel est choisi, nous récupérons donc les paramètres réels du futur contexte - if (DescribePixelFormat(m_deviceContext, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &descriptor) != 0) - { - parameters.bitsPerPixel = descriptor.cColorBits + descriptor.cAlphaBits; - parameters.depthBits = descriptor.cDepthBits; - parameters.stencilBits = descriptor.cDepthBits; - } - else - NazaraWarning("Failed to get context's parameters"); - - HGLRC shareContext = (parameters.shared) ? static_cast(parameters.shareContext->m_impl)->m_context : nullptr; - - m_context = nullptr; - if (wglCreateContextAttribs) - { - int attributes[4*2+1]; - int* attrib = attributes; - - *attrib++ = WGL_CONTEXT_MAJOR_VERSION_ARB; - *attrib++ = parameters.majorVersion; - - *attrib++ = WGL_CONTEXT_MINOR_VERSION_ARB; - *attrib++ = parameters.minorVersion; - - if (parameters.majorVersion >= 3) - { - *attrib++ = WGL_CONTEXT_PROFILE_MASK_ARB; - *attrib++ = (parameters.compatibilityProfile) ? WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB : WGL_CONTEXT_CORE_PROFILE_BIT_ARB; - - // Les contextes forward-compatible ne sont plus utilisés pour cette raison : - // http://www.opengl.org/discussion_boards/showthread.php/175052-Forward-compatible-vs-Core-profile - } - - if (parameters.debugMode) - { - *attrib++ = WGL_CONTEXT_FLAGS_ARB; - *attrib++ = WGL_CONTEXT_DEBUG_BIT_ARB; - } - - *attrib++ = 0; - - m_context = wglCreateContextAttribs(m_deviceContext, shareContext, attributes); - } - - if (!m_context) - { - m_context = wglCreateContext(m_deviceContext); - - if (shareContext) - { - // wglShareLists n'est pas thread-safe (source: SFML) - static Mutex mutex; - LockGuard lock(mutex); - - if (!wglShareLists(shareContext, m_context)) - NazaraWarning("Failed to share the context: " + Error::GetLastSystemError()); - } - } - - if (!m_context) - { - NazaraError("Failed to create context"); - return false; - } - - onExit.Reset(); - - return true; - } - - void ContextImpl::Destroy() - { - if (m_context) - { - if (wglGetCurrentContext() == m_context) - wglMakeCurrent(nullptr, nullptr); - - wglDeleteContext(m_context); - m_context = nullptr; - } - - if (m_deviceContext) - { - ReleaseDC(m_window, m_deviceContext); - m_deviceContext = nullptr; - } - - if (m_ownsWindow) - { - DestroyWindow(m_window); - m_window = nullptr; - } - } - - void ContextImpl::EnableVerticalSync(bool enabled) - { - if (wglSwapInterval) - wglSwapInterval(enabled ? 1 : 0); - else - NazaraError("Vertical sync not supported"); - } - - void ContextImpl::SwapBuffers() - { - ::SwapBuffers(m_deviceContext); - } - - bool ContextImpl::Desactivate() - { - return wglMakeCurrent(nullptr, nullptr) == TRUE; - } -} diff --git a/src/Nazara/Renderer/Win32/ContextImpl.hpp b/src/Nazara/Renderer/Win32/ContextImpl.hpp deleted file mode 100644 index 0e5c7cbc9..000000000 --- a/src/Nazara/Renderer/Win32/ContextImpl.hpp +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (C) 2015 Jérôme Leclercq -// This file is part of the "Nazara Engine". -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_CONTEXTIMPL_HPP -#define NAZARA_CONTEXTIMPL_HPP - -#include -#include -#include - -namespace Nz -{ - class ContextImpl - { - public: - ContextImpl(); - - bool Activate(); - - bool Create(ContextParameters& parameters); - - void Destroy(); - - void EnableVerticalSync(bool enabled); - - void SwapBuffers(); - - static bool Desactivate(); - - private: - HDC m_deviceContext; - HGLRC m_context; - HWND m_window; - bool m_ownsWindow; - }; -} - -#endif // NAZARA_CONTEXTIMPL_HPP diff --git a/src/Nazara/VulkanRenderer/Debug/NewOverload.cpp b/src/Nazara/VulkanRenderer/Debug/NewOverload.cpp new file mode 100644 index 000000000..f431e055f --- /dev/null +++ b/src/Nazara/VulkanRenderer/Debug/NewOverload.cpp @@ -0,0 +1,31 @@ +// Copyright (C) 2014 AUTHORS +// This file is part of the "Nazara Engine - Module name" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#if NAZARA_VULKANRENDERER_MANAGE_MEMORY + +#include +#include // Nécessaire ? + +void* operator new(std::size_t size) +{ + return Nz::MemoryManager::Allocate(size, false); +} + +void* operator new[](std::size_t size) +{ + return Nz::MemoryManager::Allocate(size, true); +} + +void operator delete(void* pointer) noexcept +{ + Nz::MemoryManager::Free(pointer, false); +} + +void operator delete[](void* pointer) noexcept +{ + Nz::MemoryManager::Free(pointer, true); +} + +#endif // NAZARA_VULKANRENDERER_MANAGE_MEMORY diff --git a/src/Nazara/VulkanRenderer/Export.cpp b/src/Nazara/VulkanRenderer/Export.cpp new file mode 100644 index 000000000..42f89c79e --- /dev/null +++ b/src/Nazara/VulkanRenderer/Export.cpp @@ -0,0 +1,15 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +extern "C" +{ + NAZARA_EXPORT Nz::RendererImpl* NazaraRenderer_Instantiate() + { + std::unique_ptr renderer(new Nz::VulkanRenderer); + return renderer.release(); + } +} diff --git a/src/Nazara/VulkanRenderer/RenderTarget.cpp b/src/Nazara/VulkanRenderer/RenderTarget.cpp new file mode 100644 index 000000000..4c78a5321 --- /dev/null +++ b/src/Nazara/VulkanRenderer/RenderTarget.cpp @@ -0,0 +1,14 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + RenderTarget::~RenderTarget() + { + OnRenderTargetRelease(this); + } +} diff --git a/src/Nazara/VulkanRenderer/RenderWindow.cpp b/src/Nazara/VulkanRenderer/RenderWindow.cpp new file mode 100644 index 000000000..1d5fbd33e --- /dev/null +++ b/src/Nazara/VulkanRenderer/RenderWindow.cpp @@ -0,0 +1,530 @@ +// Copyright (C) 2015 Jérôme Leclercq +// This file is part of the "Nazara Engine - Renderer module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + RenderWindow::RenderWindow() : + RenderTarget(), Window(), + m_surface(Nz::Vulkan::GetInstance()), + m_forcedPhysicalDevice(nullptr), + m_depthStencilFormat(VK_FORMAT_MAX_ENUM) + { + } + + RenderWindow::RenderWindow(VideoMode mode, const String& title, UInt32 style) : + RenderWindow() + { + ErrorFlags flags(ErrorFlag_ThrowException, true); + Create(mode, title, style); + } + + RenderWindow::RenderWindow(WindowHandle handle) : + RenderWindow() + { + ErrorFlags flags(ErrorFlag_ThrowException, true); + Create(handle); + } + + RenderWindow::~RenderWindow() + { + // Nécessaire si Window::Destroy est appelé par son destructeur + OnWindowDestroy(); + } + + bool RenderWindow::Acquire(UInt32* imageIndex) const + { + if (!m_swapchain.AcquireNextImage(std::numeric_limits::max(), m_imageReadySemaphore, VK_NULL_HANDLE, imageIndex)) + { + NazaraError("Failed to acquire next image"); + return false; + } + + return true; + } + + void RenderWindow::BuildPreRenderCommands(UInt32 imageIndex, Vk::CommandBuffer& commandBuffer) + { + //commandBuffer.SetImageLayout(m_swapchain.GetBuffer(imageIndex).image, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + // Temporary + if (m_depthStencilFormat != VK_FORMAT_MAX_ENUM) + { + VkImageSubresourceRange imageRange = { + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageAspectFlags aspectMask + 0, // uint32_t baseMipLevel + 1, // uint32_t levelCount + 0, // uint32_t baseArrayLayer + 1 // uint32_t layerCount + }; + + commandBuffer.SetImageLayout(m_depthBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, imageRange); + } + } + + void RenderWindow::BuildPostRenderCommands(UInt32 imageIndex, Vk::CommandBuffer& commandBuffer) + { + //commandBuffer.SetImageLayout(m_swapchain.GetBuffer(imageIndex).image, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + } + + const Vk::Framebuffer& RenderWindow::GetFrameBuffer(UInt32 imageIndex) const + { + return m_frameBuffers[imageIndex]; + } + + UInt32 RenderWindow::GetFramebufferCount() const + { + return static_cast(m_frameBuffers.size()); + } + + bool RenderWindow::Create(VideoMode mode, const String& title, UInt32 style) + { + return Window::Create(mode, title, style); + } + + bool RenderWindow::Create(WindowHandle handle) + { + return Window::Create(handle); + } + + const Vk::DeviceHandle& RenderWindow::GetDevice() const + { + return m_device; + } + + UInt32 RenderWindow::GetPresentableFamilyQueue() const + { + return m_presentableFamilyQueue; + } + + const Vk::Surface& RenderWindow::GetSurface() const + { + return m_surface; + } + + const Vk::Swapchain& RenderWindow::GetSwapchain() const + { + return m_swapchain; + } + + void RenderWindow::Present(UInt32 imageIndex) + { + NazaraAssert(imageIndex < m_frameBuffers.size(), "Invalid image index"); + + m_presentQueue.Present(m_swapchain, imageIndex); + } + + bool RenderWindow::IsValid() const + { + return m_impl != nullptr; + } + + void RenderWindow::SetDepthStencilFormats(std::vector pixelFormat) + { + m_wantedDepthStencilFormats = std::move(pixelFormat); + } + + void RenderWindow::SetPhysicalDevice(VkPhysicalDevice device) + { + m_forcedPhysicalDevice = device; + } + + bool RenderWindow::OnWindowCreated() + { + OnRenderTargetSizeChange(this); + + #if defined(NAZARA_PLATFORM_WINDOWS) + HWND handle = reinterpret_cast(GetHandle()); + HINSTANCE instance = reinterpret_cast(GetWindowLongPtrW(handle, GWLP_HINSTANCE)); + bool success = m_surface.Create(instance, handle); + #else + #error This OS is not supported by Vulkan + #endif + + if (!success) + { + NazaraError("Failed to create Vulkan surface"); + return false; + } + + m_device = Vulkan::SelectDevice(m_forcedPhysicalDevice, m_surface, &m_presentableFamilyQueue); + if (!m_device) + { + NazaraError("Failed to get compatible Vulkan device"); + return false; + } + + m_presentQueue = m_device->GetQueue(m_presentableFamilyQueue, 0); + + std::vector surfaceFormats; + if (!m_surface.GetFormats(m_forcedPhysicalDevice, &surfaceFormats)) + { + NazaraError("Failed to query supported surface formats"); + return false; + } + + if (surfaceFormats.size() == 1 && surfaceFormats[0].format == VK_FORMAT_UNDEFINED) + m_colorFormat = VK_FORMAT_B8G8R8A8_UNORM; + else + m_colorFormat = surfaceFormats[0].format; + + m_colorSpace = surfaceFormats[0].colorSpace; + + if (!m_wantedDepthStencilFormats.empty()) + { + const Vk::PhysicalDevice& deviceInfo = Vulkan::GetPhysicalDeviceInfo(m_forcedPhysicalDevice); + + for (PixelFormatType format : m_wantedDepthStencilFormats) + { + switch (format) + { + case PixelFormatType_Depth16: + m_depthStencilFormat = VK_FORMAT_D16_UNORM; + break; + + case PixelFormatType_Depth24: + case PixelFormatType_Depth24Stencil8: + m_depthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT; + break; + + case PixelFormatType_Depth32: + m_depthStencilFormat = VK_FORMAT_D32_SFLOAT; + break; + + case PixelFormatType_Stencil1: + case PixelFormatType_Stencil4: + case PixelFormatType_Stencil8: + m_depthStencilFormat = VK_FORMAT_S8_UINT; + break; + + case PixelFormatType_Stencil16: + m_depthStencilFormat = VK_FORMAT_MAX_ENUM; + break; + + default: + { + PixelFormatContent formatContent = PixelFormat::GetContent(format); + if (formatContent != PixelFormatContent_DepthStencil && formatContent != PixelFormatContent_Stencil) + NazaraWarning("Invalid format " + PixelFormat::GetName(format) + " for depth-stencil attachment"); + + m_depthStencilFormat = VK_FORMAT_MAX_ENUM; + break; + } + } + + if (m_depthStencilFormat != VK_FORMAT_MAX_ENUM) + { + VkFormatProperties formatProperties = m_device->GetInstance().GetPhysicalDeviceFormatProperties(m_forcedPhysicalDevice, m_depthStencilFormat); + if (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) + break; //< Found it + + m_depthStencilFormat = VK_FORMAT_MAX_ENUM; + } + } + } + + if (!SetupSwapchain()) + { + NazaraError("Failed to create swapchain"); + return false; + } + + if (m_depthStencilFormat != VK_FORMAT_MAX_ENUM && !SetupDepthBuffer()) + { + NazaraError("Failed to create depth buffer"); + return false; + } + + if (!SetupRenderPass()) + { + NazaraError("Failed to create render pass"); + return false; + } + + UInt32 imageCount = m_swapchain.GetBufferCount(); + + // Framebuffers + m_frameBuffers.resize(imageCount); + for (UInt32 i = 0; i < imageCount; ++i) + { + std::array attachments = {m_swapchain.GetBuffer(i).view, m_depthBufferView}; + + VkFramebufferCreateInfo frameBufferCreate = { + VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkFramebufferCreateFlags flags; + m_renderPass, // VkRenderPass renderPass; + (attachments[1] != VK_NULL_HANDLE) ? 2U : 1U, // uint32_t attachmentCount; + attachments.data(), // const VkImageView* pAttachments; + GetWidth(), // uint32_t width; + GetHeight(), // uint32_t height; + 1U // uint32_t layers; + }; + + if (!m_frameBuffers[i].Create(m_device, frameBufferCreate)) + { + NazaraError("Failed to create framebuffer for image #" + String::Number(i)); + return false; + } + } + + m_imageReadySemaphore.Create(m_device); + + m_clock.Restart(); + + return true; + } + + void RenderWindow::OnWindowDestroy() + { + m_device->WaitForIdle(); + m_frameBuffers.clear(); + m_renderPass.Destroy(); + + m_swapchain.Destroy(); + m_surface.Destroy(); + } + + void RenderWindow::OnWindowResized() + { + OnRenderTargetSizeChange(this); + } + + bool RenderWindow::SetupDepthBuffer() + { + VkImageCreateInfo imageCreateInfo = { + VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0U, // VkImageCreateFlags flags; + VK_IMAGE_TYPE_2D, // VkImageType imageType; + m_depthStencilFormat, // VkFormat format; + {GetWidth(), GetHeight(), 1U}, // VkExtent3D extent; + 1U, // uint32_t mipLevels; + 1U, // uint32_t arrayLayers; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; + VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT, // VkImageUsageFlags usage; + VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; + 0U, // uint32_t queueFamilyIndexCount; + nullptr, // const uint32_t* pQueueFamilyIndices; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + }; + + if (!m_depthBuffer.Create(m_device, imageCreateInfo)) + { + NazaraError("Failed to create depth buffer"); + return false; + } + + VkMemoryRequirements memoryReq = m_depthBuffer.GetMemoryRequirements(); + if (!m_depthBufferMemory.Create(m_device, memoryReq.size, memoryReq.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) + { + NazaraError("Failed to allocate depth buffer memory"); + return false; + } + + if (!m_depthBuffer.BindImageMemory(m_depthBufferMemory)) + { + NazaraError("Failed to bind depth buffer to buffer"); + return false; + } + + VkImageViewCreateInfo imageViewCreateInfo = { + VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkImageViewCreateFlags flags; + m_depthBuffer, // VkImage image; + VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; + m_depthStencilFormat, // VkFormat format; + { // VkComponentMapping components; + VK_COMPONENT_SWIZZLE_R, // VkComponentSwizzle .r; + VK_COMPONENT_SWIZZLE_G, // VkComponentSwizzle .g; + VK_COMPONENT_SWIZZLE_B, // VkComponentSwizzle .b; + VK_COMPONENT_SWIZZLE_A // VkComponentSwizzle .a; + }, + { // VkImageSubresourceRange subresourceRange; + VK_IMAGE_ASPECT_DEPTH_BIT, // VkImageAspectFlags .aspectMask; + 0, // uint32_t .baseMipLevel; + 1, // uint32_t .levelCount; + 0, // uint32_t .baseArrayLayer; + 1 // uint32_t .layerCount; + } + }; + + if (!m_depthBufferView.Create(m_device, imageViewCreateInfo)) + { + NazaraError("Failed to create depth buffer view"); + return false; + } + + return true; + } + + bool RenderWindow::SetupRenderPass() + { + std::array attachments = { + { + { + 0, // VkAttachmentDescriptionFlags flags; + m_colorFormat, // VkFormat format; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_STORE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR // VkImageLayout finalLayout; + }, + { + 0, // VkAttachmentDescriptionFlags flags; + m_depthStencilFormat, // VkFormat format; + VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; + VK_ATTACHMENT_LOAD_OP_CLEAR, // VkAttachmentLoadOp loadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp storeOp; + VK_ATTACHMENT_LOAD_OP_DONT_CARE, // VkAttachmentLoadOp stencilLoadOp; + VK_ATTACHMENT_STORE_OP_DONT_CARE, // VkAttachmentStoreOp stencilStoreOp; + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, // VkImageLayout initialLayout; + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout finalLayout; + }, + } + }; + + VkAttachmentReference colorReference = { + 0, // uint32_t attachment; + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL // VkImageLayout layout; + }; + + VkAttachmentReference depthReference = { + 1, // uint32_t attachment; + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL // VkImageLayout layout; + }; + + VkSubpassDescription subpass = { + 0, // VkSubpassDescriptionFlags flags; + VK_PIPELINE_BIND_POINT_GRAPHICS, // VkPipelineBindPoint pipelineBindPoint; + 0U, // uint32_t inputAttachmentCount; + nullptr, // const VkAttachmentReference* pInputAttachments; + 1U, // uint32_t colorAttachmentCount; + &colorReference, // const VkAttachmentReference* pColorAttachments; + nullptr, // const VkAttachmentReference* pResolveAttachments; + (m_depthStencilFormat != VK_FORMAT_MAX_ENUM) ? &depthReference : nullptr, // const VkAttachmentReference* pDepthStencilAttachment; + 0U, // uint32_t preserveAttachmentCount; + nullptr // const uint32_t* pPreserveAttachments; + }; + + std::array dependencies; + // First dependency at the start of the renderpass + // Does the transition from final to initial layout + dependencies[0].srcSubpass = VK_SUBPASS_EXTERNAL; // Producer of the dependency + dependencies[0].dstSubpass = 0; // Consumer is our single subpass that will wait for the execution depdendency + dependencies[0].srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dependencies[0].dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[0].srcAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencies[0].dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[0].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + // Second dependency at the end the renderpass + // Does the transition from the initial to the final layout + dependencies[1].srcSubpass = 0; // Producer of the dependency is our single subpass + dependencies[1].dstSubpass = VK_SUBPASS_EXTERNAL; // Consumer are all commands outside of the renderpass + dependencies[1].srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependencies[1].dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT; + dependencies[1].srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + dependencies[1].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT; + dependencies[1].dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT; + + VkRenderPassCreateInfo createInfo = { + VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkRenderPassCreateFlags flags; + (m_depthStencilFormat != VK_FORMAT_MAX_ENUM) ? 2U : 1U, // uint32_t attachmentCount; + attachments.data(), // const VkAttachmentDescription* pAttachments; + 1U, // uint32_t subpassCount; + &subpass, // const VkSubpassDescription* pSubpasses; + dependencies.size(), // uint32_t dependencyCount; + dependencies.data() // const VkSubpassDependency* pDependencies; + }; + + return m_renderPass.Create(m_device, createInfo); + } + + bool RenderWindow::SetupSwapchain() + { + VkSurfaceCapabilitiesKHR surfaceCapabilities; + if (!m_surface.GetCapabilities(m_forcedPhysicalDevice, &surfaceCapabilities)) + { + NazaraError("Failed to query surface capabilities"); + return false; + } + + Nz::UInt32 imageCount = surfaceCapabilities.minImageCount + 1; + if (surfaceCapabilities.maxImageCount > 0 && imageCount > surfaceCapabilities.maxImageCount) + imageCount = surfaceCapabilities.maxImageCount; + + VkExtent2D extent; + if (surfaceCapabilities.currentExtent.width == -1) + { + extent.width = Nz::Clamp(GetWidth(), surfaceCapabilities.minImageExtent.width, surfaceCapabilities.maxImageExtent.width); + extent.height = Nz::Clamp(GetHeight(), surfaceCapabilities.minImageExtent.height, surfaceCapabilities.maxImageExtent.height); + } + else + extent = surfaceCapabilities.currentExtent; + + std::vector presentModes; + if (!m_surface.GetPresentModes(m_forcedPhysicalDevice, &presentModes)) + { + NazaraError("Failed to query supported present modes"); + return false; + } + + VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR; + for (VkPresentModeKHR presentMode : presentModes) + { + if (presentMode == VK_PRESENT_MODE_MAILBOX_KHR) + { + swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR; + break; + } + + if (presentMode == VK_PRESENT_MODE_IMMEDIATE_KHR) + swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; + } + + VkSwapchainCreateInfoKHR swapchainInfo = { + VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, + nullptr, + 0, + m_surface, + imageCount, + m_colorFormat, + m_colorSpace, + extent, + 1, + VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, + VK_SHARING_MODE_EXCLUSIVE, + 0, nullptr, + surfaceCapabilities.currentTransform, + VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, + swapchainPresentMode, + VK_TRUE, + 0 + }; + + if (!m_swapchain.Create(m_device, swapchainInfo)) + { + NazaraError("Failed to create swapchain"); + return false; + } + + return true; + } +} diff --git a/src/Nazara/VulkanRenderer/VkCommandPool.cpp b/src/Nazara/VulkanRenderer/VkCommandPool.cpp new file mode 100644 index 000000000..a1f2ea629 --- /dev/null +++ b/src/Nazara/VulkanRenderer/VkCommandPool.cpp @@ -0,0 +1,53 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + CommandBuffer CommandPool::AllocateCommandBuffer(VkCommandBufferLevel level) + { + VkCommandBufferAllocateInfo createInfo = + { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + nullptr, + m_handle, + level, + 1U + }; + + VkCommandBuffer handle = VK_NULL_HANDLE; + m_lastErrorCode = m_device->vkAllocateCommandBuffers(*m_device, &createInfo, &handle); + + return CommandBuffer(*this, handle); + } + + std::vector CommandPool::AllocateCommandBuffers(UInt32 commandBufferCount, VkCommandBufferLevel level) + { + VkCommandBufferAllocateInfo createInfo = + { + VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + nullptr, + m_handle, + level, + commandBufferCount + }; + + std::vector handles(commandBufferCount, VK_NULL_HANDLE); + m_lastErrorCode = m_device->vkAllocateCommandBuffers(*m_device, &createInfo, handles.data()); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + return std::vector(); + + std::vector commandBuffers; + for (UInt32 i = 0; i < commandBufferCount; ++i) + commandBuffers.emplace_back(CommandBuffer(*this, handles[i])); + + return commandBuffers; + } + } +} diff --git a/src/Nazara/VulkanRenderer/VkDescriptorPool.cpp b/src/Nazara/VulkanRenderer/VkDescriptorPool.cpp new file mode 100644 index 000000000..f84b9dc20 --- /dev/null +++ b/src/Nazara/VulkanRenderer/VkDescriptorPool.cpp @@ -0,0 +1,53 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + DescriptorSet DescriptorPool::AllocateDescriptorSet(const VkDescriptorSetLayout& setLayouts) + { + VkDescriptorSetAllocateInfo createInfo = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + m_handle, // VkDescriptorPool descriptorPool; + 1U, // uint32_t descriptorSetCount; + &setLayouts // const VkDescriptorSetLayout* pSetLayouts; + }; + + VkDescriptorSet handle = VK_NULL_HANDLE; + m_lastErrorCode = m_device->vkAllocateDescriptorSets(*m_device, &createInfo, &handle); + + return DescriptorSet(*this, handle); + } + + std::vector DescriptorPool::AllocateDescriptorSets(UInt32 descriptorSetCount, const VkDescriptorSetLayout* setLayouts) + { + VkDescriptorSetAllocateInfo createInfo = + { + VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + m_handle, // VkDescriptorPool descriptorPool; + descriptorSetCount, // uint32_t descriptorSetCount; + setLayouts // const VkDescriptorSetLayout* pSetLayouts; + }; + + std::vector handles(descriptorSetCount, VK_NULL_HANDLE); + m_lastErrorCode = m_device->vkAllocateDescriptorSets(*m_device, &createInfo, handles.data()); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + return std::vector(); + + std::vector descriptorSets; + for (UInt32 i = 0; i < descriptorSetCount; ++i) + descriptorSets.emplace_back(DescriptorSet(*this, handles[i])); + + return descriptorSets; + } + } +} diff --git a/src/Nazara/VulkanRenderer/VkDevice.cpp b/src/Nazara/VulkanRenderer/VkDevice.cpp new file mode 100644 index 000000000..a62c65e26 --- /dev/null +++ b/src/Nazara/VulkanRenderer/VkDevice.cpp @@ -0,0 +1,222 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + bool Device::Create(VkPhysicalDevice device, const VkDeviceCreateInfo& createInfo, const VkAllocationCallbacks* allocator) + { + std::vector queuesProperties; + if (!m_instance.GetPhysicalDeviceQueueFamilyProperties(device, &queuesProperties)) + { + NazaraError("Failed to query queue family properties"); + return false; + } + + m_lastErrorCode = m_instance.vkCreateDevice(device, &createInfo, allocator, &m_device); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to create Vulkan device"); + return false; + } + + m_physicalDevice = device; + + // Store the allocator to access them when needed + if (allocator) + m_allocator = *allocator; + else + m_allocator.pfnAllocation = nullptr; + + // Parse extensions and layers + for (UInt32 i = 0; i < createInfo.enabledExtensionCount; ++i) + m_loadedExtensions.insert(createInfo.ppEnabledExtensionNames[i]); + + for (UInt32 i = 0; i < createInfo.enabledLayerCount; ++i) + m_loadedLayers.insert(createInfo.ppEnabledLayerNames[i]); + + // Load all device-related functions + #define NAZARA_VULKANRENDERER_LOAD_DEVICE(func) func = reinterpret_cast(GetProcAddr(#func)) + + try + { + ErrorFlags flags(ErrorFlag_ThrowException, true); + + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkAllocateCommandBuffers); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkAllocateDescriptorSets); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkAllocateMemory); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkBeginCommandBuffer); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkBindBufferMemory); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkBindImageMemory); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdBeginQuery); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdBeginRenderPass); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdBindDescriptorSets); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdBindIndexBuffer); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdBindPipeline); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdBindVertexBuffers); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdBlitImage); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdClearAttachments); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdClearColorImage); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdClearDepthStencilImage); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdCopyBuffer); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdCopyBufferToImage); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdCopyImage); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdCopyImageToBuffer); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdCopyQueryPoolResults); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdDispatch); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdDispatchIndirect); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdDraw); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdDrawIndexed); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdDrawIndexedIndirect); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdDrawIndirect); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdEndQuery); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdEndRenderPass); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdExecuteCommands); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdFillBuffer); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdNextSubpass); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdPipelineBarrier); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdPushConstants); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdResetEvent); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdResetQueryPool); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdResolveImage); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdSetBlendConstants); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdSetDepthBias); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdSetDepthBounds); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdSetEvent); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdSetLineWidth); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdSetScissor); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdSetStencilCompareMask); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdSetStencilReference); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdSetStencilWriteMask); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdSetViewport); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdUpdateBuffer); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdWaitEvents); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCmdWriteTimestamp); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateBuffer); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateBufferView); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateCommandPool); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateComputePipelines); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateDescriptorPool); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateDescriptorSetLayout); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateEvent); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateFramebuffer); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateGraphicsPipelines); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateImage); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateImageView); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreatePipelineCache); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreatePipelineLayout); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateRenderPass); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateSampler); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateSemaphore); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateShaderModule); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyBuffer); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyBufferView); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyCommandPool); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyDescriptorPool); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyDescriptorSetLayout); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyDevice); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyEvent); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyFramebuffer); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyImage); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyImageView); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyPipeline); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyPipelineCache); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyPipelineLayout); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyRenderPass); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroySampler); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroySemaphore); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroyShaderModule); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDeviceWaitIdle); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkEndCommandBuffer); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkFreeCommandBuffers); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkFreeDescriptorSets); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkFreeMemory); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkFlushMappedMemoryRanges); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkGetBufferMemoryRequirements); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkGetDeviceMemoryCommitment); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkGetDeviceQueue); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkGetEventStatus); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkGetFenceStatus); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkGetImageMemoryRequirements); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkGetImageSparseMemoryRequirements); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkGetImageSubresourceLayout); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkGetRenderAreaGranularity); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkInvalidateMappedMemoryRanges); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkMapMemory); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkMergePipelineCaches); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkQueueSubmit); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkQueueWaitIdle); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkResetCommandBuffer); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkResetCommandPool); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkResetDescriptorPool); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkResetFences); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkResetEvent); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkSetEvent); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkUnmapMemory); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkUpdateDescriptorSets); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkWaitForFences); + + // VK_KHR_display_swapchain + if (IsExtensionLoaded("VK_KHR_display_swapchain")) + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateSharedSwapchainsKHR); + + // VK_KHR_swapchain + if (IsExtensionLoaded("VK_KHR_swapchain")) + { + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkAcquireNextImageKHR); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkCreateSwapchainKHR); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkDestroySwapchainKHR); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkGetSwapchainImagesKHR); + NAZARA_VULKANRENDERER_LOAD_DEVICE(vkQueuePresentKHR); + } + } + catch (const std::exception& e) + { + NazaraError(String("Failed to query device function: ") + e.what()); + return false; + } + + #undef NAZARA_VULKANRENDERER_LOAD_DEVICE + + // And retains informations about queues + UInt32 maxFamilyIndex = 0; + m_enabledQueuesInfos.resize(createInfo.queueCreateInfoCount); + for (UInt32 i = 0; i < createInfo.queueCreateInfoCount; ++i) + { + const VkDeviceQueueCreateInfo& queueCreateInfo = createInfo.pQueueCreateInfos[i]; + QueueFamilyInfo& info = m_enabledQueuesInfos[i]; + + info.familyIndex = queueCreateInfo.queueFamilyIndex; + if (info.familyIndex > maxFamilyIndex) + maxFamilyIndex = info.familyIndex; + + const VkQueueFamilyProperties& queueProperties = queuesProperties[info.familyIndex]; + info.flags = queueProperties.queueFlags; + info.minImageTransferGranularity = queueProperties.minImageTransferGranularity; + info.timestampValidBits = queueProperties.timestampValidBits; + + info.queues.resize(queueCreateInfo.queueCount); + for (UInt32 queueIndex = 0; queueIndex < queueCreateInfo.queueCount; ++queueIndex) + { + QueueInfo& queueInfo = info.queues[queueIndex]; + queueInfo.familyInfo = &info; + queueInfo.priority = queueCreateInfo.pQueuePriorities[queueIndex]; + vkGetDeviceQueue(m_device, info.familyIndex, queueIndex, &queueInfo.queue); + } + } + + m_queuesByFamily.resize(maxFamilyIndex + 1); + for (const QueueFamilyInfo& familyInfo : m_enabledQueuesInfos) + m_queuesByFamily[familyInfo.familyIndex] = &familyInfo.queues; + + return true; + } + } +} diff --git a/src/Nazara/VulkanRenderer/VkInstance.cpp b/src/Nazara/VulkanRenderer/VkInstance.cpp new file mode 100644 index 000000000..411b8fa68 --- /dev/null +++ b/src/Nazara/VulkanRenderer/VkInstance.cpp @@ -0,0 +1,193 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include + +namespace Nz +{ + namespace Vk + { + bool Instance::Create(const VkInstanceCreateInfo& createInfo, const VkAllocationCallbacks* allocator) + { + m_lastErrorCode = Loader::vkCreateInstance(&createInfo, allocator, &m_instance); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to create Vulkan instance"); + return false; + } + + // Store the allocator to access them when needed + if (allocator) + m_allocator = *allocator; + else + m_allocator.pfnAllocation = nullptr; + + // Parse extensions and layers + for (UInt32 i = 0; i < createInfo.enabledExtensionCount; ++i) + m_loadedExtensions.insert(createInfo.ppEnabledExtensionNames[i]); + + for (UInt32 i = 0; i < createInfo.enabledLayerCount; ++i) + m_loadedLayers.insert(createInfo.ppEnabledLayerNames[i]); + + // And now load everything + #define NAZARA_VULKANRENDERER_LOAD_INSTANCE(func) func = reinterpret_cast(GetProcAddr(#func)) + + try + { + ErrorFlags flags(ErrorFlag_ThrowException, true); + + // Vulkan core + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkCreateDevice); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkDestroyInstance); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkEnumeratePhysicalDevices); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetDeviceProcAddr); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceFeatures); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceFormatProperties); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceImageFormatProperties); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceMemoryProperties); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceProperties); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceQueueFamilyProperties); + + // VK_KHR_display + if (IsExtensionLoaded("VK_KHR_display")) + { + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkCreateDisplayModeKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkCreateDisplayPlaneSurfaceKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetDisplayModePropertiesKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetDisplayPlaneCapabilitiesKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetDisplayPlaneSupportedDisplaysKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceDisplayPlanePropertiesKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceDisplayPropertiesKHR); + } + + // VK_KHR_surface + if (IsExtensionLoaded("VK_KHR_surface")) + { + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkDestroySurfaceKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceSurfaceCapabilitiesKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceSurfaceFormatsKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceSurfacePresentModesKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceSurfaceSupportKHR); + } + + // VK_EXT_debug_report + if (IsExtensionLoaded("VK_EXT_debug_report")) + { + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkCreateDebugReportCallbackEXT); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkDestroyDebugReportCallbackEXT); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkDebugReportMessageEXT); + } + + #ifdef VK_USE_PLATFORM_ANDROID_KHR + // VK_KHR_android_surface + if (IsExtensionLoaded("VK_KHR_android_surface")) + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkCreateAndroidSurfaceKHR); + #endif + + #ifdef VK_USE_PLATFORM_MIR_KHR + // VK_KHR_mir_surface + if (IsExtensionLoaded("VK_KHR_mir_surface")) + { + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkCreateMirSurfaceKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceMirPresentationSupportKHR); + } + #endif + + #ifdef VK_USE_PLATFORM_XCB_KHR + // VK_KHR_xcb_surface + if (IsExtensionLoaded("VK_KHR_xcb_surface")) + { + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkCreateXcbSurfaceKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceXcbPresentationSupportKHR); + } + #endif + + #ifdef VK_USE_PLATFORM_XLIB_KHR + // VK_KHR_xlib_surface + if (IsExtensionLoaded("VK_KHR_xlib_surface")) + { + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkCreateXlibSurfaceKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceXlibPresentationSupportKHR); + } + #endif + + #ifdef VK_USE_PLATFORM_WAYLAND_KHR + // VK_KHR_wayland_surface + if (IsExtensionLoaded("VK_KHR_wayland_surface")) + { + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkCreateWaylandSurfaceKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceWaylandPresentationSupportKHR); + } + #endif + + #ifdef VK_USE_PLATFORM_WIN32_KHR + // VK_KHR_win32_surface + if (IsExtensionLoaded("VK_KHR_win32_surface")) + { + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkCreateWin32SurfaceKHR); + NAZARA_VULKANRENDERER_LOAD_INSTANCE(vkGetPhysicalDeviceWin32PresentationSupportKHR); + } + #endif + } + catch (const std::exception& e) + { + NazaraError(String("Failed to query instance function: ") + e.what()); + return false; + } + + #undef NAZARA_VULKANRENDERER_LOAD_INSTANCE + + return true; + } + + bool Instance::EnumeratePhysicalDevices(std::vector* devices) + { + NazaraAssert(devices, "Invalid device vector"); + + // First, query physical device count + UInt32 deviceCount = 0; // Remember, Nz::UInt32 is a typedef on uint32_t + m_lastErrorCode = vkEnumeratePhysicalDevices(m_instance, &deviceCount, nullptr); + if (m_lastErrorCode != VkResult::VK_SUCCESS || deviceCount == 0) + { + NazaraError("Failed to query physical device count"); + return false; + } + + // Now we can get the list of the available physical device + devices->resize(deviceCount); + m_lastErrorCode = vkEnumeratePhysicalDevices(m_instance, &deviceCount, devices->data()); + if (m_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to query physical devices"); + return false; + } + + return true; + } + + bool Instance::GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice device, std::vector* queueFamilyProperties) + { + NazaraAssert(queueFamilyProperties, "Invalid device vector"); + + // First, query physical device count + UInt32 queueFamiliesCount = 0; // Remember, Nz::UInt32 is a typedef on uint32_t + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamiliesCount, nullptr); + if (queueFamiliesCount == 0) + { + NazaraError("Failed to query physical device count"); + return false; + } + + // Now we can get the list of the available physical device + queueFamilyProperties->resize(queueFamiliesCount); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamiliesCount, queueFamilyProperties->data()); + + return true; + } + + } +} diff --git a/src/Nazara/VulkanRenderer/VkLoader.cpp b/src/Nazara/VulkanRenderer/VkLoader.cpp new file mode 100644 index 000000000..0da9a930a --- /dev/null +++ b/src/Nazara/VulkanRenderer/VkLoader.cpp @@ -0,0 +1,117 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include + +namespace Nz +{ + namespace Vk + { + bool Loader::EnumerateInstanceExtensionProperties(std::vector* properties, const char* layerName) + { + NazaraAssert(properties, "Invalid device vector"); + + // First, query physical device count + UInt32 propertyCount = 0; // Remember, Nz::UInt32 is a typedef on uint32_t + s_lastErrorCode = vkEnumerateInstanceExtensionProperties(layerName, &propertyCount, properties->data()); + if (s_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to get instance extension properties count"); + return false; + } + + // Now we can get the list of the available physical device + properties->resize(propertyCount); + s_lastErrorCode = vkEnumerateInstanceExtensionProperties(layerName, &propertyCount, properties->data()); + if (s_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to enumerate instance extension properties"); + return false; + } + + return true; + } + + bool Loader::EnumerateInstanceLayerProperties(std::vector* properties) + { + NazaraAssert(properties, "Invalid device vector"); + + // First, query physical device count + UInt32 propertyCount = 0; // Remember, Nz::UInt32 is a typedef on uint32_t + s_lastErrorCode = vkEnumerateInstanceLayerProperties(&propertyCount, properties->data()); + if (s_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to get instance layer properties count"); + return false; + } + + // Now we can get the list of the available physical device + properties->resize(propertyCount); + s_lastErrorCode = vkEnumerateInstanceLayerProperties(&propertyCount, properties->data()); + if (s_lastErrorCode != VkResult::VK_SUCCESS) + { + NazaraError("Failed to enumerate instance layer properties"); + return false; + } + + return true; + } + + bool Loader::Initialize() + { + #ifdef NAZARA_PLATFORM_WINDOWS + s_vulkanLib.Load("vulkan-1.dll"); + #elif defined(NAZARA_PLATFORM_LINUX) + s_vulkanLib.Load("libvulkan.so"); + #else + #error Unhandled platform + #endif + + if (!s_vulkanLib.IsLoaded()) + { + NazaraError("Failed to open vulkan library: " + s_vulkanLib.GetLastError()); + return false; + } + + // vkGetInstanceProcAddr is the only function that's garantee to be exported + vkGetInstanceProcAddr = reinterpret_cast(s_vulkanLib.GetSymbol("vkGetInstanceProcAddr")); + if (!vkGetInstanceProcAddr) + { + NazaraError("Failed to get symbol \"vkGetInstanceProcAddr\": " + s_vulkanLib.GetLastError()); + return false; + } + + // all other functions should be loaded using vkGetInstanceProcAddr + #define NAZARA_VULKANRENDERER_LOAD_GLOBAL(func) func = reinterpret_cast(vkGetInstanceProcAddr(nullptr, #func)) + + NAZARA_VULKANRENDERER_LOAD_GLOBAL(vkCreateInstance); + NAZARA_VULKANRENDERER_LOAD_GLOBAL(vkEnumerateInstanceExtensionProperties); + NAZARA_VULKANRENDERER_LOAD_GLOBAL(vkEnumerateInstanceLayerProperties); + + #undef NAZARA_VULKANRENDERER_LOAD_GLOBAL + + s_lastErrorCode = VkResult::VK_SUCCESS; + + return true; + } + + #define NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL(func) PFN_##func Loader::func = nullptr + + NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL(vkCreateInstance); + NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL(vkEnumerateInstanceExtensionProperties); + NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL(vkEnumerateInstanceLayerProperties); + NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL(vkGetInstanceProcAddr); + + #undef NAZARA_VULKANRENDERER_GLOBAL_FUNCTION_IMPL + + DynLib Loader::s_vulkanLib; + VkResult Loader::s_lastErrorCode; + + void Loader::Uninitialize() + { + s_vulkanLib.Unload(); + } + } +} diff --git a/src/Nazara/VulkanRenderer/Vulkan.cpp b/src/Nazara/VulkanRenderer/Vulkan.cpp new file mode 100644 index 000000000..f80c3ec9a --- /dev/null +++ b/src/Nazara/VulkanRenderer/Vulkan.cpp @@ -0,0 +1,451 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + Vk::Instance& Vulkan::GetInstance() + { + return s_instance; + } + + const std::vector& Vulkan::GetPhysicalDevices() + { + return s_physDevices; + } + + const Vk::PhysicalDevice& Vulkan::GetPhysicalDeviceInfo(VkPhysicalDevice physDevice) + { + for (const Vk::PhysicalDevice& info : s_physDevices) + { + if (info.device == physDevice) + return info; + } + + // This cannot happen if physDevice is valid, as we retrieved every physical device + NazaraInternalError("Invalid physical device: " + String::Pointer(physDevice)); + + static Vk::PhysicalDevice dummy; + return dummy; + } + + bool Vulkan::Initialize() + { + if (s_moduleReferenceCounter > 0) + { + s_moduleReferenceCounter++; + return true; // Already initialized + } + + // Initialize module dependencies + if (!Utility::Initialize()) + { + NazaraError("Failed to initialize utility module"); + return false; + } + + s_moduleReferenceCounter++; + + CallOnExit onExit(Vulkan::Uninitialize); + + // Initialize module here + if (!Vk::Loader::Initialize()) + { + NazaraError("Failed to load Vulkan API, it may be not installed on your system"); + return false; + } + + String appName = "Another application made with Nazara Engine"; + String engineName = "Nazara Engine - Vulkan Renderer"; + UInt32 apiVersion = VK_MAKE_VERSION(1, 0, 8); + UInt32 appVersion = VK_MAKE_VERSION(1, 0, 0); + UInt32 engineVersion = VK_MAKE_VERSION(1, 0, 0); + + s_initializationParameters.GetStringParameter("VkAppInfo_OverrideApplicationName", &appName); + s_initializationParameters.GetStringParameter("VkAppInfo_OverrideEngineName", &engineName); + + bool bParam; + int iParam; + + if (s_initializationParameters.GetIntegerParameter("VkAppInfo_OverrideAPIVersion", &iParam)) + apiVersion = iParam; + + if (s_initializationParameters.GetIntegerParameter("VkAppInfo_OverrideApplicationVersion", &iParam)) + appVersion = iParam; + + if (s_initializationParameters.GetIntegerParameter("VkAppInfo_OverrideEngineVersion", &iParam)) + engineVersion = iParam; + + VkApplicationInfo appInfo = { + VK_STRUCTURE_TYPE_APPLICATION_INFO, + nullptr, + appName.GetConstBuffer(), + appVersion, + engineName.GetConstBuffer(), + engineVersion, + apiVersion + }; + + VkInstanceCreateFlags createFlags = 0; + + if (s_initializationParameters.GetIntegerParameter("VkInstanceInfo_OverrideCreateFlags", &iParam)) + createFlags = static_cast(iParam); + + std::vector enabledLayers; + std::vector enabledExtensions; + + if (!s_initializationParameters.GetBooleanParameter("VkInstanceInfo_OverrideEnabledLayers", &bParam) || !bParam) + { + //< Nazara default layers goes here + } + + std::vector additionalLayers; // Just to keep the String alive + if (s_initializationParameters.GetIntegerParameter("VkInstanceInfo_EnabledLayerCount", &iParam)) + { + additionalLayers.reserve(iParam); + for (int i = 0; i < iParam; ++i) + { + Nz::String parameterName = "VkInstanceInfo_EnabledLayer" + String::Number(i); + Nz::String layer; + if (s_initializationParameters.GetStringParameter(parameterName, &layer)) + { + additionalLayers.emplace_back(std::move(layer)); + enabledLayers.push_back(additionalLayers.back().GetConstBuffer()); + } + else + NazaraWarning("Parameter " + parameterName + " expected"); + } + } + + if (!s_initializationParameters.GetBooleanParameter("VkInstanceInfo_OverrideEnabledExtensions", &bParam) || !bParam) + { + enabledExtensions.push_back("VK_KHR_surface"); + + #ifdef VK_USE_PLATFORM_ANDROID_KHR + enabledExtensions.push_back("VK_KHR_android_surface"); + #endif + + #ifdef VK_USE_PLATFORM_MIR_KHR + enabledExtensions.push_back("VK_KHR_mir_surface"); + #endif + + #ifdef VK_USE_PLATFORM_XCB_KHR + enabledExtensions.push_back("VK_KHR_xcb_surface"); + #endif + + #ifdef VK_USE_PLATFORM_XLIB_KHR + enabledExtensions.push_back("VK_KHR_xlib_surface"); + #endif + + #ifdef VK_USE_PLATFORM_WAYLAND_KHR + enabledExtensions.push_back("VK_KHR_wayland_surface"); + #endif + + #ifdef VK_USE_PLATFORM_WIN32_KHR + enabledExtensions.push_back("VK_KHR_win32_surface"); + #endif + } + + std::vector additionalExtensions; // Just to keep the String alive + if (s_initializationParameters.GetIntegerParameter("VkInstanceInfo_EnabledExtensionCount", &iParam)) + { + additionalExtensions.reserve(iParam); + for (int i = 0; i < iParam; ++i) + { + Nz::String parameterName = "VkInstanceInfo_EnabledExtension" + String::Number(i); + Nz::String extension; + if (s_initializationParameters.GetStringParameter(parameterName, &extension)) + { + additionalExtensions.emplace_back(std::move(extension)); + enabledExtensions.push_back(additionalExtensions.back().GetConstBuffer()); + } + else + NazaraWarning("Parameter " + parameterName + " expected"); + } + } + + VkInstanceCreateInfo instanceInfo = { + VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, + nullptr, + createFlags, + &appInfo, + UInt32(enabledLayers.size()), + enabledLayers.data(), + UInt32(enabledExtensions.size()), + enabledExtensions.data() + }; + + if (!s_instance.Create(instanceInfo)) + { + NazaraError("Failed to create instance"); + return false; + } + + std::vector physDevices; + if (!s_instance.EnumeratePhysicalDevices(&physDevices)) + { + NazaraError("Failed to enumerate physical devices"); + return false; + } + + s_physDevices.reserve(physDevices.size()); + + for (std::size_t i = 0; i < physDevices.size(); ++i) + { + VkPhysicalDevice physDevice = physDevices[i]; + + Vk::PhysicalDevice deviceInfo; + if (!s_instance.GetPhysicalDeviceQueueFamilyProperties(physDevice, &deviceInfo.queues)) + { + NazaraWarning("Failed to query physical device queue family properties"); + continue; + } + + deviceInfo.device = physDevice; + + deviceInfo.features = s_instance.GetPhysicalDeviceFeatures(physDevice); + deviceInfo.memoryProperties = s_instance.GetPhysicalDeviceMemoryProperties(physDevice); + deviceInfo.properties = s_instance.GetPhysicalDeviceProperties(physDevice); + + s_physDevices.emplace_back(std::move(deviceInfo)); + } + + if (s_physDevices.empty()) + { + NazaraError("No valid physical device found"); + return false; + } + + onExit.Reset(); + + NazaraNotice("Initialized: Vulkan module"); + return true; + } + + bool Vulkan::IsInitialized() + { + return s_moduleReferenceCounter != 0; + } + + Vk::DeviceHandle Vulkan::CreateDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue) + { + Nz::ErrorFlags errFlags(ErrorFlag_ThrowException, true); + + std::vector queueFamilies; + s_instance.GetPhysicalDeviceQueueFamilyProperties(gpu, &queueFamilies); + + // Find a queue that supports graphics operations + UInt32 graphicsQueueNodeIndex = UINT32_MAX; + UInt32 presentQueueNodeIndex = UINT32_MAX; + UInt32 transfertQueueNodeFamily = UINT32_MAX; + for (UInt32 i = 0; i < queueFamilies.size(); i++) + { + bool supportPresentation = false; + if (!surface.GetSupportPresentation(gpu, i, &supportPresentation)) + NazaraWarning("Failed to get presentation support of queue family #" + String::Number(i)); + + if (queueFamilies[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) + { + if (graphicsQueueNodeIndex == UINT32_MAX) + graphicsQueueNodeIndex = i; + + if (supportPresentation) + { + graphicsQueueNodeIndex = i; + presentQueueNodeIndex = i; + break; + } + } + else if (supportPresentation) + presentQueueNodeIndex = i; + } + + for (UInt32 i = 0; i < queueFamilies.size(); i++) + { + if (queueFamilies[i].queueFlags & VK_QUEUE_TRANSFER_BIT) + { + transfertQueueNodeFamily = i; + if (transfertQueueNodeFamily != graphicsQueueNodeIndex) + break; + } + } + + std::array usedQueueFamilies = {graphicsQueueNodeIndex, presentQueueNodeIndex, transfertQueueNodeFamily}; + std::array priorities = {1.f, 1.f, 1.f}; + + std::vector queueCreateInfos; + for (UInt32 queueFamily : usedQueueFamilies) + { + auto it = std::find_if(queueCreateInfos.begin(), queueCreateInfos.end(), [queueFamily] (const VkDeviceQueueCreateInfo& createInfo) + { + return createInfo.queueFamilyIndex == queueFamily; + }); + + if (it == queueCreateInfos.end()) + { + VkDeviceQueueCreateInfo createInfo = { + VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + 0, // VkDeviceQueueCreateFlags flags; + queueFamily, // uint32_t queueFamilyIndex; + 1, // uint32_t queueCount; + priorities.data() // const float* pQueuePriorities; + }; + + queueCreateInfos.emplace_back(createInfo); + } + } + + + std::vector enabledLayers; + std::vector enabledExtensions; + + bool bParam; + int iParam; + + if (!s_initializationParameters.GetBooleanParameter("VkDeviceInfo_OverrideEnabledLayers", &bParam) || !bParam) + { + //< Nazara default layers goes here + } + + std::vector additionalLayers; // Just to keep the String alive + if (s_initializationParameters.GetIntegerParameter("VkDeviceInfo_EnabledLayerCount", &iParam)) + { + additionalLayers.reserve(iParam); + for (int i = 0; i < iParam; ++i) + { + Nz::String parameterName = "VkDeviceInfo_EnabledLayer" + String::Number(i); + Nz::String layer; + if (s_initializationParameters.GetStringParameter(parameterName, &layer)) + { + additionalLayers.emplace_back(std::move(layer)); + enabledLayers.push_back(additionalLayers.back().GetConstBuffer()); + } + else + NazaraWarning("Parameter " + parameterName + " expected"); + } + } + + if (!s_initializationParameters.GetBooleanParameter("VkDeviceInfo_OverrideEnabledExtensions", &bParam) || !bParam) + enabledExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); + + std::vector additionalExtensions; // Just to keep the String alive + if (s_initializationParameters.GetIntegerParameter("VkDeviceInfo_EnabledExtensionCount", &iParam)) + { + for (int i = 0; i < iParam; ++i) + { + Nz::String parameterName = "VkDeviceInfo_EnabledExtension" + String::Number(i); + Nz::String extension; + if (s_initializationParameters.GetStringParameter(parameterName, &extension)) + { + additionalExtensions.emplace_back(std::move(extension)); + enabledExtensions.push_back(additionalExtensions.back().GetConstBuffer()); + } + else + NazaraWarning("Parameter " + parameterName + " expected"); + } + } + + VkDeviceCreateInfo createInfo = { + VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, + nullptr, + 0, + UInt32(queueCreateInfos.size()), + queueCreateInfos.data(), + UInt32(enabledLayers.size()), + enabledLayers.data(), + UInt32(enabledExtensions.size()), + enabledExtensions.data(), + nullptr + }; + + ///TODO: First create then move + s_devices.emplace_back(s_instance); + + Vk::Device& device = s_devices.back(); + device.Create(gpu, createInfo); + + *presentableFamilyQueue = presentQueueNodeIndex; + + return device.CreateHandle(); + } + + Vk::DeviceHandle Vulkan::SelectDevice(VkPhysicalDevice gpu, const Vk::Surface& surface, UInt32* presentableFamilyQueue) + { + // First, try to find a device compatible with that surface + for (Vk::Device& device : s_devices) + { + if (device.GetPhysicalDevice() == gpu) + { + const std::vector& queueFamilyInfo = device.GetEnabledQueues(); + UInt32 presentableQueueFamilyIndex = UINT32_MAX; + for (Vk::Device::QueueFamilyInfo queueInfo : queueFamilyInfo) + { + bool supported = false; + if (surface.GetSupportPresentation(gpu, queueInfo.familyIndex, &supported) && supported) + { + if (presentableQueueFamilyIndex == UINT32_MAX || queueInfo.flags & VK_QUEUE_GRAPHICS_BIT) + { + presentableQueueFamilyIndex = queueInfo.familyIndex; + if (queueInfo.flags & VK_QUEUE_GRAPHICS_BIT) + break; + } + } + } + + if (presentableQueueFamilyIndex != UINT32_MAX) + *presentableFamilyQueue = presentableQueueFamilyIndex; + } + } + + // No device had support for that surface, create one + return CreateDevice(gpu, surface, presentableFamilyQueue); + } + + void Vulkan::SetParameters(const ParameterList& parameters) + { + s_initializationParameters = parameters; + } + + void Vulkan::Uninitialize() + { + if (s_moduleReferenceCounter != 1) + { + // Either the module is not initialized, either it was initialized multiple times + if (s_moduleReferenceCounter > 1) + s_moduleReferenceCounter--; + + return; + } + + s_moduleReferenceCounter = 0; + + // Uninitialize module here + s_devices.clear(); + s_instance.Destroy(); + + Vk::Loader::Uninitialize(); + + NazaraNotice("Uninitialized: Vulkan module"); + + // Free module dependencies + Utility::Uninitialize(); + } + + std::list Vulkan::s_devices; + std::vector Vulkan::s_physDevices; + Vk::Instance Vulkan::s_instance; + ParameterList Vulkan::s_initializationParameters; + unsigned int Vulkan::s_moduleReferenceCounter = 0; +} + diff --git a/src/Nazara/VulkanRenderer/VulkanRenderer.cpp b/src/Nazara/VulkanRenderer/VulkanRenderer.cpp new file mode 100644 index 000000000..6d6f4d055 --- /dev/null +++ b/src/Nazara/VulkanRenderer/VulkanRenderer.cpp @@ -0,0 +1,252 @@ +// Copyright (C) 2016 Jérôme Leclercq +// This file is part of the "Nazara Engine - Vulkan Renderer" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + bool VulkanRenderer::IsBetterThan(const RendererImpl* other) const + { + if (other->QueryAPI() == RenderAPI_Vulkan && QueryAPIVersion() < other->QueryAPIVersion()) + return false; + + return true; //< Vulkan FTW + } + + bool VulkanRenderer::Prepare(const ParameterList& parameters) + { + if (!Vk::Loader::Initialize()) + { + NazaraError("Failed to load Vulkan API, it may be not installed on your system"); + return false; + } + + String appName = "Another application made with Nazara Engine"; + String engineName = "Nazara Engine - Vulkan Renderer"; + + UInt32 apiVersion = APIVersion; + UInt32 appVersion = VK_MAKE_VERSION(1, 0, 0); + UInt32 engineVersion = VK_MAKE_VERSION(1, 0, 0); + + parameters.GetStringParameter("VkAppInfo_OverrideApplicationName", &appName); + parameters.GetStringParameter("VkAppInfo_OverrideEngineName", &engineName); + + bool bParam; + int iParam; + + if (parameters.GetIntegerParameter("VkAppInfo_OverrideAPIVersion", &iParam)) + apiVersion = iParam; + + if (parameters.GetIntegerParameter("VkAppInfo_OverrideApplicationVersion", &iParam)) + appVersion = iParam; + + if (parameters.GetIntegerParameter("VkAppInfo_OverrideEngineVersion", &iParam)) + engineVersion = iParam; + + VkApplicationInfo appInfo = { + VK_STRUCTURE_TYPE_APPLICATION_INFO, + nullptr, + appName.GetConstBuffer(), + appVersion, + engineName.GetConstBuffer(), + engineVersion, + apiVersion + }; + + VkInstanceCreateFlags createFlags = 0; + + if (parameters.GetIntegerParameter("VkInstanceInfo_OverrideCreateFlags", &iParam)) + createFlags = static_cast(iParam); + + std::vector enabledLayers; + std::vector enabledExtensions; + + if (!parameters.GetBooleanParameter("VkInstanceInfo_OverrideEnabledLayers", &bParam) || !bParam) + { + //< Nazara default layers goes here + } + + std::vector additionalLayers; // Just to keep the String alive + if (parameters.GetIntegerParameter("VkInstanceInfo_EnabledLayerCount", &iParam)) + { + additionalLayers.reserve(iParam); + for (int i = 0; i < iParam; ++i) + { + Nz::String parameterName = "VkInstanceInfo_EnabledLayer" + String::Number(i); + Nz::String layer; + if (parameters.GetStringParameter(parameterName, &layer)) + { + additionalLayers.emplace_back(std::move(layer)); + enabledLayers.push_back(additionalLayers.back().GetConstBuffer()); + } + else + NazaraWarning("Parameter " + parameterName + " expected"); + } + } + + if (!parameters.GetBooleanParameter("VkInstanceInfo_OverrideEnabledExtensions", &bParam) || !bParam) + { + enabledExtensions.push_back("VK_KHR_surface"); + + #ifdef VK_USE_PLATFORM_ANDROID_KHR + enabledExtensions.push_back("VK_KHR_android_surface"); + #endif + + #ifdef VK_USE_PLATFORM_MIR_KHR + enabledExtensions.push_back("VK_KHR_mir_surface"); + #endif + + #ifdef VK_USE_PLATFORM_XCB_KHR + enabledExtensions.push_back("VK_KHR_xcb_surface"); + #endif + + #ifdef VK_USE_PLATFORM_XLIB_KHR + enabledExtensions.push_back("VK_KHR_xlib_surface"); + #endif + + #ifdef VK_USE_PLATFORM_WAYLAND_KHR + enabledExtensions.push_back("VK_KHR_wayland_surface"); + #endif + + #ifdef VK_USE_PLATFORM_WIN32_KHR + enabledExtensions.push_back("VK_KHR_win32_surface"); + #endif + } + + std::vector additionalExtensions; // Just to keep the String alive + if (parameters.GetIntegerParameter("VkInstanceInfo_EnabledExtensionCount", &iParam)) + { + additionalExtensions.reserve(iParam); + for (int i = 0; i < iParam; ++i) + { + Nz::String parameterName = "VkInstanceInfo_EnabledExtension" + String::Number(i); + Nz::String extension; + if (parameters.GetStringParameter(parameterName, &extension)) + { + additionalExtensions.emplace_back(std::move(extension)); + enabledExtensions.push_back(additionalExtensions.back().GetConstBuffer()); + } + else + NazaraWarning("Parameter " + parameterName + " expected"); + } + } + + VkInstanceCreateInfo instanceInfo = + { + VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType; + nullptr, // const void* pNext; + createFlags, // VkInstanceCreateFlags flags; + &appInfo, // const VkApplicationInfo* pApplicationInfo; + UInt32(enabledLayers.size()), // uint32_t enabledLayerCount; + enabledLayers.data(), // const char* const* ppEnabledLayerNames; + UInt32(enabledExtensions.size()), // uint32_t enabledExtensionCount; + enabledExtensions.data() // const char* const* ppEnabledExtensionNames; + }; + + if (!m_instance.Create(instanceInfo)) + { + NazaraError("Failed to create instance"); + return false; + } + + m_apiVersion = apiVersion; + + std::vector physDevices; + if (!m_instance.EnumeratePhysicalDevices(&physDevices)) + { + NazaraError("Failed to enumerate physical devices"); + return false; + } + + m_physDevices.reserve(physDevices.size()); + for (std::size_t i = 0; i < physDevices.size(); ++i) + { + VkPhysicalDevice physDevice = physDevices[i]; + + Vk::PhysicalDevice deviceInfo; + if (!m_instance.GetPhysicalDeviceQueueFamilyProperties(physDevice, &deviceInfo.queues)) + { + NazaraWarning("Failed to query physical device queue family properties for " + String(deviceInfo.properties.deviceName) + " (0x" + String::Number(deviceInfo.properties.deviceID, 16) + ')'); + continue; + } + + deviceInfo.device = physDevice; + + deviceInfo.features = m_instance.GetPhysicalDeviceFeatures(physDevice); + deviceInfo.memoryProperties = m_instance.GetPhysicalDeviceMemoryProperties(physDevice); + deviceInfo.properties = m_instance.GetPhysicalDeviceProperties(physDevice); + + m_physDevices.emplace_back(std::move(deviceInfo)); + } + + if (m_physDevices.empty()) + { + NazaraError("No valid physical device found"); + return false; + } + + return true; + } + + RenderAPI VulkanRenderer::QueryAPI() const + { + return RenderAPI_Vulkan; + } + + String VulkanRenderer::QueryAPIString() const + { + StringStream ss; + ss << "Vulkan renderer " << VK_VERSION_MAJOR(m_apiVersion) << '.' << VK_VERSION_MINOR(m_apiVersion) << '.' << VK_VERSION_PATCH(m_apiVersion); + + return ss; + } + + UInt32 VulkanRenderer::QueryAPIVersion() const + { + return m_apiVersion; + } + + std::vector VulkanRenderer::QueryRenderDevices() const + { + std::vector devices; + devices.reserve(m_physDevices.size()); + + for (const Vk::PhysicalDevice& physDevice : m_physDevices) + { + RenderDevice device; + device.name = physDevice.properties.deviceName; + + switch (physDevice.properties.deviceType) + { + case VK_PHYSICAL_DEVICE_TYPE_CPU: + device.type = RenderDeviceType_Software; + break; + + case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: + device.type = RenderDeviceType_Dedicated; + break; + + case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: + device.type = RenderDeviceType_Integrated; + break; + + case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: + device.type = RenderDeviceType_Virtual; + break; + + default: + NazaraWarning("Device " + device.name + " has handled device type (0x" + String::Number(physDevice.properties.deviceType, 16) + ')'); + case VK_PHYSICAL_DEVICE_TYPE_OTHER: + device.type = RenderDeviceType_Unknown; + break; + } + + devices.emplace_back(device); + } + + return devices; + } +}