From 4abefc3e9372285cfc8419aef3f47ed8af568b2a Mon Sep 17 00:00:00 2001 From: Lynix Date: Mon, 1 Jul 2013 16:14:29 +0200 Subject: [PATCH] Reworked IndexBuffer, Vertex[Buffer|Declaration|Structs] Former-commit-id: e3f637f2680afda57a444f73b8f7ad681bb1b8a5 --- include/Nazara/Core/Resource.hpp | 1 - include/Nazara/Renderer/OpenGL.hpp | 4 +- include/Nazara/Renderer/Renderer.hpp | 10 +- include/Nazara/Utility/AbstractBuffer.hpp | 2 - include/Nazara/Utility/Buffer.hpp | 17 +- include/Nazara/Utility/Enums.hpp | 95 ++-- include/Nazara/Utility/IndexBuffer.hpp | 29 +- include/Nazara/Utility/Mesh.hpp | 2 - include/Nazara/Utility/VertexBuffer.hpp | 25 +- include/Nazara/Utility/VertexDeclaration.hpp | 62 ++- include/Nazara/Utility/VertexStruct.hpp | 71 +-- src/Nazara/Core/Resource.cpp | 6 - src/Nazara/Graphics/Loaders/OBJ/Loader.cpp | 4 +- src/Nazara/Graphics/SkyboxBackground.cpp | 23 +- src/Nazara/Renderer/DebugDrawer.cpp | 19 +- src/Nazara/Renderer/GLSLShader.cpp | 32 +- src/Nazara/Renderer/HardwareBuffer.cpp | 5 - src/Nazara/Renderer/HardwareBuffer.hpp | 2 - src/Nazara/Renderer/OpenGL.cpp | 48 +- src/Nazara/Renderer/Renderer.cpp | 339 ++++++------- src/Nazara/Utility/Buffer.cpp | 84 +--- src/Nazara/Utility/Image.cpp | 7 +- src/Nazara/Utility/IndexBuffer.cpp | 210 ++++----- src/Nazara/Utility/IndexMapper.cpp | 68 ++- src/Nazara/Utility/Loaders/MD2/Loader.cpp | 4 +- src/Nazara/Utility/Loaders/MD5Mesh/Parser.cpp | 4 +- src/Nazara/Utility/Mesh.cpp | 42 +- src/Nazara/Utility/SoftwareBuffer.cpp | 5 - src/Nazara/Utility/SoftwareBuffer.hpp | 2 - src/Nazara/Utility/Utility.cpp | 10 + src/Nazara/Utility/VertexBuffer.cpp | 136 ++++-- src/Nazara/Utility/VertexDeclaration.cpp | 446 +++++------------- 32 files changed, 713 insertions(+), 1101 deletions(-) diff --git a/include/Nazara/Core/Resource.hpp b/include/Nazara/Core/Resource.hpp index 45acbdc64..efc972d7b 100644 --- a/include/Nazara/Core/Resource.hpp +++ b/include/Nazara/Core/Resource.hpp @@ -40,7 +40,6 @@ class NAZARA_API NzResource { public: NzResource(bool persistent = true); - NzResource(const NzResource& resource); virtual ~NzResource(); void AddResourceListener(NzResourceListener* listener, int index = 0) const; diff --git a/include/Nazara/Renderer/OpenGL.hpp b/include/Nazara/Renderer/OpenGL.hpp index 295f92377..68b0c514f 100644 --- a/include/Nazara/Renderer/OpenGL.hpp +++ b/include/Nazara/Renderer/OpenGL.hpp @@ -102,7 +102,8 @@ class NAZARA_API NzOpenGL static void Uninitialize(); static GLenum Attachment[nzAttachmentPoint_Max+1]; - static nzUInt8 AttributeIndex[nzElementUsage_Max+1]; + static nzUInt8 AttributeIndex[nzAttributeUsage_Max+1]; + static GLenum AttributeType[nzAttributeType_Max+1]; static GLenum BlendFunc[nzBlendFunc_Max+1]; static GLenum BufferLock[nzBufferAccess_Max+1]; static GLenum BufferLockRange[nzBufferAccess_Max+1]; @@ -110,7 +111,6 @@ class NAZARA_API NzOpenGL static GLenum BufferTargetBinding[nzBufferType_Max+1]; static GLenum BufferUsage[nzBufferUsage_Max+1]; static GLenum CubemapFace[6]; // Un cube possède six faces et ça n'est pas prêt de changer - static GLenum ElementType[nzElementType_Max+1]; static GLenum FaceCulling[nzFaceCulling_Max+1]; static GLenum FaceFilling[nzFaceFilling_Max+1]; static GLenum PrimitiveMode[nzPrimitiveMode_Max+1]; diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index 513926bf2..817e537ac 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -15,6 +15,7 @@ #include #include #include +#include class NzColor; class NzContext; @@ -27,11 +28,6 @@ class NzVertexBuffer; class NAZARA_API NzRenderer { public: - struct InstancingData - { - NzMatrix4f worldMatrix; - }; - NzRenderer() = delete; ~NzRenderer() = delete; @@ -52,6 +48,7 @@ class NAZARA_API NzRenderer static nzUInt8 GetMaxAnisotropyLevel(); static unsigned int GetMaxRenderTargets(); static unsigned int GetMaxTextureUnits(); + static unsigned int GetMaxVertexAttribs(); static float GetPointSize(); static const NzRenderStates& GetRenderStates(); static NzRectui GetScissorRect(); @@ -75,7 +72,8 @@ class NAZARA_API NzRenderer static void SetFaceCulling(nzFaceCulling cullingMode); static void SetFaceFilling(nzFaceFilling fillingMode); static void SetIndexBuffer(const NzIndexBuffer* indexBuffer); - static void SetInstancingData(const InstancingData* instancingData, unsigned int instanceCount); + static void SetInstancingData(const void* instancingDatainstancingData, unsigned int instanceCount); + static void SetInstancingDeclaration(const NzVertexDeclaration* declaration, unsigned int* newMaxInstanceCount); static void SetLineWidth(float size); static void SetMatrix(nzMatrixType type, const NzMatrix4f& matrix); static void SetPointSize(float size); diff --git a/include/Nazara/Utility/AbstractBuffer.hpp b/include/Nazara/Utility/AbstractBuffer.hpp index 3c33f5061..642154b57 100644 --- a/include/Nazara/Utility/AbstractBuffer.hpp +++ b/include/Nazara/Utility/AbstractBuffer.hpp @@ -20,8 +20,6 @@ class NAZARA_API NzAbstractBuffer virtual bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard = false) = 0; - virtual void* GetPointer() = 0; - virtual bool IsHardware() const = 0; virtual void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0) = 0; diff --git a/include/Nazara/Utility/Buffer.hpp b/include/Nazara/Utility/Buffer.hpp index 89a9f3608..9b2201846 100644 --- a/include/Nazara/Utility/Buffer.hpp +++ b/include/Nazara/Utility/Buffer.hpp @@ -28,31 +28,27 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable using BufferFunction = NzAbstractBuffer* (*)(NzBuffer* parent, nzBufferType type); NzBuffer(nzBufferType type); - NzBuffer(nzBufferType type, unsigned int length, nzUInt8 typeSize, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); + NzBuffer(nzBufferType type, unsigned int size, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); ~NzBuffer(); bool CopyContent(const NzBuffer& buffer); - bool Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); + bool Create(unsigned int size, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); void Destroy(); - bool Fill(const void* data, unsigned int offset, unsigned int length, bool forceDiscard = false); + bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard = false); NzAbstractBuffer* GetImpl() const; - unsigned int GetLength() const; - void* GetPointer(); - const void* GetPointer() const; unsigned int GetSize() const; nzBufferStorage GetStorage() const; nzBufferType GetType() const; - nzUInt8 GetTypeSize() const; nzBufferUsage GetUsage() const; bool IsHardware() const; bool IsValid() const; - void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); - void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0) const; + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0); + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0) const; bool SetStorage(nzBufferStorage storage); @@ -68,9 +64,8 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable nzBufferStorage m_storage; nzBufferType m_type; nzBufferUsage m_usage; - nzUInt8 m_typeSize; NzAbstractBuffer* m_impl; - unsigned int m_length; + unsigned int m_size; static BufferFunction s_bufferFunctions[nzBufferStorage_Max+1]; }; diff --git a/include/Nazara/Utility/Enums.hpp b/include/Nazara/Utility/Enums.hpp index 388c09d93..f51f15803 100644 --- a/include/Nazara/Utility/Enums.hpp +++ b/include/Nazara/Utility/Enums.hpp @@ -15,6 +15,48 @@ enum nzAnimationType nzAnimationType_Max = nzAnimationType_Static }; +enum nzAttributeType +{ + nzAttributeType_Color, + nzAttributeType_Double1, + nzAttributeType_Double2, + nzAttributeType_Double3, + nzAttributeType_Double4, + nzAttributeType_Float1, + nzAttributeType_Float2, + nzAttributeType_Float3, + nzAttributeType_Float4, + + nzAttributeType_Max = nzAttributeType_Float4 +}; + +enum nzAttributeUsage +{ + nzAttributeUsage_InstanceData0, + nzAttributeUsage_InstanceData1, + nzAttributeUsage_InstanceData2, + nzAttributeUsage_InstanceData3, + nzAttributeUsage_InstanceData4, + nzAttributeUsage_InstanceData5, + nzAttributeUsage_Normal, + nzAttributeUsage_Position, + nzAttributeUsage_Tangent, + nzAttributeUsage_TexCoord, + nzAttributeUsage_Userdata0, + nzAttributeUsage_Userdata1, + nzAttributeUsage_Userdata2, + nzAttributeUsage_Userdata3, + nzAttributeUsage_Userdata4, + nzAttributeUsage_Userdata5, + + nzAttributeUsage_FirstInstanceData = nzAttributeUsage_InstanceData0, + nzAttributeUsage_FirstVertexData = nzAttributeUsage_Normal, + nzAttributeUsage_LastInstanceData = nzAttributeUsage_InstanceData5, + nzAttributeUsage_LastVertexData = nzAttributeUsage_Userdata5, + + nzAttributeUsage_Max = nzAttributeUsage_Userdata5 +}; + enum nzBufferAccess { nzBufferAccess_DiscardAndWrite, @@ -27,7 +69,7 @@ enum nzBufferAccess enum nzBufferStorage { - //nzBufferStorage_Both, + //nzBufferStorage_Both, ///TODO nzBufferStorage_Hardware, nzBufferStorage_Software, @@ -64,40 +106,6 @@ enum nzCubemapFace nzCubemapFace_Max = nzCubemapFace_NegativeZ }; -enum nzElementStream -{ - nzElementStream_VertexData, - nzElementStream_InstancedData, - - nzElementStream_Max = nzElementStream_InstancedData -}; - -enum nzElementType -{ - nzElementType_Color, - nzElementType_Double1, - nzElementType_Double2, - nzElementType_Double3, - nzElementType_Double4, - nzElementType_Float1, - nzElementType_Float2, - nzElementType_Float3, - nzElementType_Float4, - - nzElementType_Max = nzElementType_Float4 -}; - -enum nzElementUsage -{ - nzElementUsage_Diffuse, - nzElementUsage_Normal, - nzElementUsage_Position, - nzElementUsage_Tangent, - nzElementUsage_TexCoord, - - nzElementUsage_Max = nzElementUsage_TexCoord -}; - enum nzEventType { nzEventType_GainedFocus, @@ -209,6 +217,23 @@ enum nzPrimitiveMode nzPrimitiveMode_Max = nzPrimitiveMode_TriangleFan }; +enum nzVertexLayout +{ + // Déclarations destinées au rendu + nzVertexLayout_XY, + nzVertexLayout_XY_UV, + nzVertexLayout_XYZ, + nzVertexLayout_XYZ_Normal, + nzVertexLayout_XYZ_Normal_UV, + nzVertexLayout_XYZ_Normal_UV_Tangent, + nzVertexLayout_XYZ_UV, + + // Déclarations destinées à l'instancing + nzVertexLayout_Matrix4, + + nzVertexLayout_Max = nzVertexLayout_Matrix4 +}; + enum nzWindowCursor { nzWindowCursor_None, diff --git a/include/Nazara/Utility/IndexBuffer.hpp b/include/Nazara/Utility/IndexBuffer.hpp index 2904a73a6..24286b349 100644 --- a/include/Nazara/Utility/IndexBuffer.hpp +++ b/include/Nazara/Utility/IndexBuffer.hpp @@ -20,28 +20,30 @@ using NzIndexBufferRef = NzResourceRef; class NAZARA_API NzIndexBuffer : public NzResource { public: - NzIndexBuffer(NzBuffer* buffer, unsigned int startIndex, unsigned int indexCount); - NzIndexBuffer(unsigned int length, bool largeIndices = false, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); - NzIndexBuffer(const NzIndexBuffer& indexBuffer); - ~NzIndexBuffer(); + NzIndexBuffer(bool largeIndices, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset); + NzIndexBuffer(bool largeIndices, unsigned int length, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); + NzIndexBuffer(const NzIndexBuffer& vertexBuffer); + ~NzIndexBuffer() = default; unsigned int ComputeCacheMissCount() const; - bool Fill(const void* data, unsigned int offset, unsigned int length, bool forceDiscard = false); + bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard = false); + bool FillIndices(const void* data, unsigned int startIndex, unsigned int length, bool forceDiscard = false); NzBuffer* GetBuffer() const; + unsigned int GetEndOffset() const; unsigned int GetIndexCount() const; - void* GetPointer(); - const void* GetPointer() const; - unsigned int GetStartIndex() const; + unsigned int GetStride() const; + unsigned int GetStartOffset() const; bool HasLargeIndices() const; bool IsHardware() const; - bool IsSequential() const; - void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); - void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0) const; + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0); + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0) const; + void* MapIndices(nzBufferAccess access, unsigned int startVertex = 0, unsigned int length = 0); + void* MapIndices(nzBufferAccess access, unsigned int startVertex = 0, unsigned int length = 0) const; void Optimize(); @@ -51,9 +53,10 @@ class NAZARA_API NzIndexBuffer : public NzResource private: NzBufferRef m_buffer; - bool m_ownsBuffer; + bool m_largeIndices; + unsigned int m_endOffset; unsigned int m_indexCount; - unsigned int m_startIndex; + unsigned int m_startOffset; }; #endif // NAZARA_INDEXBUFFER_HPP diff --git a/include/Nazara/Utility/Mesh.hpp b/include/Nazara/Utility/Mesh.hpp index 5dae25937..c025318f7 100644 --- a/include/Nazara/Utility/Mesh.hpp +++ b/include/Nazara/Utility/Mesh.hpp @@ -113,8 +113,6 @@ class NAZARA_API NzMesh : public NzResource, NzResourceListener void Transform(const NzMatrix4f& matrix); - static const NzVertexDeclaration* GetDeclaration(); - private: void OnResourceReleased(const NzResource* resource, int index) override; diff --git a/include/Nazara/Utility/VertexBuffer.hpp b/include/Nazara/Utility/VertexBuffer.hpp index 22112c5b9..2f2b929e5 100644 --- a/include/Nazara/Utility/VertexBuffer.hpp +++ b/include/Nazara/Utility/VertexBuffer.hpp @@ -21,35 +21,38 @@ using NzVertexBufferRef = NzResourceRef; class NAZARA_API NzVertexBuffer : public NzResource { public: - NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer, unsigned int startVertex, unsigned int vertexCount); + NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset); NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); NzVertexBuffer(const NzVertexBuffer& vertexBuffer); - ~NzVertexBuffer(); + ~NzVertexBuffer() = default; - bool Fill(const void* data, unsigned int offset, unsigned int length, bool forceDiscard = false); + bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard = false); + bool FillVertices(const void* data, unsigned int startVertex, unsigned int length, bool forceDiscard = false); NzBuffer* GetBuffer() const; - void* GetPointer(); - const void* GetPointer() const; - unsigned int GetStartVertex() const; - nzUInt8 GetTypeSize() const; + unsigned int GetEndOffset() const; + unsigned int GetStartOffset() const; + unsigned int GetStride() const; unsigned int GetVertexCount() const; const NzVertexDeclaration* GetVertexDeclaration() const; bool IsHardware() const; - void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); - void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0) const; + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0); + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0) const; + void* MapVertices(nzBufferAccess access, unsigned int startVertex = 0, unsigned int length = 0); + void* MapVertices(nzBufferAccess access, unsigned int startVertex = 0, unsigned int length = 0) const; bool SetStorage(nzBufferStorage storage); + void SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration); void Unmap() const; private: NzBufferRef m_buffer; NzVertexDeclarationConstRef m_vertexDeclaration; - bool m_ownsBuffer; - unsigned int m_startVertex; + unsigned int m_endOffset; + unsigned int m_startOffset; unsigned int m_vertexCount; }; diff --git a/include/Nazara/Utility/VertexDeclaration.hpp b/include/Nazara/Utility/VertexDeclaration.hpp index d14023439..1d39c1ab3 100644 --- a/include/Nazara/Utility/VertexDeclaration.hpp +++ b/include/Nazara/Utility/VertexDeclaration.hpp @@ -12,15 +12,6 @@ #include #include -struct NzVertexElement -{ - unsigned int offset; - unsigned int usageIndex = 0; - nzElementStream stream = nzElementStream_VertexData; - nzElementType type; - nzElementUsage usage; -}; - class NzVertexDeclaration; using NzVertexDeclarationConstRef = NzResourceRef; @@ -30,38 +21,45 @@ struct NzVertexDeclarationImpl; class NAZARA_API NzVertexDeclaration : public NzResource { + friend class NzUtility; + public: - NzVertexDeclaration() = default; - NzVertexDeclaration(const NzVertexElement* elements, unsigned int elementCount); - NzVertexDeclaration(const NzVertexDeclaration& declaration); - NzVertexDeclaration(NzVertexDeclaration&& declaration) noexcept; - ~NzVertexDeclaration(); + NzVertexDeclaration(); + NzVertexDeclaration(NzVertexDeclaration& declaration); + ~NzVertexDeclaration() = default; - bool Create(const NzVertexElement* elements, unsigned int elementCount); - void Destroy(); + void DisableAttribute(nzAttributeUsage usage); + void EnableAttribute(nzAttributeUsage usage, nzAttributeType type, unsigned int offset); - const NzVertexElement* GetElement(unsigned int i) const; - const NzVertexElement* GetElement(nzElementStream stream, unsigned int i) const; - const NzVertexElement* GetElement(nzElementStream stream, nzElementUsage usage, unsigned int usageIndex = 0) const; - unsigned int GetElementCount() const; - unsigned int GetElementCount(nzElementStream stream) const; - unsigned int GetStride(nzElementStream stream) const; + void GetAttribute(nzAttributeUsage usage, bool* enabled, nzAttributeType* type, unsigned int* offset) const; + unsigned int GetStride() const; - bool HasElement(unsigned int i) const; - bool HasElement(nzElementStream stream, unsigned int i) const; - bool HasElement(nzElementStream stream, nzElementUsage usage, unsigned int usageIndex = 0) const; - bool HasStream(nzElementStream stream) const; - - bool IsValid() const; + void SetStride(unsigned int stride); NzVertexDeclaration& operator=(const NzVertexDeclaration& declaration); - NzVertexDeclaration& operator=(NzVertexDeclaration&& declaration) noexcept; - static unsigned int GetElementCount(nzElementType type); - static unsigned int GetElementSize(nzElementType type); + static NzVertexDeclaration* Get(nzVertexLayout layout); + static unsigned int GetAttributeSize(nzAttributeType type); private: - NzVertexDeclarationImpl* m_sharedImpl = nullptr; + static bool Initialize(); + static void Uninitialize(); + + struct Attribute + { + nzAttributeType type; + bool enabled = false; + unsigned int offset; + // Il serait aussi possible de préciser le stride de façon indépendante, ce que je ne permets pas + // pour décomplexifier l'interface en enlevant quelque chose d'inutile. + // Si vous pensez que ça peut être utile, n'hésitez pas à me le faire savoir ! + // PS: Même cas pour le diviseur (instancing) + }; + + Attribute m_attributes[nzAttributeUsage_Max+1]; + unsigned int m_stride; + + static NzVertexDeclaration s_declarations[nzVertexLayout_Max+1]; }; #endif // NAZARA_VERTEXDECLARATION_HPP diff --git a/include/Nazara/Utility/VertexStruct.hpp b/include/Nazara/Utility/VertexStruct.hpp index 482caf398..1b22a9fac 100644 --- a/include/Nazara/Utility/VertexStruct.hpp +++ b/include/Nazara/Utility/VertexStruct.hpp @@ -15,9 +15,9 @@ struct NzVertexStruct_XY NzVector2f position; }; -struct NzVertexStruct_XY_Color : public NzVertexStruct_XY +struct NzVertexStruct_XY_UV : public NzVertexStruct_XY { - NzVector3f color; + NzVector2f uv; }; ///////////////////////////////////////// @@ -27,87 +27,24 @@ struct NzVertexStruct_XYZ NzVector3f position; }; -struct NzVertexStruct_XYZ_Color : public NzVertexStruct_XYZ -{ - NzVector3f color; -}; - struct NzVertexStruct_XYZ_Normal : public NzVertexStruct_XYZ { NzVector3f normal; }; -struct NzVertexStruct_XYZ_Normal_Color : public NzVertexStruct_XYZ_Normal -{ - NzVector3f color; -}; - -///////////////////////////////////////// - -struct NzVertexStruct_XYZ_UV : public NzVertexStruct_XYZ -{ - NzVector2f uv; -}; - -struct NzVertexStruct_XYZ_UV_Color : public NzVertexStruct_XYZ_UV -{ - NzVector3f color; -}; - struct NzVertexStruct_XYZ_Normal_UV : public NzVertexStruct_XYZ_Normal { NzVector2f uv; }; -struct NzVertexStruct_XYZ_Normal_UV_Color : public NzVertexStruct_XYZ_Normal_UV -{ - NzVector3f color; -}; - struct NzVertexStruct_XYZ_Normal_UV_Tangent : public NzVertexStruct_XYZ_Normal_UV { NzVector3f tangent; }; -struct NzVertexStruct_XYZ_Normal_UV_Tangent_Color : public NzVertexStruct_XYZ_Normal_UV_Tangent +struct NzVertexStruct_XYZ_UV : public NzVertexStruct_XYZ { - NzVector3f color; -}; - -///////////////////////////////////////// - -struct NzVertexStruct_XYZ_UV_UV2 : public NzVertexStruct_XYZ_UV -{ - NzVector2f uv2; -}; - -struct NzVertexStruct_XYZ_UV_UV2_Color : public NzVertexStruct_XYZ_UV_UV2 -{ - NzVector3f color; -}; - -///////////////////////////////////////// - -struct NzVertexStruct_XYZ_Normal_UV_UV2 : public NzVertexStruct_XYZ_Normal_UV -{ - NzVector2f uv2; -}; - -struct NzVertexStruct_XYZ_Normal_UV_UV2_Color : public NzVertexStruct_XYZ_Normal_UV_UV2 -{ - NzVector3f color; -}; - -struct NzVertexStruct_XYZ_Normal_UV_UV2_Tangent : public NzVertexStruct_XYZ_Normal_UV_UV2 -{ - NzVector3f tangent; -}; - -///////////////////////////////////////// - -struct NzVertexStruct_XYZ_Normal_UV_UV2_Tangent_Color : public NzVertexStruct_XYZ_Normal_UV_UV2_Tangent -{ - NzVector3f color; + NzVector2f uv; }; #endif // NAZARA_VERTEXSTRUCT_HPP diff --git a/src/Nazara/Core/Resource.cpp b/src/Nazara/Core/Resource.cpp index ead8fb8f6..c3c744966 100644 --- a/src/Nazara/Core/Resource.cpp +++ b/src/Nazara/Core/Resource.cpp @@ -16,12 +16,6 @@ m_resourceReferenceCount(0) { } -NzResource::NzResource(const NzResource& resource) : -m_resourcePersistent(resource.m_resourcePersistent.load()), -m_resourceReferenceCount(0) -{ -} - NzResource::~NzResource() { EnsureResourceListenerUpdate(); diff --git a/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp b/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp index d34a20f63..f222732d6 100644 --- a/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp +++ b/src/Nazara/Graphics/Loaders/OBJ/Loader.cpp @@ -97,10 +97,10 @@ namespace } } - std::unique_ptr indexBuffer(new NzIndexBuffer(indices.size(), vertexCount > std::numeric_limits::max(), parameters.mesh.storage, nzBufferUsage_Static)); + std::unique_ptr indexBuffer(new NzIndexBuffer(vertexCount > std::numeric_limits::max(), indices.size(), parameters.mesh.storage, nzBufferUsage_Static)); indexBuffer->SetPersistent(false); - std::unique_ptr vertexBuffer(new NzVertexBuffer(NzMesh::GetDeclaration(), vertexCount, parameters.mesh.storage, nzBufferUsage_Static)); + std::unique_ptr vertexBuffer(new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent), vertexCount, parameters.mesh.storage, nzBufferUsage_Static)); vertexBuffer->SetPersistent(false); // Remplissage des indices diff --git a/src/Nazara/Graphics/SkyboxBackground.cpp b/src/Nazara/Graphics/SkyboxBackground.cpp index 6cecccebd..58ed45091 100644 --- a/src/Nazara/Graphics/SkyboxBackground.cpp +++ b/src/Nazara/Graphics/SkyboxBackground.cpp @@ -22,7 +22,7 @@ namespace { NzIndexBuffer* BuildIndexBuffer() { - std::unique_ptr indexBuffer(new NzIndexBuffer(36, false, nzBufferStorage_Hardware, nzBufferUsage_Static)); + std::unique_ptr indexBuffer(new NzIndexBuffer(false, 36, nzBufferStorage_Hardware, nzBufferUsage_Static)); indexBuffer->SetPersistent(false); nzUInt16 indices[6*6] = @@ -35,7 +35,7 @@ namespace 1, 6, 2, 1, 5, 6 }; - if (!indexBuffer->Fill(indices, 0, 36)) + if (!indexBuffer->FillIndices(indices, 0, 36)) { NazaraError("Failed to create vertex buffer"); return nullptr; @@ -125,22 +125,7 @@ namespace NzVertexBuffer* BuildVertexBuffer() { - std::unique_ptr declaration(new NzVertexDeclaration); - declaration->SetPersistent(false); - - NzVertexElement elements; - elements.offset = 0; - elements.type = nzElementType_Float3; - elements.usage = nzElementUsage_Position; - - if (!declaration->Create(&elements, 1)) - { - NazaraError("Failed to create declaration"); - return nullptr; - } - - std::unique_ptr vertexBuffer(new NzVertexBuffer(declaration.get(), 8, nzBufferStorage_Hardware, nzBufferUsage_Static)); - declaration.release(); + std::unique_ptr vertexBuffer(new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ), 8, nzBufferStorage_Hardware, nzBufferUsage_Static)); vertexBuffer->SetPersistent(false); float vertices[8*(sizeof(float)*3)] = @@ -155,7 +140,7 @@ namespace 1.0, 1.0, -1.0, }; - if (!vertexBuffer->Fill(vertices, 0, 8)) + if (!vertexBuffer->FillVertices(vertices, 0, 8)) { NazaraError("Failed to create vertex buffer"); return nullptr; diff --git a/src/Nazara/Renderer/DebugDrawer.cpp b/src/Nazara/Renderer/DebugDrawer.cpp index 8c73f52af..28d8a1772 100644 --- a/src/Nazara/Renderer/DebugDrawer.cpp +++ b/src/Nazara/Renderer/DebugDrawer.cpp @@ -539,26 +539,9 @@ bool NzDebugDrawer::Initialize() colorLocation = shader->GetUniformLocation(nzShaderUniform_MaterialDiffuse); } - // VertexDeclaration - { - NzVertexElement element; - element.offset = 0; - element.type = nzElementType_Float3; - element.usage = nzElementUsage_Position; - - vertexDeclaration = new NzVertexDeclaration; - if (!vertexDeclaration->Create(&element, 1)) - { - NazaraError("Failed to create declaration"); - Uninitialize(); - - return false; - } - } - // VertexBuffer (Nécessite la déclaration) { - vertexBuffer = new NzVertexBuffer(vertexDeclaration, 65365, nzBufferStorage_Hardware, nzBufferUsage_Dynamic); + vertexBuffer = new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent), 65365, nzBufferStorage_Hardware, nzBufferUsage_Dynamic); if (!vertexBuffer->GetBuffer()->IsValid()) { NazaraError("Failed to create buffer"); diff --git a/src/Nazara/Renderer/GLSLShader.cpp b/src/Nazara/Renderer/GLSLShader.cpp index 5592aabe5..be735aec5 100644 --- a/src/Nazara/Renderer/GLSLShader.cpp +++ b/src/Nazara/Renderer/GLSLShader.cpp @@ -123,26 +123,26 @@ bool NzGLSLShader::Create() return false; } - glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_TexCoord]+8, "InstanceMatrix"); - - glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Position], "VertexPosition"); - glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Normal], "VertexNormal"); - glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Diffuse], "VertexDiffuse"); - glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_Tangent], "VertexTangent"); - - char texCoordsUniform[] = "VertexTexCoord*"; - - unsigned int maxTexCoords = std::min(8U, NzRenderer::GetMaxTextureUnits()); - for (unsigned int i = 0; i < maxTexCoords; ++i) - { - texCoordsUniform[14] = '0' + i; - glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzElementUsage_TexCoord]+i, texCoordsUniform); - } + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_InstanceData0], "InstanceData0"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_InstanceData1], "InstanceData1"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_InstanceData2], "InstanceData2"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_InstanceData3], "InstanceData3"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_InstanceData4], "InstanceData4"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_InstanceData5], "InstanceData5"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_Normal], "VertexNormal"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_Position], "VertexPosition"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_Tangent], "VertexTangent"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_TexCoord], "VertexTexCoord"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_Userdata0], "VertexUserdata0"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_Userdata1], "VertexUserdata1"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_Userdata2], "VertexUserdata2"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_Userdata3], "VertexUserdata3"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_Userdata4], "VertexUserdata4"); + glBindAttribLocation(m_program, NzOpenGL::AttributeIndex[nzAttributeUsage_Userdata5], "VertexUserdata5"); if (NzRenderer::HasCapability(nzRendererCap_MultipleRenderTargets)) { NzString uniform; - uniform.Reserve(14); // 12 + 2 uniform = "RenderTarget"; unsigned int maxRenderTargets = NzRenderer::GetMaxRenderTargets(); diff --git a/src/Nazara/Renderer/HardwareBuffer.cpp b/src/Nazara/Renderer/HardwareBuffer.cpp index 2b89848ce..55f10347d 100644 --- a/src/Nazara/Renderer/HardwareBuffer.cpp +++ b/src/Nazara/Renderer/HardwareBuffer.cpp @@ -143,11 +143,6 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int return true; } -void* NzHardwareBuffer::GetPointer() -{ - return nullptr; -} - bool NzHardwareBuffer::IsHardware() const { return true; diff --git a/src/Nazara/Renderer/HardwareBuffer.hpp b/src/Nazara/Renderer/HardwareBuffer.hpp index 11d92c91d..e7db8ffc2 100644 --- a/src/Nazara/Renderer/HardwareBuffer.hpp +++ b/src/Nazara/Renderer/HardwareBuffer.hpp @@ -24,8 +24,6 @@ class NzHardwareBuffer : public NzAbstractBuffer bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard); - void* GetPointer(); - bool IsHardware() const; void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0); diff --git a/src/Nazara/Renderer/OpenGL.cpp b/src/Nazara/Renderer/OpenGL.cpp index f9f2b1384..dc877afdb 100644 --- a/src/Nazara/Renderer/OpenGL.cpp +++ b/src/Nazara/Renderer/OpenGL.cpp @@ -1161,14 +1161,37 @@ GLenum NzOpenGL::Attachment[nzAttachmentPoint_Max+1] = GL_STENCIL_ATTACHMENT // nzAttachmentPoint_Stencil }; -nzUInt8 NzOpenGL::AttributeIndex[nzElementUsage_Max+1] = +nzUInt8 NzOpenGL::AttributeIndex[nzAttributeUsage_Max+1] = { - 2, // nzElementUsage_Diffuse - 1, // nzElementUsage_Normal - 0, // nzElementUsage_Position - 3, // nzElementUsage_Tangent + 10, // nzAttributeUsage_InstanceData0 + 11, // nzAttributeUsage_InstanceData1 + 12, // nzAttributeUsage_InstanceData2 + 13, // nzAttributeUsage_InstanceData3 + 14, // nzAttributeUsage_InstanceData4 + 15, // nzAttributeUsage_InstanceData5 + 2, // nzAttributeUsage_Normal + 0, // nzAttributeUsage_Position + 3, // nzAttributeUsage_Tangent + 1, // nzAttributeUsage_TexCoord + 4, // nzAttributeUsage_Userdata0 + 5, // nzAttributeUsage_Userdata1 + 6, // nzAttributeUsage_Userdata2 + 7, // nzAttributeUsage_Userdata3 + 8, // nzAttributeUsage_Userdata4 + 9 // nzAttributeUsage_Userdata5 +}; - 4 // nzElementUsage_TexCoord (Doit être le dernier de la liste car extensible) +GLenum NzOpenGL::AttributeType[nzAttributeType_Max+1] = +{ + GL_UNSIGNED_BYTE, // nzAttributeType_Color + GL_DOUBLE, // nzAttributeType_Double1 + GL_DOUBLE, // nzAttributeType_Double2 + GL_DOUBLE, // nzAttributeType_Double3 + GL_DOUBLE, // nzAttributeType_Double4 + GL_FLOAT, // nzAttributeType_Float1 + GL_FLOAT, // nzAttributeType_Float2 + GL_FLOAT, // nzAttributeType_Float3 + GL_FLOAT // nzAttributeType_Float4 }; GLenum NzOpenGL::BlendFunc[nzBlendFunc_Max+1] = @@ -1232,19 +1255,6 @@ GLenum NzOpenGL::CubemapFace[6] = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z // nzCubemapFace_NegativeZ }; -GLenum NzOpenGL::ElementType[nzElementType_Max+1] = -{ - GL_UNSIGNED_BYTE, // nzElementType_Color - GL_DOUBLE, // nzElementType_Double1 - GL_DOUBLE, // nzElementType_Double2 - GL_DOUBLE, // nzElementType_Double3 - GL_DOUBLE, // nzElementType_Double4 - GL_FLOAT, // nzElementType_Float1 - GL_FLOAT, // nzElementType_Float2 - GL_FLOAT, // nzElementType_Float3 - GL_FLOAT // nzElementType_Float4 -}; - GLenum NzOpenGL::FaceCulling[nzFaceCulling_Max+1] = { GL_BACK, // nzFaceCulling_Back diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 4e0d8eadc..461075247 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -63,13 +64,13 @@ namespace return new NzHardwareBuffer(parent, type); } - using VAO_Key = std::tuple; + using VAO_Key = std::tuple; - std::map s_vaos; + std::unordered_map> s_vaos; std::set s_dirtyTextureUnits; std::vector s_textureUnits; GLuint s_currentVAO = 0; - NzBuffer* s_instancingBuffer = nullptr; + NzVertexBuffer* s_instancingBuffer = nullptr; NzVertexBuffer* s_fullscreenQuadBuffer = nullptr; MatrixUnit s_matrices[nzMatrixType_Max+1]; NzRenderStates s_states; @@ -80,12 +81,14 @@ namespace const NzRenderTarget* s_target; const NzShader* s_shader; const NzVertexBuffer* s_vertexBuffer; + const NzVertexDeclaration* s_instancingDeclaration; bool s_capabilities[nzRendererCap_Max+1]; bool s_instancing; bool s_useSamplerObjects; bool s_useVertexArrayObjects; unsigned int s_maxRenderTarget; unsigned int s_maxTextureUnit; + unsigned int s_maxVertexAttribs; } void NzRenderer::Clear(unsigned long flags) @@ -173,26 +176,21 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode mode, unsigned int firstI return; } - if (s_indexBuffer->IsSequential()) - glDrawArrays(NzOpenGL::PrimitiveMode[mode], s_indexBuffer->GetStartIndex(), s_indexBuffer->GetIndexCount()); + GLenum type; + nzUInt8* offset = reinterpret_cast(s_indexBuffer->GetStartOffset()); + + if (s_indexBuffer->HasLargeIndices()) + { + offset += firstIndex*sizeof(nzUInt64); + type = GL_UNSIGNED_INT; + } else { - GLenum type; - const nzUInt8* ptr = reinterpret_cast(s_indexBuffer->GetPointer()); - if (s_indexBuffer->HasLargeIndices()) - { - ptr += firstIndex*sizeof(nzUInt32); - type = GL_UNSIGNED_INT; - } - else - { - ptr += firstIndex*sizeof(nzUInt16); - type = GL_UNSIGNED_SHORT; - } - - glDrawElements(NzOpenGL::PrimitiveMode[mode], indexCount, type, ptr); + offset += firstIndex*sizeof(nzUInt32); + type = GL_UNSIGNED_SHORT; } + glDrawElements(NzOpenGL::PrimitiveMode[mode], indexCount, type, offset); glBindVertexArray(0); } @@ -246,27 +244,21 @@ void NzRenderer::DrawIndexedPrimitivesInstanced(unsigned int instanceCount, nzPr return; } - if (s_indexBuffer->IsSequential()) - glDrawArraysInstanced(NzOpenGL::PrimitiveMode[mode], s_indexBuffer->GetStartIndex(), s_indexBuffer->GetIndexCount(), instanceCount); + GLenum type; + nzUInt8* offset = reinterpret_cast(s_indexBuffer->GetStartOffset()); + + if (s_indexBuffer->HasLargeIndices()) + { + offset += firstIndex*sizeof(nzUInt64); + type = GL_UNSIGNED_INT; + } else { - GLenum type; - const nzUInt8* ptr = reinterpret_cast(s_indexBuffer->GetPointer()); - - if (s_indexBuffer->HasLargeIndices()) - { - ptr += firstIndex*sizeof(nzUInt32); - type = GL_UNSIGNED_INT; - } - else - { - ptr += firstIndex*sizeof(nzUInt16); - type = GL_UNSIGNED_SHORT; - } - - glDrawElementsInstanced(NzOpenGL::PrimitiveMode[mode], indexCount, type, ptr, instanceCount); + offset += firstIndex*sizeof(nzUInt32); + type = GL_UNSIGNED_SHORT; } + glDrawElementsInstanced(NzOpenGL::PrimitiveMode[mode], indexCount, type, offset, instanceCount); glBindVertexArray(0); } @@ -422,16 +414,13 @@ unsigned int NzRenderer::GetMaxTextureUnits() return s_maxTextureUnit; } +unsigned int NzRenderer::GetMaxVertexAttribs() +{ + return s_maxVertexAttribs; +} + float NzRenderer::GetPointSize() { - #ifdef NAZARA_DEBUG - if (NzContext::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return 0.f; - } - #endif - return s_states.pointSize; } @@ -551,20 +540,6 @@ bool NzRenderer::Initialize() else s_maxAnisotropyLevel = 1; - if (s_capabilities[nzRendererCap_Instancing]) - { - s_instancingBuffer = new NzBuffer(nzBufferType_Vertex); - if (!s_instancingBuffer->Create(NAZARA_RENDERER_MAX_INSTANCES, sizeof(InstancingData), nzBufferStorage_Hardware, nzBufferUsage_Dynamic)) - { - s_capabilities[nzRendererCap_Instancing] = false; - - delete s_instancingBuffer; - s_instancingBuffer = nullptr; - - NazaraWarning("Failed to create instancing buffer, disabled instancing."); - } - } - if (s_capabilities[nzRendererCap_MultipleRenderTargets]) { GLint maxDrawBuffers; @@ -580,15 +555,16 @@ bool NzRenderer::Initialize() GLint maxTextureUnits; glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxTextureUnits); - GLint maxVertexAttribs; - glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs); - // Impossible de binder plus de texcoords que d'attributes (en sachant qu'un certain nombre est déjà pris par les autres attributs) - s_maxTextureUnit = static_cast(std::min(maxTextureUnits, maxVertexAttribs-NzOpenGL::AttributeIndex[nzElementUsage_TexCoord])); + s_maxTextureUnit = static_cast(maxTextureUnits); } else s_maxTextureUnit = 1; + GLint maxVertexAttribs; + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxVertexAttribs); + s_maxVertexAttribs = static_cast(maxVertexAttribs); + s_states = NzRenderStates(); s_indexBuffer = nullptr; @@ -600,25 +576,7 @@ bool NzRenderer::Initialize() s_vertexBuffer = nullptr; s_updateFlags = (Update_Matrices | Update_Shader | Update_VAO); - NzVertexElement element; - element.offset = 0; - element.type = nzElementType_Float2; - element.usage = nzElementUsage_Position; - - std::unique_ptr declaration(new NzVertexDeclaration); - if (!declaration->Create(&element, 1)) - { - NazaraError("Failed to create fullscreen quad declaration"); - Uninitialize(); - - return false; - } - - declaration->SetPersistent(false); - - s_fullscreenQuadBuffer = new NzVertexBuffer(declaration.get(), 4, nzBufferStorage_Hardware, nzBufferUsage_Static); - declaration.release(); - + s_fullscreenQuadBuffer = new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XY), 4, nzBufferStorage_Hardware, nzBufferUsage_Static); float vertices[4*2] = { -1.f, -1.f, @@ -627,7 +585,7 @@ bool NzRenderer::Initialize() 1.f, 1.f, }; - if (!s_fullscreenQuadBuffer->Fill(vertices, 0, 4)) + if (!s_fullscreenQuadBuffer->FillVertices(vertices, 0, 4)) { NazaraError("Failed to fill fullscreen quad buffer"); Uninitialize(); @@ -635,6 +593,22 @@ bool NzRenderer::Initialize() return false; } + if (s_capabilities[nzRendererCap_Instancing]) + { + try + { + s_instancingBuffer = new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_Matrix4), NAZARA_RENDERER_MAX_INSTANCES, nzBufferStorage_Hardware, nzBufferUsage_Dynamic); + } + catch (const std::exception& e) + { + s_capabilities[nzRendererCap_Instancing] = false; + s_instancingBuffer = nullptr; + NazaraError("Failed to create instancing buffer: " + e.what()); ///TODO: Noexcept + } + } + else + s_instancingBuffer = nullptr; + if (!NzMaterial::Initialize()) { NazaraError("Failed to initialize materials"); @@ -670,12 +644,6 @@ bool NzRenderer::Initialize() bool NzRenderer::IsEnabled(nzRendererParameter parameter) { #ifdef NAZARA_DEBUG - if (NzContext::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return false; - } - if (parameter > nzRendererParameter_Max) { NazaraError("Renderer parameter out of enum"); @@ -693,14 +661,6 @@ bool NzRenderer::IsInitialized() void NzRenderer::SetBlendFunc(nzBlendFunc srcBlend, nzBlendFunc dstBlend) { - #ifdef NAZARA_DEBUG - if (NzContext::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - s_states.srcBlend = srcBlend; s_states.dstBlend = dstBlend; } @@ -759,47 +719,23 @@ void NzRenderer::SetClearStencil(unsigned int value) void NzRenderer::SetDepthFunc(nzRendererComparison compareFunc) { - #ifdef NAZARA_DEBUG - if (NzContext::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - s_states.depthFunc = compareFunc; } void NzRenderer::SetFaceCulling(nzFaceCulling cullingMode) { - #ifdef NAZARA_DEBUG - if (NzContext::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - s_states.faceCulling = cullingMode; } void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode) { - #ifdef NAZARA_DEBUG - if (NzContext::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - s_states.faceFilling = fillingMode; } void NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer) { #if NAZARA_RENDERER_SAFE - if (indexBuffer && !indexBuffer->IsSequential() && !indexBuffer->IsHardware()) + if (indexBuffer && !indexBuffer->IsHardware()) { NazaraError("Buffer must be hardware"); return; @@ -813,7 +749,7 @@ void NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer) } } -void NzRenderer::SetInstancingData(const NzRenderer::InstancingData* instancingData, unsigned int instanceCount) +void NzRenderer::SetInstancingData(const void* instancingData, unsigned int instanceCount) { #if NAZARA_RENDERER_SAFE if (!s_capabilities[nzRendererCap_Instancing]) @@ -834,27 +770,42 @@ void NzRenderer::SetInstancingData(const NzRenderer::InstancingData* instancingD return; } - if (instanceCount > NAZARA_RENDERER_MAX_INSTANCES) + unsigned int maxInstanceCount = s_instancingBuffer->GetVertexCount(); + if (instanceCount > maxInstanceCount) { - NazaraError("Instance count is over maximum instance count (" + NzString::Number(instanceCount) + " >= " NazaraStringifyMacro(NAZARA_RENDERER_MAX_INSTANCES) ")"); + NazaraError("Instance count is over maximum instance count (" + NzString::Number(instanceCount) + " >= " + NzString::Number(maxInstanceCount) + ")"); return; } #endif - if (!s_instancingBuffer->Fill(instancingData, 0, instanceCount, true)) + if (!s_instancingBuffer->FillVertices(instancingData, 0, instanceCount, true)) NazaraError("Failed to fill instancing buffer"); } +void NzRenderer::SetInstancingDeclaration(const NzVertexDeclaration* declaration, unsigned int* newMaxInstanceCount) +{ + #if NAZARA_RENDERER_SAFE + if (!s_capabilities[nzRendererCap_Instancing]) + { + NazaraError("Instancing not supported"); + return; + } + + if (!declaration) + { + NazaraError("Declaration must be valid"); + return; + } + #endif + + s_instancingBuffer->SetVertexDeclaration(declaration); + + if (newMaxInstanceCount) + *newMaxInstanceCount = s_instancingBuffer->GetVertexCount(); +} + void NzRenderer::SetLineWidth(float width) { - #ifdef NAZARA_DEBUG - if (NzContext::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - #if NAZARA_RENDERER_SAFE if (width <= 0.f) { @@ -914,14 +865,6 @@ void NzRenderer::SetMatrix(nzMatrixType type, const NzMatrix4f& matrix) void NzRenderer::SetPointSize(float size) { - #ifdef NAZARA_DEBUG - if (NzContext::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - #if NAZARA_RENDERER_SAFE if (size <= 0.f) { @@ -1197,25 +1140,23 @@ void NzRenderer::Uninitialize() // Loaders NzLoaders_Texture_Unregister(); - NzDebugDrawer::Uninitialize(); - NzMaterial::Uninitialize(); - NzShaderBuilder::Uninitialize(); NzTextureSampler::Uninitialize(); + NzShaderBuilder::Uninitialize(); + NzMaterial::Uninitialize(); + NzDebugDrawer::Uninitialize(); // Libération des buffers delete s_fullscreenQuadBuffer; - - if (s_instancingBuffer) - { - delete s_instancingBuffer; - s_instancingBuffer = nullptr; - } + delete s_instancingBuffer; // Libération des VAOs - for (auto it = s_vaos.begin(); it != s_vaos.end(); ++it) + for (auto pair : s_vaos) { - GLuint vao = static_cast(it->second); - glDeleteVertexArrays(1, &vao); + for (auto pair2 : pair.second) + { + GLuint vao = static_cast(pair2.second); + glDeleteVertexArrays(1, &vao); + } } NzOpenGL::Uninitialize(); @@ -1355,20 +1296,22 @@ bool NzRenderer::EnsureStateUpdate() // Si les VAOs sont supportés, on entoure nos appels par ceux-ci if (s_useVertexArrayObjects) { - // On recherche si un VAO existe déjà avec notre configuration - // Note: Les VAOs ne sont pas partagés entre les contextes, ces derniers font donc partie de notre configuration + // Note: Les VAOs ne sont pas partagés entre les contextes, nous avons donc un tableau de VAOs par contexte + auto vaos = s_vaos[NzContext::GetCurrent()]; - VAO_Key key(NzContext::GetCurrent(), s_indexBuffer, s_vertexBuffer, s_instancing); - auto it = s_vaos.find(key); + // Notre clé est composée de ce qui définit un VAO + VAO_Key key(s_indexBuffer, s_vertexBuffer, s_vertexBuffer->GetVertexDeclaration(), (s_instancing) ? s_instancingDeclaration : nullptr); - if (it == s_vaos.end()) + // On recherche un VAO existant avec notre configuration + auto it = vaos.find(key); + if (it == vaos.end()) { // On créé notre VAO glGenVertexArrays(1, &s_currentVAO); glBindVertexArray(s_currentVAO); // On l'ajoute à notre liste - s_vaos.insert(std::make_pair(key, static_cast(s_currentVAO))); + vaos.insert(std::make_pair(key, static_cast(s_currentVAO))); // Et on indique qu'on veut le programmer update = true; @@ -1386,53 +1329,72 @@ bool NzRenderer::EnsureStateUpdate() if (update) { + const NzVertexDeclaration* vertexDeclaration; + unsigned int bufferOffset; + unsigned int stride; + NzHardwareBuffer* vertexBufferImpl = static_cast(s_vertexBuffer->GetBuffer()->GetImpl()); vertexBufferImpl->Bind(); - const NzVertexDeclaration* vertexDeclaration = s_vertexBuffer->GetVertexDeclaration(); - - const nzUInt8* buffer = static_cast(s_vertexBuffer->GetPointer()); - unsigned int stride = vertexDeclaration->GetStride(nzElementStream_VertexData); - for (unsigned int i = 0; i <= nzElementUsage_Max; ++i) + bufferOffset = s_vertexBuffer->GetStartOffset(); + vertexDeclaration = s_vertexBuffer->GetVertexDeclaration(); + stride = vertexDeclaration->GetStride(); + for (unsigned int i = nzAttributeUsage_FirstVertexData; i <= nzAttributeUsage_LastVertexData; ++i) { - nzElementUsage usage = static_cast(i); - if (vertexDeclaration->HasElement(nzElementStream_VertexData, usage)) - { - const NzVertexElement* element = vertexDeclaration->GetElement(nzElementStream_VertexData, usage); + nzAttributeType type; + bool enabled; + unsigned int offset; + vertexDeclaration->GetAttribute(static_cast(i), &enabled, &type, &offset); + if (enabled) + { glEnableVertexAttribArray(NzOpenGL::AttributeIndex[i]); glVertexAttribPointer(NzOpenGL::AttributeIndex[i], - NzVertexDeclaration::GetElementCount(element->type), - NzOpenGL::ElementType[element->type], - (element->type == nzElementType_Color) ? GL_TRUE : GL_FALSE, - stride, - &buffer[element->offset]); + NzVertexDeclaration::GetAttributeSize(type), + NzOpenGL::AttributeType[type], + (type == nzAttributeType_Color) ? GL_TRUE : GL_FALSE, + stride, + reinterpret_cast(bufferOffset + offset)); } else glDisableVertexAttribArray(NzOpenGL::AttributeIndex[i]); } - unsigned int instanceMatrixIndex = NzOpenGL::AttributeIndex[nzElementUsage_TexCoord] + 8; - if (s_instancing) + /*if (s_instancing) { - static_cast(s_instancingBuffer->GetImpl())->Bind(); - - for (unsigned int i = 0; i < 4; ++i) + bufferOffset = s_instancingBuffer->GetStartOffset(); + vertexDeclaration = s_instancingBuffer->GetVertexDeclaration(); + stride = vertexDeclaration->GetStride(); + for (unsigned int i = nzAttributeUsage_FirstInstanceData; i <= nzAttributeUsage_LastInstanceData; ++i) { - glEnableVertexAttribArray(instanceMatrixIndex); - glVertexAttribPointer(instanceMatrixIndex, 4, GL_FLOAT, GL_FALSE, sizeof(InstancingData), reinterpret_cast(offsetof(InstancingData, worldMatrix) + i*sizeof(float)*4)); - glVertexAttribDivisor(instanceMatrixIndex, 1); + nzAttributeType type; + bool enabled; + unsigned int offset; + vertexDeclaration->GetAttribute(static_cast(i), &enabled, &offset, &type); - instanceMatrixIndex++; + if (enabled) + { + glEnableVertexAttribArray(NzOpenGL::AttributeIndex[i]); + glVertexAttribPointer(NzOpenGL::AttributeIndex[i], + NzVertexDeclaration::GetElementCount(type), + NzOpenGL::AttributeType[type], + (type == nzAttributeType_Color) ? GL_TRUE : GL_FALSE, + stride, + reinterpret_cast(bufferOffset + offset)); + glVertexAttribDivisor(NzOpenGL::AttributeIndex[i], 1); + } + else + glDisableVertexAttribArray(NzOpenGL::AttributeIndex[i]); } } else { - for (unsigned int i = 0; i < 4; ++i) - glDisableVertexAttribArray(instanceMatrixIndex++); - } + for (unsigned int i = nzAttributeUsage_FirstInstanceData; i <= nzAttributeUsage_LastInstanceData; ++i) + glDisableVertexAttribArray(NzOpenGL::AttributeIndex[i]); + }*/ - if (s_indexBuffer && !s_indexBuffer->IsSequential()) + // Et on active l'index buffer (Un seul index buffer par VAO) + if (s_indexBuffer) { NzHardwareBuffer* indexBufferImpl = static_cast(s_indexBuffer->GetBuffer()->GetImpl()); indexBufferImpl->Bind(); @@ -1453,7 +1415,7 @@ bool NzRenderer::EnsureStateUpdate() } #ifdef NAZARA_DEBUG - if (s_updateFlags != Update_None) + if (s_updateFlags != Update_None && !s_useVertexArrayObjects && s_updateFlags != Update_VAO) NazaraWarning("Update flags not fully cleared"); #endif } @@ -1463,6 +1425,8 @@ bool NzRenderer::EnsureStateUpdate() 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 ait eu lieu + // entre le dernier rendu et maintenant for (unsigned int i = 0; i < s_maxTextureUnit; ++i) { const NzTexture* texture = s_textureUnits[i].texture; @@ -1470,6 +1434,7 @@ bool NzRenderer::EnsureStateUpdate() NzOpenGL::BindTexture(i, texture->GetType(), texture->GetOpenGLID()); } + // Et on termine par envoyer nos états à OpenGL NzOpenGL::ApplyStates(s_states); return true; diff --git a/src/Nazara/Utility/Buffer.cpp b/src/Nazara/Utility/Buffer.cpp index a7af2b861..cfb8a1c49 100644 --- a/src/Nazara/Utility/Buffer.cpp +++ b/src/Nazara/Utility/Buffer.cpp @@ -22,17 +22,16 @@ namespace NzBuffer::NzBuffer(nzBufferType type) : m_type(type), -m_typeSize(0), m_impl(nullptr), -m_length(0) +m_size(0) { } -NzBuffer::NzBuffer(nzBufferType type, unsigned int length, nzUInt8 typeSize, nzBufferStorage storage, nzBufferUsage usage) : +NzBuffer::NzBuffer(nzBufferType type, unsigned int size, nzBufferStorage storage, nzBufferUsage usage) : m_type(type), m_impl(nullptr) { - Create(length, typeSize, storage, usage); + Create(size, storage, usage); #ifdef NAZARA_DEBUG if (!m_impl) @@ -62,20 +61,14 @@ bool NzBuffer::CopyContent(const NzBuffer& buffer) NazaraError("Source buffer must be valid"); return false; } - - if (!buffer.GetTypeSize() != m_typeSize) - { - NazaraError("Source buffer type size does not match buffer type size"); - return false; - } #endif NzBufferMapper mapper(buffer, nzBufferAccess_ReadOnly); - return Fill(mapper.GetPointer(), 0, buffer.GetLength()); + return Fill(mapper.GetPointer(), 0, buffer.GetSize()); } -bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage storage, nzBufferUsage usage) +bool NzBuffer::Create(unsigned int size, nzBufferStorage storage, nzBufferUsage usage) { Destroy(); @@ -87,7 +80,7 @@ bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage sto } NzAbstractBuffer* impl = s_bufferFunctions[storage](this, m_type); - if (!impl->Create(length*typeSize, usage)) + if (!impl->Create(size, usage)) { NazaraError("Failed to create buffer"); delete impl; @@ -96,8 +89,7 @@ bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage sto } m_impl = impl; - m_length = length; - m_typeSize = typeSize; + m_size = size; m_storage = storage; m_usage = usage; @@ -117,7 +109,7 @@ void NzBuffer::Destroy() } } -bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length, bool forceDiscard) +bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard) { #if NAZARA_UTILITY_SAFE if (!m_impl) @@ -126,14 +118,14 @@ bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length, return false; } - if (offset+length > m_length) + if (offset+size > m_size) { NazaraError("Exceeding buffer size"); return false; } #endif - return m_impl->Fill(data, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize, forceDiscard); + return m_impl->Fill(data, offset, (size == 0) ? m_size-offset : size, forceDiscard); } NzAbstractBuffer* NzBuffer::GetImpl() const @@ -141,40 +133,9 @@ NzAbstractBuffer* NzBuffer::GetImpl() const return m_impl; } -unsigned int NzBuffer::GetLength() const -{ - return m_length; -} - -void* NzBuffer::GetPointer() -{ - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Buffer not valid"); - return nullptr; - } - #endif - - return m_impl->GetPointer(); -} - -const void* NzBuffer::GetPointer() const -{ - #if NAZARA_UTILITY_SAFE - if (!m_impl) - { - NazaraError("Buffer not valid"); - return nullptr; - } - #endif - - return m_impl->GetPointer(); -} - unsigned int NzBuffer::GetSize() const { - return m_length*m_typeSize; + return m_size; } nzBufferStorage NzBuffer::GetStorage() const @@ -187,11 +148,6 @@ nzBufferType NzBuffer::GetType() const return m_type; } -nzUInt8 NzBuffer::GetTypeSize() const -{ - return m_typeSize; -} - nzBufferUsage NzBuffer::GetUsage() const { return m_usage; @@ -207,7 +163,7 @@ bool NzBuffer::IsValid() const return m_impl != nullptr; } -void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) +void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size) { #if NAZARA_UTILITY_SAFE if (!m_impl) @@ -216,17 +172,17 @@ void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int len return nullptr; } - if (offset+length > m_length) + if (offset+size > m_size) { NazaraError("Exceeding buffer size"); return nullptr; } #endif - return m_impl->Map(access, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize); + return m_impl->Map(access, offset, (size == 0) ? m_size-offset : size); } -void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) const +void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size) const { #if NAZARA_UTILITY_SAFE if (!m_impl) @@ -241,14 +197,14 @@ void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int len return nullptr; } - if (offset+length > m_length) + if (offset+size > m_size) { NazaraError("Exceeding buffer size"); return nullptr; } #endif - return m_impl->Map(access, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize); + return m_impl->Map(access, offset, (size == 0) ? m_size-offset : size); } bool NzBuffer::SetStorage(nzBufferStorage storage) @@ -272,7 +228,7 @@ bool NzBuffer::SetStorage(nzBufferStorage storage) } #endif - void* ptr = m_impl->Map(nzBufferAccess_ReadOnly, 0, m_length*m_typeSize); + void* ptr = m_impl->Map(nzBufferAccess_ReadOnly, 0, m_size); if (!ptr) { NazaraError("Failed to map buffer"); @@ -280,7 +236,7 @@ bool NzBuffer::SetStorage(nzBufferStorage storage) } NzAbstractBuffer* impl = s_bufferFunctions[storage](this, m_type); - if (!impl->Create(m_length*m_typeSize, m_usage)) + if (!impl->Create(m_size, m_usage)) { NazaraError("Failed to create buffer"); delete impl; @@ -289,7 +245,7 @@ bool NzBuffer::SetStorage(nzBufferStorage storage) return false; } - if (!impl->Fill(ptr, 0, m_length*m_typeSize)) + if (!impl->Fill(ptr, 0, m_size)) { NazaraError("Failed to fill buffer"); impl->Destroy(); diff --git a/src/Nazara/Utility/Image.cpp b/src/Nazara/Utility/Image.cpp index 4211f1474..0d014e945 100644 --- a/src/Nazara/Utility/Image.cpp +++ b/src/Nazara/Utility/Image.cpp @@ -50,7 +50,7 @@ m_sharedImage(&emptyImage) } NzImage::NzImage(const NzImage& image) : -NzResource(image), +NzResource(), m_sharedImage(image.m_sharedImage) { if (m_sharedImage != &emptyImage) @@ -63,6 +63,11 @@ m_sharedImage(image.m_sharedImage) image.m_sharedImage = &emptyImage; } +NzImage::NzImage(SharedImage* sharedImage) : +m_sharedImage(sharedImage) +{ +} + NzImage::~NzImage() { Destroy(); diff --git a/src/Nazara/Utility/IndexBuffer.cpp b/src/Nazara/Utility/IndexBuffer.cpp index 8f0a57e3e..2e1422f7f 100644 --- a/src/Nazara/Utility/IndexBuffer.cpp +++ b/src/Nazara/Utility/IndexBuffer.cpp @@ -11,62 +11,65 @@ #include #include -///FIXME: Gérer efficacement les erreurs de création du buffer - -NzIndexBuffer::NzIndexBuffer(NzBuffer* buffer, unsigned int startIndex, unsigned int indexCount) : +NzIndexBuffer::NzIndexBuffer(bool largeIndices, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset) : m_buffer(buffer), -m_ownsBuffer(false), -m_indexCount(indexCount), -m_startIndex(startIndex) +m_largeIndices(largeIndices), +m_endOffset(endOffset), +m_startOffset(startOffset) { - if (m_buffer) + #ifdef NAZARA_DEBUG + if (!m_buffer || !m_buffer->IsValid()) { - #ifdef NAZARA_DEBUG - nzUInt8 indexSize = m_buffer->GetSize(); - if (indexSize != 2 && indexSize != 4) - { - NazaraError("Invalid index size (" + NzString::Number(indexSize) + ')'); - m_buffer = nullptr; - - throw std::runtime_error("Constructor failed"); - } - #endif + NazaraError("Buffer is invalid"); + throw std::invalid_argument("Buffer must be valid"); } + + if (endOffset > startOffset) + { + NazaraError("End offset cannot be over start offset"); + throw std::invalid_argument("End offset cannot be over start offset"); + } + + unsigned int bufferSize = m_buffer->GetSize(); + if (startOffset >= bufferSize) + { + NazaraError("Start offset is over buffer size"); + throw std::invalid_argument("Start offset is over buffer size"); + } + + if (endOffset >= bufferSize) + { + NazaraError("End offset is over buffer size"); + throw std::invalid_argument("End offset is over buffer size"); + } + #endif + + unsigned int stride = (largeIndices) ? sizeof(nzUInt32) : sizeof(nzUInt16); + + m_indexCount = (endOffset - startOffset) / stride; } -NzIndexBuffer::NzIndexBuffer(unsigned int length, bool largeIndices, nzBufferStorage storage, nzBufferUsage usage) : -m_ownsBuffer(true), +NzIndexBuffer::NzIndexBuffer(bool largeIndices, unsigned int length, nzBufferStorage storage, nzBufferUsage usage) : +m_largeIndices(largeIndices), m_indexCount(length), -m_startIndex(0) +m_startOffset(0) { - m_buffer = new NzBuffer(nzBufferType_Index, length, (largeIndices) ? 4 : 2, storage, usage); + m_endOffset = length * ((largeIndices) ? sizeof(nzUInt32) : sizeof(nzUInt16)); + + m_buffer = new NzBuffer(nzBufferType_Index, m_endOffset, storage, usage); m_buffer->SetPersistent(false); } NzIndexBuffer::NzIndexBuffer(const NzIndexBuffer& indexBuffer) : -NzResource(true), +NzResource(), m_buffer(indexBuffer.m_buffer), -m_ownsBuffer(indexBuffer.m_ownsBuffer), +m_largeIndices(indexBuffer.m_largeIndices), +m_endOffset(indexBuffer.m_endOffset), m_indexCount(indexBuffer.m_indexCount), -m_startIndex(indexBuffer.m_startIndex) +m_startOffset(indexBuffer.m_startOffset) { - if (m_buffer) - { - if (m_ownsBuffer) - { - NzBuffer* buffer = indexBuffer.m_buffer; - - m_buffer = new NzBuffer(nzBufferType_Index, buffer->GetLength(), buffer->GetSize(), buffer->GetStorage(), buffer->GetUsage()); - m_buffer->SetPersistent(false); - m_buffer->CopyContent(*indexBuffer.m_buffer); - } - else - m_buffer = indexBuffer.m_buffer; - } } -NzIndexBuffer::~NzIndexBuffer() = default; - unsigned int NzIndexBuffer::ComputeCacheMissCount() const { NzIndexMapper mapper(this); @@ -74,23 +77,23 @@ unsigned int NzIndexBuffer::ComputeCacheMissCount() const return NzComputeCacheMissCount(mapper.begin(), m_indexCount); } -bool NzIndexBuffer::Fill(const void* data, unsigned int offset, unsigned int length, bool forceDiscard) +bool NzIndexBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard) { #if NAZARA_UTILITY_SAFE - if (!m_buffer) - { - NazaraError("Impossible to fill sequential buffers"); - return false; - } - - if (offset+length > m_indexCount) + if (m_startOffset + offset + size > m_endOffset) { NazaraError("Exceeding virtual buffer size"); return false; } #endif - return m_buffer->Fill(data, m_startIndex+offset, length, forceDiscard); + return m_buffer->Fill(data, m_startOffset+offset, size, forceDiscard); +} + +bool NzIndexBuffer::FillIndices(const void* data, unsigned int startIndex, unsigned int length, bool forceDiscard) +{ + unsigned int stride = GetStride(); + return Fill(data, startIndex*stride, length*stride, forceDiscard); } NzBuffer* NzIndexBuffer::GetBuffer() const @@ -98,30 +101,9 @@ NzBuffer* NzIndexBuffer::GetBuffer() const return m_buffer; } -void* NzIndexBuffer::GetPointer() +unsigned int NzIndexBuffer::GetEndOffset() const { - #if NAZARA_UTILITY_SAFE - if (!m_buffer) - { - NazaraError("Sequential buffers have no pointer"); - return nullptr; - } - #endif - - return reinterpret_cast(m_buffer->GetPointer()) + m_startIndex*m_buffer->GetTypeSize(); -} - -const void* NzIndexBuffer::GetPointer() const -{ - #if NAZARA_UTILITY_SAFE - if (!m_buffer) - { - NazaraError("Sequential buffers have no pointer"); - return nullptr; - } - #endif - - return reinterpret_cast(m_buffer->GetPointer()) + m_startIndex*m_buffer->GetTypeSize(); + return m_endOffset; } unsigned int NzIndexBuffer::GetIndexCount() const @@ -129,78 +111,64 @@ unsigned int NzIndexBuffer::GetIndexCount() const return m_indexCount; } -unsigned int NzIndexBuffer::GetStartIndex() const +unsigned int NzIndexBuffer::GetStride() const { - return m_startIndex; + return (m_largeIndices) ? sizeof(nzUInt32) : sizeof(nzUInt16); +} + +unsigned int NzIndexBuffer::GetStartOffset() const +{ + return m_startOffset; } bool NzIndexBuffer::HasLargeIndices() const { - #if NAZARA_UTILITY_SAFE - if (!m_buffer) - { - NazaraError("Sequential buffers have no index size"); - return 0; - } - #endif - - return (m_buffer->GetTypeSize() == 4); + return m_largeIndices; } bool NzIndexBuffer::IsHardware() const +{ + return m_buffer->IsHardware(); +} + +void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size) { #if NAZARA_UTILITY_SAFE - if (!m_buffer) + if (m_startOffset + offset + size > m_endOffset) { - NazaraWarning("Sequential index buffers are neither hardware or software"); + NazaraError("Exceeding virtual buffer size"); return false; } #endif - return m_buffer->IsHardware(); + return m_buffer->Map(access, offset, size); } -bool NzIndexBuffer::IsSequential() const -{ - return m_buffer == nullptr; -} - -void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) +void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size) const { #if NAZARA_UTILITY_SAFE - if (!m_buffer) - { - NazaraError("Impossible to map sequential buffers"); - return nullptr; - } - - if (offset+length > m_indexCount) + if (m_startOffset + offset + size > m_endOffset) { NazaraError("Exceeding virtual buffer size"); return nullptr; } #endif - return m_buffer->Map(access, m_startIndex+offset, (length) ? length : m_indexCount-offset); + return m_buffer->Map(access, offset, size); } -void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) const +void* NzIndexBuffer::MapIndices(nzBufferAccess access, unsigned int startIndex, unsigned int length) { - #if NAZARA_UTILITY_SAFE - if (!m_buffer) - { - NazaraError("Impossible to map sequential buffers"); - return nullptr; - } + unsigned int stride = GetStride(); - if (offset+length > m_indexCount) - { - NazaraError("Exceeding virtual buffer size"); - return nullptr; - } - #endif + return Map(access, startIndex*stride, length*stride); +} - return m_buffer->Map(access, m_startIndex+offset, (length) ? length : m_indexCount-offset); +void* NzIndexBuffer::MapIndices(nzBufferAccess access, unsigned int startIndex, unsigned int length) const +{ + unsigned int stride = GetStride(); + + return Map(access, startIndex*stride, length*stride); } void NzIndexBuffer::Optimize() @@ -212,26 +180,10 @@ void NzIndexBuffer::Optimize() bool NzIndexBuffer::SetStorage(nzBufferStorage storage) { - #if NAZARA_UTILITY_SAFE - if (!m_buffer) - { - NazaraWarning("Sequential buffers have no storage"); - return true; - } - #endif - return m_buffer->SetStorage(storage); } void NzIndexBuffer::Unmap() const { - #if NAZARA_UTILITY_SAFE - if (!m_buffer) - { - NazaraError("Impossible to unlock sequential buffers"); - return; - } - #endif - m_buffer->Unmap(); } diff --git a/src/Nazara/Utility/IndexMapper.cpp b/src/Nazara/Utility/IndexMapper.cpp index 436d11131..13d112461 100644 --- a/src/Nazara/Utility/IndexMapper.cpp +++ b/src/Nazara/Utility/IndexMapper.cpp @@ -22,13 +22,6 @@ namespace return ptr[i]; } - nzUInt32 GetterSequential(const void* buffer, unsigned int i) - { - NazaraUnused(buffer); - - return static_cast(i); - } - void Setter16(void* buffer, unsigned int i, nzUInt32 value) { nzUInt16* ptr = reinterpret_cast(buffer); @@ -50,32 +43,32 @@ namespace NzIndexMapper::NzIndexMapper(NzIndexBuffer* indexBuffer, nzBufferAccess access) : m_indexCount(indexBuffer->GetIndexCount()) { - if (indexBuffer && !indexBuffer->IsSequential()) + #if NAZARA_UTILITY_SAFE + if (!indexBuffer) { - if (!m_mapper.Map(indexBuffer, access)) - NazaraError("Failed to map buffer"); ///TODO: Unexcepted + NazaraError("Index buffer must be valid"); + return; + } + #endif - if (indexBuffer->HasLargeIndices()) - { - m_getter = Getter32; - if (access != nzBufferAccess_ReadOnly) - m_setter = Setter32; - else - m_setter = SetterError; - } + if (!m_mapper.Map(indexBuffer, access)) + NazaraError("Failed to map buffer"); ///TODO: Unexcepted + + if (indexBuffer->HasLargeIndices()) + { + m_getter = Getter32; + if (access != nzBufferAccess_ReadOnly) + m_setter = Setter32; else - { - m_getter = Getter16; - if (access != nzBufferAccess_ReadOnly) - m_setter = Setter16; - else - m_setter = SetterError; - } + m_setter = SetterError; } else { - m_getter = GetterSequential; - m_setter = SetterError; + m_getter = Getter16; + if (access != nzBufferAccess_ReadOnly) + m_setter = Setter16; + else + m_setter = SetterError; } } @@ -83,18 +76,21 @@ NzIndexMapper::NzIndexMapper(const NzIndexBuffer* indexBuffer, nzBufferAccess ac m_setter(SetterError), m_indexCount(indexBuffer->GetIndexCount()) { - if (indexBuffer && !indexBuffer->IsSequential()) + #if NAZARA_UTILITY_SAFE + if (!indexBuffer) { - if (!m_mapper.Map(indexBuffer, access)) - NazaraError("Failed to map buffer"); ///TODO: Unexcepted - - if (indexBuffer->HasLargeIndices()) - m_getter = Getter32; - else - m_getter = Getter16; + NazaraError("Index buffer must be valid"); + return; } + #endif + + if (!m_mapper.Map(indexBuffer, access)) + NazaraError("Failed to map buffer"); ///TODO: Unexcepted + + if (indexBuffer->HasLargeIndices()) + m_getter = Getter32; else - m_getter = GetterSequential; + m_getter = Getter16; } NzIndexMapper::NzIndexMapper(const NzSubMesh* subMesh) : diff --git a/src/Nazara/Utility/Loaders/MD2/Loader.cpp b/src/Nazara/Utility/Loaders/MD2/Loader.cpp index 701df3af2..76f286886 100644 --- a/src/Nazara/Utility/Loaders/MD2/Loader.cpp +++ b/src/Nazara/Utility/Loaders/MD2/Loader.cpp @@ -102,7 +102,7 @@ namespace /// Chargement des submesh // Actuellement le loader ne charge qu'un submesh - std::unique_ptr indexBuffer(new NzIndexBuffer(header.num_tris * 3, false, parameters.storage, nzBufferUsage_Static)); + std::unique_ptr indexBuffer(new NzIndexBuffer(false, header.num_tris * 3, parameters.storage, nzBufferUsage_Static)); indexBuffer->SetPersistent(false); /// Lecture des triangles @@ -149,7 +149,7 @@ namespace } #endif - std::unique_ptr vertexBuffer(new NzVertexBuffer(NzMesh::GetDeclaration(), header.num_vertices, parameters.storage, nzBufferUsage_Static)); + std::unique_ptr vertexBuffer(new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent), header.num_vertices, parameters.storage, nzBufferUsage_Static)); std::unique_ptr subMesh(new NzStaticMesh(mesh)); if (!subMesh->Create(vertexBuffer.get())) { diff --git a/src/Nazara/Utility/Loaders/MD5Mesh/Parser.cpp b/src/Nazara/Utility/Loaders/MD5Mesh/Parser.cpp index 0b4468368..0cbe2a06b 100644 --- a/src/Nazara/Utility/Loaders/MD5Mesh/Parser.cpp +++ b/src/Nazara/Utility/Loaders/MD5Mesh/Parser.cpp @@ -292,7 +292,7 @@ bool NzMD5MeshParser::Parse(NzMesh* mesh) // Index buffer bool largeIndices = (vertexCount > std::numeric_limits::max()); - std::unique_ptr indexBuffer(new NzIndexBuffer(indexCount, largeIndices, m_parameters.storage)); + std::unique_ptr indexBuffer(new NzIndexBuffer(largeIndices, indexCount, m_parameters.storage)); indexBuffer->SetPersistent(false); NzIndexMapper indexMapper(indexBuffer.get(), nzBufferAccess_DiscardAndWrite); @@ -308,7 +308,7 @@ bool NzMD5MeshParser::Parse(NzMesh* mesh) indexMapper.Unmap(); // Vertex buffer - std::unique_ptr vertexBuffer(new NzVertexBuffer(NzMesh::GetDeclaration(), vertexCount, m_parameters.storage)); + std::unique_ptr vertexBuffer(new NzVertexBuffer(NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent), vertexCount, m_parameters.storage)); NzBufferMapper vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly); NzMeshVertex* vertex = reinterpret_cast(vertexMapper.GetPointer()); diff --git a/src/Nazara/Utility/Mesh.cpp b/src/Nazara/Utility/Mesh.cpp index 01b557f76..54c114e14 100644 --- a/src/Nazara/Utility/Mesh.cpp +++ b/src/Nazara/Utility/Mesh.cpp @@ -170,6 +170,8 @@ NzSubMesh* NzMesh::BuildSubMesh(const NzPrimitive& primitive, const NzMeshParams NzMatrix4f matrix(primitive.matrix); matrix.ApplyScale(params.scale); + NzVertexDeclaration* declaration = NzVertexDeclaration::Get(nzVertexLayout_XYZ_Normal_UV_Tangent); + switch (primitive.type) { case nzPrimitiveType_Box: @@ -181,7 +183,7 @@ NzSubMesh* NzMesh::BuildSubMesh(const NzPrimitive& primitive, const NzMeshParams indexBuffer.reset(new NzIndexBuffer(indexCount, vertexCount > std::numeric_limits::max(), params.storage, nzBufferUsage_Static)); indexBuffer->SetPersistent(false); - vertexBuffer.reset(new NzVertexBuffer(GetDeclaration(), vertexCount, params.storage, nzBufferUsage_Static)); + vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static)); vertexBuffer->SetPersistent(false); NzBufferMapper vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly); @@ -200,7 +202,7 @@ NzSubMesh* NzMesh::BuildSubMesh(const NzPrimitive& primitive, const NzMeshParams indexBuffer.reset(new NzIndexBuffer(indexCount, vertexCount > std::numeric_limits::max(), params.storage, nzBufferUsage_Static)); indexBuffer->SetPersistent(false); - vertexBuffer.reset(new NzVertexBuffer(GetDeclaration(), vertexCount, params.storage, nzBufferUsage_Static)); + vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static)); vertexBuffer->SetPersistent(false); NzBufferMapper vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly); @@ -223,7 +225,7 @@ NzSubMesh* NzMesh::BuildSubMesh(const NzPrimitive& primitive, const NzMeshParams indexBuffer.reset(new NzIndexBuffer(indexCount, vertexCount > std::numeric_limits::max(), params.storage, nzBufferUsage_Static)); indexBuffer->SetPersistent(false); - vertexBuffer.reset(new NzVertexBuffer(GetDeclaration(), vertexCount, params.storage, nzBufferUsage_Static)); + vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static)); vertexBuffer->SetPersistent(false); NzBufferMapper vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly); @@ -242,7 +244,7 @@ NzSubMesh* NzMesh::BuildSubMesh(const NzPrimitive& primitive, const NzMeshParams indexBuffer.reset(new NzIndexBuffer(indexCount, vertexCount > std::numeric_limits::max(), params.storage, nzBufferUsage_Static)); indexBuffer->SetPersistent(false); - vertexBuffer.reset(new NzVertexBuffer(GetDeclaration(), vertexCount, params.storage, nzBufferUsage_Static)); + vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static)); vertexBuffer->SetPersistent(false); NzBufferMapper vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly); @@ -261,7 +263,7 @@ NzSubMesh* NzMesh::BuildSubMesh(const NzPrimitive& primitive, const NzMeshParams indexBuffer.reset(new NzIndexBuffer(indexCount, vertexCount > std::numeric_limits::max(), params.storage, nzBufferUsage_Static)); indexBuffer->SetPersistent(false); - vertexBuffer.reset(new NzVertexBuffer(GetDeclaration(), vertexCount, params.storage, nzBufferUsage_Static)); + vertexBuffer.reset(new NzVertexBuffer(declaration, vertexCount, params.storage, nzBufferUsage_Static)); vertexBuffer->SetPersistent(false); NzBufferMapper vertexMapper(vertexBuffer.get(), nzBufferAccess_WriteOnly); @@ -979,36 +981,6 @@ void NzMesh::Transform(const NzMatrix4f& matrix) m_impl->aabbUpdated = false; } -const NzVertexDeclaration* NzMesh::GetDeclaration() -{ - static NzVertexDeclaration declaration; - - if (!declaration.IsValid()) - { - // Déclaration correspondant à NzVertexStruct_XYZ_Normal_UV_Tangent - NzVertexElement elements[4]; - elements[0].offset = 0; - elements[0].type = nzElementType_Float3; - elements[0].usage = nzElementUsage_Position; - - elements[1].offset = 3*sizeof(float); - elements[1].type = nzElementType_Float3; - elements[1].usage = nzElementUsage_Normal; - - elements[2].offset = 3*sizeof(float) + 3*sizeof(float); - elements[2].type = nzElementType_Float2; - elements[2].usage = nzElementUsage_TexCoord; - - elements[3].offset = 3*sizeof(float) + 3*sizeof(float) + 2*sizeof(float); - elements[3].type = nzElementType_Float3; - elements[3].usage = nzElementUsage_Tangent; - - declaration.Create(elements, 4); - } - - return &declaration; -} - void NzMesh::OnResourceReleased(const NzResource* resource, int index) { NazaraUnused(resource); diff --git a/src/Nazara/Utility/SoftwareBuffer.cpp b/src/Nazara/Utility/SoftwareBuffer.cpp index 02889ac6b..d511a4ac9 100644 --- a/src/Nazara/Utility/SoftwareBuffer.cpp +++ b/src/Nazara/Utility/SoftwareBuffer.cpp @@ -61,11 +61,6 @@ bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int return true; } -void* NzSoftwareBuffer::GetPointer() -{ - return m_buffer; -} - bool NzSoftwareBuffer::IsHardware() const { return false; diff --git a/src/Nazara/Utility/SoftwareBuffer.hpp b/src/Nazara/Utility/SoftwareBuffer.hpp index d8705f70d..41dd37787 100644 --- a/src/Nazara/Utility/SoftwareBuffer.hpp +++ b/src/Nazara/Utility/SoftwareBuffer.hpp @@ -21,8 +21,6 @@ class NzSoftwareBuffer : public NzAbstractBuffer bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard); - void* GetPointer(); - bool IsHardware() const; void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0); diff --git a/src/Nazara/Utility/Utility.cpp b/src/Nazara/Utility/Utility.cpp index c8fd422a3..1d64aab57 100644 --- a/src/Nazara/Utility/Utility.cpp +++ b/src/Nazara/Utility/Utility.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -60,6 +61,14 @@ bool NzUtility::Initialize() return false; } + if (!NzVertexDeclaration::Initialize()) + { + NazaraError("Failed to initialize vertex declarations"); + Uninitialize(); + + return false; + } + if (!NzWindow::Initialize()) { NazaraError("Failed to initialize window's system"); @@ -117,6 +126,7 @@ void NzUtility::Uninitialize() NzLoaders_STB_Unregister(); NzWindow::Uninitialize(); + NzVertexDeclaration::Uninitialize(); NzPixelFormat::Uninitialize(); NzBuffer::Uninitialize(); diff --git a/src/Nazara/Utility/VertexBuffer.cpp b/src/Nazara/Utility/VertexBuffer.cpp index ee73b0b5e..b899ae33b 100644 --- a/src/Nazara/Utility/VertexBuffer.cpp +++ b/src/Nazara/Utility/VertexBuffer.cpp @@ -7,80 +7,95 @@ #include #include -///FIXME: Gérer efficacement les erreurs de création du buffer - -NzVertexBuffer::NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer, unsigned int startVertex, unsigned int vertexCount) : +NzVertexBuffer::NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, NzBuffer* buffer, unsigned int startOffset, unsigned int endOffset) : m_buffer(buffer), m_vertexDeclaration(vertexDeclaration), -m_ownsBuffer(false), -m_startVertex(startVertex), -m_vertexCount(vertexCount) +m_endOffset(endOffset), +m_startOffset(startOffset) { #ifdef NAZARA_DEBUG + if (!m_vertexDeclaration) + { + NazaraError("Vertex declaration is invalid"); + throw std::invalid_argument("Invalid vertex declaration"); + } + if (!m_buffer || !m_buffer->IsValid()) { NazaraError("Buffer is invalid"); throw std::invalid_argument("Buffer must be valid"); } - if (!m_vertexDeclaration || !m_vertexDeclaration->IsValid()) + if (endOffset > startOffset) { - NazaraError("Vertex declaration is invalid"); - throw std::invalid_argument("Invalid vertex declaration"); + NazaraError("End offset cannot be over start offset"); + throw std::invalid_argument("End offset cannot be over start offset"); + } + + unsigned int bufferSize = m_buffer->GetSize(); + if (startOffset >= bufferSize) + { + NazaraError("Start offset is over buffer size"); + throw std::invalid_argument("Start offset is over buffer size"); + } + + if (endOffset >= bufferSize) + { + NazaraError("End offset is over buffer size"); + throw std::invalid_argument("End offset is over buffer size"); } #endif + + m_vertexCount = (endOffset - startOffset) / m_vertexDeclaration->GetStride(); } NzVertexBuffer::NzVertexBuffer(const NzVertexDeclaration* vertexDeclaration, unsigned int length, nzBufferStorage storage, nzBufferUsage usage) : m_vertexDeclaration(vertexDeclaration), -m_ownsBuffer(true), -m_startVertex(0), +m_startOffset(0), m_vertexCount(length) { #ifdef NAZARA_DEBUG - if (!m_vertexDeclaration || !m_vertexDeclaration->IsValid()) + if (!m_vertexDeclaration) { NazaraError("Vertex declaration is invalid"); throw std::invalid_argument("Invalid vertex declaration"); } #endif - m_buffer = new NzBuffer(nzBufferType_Vertex, length, vertexDeclaration->GetStride(nzElementStream_VertexData), storage, usage); + m_endOffset = length*vertexDeclaration->GetStride(); + + m_buffer = new NzBuffer(nzBufferType_Vertex, m_endOffset, storage, usage); m_buffer->SetPersistent(false); } NzVertexBuffer::NzVertexBuffer(const NzVertexBuffer& vertexBuffer) : -NzResource(true), +NzResource(), +m_buffer(vertexBuffer.m_buffer), m_vertexDeclaration(vertexBuffer.m_vertexDeclaration), -m_ownsBuffer(vertexBuffer.m_ownsBuffer), -m_startVertex(vertexBuffer.m_startVertex), +m_endOffset(vertexBuffer.m_endOffset), +m_startOffset(vertexBuffer.m_startOffset), m_vertexCount(vertexBuffer.m_vertexCount) { - if (m_ownsBuffer) - { - NzBuffer* buffer = vertexBuffer.m_buffer; - - m_buffer = new NzBuffer(nzBufferType_Vertex, buffer->GetLength(), buffer->GetSize(), buffer->GetStorage(), buffer->GetUsage()); - m_buffer->SetPersistent(false); - m_buffer->CopyContent(*vertexBuffer.m_buffer); - } - else - m_buffer = vertexBuffer.m_buffer; } -NzVertexBuffer::~NzVertexBuffer() = default; - -bool NzVertexBuffer::Fill(const void* data, unsigned int offset, unsigned int length, bool forceDiscard) +bool NzVertexBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard) { #if NAZARA_UTILITY_SAFE - if (offset+length > m_vertexCount) + if (m_startOffset + offset + size > m_endOffset) { NazaraError("Exceeding virtual buffer size"); return false; } #endif - return m_buffer->Fill(data, m_startVertex+offset, length, forceDiscard); + return m_buffer->Fill(data, m_startOffset+offset, size, forceDiscard); +} + +bool NzVertexBuffer::FillVertices(const void* data, unsigned int startVertex, unsigned int length, bool forceDiscard) +{ + unsigned int stride = m_vertexDeclaration->GetStride(); + + return Fill(data, startVertex*stride, length*stride, forceDiscard); } NzBuffer* NzVertexBuffer::GetBuffer() const @@ -88,24 +103,19 @@ NzBuffer* NzVertexBuffer::GetBuffer() const return m_buffer; } -void* NzVertexBuffer::GetPointer() +unsigned int NzVertexBuffer::GetEndOffset() const { - return reinterpret_cast(m_buffer->GetPointer()) + m_startVertex*m_buffer->GetTypeSize(); + return m_endOffset; } -const void* NzVertexBuffer::GetPointer() const +unsigned int NzVertexBuffer::GetStartOffset() const { - return reinterpret_cast(m_buffer->GetPointer()) + m_startVertex*m_buffer->GetTypeSize(); + return m_startOffset; } -unsigned int NzVertexBuffer::GetStartVertex() const +unsigned int NzVertexBuffer::GetStride() const { - return m_startVertex; -} - -nzUInt8 NzVertexBuffer::GetTypeSize() const -{ - return m_buffer->GetTypeSize(); + return m_vertexDeclaration->GetStride(); } unsigned int NzVertexBuffer::GetVertexCount() const @@ -123,30 +133,44 @@ bool NzVertexBuffer::IsHardware() const return m_buffer->IsHardware(); } -void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) +void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size) { #if NAZARA_UTILITY_SAFE - if (offset+length > m_vertexCount) + if (m_startOffset + offset + size > m_endOffset) { NazaraError("Exceeding virtual buffer size"); - return nullptr; + return false; } #endif - return m_buffer->Map(access, m_startVertex+offset, (length) ? length : m_vertexCount-offset); + return m_buffer->Map(access, offset, size); } -void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) const +void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size) const { #if NAZARA_UTILITY_SAFE - if (offset+length > m_vertexCount) + if (m_startOffset + offset + size > m_endOffset) { NazaraError("Exceeding virtual buffer size"); return nullptr; } #endif - return m_buffer->Map(access, m_startVertex+offset, (length) ? length : m_vertexCount-offset); + return m_buffer->Map(access, offset, size); +} + +void* NzVertexBuffer::MapVertices(nzBufferAccess access, unsigned int startVertex, unsigned int length) +{ + unsigned int stride = m_vertexDeclaration->GetStride(); + + return Map(access, startVertex*stride, length*stride); +} + +void* NzVertexBuffer::MapVertices(nzBufferAccess access, unsigned int startVertex, unsigned int length) const +{ + unsigned int stride = m_vertexDeclaration->GetStride(); + + return Map(access, startVertex*stride, length*stride); } bool NzVertexBuffer::SetStorage(nzBufferStorage storage) @@ -154,6 +178,20 @@ bool NzVertexBuffer::SetStorage(nzBufferStorage storage) return m_buffer->SetStorage(storage); } +void NzVertexBuffer::SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration) +{ + #if NAZARA_UTILITY_SAFE + if (!vertexDeclaration) + { + NazaraError("Vertex declaration is invalid"); + return; + } + #endif + + m_vertexCount = (m_endOffset - m_startOffset)/vertexDeclaration->GetStride(); + m_vertexDeclaration = vertexDeclaration; +} + void NzVertexBuffer::Unmap() const { m_buffer->Unmap(); diff --git a/src/Nazara/Utility/VertexDeclaration.cpp b/src/Nazara/Utility/VertexDeclaration.cpp index 7721f6969..61b8caa9a 100644 --- a/src/Nazara/Utility/VertexDeclaration.cpp +++ b/src/Nazara/Utility/VertexDeclaration.cpp @@ -5,386 +5,192 @@ #include #include #include -#include -#include #include -#include -#include #include namespace { - const unsigned int elementCount[] = + unsigned int attributeSize[nzAttributeType_Max+1] = { - 4, // nzElementType_Color - 1, // nzElementType_Double1 - 2, // nzElementType_Double2 - 3, // nzElementType_Double3 - 4, // nzElementType_Double4 - 1, // nzElementType_Float1 - 2, // nzElementType_Float2 - 3, // nzElementType_Float3 - 4 // nzElementType_Float4 + 4, // nzAttributeType_Color + 1, // nzAttributeType_Double1 + 2, // nzAttributeType_Double2 + 3, // nzAttributeType_Double3 + 4, // nzAttributeType_Double4 + 1, // nzAttributeType_Float1 + 2, // nzAttributeType_Float2 + 3, // nzAttributeType_Float3 + 4 // nzAttributeType_Float4 }; - const unsigned int elementSize[] = + unsigned int attributeStride[nzAttributeType_Max+1] = { - 4*sizeof(nzUInt8), // nzElementType_Color - 1*sizeof(double), // nzElementType_Double1 - 2*sizeof(double), // nzElementType_Double2 - 3*sizeof(double), // nzElementType_Double3 - 4*sizeof(double), // nzElementType_Double4 - 1*sizeof(float), // nzElementType_Float1 - 2*sizeof(float), // nzElementType_Float2 - 3*sizeof(float), // nzElementType_Float3 - 4*sizeof(float) // nzElementType_Float4 + 4*sizeof(nzUInt8), // nzAttributeType_Color + 1*sizeof(double), // nzAttributeType_Double1 + 2*sizeof(double), // nzAttributeType_Double2 + 3*sizeof(double), // nzAttributeType_Double3 + 4*sizeof(double), // nzAttributeType_Double4 + 1*sizeof(float), // nzAttributeType_Float1 + 2*sizeof(float), // nzAttributeType_Float2 + 3*sizeof(float), // nzAttributeType_Float3 + 4*sizeof(float) // nzAttributeType_Float4 }; - - bool VertexElementCompare(const NzVertexElement& elementA, const NzVertexElement& elementB) - { - // Nous classons d'abord par stream - if (elementA.stream == elementB.stream) - { - // Ensuite par usage - if (elementA.usage == elementB.usage) - // Et finalement par usageIndex - return elementA.usageIndex < elementB.usageIndex; - else - return elementA.usage < elementB.usage; - } - else - return elementA.stream < elementB.stream; - } } -struct NzVertexDeclarationImpl +NzVertexDeclaration::NzVertexDeclaration() : +m_stride(0) { - NzVertexDeclarationImpl() : - refCount(1) - { - } +} - std::vector elements; - int elementPos[nzElementStream_Max+1][nzElementUsage_Max+1]; - int streamPos[nzElementStream_Max+1]; - unsigned int stride[nzElementStream_Max+1] = {0}; +NzVertexDeclaration::NzVertexDeclaration(NzVertexDeclaration& declaration) : +NzResource(), +m_stride(declaration.m_stride) +{ + std::memcpy(m_attributes, declaration.m_attributes, sizeof(Attribute)*(nzAttributeUsage_Max+1)); +} - std::atomic_ushort refCount; -}; - -NzVertexDeclaration::NzVertexDeclaration(const NzVertexElement* elements, unsigned int elementCount) +void NzVertexDeclaration::DisableAttribute(nzAttributeUsage usage) { #ifdef NAZARA_DEBUG - if (!Create(elements, elementCount)) + if (usage > nzAttributeUsage_Max) { - NazaraError("Failed to create declaration"); - throw std::runtime_error("Constructor failed"); - } - #else - Create(elements, elementCount); - #endif -} - -NzVertexDeclaration::NzVertexDeclaration(const NzVertexDeclaration& declaration) : -NzResource(), -m_sharedImpl(declaration.m_sharedImpl) -{ - if (m_sharedImpl) - m_sharedImpl->refCount++; -} - -NzVertexDeclaration::NzVertexDeclaration(NzVertexDeclaration&& declaration) noexcept : -m_sharedImpl(declaration.m_sharedImpl) -{ - declaration.m_sharedImpl = nullptr; -} - -NzVertexDeclaration::~NzVertexDeclaration() -{ - Destroy(); -} - -bool NzVertexDeclaration::Create(const NzVertexElement* elements, unsigned int elementCount) -{ - Destroy(); - - #if NAZARA_UTILITY_SAFE - if (!elements || elementCount == 0) - { - NazaraError("No element"); - return false; - } - #endif - - NzVertexDeclarationImpl* impl = new NzVertexDeclarationImpl; - std::memset(&impl->elementPos, -1, (nzElementStream_Max+1)*(nzElementUsage_Max+1)*sizeof(int)); - std::memset(&impl->streamPos, -1, (nzElementStream_Max+1)*sizeof(int)); - - // On copie et trions les éléments - impl->elements.resize(elementCount); - std::memcpy(&impl->elements[0], elements, elementCount*sizeof(NzVertexElement)); - std::sort(impl->elements.begin(), impl->elements.end(), VertexElementCompare); - - for (unsigned int i = 0; i < elementCount; ++i) - { - NzVertexElement& current = impl->elements[i]; - #if NAZARA_UTILITY_SAFE - // Notre tableau étant trié, s'il y a collision, les deux éléments identiques se suivent... - if (i > 0) - { - NzVertexElement& previous = impl->elements[i-1]; // On accède à l'élément précédent - if (previous.usage == current.usage && previous.usageIndex == current.usageIndex && previous.stream == current.stream) - { - // Les deux éléments sont identiques là où ils ne devraient pas, nous avons une collision... - NazaraError("Element usage 0x" + NzString::Number(current.usage, 16) + " collision with usage index " + NzString::Number(current.usageIndex) + " on stream 0x" + NzString::Number(current.stream, 16)); - delete impl; - - return false; - } - } - #endif - - if (current.usageIndex == 0) - impl->elementPos[current.stream][current.usage] = i; - - if (impl->streamPos[current.stream] == -1) - impl->streamPos[current.stream] = i; // Premier élément du stream (via le triage) - - impl->stride[current.stream] += elementSize[current.type]; - } - - #if NAZARA_UTILITY_FORCE_DECLARATION_STRIDE_MULTIPLE_OF_32 - for (unsigned int& stride : impl->stride) - stride = ((static_cast(stride)-1)/32+1)*32; - #endif - - m_sharedImpl = impl; - - NotifyCreated(); - return true; -} - -void NzVertexDeclaration::Destroy() -{ - if (!m_sharedImpl) + NazaraError("Attribute usage out of enum"); return; - - NotifyDestroy(); - - if (--m_sharedImpl->refCount == 0) - delete m_sharedImpl; - - m_sharedImpl = nullptr; -} - -const NzVertexElement* NzVertexDeclaration::GetElement(unsigned int i) const -{ - #if NAZARA_UTILITY_SAFE - if (!m_sharedImpl) - { - NazaraError("Declaration not created"); - return nullptr; - } - - if (i >= m_sharedImpl->elements.size()) - { - NazaraError("Element index out of range (" + NzString::Number(i) + " >= " + NzString::Number(m_sharedImpl->elements.size()) + ')'); - return nullptr; } #endif - return &m_sharedImpl->elements[i]; + Attribute& attribute = m_attributes[usage]; + + if (attribute.enabled) + { + attribute.enabled = false; + m_stride -= attributeStride[attribute.type]; + } } -const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, unsigned int i) const +void NzVertexDeclaration::EnableAttribute(nzAttributeUsage usage, nzAttributeType type, unsigned int offset) { - #if NAZARA_UTILITY_SAFE - if (!m_sharedImpl) + #ifdef NAZARA_DEBUG + if (usage > nzAttributeUsage_Max) { - NazaraError("Declaration not created"); - return nullptr; - } - - int streamPos = m_sharedImpl->streamPos[stream]; - if (streamPos == -1) - { - NazaraError("Declaration has no stream 0x" + NzString::Number(stream, 16)); - return nullptr; - } - - unsigned int upperLimit = GetElementCount(stream); - if (i >= upperLimit) - { - NazaraError("Element index out of range (" + NzString::Number(i) + " >= " + NzString::Number(upperLimit) + ')'); - return nullptr; + NazaraError("Attribute usage out of enum"); + return; } #endif - return &m_sharedImpl->elements[m_sharedImpl->streamPos[stream]+i]; -} + Attribute& attribute = m_attributes[usage]; -const NzVertexElement* NzVertexDeclaration::GetElement(nzElementStream stream, nzElementUsage usage, unsigned int usageIndex) const -{ - #if NAZARA_UTILITY_SAFE - if (!m_sharedImpl) - { - NazaraError("Declaration not created"); - return nullptr; - } - #endif - - int elementPos = m_sharedImpl->elementPos[stream][usage]; - if (elementPos == -1) - return nullptr; - - if (usageIndex == 0) // Si l'usage index vaut zéro, alors nous sommes certains d'être sur le bon élément (Majorité des cas) - return &m_sharedImpl->elements[elementPos]; + if (attribute.enabled) + m_stride -= attributeStride[attribute.type]; else - { - elementPos += usageIndex; - if (static_cast(elementPos) >= m_sharedImpl->elements.size()) - return nullptr; + attribute.enabled = true; - NzVertexElement& element = m_sharedImpl->elements[elementPos]; - if (element.stream != stream || element.usage != usage || element.usageIndex != usageIndex) - return nullptr; + attribute.offset = offset; + attribute.type = type; - return &element; - } + m_stride += attributeStride[type]; } -unsigned int NzVertexDeclaration::GetElementCount() const +void NzVertexDeclaration::GetAttribute(nzAttributeUsage usage, bool* enabled, nzAttributeType* type, unsigned int* offset) const { - #if NAZARA_UTILITY_SAFE - if (!m_sharedImpl) + #ifdef NAZARA_DEBUG + if (usage > nzAttributeUsage_Max) { - NazaraError("Declaration not created"); - return 0; + NazaraError("Attribute usage out of enum"); + return; } #endif - return m_sharedImpl->elements.size(); + const Attribute& attribute = m_attributes[usage]; + + if (enabled) + *enabled = attribute.enabled; + + if (type) + *type = attribute.type; + + if (offset) + *offset = attribute.offset; } -unsigned int NzVertexDeclaration::GetElementCount(nzElementStream stream) const +unsigned int NzVertexDeclaration::GetStride() const { - #if NAZARA_UTILITY_SAFE - if (!m_sharedImpl) - { - NazaraError("Declaration not created"); - return 0; - } - #endif - - int streamPos = m_sharedImpl->streamPos[stream]; - if (streamPos == -1) - return 0; - - unsigned int upperLimit = 0; - if (stream == nzElementStream_Max) - upperLimit = m_sharedImpl->elements.size(); - else - { - for (unsigned int upperStream = stream+1; upperStream <= nzElementStream_Max; ++upperStream) - { - if (m_sharedImpl->streamPos[upperStream] != -1) - { - upperLimit = m_sharedImpl->streamPos[upperStream]; - break; - } - else if (upperStream == nzElementStream_Max) // Dernier stream, toujours pas de limite - upperLimit = m_sharedImpl->elements.size(); - } - } - - return upperLimit-streamPos; + return m_stride; } -unsigned int NzVertexDeclaration::GetStride(nzElementStream stream) const +void NzVertexDeclaration::SetStride(unsigned int stride) { - #if NAZARA_UTILITY_SAFE - if (!m_sharedImpl) - { - NazaraError("Declaration not created"); - return 0; - } - #endif - - return m_sharedImpl->stride[stream]; -} - -bool NzVertexDeclaration::HasElement(unsigned int i) const -{ - return i < m_sharedImpl->elements.size(); -} - -bool NzVertexDeclaration::HasElement(nzElementStream stream, unsigned int i) const -{ - return i < GetElementCount(stream); -} - -bool NzVertexDeclaration::HasElement(nzElementStream stream, nzElementUsage usage, unsigned int usageIndex) const -{ - int elementPos = m_sharedImpl->elementPos[stream][usage]; - if (elementPos == -1) - return false; - - elementPos += usageIndex; - if (static_cast(elementPos) >= m_sharedImpl->elements.size()) - return false; - - NzVertexElement& element = m_sharedImpl->elements[elementPos]; - if (element.stream != stream || element.usage != usage || element.usageIndex != usageIndex) - return false; - - return true; -} - -bool NzVertexDeclaration::HasStream(nzElementStream stream) const -{ - #if NAZARA_UTILITY_SAFE - if (!m_sharedImpl) - { - NazaraError("Declaration not created"); - return false; - } - #endif - - return m_sharedImpl->streamPos[stream] != -1; -} - -bool NzVertexDeclaration::IsValid() const -{ - return m_sharedImpl != nullptr; + m_stride = stride; } NzVertexDeclaration& NzVertexDeclaration::operator=(const NzVertexDeclaration& declaration) { - Destroy(); - - m_sharedImpl = declaration.m_sharedImpl; - if (m_sharedImpl) - m_sharedImpl->refCount++; + std::memcpy(m_attributes, declaration.m_attributes, sizeof(Attribute)*(nzAttributeUsage_Max+1)); + m_stride = declaration.m_stride; return *this; } -NzVertexDeclaration& NzVertexDeclaration::operator=(NzVertexDeclaration&& declaration) noexcept +NzVertexDeclaration* NzVertexDeclaration::Get(nzVertexLayout layout) { - Destroy(); + #ifdef NAZARA_DEBUG + if (layout > nzVertexLayout_Max) + { + NazaraError("Vertex layout out of enum"); + return nullptr; + } + #endif - m_sharedImpl = declaration.m_sharedImpl; - declaration.m_sharedImpl = nullptr; - - return *this; + return &s_declarations[layout]; } -unsigned int NzVertexDeclaration::GetElementCount(nzElementType type) +unsigned int NzVertexDeclaration::GetAttributeSize(nzAttributeType type) { - return elementCount[type]; + #ifdef NAZARA_DEBUG + if (type > nzAttributeType_Max) + { + NazaraError("Attribute type out of enum"); + return 0; + } + #endif + + return attributeSize[type]; } -unsigned int NzVertexDeclaration::GetElementSize(nzElementType type) +bool NzVertexDeclaration::Initialize() { - return elementSize[type]; + s_declarations[nzVertexLayout_XY].EnableAttribute(nzAttributeUsage_Position, nzAttributeType_Float2, 0); + + s_declarations[nzVertexLayout_XY_UV].EnableAttribute(nzAttributeUsage_Position, nzAttributeType_Float2, 0); + s_declarations[nzVertexLayout_XY_UV].EnableAttribute(nzAttributeUsage_TexCoord, nzAttributeType_Float2, 2*sizeof(float)); + + s_declarations[nzVertexLayout_XYZ].EnableAttribute(nzAttributeUsage_Position, nzAttributeType_Float3, 0); + + s_declarations[nzVertexLayout_XYZ_Normal].EnableAttribute(nzAttributeUsage_Position, nzAttributeType_Float3, 0); + s_declarations[nzVertexLayout_XYZ_Normal].EnableAttribute(nzAttributeUsage_Normal, nzAttributeType_Float3, 3*sizeof(float)); + + s_declarations[nzVertexLayout_XYZ_Normal_UV].EnableAttribute(nzAttributeUsage_Position, nzAttributeType_Float3, 0); + s_declarations[nzVertexLayout_XYZ_Normal_UV].EnableAttribute(nzAttributeUsage_Normal, nzAttributeType_Float3, 3*sizeof(float)); + s_declarations[nzVertexLayout_XYZ_Normal_UV].EnableAttribute(nzAttributeUsage_TexCoord, nzAttributeType_Float2, (3+3)*sizeof(float)); + + s_declarations[nzVertexLayout_XYZ_Normal_UV_Tangent].EnableAttribute(nzAttributeUsage_Position, nzAttributeType_Float3, 0); + s_declarations[nzVertexLayout_XYZ_Normal_UV_Tangent].EnableAttribute(nzAttributeUsage_Normal, nzAttributeType_Float3, 3*sizeof(float)); + s_declarations[nzVertexLayout_XYZ_Normal_UV_Tangent].EnableAttribute(nzAttributeUsage_TexCoord, nzAttributeType_Float2, (3+3)*sizeof(float)); + s_declarations[nzVertexLayout_XYZ_Normal_UV_Tangent].EnableAttribute(nzAttributeUsage_Tangent, nzAttributeType_Float3, (3+3+2)*sizeof(float)); + + s_declarations[nzVertexLayout_XYZ_UV].EnableAttribute(nzAttributeUsage_Position, nzAttributeType_Float3, 0); + s_declarations[nzVertexLayout_XYZ_UV].EnableAttribute(nzAttributeUsage_TexCoord, nzAttributeType_Float2, 3*sizeof(float)); + + s_declarations[nzVertexLayout_Matrix4].EnableAttribute(nzAttributeUsage_InstanceData0, nzAttributeType_Float4, 0*4*sizeof(float)); + s_declarations[nzVertexLayout_Matrix4].EnableAttribute(nzAttributeUsage_InstanceData1, nzAttributeType_Float4, 1*4*sizeof(float)); + s_declarations[nzVertexLayout_Matrix4].EnableAttribute(nzAttributeUsage_InstanceData2, nzAttributeType_Float4, 2*4*sizeof(float)); + s_declarations[nzVertexLayout_Matrix4].EnableAttribute(nzAttributeUsage_InstanceData3, nzAttributeType_Float4, 3*4*sizeof(float)); + + return true; } + +void NzVertexDeclaration::Uninitialize() +{ +} + +NzVertexDeclaration NzVertexDeclaration::s_declarations[nzVertexLayout_Max+1];