From b667df3537d393ceefa60a877307cf817017e546 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Sun, 22 Oct 2023 19:50:09 -0700 Subject: [PATCH 01/17] feat: reorganize binding logic Signed-off-by: Michael Pollind --- HPL2/include/engine/SaveGame.h | 13 - HPL2/include/graphics/DrawPacket.h | 43 + HPL2/include/graphics/MeshCreator.h | 14 - HPL2/include/graphics/MeshUtility.h | 83 +- HPL2/include/graphics/Renderable.h | 6 +- HPL2/include/impl/LegacyVertexBuffer.h | 4 +- HPL2/include/scene/Beam.h | 13 +- HPL2/include/scene/BillBoard.h | 7 +- HPL2/include/scene/DummyRenderable.h | 19 +- HPL2/include/scene/FogArea.h | 9 +- HPL2/include/scene/GuiSetEntity.h | 9 +- HPL2/include/scene/Light.h | 14 +- HPL2/include/scene/LightBox.h | 4 +- HPL2/include/scene/ParticleEmitter.h | 28 +- HPL2/include/scene/RopeEntity.h | 14 +- HPL2/include/scene/SubMeshEntity.h | 1 + HPL2/sources/graphics/DecalCreator.cpp | 1 - HPL2/sources/graphics/DrawPacket.cpp | 32 + HPL2/sources/graphics/MeshCreator.cpp | 528 ------------- HPL2/sources/graphics/MeshUtility.cpp | 736 +++++++++++++++++- HPL2/sources/graphics/RendererDeferred.cpp | 203 +++-- HPL2/sources/graphics/RendererWireFrame.cpp | 13 +- HPL2/sources/impl/LegacyVertexBuffer.cpp | 48 +- HPL2/sources/resources/EntFileManager.cpp | 38 - HPL2/sources/resources/WorldLoaderHplMap.cpp | 64 +- HPL2/sources/scene/Beam.cpp | 12 +- HPL2/sources/scene/BillBoard.cpp | 12 +- HPL2/sources/scene/FogArea.cpp | 22 +- HPL2/sources/scene/ParticleEmitter.cpp | 7 +- HPL2/sources/scene/RopeEntity.cpp | 21 +- HPL2/sources/scene/SubMeshEntity.cpp | 8 + amnesia/game/LuxEffectRenderer.cpp | 48 +- tools/NewEditors/Common/EdEngineObject.cpp | 10 - .../editors/common/EntityWrapperBodyShape.cpp | 83 +- .../common/EntityWrapperPrimitivePlane.cpp | 60 +- 35 files changed, 1285 insertions(+), 942 deletions(-) create mode 100644 HPL2/include/graphics/DrawPacket.h create mode 100644 HPL2/sources/graphics/DrawPacket.cpp diff --git a/HPL2/include/engine/SaveGame.h b/HPL2/include/engine/SaveGame.h index ccac807d6..6fc4fa604 100644 --- a/HPL2/include/engine/SaveGame.h +++ b/HPL2/include/engine/SaveGame.h @@ -27,19 +27,6 @@ class TiXmlElement; -#define kSaveData_LoadFromBegin(aClass) \ - __super::LoadFromSaveData(apSaveData); \ - cSaveData_##aClass *pData = static_cast(apSaveData); - -#define kSaveData_SaveToBegin(aClass) \ - __super::SaveToSaveData(apSaveData);\ - cSaveData_##aClass *pData = static_cast(apSaveData); - -#define kSaveData_SetupBegin(aClass) \ - __super::SaveDataSetup(apSaveObjectHandler,apGame);\ - cSaveData_##aClass *pData = static_cast(mpSaveData); \ - const char *sClassNameString = #aClass; - #define kSaveData_BaseClass(aClass) class cSaveData_##aClass : public iSaveData #define kSaveData_ChildClass(aParent, aChild) class cSaveData_##aChild : public cSaveData_##aParent diff --git a/HPL2/include/graphics/DrawPacket.h b/HPL2/include/graphics/DrawPacket.h new file mode 100644 index 000000000..ebb2838e4 --- /dev/null +++ b/HPL2/include/graphics/DrawPacket.h @@ -0,0 +1,43 @@ +#pragma once + +#include "graphics/ForgeHandles.h" +#include "graphics/ForgeRenderer.h" +#include + +namespace hpl { + class DrawPacket { + public: + static constexpr uint32_t MaxVertexBindings = 15; + enum DrawPacketType { + Unknown, + IndvidualBindings, // everything will be bound indvidually for the moment until + UnifiedAllocatorBinding + }; + struct VertexStream { + SharedBuffer* m_buffer; + uint64_t m_offset; + uint32_t m_stride; + }; + struct IndexStream { + SharedBuffer* buffer; + uint64_t m_offset; + }; + + static void cmdBindBuffers(Cmd* cmd, ForgeRenderer::CommandResourcePool* resourcePool, DrawPacket* packet); + + DrawPacket() + : m_type(DrawPacketType::Unknown) { + } + + DrawPacketType m_type; + uint32_t m_numIndices; + union { + struct { + uint32_t m_numStreams; + VertexStream m_vertexStream[MaxVertexBindings]; + IndexStream m_indexStream; + } m_indvidual; + }; + }; + +} // namespace hpl diff --git a/HPL2/include/graphics/MeshCreator.h b/HPL2/include/graphics/MeshCreator.h index 6f8ad8e9d..594954208 100644 --- a/HPL2/include/graphics/MeshCreator.h +++ b/HPL2/include/graphics/MeshCreator.h @@ -40,23 +40,9 @@ namespace hpl { iVertexBuffer* CreateWireframeVertexBuffer(iVertexBuffer *apSrc); - cMesh* CreateBox(const tString &asName, cVector3f avSize, const tString &asMaterial); - - cMesh* CreatePlane(const tString &asName, const cVector3f& avCorner1, const cVector3f& avCorner2, - const cVector2f& avCorner1UV, const cVector2f& avCorner2UV, const cVector2f& avCorner3UV, const cVector2f& avCorner4UV, - const tString& asMaterial); - - cMesh* CreateSphere(const tString &asName, float afRadius, int alSections, int alSlices, const tString& asMaterial); - - cMesh* CreateCylinder(const tString &asName, const cVector2f &avSize, int alSections, const tString &asMaterial); - - cMesh* CreateCapsule(const tString &asName, const cVector2f &avSize, int alSections, int alSlices, const tString &asMaterial); - cMesh* CreateCone(const tString &asName, const cVector2f &avSize, int alSections, const tString &asMaterial); iVertexBuffer* CreateSkyBoxVertexBuffer(float afSize); - iVertexBuffer* CreateBoxVertexBuffer(cVector3f avSize); - private: cVector3f GetBoxTex(int i,int x, int y, int z, cVector3f *vAdd); int GetBoxIdx(int i,int x, int y, int z); diff --git a/HPL2/include/graphics/MeshUtility.h b/HPL2/include/graphics/MeshUtility.h index fbd978d1e..b0aba1c30 100644 --- a/HPL2/include/graphics/MeshUtility.h +++ b/HPL2/include/graphics/MeshUtility.h @@ -4,11 +4,20 @@ #include "graphics/AssetBuffer.h" #include #include +#include #include "Common_3/Utilities/Math/MathTypes.h" #include "FixPreprocessor.h" namespace hpl::MeshUtility { + struct MeshCreateResult { + uint32_t numVertices; + uint32_t numIndices; + }; + + // for create might have to offset the indecies + //void OffsetIndecies(uint32_t vtxOffset, uint32_t numIndecies, AssetBuffer::BufferIndexView* index); + void Transform( uint32_t numElements, const Matrix4& transform, @@ -17,7 +26,7 @@ namespace hpl::MeshUtility { AssetBuffer::BufferStructuredView* tangent ); - void MikktSpaceGenerate( + void MikkTSpaceGenerate( uint32_t numVerts, uint32_t numIndecies, AssetBuffer::BufferIndexView* view, @@ -26,6 +35,78 @@ namespace hpl::MeshUtility { AssetBuffer::BufferStructuredView* normal, AssetBuffer::BufferStructuredView* writeTangent ); + + void CreateTriTangentVectorsHPL2( + uint32_t numVerts, + uint32_t numIndecies, + AssetBuffer::BufferIndexView* index, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* uv, + AssetBuffer::BufferStructuredView* normal, + std::variant*, AssetBuffer::BufferStructuredView*> tangent + ); + + MeshCreateResult CreateSphere( + float afRadius, + uint32_t alSections, + uint32_t alSlices, + AssetBuffer::BufferIndexView* index, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* color, + AssetBuffer::BufferStructuredView* normal, + AssetBuffer::BufferStructuredView* uv, + std::variant*, AssetBuffer::BufferStructuredView*> tangent + ); + + MeshCreateResult CreateBox( + float3 size, + AssetBuffer::BufferIndexView* index, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* color, + AssetBuffer::BufferStructuredView* normal, + AssetBuffer::BufferStructuredView* uv, + std::variant*, AssetBuffer::BufferStructuredView*> tangent + ); + MeshCreateResult CreateCylinder( + Vector2 size, + uint32_t sections, + AssetBuffer::BufferIndexView* index, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* color, + AssetBuffer::BufferStructuredView* normal, + AssetBuffer::BufferStructuredView* uv, + std::variant*, AssetBuffer::BufferStructuredView*> tangent); + + MeshCreateResult CreateCapsule( + Vector2 avSize, + int alSections, + int alSlices, + AssetBuffer::BufferIndexView* index, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* color, + AssetBuffer::BufferStructuredView* normal, + AssetBuffer::BufferStructuredView* uv, + std::variant*, AssetBuffer::BufferStructuredView*> tangent + + ); + + MeshCreateResult CreatePlane( + const std::array corners, + const std::array uvCorners, + AssetBuffer::BufferIndexView* index, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* color, + AssetBuffer::BufferStructuredView* normal, + AssetBuffer::BufferStructuredView* uv, + std::variant*, AssetBuffer::BufferStructuredView*> tangent + ); + + MeshCreateResult CreateCone(const float2 avSize, int alSections, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* color, + AssetBuffer::BufferStructuredView* normal, + AssetBuffer::BufferStructuredView* uv, + std::variant*, AssetBuffer::BufferStructuredView*> tangent); } diff --git a/HPL2/include/graphics/Renderable.h b/HPL2/include/graphics/Renderable.h index 174a0b994..b2682fad8 100644 --- a/HPL2/include/graphics/Renderable.h +++ b/HPL2/include/graphics/Renderable.h @@ -19,6 +19,8 @@ #pragma once +#include "graphics/DrawPacket.h" +#include "graphics/ForgeRenderer.h" #include "math/MathTypes.h" #include "graphics/GraphicsTypes.h" #include "system/SystemTypes.h" @@ -41,8 +43,6 @@ namespace hpl { class iPhysicsBody; class iRenderer; - //------------------------------------------ - class iRenderable : public iEntity3D { HPL_RTTI_IMPL_CLASS(iEntity3D, iRenderable, "{285bbdb4-de5b-4960-bf44-ae543432ff40}") @@ -53,7 +53,7 @@ namespace hpl { virtual cMaterial *GetMaterial()=0; virtual iVertexBuffer* GetVertexBuffer()=0; - + virtual DrawPacket ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) = 0; virtual bool CollidesWithBV(cBoundingVolume *apBV); virtual bool CollidesWithFrustum(cFrustum *apFrustum); diff --git a/HPL2/include/impl/LegacyVertexBuffer.h b/HPL2/include/impl/LegacyVertexBuffer.h index 1dd0a63cb..ae6e160a7 100644 --- a/HPL2/include/impl/LegacyVertexBuffer.h +++ b/HPL2/include/impl/LegacyVertexBuffer.h @@ -18,6 +18,7 @@ */ #pragma once +#include "graphics/DrawPacket.h" #include #include @@ -110,8 +111,7 @@ namespace hpl { folly::small_vector m_vertexElement; // elements are in the order they are requested VertexIndexEntry m_indexBuffer; }; - static void cmdBindGeometry(Cmd* cmd, ForgeRenderer::CommandResourcePool* resourcePool, LegacyVertexBuffer::GeometryBinding& binding); - void resolveGeometryBinding(uint32_t currentFrame, std::span elements, GeometryBinding* binding); + DrawPacket resolveGeometryBinding(uint32_t currentFrame, std::span elements); virtual void UnBind() override; diff --git a/HPL2/include/scene/Beam.h b/HPL2/include/scene/Beam.h index da357c8ca..62f1d64fc 100644 --- a/HPL2/include/scene/Beam.h +++ b/HPL2/include/scene/Beam.h @@ -36,13 +36,12 @@ namespace hpl { class cMaterial; class iVertexBuffer; - //------------------------------------------ class cBeam; class cBeamEnd : public iEntity3D { - friend class cBeam; - friend class cBeamEnd_UpdateCallback; + friend class cBeam; + friend class cBeamEnd_UpdateCallback; public: cBeamEnd(const tString asName, cBeam *apBeam) : iEntity3D(asName), mColor(1,1),mpBeam(apBeam) {} @@ -70,9 +69,6 @@ namespace hpl { class cBeam : public iRenderable { - #ifdef __GNUC__ - typedef iRenderable __super; - #endif friend class cBeamEnd; public: cBeam(const tString asName, cResources *apResources,cGraphics *apGraphics); @@ -112,8 +108,9 @@ namespace hpl { bool IsVisible(); //Renderable implementations - cMaterial *GetMaterial(){ return mpMaterial;} - iVertexBuffer* GetVertexBuffer(){return mpVtxBuffer;} + virtual cMaterial *GetMaterial() override{ return mpMaterial;} + virtual iVertexBuffer* GetVertexBuffer() override{return mpVtxBuffer;} + virtual DrawPacket ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) override; void UpdateGraphicsForFrame(float afFrameTime); diff --git a/HPL2/include/scene/BillBoard.h b/HPL2/include/scene/BillBoard.h index 68baacde4..9172e632c 100644 --- a/HPL2/include/scene/BillBoard.h +++ b/HPL2/include/scene/BillBoard.h @@ -17,8 +17,7 @@ * along with Amnesia: The Dark Descent. If not, see . */ -#ifndef HPL_BILLBOARD_H -#define HPL_BILLBOARD_H +#pragma once #include "math/MathTypes.h" #include "graphics/GraphicsTypes.h" @@ -83,8 +82,9 @@ namespace hpl { //Renderable implementations cMaterial *GetMaterial() override{ return mpMaterial;} iVertexBuffer* GetVertexBuffer()override{return mpVtxBuffer;} + virtual DrawPacket ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) override; - cMatrixf* GetModelMatrix(cFrustum *apFrustum)override; + cMatrixf* GetModelMatrix(cFrustum *apFrustum)override; int GetMatrixUpdateCount()override; @@ -120,4 +120,3 @@ namespace hpl { }; }; -#endif // HPL_BILLBOARD_H diff --git a/HPL2/include/scene/DummyRenderable.h b/HPL2/include/scene/DummyRenderable.h index 16971900e..943192fcb 100644 --- a/HPL2/include/scene/DummyRenderable.h +++ b/HPL2/include/scene/DummyRenderable.h @@ -20,6 +20,7 @@ #ifndef HPL_DUMMY_RENDERABLE_H #define HPL_DUMMY_RENDERABLE_H +#include "graphics/DrawPacket.h" #include "graphics/GraphicsTypes.h" #include "graphics/Renderable.h" @@ -45,17 +46,23 @@ namespace hpl { ////////////////////////////// //iEntity implementation - tString GetEntityType(){ return "cDummy";} + virtual tString GetEntityType() override{ return "cDummy";} /////////////////////////////// //Renderable implementation: - cMaterial *GetMaterial(){ return NULL;} - iVertexBuffer* GetVertexBuffer(){ return NULL;} + virtual cMaterial *GetMaterial() override { return NULL;} + virtual iVertexBuffer* GetVertexBuffer() override{ return NULL;} - eRenderableType GetRenderType(){ return eRenderableType_Dummy;} + virtual DrawPacket ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) override { + DrawPacket packet; + packet.m_type = DrawPacket::Unknown; + return packet; + } - int GetMatrixUpdateCount(){ return GetTransformUpdateCount();} - cMatrixf* GetModelMatrix(cFrustum* apFrustum); + virtual eRenderableType GetRenderType() override{ return eRenderableType_Dummy;} + + virtual int GetMatrixUpdateCount() override{ return GetTransformUpdateCount();} + virtual cMatrixf* GetModelMatrix(cFrustum* apFrustum) override; private: cMatrixf m_mtxModelOutput; diff --git a/HPL2/include/scene/FogArea.h b/HPL2/include/scene/FogArea.h index da9faf26e..b78ed38c7 100644 --- a/HPL2/include/scene/FogArea.h +++ b/HPL2/include/scene/FogArea.h @@ -17,22 +17,18 @@ * along with Amnesia: The Dark Descent. If not, see . */ -#ifndef HPL_FOG_AREA_H -#define HPL_FOG_AREA_H +#pragma once #include "graphics/GraphicsTypes.h" #include "graphics/Renderable.h" namespace hpl { - //------------------------------------------ - class cCamera; class cFrustum; class iTexture; class cResources; - //------------------------------------------ class cFogArea : public iRenderable { @@ -70,7 +66,7 @@ namespace hpl { //Renderable implementation: cMaterial *GetMaterial(){ return NULL;} iVertexBuffer* GetVertexBuffer(){ return NULL;} - + virtual DrawPacket ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) override; eRenderableType GetRenderType(){ return eRenderableType_FogArea;} int GetMatrixUpdateCount(){ return GetTransformUpdateCount();} @@ -90,4 +86,3 @@ namespace hpl { }; }; -#endif // HPL_FOG_AREA_H diff --git a/HPL2/include/scene/GuiSetEntity.h b/HPL2/include/scene/GuiSetEntity.h index 51f93ba3b..df43b143b 100644 --- a/HPL2/include/scene/GuiSetEntity.h +++ b/HPL2/include/scene/GuiSetEntity.h @@ -16,9 +16,7 @@ * You should have received a copy of the GNU General Public License * along with Amnesia: The Dark Descent. If not, see . */ - -#ifndef HPL_GUI_SET_ENTITY_H -#define HPL_GUI_SET_ENTITY_H +#pragma once #include "math/MathTypes.h" #include "graphics/GraphicsTypes.h" @@ -39,9 +37,6 @@ namespace hpl { class cGuiSetEntity : public iRenderable { - #ifdef __GNUC__ - typedef iRenderable __super; - #endif public: cGuiSetEntity(const tString asName,cGuiSet *apSet); ~cGuiSetEntity(); @@ -57,6 +52,7 @@ namespace hpl { //Renderable implementations cMaterial *GetMaterial(){ return NULL;} iVertexBuffer* GetVertexBuffer(){return NULL;} + virtual DrawPacket ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) { return DrawPacket();} eRenderableType GetRenderType(){ return eRenderableType_GuiSet;} cMatrixf* GetModelMatrix(cFrustum *apFrustum); @@ -69,4 +65,3 @@ namespace hpl { }; }; -#endif // HPL_GUI_SET_ENTITY_H diff --git a/HPL2/include/scene/Light.h b/HPL2/include/scene/Light.h index df1c2ad39..7f468d308 100644 --- a/HPL2/include/scene/Light.h +++ b/HPL2/include/scene/Light.h @@ -16,11 +16,10 @@ * You should have received a copy of the GNU General Public License * along with Amnesia: The Dark Descent. If not, see . */ - -#ifndef HPL_LIGHT_H -#define HPL_LIGHT_H +#pragma once #include "graphics/AnimatedImage.h" +#include "graphics/DrawPacket.h" #include "graphics/Image.h" #include "graphics/ImageResourceWrapper.h" #include "scene/Entity3D.h" @@ -109,8 +108,12 @@ namespace hpl { /////////////////////////////// //Renderable implementation: - cMaterial *GetMaterial(){ return NULL;} - iVertexBuffer* GetVertexBuffer(){ return NULL;} + virtual cMaterial *GetMaterial() override{ return NULL;} + virtual iVertexBuffer* GetVertexBuffer() override{ return NULL;} + + virtual DrawPacket ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) override { + return DrawPacket(); + } eRenderableType GetRenderType(){ return eRenderableType_Light;} @@ -297,4 +300,3 @@ namespace hpl { typedef std::list tLightList; typedef tLightList::iterator tLightListIt; }; -#endif // HPL_LIGHT_H diff --git a/HPL2/include/scene/LightBox.h b/HPL2/include/scene/LightBox.h index 59a3a1aae..10b304769 100644 --- a/HPL2/include/scene/LightBox.h +++ b/HPL2/include/scene/LightBox.h @@ -17,8 +17,7 @@ * along with Amnesia: The Dark Descent. If not, see . */ -#ifndef HPL_LIGHT_BOX_H -#define HPL_LIGHT_BOX_H +#pragma once #include "scene/Light.h" #include "scene/SceneTypes.h" @@ -52,4 +51,3 @@ namespace hpl { }; }; -#endif // HPL_LIGHT_BOX_H diff --git a/HPL2/include/scene/ParticleEmitter.h b/HPL2/include/scene/ParticleEmitter.h index 40caa7e55..b7a1ce1e0 100644 --- a/HPL2/include/scene/ParticleEmitter.h +++ b/HPL2/include/scene/ParticleEmitter.h @@ -16,9 +16,7 @@ * You should have received a copy of the GNU General Public License * along with Amnesia: The Dark Descent. If not, see . */ - -#ifndef HPL_PARTICLE_EMITTER_H -#define HPL_PARTICLE_EMITTER_H +#pragma once #include "graphics/Renderable.h" #include "scene/Entity3D.h" @@ -195,21 +193,22 @@ namespace hpl { int GetParticleNum(){ return mlNumOfParticles;} //Entity implementation - tString GetEntityType(){ return "ParticleEmitter"; } - bool IsVisible(); + virtual tString GetEntityType() override { return "ParticleEmitter"; } + virtual bool IsVisible() override; //Renderable implementation - bool UpdateGraphicsForViewport(cFrustum *apFrustum,float afFrameTime); + virtual bool UpdateGraphicsForViewport(cFrustum *apFrustum,float afFrameTime) override; - cMaterial *GetMaterial(); - iVertexBuffer* GetVertexBuffer(); + virtual cMaterial *GetMaterial() override; + virtual iVertexBuffer* GetVertexBuffer() override; + virtual DrawPacket ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) override; - cBoundingVolume* GetBoundingVolume(); + virtual cBoundingVolume* GetBoundingVolume() override; - cMatrixf* GetModelMatrix(cFrustum *apFrustum); + virtual cMatrixf* GetModelMatrix(cFrustum *apFrustum) override; - int GetMatrixUpdateCount(){return GetTransformUpdateCount();} - eRenderableType GetRenderType(){ return eRenderableType_ParticleEmitter;} + int GetMatrixUpdateCount() override{return GetTransformUpdateCount();} + eRenderableType GetRenderType() override{ return eRenderableType_ParticleEmitter;} protected: void SwapRemove(unsigned int alIndex); @@ -322,13 +321,8 @@ namespace hpl { float mfWarmUpStepsPerSec; }; - //----------------------------------------------------------------- - typedef std::map tParticleEmitterDataMap; typedef tParticleEmitterDataMap::iterator tParticleEmitterDataMapIt; - - //----------------------------------------------------------------- }; -#endif // HPL_PARTICLE_EMITTER_H diff --git a/HPL2/include/scene/RopeEntity.h b/HPL2/include/scene/RopeEntity.h index 97632de5c..1e943bb2c 100644 --- a/HPL2/include/scene/RopeEntity.h +++ b/HPL2/include/scene/RopeEntity.h @@ -16,9 +16,7 @@ * You should have received a copy of the GNU General Public License * along with Amnesia: The Dark Descent. If not, see . */ - -#ifndef HPL_ROPE_ENTITY_H -#define HPL_ROPE_ENTITY_H +#pragma once #include "math/MathTypes.h" #include "graphics/GraphicsTypes.h" @@ -82,11 +80,12 @@ namespace hpl { ///////////////////////////////// //Renderable implementations - cMaterial *GetMaterial(){ return mpMaterial;} - iVertexBuffer* GetVertexBuffer(){return mpVtxBuffer;} + virtual cMaterial *GetMaterial() override{ return mpMaterial;} + virtual iVertexBuffer* GetVertexBuffer() override{return mpVtxBuffer;} + virtual DrawPacket ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) override; - void UpdateGraphicsForFrame(float afFrameTime); - bool UpdateGraphicsForViewport(cFrustum *apFrustum,float afFrameTime); + virtual void UpdateGraphicsForFrame(float afFrameTime) override; + virtual bool UpdateGraphicsForViewport(cFrustum *apFrustum,float afFrameTime) override; cBoundingVolume* GetBoundingVolume(); @@ -117,4 +116,3 @@ namespace hpl { }; }; -#endif // HPL_ROPE_ENTITY_H diff --git a/HPL2/include/scene/SubMeshEntity.h b/HPL2/include/scene/SubMeshEntity.h index 20c5bd2e9..646d00816 100644 --- a/HPL2/include/scene/SubMeshEntity.h +++ b/HPL2/include/scene/SubMeshEntity.h @@ -58,6 +58,7 @@ namespace hpl { virtual void UpdateGraphicsForFrame(float afFrameTime) override; virtual iVertexBuffer* GetVertexBuffer() override; + virtual DrawPacket ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) override; virtual cBoundingVolume* GetBoundingVolume() override; diff --git a/HPL2/sources/graphics/DecalCreator.cpp b/HPL2/sources/graphics/DecalCreator.cpp index b8fb571ea..b9d7593f8 100644 --- a/HPL2/sources/graphics/DecalCreator.cpp +++ b/HPL2/sources/graphics/DecalCreator.cpp @@ -304,7 +304,6 @@ namespace hpl { for(int j=0;j<2;++j) { mvClipPlanes.push_back(cPlanef(vAxes[i]*vSign[j], mvDecalPosition - vAdd*vSign[j])); - //Log("ClipPlane %i %s %f\n",i+j, mvClipPlanes.back().GetNormal().ToFileString().c_str(), mvClipPlanes.back().d); } } diff --git a/HPL2/sources/graphics/DrawPacket.cpp b/HPL2/sources/graphics/DrawPacket.cpp new file mode 100644 index 000000000..c6677c912 --- /dev/null +++ b/HPL2/sources/graphics/DrawPacket.cpp @@ -0,0 +1,32 @@ +#include "graphics/DrawPacket.h" +#include "impl/LegacyVertexBuffer.h" + +namespace hpl { + + void DrawPacket::cmdBindBuffers(Cmd* cmd, ForgeRenderer::CommandResourcePool* resourcePool, DrawPacket* packet) { + folly::small_vector vbBuffer; + folly::small_vector vbOffsets; + folly::small_vector vbStride; + switch(packet->m_type) { + case DrawPacketType::IndvidualBindings: { + for(size_t i = 0; i < packet->m_indvidual.m_numStreams; i++) { + auto& stream = packet->m_indvidual.m_vertexStream[i]; + resourcePool->Push(*stream.m_buffer); + vbBuffer.push_back(stream.m_buffer->m_handle); + vbOffsets.push_back(stream.m_offset); + vbStride.push_back(stream.m_stride); + } + break; + } + default: + ASSERT(false); + break; + } + + cmdBindVertexBuffer(cmd, packet->m_indvidual.m_numStreams, vbBuffer.data(), vbStride.data(), vbOffsets.data()); + cmdBindIndexBuffer(cmd, packet->m_indvidual.m_indexStream.buffer->m_handle, INDEX_TYPE_UINT32, packet->m_indvidual.m_indexStream.m_offset); + + } +} + + diff --git a/HPL2/sources/graphics/MeshCreator.cpp b/HPL2/sources/graphics/MeshCreator.cpp index cc4b0614d..5fe01ce21 100644 --- a/HPL2/sources/graphics/MeshCreator.cpp +++ b/HPL2/sources/graphics/MeshCreator.cpp @@ -76,442 +76,6 @@ namespace hpl { return pDest; } - - cMesh* cMeshCreator::CreateBox(const tString &asName,cVector3f avSize, const tString &asMaterial) - { - cMesh *pMesh = hplNew( cMesh, (asName, _W(""), mpResources->GetMaterialManager(), mpResources->GetAnimationManager()) ); - - cSubMesh *pSubMesh = pMesh->CreateSubMesh("Main"); - - cMaterial *pMat = mpResources->GetMaterialManager()->CreateMaterial(asMaterial); - pSubMesh->SetMaterial(pMat); - iVertexBuffer *pVtxBuff = CreateBoxVertexBuffer(avSize); - pSubMesh->SetVertexBuffer(pVtxBuff); - - return pMesh; - } - - - cMesh* cMeshCreator::CreatePlane(const tString& asName, const cVector3f& avCorner1, const cVector3f& avCorner2, - const cVector2f& avCorner1UV, const cVector2f& avCorner2UV, const cVector2f& avCorner3UV, const cVector2f& avCorner4UV, - const tString& asMaterial) - { - if(avCorner1==avCorner2) - { - Error("CreatePlane failed: plane corners are coincident. Plane name: %s\n", asName.c_str()); - return NULL; - } - - cVector3f vDiff = avCorner2 - avCorner1; - tIntVec vPlaneAxes; - int lPlaneNormalAxis = -1; - int lNumSameCoords = 0; - for(int i=0;i<3;++i) - { - if(vDiff.v[i]==0) - { - lPlaneNormalAxis = i; - ++lNumSameCoords; - } - else vPlaneAxes.push_back(i); - } - if(lPlaneNormalAxis<0 || lNumSameCoords>1) - { - Error("CreatePlane failed: plane corners are not coplanar. Plane name: %s\n", asName.c_str()); - return NULL; - } - - cVector3f vCenter = (avCorner1 + avCorner2)*0.5f; - - tVector3fVec vTempCoords; - vTempCoords.resize(4); - vTempCoords[0] = avCorner1; - vTempCoords[1] = avCorner2; - - cVector3f vTest1; - cVector3f vTest2; - - for(int i=2; i<4;++i) - { - int lIndex1 = vPlaneAxes[0]; - int lIndex2 = vPlaneAxes[1]; - - vTempCoords[i].v[lPlaneNormalAxis] = vTempCoords[0].v[lPlaneNormalAxis]; - vTempCoords[i].v[lIndex1] = vTempCoords[i-2].v[lIndex1]; - vTempCoords[i].v[lIndex2] = vTempCoords[3-i].v[lIndex2]; - - vTest1 = vTempCoords[2]; - vTest2 = vTempCoords[3]; - } - - tVector3fVec vCoords; - vCoords.resize(4); - for(int i=0;i<(int)vCoords.size(); ++i) - { - int lCornerIndex; - cVector3f vCorner = vTempCoords[i] - vCenter; - if(vCorner.v[vPlaneAxes[0]]<=0) - { - if(vCorner.v[vPlaneAxes[1]]>0) - lCornerIndex=0; - else - lCornerIndex=1; - } - else - { - if(vCorner.v[vPlaneAxes[1]]>0) - lCornerIndex=3; - else - lCornerIndex=2; - } - vCoords[lCornerIndex] = vTempCoords[i]; - } - cVector3f vFirstCorner = vCoords[1]; - for(int i=0;i<(int)vCoords.size();++i) - { - vCoords[i]-=vFirstCorner; - } - - iVertexBuffer* pVtxBuffer = mpLowLevelGraphics->CreateVertexBuffer( - eVertexBufferType_Hardware, - eVertexBufferDrawType_Tri, eVertexBufferUsageType_Dynamic,4,6); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Position,eVertexBufferElementFormat_Float,4); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Normal,eVertexBufferElementFormat_Float,3); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Color0,eVertexBufferElementFormat_Float,4); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Texture0,eVertexBufferElementFormat_Float,3); - - cVector2f vTexCoords[4] = - { - cVector2f(avCorner1UV.x, avCorner1UV.y), - cVector2f(avCorner2UV.x, avCorner2UV.y), // Start Corner - cVector2f(avCorner3UV.x, avCorner3UV.y), - cVector2f(avCorner4UV.x, avCorner4UV.y) // End Corner - }; - - for(int i=0;i<4;i++) - { - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Position, vCoords[i]); - pVtxBuffer->AddVertexColor(eVertexBufferElement_Color0, cColor(1,1,1,1)); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Texture0, vTexCoords[i] ); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Normal,cVector3f(0,1,0)); - - } - - for(int i=0;i<3;i++) pVtxBuffer->AddIndex(i); - for(int i=2;i<5;i++) pVtxBuffer->AddIndex(i==4?0:i); - - pVtxBuffer->Compile(eVertexCompileFlag_CreateTangents); - - cMesh *pMesh = hplNew( cMesh, (asName, _W(""), mpResources->GetMaterialManager(), mpResources->GetAnimationManager()) ); - - cSubMesh *pSubMesh = pMesh->CreateSubMesh("Main"); - - cMaterial *pMat = mpResources->GetMaterialManager()->CreateMaterial(asMaterial); - pSubMesh->SetMaterial(pMat); - pSubMesh->SetVertexBuffer(pVtxBuffer); - pSubMesh->SetMaterialName(asMaterial); - - return pMesh; - } - - //----------------------------------------------------------------------- - - cMesh* cMeshCreator::CreateSphere(const tString& asName, float afRadius, int alSections, int alSlices, const tString &asMaterial) - { - ////////////////////////////////////////////////// - // Create vertex buffer - iVertexBuffer* pVtxBuffer = mpLowLevelGraphics->CreateVertexBuffer(eVertexBufferType_Hardware, eVertexBufferDrawType_Tri, - eVertexBufferUsageType_Static); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Position,eVertexBufferElementFormat_Float,4); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Normal,eVertexBufferElementFormat_Float,3); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Color0,eVertexBufferElementFormat_Float,4); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Texture0,eVertexBufferElementFormat_Float,3); - - ///////////////////////////////// - // Set up variables - float fInvSlices = 1.0f/alSlices; - float fDiameter = 2*afRadius; - float fHeightStep = fDiameter*fInvSlices; - float fSectionStep = k2Pif/(float)alSections; - - cColor col = cColor(1,1); - - ///////////////////////////////// - // Create north pole vertex - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Position, cVector3f(0, afRadius, 0)); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Normal, cVector3f(0, 1, 0)); - pVtxBuffer->AddVertexColor(eVertexBufferElement_Color0, col); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Texture0, cVector3f(0)); - - ///////////////////////////////// - // Create slice vertices - float fPiOverSlices = kPif*fInvSlices; - float fHalfPi = kPif*0.5f; - for(int i=0;iAddVertexVec3f(eVertexBufferElement_Position, vVertex); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Normal, vNormal); - pVtxBuffer->AddVertexColor(eVertexBufferElement_Color0, col); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Texture0, cVector3f(0)); - } - } - ///////////////////////////////// - // Create south pole vertex - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Position, cVector3f(0, -afRadius, 0)); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Normal, cVector3f(0, -1, 0)); - pVtxBuffer->AddVertexColor(eVertexBufferElement_Color0, col); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Texture0, cVector3f(0)); - - ////////////////////////////////// - // Create triangles (Wrap helpers do this for us) - - // Create north pole slice triangles - WrapUpperCap(pVtxBuffer, 0, 1, alSections); - - // Create faces for inner slices - for(int i=0;iGetVertexNum()-1; - int lSliceStart = lLastVertex-alSections; - - WrapLowerCap(pVtxBuffer, lLastVertex, lSliceStart, alSections); - } - - //////////////////////////////////////////////////////////// - // Compile vertex buffer and create mesh - if(!pVtxBuffer->Compile(eVertexCompileFlag_CreateTangents)) - { - hplDelete(pVtxBuffer); - pVtxBuffer = NULL; - } - - cMesh* pMesh = hplNew( cMesh, (asName, _W(""), mpResources->GetMaterialManager(), mpResources->GetAnimationManager())); - cSubMesh* pSubMesh = pMesh->CreateSubMesh("Main"); - - cMaterial *pMat = mpResources->GetMaterialManager()->CreateMaterial(asMaterial); - pSubMesh->SetMaterial(pMat); - pSubMesh->SetVertexBuffer(pVtxBuffer); - - return pMesh; - } - - //----------------------------------------------------------------------- - - cMesh* cMeshCreator::CreateCylinder(const tString& asName, const cVector2f &avSize, int alSections, const tString &asMaterial) - { - iVertexBuffer* pVtxBuffer = mpLowLevelGraphics->CreateVertexBuffer(eVertexBufferType_Hardware, eVertexBufferDrawType_Tri, - eVertexBufferUsageType_Static); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Position,eVertexBufferElementFormat_Float,4); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Normal,eVertexBufferElementFormat_Float,3); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Color0,eVertexBufferElementFormat_Float,4); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Texture0,eVertexBufferElementFormat_Float,3); - - float fAngleStep = k2Pif/(float)alSections; - float fHalfHeight = avSize.y*0.5f; - cColor col = cColor(1,1); - - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Position, cVector3f(0,fHalfHeight,0)); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Normal, cVector3f(0,1,0)); - pVtxBuffer->AddVertexColor(eVertexBufferElement_Color0, col); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Texture0, cVector3f(0)); - tVector3fVec vVertices; - CreateCircumference(avSize.x, fAngleStep, 0, vVertices); - float vHeights[] = { fHalfHeight, -fHalfHeight }; - - for(int i=0;i<2;++i) - { - for(int j=0;j<(int)vVertices.size();++j) - { - cVector3f vVertex = vVertices[j]; - vVertex.y = vHeights[i]; - cVector3f vNormal = vVertex; - vNormal.Normalize(); - - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Position, vVertex); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Normal, vNormal); - pVtxBuffer->AddVertexColor(eVertexBufferElement_Color0, col); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Texture0, cVector3f(0)); - } - } - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Position, cVector3f(0,-fHalfHeight,0)); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Normal, cVector3f(0,-1,0)); - pVtxBuffer->AddVertexColor(eVertexBufferElement_Color0, col); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Texture0, cVector3f(0)); - - // Top cap - { - WrapUpperCap(pVtxBuffer, 0, 1, alSections); - } - - // Sides - { - WrapSides(pVtxBuffer, 1, alSections); - } - - // Bottom cap - { - int lLastVertex = pVtxBuffer->GetVertexNum()-1; - int lCapStart = lLastVertex-alSections; - WrapLowerCap(pVtxBuffer, lLastVertex, lCapStart, alSections); - } - - if(!pVtxBuffer->Compile(eVertexCompileFlag_CreateTangents)) - { - hplDelete(pVtxBuffer); - pVtxBuffer = NULL; - } - - cMesh* pMesh = hplNew( cMesh, (asName, _W(""), mpResources->GetMaterialManager(), mpResources->GetAnimationManager())); - cSubMesh* pSubMesh = pMesh->CreateSubMesh("Main"); - - cMaterial *pMat = mpResources->GetMaterialManager()->CreateMaterial(asMaterial); - pSubMesh->SetMaterial(pMat); - pSubMesh->SetVertexBuffer(pVtxBuffer); - - return pMesh; - } - - //----------------------------------------------------------------------- - - cMesh* cMeshCreator::CreateCapsule(const tString &asName, const cVector2f &avSize, int alSections, int alSlices, const tString &asMaterial) - { - iVertexBuffer* pVtxBuffer = mpLowLevelGraphics->CreateVertexBuffer(eVertexBufferType_Hardware, eVertexBufferDrawType_Tri, - eVertexBufferUsageType_Static); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Position,eVertexBufferElementFormat_Float,4); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Normal,eVertexBufferElementFormat_Float,3); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Color0,eVertexBufferElementFormat_Float,4); - pVtxBuffer->CreateElementArray(eVertexBufferElement_Texture0,eVertexBufferElementFormat_Float,3); - - float fAngleStep = k2Pif/(float)alSections; - cColor col = cColor(1,1); - - float fRadius = avSize.x; - float fHalfHeight = avSize.y*0.5f; - float fCylinderHalfHeight = fHalfHeight-fRadius; - fCylinderHalfHeight = cMath::Clamp(fCylinderHalfHeight, 0, fCylinderHalfHeight); - - float fInvSlices = 1.0f/alSlices; - float fSectionStep = k2Pif/(float)alSections; - - // North pole - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Position, cVector3f(0, cMath::Max(fHalfHeight, fRadius), 0)); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Normal, cVector3f(0, 1, 0)); - pVtxBuffer->AddVertexColor(eVertexBufferElement_Color0, col); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Texture0, cVector3f(0)); - - // Slices - float fHalfPi = kPif*0.5f; - float fHalfPiOverSlices = fHalfPi*fInvSlices; - for(int i=0;iAddVertexVec3f(eVertexBufferElement_Position, vVertex); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Normal, vNormal); - pVtxBuffer->AddVertexColor(eVertexBufferElement_Color0, col); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Texture0, cVector3f(0)); - } - } - - { - tVector3fVec vCylinderVertices; - CreateCircumference(avSize.x, fSectionStep, 0, vCylinderVertices); - float vCylinderHeights[] = { fCylinderHalfHeight, -fCylinderHalfHeight }; - for(int i=0;i<2;++i) - { - float fHeight = vCylinderHeights[i]; - for(int j=0;j<(int)vCylinderVertices.size();++j) - { - cVector3f vVertex = vCylinderVertices[j]; - vVertex.y = fHeight; - cVector3f vNormal = vVertex; - vNormal.Normalize(); - - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Position, vVertex); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Normal, vNormal); - pVtxBuffer->AddVertexColor(eVertexBufferElement_Color0, col); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Texture0, cVector3f(0)); - } - } - } - - for(int i=alSlices-2;i>=0; --i) - { - // Same absolute height and radius than upper dome, only reverse order - - float fHeight = fCylinderHalfHeight + fRadius - fRadius*(1+sin(fHalfPiOverSlices*(float)(i+1)-fHalfPi)); - float fAngle = asin((fHeight-fCylinderHalfHeight)/fRadius); - tVector3fVec vVertices; - - // and height is negative here - CreateCircumference(avSize.x*cos(fAngle), fSectionStep, -fHeight, vVertices); - for(int j=0;j<(int)vVertices.size();++j) - { - const cVector3f& vVertex = vVertices[j]; - cVector3f vNormal = vVertex - fCylinderHalfHeight; - vNormal.Normalize(); - - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Position, vVertex); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Normal, vNormal); - pVtxBuffer->AddVertexColor(eVertexBufferElement_Color0, col); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Texture0, cVector3f(0)); - } - } - - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Position, cVector3f(0,cMath::Min(-fHalfHeight, -fRadius),0)); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Normal, cVector3f(0,-1,0)); - pVtxBuffer->AddVertexColor(eVertexBufferElement_Color0, col); - pVtxBuffer->AddVertexVec3f(eVertexBufferElement_Texture0, cVector3f(0)); - - WrapUpperCap(pVtxBuffer, 0, 1, alSections); - for(int i=0;i<2*alSlices-1;++i) - { - WrapSides(pVtxBuffer, 1 + i*alSections, alSections); - } - - int lLastVertex = pVtxBuffer->GetVertexNum()-1; - WrapLowerCap(pVtxBuffer, lLastVertex, lLastVertex-alSections, alSections); - - if(!pVtxBuffer->Compile(eVertexCompileFlag_CreateTangents)) - { - hplDelete(pVtxBuffer); - pVtxBuffer = NULL; - } - - cMesh* pMesh = hplNew( cMesh, (asName, _W(""), mpResources->GetMaterialManager(), mpResources->GetAnimationManager())); - cSubMesh* pSubMesh = pMesh->CreateSubMesh("Main"); - - cMaterial *pMat = mpResources->GetMaterialManager()->CreateMaterial(asMaterial); - pSubMesh->SetMaterial(pMat); - pSubMesh->SetVertexBuffer(pVtxBuffer); - - return pMesh; - } - - //----------------------------------------------------------------------- - cMesh* cMeshCreator::CreateCone(const tString &asName, const cVector2f &avSize, int alSections, const tString &asMaterial) { ////////////////////////////////////////// @@ -666,98 +230,6 @@ namespace hpl { return pSkyBox; } - //----------------------------------------------------------------------- - - iVertexBuffer* cMeshCreator::CreateBoxVertexBuffer(cVector3f avSize) - { - iVertexBuffer* pBox = mpLowLevelGraphics->CreateVertexBuffer( - eVertexBufferType_Hardware, - eVertexBufferDrawType_Tri,eVertexBufferUsageType_Static); - pBox->CreateElementArray(eVertexBufferElement_Position,eVertexBufferElementFormat_Float,4); - pBox->CreateElementArray(eVertexBufferElement_Normal,eVertexBufferElementFormat_Float,3); - pBox->CreateElementArray(eVertexBufferElement_Color0,eVertexBufferElementFormat_Float,4); - pBox->CreateElementArray(eVertexBufferElement_Texture0,eVertexBufferElementFormat_Float,3); - - - avSize = avSize*0.5; - - int lVtxIdx =0; - - for(int x=-1; x<=1;x++) - for(int y=-1; y<=1;y++) - for(int z=-1; z<=1;z++) - { - if(x==0 && y==0 && z==0)continue; - if(std::abs(x) + std::abs(y) + std::abs(z) > 1)continue; - - //Direction (could say inverse normal) of the quad. - cVector3f vDir(0); - cVector3f vSide(0); - - cVector3f vAdd[4]; - if(std::abs(x)){ - vDir.x = (float)x; - - vAdd[0].y = 1; vAdd[0].z = 1; vAdd[0].x = 0; - vAdd[1].y = -1; vAdd[1].z = 1; vAdd[1].x = 0; - vAdd[2].y = -1; vAdd[2].z = -1; vAdd[2].x = 0; - vAdd[3].y = 1; vAdd[3].z = -1; vAdd[3].x = 0; - } - else if(std::abs(y)){ - vDir.y = (float)y; - - vAdd[0].z = 1; vAdd[0].x = 1; vAdd[0].y = 0; - vAdd[1].z = -1; vAdd[1].x = 1; vAdd[1].y = 0; - vAdd[2].z = -1; vAdd[2].x = -1; vAdd[2].y = 0; - vAdd[3].z = 1; vAdd[3].x = -1; vAdd[3].y = 0; - } - else if(std::abs(z)){ - vAdd[0].y = 1; vAdd[0].x = 1; vAdd[0].z = 0; - vAdd[1].y = 1; vAdd[1].x = -1; vAdd[1].z = 0; - vAdd[2].y = -1; vAdd[2].x = -1; vAdd[2].z = 0; - vAdd[3].y = -1; vAdd[3].x = 1; vAdd[3].z = 0; - - vDir.z = (float)z; - } - - - //Log("Side: (%.0f : %.0f : %.0f) [ ", vDir.x, vDir.y,vDir.z); - for(int i=0;i<4;i++) - { - int idx = GetBoxIdx(i,x,y,z); - cVector3f vTex = GetBoxTex(i,x,y,z,vAdd); - - pBox->AddVertexColor(eVertexBufferElement_Color0, cColor(1,1,1,1)); - pBox->AddVertexVec3f(eVertexBufferElement_Position, (vDir+vAdd[idx])*avSize); - pBox->AddVertexVec3f(eVertexBufferElement_Normal, vDir); - - //texture coord - cVector3f vCoord = cVector3f((vTex.x+1)*0.5f,(vTex.y+1)*0.5f,0); - pBox->AddVertexVec3f(eVertexBufferElement_Texture0,vCoord); - - vSide = vDir+vAdd[idx]; - //Log("%d: Tex: (%.1f : %.1f : %.1f) ", i,vTex.x, vTex.y,vTex.z); - //Log("%d: (%.1f : %.1f : %.1f) ", i,vSide.x, vSide.y,vSide.z); - } - - for(int i=0;i<3;i++)pBox->AddIndex(lVtxIdx + i); - pBox->AddIndex(lVtxIdx + 2); - pBox->AddIndex(lVtxIdx + 3); - pBox->AddIndex(lVtxIdx + 0); - - lVtxIdx +=4; - - //Log("\n"); - } - - if(!pBox->Compile(eVertexCompileFlag_CreateTangents)) - { - hplDelete(pBox); - return NULL; - } - return pBox; - } - cVector3f cMeshCreator::GetBoxTex(int i,int x, int y, int z, cVector3f *vAdd) { cVector3f vTex; diff --git a/HPL2/sources/graphics/MeshUtility.cpp b/HPL2/sources/graphics/MeshUtility.cpp index 91dccf09e..ab1d5129e 100644 --- a/HPL2/sources/graphics/MeshUtility.cpp +++ b/HPL2/sources/graphics/MeshUtility.cpp @@ -1,5 +1,7 @@ #include "graphics/MeshUtility.h" #include "Common_3/Utilities/Log/Log.h" +#include "Common_3/Utilities/ThirdParty/OpenSource/ModifiedSonyMath/common.hpp" +#include "Common_3/Utilities/ThirdParty/OpenSource/ModifiedSonyMath/sse/vectormath.hpp" #include "graphics/AssetBuffer.h" #include "graphics/mikktspace.h" #include "math/Math.h" @@ -9,12 +11,14 @@ #include #include +#include +#include namespace hpl::MeshUtility { namespace details { struct MikktSpaceUser { uint32_t m_numElements; - uint32_t m_numIndecies; + uint32_t m_numIndices; AssetBuffer::BufferIndexView* m_indexView; AssetBuffer::BufferStructuredView* m_position; AssetBuffer::BufferStructuredView* m_uv; @@ -22,17 +26,109 @@ namespace hpl::MeshUtility { AssetBuffer::BufferStructuredView* m_tangent; }; - int mikkT_getNumberFaces(const SMikkTSpaceContext * pContext) { + inline void CreateTriTangentVectorsHPL2( + uint32_t numVerts, + uint32_t numIndecies, + AssetBuffer::BufferIndexView* indexView, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* uv, + AssetBuffer::BufferStructuredView* normal, + std::function handler + ) { + + } + + + uint32_t WrapSides(uint32_t viewIndex, AssetBuffer::BufferIndexView* view, int alStartVertexIdx, int alSections) { + // Create indices like this 0 --- 1 --- 2 --- ... --- 0 + // | / | / | + // | / | / | + // | / | / | + // Se---Se+1---Se+2---2S-1--- S + + for (int i = 0; i < alSections - 1; ++i) { + int lPoint0 = alStartVertexIdx + i; + int lPoint1 = lPoint0 + 1; + int lPoint2 = lPoint0 + alSections; + int lPoint3 = lPoint2 + 1; + + view->Write(viewIndex++, lPoint0); + view->Write(viewIndex++, lPoint2); + view->Write(viewIndex++, lPoint1); + + view->Write(viewIndex++, lPoint1); + view->Write(viewIndex++, lPoint2); + view->Write(viewIndex++, lPoint3); + } + + { + int lPoint0 = alStartVertexIdx + alSections - 1; + int lPoint1 = alStartVertexIdx; + int lPoint2 = lPoint0 + alSections; + int lPoint3 = lPoint0 + 1; + + view->Write(viewIndex++, lPoint0); + view->Write(viewIndex++, lPoint2); + view->Write(viewIndex++, lPoint1); + + view->Write(viewIndex++, lPoint1); + view->Write(viewIndex++, lPoint2); + view->Write(viewIndex++, lPoint3); + + // Log("%d %d %d\t %d %d %d\n", lPoint0, lPoint2, lPoint1, + // lPoint1, lPoint2, lPoint3); + } + return viewIndex; + } + void CreateCircumference(float afRadius, float afAngleStep, float afHeight, std::function handler) { + float fEnd = k2Pif - afAngleStep; + for (float fAngle = 0; fAngle <= fEnd; fAngle += afAngleStep) { + float3 vPoint = float3( + cMath::RoundFloatToDecimals(afRadius * cos(fAngle), 6), + cMath::RoundFloatToDecimals(afHeight, 6), + cMath::RoundFloatToDecimals(afRadius * sin(fAngle), 6)); + handler(vPoint); + } + } + uint32_t WrapLowerCap( + uint32_t viewIndex, AssetBuffer::BufferIndexView* view, int alCenterVertexIdx, int alStartVertexIdx, int alSections) { + for (int i = 0; i < alSections - 1; ++i) { + int lBase = alStartVertexIdx + i; + view->Write(viewIndex++, alCenterVertexIdx); + view->Write(viewIndex++, lBase + 1); + view->Write(viewIndex++, lBase); + } + + view->Write(viewIndex++, alCenterVertexIdx); + view->Write(viewIndex++, alStartVertexIdx); + view->Write(viewIndex++, alStartVertexIdx + alSections - 1); + return viewIndex; + } + uint32_t WrapUpperCap( + uint32_t viewIndex, AssetBuffer::BufferIndexView* view, int alCenterVertexIdx, int alStartVertexIdx, int alSections) { + for (int i = 0; i < alSections - 1; ++i) { + int lBase = alStartVertexIdx + i; + view->Write(viewIndex++, alCenterVertexIdx); + view->Write(viewIndex++, lBase); + view->Write(viewIndex++, lBase + 1); + } + view->Write(viewIndex++, alCenterVertexIdx); + view->Write(viewIndex++, alStartVertexIdx + alSections - 1); + view->Write(viewIndex++, alStartVertexIdx); + return viewIndex; + } + + int mikkT_getNumberFaces(const SMikkTSpaceContext* pContext) { MikktSpaceUser* user = reinterpret_cast(pContext->m_pUserData); - return user->m_numIndecies / 3; + return user->m_numIndices / 3; } - int mikkT_getNumVerticesOfFaces(const SMikkTSpaceContext * pContext, const int iFace) { + int mikkT_getNumVerticesOfFaces(const SMikkTSpaceContext* pContext, const int iFace) { MikktSpaceUser* user = reinterpret_cast(pContext->m_pUserData); return 3; } - void mikkT_getPosition(const SMikkTSpaceContext * pContext, float fvPosOut[], const int iFace, const int iVert) { + void mikkT_getPosition(const SMikkTSpaceContext* pContext, float fvPosOut[], const int iFace, const int iVert) { MikktSpaceUser* user = reinterpret_cast(pContext->m_pUserData); uint32_t vertIdx = user->m_indexView->Get((iFace * 3) + iVert); float3 v = user->m_position->Get(vertIdx); @@ -41,7 +137,7 @@ namespace hpl::MeshUtility { fvPosOut[1] = v.getY(); fvPosOut[2] = v.getZ(); } - void mikkT_getNormal(const SMikkTSpaceContext * pContext, float fvNormOut[], const int iFace, const int iVert) { + void mikkT_getNormal(const SMikkTSpaceContext* pContext, float fvNormOut[], const int iFace, const int iVert) { MikktSpaceUser* user = reinterpret_cast(pContext->m_pUserData); uint32_t vertIdx = user->m_indexView->Get((iFace * 3) + iVert); float3 v = user->m_normal->Get(vertIdx); @@ -50,7 +146,7 @@ namespace hpl::MeshUtility { fvNormOut[1] = v.getY(); fvNormOut[2] = v.getZ(); } - void mikkT_getTexCoord(const SMikkTSpaceContext * pContext, float fvTexcOut[], const int iFace, const int iVert) { + void mikkT_getTexCoord(const SMikkTSpaceContext* pContext, float fvTexcOut[], const int iFace, const int iVert) { MikktSpaceUser* user = reinterpret_cast(pContext->m_pUserData); uint32_t vertIdx = user->m_indexView->Get((iFace * 3) + iVert); float2 v = user->m_uv->Get(vertIdx); @@ -58,58 +154,640 @@ namespace hpl::MeshUtility { fvTexcOut[0] = v.getX(); fvTexcOut[1] = v.getY(); } - void mikkT_setTSpaceBasic(const SMikkTSpaceContext * pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) { + void mikkT_setTSpaceBasic( + const SMikkTSpaceContext* pContext, const float fvTangent[], const float fSign, const int iFace, const int iVert) { MikktSpaceUser* user = reinterpret_cast(pContext->m_pUserData); uint32_t vertIdx = user->m_indexView->Get((iFace * 3) + iVert); user->m_tangent->Write(vertIdx, float3(fvTangent[0], fvTangent[1], fvTangent[2])); } - } + } // namespace details void Transform( uint32_t numElements, const Matrix4& transform, AssetBuffer::BufferStructuredView* position, AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* tangent - ) { + AssetBuffer::BufferStructuredView* tangent) { Matrix3 normalMat = transpose(inverse(transform.getUpper3x3())); - for(size_t i = 0; i < numElements; i++) { - if(position) { - float3 value = position->Get(i); - position->Write(i, v3ToF3((transform * Vector4(f3Tov3(value), 1.0f)).getXYZ())); - } - if(normal) { - float3 value = normal->Get(i); - normal->Write(i, v3ToF3(normalMat * f3Tov3(value))); + for (size_t i = 0; i < numElements; i++) { + if (position) { + float3 value = position->Get(i); + position->Write(i, v3ToF3((transform * Vector4(f3Tov3(value), 1.0f)).getXYZ())); + } + if (normal) { + float3 value = normal->Get(i); + normal->Write(i, v3ToF3(normalMat * f3Tov3(value))); + } + if (tangent) { + float3 value = tangent->Get(i); + tangent->Write(i, v3ToF3(normalMat * f3Tov3(value))); + } + } + } + + void CreateTriTangentVectorsHPL2( + uint32_t numVerts, + uint32_t numIndices, + AssetBuffer::BufferIndexView* indexView, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* uv, + AssetBuffer::BufferStructuredView* normal, + std::variant*, AssetBuffer::BufferStructuredView*> tangent + ) { + struct TangentPairs { + float3 sDir; + float3 tDir; + }; + + std::vector tangentPairs; + tangentPairs.resize(numVerts, { + float3(0, 0 ,0), + float3(0, 0 ,0) + }); + + for(size_t idxBuffer = 0; idxBuffer < numIndices; idxBuffer += 3) { + const uint32_t vtxIdx1 = indexView->Get(idxBuffer + 0); + const uint32_t vtxIdx2 = indexView->Get(idxBuffer + 1); + const uint32_t vtxIdx3 = indexView->Get(idxBuffer + 2); + + const float3 pos1 = position->Get(vtxIdx1); + const float3 pos2 = position->Get(vtxIdx2); + const float3 pos3 = position->Get(vtxIdx3); + + const float2 tex1 = uv->Get(vtxIdx1); + const float2 tex2 = uv->Get(vtxIdx2); + const float2 tex3 = uv->Get(vtxIdx3); + + //Get the vectors between the positions. + const float3 vPos1To2 = pos2 - pos1; + const float3 vPos1To3 = pos3 - pos1; + + //Get the vectors between the tex coords + const float2 vTex1To2 = tex2 - tex1; + const float2 vTex1To3 = tex3 - tex1; + + const float fR = 1.0f / (vTex1To2.x * vTex1To3.y - vTex1To2.y * vTex1To3.x); + + const float3 sDir((vTex1To3.y * vPos1To2.x - vTex1To2.y * vPos1To3.x) * fR, + (vTex1To3.y * vPos1To2.y - vTex1To2.y * vPos1To3.y) * fR, + (vTex1To3.y * vPos1To2.z - vTex1To2.y * vPos1To3.z) * fR + ); + + const float3 tDir((vTex1To2.x * vPos1To3.x - vTex1To3.x * vPos1To2.x) * fR, + (vTex1To2.x * vPos1To3.y - vTex1To3.x * vPos1To2.y) * fR, + (vTex1To2.x * vPos1To3.z - vTex1To3.x * vPos1To2.z) * fR + ); + + tangentPairs[vtxIdx1].sDir += sDir; + tangentPairs[vtxIdx2].sDir += sDir; + tangentPairs[vtxIdx3].sDir += sDir; + + tangentPairs[vtxIdx1].tDir += tDir; + tangentPairs[vtxIdx2].tDir += tDir; + tangentPairs[vtxIdx3].tDir += tDir; + } + const float fMaxCosAngle = -1.0f; + for(int i=0; i < numVerts; i++) + { + for(int j=i+1; j< numVerts; j++) + { + const float3 dp = (position->Get(i) - position->Get(j)); + const float3 dn = (normal->Get(i) - normal->Get(j)); + if( + (abs(dp.x) < FLT_EPSILON && abs(dp.y) < FLT_EPSILON && abs(dp.z) < FLT_EPSILON) && + (abs(dn.x) < FLT_EPSILON && abs(dn.y) < FLT_EPSILON && abs(dn.z) < FLT_EPSILON) + ) { + if(dot(f3Tov3(tangentPairs[i].sDir), f3Tov3(tangentPairs[i].tDir)) >= fMaxCosAngle) { + float3 idir = tangentPairs[i].sDir; + float3 jdir = tangentPairs[j].sDir; + tangentPairs[j].sDir = idir ; + tangentPairs[i].sDir = jdir; + } + + if(dot(f3Tov3(tangentPairs[i].sDir), f3Tov3(tangentPairs[i].tDir)) >= fMaxCosAngle) { + float3 idir = tangentPairs[i].tDir; + float3 jdir = tangentPairs[j].tDir; + tangentPairs[j].tDir = idir; + tangentPairs[i].tDir = jdir; + } + } + } + } + + for(uint32_t vtxIdx = 0;vtxIdx < numVerts; vtxIdx++) { + Vector3 norm = f3Tov3(normal->Get(vtxIdx)); + auto& tangentPair = tangentPairs[vtxIdx]; + Vector3 tang = f3Tov3(tangentPair.sDir) - mulPerElem(norm, cross(norm, f3Tov3(tangentPair.sDir))); + float fw = dot(cross(norm,f3Tov3(tangentPair.sDir)), f3Tov3(tangentPair.tDir)) < 0.0f ? -1.0f : 1.0f; + std::visit([&](auto& item) { + using T = std::decay_t; + if constexpr (std::is_same_v*>) { + item->Write(vtxIdx, v3ToF3(tang)); + } + if constexpr (std::is_same_v*>) { + item->Write(vtxIdx, float4(v3ToF3(tang), fw)); + } + }, tangent); + } + } + MeshCreateResult CreateSphere( + float afRadius, + uint32_t alSections, + uint32_t alSlices, + AssetBuffer::BufferIndexView* index, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* color, + AssetBuffer::BufferStructuredView* normal, + AssetBuffer::BufferStructuredView* uv, + std::variant*, AssetBuffer::BufferStructuredView*> tangent) { + ASSERT(index); + ASSERT(position); + ASSERT(color); + ASSERT(normal); + ASSERT(uv); + + ///////////////////////////////// + // Set up variables + const float fInvSlices = 1.0f / alSlices; + const float fDiameter = 2 * afRadius; + const float fHeightStep = fDiameter * fInvSlices; + const float fSectionStep = k2Pif / (float)alSections; + uint32_t vertexBufIdx = 0; + uint32_t indexBufIndex = 0; + + ///////////////////////////////// + // Create north pole vertex + position->Write(vertexBufIdx, float3(0.0f, afRadius, 0.0f)); + normal->Write(vertexBufIdx, float3(0.0f, 1.0f, 0.0f)); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + + ///////////////////////////////// + // Create slice vertices + const float fPiOverSlices = kPif * fInvSlices; + const float fHalfPi = kPif * 0.5f; + for (int i = 0; i < alSlices - 1; ++i) { + const float fHeight = afRadius - afRadius * (1 + sin(fPiOverSlices * (float)(i + 1) - fHalfPi)); + const float fAngle = asin(fHeight / afRadius); + details::CreateCircumference(afRadius * cos(fAngle), fSectionStep, fHeight, [&](float3 vertex) { + position->Write(vertexBufIdx, vertex); + normal->Write(vertexBufIdx, v3ToF3(normalize(f3Tov3(vertex)))); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + }); + } + ///////////////////////////////// + // Create south pole vertex + position->Write(vertexBufIdx, float3(0.0f, -afRadius, 0.0f)); + normal->Write(vertexBufIdx, float3(0.0f, -1.0f, 0.0f)); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + + ////////////////////////////////// + // Create triangles (Wrap helpers do this for us) + + // Create north pole slice triangles + indexBufIndex = details::WrapUpperCap(indexBufIndex, index, 0, 1, alSections); + + // Create faces for inner slices + for (int i = 0; i < alSlices - 2; ++i) { + indexBufIndex = details::WrapSides(indexBufIndex,index, 1 + i * alSections, alSections); + } + + // Create triangles for south pole slice + { + const int lLastVertex = vertexBufIdx - 1; + const int lSliceStart = lLastVertex - alSections; + indexBufIndex = details::WrapLowerCap(indexBufIndex, index, lLastVertex, lSliceStart, alSections); + } + + CreateTriTangentVectorsHPL2(vertexBufIdx, indexBufIndex, index, position, uv, normal, tangent); + MeshCreateResult result; + result.numIndices = indexBufIndex; + result.numVertices = vertexBufIdx; + return result; + } + + MeshCreateResult CreatePlane( + const std::array corners, + const std::array uvCorners, + AssetBuffer::BufferIndexView* index, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* color, + AssetBuffer::BufferStructuredView* normal, + AssetBuffer::BufferStructuredView* uv, + std::variant*, AssetBuffer::BufferStructuredView*> tangent + ) { + const Vector3 diff = corners[0] - corners[1]; + folly::small_vector vPlaneAxes; + int lPlaneNormalAxis = -1; + int lNumSameCoords = 0; + uint32_t vertexBufIdx = 0; + uint32_t indexBufIndex = 0; + for (int i = 0; i < 3; ++i) { + if (diff[i] == 0) { + lPlaneNormalAxis = i; + ++lNumSameCoords; + } else { + vPlaneAxes.push_back(i); + } + } + if (lPlaneNormalAxis < 0 || lNumSameCoords > 1) { + LOGF(LogLevel::eERROR, "CreatePlane failed: plane corners are not coplanar"); + return MeshCreateResult{0}; + } + Vector3 vCenter = (corners[0] + corners[1]) * 0.5f; + + std::array vTempCoords; + vTempCoords[0] = corners[0]; + vTempCoords[1] = corners[1]; + Vector3 vTest1; + Vector3 vTest2; + + for (int i = 2; i < 4; ++i) { + int lIndex1 = vPlaneAxes[0]; + int lIndex2 = vPlaneAxes[1]; + + vTempCoords[i][lPlaneNormalAxis] = vTempCoords[0][lPlaneNormalAxis]; + vTempCoords[i][lIndex1] = vTempCoords[i - 2][lIndex1]; + vTempCoords[i][lIndex2] = vTempCoords[3 - i][lIndex2]; + + vTest1 = vTempCoords[2]; + vTest2 = vTempCoords[3]; + } + + std::array vCoords; + for (int i = 0; i < (int)vCoords.size(); ++i) { + int lCornerIndex; + Vector3 vCorner = vTempCoords[i] - vCenter; + if (vCorner[vPlaneAxes[0]] <= 0) { + if (vCorner[vPlaneAxes[1]] > 0) { + lCornerIndex = 0; + } else { + lCornerIndex = 1; } - if(tangent) { - float3 value = tangent->Get(i); - tangent->Write(i, v3ToF3(normalMat * f3Tov3(value))); + } else { + if (vCorner[vPlaneAxes[1]] > 0) { + lCornerIndex = 3; + } else { + lCornerIndex = 2; } + } + vCoords[lCornerIndex] = vTempCoords[i]; + } + Vector3 vFirstCorner = vCoords[1]; + for (int i = 0; i < (int)vCoords.size(); ++i) { + vCoords[i] -= vFirstCorner; + } + for (size_t i = 0; i < 4; i++) { + position->Write(vertexBufIdx, v3ToF3(vCoords[i])); + normal->Write(vertexBufIdx, float3(0.0f, 1.0f, 0.0f)); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, v2ToF2(uvCorners[i])); + } + for (int i = 0; i < 3; i++) { + index->Write(indexBufIndex++, i); + } + for (int i = 2; i < 5; i++) { + index->Write(indexBufIndex++, i == 4 ? 0 : i); + } + CreateTriTangentVectorsHPL2(vertexBufIdx, indexBufIndex, index, position, uv, normal, tangent); + MeshCreateResult result; + result.numIndices = indexBufIndex; + result.numVertices = vertexBufIdx; + return result; + } + + MeshCreateResult CreateCone(const float2 avSize, int alSections, + AssetBuffer::BufferIndexView* index, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* color, + AssetBuffer::BufferStructuredView* normal, + AssetBuffer::BufferStructuredView* uv, + std::variant*, AssetBuffer::BufferStructuredView*> tangent) { + + const float fAngleStep = k2Pif/(float)alSections; + const float fHalfHeight = avSize.y*0.5f; + + uint32_t vertexBufIdx = 0; + uint32_t indexBufIndex = 0; + + position->Write(vertexBufIdx, float3(0.0f, fHalfHeight, 0.0f)); + normal->Write(vertexBufIdx, float3(0.0f, 1.0f, 0.0f)); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + + // Create vertices for base + details::CreateCircumference(avSize.x, fAngleStep, -fHalfHeight, [&](float3 pos) { + float3 norm = v3ToF3(normalize(f3Tov3(pos))); + position->Write(vertexBufIdx, pos); + normal->Write(vertexBufIdx, norm); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + }); + + // Base center vertex + position->Write(vertexBufIdx, float3(0.0f, -fHalfHeight, 0.0f)); + normal->Write(vertexBufIdx, float3(0.0f, -1.0f, 0.0f)); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + + indexBufIndex = details::WrapUpperCap(indexBufIndex, index, 0, 1, alSections); + indexBufIndex = details::WrapLowerCap(indexBufIndex, index, vertexBufIdx - 1, (vertexBufIdx - 1) - alSections, alSections); + + CreateTriTangentVectorsHPL2(vertexBufIdx, indexBufIndex, index, position, uv, normal, tangent); + MeshCreateResult result; + result.numIndices = indexBufIndex; + result.numVertices = vertexBufIdx; + return result; + } + MeshCreateResult CreateBox( + float3 size, + AssetBuffer::BufferIndexView* index, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* color, + AssetBuffer::BufferStructuredView* normal, + AssetBuffer::BufferStructuredView* uv, + std::variant*, AssetBuffer::BufferStructuredView*> tangent + ) { + ASSERT(index); + ASSERT(position); + ASSERT(color); + ASSERT(normal); + ASSERT(uv); + + const float3 halfSize = size * 0.5; + int lVtxIdx = 0; + uint32_t vertexBufIdx = 0; + uint32_t indexBufIndex = 0; + + auto getBoxIdx = [](int i, int x, int y, int z) { + int idx = i; + if (x + y + z > 0) + idx = 3 - i; + + return idx; + }; + + auto getBoxTex = [](int i, int x, int y, int z, std::array& vAdd) { + float3 vTex; + + if (std::abs(x)) { + vTex.x = vAdd[i].z; + vTex.y = vAdd[i].y; + } else if (std::abs(y)) { + vTex.x = vAdd[i].x; + vTex.y = vAdd[i].z; + } else if (std::abs(z)) { + vTex.x = vAdd[i].x; + vTex.y = vAdd[i].y; + } + + // Inverse for negative directions + if (x + y + z < 0) { + vTex.x = -vTex.x; + vTex.y = -vTex.y; + } + return vTex; + }; + + for (int x = -1; x <= 1; x++) { + for (int y = -1; y <= 1; y++) { + for (int z = -1; z <= 1; z++) { + if (x == 0 && y == 0 && z == 0) + continue; + if (std::abs(x) + std::abs(y) + std::abs(z) > 1) + continue; + // Direction (could say inverse normal) of the quad. + float3 vDir(0); + float3 vSide(0); + + std::array vAdd; + if (std::abs(x)) { + vDir.x = (float)x; + + vAdd[0] = float3(0, 1, 1); + vAdd[1] = float3(0, -1, 1); + vAdd[2] = float3(0, -1, -1); + vAdd[3] = float3(0, 1, -1); + } else if (std::abs(y)) { + vDir.y = (float)y; + + vAdd[0] = float3(1, 0, 1); + vAdd[1] = float3(1, 0, 1); + vAdd[2] = float3(-1, 0, -1); + vAdd[3] = float3(-1, 0, -1); + } else if (std::abs(z)) { + vDir.z = (float)z; + + vAdd[0] = float3(1, 1, 0); + vAdd[1] = float3(-1, 1, 0); + vAdd[2] = float3(-1, -1, 0); + vAdd[3] = float3(1, -1, 0); + } + + // Log("Side: (%.0f : %.0f : %.0f) [ ", vDir.x, vDir.y,vDir.z); + for (int i = 0; i < 4; i++) { + int idx = getBoxIdx(i, x, y, z); + float3 vTex = getBoxTex(i, x, y, z, vAdd); + float2 vCoord = float2((vTex.x + 1) * 0.5f, (vTex.y + 1) * 0.5f); + + color->Write(vertexBufIdx, float4(1, 1, 1, 1)); + position->Write(vertexBufIdx, (vDir + vAdd[idx]) * size); + normal->Write(vertexBufIdx, vDir); + uv->Write(vertexBufIdx++, vCoord); + vSide = vDir + vAdd[idx]; + // Log("%d: Tex: (%.1f : %.1f : %.1f) ", i,vTex.x, vTex.y,vTex.z); + // Log("%d: (%.1f : %.1f : %.1f) ", i,vSide.x, vSide.y,vSide.z); + } + + for (int i = 0; i < 3; i++) { + index->Write(indexBufIndex++, lVtxIdx + i); + } + index->Write(indexBufIndex++, lVtxIdx + 2); + index->Write(indexBufIndex++, lVtxIdx + 3); + index->Write(indexBufIndex++, lVtxIdx + 0); + lVtxIdx += 4; + } } + } + CreateTriTangentVectorsHPL2(vertexBufIdx, indexBufIndex, index, position, uv, normal, tangent); + MeshCreateResult result; + result.numIndices = indexBufIndex; + result.numVertices = vertexBufIdx; + return result; + } + + MeshCreateResult CreateCapsule( + Vector2 avSize, + int alSections, + int alSlices, + AssetBuffer::BufferIndexView* index, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* color, + AssetBuffer::BufferStructuredView* normal, + AssetBuffer::BufferStructuredView* uv, + std::variant*, AssetBuffer::BufferStructuredView*> tangent + ) { + const float fAngleStep = k2Pif/(float)alSections; + const float fRadius = avSize.getX(); + const float fHalfHeight = avSize.getY()*0.5f; + const float fCylinderHalfHeight = cMath::Clamp(fHalfHeight-fRadius, 0,fCylinderHalfHeight); + const float fInvSlices = 1.0f/alSlices; + const float fSectionStep = k2Pif/(float)alSections; + + uint32_t vertexBufIdx = 0; + uint32_t indexBufIndex = 0; + + position->Write(vertexBufIdx, float3(0.0f, cMath::Max(fHalfHeight, fRadius), 0.0f)); + normal->Write(vertexBufIdx, float3(0.0f, 1.0f, 0.0f)); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + + // Slices + const float fHalfPi = kPif*0.5f; + const float fHalfPiOverSlices = fHalfPi*fInvSlices; + + for(int i=0;iWrite(vertexBufIdx, pos); + normal->Write(vertexBufIdx, norm); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + }); + } + details::CreateCircumference(avSize.getX(), fSectionStep, 0, [&](float3 pos) { + pos.y = fCylinderHalfHeight; + float3 norm = v3ToF3(normalize(f3Tov3(pos))); + position->Write(vertexBufIdx, pos); + normal->Write(vertexBufIdx, norm); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + }); + + details::CreateCircumference(avSize.getX(), fSectionStep, 0, [&](float3 pos) { + pos.y = -fCylinderHalfHeight; + float3 norm = v3ToF3(normalize(f3Tov3(pos))); + position->Write(vertexBufIdx, pos); + normal->Write(vertexBufIdx, norm); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + }); + + for(int i=alSlices-2;i>=0; --i) + { + // Same absolute height and radius than upper dome, only reverse order + const float fHeight = fCylinderHalfHeight + fRadius - fRadius*(1+sin(fHalfPiOverSlices*(float)(i+1)-fHalfPi)); + const float fAngle = asin((fHeight-fCylinderHalfHeight)/fRadius); + tVector3fVec vVertices; + + // and height is negative here + details::CreateCircumference(avSize.getX()*cos(fAngle), fSectionStep, -fHeight, [&](float3 pos) { + float3 norm = v3ToF3(normalize(f3Tov3(pos) + Vector3(0, fCylinderHalfHeight, 0))); + position->Write(vertexBufIdx, pos); + normal->Write(vertexBufIdx, norm); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + }); + } + position->Write(vertexBufIdx, float3(0.0f, cMath::Min(-fHalfHeight, -fRadius), 0.0f)); + normal->Write(vertexBufIdx, float3(0.0f, -1.0f, 0.0f)); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + + indexBufIndex = details::WrapUpperCap(indexBufIndex, index, 0, 1, alSections); + for(int i=0;i<2*alSlices-1;++i) + { + indexBufIndex = details::WrapSides(indexBufIndex, index, 1 + i*alSections, alSections); + } + indexBufIndex = details::WrapLowerCap(indexBufIndex, index, vertexBufIdx-1, (vertexBufIdx-1) - alSections, alSections); + CreateTriTangentVectorsHPL2(vertexBufIdx, indexBufIndex, index, position, uv, normal, tangent); + MeshCreateResult result; + result.numIndices = indexBufIndex; + result.numVertices = vertexBufIdx; + return result; } - void MikktSpaceGenerate( + MeshCreateResult CreateCylinder( + Vector2 size, + uint32_t sections, + AssetBuffer::BufferIndexView* index, + AssetBuffer::BufferStructuredView* position, + AssetBuffer::BufferStructuredView* color, + AssetBuffer::BufferStructuredView* normal, + AssetBuffer::BufferStructuredView* uv, + std::variant*, AssetBuffer::BufferStructuredView*> tangent + ) { + + const float fAngleStep = k2Pif/(float)sections; + const float fHalfHeight = size.getY()*0.5f; + + uint32_t vertexBufIdx = 0; + uint32_t indexBufIndex = 0; + + position->Write(vertexBufIdx, float3(0.0f, fHalfHeight, 0.0f)); + normal->Write(vertexBufIdx, float3(0.0f, 1.0f, 0.0f)); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + + details::CreateCircumference(size.getX(), fAngleStep, 0, [&](float3 pos) { + pos.y = fHalfHeight; + float3 norm = v3ToF3(normalize(f3Tov3(pos))); + position->Write(vertexBufIdx, pos); + normal->Write(vertexBufIdx, norm); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + }); + + details::CreateCircumference(size.getX(), fAngleStep, 0, [&](float3 pos) { + pos.y = -fHalfHeight; + float3 norm = v3ToF3(normalize(f3Tov3(pos))); + position->Write(vertexBufIdx, pos); + normal->Write(vertexBufIdx, norm); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + }); + + position->Write(vertexBufIdx, float3(0.0f, -fHalfHeight, 0.0f)); + normal->Write(vertexBufIdx, float3(0.0f, -1.0f, 0.0f)); + color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); + uv->Write(vertexBufIdx++, float2(0, 0)); + + indexBufIndex = details::WrapUpperCap(indexBufIndex, index, 0, 1, sections); + indexBufIndex = details::WrapSides(indexBufIndex, index, 1, sections); + indexBufIndex = details::WrapLowerCap(indexBufIndex, index, (vertexBufIdx - 1), (vertexBufIdx - 1) - sections, sections); + + CreateTriTangentVectorsHPL2(vertexBufIdx, indexBufIndex, index, position, uv, normal, tangent); + MeshCreateResult result; + result.numIndices= indexBufIndex; + result.numVertices = vertexBufIdx; + return result; + } + + void MikkTSpaceGenerate( uint32_t numVerts, uint32_t numIndecies, AssetBuffer::BufferIndexView* view, AssetBuffer::BufferStructuredView* position, AssetBuffer::BufferStructuredView* uv, AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* writeTangent - ) { + AssetBuffer::BufferStructuredView* writeTangent) { details::MikktSpaceUser user; user.m_numElements = numVerts; - user.m_numIndecies = numIndecies; + user.m_numIndices = numIndecies; user.m_indexView = view; user.m_position = position; user.m_uv = uv; user.m_normal = normal; user.m_tangent = writeTangent; - SMikkTSpaceContext context = {0}; - SMikkTSpaceInterface handlers = {0}; + SMikkTSpaceContext context = { 0 }; + SMikkTSpaceInterface handlers = { 0 }; handlers.m_getNumFaces = details::mikkT_getNumberFaces; handlers.m_getNumVerticesOfFace = details::mikkT_getNumVerticesOfFaces; handlers.m_getPosition = details::mikkT_getPosition; @@ -121,4 +799,4 @@ namespace hpl::MeshUtility { bool isSuccess = genTangSpaceDefault(&context); ASSERT(isSuccess == true); } -} +} // namespace hpl::MeshUtility diff --git a/HPL2/sources/graphics/RendererDeferred.cpp b/HPL2/sources/graphics/RendererDeferred.cpp index 1c3fe80d3..a68e0c9b6 100644 --- a/HPL2/sources/graphics/RendererDeferred.cpp +++ b/HPL2/sources/graphics/RendererDeferred.cpp @@ -22,6 +22,7 @@ #include "engine/Event.h" #include "engine/Interface.h" +#include "graphics/DrawPacket.h" #include "graphics/ForgeHandles.h" #include "graphics/DebugDraw.h" #include "graphics/MaterialResource.h" @@ -2519,11 +2520,10 @@ namespace hpl { eVertexBufferElement_Position, eVertexBufferElement_Texture0, }; - LegacyVertexBuffer::GeometryBinding binding; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - LegacyVertexBuffer::cmdBindGeometry(cmd, frame.m_resourcePool, binding); + DrawPacket pkt = illuminationItem->ResolveDrawPacket(frame, targets); + DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &pkt); cmdBindPushConstants(cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(cmd, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(cmd, pkt.m_numIndices, 0, 0); } } void cRendererDeferred::cmdLightPass( @@ -2758,24 +2758,21 @@ namespace hpl { pObject->GetCoverageAmount() >= 1 ? eMaterialRenderMode_Z : eMaterialRenderMode_Z_Dissolve; cMaterial* pMaterial = pObject->GetMaterial(); const MaterialDescriptor& descriptor = pMaterial->Descriptor(); - iVertexBuffer* vertexBuffer = pObject->GetVertexBuffer(); - if (vertexBuffer == nullptr || descriptor.m_id == MaterialID::Unknown) { + std::array targets = { eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + eVertexBufferElement_Normal, + eVertexBufferElement_Texture1Tangent }; + DrawPacket packet = pObject->ResolveDrawPacket(frame, targets); + if (packet.m_type == DrawPacket::Unknown || descriptor.m_id == MaterialID::Unknown) { return; } MaterialRootConstant materialConst = {}; uint32_t instance = cmdBindMaterialAndObject(shadowMapData->m_cmd.m_handle, frame, pMaterial, pObject); materialConst.objectId = instance; - std::array targets = { eVertexBufferElement_Position, - eVertexBufferElement_Texture0, - eVertexBufferElement_Normal, - eVertexBufferElement_Texture1Tangent }; - LegacyVertexBuffer::GeometryBinding binding{}; - static_cast(vertexBuffer) - ->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - LegacyVertexBuffer::cmdBindGeometry(shadowMapData->m_cmd.m_handle, frame.m_resourcePool, binding); + DrawPacket::cmdBindBuffers(shadowMapData->m_cmd.m_handle, frame.m_resourcePool, &packet); cmdBindPushConstants( shadowMapData->m_cmd.m_handle, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(shadowMapData->m_cmd.m_handle, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(shadowMapData->m_cmd.m_handle, packet.m_numIndices, 0, 0); } { cmdBindRenderTargets(shadowMapData->m_cmd.m_handle, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); @@ -3008,16 +3005,15 @@ namespace hpl { cmdSetStencilReferenceValue(cmd, 0xff); std::array elements = { eVertexBufferElement_Position }; - LegacyVertexBuffer::GeometryBinding binding{}; auto lightShape = GetLightShape(light->m_light, eDeferredShapeQuality_High); ASSERT(lightShape && "Light shape not found"); - static_cast(lightShape)->resolveGeometryBinding(frame.m_currentFrame, elements, &binding); - LegacyVertexBuffer::cmdBindGeometry(cmd, frame.m_resourcePool, binding); + DrawPacket packet = static_cast(lightShape)->resolveGeometryBinding(frame.m_currentFrame, elements); + DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &packet); cmdBindPipeline(cmd, options.m_invert ? m_lightStencilPipelineCW.m_handle : m_lightStencilPipelineCCW.m_handle); uint32_t instance = cmdBindLightDescriptor(light); // bind light descriptor light uniforms cmdBindPushConstants(cmd, m_lightPassRootSignature.m_handle, lightRootConstantIndex, &instance); - cmdDrawIndexed(cmd, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(cmd, packet.m_numIndices, 0, 0); switch (light->m_light->GetLightType()) { case eLightType_Point: @@ -3046,7 +3042,7 @@ namespace hpl { break; } cmdBindPushConstants(cmd, m_lightPassRootSignature.m_handle, lightRootConstantIndex, &instance); - cmdDrawIndexed(cmd, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(cmd, packet.m_numIndices, 0, 0); { LoadActionsDesc loadActions = {}; loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; @@ -3110,15 +3106,14 @@ namespace hpl { } std::array targets = { eVertexBufferElement_Position }; - LegacyVertexBuffer::GeometryBinding binding{}; auto lightShape = GetLightShape(light->m_light, eDeferredShapeQuality_High); ASSERT(lightShape && "Light shape not found"); - static_cast(lightShape)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); + DrawPacket packet = static_cast(lightShape)->resolveGeometryBinding(frame.m_currentFrame, targets); uint32_t instance = cmdBindLightDescriptor(light); - LegacyVertexBuffer::cmdBindGeometry(cmd, frame.m_resourcePool, binding); + DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &packet); cmdBindPushConstants(cmd, m_lightPassRootSignature.m_handle, lightRootConstantIndex, &instance); - cmdDrawIndexed(cmd, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(cmd, packet.m_numIndices, 0, 0); } cmdEndDebugMarker(cmd); } @@ -3156,8 +3151,12 @@ namespace hpl { for (auto& diffuseItem : renderList.GetRenderableItems(eRenderListType_Diffuse)) { cMaterial* pMaterial = diffuseItem->GetMaterial(); - iVertexBuffer* vertexBuffer = diffuseItem->GetVertexBuffer(); - if (pMaterial == nullptr || vertexBuffer == nullptr) { + std::array targets = { eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + eVertexBufferElement_Normal, + eVertexBufferElement_Texture1Tangent }; + DrawPacket packet = diffuseItem->ResolveDrawPacket(frame, targets); + if (pMaterial == nullptr || packet.m_type == DrawPacket::Unknown) { continue; } @@ -3165,15 +3164,9 @@ namespace hpl { MaterialRootConstant materialConst = {}; uint32_t instance = cmdBindMaterialAndObject(cmd, frame, pMaterial, diffuseItem); materialConst.objectId = instance; - std::array targets = { eVertexBufferElement_Position, - eVertexBufferElement_Texture0, - eVertexBufferElement_Normal, - eVertexBufferElement_Texture1Tangent }; - LegacyVertexBuffer::GeometryBinding binding; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - LegacyVertexBuffer::cmdBindGeometry(cmd, frame.m_resourcePool, binding); + DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &packet); cmdBindPushConstants(cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(cmd, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(cmd, packet.m_numIndices, 0, 0); } cmdEndDebugMarker(cmd); } @@ -3196,23 +3189,22 @@ namespace hpl { cmdBindDescriptorSet(cmd, frameDescriptorIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); for (auto& decalItem : m_rendererList.GetRenderableItems(eRenderListType_Decal)) { cMaterial* pMaterial = decalItem->GetMaterial(); - iVertexBuffer* vertexBuffer = decalItem->GetVertexBuffer(); - if (pMaterial == nullptr || vertexBuffer == nullptr) { + std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0, eVertexBufferElement_Color0 }; + DrawPacket packet = decalItem->ResolveDrawPacket(frame, targets); + if (pMaterial == nullptr || packet.m_type == DrawPacket::Unknown) { continue; } ASSERT(pMaterial->GetBlendMode() < eMaterialBlendMode_LastEnum && "Invalid blend mode"); ASSERT(pMaterial->Descriptor().m_id == MaterialID::Decal && "Invalid material type"); cmdBindPipeline(cmd, options.m_invert ? m_decalPipelineCW[pMaterial->GetBlendMode()].m_handle : m_decalPipeline[pMaterial->GetBlendMode()].m_handle); - std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0, eVertexBufferElement_Color0 }; MaterialRootConstant materialConst = {}; uint32_t instance = cmdBindMaterialAndObject(cmd, frame, pMaterial, decalItem); materialConst.objectId = instance; - LegacyVertexBuffer::GeometryBinding binding; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - LegacyVertexBuffer::cmdBindGeometry(cmd, frame.m_resourcePool, binding); + //LegacyVertexBuffer::GeometryBinding binding; + DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &packet); cmdBindPushConstants(cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(cmd, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(cmd, packet.m_numIndices, 0, 0); } cmdEndDebugMarker(cmd); } @@ -3298,7 +3290,6 @@ namespace hpl { test.m_renderable = pObject; cMaterial* pMaterial = pObject->GetMaterial(); - iVertexBuffer* vertexBuffer = pObject->GetVertexBuffer(); if (pObject && pObject->GetRenderFrameCount() != iRenderer::GetRenderFrameCount()) { pObject->SetRenderFrameCount(iRenderer::GetRenderFrameCount()); @@ -3397,7 +3388,6 @@ namespace hpl { for (size_t i = 0; i < uniformTest.size(); i++) { auto& test = uniformTest[i]; cMaterial* pMaterial = test.m_renderable->GetMaterial(); - iVertexBuffer* vertexBuffer = test.m_renderable->GetVertexBuffer(); ASSERT(uniformTest.size() < MaxObjectTest && "Too many renderables"); auto* pBoundingVolume = test.m_renderable->GetBoundingVolume(); @@ -3410,22 +3400,24 @@ namespace hpl { reinterpret_cast(updateDesc.pMappedData)[1] = float4(boundBoxMax.x, boundBoxMax.y, boundBoxMax.z, 0.0f); endUpdateResource(&updateDesc, nullptr); - if (!test.m_preZPass || !vertexBuffer || !pMaterial || cMaterial::IsTranslucent(pMaterial->Descriptor().m_id)) { + if (!test.m_preZPass || !pMaterial || cMaterial::IsTranslucent(pMaterial->Descriptor().m_id)) { continue; } - MaterialRootConstant materialConst = {}; - uint32_t instance = cmdBindMaterialAndObject(m_prePassCmd.m_handle, frame, pMaterial, test.m_renderable, {}); - materialConst.objectId = instance; std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0, eVertexBufferElement_Normal, eVertexBufferElement_Texture1Tangent }; - LegacyVertexBuffer::GeometryBinding binding{}; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - LegacyVertexBuffer::cmdBindGeometry(m_prePassCmd.m_handle, frame.m_resourcePool, binding); + DrawPacket packet = test.m_renderable->ResolveDrawPacket(frame, targets); + if(packet.m_type == DrawPacket::Unknown) { + continue; + } + MaterialRootConstant materialConst = {}; + uint32_t instance = cmdBindMaterialAndObject(m_prePassCmd.m_handle, frame, pMaterial, test.m_renderable, {}); + materialConst.objectId = instance; + DrawPacket::cmdBindBuffers(m_prePassCmd.m_handle, frame.m_resourcePool, &packet); cmdBindPushConstants(m_prePassCmd.m_handle, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(m_prePassCmd.m_handle, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(m_prePassCmd.m_handle, packet.m_numIndices, 0, 0); } uniformPropBlock.maxMipLevel = hiZBuffer->mMipLevels - 1; @@ -3440,9 +3432,8 @@ namespace hpl { } { cmdBeginDebugMarker(m_prePassCmd.m_handle, 1, 1, 0, "Occlusion Query"); - LegacyVertexBuffer::GeometryBinding binding{}; std::array targets = { eVertexBufferElement_Position }; - static_cast(m_box.get())->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); + DrawPacket packet = static_cast(m_box.get())->resolveGeometryBinding(frame.m_currentFrame, targets); uint32_t occlusionObjectIndex = getDescriptorIndexFromName(m_rootSignatureOcclusuion.m_handle, "rootConstant"); uint32_t occlusionIndex = 0; @@ -3465,20 +3456,20 @@ namespace hpl { cmdBindPushConstants( m_prePassCmd.m_handle, m_rootSignatureOcclusuion.m_handle, occlusionObjectIndex, &m_occlusionIndex); - LegacyVertexBuffer::cmdBindGeometry(m_prePassCmd.m_handle, frame.m_resourcePool, binding); + DrawPacket::cmdBindBuffers(m_prePassCmd.m_handle, frame.m_resourcePool, &packet); QueryDesc queryDesc = {}; queryDesc.mIndex = queryIndex++; cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineOcclusionQuery.m_handle); cmdBeginQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); - cmdDrawIndexed(m_prePassCmd.m_handle, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(m_prePassCmd.m_handle, packet.m_numIndices, 0, 0); cmdEndQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); query.m_queryIndex = queryDesc.mIndex; queryDesc.mIndex = queryIndex++; cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineMaxOcclusionQuery.m_handle); cmdBeginQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); - cmdDrawIndexed(m_prePassCmd.m_handle, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(m_prePassCmd.m_handle, packet.m_numIndices, 0, 0); cmdEndQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); query.m_maxQueryIndex = queryDesc.mIndex; @@ -3648,23 +3639,25 @@ namespace hpl { renderable->GetCoverageAmount() >= 1 ? eMaterialRenderMode_Z : eMaterialRenderMode_Z_Dissolve; cMaterial* pMaterial = renderable->GetMaterial(); - iVertexBuffer* vertexBuffer = renderable->GetVertexBuffer(); - if (!vertexBuffer || !pMaterial || cMaterial::IsTranslucent(pMaterial->Descriptor().m_id)) { + if (!pMaterial || cMaterial::IsTranslucent(pMaterial->Descriptor().m_id)) { continue; } - - MaterialRootConstant materialConst = {}; - uint32_t instance = cmdBindMaterialAndObject(cmd, frame, pMaterial, renderable); - materialConst.objectId = instance; std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0, eVertexBufferElement_Normal, eVertexBufferElement_Texture1Tangent }; - LegacyVertexBuffer::GeometryBinding binding{}; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - LegacyVertexBuffer::cmdBindGeometry(cmd, frame.m_resourcePool, binding); + DrawPacket drawPacket = renderable->ResolveDrawPacket(frame, targets); + if(drawPacket.m_type == DrawPacket::Unknown) { + continue; + } + + + MaterialRootConstant materialConst = {}; + uint32_t instance = cmdBindMaterialAndObject(cmd, frame, pMaterial, renderable); + materialConst.objectId = instance; + DrawPacket::cmdBindBuffers(frame.m_cmd, frame.m_resourcePool, &drawPacket); cmdBindPushConstants(cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(cmd, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(cmd, drawPacket.m_numIndices, 0, 0); } } } @@ -4120,23 +4113,23 @@ void cRendererDeferred::Draw( for (auto& illuminationItem : m_rendererList.GetRenderableItems(eRenderListType_Illumination)) { cMaterial* pMaterial = illuminationItem->GetMaterial(); - iVertexBuffer* vertexBuffer = illuminationItem->GetVertexBuffer(); - if (pMaterial == nullptr || vertexBuffer == nullptr) { + std::array targets = { + eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + }; + DrawPacket packet = illuminationItem->ResolveDrawPacket(frame, targets); + + if (pMaterial == nullptr || packet.m_type == DrawPacket::Unknown) { continue; } ASSERT(pMaterial->Descriptor().m_id == MaterialID::SolidDiffuse && "Invalid material type"); MaterialRootConstant materialConst = {}; uint32_t instance = cmdBindMaterialAndObject(frame.m_cmd, frame, pMaterial, illuminationItem); materialConst.objectId = instance; - std::array targets = { - eVertexBufferElement_Position, - eVertexBufferElement_Texture0, - }; - LegacyVertexBuffer::GeometryBinding binding; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - LegacyVertexBuffer::cmdBindGeometry(frame.m_cmd, frame.m_resourcePool, binding); + + DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &packet); cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(frame.m_cmd, packet.m_numIndices, 0, 0); } } @@ -4216,10 +4209,9 @@ void cRendererDeferred::Draw( cmdBindPipeline(frame.m_cmd, m_fogPass.m_pipeline.m_handle); - LegacyVertexBuffer::GeometryBinding binding{}; std::array geometryStream = { eVertexBufferElement_Position }; - static_cast(m_box.get())->resolveGeometryBinding(frame.m_currentFrame, geometryStream, &binding); - LegacyVertexBuffer::cmdBindGeometry(frame.m_cmd, frame.m_resourcePool, binding); + DrawPacket drawPacket = static_cast(m_box.get())->resolveGeometryBinding(frame.m_currentFrame, geometryStream); + DrawPacket::cmdBindBuffers(frame.m_cmd, frame.m_resourcePool, &drawPacket); { std::array params = {}; @@ -4236,7 +4228,7 @@ void cRendererDeferred::Draw( cmdBindDescriptorSet(frame.m_cmd, 0, m_fogPass.m_perFrameSet[frame.m_frameIndex]); cmdBindPushConstants(frame.m_cmd, m_fogPass.m_fogRootSignature.m_handle, rootConstantIndex, &fogConstant); - cmdDrawIndexedInstanced(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, fogIndex, 0, 0); + cmdDrawIndexedInstanced(frame.m_cmd, drawPacket.m_numIndices, 0, fogIndex, 0, 0); size_t offsetIndex = fogIndex; for (auto& fogArea : nearPlanFog) { @@ -4251,7 +4243,7 @@ void cRendererDeferred::Draw( cmdBindPipeline(frame.m_cmd, m_fogPass.m_pipelineInsideNearFrustum.m_handle); fogConstant.m_instanceIndex = offsetIndex; cmdBindPushConstants(frame.m_cmd, m_fogPass.m_fogRootSignature.m_handle, rootConstantIndex, &fogConstant); - cmdDrawIndexedInstanced(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, fogIndex - offsetIndex, 0, 0); + cmdDrawIndexedInstanced(frame.m_cmd, drawPacket.m_numIndices, 0, fogIndex - offsetIndex, 0, 0); cmdEndDebugMarker(frame.m_cmd); if (apWorld->GetFogActive()) { @@ -4354,8 +4346,7 @@ void cRendererDeferred::Draw( cmdBindDescriptorSet(frame.m_cmd, mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); for (auto& translucencyItem : m_rendererList.GetRenderableItems(eRenderListType_Translucent)) { cMaterial* pMaterial = translucencyItem->GetMaterial(); - iVertexBuffer* vertexBuffer = translucencyItem->GetVertexBuffer(); - if (pMaterial == nullptr || vertexBuffer == nullptr) { + if (pMaterial == nullptr) { continue; } @@ -4583,12 +4574,6 @@ void cRendererDeferred::Draw( } } - if (isParticleEmitter) { - if (static_cast(vertexBuffer)->GetRequestNumberIndecies() == 0) { - continue; - } - } - MaterialRootConstant materialConst = { 0 }; float sceneAlpha = 1; for (auto& fogArea : fogRenderData) { @@ -4599,23 +4584,30 @@ void cRendererDeferred::Draw( switch (pMaterial->Descriptor().m_id) { case MaterialID::Translucent: { - uint32_t instance = cmdBindMaterialAndObject( - frame.m_cmd, frame, pMaterial, translucencyItem, std::optional{ pMatrix ? *pMatrix : cMatrixf::Identity }); - materialConst.objectId = instance; - LegacyVertexBuffer::GeometryBinding binding; - + //LegacyVertexBuffer::GeometryBinding binding; + DrawPacket drawPacket; if (isParticleEmitter) { std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0, eVertexBufferElement_Color0 }; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); + drawPacket = translucencyItem->ResolveDrawPacket(frame, targets); + if(drawPacket.m_type == DrawPacket::Unknown && drawPacket.m_numIndices == 0) { + break; + } + } else { std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0, eVertexBufferElement_Normal, eVertexBufferElement_Texture1Tangent, eVertexBufferElement_Color0 }; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); + drawPacket = translucencyItem->ResolveDrawPacket(frame, targets); + if(drawPacket.m_type == DrawPacket::Unknown && drawPacket.m_numIndices == 0) { + break; + } } + uint32_t instance = cmdBindMaterialAndObject( + frame.m_cmd, frame, pMaterial, translucencyItem, std::optional{ pMatrix ? *pMatrix : cMatrixf::Identity }); + materialConst.objectId = instance; cRendererDeferred::TranslucencyPipeline::TranslucencyKey key = {}; key.m_field.m_hasDepthTest = pMaterial->GetDepthTest(); @@ -4636,12 +4628,13 @@ void cRendererDeferred::Draw( .m_handle)); } - LegacyVertexBuffer::cmdBindGeometry(frame.m_cmd, frame.m_resourcePool, binding); + DrawPacket::cmdBindBuffers(frame.m_cmd, frame.m_resourcePool, &drawPacket); + materialConst.m_options = (isFogActive ? TranslucencyFlags::UseFog : 0) | (isRefraction ? TranslucencyFlags::UseRefractionTrans : 0) | translucencyBlendTable[pMaterial->GetBlendMode()]; cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(frame.m_cmd, drawPacket.m_numIndices, 0, 0); if (cubeMap && !isRefraction) { materialConst.m_options = TranslucencyFlags::UseIlluminationTrans | (isFogActive ? TranslucencyFlags::UseFog : 0) | @@ -4651,19 +4644,21 @@ void cRendererDeferred::Draw( frame.m_cmd, m_materialTranslucencyPass.m_pipelines[TranslucencyPipeline::TranslucencyBlend::BlendAdd][key.m_id].m_handle); cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(frame.m_cmd, drawPacket.m_numIndices, 0, 0); } } break; case MaterialID::Water: { - LegacyVertexBuffer::GeometryBinding binding; std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0, eVertexBufferElement_Normal, eVertexBufferElement_Texture1Tangent, eVertexBufferElement_Color0 }; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); + DrawPacket packet = translucencyItem->ResolveDrawPacket(frame, targets); + if(packet.m_type == DrawPacket::Unknown) { + break; + } materialConst.m_options = (isFogActive ? TranslucencyFlags::UseFog : 0) | (isRefraction ? TranslucencyFlags::UseRefractionTrans : 0) | @@ -4675,14 +4670,14 @@ void cRendererDeferred::Draw( cRendererDeferred::TranslucencyPipeline::TranslucencyWaterKey key = {}; key.m_field.m_hasDepthTest = pMaterial->GetDepthTest(); - LegacyVertexBuffer::cmdBindGeometry(frame.m_cmd, frame.m_resourcePool, binding); - + //LegacyVertexBuffer::cmdBindGeometry(frame.m_cmd, frame.m_resourcePool, binding); + DrawPacket::cmdBindBuffers(frame.m_cmd, frame.m_resourcePool, &packet); cmdBindPipeline(frame.m_cmd, m_materialTranslucencyPass.m_waterPipeline[key.m_id].m_handle); uint32_t instance = cmdBindMaterialAndObject( frame.m_cmd, frame, pMaterial, translucencyItem, std::optional{ pMatrix ? *pMatrix : cMatrixf::Identity }); materialConst.objectId = instance; cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(frame.m_cmd, packet.m_numIndices, 0, 0); } break; diff --git a/HPL2/sources/graphics/RendererWireFrame.cpp b/HPL2/sources/graphics/RendererWireFrame.cpp index 7d3faf924..071c64789 100644 --- a/HPL2/sources/graphics/RendererWireFrame.cpp +++ b/HPL2/sources/graphics/RendererWireFrame.cpp @@ -20,6 +20,7 @@ #include "graphics/RendererWireFrame.h" #include "Common_3/Graphics/Interfaces/IGraphics.h" +#include "graphics/DrawPacket.h" #include "graphics/ForgeHandles.h" #include "graphics/RenderTarget.h" #include "graphics/VertexBuffer.h" @@ -325,19 +326,17 @@ namespace hpl { cmdBindDescriptorSet(frame.m_cmd, frame.m_frameIndex, m_constDescriptorSet.m_handle); for (auto& diffuseItem : m_rendererList.GetRenderableItems(eRenderListType_Diffuse)) { cMaterial* pMaterial = diffuseItem->GetMaterial(); - iVertexBuffer* vertexBuffer = diffuseItem->GetVertexBuffer(); - if (pMaterial == nullptr || vertexBuffer == nullptr) { + std::array targets = { eVertexBufferElement_Position }; + DrawPacket packet = diffuseItem->ResolveDrawPacket(frame, targets); + if (pMaterial == nullptr || packet.m_type == DrawPacket::Unknown) { continue; } ASSERT(pMaterial->Descriptor().m_id == MaterialID::SolidDiffuse && "Invalid material type"); - std::array targets = { eVertexBufferElement_Position }; - LegacyVertexBuffer::GeometryBinding binding; - static_cast(vertexBuffer)->resolveGeometryBinding(frame.m_currentFrame, targets, &binding); - LegacyVertexBuffer::cmdBindGeometry(frame.m_cmd, frame.m_resourcePool, binding); + DrawPacket::cmdBindBuffers(frame.m_cmd, frame.m_resourcePool, &packet); uint32_t objectIndex = prepareObjectData(frame, diffuseItem); cmdBindPushConstants(frame.m_cmd, m_rootSignature.m_handle, rootConstantIndex, &objectIndex); - cmdDrawIndexed(frame.m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(frame.m_cmd, packet.m_numIndices, 0, 0); } cViewport::PostSolidDrawPacket postSolidEvent = cViewport::PostSolidDrawPacket(); diff --git a/HPL2/sources/impl/LegacyVertexBuffer.cpp b/HPL2/sources/impl/LegacyVertexBuffer.cpp index 7d8bab874..770e7648c 100644 --- a/HPL2/sources/impl/LegacyVertexBuffer.cpp +++ b/HPL2/sources/impl/LegacyVertexBuffer.cpp @@ -18,6 +18,7 @@ */ #include "impl/LegacyVertexBuffer.h" +#include "graphics/DrawPacket.h" #include "graphics/ForgeRenderer.h" #include "math/Math.h" #include "system/LowLevelSystem.h" @@ -84,22 +85,22 @@ namespace hpl { } } - void LegacyVertexBuffer::cmdBindGeometry(Cmd* cmd, ForgeRenderer::CommandResourcePool* resourcePool, LegacyVertexBuffer::GeometryBinding& binding) { - folly::small_vector vbBuffer; - folly::small_vector vbOffsets; - folly::small_vector vbStride; + // void LegacyVertexBuffer::cmdBindGeometry(Cmd* cmd, ForgeRenderer::CommandResourcePool* resourcePool, LegacyVertexBuffer::GeometryBinding& binding) { + // folly::small_vector vbBuffer; + // folly::small_vector vbOffsets; + // folly::small_vector vbStride; - for (auto& element : binding.m_vertexElement) { - vbBuffer.push_back(element.element->m_buffer.m_handle); - vbOffsets.push_back(element.offset); - vbStride.push_back(element.element->Stride()); - resourcePool->Push(element.element->m_buffer); - } - resourcePool->Push(*binding.m_indexBuffer.element); + // for (auto& element : binding.m_vertexElement) { + // vbBuffer.push_back(element.element->m_buffer.m_handle); + // vbOffsets.push_back(element.offset); + // vbStride.push_back(element.element->Stride()); + // resourcePool->Push(element.element->m_buffer); + // } + // resourcePool->Push(*binding.m_indexBuffer.element); - cmdBindVertexBuffer(cmd, binding.m_vertexElement.size(), vbBuffer.data(), vbStride.data(), vbOffsets.data()); - cmdBindIndexBuffer(cmd, binding.m_indexBuffer.element->m_handle, INDEX_TYPE_UINT32, binding.m_indexBuffer.offset); - } + // cmdBindVertexBuffer(cmd, binding.m_vertexElement.size(), vbBuffer.data(), vbStride.data(), vbOffsets.data()); + // cmdBindIndexBuffer(cmd, binding.m_indexBuffer.element->m_handle, INDEX_TYPE_UINT32, binding.m_indexBuffer.offset); + // } void LegacyVertexBuffer::PushVertexElements( std::span values, eVertexBufferElement elementType, std::span elements) { for (auto& element : elements) { @@ -451,8 +452,10 @@ namespace hpl { void LegacyVertexBuffer::Draw(eVertexBufferDrawType aDrawType) { } - void LegacyVertexBuffer::resolveGeometryBinding( - uint32_t frameIndex, std::span elements, GeometryBinding* binding) { + DrawPacket LegacyVertexBuffer::resolveGeometryBinding( + uint32_t frameIndex, std::span elements) { + DrawPacket packet; + packet.m_type = DrawPacket::IndvidualBindings; if(m_updateFlags) { for (auto& element : m_vertexElements) { const bool isDynamicAccess = detail::IsDynamicMemory(mUsageType); @@ -526,17 +529,22 @@ namespace hpl { } // GeometryBinding binding = {}; + packet.m_indvidual.m_numStreams = 0; for (auto& targetEle : elements) { auto found = std::find_if(m_vertexElements.begin(), m_vertexElements.end(), [&](auto& element) { return element.m_type == targetEle; }); ASSERT(found != m_vertexElements.end() && "Element not found"); - binding->m_vertexElement.push_back({found, found->m_activeCopy * found->m_shadowData.size() }); + auto& stream = packet.m_indvidual.m_vertexStream[packet.m_indvidual.m_numStreams++]; + stream.m_buffer = &found->m_buffer; + stream.m_offset = found->m_activeCopy * found->m_shadowData.size(); + stream.m_stride = found->Stride(); } uint32_t numIndecies = (GetRequestNumberIndecies() > 0) ? GetRequestNumberIndecies() : static_cast(m_indices.size()) ; - binding->m_indexBuffer = { - &m_indexBuffer, m_indexBufferActiveCopy * m_indices.size() * sizeof(uint32_t), numIndecies - }; + packet.m_indvidual.m_indexStream.m_offset = m_indexBufferActiveCopy * m_indices.size() * sizeof(uint32_t); + packet.m_numIndices = numIndecies; + packet.m_indvidual.m_indexStream.buffer = &m_indexBuffer; + return packet; } void LegacyVertexBuffer::UnBind() { diff --git a/HPL2/sources/resources/EntFileManager.cpp b/HPL2/sources/resources/EntFileManager.cpp index d95f86618..63e55a352 100644 --- a/HPL2/sources/resources/EntFileManager.cpp +++ b/HPL2/sources/resources/EntFileManager.cpp @@ -28,12 +28,6 @@ namespace hpl { - ////////////////////////////////////////////////////////////////////////// - // ENT FILE - ////////////////////////////////////////////////////////////////////////// - - //----------------------------------------------------------------------- - cEntFile::cEntFile(const tString& asName, const tWString& asFullPath, cResources *apResources) : iResourceBase(asName, asFullPath, 0) { mpXmlDoc = apResources->GetLowLevel()->CreateXmlDocument(asName); @@ -48,15 +42,6 @@ namespace hpl { return mpXmlDoc->CreateFromFile(GetFullPath()); } - //----------------------------------------------------------------------- - - - ////////////////////////////////////////////////////////////////////////// - // CONSTRUCTORS - ////////////////////////////////////////////////////////////////////////// - - //----------------------------------------------------------------------- - cEntFileManager::cEntFileManager(cResources *apResources) : iResourceManager(apResources->GetFileSearcher(), apResources->GetLowLevel(), apResources->GetLowLevelSystem()) { @@ -69,14 +54,6 @@ namespace hpl { Log(" Done with ent files\n"); } - //----------------------------------------------------------------------- - - ////////////////////////////////////////////////////////////////////////// - // PUBLIC METHODS - ////////////////////////////////////////////////////////////////////////// - - //----------------------------------------------------------------------- - cEntFile* cEntFileManager::CreateEntFile(const tString& asName) { tWString sPath; @@ -111,13 +88,11 @@ namespace hpl { return pEntFile; } - //----------------------------------------------------------------------- void cEntFileManager::Unload(iResourceBase* apResource) { } - //----------------------------------------------------------------------- void cEntFileManager::Destroy(iResourceBase* apResource) { @@ -128,17 +103,4 @@ namespace hpl { hplDelete(apResource); } } - - //----------------------------------------------------------------------- - - //----------------------------------------------------------------------- - - ////////////////////////////////////////////////////////////////////////// - // PRIVATE METHODS - ////////////////////////////////////////////////////////////////////////// - - //----------------------------------------------------------------------- - - - //----------------------------------------------------------------------- } diff --git a/HPL2/sources/resources/WorldLoaderHplMap.cpp b/HPL2/sources/resources/WorldLoaderHplMap.cpp index 0398863ca..59fee4fd9 100644 --- a/HPL2/sources/resources/WorldLoaderHplMap.cpp +++ b/HPL2/sources/resources/WorldLoaderHplMap.cpp @@ -22,6 +22,7 @@ #include "Common_3/Utilities/Log/Log.h" #include "graphics/AssetBuffer.h" #include "graphics/Image.h" +#include "graphics/MeshUtility.h" #include "impl/LegacyVertexBuffer.h" #include "system/String.h" #include "system/LowLevelSystem.h" @@ -1839,16 +1840,63 @@ namespace hpl { // Plane if(sType == "Plane") { + auto position = AssetBuffer::BufferStructuredView(); + auto color = AssetBuffer::BufferStructuredView(); + auto normal = AssetBuffer::BufferStructuredView(); + auto uv = AssetBuffer::BufferStructuredView(); + auto tangent = AssetBuffer::BufferStructuredView(); + cSubMesh::IndexBufferInfo indexInfo; + cSubMesh::StreamBufferInfo positionInfo; + cSubMesh::StreamBufferInfo tangentInfo; + cSubMesh::StreamBufferInfo colorInfo; + cSubMesh::StreamBufferInfo normalInfo; + cSubMesh::StreamBufferInfo textureInfo; + cSubMesh::StreamBufferInfo::InitializeBuffer(&positionInfo, &position); + cSubMesh::StreamBufferInfo::InitializeBuffer(&colorInfo, &color); + cSubMesh::StreamBufferInfo::InitializeBuffer(&normalInfo, &normal); + cSubMesh::StreamBufferInfo::InitializeBuffer(&textureInfo, &uv); + cSubMesh::StreamBufferInfo::InitializeBuffer(&tangentInfo, &tangent); + AssetBuffer::BufferIndexView index = indexInfo.GetView(); + cVector3f vStartCorner = apElement->GetAttributeVector3f("StartCorner",0); cVector3f vEndCorner = apElement->GetAttributeVector3f("EndCorner",0); - tVector2fVec vUVCorners; - for(int i=0;i<4;++i) - vUVCorners.push_back(apElement->GetAttributeVector2f("Corner" + cString::ToString(i+1) + "UV")); - - //Create the mesh - cMesh *pMesh = mpGraphics->GetMeshCreator()->CreatePlane(sName,vStartCorner,vEndCorner, - vUVCorners[0],vUVCorners[1], vUVCorners[2], vUVCorners[3], - sMaterial); + std::array vUVCorners; + for(int i=0;i<4;++i) { + vUVCorners[i] = cMath::ToForgeVec2(apElement->GetAttributeVector2f("Corner" + cString::ToString(i+1) + "UV")); + } + + MeshUtility::MeshCreateResult result = MeshUtility::CreatePlane( + {cMath::ToForgeVec3(vStartCorner), cMath::ToForgeVec3(vEndCorner)}, + vUVCorners, + &index, + &position, + &color, + &normal, + &uv, + &tangent + ); + positionInfo.m_numberElements = result.numVertices; + tangentInfo.m_numberElements = result.numVertices; + colorInfo.m_numberElements = result.numVertices; + normalInfo.m_numberElements = result.numVertices; + textureInfo.m_numberElements = result.numVertices; //Create the mesh + indexInfo.m_numberElements = result.numIndices; + + std::vector vertexStreams; + vertexStreams.push_back(std::move(positionInfo)); + vertexStreams.push_back(std::move(tangentInfo)); + vertexStreams.push_back(std::move(colorInfo)); + vertexStreams.push_back(std::move(normalInfo)); + vertexStreams.push_back(std::move(textureInfo)); + + iVertexBuffer* pVtxBuffer = mpGraphics->GetLowLevel()->CreateVertexBuffer(eVertexBufferType_Hardware, eVertexBufferDrawType_Tri, + eVertexBufferUsageType_Static); + cMesh* pMesh = hplNew( cMesh, (sName, _W(""), mpResources->GetMaterialManager(), mpResources->GetAnimationManager())); + cSubMesh* pSubMesh = pMesh->CreateSubMesh("Main"); + cMaterial *pMat = mpResources->GetMaterialManager()->CreateMaterial(sMaterial); + pSubMesh->SetMaterial(pMat); + + pSubMesh->SetStreamBuffers(pVtxBuffer, std::move(vertexStreams), std::move(indexInfo)); ////////////////////// //RENDER_DEBUG diff --git a/HPL2/sources/scene/Beam.cpp b/HPL2/sources/scene/Beam.cpp index 514382c54..4c494ee43 100644 --- a/HPL2/sources/scene/Beam.cpp +++ b/HPL2/sources/scene/Beam.cpp @@ -19,6 +19,7 @@ #include "scene/Beam.h" +#include "impl/LegacyVertexBuffer.h" #include "impl/tinyXML/tinyxml.h" #include "math/Math.h" @@ -112,15 +113,12 @@ namespace hpl { if(mpVtxBuffer) hplDelete(mpVtxBuffer); } - //----------------------------------------------------------------------- + DrawPacket cBeam::ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) { - ////////////////////////////////////////////////////////////////////////// - // PUBLIC METHODS - ////////////////////////////////////////////////////////////////////////// - - //----------------------------------------------------------------------- + return static_cast(mpVtxBuffer)->resolveGeometryBinding(frame.m_currentFrame, elements); + } - void cBeam::SetSize(const cVector2f& avSize) + void cBeam::SetSize(const cVector2f& avSize) { mvSize = avSize; mBoundingVolume.SetSize(cVector3f(mvSize.x, mvSize.y, mvSize.x)); diff --git a/HPL2/sources/scene/BillBoard.cpp b/HPL2/sources/scene/BillBoard.cpp index f4d6cf699..2cfb5cc42 100644 --- a/HPL2/sources/scene/BillBoard.cpp +++ b/HPL2/sources/scene/BillBoard.cpp @@ -19,6 +19,7 @@ #include "scene/BillBoard.h" +#include "impl/LegacyVertexBuffer.h" #include "impl/tinyXML/tinyxml.h" #include "math/MathTypes.h" @@ -126,15 +127,12 @@ namespace hpl { } - //----------------------------------------------------------------------- - - ////////////////////////////////////////////////////////////////////////// - // PUBLIC METHODS - ////////////////////////////////////////////////////////////////////////// - //----------------------------------------------------------------------- + DrawPacket cBillboard::ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) { + return static_cast(mpVtxBuffer)->resolveGeometryBinding(frame.m_currentFrame, elements); + } - void cBillboard::SetSize(const cVector2f& avSize) + void cBillboard::SetSize(const cVector2f& avSize) { mvSize = avSize; mBoundingVolume.SetSize(cVector3f(mvSize.x, mvSize.y, mvSize.x)); diff --git a/HPL2/sources/scene/FogArea.cpp b/HPL2/sources/scene/FogArea.cpp index ba0ff4ba0..9594b0ac6 100644 --- a/HPL2/sources/scene/FogArea.cpp +++ b/HPL2/sources/scene/FogArea.cpp @@ -19,18 +19,13 @@ #include "scene/FogArea.h" +#include "graphics/DrawPacket.h" #include "math/Math.h" #include "resources/Resources.h" namespace hpl { - ////////////////////////////////////////////////////////////////////////// - // CONSTRUCTORS - ////////////////////////////////////////////////////////////////////////// - - //----------------------------------------------------------------------- - cFogArea::cFogArea(tString asName, cResources *apResources) : iRenderable(asName) { mColor = cColor(1,1); @@ -48,22 +43,19 @@ namespace hpl { mBoundingVolume.SetSize(1); } - //----------------------------------------------------------------------- cFogArea::~cFogArea() { } - //----------------------------------------------------------------------- - - ////////////////////////////////////////////////////////////////////////// - // PUBLIC METHODS - ////////////////////////////////////////////////////////////////////////// - - //----------------------------------------------------------------------- + DrawPacket cFogArea::ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) { + DrawPacket drawPacket; + drawPacket.m_type = DrawPacket::Unknown; + return drawPacket; + } - void cFogArea::SetSize(const cVector3f& avSize) + void cFogArea::SetSize(const cVector3f& avSize) { mvSize = avSize; diff --git a/HPL2/sources/scene/ParticleEmitter.cpp b/HPL2/sources/scene/ParticleEmitter.cpp index 600a35a8b..d6c7a4ac2 100644 --- a/HPL2/sources/scene/ParticleEmitter.cpp +++ b/HPL2/sources/scene/ParticleEmitter.cpp @@ -19,6 +19,7 @@ #include "scene/ParticleEmitter.h" +#include "impl/LegacyVertexBuffer.h" #include "system/LowLevelSystem.h" #include "resources/Resources.h" @@ -678,7 +679,11 @@ namespace hpl { return true; } - //----------------------------------------------------------------------- + + DrawPacket iParticleEmitter::ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) + { + return static_cast(mpVtxBuffer)->resolveGeometryBinding(frame.m_currentFrame, elements); + } iVertexBuffer* iParticleEmitter::GetVertexBuffer() { diff --git a/HPL2/sources/scene/RopeEntity.cpp b/HPL2/sources/scene/RopeEntity.cpp index 966773345..3a7915ea3 100644 --- a/HPL2/sources/scene/RopeEntity.cpp +++ b/HPL2/sources/scene/RopeEntity.cpp @@ -19,6 +19,7 @@ #include "scene/RopeEntity.h" +#include "impl/LegacyVertexBuffer.h" #include "math/Math.h" #include "graphics/Graphics.h" @@ -37,12 +38,6 @@ namespace hpl { - ////////////////////////////////////////////////////////////////////////// - // CONSTRUCTORS - ////////////////////////////////////////////////////////////////////////// - - //----------------------------------------------------------------------- - cRopeEntity::cRopeEntity(const tString& asName, cResources *apResources,cGraphics *apGraphics, iPhysicsRope *apRope, int alMaxSegments) : iRenderable(asName) { @@ -96,19 +91,17 @@ namespace hpl { //----------------------------------------------------------------------- - cRopeEntity::~cRopeEntity() + DrawPacket cRopeEntity::ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) { + + return static_cast(mpVtxBuffer)->resolveGeometryBinding(frame.m_currentFrame, elements); + } + + cRopeEntity::~cRopeEntity() { if(mpMaterial) mpMaterialManager->Destroy(mpMaterial); if(mpVtxBuffer) hplDelete(mpVtxBuffer); } - //----------------------------------------------------------------------- - - ////////////////////////////////////////////////////////////////////////// - // PUBLIC METHODS - ////////////////////////////////////////////////////////////////////////// - - //----------------------------------------------------------------------- void cRopeEntity::SetMultiplyAlphaWithColor(bool abX) { diff --git a/HPL2/sources/scene/SubMeshEntity.cpp b/HPL2/sources/scene/SubMeshEntity.cpp index e8b842e8d..25e433a24 100644 --- a/HPL2/sources/scene/SubMeshEntity.cpp +++ b/HPL2/sources/scene/SubMeshEntity.cpp @@ -19,6 +19,7 @@ #include "scene/SubMeshEntity.h" +#include "impl/LegacyVertexBuffer.h" #include "scene/MeshEntity.h" #include "resources/MaterialManager.h" @@ -219,6 +220,13 @@ namespace hpl { } + DrawPacket cSubMeshEntity::ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) { + if(mpDynVtxBuffer) + { + return static_cast(mpDynVtxBuffer)->resolveGeometryBinding(frame.m_currentFrame, elements); + } + return static_cast(mpSubMesh->GetVertexBuffer())->resolveGeometryBinding(frame.m_currentFrame, elements); + } iVertexBuffer* cSubMeshEntity::GetVertexBuffer() { if(mpDynVtxBuffer) diff --git a/amnesia/game/LuxEffectRenderer.cpp b/amnesia/game/LuxEffectRenderer.cpp index 230cd5881..74acdb78d 100644 --- a/amnesia/game/LuxEffectRenderer.cpp +++ b/amnesia/game/LuxEffectRenderer.cpp @@ -28,6 +28,7 @@ #include #include +#include "graphics/DrawPacket.h" #include "graphics/ForgeRenderer.h" #include "graphics/GraphicsTypes.h" @@ -656,16 +657,13 @@ void cLuxEffectRenderer::RenderTrans(cViewport::PostTranslucenceDrawPacket& inp cmdBindPipeline(input.m_frame->m_cmd, m_flashPipeline); for(auto& flashObject: mvFlashObjects) { auto* pObject = flashObject.mpObject; - - auto* vertexBuffer = pObject->GetVertexBuffer(); - if (!pObject->CollidesWithFrustum(input.m_frustum)) + std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Normal, eVertexBufferElement_Texture0 }; + DrawPacket packet = pObject->ResolveDrawPacket(*frame, targets); + if (!pObject->CollidesWithFrustum(input.m_frustum) && packet.m_type == DrawPacket::Unknown) { continue; } - LegacyVertexBuffer::GeometryBinding binding{}; - std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Normal, eVertexBufferElement_Texture0 }; - static_cast(pObject->GetVertexBuffer())->resolveGeometryBinding(frame->m_currentFrame, targets, &binding); - + uint32_t requestSize = round_up(sizeof(LuxEffectObjectUniform::FlashUniform), 256); #ifdef USE_THE_FORGE_LEGACY @@ -698,9 +696,9 @@ void cLuxEffectRenderer::RenderTrans(cViewport::PostTranslucenceDrawPacket& inp endUpdateResource(&updateDesc, NULL); cmdBindDescriptorSet(input.m_frame->m_cmd, objectIndex++, m_perObjectDescriptorSet[frame->m_frameIndex]); - LegacyVertexBuffer::cmdBindGeometry(frame->m_cmd, frame->m_resourcePool, binding); + DrawPacket::cmdBindBuffers(frame->m_cmd, frame->m_resourcePool, &packet); for(size_t i = 0; i < 2; i++) { - cmdDrawIndexed(input.m_frame->m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + cmdDrawIndexed(input.m_frame->m_cmd, packet.m_numIndices, 0, 0); } } cmdEndDebugMarker(input.m_frame->m_cmd); @@ -715,9 +713,8 @@ void cLuxEffectRenderer::RenderTrans(cViewport::PostTranslucenceDrawPacket& inp if (!pObject->CollidesWithFrustum(input.m_frustum)) { continue; } - LegacyVertexBuffer::GeometryBinding binding{}; std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Normal, eVertexBufferElement_Texture0 }; - static_cast(pObject->GetVertexBuffer())->resolveGeometryBinding(frame->m_currentFrame, targets, &binding); + DrawPacket packet = pObject->ResolveDrawPacket(*frame, targets); uint32_t requestSize = round_up(sizeof(LuxEffectObjectUniform::FlashUniform), 256); #ifdef USE_THE_FORGE_LEGACY @@ -749,8 +746,8 @@ void cLuxEffectRenderer::RenderTrans(cViewport::PostTranslucenceDrawPacket& inp endUpdateResource(&updateDesc, NULL); cmdBindDescriptorSet(input.m_frame->m_cmd, objectIndex++, m_perObjectDescriptorSet[frame->m_frameIndex]); - LegacyVertexBuffer::cmdBindGeometry(frame->m_cmd, frame->m_resourcePool, binding); - cmdDrawIndexed(input.m_frame->m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + DrawPacket::cmdBindBuffers(frame->m_cmd, frame->m_resourcePool, &packet); + cmdDrawIndexed(input.m_frame->m_cmd, packet.m_numIndices, 0, 0); } cmdEndDebugMarker(input.m_frame->m_cmd); @@ -780,15 +777,14 @@ void cLuxEffectRenderer::RenderTrans(cViewport::PostTranslucenceDrawPacket& inp continue; } auto* imageAlpha = pMaterial->GetImage(eMaterialTexture_Alpha); - LegacyVertexBuffer::GeometryBinding binding{}; std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0 }; - static_cast(pObject->GetVertexBuffer())->resolveGeometryBinding(frame->m_currentFrame, targets, &binding); + DrawPacket packet = pObject->ResolveDrawPacket(*frame, targets); uint32_t requestSize = round_up(sizeof(LuxEffectObjectUniform::OutlineUniform), 256); #ifdef USE_THE_FORGE_LEGACY - GPURingBufferOffset uniformBlockOffset = getGPURingBufferOffset(m_uniformBuffer, requestSize); + GPURingBufferOffset uniformBlockOffset = getGPURingBufferOffset(m_uniformBuffer, requestSize); #else - GPURingBufferOffset uniformBlockOffset = getGPURingBufferOffset(&m_uniformBuffer, requestSize); + GPURingBufferOffset uniformBlockOffset = getGPURingBufferOffset(&m_uniformBuffer, requestSize); #endif cMatrixf worldMatrix = pObject->GetModelMatrixPtr() ? *pObject->GetModelMatrixPtr() : cMatrixf::Identity; @@ -820,8 +816,8 @@ void cLuxEffectRenderer::RenderTrans(cViewport::PostTranslucenceDrawPacket& inp updateDescriptorSet(frame->m_renderer->Rend(), objectIndex, m_perObjectDescriptorSet[frame->m_frameIndex], params.size(), params.data()); cmdBindDescriptorSet(input.m_frame->m_cmd, objectIndex++, m_perObjectDescriptorSet[frame->m_frameIndex]); - LegacyVertexBuffer::cmdBindGeometry(frame->m_cmd, frame->m_resourcePool, binding); - cmdDrawIndexed(input.m_frame->m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + DrawPacket::cmdBindBuffers(input.m_frame->m_cmd, frame->m_resourcePool, &packet); + cmdDrawIndexed(input.m_frame->m_cmd, packet.m_numIndices, 0, 0); } cmdEndDebugMarker(input.m_frame->m_cmd); @@ -831,14 +827,12 @@ void cLuxEffectRenderer::RenderTrans(cViewport::PostTranslucenceDrawPacket& inp for(auto& pObject: filteredObjects) { auto* vertexBuffer = pObject->GetVertexBuffer(); auto* pMaterial = pObject->GetMaterial(); - if (!pObject->CollidesWithFrustum(input.m_frustum)) { - continue; - } - LegacyVertexBuffer::GeometryBinding binding{}; std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0 }; - static_cast(pObject->GetVertexBuffer())->resolveGeometryBinding(frame->m_currentFrame, targets, &binding); - + DrawPacket drawPacket = pObject->ResolveDrawPacket(*frame, targets); + if (!pObject->CollidesWithFrustum(input.m_frustum) || drawPacket.m_type == DrawPacket::Unknown) { + continue; + } uint32_t requestSize = round_up(sizeof(LuxEffectObjectUniform::OutlineUniform), 256); #ifdef USE_THE_FORGE_LEGACY @@ -874,8 +868,8 @@ void cLuxEffectRenderer::RenderTrans(cViewport::PostTranslucenceDrawPacket& inp updateDescriptorSet(frame->m_renderer->Rend(), objectIndex, m_perObjectDescriptorSet[frame->m_frameIndex], params.size(), params.data()); cmdBindDescriptorSet(input.m_frame->m_cmd, objectIndex++, m_perObjectDescriptorSet[frame->m_frameIndex]); - LegacyVertexBuffer::cmdBindGeometry(frame->m_cmd, frame->m_resourcePool, binding); - cmdDrawIndexed(input.m_frame->m_cmd, binding.m_indexBuffer.numIndicies, 0, 0); + DrawPacket::cmdBindBuffers(input.m_frame->m_cmd, input.m_frame->m_resourcePool, &drawPacket); + cmdDrawIndexed(input.m_frame->m_cmd, drawPacket.m_numIndices, 0, 0); } cmdEndDebugMarker(input.m_frame->m_cmd); diff --git a/tools/NewEditors/Common/EdEngineObject.cpp b/tools/NewEditors/Common/EdEngineObject.cpp index 8613b2569..7ce072715 100644 --- a/tools/NewEditors/Common/EdEngineObject.cpp +++ b/tools/NewEditors/Common/EdEngineObject.cpp @@ -369,7 +369,6 @@ bool cEngineGeneratedMesh::ReCreate(cMesh* apMesh) return Create(sName); } -//----------------------------------------------------------------------- iVertexBuffer* cEngineGeneratedMesh::GetVertexBuffer() { @@ -379,15 +378,6 @@ iVertexBuffer* cEngineGeneratedMesh::GetVertexBuffer() return NULL; } -//----------------------------------------------------------------------- - -////////////////////////////////////////////////////////////////// -// ICON ENTITY - CONSTRUCTORS -////////////////////////////////////////////////////////////////// - -//----------------------------------------------------------------------- - - iIconObject::iIconObject(iEdScnObject* apParent, const tString& asIconFile) : iEngineObject(apParent) { mpIcon = hplNew(cObjectIcon,(apParent, asIconFile)); diff --git a/tools/editors/common/EntityWrapperBodyShape.cpp b/tools/editors/common/EntityWrapperBodyShape.cpp index cff9abbdb..60b1b1f67 100644 --- a/tools/editors/common/EntityWrapperBodyShape.cpp +++ b/tools/editors/common/EntityWrapperBodyShape.cpp @@ -29,7 +29,10 @@ #include "EntityWrapperBody.h" #include "EditorActionsBodies.h" +#include "graphics/AssetBuffer.h" #include "graphics/DebugDraw.h" +#include "graphics/MeshUtility.h" +#include "impl/LegacyVertexBuffer.h" //--------------------------------------------------------------------------- @@ -355,34 +358,68 @@ void cEntityWrapperBodyShape::SetAbsScale(const cVector3f& avScale, int alAxis) ((cEngineEntityGeneratedMesh*)mpEngineEntity)->ReCreate(CreateShape()); } -//--------------------------------------------------------------------------- - -///////////////////////////////////////////////////////////////////////////// -// PROTECTED METHODS -///////////////////////////////////////////////////////////////////////////// - -//--------------------------------------------------------------------------- - cMesh* cEntityWrapperBodyShape::CreateShape() { cEntityWrapperTypeBodyShape* pType = (cEntityWrapperTypeBodyShape*)mpType; tString sMat = pType->GetMaterialFile(HasParentBody(), mbSelected); - int lMeshResolution = 18; - cMesh* pMesh = NULL; - cMeshCreator* pCreator = GetEditorWorld()->GetEditor()->GetEngine()->GetGraphics()->GetMeshCreator(); - switch(mShapeType) - { - case eEditorBodyShape_Box: pMesh = pCreator->CreateBox("", mvScale, sMat); - break; - case eEditorBodyShape_Sphere: pMesh = pCreator->CreateSphere("", mvScale.x, lMeshResolution, lMeshResolution, sMat); //mCustomBV.SetSize(cVector3f(2)); //diameter = radius*2 = 2 - break; - case eEditorBodyShape_Cylinder: pMesh = pCreator->CreateCylinder("", cVector2f(mvScale.x, mvScale.y), lMeshResolution, sMat); //mCustomBV.SetSize(cVector3f(2,1,2)); //diameter = radius*2 = 2 - break; - case eEditorBodyShape_Capsule: pMesh = pCreator->CreateCapsule("", cVector2f(mvScale.x, mvScale.y), lMeshResolution, 5, sMat); //mCustomBV.SetSize(cVector3f(2,1,2)); //diameter = radius*2 = 2//mCustomBV.SetSize(cVector3f(2,1,2)); //diameter = radius*2 = 2 - break; - } - + auto position = AssetBuffer::BufferStructuredView(); + auto color = AssetBuffer::BufferStructuredView(); + auto normal = AssetBuffer::BufferStructuredView(); + auto uv = AssetBuffer::BufferStructuredView(); + auto tangent = AssetBuffer::BufferStructuredView(); + cSubMesh::IndexBufferInfo indexInfo; + cSubMesh::StreamBufferInfo positionInfo; + cSubMesh::StreamBufferInfo tangentInfo; + cSubMesh::StreamBufferInfo colorInfo; + cSubMesh::StreamBufferInfo normalInfo; + cSubMesh::StreamBufferInfo textureInfo; + AssetBuffer::BufferIndexView index = indexInfo.GetView(); + cSubMesh::StreamBufferInfo::InitializeBuffer(&positionInfo, &position); + cSubMesh::StreamBufferInfo::InitializeBuffer(&colorInfo, &color); + cSubMesh::StreamBufferInfo::InitializeBuffer(&normalInfo, &normal); + cSubMesh::StreamBufferInfo::InitializeBuffer(&textureInfo, &uv); + cSubMesh::StreamBufferInfo::InitializeBuffer(&tangentInfo, &tangent); + + MeshUtility::MeshCreateResult result; + switch (mShapeType) { + case eEditorBodyShape_Box: + result = MeshUtility::CreateBox(v3ToF3(cMath::ToForgeVec3(mvScale)), &index, &position, &color, &normal, &uv, &tangent); + break; + case eEditorBodyShape_Sphere: + result = MeshUtility::CreateSphere(mvScale.x, 18, 18, &index, &position, &color, &normal, &uv, &tangent); + break; + case eEditorBodyShape_Cylinder: + result = MeshUtility::CreateCylinder(Vector2(mvScale.x, mvScale.y), 18, &index, &position, &color, &normal, &uv, &tangent); + break; + case eEditorBodyShape_Capsule: + result = MeshUtility::CreateCapsule(Vector2(mvScale.x, mvScale.y), 18, 5, &index, &position, &color, &normal, &uv, &tangent); + break; + default: + ASSERT(false); + break; + } + + positionInfo.m_numberElements = result.numVertices; + tangentInfo.m_numberElements = result.numVertices; + colorInfo.m_numberElements = result.numVertices; + normalInfo.m_numberElements = result.numVertices; + textureInfo.m_numberElements = result.numVertices; //Create the mesh + indexInfo.m_numberElements = result.numIndices; + std::vector vertexStreams; + vertexStreams.push_back(std::move(positionInfo)); + vertexStreams.push_back(std::move(tangentInfo)); + vertexStreams.push_back(std::move(colorInfo)); + vertexStreams.push_back(std::move(normalInfo)); + vertexStreams.push_back(std::move(textureInfo)); + auto* resouces = GetEditorWorld()->GetEditor()->GetEngine()->GetResources(); + auto* graphics = GetEditorWorld()->GetEditor()->GetEngine()->GetGraphics(); + cMesh* pMesh = hplNew( cMesh, ("", _W(""), resouces ->GetMaterialManager(), resouces->GetAnimationManager())); + cSubMesh* pSubMesh = pMesh->CreateSubMesh("Main"); + cMaterial *pMat = resouces->GetMaterialManager()->CreateMaterial(sMat); + pSubMesh->SetMaterial(pMat); + iVertexBuffer* pVtxBuffer = new LegacyVertexBuffer(eVertexBufferDrawType_Tri, eVertexBufferUsageType_Static, 0, 0); + pSubMesh->SetStreamBuffers(pVtxBuffer, std::move(vertexStreams), std::move(indexInfo)); return pMesh; } diff --git a/tools/editors/common/EntityWrapperPrimitivePlane.cpp b/tools/editors/common/EntityWrapperPrimitivePlane.cpp index 767127849..5732685bf 100644 --- a/tools/editors/common/EntityWrapperPrimitivePlane.cpp +++ b/tools/editors/common/EntityWrapperPrimitivePlane.cpp @@ -26,6 +26,8 @@ #include "EngineEntity.h" #include "graphics/DebugDraw.h" +#include "graphics/MeshUtility.h" +#include "impl/LegacyVertexBuffer.h" //--------------------------------------------------------------------------- @@ -475,10 +477,60 @@ cMesh* cEntityWrapperPrimitivePlane::CreatePrimitiveMesh() if(vEndCorner.v[i]!=0) vEndCorner.v[i] /= vEndCorner.v[i]; } - cMesh* pMesh = GetEditorWorld()->GetEditor()->GetEngine()->GetGraphics()->GetMeshCreator()->CreatePlane("", 0, vEndCorner, - cVector2f(1,0), 0, - cVector2f(0,1), 1, - msMaterial); + + auto position = AssetBuffer::BufferStructuredView(); + auto color = AssetBuffer::BufferStructuredView(); + auto normal = AssetBuffer::BufferStructuredView(); + auto uv = AssetBuffer::BufferStructuredView(); + auto tangent = AssetBuffer::BufferStructuredView(); + cSubMesh::IndexBufferInfo indexInfo; + cSubMesh::StreamBufferInfo positionInfo; + cSubMesh::StreamBufferInfo tangentInfo; + cSubMesh::StreamBufferInfo colorInfo; + cSubMesh::StreamBufferInfo normalInfo; + cSubMesh::StreamBufferInfo textureInfo; + AssetBuffer::BufferIndexView index = indexInfo.GetView(); + cSubMesh::StreamBufferInfo::InitializeBuffer(&positionInfo, &position); + cSubMesh::StreamBufferInfo::InitializeBuffer(&colorInfo, &color); + cSubMesh::StreamBufferInfo::InitializeBuffer(&normalInfo, &normal); + cSubMesh::StreamBufferInfo::InitializeBuffer(&textureInfo, &uv); + cSubMesh::StreamBufferInfo::InitializeBuffer(&tangentInfo, &tangent); + + MeshUtility::MeshCreateResult result; + MeshUtility::CreatePlane( + {Vector3(0,0,0), cMath::ToForgeVec3(vEndCorner)}, + {Vector2(1,0), Vector2(0,0), Vector2(0,1), Vector2(1,1)}, + &index, + &position, + &color, + &normal, + &uv, + &tangent); + + positionInfo.m_numberElements = result.numVertices; + tangentInfo.m_numberElements = result.numVertices; + colorInfo.m_numberElements = result.numVertices; + normalInfo.m_numberElements = result.numVertices; + textureInfo.m_numberElements = result.numVertices; //Create the mesh + indexInfo.m_numberElements = result.numIndices; + std::vector vertexStreams; + vertexStreams.push_back(std::move(positionInfo)); + vertexStreams.push_back(std::move(tangentInfo)); + vertexStreams.push_back(std::move(colorInfo)); + vertexStreams.push_back(std::move(normalInfo)); + vertexStreams.push_back(std::move(textureInfo)); + auto* resouces = GetEditorWorld()->GetEditor()->GetEngine()->GetResources(); + auto* graphics = GetEditorWorld()->GetEditor()->GetEngine()->GetGraphics(); + cMesh* pMesh = hplNew( cMesh, ("", _W(""), resouces ->GetMaterialManager(), resouces->GetAnimationManager())); + cSubMesh* pSubMesh = pMesh->CreateSubMesh("Main"); + cMaterial *pMat = resouces->GetMaterialManager()->CreateMaterial(msMaterial); + pSubMesh->SetMaterial(pMat); + iVertexBuffer* pVtxBuffer = new LegacyVertexBuffer(eVertexBufferDrawType_Tri, eVertexBufferUsageType_Static, 0, 0); + pSubMesh->SetStreamBuffers(pVtxBuffer, std::move(vertexStreams), std::move(indexInfo)); + //cMesh* pMesh = GetEditorWorld()->GetEditor()->GetEngine()->GetGraphics()->GetMeshCreator()->CreatePlane("", 0, vEndCorner, + // cVector2f(1,0), 0, + // cVector2f(0,1), 1, + // msMaterial); return pMesh; } From 1a396dad6e7d99a9973084112475147db1ac83e5 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Sun, 22 Oct 2023 21:29:08 -0700 Subject: [PATCH 02/17] feat: reworking storing scheme Signed-off-by: Michael Pollind --- HPL2/include/graphics/Geometry.h | 9 ++ .../{AssetBuffer.h => GraphicsBuffer.h} | 38 ++++-- HPL2/include/graphics/MeshUtility.h | 98 +++++++------- HPL2/include/graphics/SubMesh.h | 12 +- HPL2/sources/graphics/AssetBuffer.cpp | 31 ----- HPL2/sources/graphics/GraphicsBuffer.cpp | 44 ++++++ HPL2/sources/graphics/MeshUtility.cpp | 128 +++++++++--------- HPL2/sources/graphics/SubMesh.cpp | 4 +- HPL2/sources/impl/MeshLoaderCollada.cpp | 12 +- HPL2/sources/impl/MeshLoaderMSH.cpp | 4 +- HPL2/sources/resources/EngineFileLoading.cpp | 12 +- HPL2/sources/resources/WorldLoaderHplMap.cpp | 18 +-- .../editors/common/EntityWrapperBodyShape.cpp | 14 +- .../common/EntityWrapperPrimitivePlane.cpp | 12 +- 14 files changed, 237 insertions(+), 199 deletions(-) create mode 100644 HPL2/include/graphics/Geometry.h rename HPL2/include/graphics/{AssetBuffer.h => GraphicsBuffer.h} (91%) delete mode 100644 HPL2/sources/graphics/AssetBuffer.cpp create mode 100644 HPL2/sources/graphics/GraphicsBuffer.cpp diff --git a/HPL2/include/graphics/Geometry.h b/HPL2/include/graphics/Geometry.h new file mode 100644 index 000000000..6bd567f08 --- /dev/null +++ b/HPL2/include/graphics/Geometry.h @@ -0,0 +1,9 @@ +#pragma once +namespace hpl { + class Geometry { + + + private: + + }; +} diff --git a/HPL2/include/graphics/AssetBuffer.h b/HPL2/include/graphics/GraphicsBuffer.h similarity index 91% rename from HPL2/include/graphics/AssetBuffer.h rename to HPL2/include/graphics/GraphicsBuffer.h index 7e1c4eb9a..ee48553d2 100644 --- a/HPL2/include/graphics/AssetBuffer.h +++ b/HPL2/include/graphics/GraphicsBuffer.h @@ -29,23 +29,33 @@ namespace hpl { } - class AssetBuffer final { + class GraphicsBuffer final { public: + enum BufferType { + ResourceBuffer, + MappedBuffer + }; + struct MappedBufferDesc { + uint64_t m_size; + uint64_t m_dstOffset; + void* m_mappedData; + }; + enum class IndexType : uint8_t { Uint16, Uint32 }; - AssetBuffer() {} - explicit AssetBuffer(const AssetBuffer&); - explicit AssetBuffer(AssetBuffer&&); - explicit AssetBuffer(uint32_t numBytes); + GraphicsBuffer() {} + explicit GraphicsBuffer(const MappedBufferDesc& desc); + explicit GraphicsBuffer(const GraphicsBuffer&); + explicit GraphicsBuffer(GraphicsBuffer&&); - void operator=(const AssetBuffer& other); - void operator=(AssetBuffer&& other); + void operator=(const GraphicsBuffer& other); + void operator=(GraphicsBuffer&& other); class BufferRawView { public: BufferRawView() { } - BufferRawView(AssetBuffer* asset, uint32_t byteOffset) : + BufferRawView(GraphicsBuffer* asset, uint32_t byteOffset) : m_asset(asset), m_byteOffset(byteOffset) { ASSERT(m_byteOffset <= m_asset->Data().size()); @@ -96,13 +106,13 @@ namespace hpl { inline std::span RawView() { return std::span(m_asset->m_buffer.data() + m_byteOffset, m_asset->m_buffer.size() - m_byteOffset); } inline uint32_t NumBytes() { return (m_asset->m_buffer.size() - m_byteOffset); } protected: - AssetBuffer* m_asset = nullptr; + GraphicsBuffer* m_asset = nullptr; uint32_t m_byteOffset = 0; }; struct BufferIndexView: BufferRawView { public: - BufferIndexView(AssetBuffer* asset, uint32_t byteOffset, IndexType type) + BufferIndexView(GraphicsBuffer* asset, uint32_t byteOffset, IndexType type) : BufferRawView(asset, byteOffset) , m_indexType(type) { } @@ -190,7 +200,7 @@ namespace hpl { public: BufferStructuredView() {} - BufferStructuredView(AssetBuffer* asset, uint32_t byteOffset, uint32_t byteStride) + BufferStructuredView(GraphicsBuffer* asset, uint32_t byteOffset, uint32_t byteStride) : BufferRawView(asset, byteOffset) , m_byteStride(byteStride) { ASSERT(m_byteStride >= sizeof(T)); @@ -264,7 +274,13 @@ namespace hpl { std::span Data(); private: + struct { + uint64_t m_size; + uint64_t m_dstOffset; + void* m_mappedData; + } m_mapped; std::vector m_buffer; + BufferType m_type = BufferType::ResourceBuffer; }; diff --git a/HPL2/include/graphics/MeshUtility.h b/HPL2/include/graphics/MeshUtility.h index b0aba1c30..9a10ea02b 100644 --- a/HPL2/include/graphics/MeshUtility.h +++ b/HPL2/include/graphics/MeshUtility.h @@ -1,7 +1,7 @@ #pragma once -#include "graphics/AssetBuffer.h" +#include "graphics/GraphicsBuffer.h" #include #include #include @@ -21,92 +21,92 @@ namespace hpl::MeshUtility { void Transform( uint32_t numElements, const Matrix4& transform, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* tangent + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* tangent ); void MikkTSpaceGenerate( uint32_t numVerts, uint32_t numIndecies, - AssetBuffer::BufferIndexView* view, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* uv, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* writeTangent + GraphicsBuffer::BufferIndexView* view, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* uv, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* writeTangent ); void CreateTriTangentVectorsHPL2( uint32_t numVerts, uint32_t numIndecies, - AssetBuffer::BufferIndexView* index, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* uv, - AssetBuffer::BufferStructuredView* normal, - std::variant*, AssetBuffer::BufferStructuredView*> tangent + GraphicsBuffer::BufferIndexView* index, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* uv, + GraphicsBuffer::BufferStructuredView* normal, + std::variant*, GraphicsBuffer::BufferStructuredView*> tangent ); MeshCreateResult CreateSphere( float afRadius, uint32_t alSections, uint32_t alSlices, - AssetBuffer::BufferIndexView* index, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* color, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* uv, - std::variant*, AssetBuffer::BufferStructuredView*> tangent + GraphicsBuffer::BufferIndexView* index, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* color, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* uv, + std::variant*, GraphicsBuffer::BufferStructuredView*> tangent ); MeshCreateResult CreateBox( float3 size, - AssetBuffer::BufferIndexView* index, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* color, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* uv, - std::variant*, AssetBuffer::BufferStructuredView*> tangent + GraphicsBuffer::BufferIndexView* index, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* color, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* uv, + std::variant*, GraphicsBuffer::BufferStructuredView*> tangent ); MeshCreateResult CreateCylinder( Vector2 size, uint32_t sections, - AssetBuffer::BufferIndexView* index, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* color, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* uv, - std::variant*, AssetBuffer::BufferStructuredView*> tangent); + GraphicsBuffer::BufferIndexView* index, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* color, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* uv, + std::variant*, GraphicsBuffer::BufferStructuredView*> tangent); MeshCreateResult CreateCapsule( Vector2 avSize, int alSections, int alSlices, - AssetBuffer::BufferIndexView* index, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* color, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* uv, - std::variant*, AssetBuffer::BufferStructuredView*> tangent + GraphicsBuffer::BufferIndexView* index, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* color, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* uv, + std::variant*, GraphicsBuffer::BufferStructuredView*> tangent ); MeshCreateResult CreatePlane( const std::array corners, const std::array uvCorners, - AssetBuffer::BufferIndexView* index, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* color, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* uv, - std::variant*, AssetBuffer::BufferStructuredView*> tangent + GraphicsBuffer::BufferIndexView* index, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* color, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* uv, + std::variant*, GraphicsBuffer::BufferStructuredView*> tangent ); MeshCreateResult CreateCone(const float2 avSize, int alSections, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* color, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* uv, - std::variant*, AssetBuffer::BufferStructuredView*> tangent); + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* color, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* uv, + std::variant*, GraphicsBuffer::BufferStructuredView*> tangent); } diff --git a/HPL2/include/graphics/SubMesh.h b/HPL2/include/graphics/SubMesh.h index f607b4350..2b73ef2f1 100644 --- a/HPL2/include/graphics/SubMesh.h +++ b/HPL2/include/graphics/SubMesh.h @@ -19,7 +19,7 @@ #pragma once -#include "graphics/AssetBuffer.h" +#include "graphics/GraphicsBuffer.h" #include "graphics/GraphicsTypes.h" #include "math/MathTypes.h" #include "math/MeshTypes.h" @@ -107,7 +107,7 @@ namespace hpl { // utility function to create buffers allows for consistancy for these types of buffers in the engine template - static void InitializeBuffer(StreamBufferInfo* info, AssetBuffer::BufferStructuredView* view = nullptr) { + static void InitializeBuffer(StreamBufferInfo* info, GraphicsBuffer::BufferStructuredView* view = nullptr) { info->m_stride = Trait::Stride; info->m_semantic = Trait::Semantic; if(view) { @@ -116,11 +116,11 @@ namespace hpl { } template - constexpr AssetBuffer::BufferStructuredView GetStructuredView(uint32_t byteOffset = 0) { + constexpr GraphicsBuffer::BufferStructuredView GetStructuredView(uint32_t byteOffset = 0) { return m_buffer.CreateStructuredView(byteOffset, m_stride); } - AssetBuffer m_buffer; + GraphicsBuffer m_buffer; uint32_t m_stride = 0; uint32_t m_numberElements = 0; ShaderSemantic m_semantic = ShaderSemantic::SEMANTIC_UNDEFINED; @@ -131,12 +131,12 @@ namespace hpl { IndexBufferInfo() { } - AssetBuffer::BufferIndexView GetView() { + GraphicsBuffer::BufferIndexView GetView() { return m_buffer.CreateIndexView(); } uint32_t m_numberElements = 0; - AssetBuffer m_buffer; + GraphicsBuffer m_buffer; }; class MeshCollisionResource { diff --git a/HPL2/sources/graphics/AssetBuffer.cpp b/HPL2/sources/graphics/AssetBuffer.cpp deleted file mode 100644 index 3845adeda..000000000 --- a/HPL2/sources/graphics/AssetBuffer.cpp +++ /dev/null @@ -1,31 +0,0 @@ - -#include "graphics/AssetBuffer.h" - -#include "Common_3/Graphics/Interfaces/IGraphics.h" -#include "FixPreprocessor.h" -#include - -namespace hpl { - - AssetBuffer::AssetBuffer(uint32_t numBytes) { - m_buffer.resize(numBytes, 0); - } - - AssetBuffer::AssetBuffer(const AssetBuffer& asset): - m_buffer(asset.m_buffer){ - } - AssetBuffer::AssetBuffer(AssetBuffer&& asset): - m_buffer(std::move(asset.m_buffer)){ - } - std::span AssetBuffer::Data() { - return m_buffer; - } - - void AssetBuffer::operator=(const AssetBuffer& other) { - m_buffer = other.m_buffer; - } - void AssetBuffer::operator=(AssetBuffer&& other) { - m_buffer = std::move(other.m_buffer); - } - -} // namespace hpl diff --git a/HPL2/sources/graphics/GraphicsBuffer.cpp b/HPL2/sources/graphics/GraphicsBuffer.cpp new file mode 100644 index 000000000..97dc3568a --- /dev/null +++ b/HPL2/sources/graphics/GraphicsBuffer.cpp @@ -0,0 +1,44 @@ + +#include "graphics/GraphicsBuffer.h" + +#include "Common_3/Graphics/Interfaces/IGraphics.h" +#include "FixPreprocessor.h" +#include + +namespace hpl { + + GraphicsBuffer::GraphicsBuffer(const MappedBufferDesc& desc): + m_mapped({ + desc.m_size, + desc.m_dstOffset, + desc.m_mappedData + }), + m_type(BufferType::MappedBuffer){ + } + + GraphicsBuffer::GraphicsBuffer(const GraphicsBuffer& asset): + m_buffer(asset.m_buffer), + m_mapped(asset.m_mapped), + m_type(asset.m_type){ + } + GraphicsBuffer::GraphicsBuffer(GraphicsBuffer&& asset): + m_buffer(std::move(asset.m_buffer)), + m_mapped(asset.m_mapped), + m_type(asset.m_type){ + } + std::span GraphicsBuffer::Data() { + return m_buffer; + } + + void GraphicsBuffer::operator=(const GraphicsBuffer& other) { + m_buffer = other.m_buffer; + m_mapped = other.m_mapped; + m_type = other.m_type; + } + void GraphicsBuffer::operator=(GraphicsBuffer&& other) { + m_buffer = std::move(other.m_buffer); + m_mapped = other.m_mapped; + m_type = other.m_type; + } + +} // namespace hpl diff --git a/HPL2/sources/graphics/MeshUtility.cpp b/HPL2/sources/graphics/MeshUtility.cpp index ab1d5129e..b1ac2b84b 100644 --- a/HPL2/sources/graphics/MeshUtility.cpp +++ b/HPL2/sources/graphics/MeshUtility.cpp @@ -2,7 +2,7 @@ #include "Common_3/Utilities/Log/Log.h" #include "Common_3/Utilities/ThirdParty/OpenSource/ModifiedSonyMath/common.hpp" #include "Common_3/Utilities/ThirdParty/OpenSource/ModifiedSonyMath/sse/vectormath.hpp" -#include "graphics/AssetBuffer.h" +#include "graphics/GraphicsBuffer.h" #include "graphics/mikktspace.h" #include "math/Math.h" @@ -19,27 +19,27 @@ namespace hpl::MeshUtility { struct MikktSpaceUser { uint32_t m_numElements; uint32_t m_numIndices; - AssetBuffer::BufferIndexView* m_indexView; - AssetBuffer::BufferStructuredView* m_position; - AssetBuffer::BufferStructuredView* m_uv; - AssetBuffer::BufferStructuredView* m_normal; - AssetBuffer::BufferStructuredView* m_tangent; + GraphicsBuffer::BufferIndexView* m_indexView; + GraphicsBuffer::BufferStructuredView* m_position; + GraphicsBuffer::BufferStructuredView* m_uv; + GraphicsBuffer::BufferStructuredView* m_normal; + GraphicsBuffer::BufferStructuredView* m_tangent; }; inline void CreateTriTangentVectorsHPL2( uint32_t numVerts, uint32_t numIndecies, - AssetBuffer::BufferIndexView* indexView, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* uv, - AssetBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferIndexView* indexView, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* uv, + GraphicsBuffer::BufferStructuredView* normal, std::function handler ) { } - uint32_t WrapSides(uint32_t viewIndex, AssetBuffer::BufferIndexView* view, int alStartVertexIdx, int alSections) { + uint32_t WrapSides(uint32_t viewIndex, GraphicsBuffer::BufferIndexView* view, int alStartVertexIdx, int alSections) { // Create indices like this 0 --- 1 --- 2 --- ... --- 0 // | / | / | // | / | / | @@ -91,7 +91,7 @@ namespace hpl::MeshUtility { } } uint32_t WrapLowerCap( - uint32_t viewIndex, AssetBuffer::BufferIndexView* view, int alCenterVertexIdx, int alStartVertexIdx, int alSections) { + uint32_t viewIndex, GraphicsBuffer::BufferIndexView* view, int alCenterVertexIdx, int alStartVertexIdx, int alSections) { for (int i = 0; i < alSections - 1; ++i) { int lBase = alStartVertexIdx + i; view->Write(viewIndex++, alCenterVertexIdx); @@ -105,7 +105,7 @@ namespace hpl::MeshUtility { return viewIndex; } uint32_t WrapUpperCap( - uint32_t viewIndex, AssetBuffer::BufferIndexView* view, int alCenterVertexIdx, int alStartVertexIdx, int alSections) { + uint32_t viewIndex, GraphicsBuffer::BufferIndexView* view, int alCenterVertexIdx, int alStartVertexIdx, int alSections) { for (int i = 0; i < alSections - 1; ++i) { int lBase = alStartVertexIdx + i; view->Write(viewIndex++, alCenterVertexIdx); @@ -165,9 +165,9 @@ namespace hpl::MeshUtility { void Transform( uint32_t numElements, const Matrix4& transform, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* tangent) { + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* tangent) { Matrix3 normalMat = transpose(inverse(transform.getUpper3x3())); for (size_t i = 0; i < numElements; i++) { if (position) { @@ -188,11 +188,11 @@ namespace hpl::MeshUtility { void CreateTriTangentVectorsHPL2( uint32_t numVerts, uint32_t numIndices, - AssetBuffer::BufferIndexView* indexView, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* uv, - AssetBuffer::BufferStructuredView* normal, - std::variant*, AssetBuffer::BufferStructuredView*> tangent + GraphicsBuffer::BufferIndexView* indexView, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* uv, + GraphicsBuffer::BufferStructuredView* normal, + std::variant*, GraphicsBuffer::BufferStructuredView*> tangent ) { struct TangentPairs { float3 sDir; @@ -281,10 +281,10 @@ namespace hpl::MeshUtility { float fw = dot(cross(norm,f3Tov3(tangentPair.sDir)), f3Tov3(tangentPair.tDir)) < 0.0f ? -1.0f : 1.0f; std::visit([&](auto& item) { using T = std::decay_t; - if constexpr (std::is_same_v*>) { + if constexpr (std::is_same_v*>) { item->Write(vtxIdx, v3ToF3(tang)); } - if constexpr (std::is_same_v*>) { + if constexpr (std::is_same_v*>) { item->Write(vtxIdx, float4(v3ToF3(tang), fw)); } }, tangent); @@ -294,12 +294,12 @@ namespace hpl::MeshUtility { float afRadius, uint32_t alSections, uint32_t alSlices, - AssetBuffer::BufferIndexView* index, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* color, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* uv, - std::variant*, AssetBuffer::BufferStructuredView*> tangent) { + GraphicsBuffer::BufferIndexView* index, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* color, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* uv, + std::variant*, GraphicsBuffer::BufferStructuredView*> tangent) { ASSERT(index); ASSERT(position); ASSERT(color); @@ -371,12 +371,12 @@ namespace hpl::MeshUtility { MeshCreateResult CreatePlane( const std::array corners, const std::array uvCorners, - AssetBuffer::BufferIndexView* index, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* color, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* uv, - std::variant*, AssetBuffer::BufferStructuredView*> tangent + GraphicsBuffer::BufferIndexView* index, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* color, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* uv, + std::variant*, GraphicsBuffer::BufferStructuredView*> tangent ) { const Vector3 diff = corners[0] - corners[1]; folly::small_vector vPlaneAxes; @@ -459,12 +459,12 @@ namespace hpl::MeshUtility { } MeshCreateResult CreateCone(const float2 avSize, int alSections, - AssetBuffer::BufferIndexView* index, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* color, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* uv, - std::variant*, AssetBuffer::BufferStructuredView*> tangent) { + GraphicsBuffer::BufferIndexView* index, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* color, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* uv, + std::variant*, GraphicsBuffer::BufferStructuredView*> tangent) { const float fAngleStep = k2Pif/(float)alSections; const float fHalfHeight = avSize.y*0.5f; @@ -503,12 +503,12 @@ namespace hpl::MeshUtility { } MeshCreateResult CreateBox( float3 size, - AssetBuffer::BufferIndexView* index, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* color, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* uv, - std::variant*, AssetBuffer::BufferStructuredView*> tangent + GraphicsBuffer::BufferIndexView* index, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* color, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* uv, + std::variant*, GraphicsBuffer::BufferStructuredView*> tangent ) { ASSERT(index); ASSERT(position); @@ -623,12 +623,12 @@ namespace hpl::MeshUtility { Vector2 avSize, int alSections, int alSlices, - AssetBuffer::BufferIndexView* index, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* color, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* uv, - std::variant*, AssetBuffer::BufferStructuredView*> tangent + GraphicsBuffer::BufferIndexView* index, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* color, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* uv, + std::variant*, GraphicsBuffer::BufferStructuredView*> tangent ) { const float fAngleStep = k2Pif/(float)alSections; const float fRadius = avSize.getX(); @@ -717,12 +717,12 @@ namespace hpl::MeshUtility { MeshCreateResult CreateCylinder( Vector2 size, uint32_t sections, - AssetBuffer::BufferIndexView* index, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* color, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* uv, - std::variant*, AssetBuffer::BufferStructuredView*> tangent + GraphicsBuffer::BufferIndexView* index, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* color, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* uv, + std::variant*, GraphicsBuffer::BufferStructuredView*> tangent ) { const float fAngleStep = k2Pif/(float)sections; @@ -773,11 +773,11 @@ namespace hpl::MeshUtility { void MikkTSpaceGenerate( uint32_t numVerts, uint32_t numIndecies, - AssetBuffer::BufferIndexView* view, - AssetBuffer::BufferStructuredView* position, - AssetBuffer::BufferStructuredView* uv, - AssetBuffer::BufferStructuredView* normal, - AssetBuffer::BufferStructuredView* writeTangent) { + GraphicsBuffer::BufferIndexView* view, + GraphicsBuffer::BufferStructuredView* position, + GraphicsBuffer::BufferStructuredView* uv, + GraphicsBuffer::BufferStructuredView* normal, + GraphicsBuffer::BufferStructuredView* writeTangent) { details::MikktSpaceUser user; user.m_numElements = numVerts; user.m_numIndices = numIndecies; diff --git a/HPL2/sources/graphics/SubMesh.cpp b/HPL2/sources/graphics/SubMesh.cpp index 9d20a8c9f..844fd5ba6 100644 --- a/HPL2/sources/graphics/SubMesh.cpp +++ b/HPL2/sources/graphics/SubMesh.cpp @@ -19,7 +19,7 @@ #include "graphics/SubMesh.h" -#include "graphics/AssetBuffer.h" +#include "graphics/GraphicsBuffer.h" #include "graphics/GraphicsTypes.h" #include "impl/LegacyVertexBuffer.h" @@ -53,7 +53,7 @@ namespace hpl { auto* lvbElement = buffer->GetElement(element); if(lvbElement) { cSubMesh::StreamBufferInfo& info = vertexBuffers.emplace_back(); - AssetBuffer::BufferStructuredView view; + GraphicsBuffer::BufferStructuredView view; cSubMesh::StreamBufferInfo::InitializeBuffer(&info, &view); uint32_t numElements = lvbElement->NumElements(); view.ReserveElements(numElements); diff --git a/HPL2/sources/impl/MeshLoaderCollada.cpp b/HPL2/sources/impl/MeshLoaderCollada.cpp index 0acc8ca17..9701cda76 100644 --- a/HPL2/sources/impl/MeshLoaderCollada.cpp +++ b/HPL2/sources/impl/MeshLoaderCollada.cpp @@ -477,11 +477,11 @@ namespace hpl { //To be filled by extra vertex positions (not used, use the one in Geometry) tColladaExtraVtxListVec &vExtraVtxVec = Geom.mvExtraVtxVec; - auto position = AssetBuffer::BufferStructuredView(); - auto color = AssetBuffer::BufferStructuredView(); - auto normal = AssetBuffer::BufferStructuredView(); - auto uv = AssetBuffer::BufferStructuredView(); - auto tangent = AssetBuffer::BufferStructuredView(); + auto position = GraphicsBuffer::BufferStructuredView(); + auto color = GraphicsBuffer::BufferStructuredView(); + auto normal = GraphicsBuffer::BufferStructuredView(); + auto uv = GraphicsBuffer::BufferStructuredView(); + auto tangent = GraphicsBuffer::BufferStructuredView(); cSubMesh::IndexBufferInfo indexInfo; cSubMesh::StreamBufferInfo positionInfo; cSubMesh::StreamBufferInfo tangentInfo; @@ -493,7 +493,7 @@ namespace hpl { cSubMesh::StreamBufferInfo::InitializeBuffer(&normalInfo, &normal); cSubMesh::StreamBufferInfo::InitializeBuffer(&textureInfo, &uv); cSubMesh::StreamBufferInfo::InitializeBuffer(&tangentInfo, &tangent); - AssetBuffer::BufferIndexView indexView = indexInfo.GetView(); + GraphicsBuffer::BufferIndexView indexView = indexInfo.GetView(); for(size_t i = 0; i < Geom.mvVertexVec.size(); i++) { auto& vert = Geom.mvVertexVec[i]; position.Write(i, float3(vert.pos.x, vert.pos.y, vert.pos.z)); diff --git a/HPL2/sources/impl/MeshLoaderMSH.cpp b/HPL2/sources/impl/MeshLoaderMSH.cpp index 885705006..51d59113e 100644 --- a/HPL2/sources/impl/MeshLoaderMSH.cpp +++ b/HPL2/sources/impl/MeshLoaderMSH.cpp @@ -229,7 +229,7 @@ namespace hpl { // Vertex data std::vector vertexStreams; cSubMesh::IndexBufferInfo indexInfo; - AssetBuffer::BufferIndexView indexView = indexInfo.GetView(); + GraphicsBuffer::BufferIndexView indexView = indexInfo.GetView(); { int lVtxNum = binBuff.GetInt32(); int lVtxTypeNum = binBuff.GetInt32(); @@ -253,7 +253,7 @@ namespace hpl { streamBuffer.m_stride = mp.streamBufferStride; streamBuffer.m_semantic = mp.semantic; streamBuffer.m_numberElements = lVtxNum; - AssetBuffer::BufferRawView rawView = streamBuffer.m_buffer.CreateViewRaw(); + GraphicsBuffer::BufferRawView rawView = streamBuffer.m_buffer.CreateViewRaw(); std::array stage; std::span floatSpan = rawView.RawDataView(); for(size_t vtxIdx = 0; vtxIdx < lVtxNum; vtxIdx++) { diff --git a/HPL2/sources/resources/EngineFileLoading.cpp b/HPL2/sources/resources/EngineFileLoading.cpp index 46e2ea9fb..beed2bdc8 100644 --- a/HPL2/sources/resources/EngineFileLoading.cpp +++ b/HPL2/sources/resources/EngineFileLoading.cpp @@ -388,11 +388,11 @@ namespace hpl { } tString sSepp=" "; - auto position = AssetBuffer::BufferStructuredView(); - auto color = AssetBuffer::BufferStructuredView(); - auto normal = AssetBuffer::BufferStructuredView(); - auto uv = AssetBuffer::BufferStructuredView(); - auto tangent = AssetBuffer::BufferStructuredView(); + auto position = GraphicsBuffer::BufferStructuredView(); + auto color = GraphicsBuffer::BufferStructuredView(); + auto normal = GraphicsBuffer::BufferStructuredView(); + auto uv = GraphicsBuffer::BufferStructuredView(); + auto tangent = GraphicsBuffer::BufferStructuredView(); cSubMesh::IndexBufferInfo indexInfo; cSubMesh::StreamBufferInfo positionInfo; cSubMesh::StreamBufferInfo tangentInfo; @@ -450,7 +450,7 @@ namespace hpl { std::vector indexArray; indexArray.reserve(lNumOfIdx); cString::GetIntVec(pIndicesElem->GetAttributeString("Array"), indexArray,&sSepp); - AssetBuffer::BufferIndexView view = indexInfo.GetView(); + GraphicsBuffer::BufferIndexView view = indexInfo.GetView(); for(int idx=0; idx < lNumOfIdx; ++idx) { view.Write(idx, indexArray[idx]); } diff --git a/HPL2/sources/resources/WorldLoaderHplMap.cpp b/HPL2/sources/resources/WorldLoaderHplMap.cpp index 59fee4fd9..7d72107e7 100644 --- a/HPL2/sources/resources/WorldLoaderHplMap.cpp +++ b/HPL2/sources/resources/WorldLoaderHplMap.cpp @@ -20,7 +20,7 @@ #include "resources/WorldLoaderHplMap.h" #include "Common_3/Utilities/Log/Log.h" -#include "graphics/AssetBuffer.h" +#include "graphics/GraphicsBuffer.h" #include "graphics/Image.h" #include "graphics/MeshUtility.h" #include "impl/LegacyVertexBuffer.h" @@ -512,7 +512,7 @@ namespace hpl { std::vector vertexStreams; cSubMesh::IndexBufferInfo indexInfo; - AssetBuffer::BufferIndexView indexView = indexInfo.GetView(); + GraphicsBuffer::BufferIndexView indexView = indexInfo.GetView(); { int lVtxNum = binBuff.GetInt32(); int lVtxTypeNum = binBuff.GetInt32(); @@ -551,7 +551,7 @@ namespace hpl { streamBuffer.m_stride = mp.streamBufferStride; streamBuffer.m_semantic = mp.semantic; streamBuffer.m_numberElements = lElementNum; - AssetBuffer::BufferRawView rawView = streamBuffer.m_buffer.CreateViewRaw(); + GraphicsBuffer::BufferRawView rawView = streamBuffer.m_buffer.CreateViewRaw(); std::array stage; std::span floatSpan = rawView.RawDataView(); for(size_t vtxIdx = 0; vtxIdx < lVtxNum; vtxIdx++) { @@ -1840,11 +1840,11 @@ namespace hpl { // Plane if(sType == "Plane") { - auto position = AssetBuffer::BufferStructuredView(); - auto color = AssetBuffer::BufferStructuredView(); - auto normal = AssetBuffer::BufferStructuredView(); - auto uv = AssetBuffer::BufferStructuredView(); - auto tangent = AssetBuffer::BufferStructuredView(); + auto position = GraphicsBuffer::BufferStructuredView(); + auto color = GraphicsBuffer::BufferStructuredView(); + auto normal = GraphicsBuffer::BufferStructuredView(); + auto uv = GraphicsBuffer::BufferStructuredView(); + auto tangent = GraphicsBuffer::BufferStructuredView(); cSubMesh::IndexBufferInfo indexInfo; cSubMesh::StreamBufferInfo positionInfo; cSubMesh::StreamBufferInfo tangentInfo; @@ -1856,7 +1856,7 @@ namespace hpl { cSubMesh::StreamBufferInfo::InitializeBuffer(&normalInfo, &normal); cSubMesh::StreamBufferInfo::InitializeBuffer(&textureInfo, &uv); cSubMesh::StreamBufferInfo::InitializeBuffer(&tangentInfo, &tangent); - AssetBuffer::BufferIndexView index = indexInfo.GetView(); + GraphicsBuffer::BufferIndexView index = indexInfo.GetView(); cVector3f vStartCorner = apElement->GetAttributeVector3f("StartCorner",0); cVector3f vEndCorner = apElement->GetAttributeVector3f("EndCorner",0); diff --git a/tools/editors/common/EntityWrapperBodyShape.cpp b/tools/editors/common/EntityWrapperBodyShape.cpp index 60b1b1f67..f782d2300 100644 --- a/tools/editors/common/EntityWrapperBodyShape.cpp +++ b/tools/editors/common/EntityWrapperBodyShape.cpp @@ -29,7 +29,7 @@ #include "EntityWrapperBody.h" #include "EditorActionsBodies.h" -#include "graphics/AssetBuffer.h" +#include "graphics/GraphicsBuffer.h" #include "graphics/DebugDraw.h" #include "graphics/MeshUtility.h" #include "impl/LegacyVertexBuffer.h" @@ -363,18 +363,18 @@ cMesh* cEntityWrapperBodyShape::CreateShape() cEntityWrapperTypeBodyShape* pType = (cEntityWrapperTypeBodyShape*)mpType; tString sMat = pType->GetMaterialFile(HasParentBody(), mbSelected); - auto position = AssetBuffer::BufferStructuredView(); - auto color = AssetBuffer::BufferStructuredView(); - auto normal = AssetBuffer::BufferStructuredView(); - auto uv = AssetBuffer::BufferStructuredView(); - auto tangent = AssetBuffer::BufferStructuredView(); + auto position = GraphicsBuffer::BufferStructuredView(); + auto color = GraphicsBuffer::BufferStructuredView(); + auto normal = GraphicsBuffer::BufferStructuredView(); + auto uv = GraphicsBuffer::BufferStructuredView(); + auto tangent = GraphicsBuffer::BufferStructuredView(); cSubMesh::IndexBufferInfo indexInfo; cSubMesh::StreamBufferInfo positionInfo; cSubMesh::StreamBufferInfo tangentInfo; cSubMesh::StreamBufferInfo colorInfo; cSubMesh::StreamBufferInfo normalInfo; cSubMesh::StreamBufferInfo textureInfo; - AssetBuffer::BufferIndexView index = indexInfo.GetView(); + GraphicsBuffer::BufferIndexView index = indexInfo.GetView(); cSubMesh::StreamBufferInfo::InitializeBuffer(&positionInfo, &position); cSubMesh::StreamBufferInfo::InitializeBuffer(&colorInfo, &color); cSubMesh::StreamBufferInfo::InitializeBuffer(&normalInfo, &normal); diff --git a/tools/editors/common/EntityWrapperPrimitivePlane.cpp b/tools/editors/common/EntityWrapperPrimitivePlane.cpp index 5732685bf..588857785 100644 --- a/tools/editors/common/EntityWrapperPrimitivePlane.cpp +++ b/tools/editors/common/EntityWrapperPrimitivePlane.cpp @@ -478,18 +478,18 @@ cMesh* cEntityWrapperPrimitivePlane::CreatePrimitiveMesh() vEndCorner.v[i] /= vEndCorner.v[i]; } - auto position = AssetBuffer::BufferStructuredView(); - auto color = AssetBuffer::BufferStructuredView(); - auto normal = AssetBuffer::BufferStructuredView(); - auto uv = AssetBuffer::BufferStructuredView(); - auto tangent = AssetBuffer::BufferStructuredView(); + auto position = GraphicsBuffer::BufferStructuredView(); + auto color = GraphicsBuffer::BufferStructuredView(); + auto normal = GraphicsBuffer::BufferStructuredView(); + auto uv = GraphicsBuffer::BufferStructuredView(); + auto tangent = GraphicsBuffer::BufferStructuredView(); cSubMesh::IndexBufferInfo indexInfo; cSubMesh::StreamBufferInfo positionInfo; cSubMesh::StreamBufferInfo tangentInfo; cSubMesh::StreamBufferInfo colorInfo; cSubMesh::StreamBufferInfo normalInfo; cSubMesh::StreamBufferInfo textureInfo; - AssetBuffer::BufferIndexView index = indexInfo.GetView(); + GraphicsBuffer::BufferIndexView index = indexInfo.GetView(); cSubMesh::StreamBufferInfo::InitializeBuffer(&positionInfo, &position); cSubMesh::StreamBufferInfo::InitializeBuffer(&colorInfo, &color); cSubMesh::StreamBufferInfo::InitializeBuffer(&normalInfo, &normal); From e45d254ef7c072b41d9e37f580cbfd6eb389dd63 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Mon, 23 Oct 2023 22:10:24 -0700 Subject: [PATCH 03/17] add missing logic for merging geometries Signed-off-by: Michael Pollind --- HPL2/include/graphics/Enum.h | 14 +- HPL2/include/graphics/Geometry.h | 23 +- HPL2/include/graphics/GraphicsBuffer.h | 273 ++++++++++++++---- HPL2/include/graphics/MeshUtility.h | 8 +- HPL2/include/graphics/SubMesh.h | 21 +- HPL2/include/resources/TextureManager.h | 9 +- HPL2/include/scene/SubMeshEntity.h | 21 +- HPL2/sources/graphics/Enum.cpp | 33 +++ HPL2/sources/graphics/GraphicsBuffer.cpp | 5 - HPL2/sources/graphics/MeshUtility.cpp | 24 +- HPL2/sources/graphics/RendererDeferred.cpp | 17 +- HPL2/sources/graphics/SubMesh.cpp | 5 +- HPL2/sources/impl/MeshLoaderMSH.cpp | 2 +- HPL2/sources/resources/WorldLoaderHplMap.cpp | 219 +++++++------- HPL2/sources/scene/SubMeshEntity.cpp | 80 ++++- .../common/EntityWrapperPrimitivePlane.cpp | 4 +- 16 files changed, 542 insertions(+), 216 deletions(-) diff --git a/HPL2/include/graphics/Enum.h b/HPL2/include/graphics/Enum.h index 7cdbfb3ef..827aa1dc4 100644 --- a/HPL2/include/graphics/Enum.h +++ b/HPL2/include/graphics/Enum.h @@ -1,10 +1,13 @@ #pragma once -#include "graphics/GraphicsTypes.h" #include +#include "FixPreprocessor.h" +#include "graphics/GraphicsTypes.h" -namespace hpl -{ +#include "Common_3/Graphics/Interfaces/IGraphics.h" +#include "FixPreprocessor.h" + +namespace hpl { enum class WrapMode : uint8_t { None, @@ -14,5 +17,10 @@ namespace hpl Border }; + enum class IndexBufferType : uint8_t { + Uint16 = 0, + Uint32 = 1 + }; + ShaderSemantic hplToForgeShaderSemantic(eVertexBufferElement element); } // namespace hpl diff --git a/HPL2/include/graphics/Geometry.h b/HPL2/include/graphics/Geometry.h index 6bd567f08..a848f2172 100644 --- a/HPL2/include/graphics/Geometry.h +++ b/HPL2/include/graphics/Geometry.h @@ -1,9 +1,28 @@ #pragma once +#include "Common_3/Graphics/Interfaces/IGraphics.h" +#include "graphics/ForgeHandles.h" +#include +#include namespace hpl { - class Geometry { + struct Geometry { + public: + static constexpr uint32_t MaxVertexBindings = 15; + struct StreamBufferInfo { + SharedBuffer m_buffer; + ShaderSemantic m_semantic; + uint64_t m_stride; + uint64_t m_offset; + }; - private: + struct IndexBufferInfo { + SharedBuffer m_buffer; + IndexType m_IndexType; + uint64_t m_offset; + }; + uint32_t m_numIndices; + folly::small_vector m_vertexStreams; + IndexBufferInfo m_indexStream; }; } diff --git a/HPL2/include/graphics/GraphicsBuffer.h b/HPL2/include/graphics/GraphicsBuffer.h index ee48553d2..2b554506a 100644 --- a/HPL2/include/graphics/GraphicsBuffer.h +++ b/HPL2/include/graphics/GraphicsBuffer.h @@ -1,7 +1,5 @@ #pragma once -#include "Common_3/Graphics/Interfaces/IGraphics.h" -#include "graphics/GraphicsTypes.h" #include "math/MathTypes.h" #include "math/MeshTypes.h" #include "physics/PhysicsTypes.h" @@ -14,6 +12,10 @@ #include #include +#include "graphics/GraphicsTypes.h" +#include "graphics/Enum.h" + +#include "Common_3/Graphics/Interfaces/IGraphics.h" #include "Common_3/Graphics/Interfaces/IGraphics.h" #include "Common_3/Resources/ResourceLoader/Interfaces/IResourceLoader.h" #include "Common_3/Utilities/Math/MathTypes.h" @@ -28,7 +30,6 @@ namespace hpl { } } - class GraphicsBuffer final { public: enum BufferType { @@ -37,12 +38,9 @@ namespace hpl { }; struct MappedBufferDesc { uint64_t m_size; - uint64_t m_dstOffset; void* m_mappedData; }; - enum class IndexType : uint8_t { Uint16, Uint32 }; - GraphicsBuffer() {} explicit GraphicsBuffer(const MappedBufferDesc& desc); explicit GraphicsBuffer(const GraphicsBuffer&); @@ -58,7 +56,6 @@ namespace hpl { BufferRawView(GraphicsBuffer* asset, uint32_t byteOffset) : m_asset(asset), m_byteOffset(byteOffset) { - ASSERT(m_byteOffset <= m_asset->Data().size()); } BufferRawView(const BufferRawView& view): m_asset(view.m_asset), @@ -73,22 +70,47 @@ namespace hpl { * When Writing a raw to a buffer the buffer will resize to accomidate */ void WriteRaw(uint32_t byteOffset, std::span data) { - details::testAndResize(m_asset->m_buffer, m_byteOffset + byteOffset + data.size()); - std::copy(data.begin(), data.end(), m_asset->m_buffer.begin() + m_byteOffset + byteOffset); + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: { + details::testAndResize(m_asset->m_buffer, m_byteOffset + byteOffset + data.size()); + std::copy(data.begin(), data.end(), m_asset->m_buffer.begin() + m_byteOffset + byteOffset); + break; + } + case BufferType::MappedBuffer: { + ASSERT(m_asset->m_mapped.m_size == 0 || m_byteOffset + byteOffset + data.size() < m_asset->m_mapped.m_size); + std::copy(data.begin(), data.end(), reinterpret_cast(m_asset->m_mapped.m_mappedData) + m_byteOffset + byteOffset); + break; + } + } } template void WriteRawType(uint32_t byteOffset, const T& data) { std::span raw(reinterpret_cast(&data), sizeof(T)); - details::testAndResize(m_asset->m_buffer, m_byteOffset + byteOffset + raw.size()); - std::copy(raw.begin(), raw.end(), m_asset->m_buffer.begin() + m_byteOffset + byteOffset); + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: + details::testAndResize(m_asset->m_buffer, m_byteOffset + byteOffset + raw.size()); + std::copy(raw.begin(), raw.end(), m_asset->m_buffer.begin() + m_byteOffset + byteOffset); + break; + case BufferType::MappedBuffer: + std::copy(raw.begin(), raw.end(), reinterpret_cast(m_asset->m_mapped.m_mappedData) + m_byteOffset + byteOffset); + break; + } } template void WriteRawType(uint32_t byteOffset, const std::span& data) { std::span raw(reinterpret_cast(data.data()), data.size() * sizeof(T)); - details::testAndResize(m_asset->m_buffer, m_byteOffset + byteOffset + raw.size()); - std::copy(raw.begin(), raw.end(), m_asset->m_buffer.begin() + m_byteOffset + byteOffset); + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: + details::testAndResize(m_asset->m_buffer, m_byteOffset + byteOffset + raw.size()); + std::copy(raw.begin(), raw.end(), m_asset->m_buffer.begin() + m_byteOffset + byteOffset); + break; + case BufferType::MappedBuffer: + ASSERT(m_asset->m_mapped.m_mappedData); + std::copy(raw.begin(), raw.end(), reinterpret_cast(m_asset->m_mapped.m_mappedData) + m_byteOffset + byteOffset); + break; + } } void operator=(const BufferRawView& other) { @@ -102,17 +124,44 @@ namespace hpl { } template - inline std::span RawDataView() { return std::span(reinterpret_cast(m_asset->m_buffer.data() + m_byteOffset), (m_asset->m_buffer.size() - m_byteOffset) / sizeof(T));} - inline std::span RawView() { return std::span(m_asset->m_buffer.data() + m_byteOffset, m_asset->m_buffer.size() - m_byteOffset); } - inline uint32_t NumBytes() { return (m_asset->m_buffer.size() - m_byteOffset); } + inline std::span rawSpanByType() { + ASSERT(m_asset->m_type == BufferType::ResourceBuffer); + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: + return std::span(reinterpret_cast(m_asset->m_buffer.data() + m_byteOffset), (m_asset->m_buffer.size() - m_byteOffset) / sizeof(T)); + case BufferType::MappedBuffer: { + ASSERT(m_asset->m_mapped.m_size > 0); // can't have a span over data with a unbounded buffer + return std::span(reinterpret_cast(reinterpret_cast(m_asset->m_mapped.m_mappedData) + m_byteOffset), (m_asset->m_mapped.m_size - m_byteOffset) / sizeof(T)); + } + } + } + inline std::span rawByteSpan() { + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: + return std::span(m_asset->m_buffer.data() + m_byteOffset, m_asset->m_buffer.size() - m_byteOffset); + case BufferType::MappedBuffer: + ASSERT(m_asset->m_mapped.m_size > 0); // can't have a span over data with a unbounded buffer + return std::span(reinterpret_cast(m_asset->m_mapped.m_mappedData) + m_byteOffset, m_asset->m_mapped.m_size - m_byteOffset); + } + return std::span(); + } + inline uint32_t NumBytes() { + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: + return (m_asset->m_buffer.size() - m_byteOffset); + case BufferType::MappedBuffer: + return (m_asset->m_mapped.m_size == 0) ? UINT32_MAX : m_asset->m_mapped.m_size - m_byteOffset; + } + return UINT32_MAX; + } protected: GraphicsBuffer* m_asset = nullptr; uint32_t m_byteOffset = 0; }; - struct BufferIndexView: BufferRawView { + struct BufferIndexView final: BufferRawView { public: - BufferIndexView(GraphicsBuffer* asset, uint32_t byteOffset, IndexType type) + BufferIndexView(GraphicsBuffer* asset, uint32_t byteOffset, IndexBufferType type) : BufferRawView(asset, byteOffset) , m_indexType(type) { } @@ -136,67 +185,123 @@ namespace hpl { m_indexType = other.m_indexType; } - void ResizeElements(uint32_t numElements) { - switch(m_indexType) { - case IndexType::Uint32: - m_asset->m_buffer.resize(m_byteOffset + (numElements * sizeof(uint32_t))); + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: { + switch(m_indexType) { + case IndexBufferType::Uint32: + m_asset->m_buffer.resize(m_byteOffset + (numElements * sizeof(uint32_t))); + break; + case IndexBufferType::Uint16: + m_asset->m_buffer.resize(m_byteOffset + (numElements * sizeof(uint16_t))); + break; + } break; - case IndexType::Uint16: - m_asset->m_buffer.resize(m_byteOffset + (numElements * sizeof(uint16_t))); + } + case BufferType::MappedBuffer: + ASSERT(false); // you can't resize a mapped buffer break; } } void ReserveElements(uint32_t numElements) { - switch(m_indexType) { - case IndexType::Uint32: - m_asset->m_buffer.reserve(m_byteOffset + (numElements * sizeof(uint32_t))); + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: { + switch(m_indexType) { + case IndexBufferType::Uint32: + m_asset->m_buffer.reserve(m_byteOffset + (numElements * sizeof(uint32_t))); + break; + case IndexBufferType::Uint16: + m_asset->m_buffer.reserve(m_byteOffset + (numElements * sizeof(uint16_t))); + break; + } break; - case IndexType::Uint16: - m_asset->m_buffer.reserve(m_byteOffset + (numElements * sizeof(uint16_t))); + } + case BufferType::MappedBuffer: + ASSERT(false); break; } } uint32_t Get(uint32_t index) { - switch(m_indexType) { - case IndexType::Uint32: - ASSERT(m_asset->m_buffer.begin() + (m_byteOffset + (index * sizeof(uint32_t))) < m_asset->m_buffer.end()); - return *reinterpret_cast(m_asset->m_buffer.data() + (m_byteOffset + (index * sizeof(uint32_t)))); - case IndexType::Uint16: - ASSERT(m_asset->m_buffer.begin() + (m_byteOffset + (index * sizeof(uint16_t))) < m_asset->m_buffer.end()); - return *reinterpret_cast(m_asset->m_buffer.data() + (m_byteOffset + (index * sizeof(uint16_t)))); + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: { + switch(m_indexType) { + case IndexBufferType::Uint32: + ASSERT(m_asset->m_buffer.begin() + (m_byteOffset + (index * sizeof(uint32_t))) < m_asset->m_buffer.end()); + return *reinterpret_cast(m_asset->m_buffer.data() + (m_byteOffset + (index * sizeof(uint32_t)))); + case IndexBufferType::Uint16: + ASSERT(m_asset->m_buffer.begin() + (m_byteOffset + (index * sizeof(uint16_t))) < m_asset->m_buffer.end()); + return *reinterpret_cast(m_asset->m_buffer.data() + (m_byteOffset + (index * sizeof(uint16_t)))); + } + } + case BufferType::MappedBuffer: + switch(m_indexType) { + case IndexBufferType::Uint32: + ASSERT(m_asset->m_buffer.begin() + (m_byteOffset + (index * sizeof(uint32_t))) < m_asset->m_buffer.end()); + return *reinterpret_cast(reinterpret_cast(m_asset->m_mapped.m_mappedData) + (m_byteOffset + (index * sizeof(uint32_t)))); + case IndexBufferType::Uint16: + ASSERT(m_asset->m_buffer.begin() + (m_byteOffset + (index * sizeof(uint16_t))) < m_asset->m_buffer.end()); + return *reinterpret_cast(reinterpret_cast(m_asset->m_mapped.m_mappedData) + (m_byteOffset + (index * sizeof(uint16_t)))); + } + break; } return UINT32_MAX; } void Write(uint32_t index, uint32_t value) { - switch(m_indexType) { - case IndexType::Uint32: { - uint32_t v = value; - auto buf = std::span(reinterpret_cast(&v), sizeof(uint32_t)); - const size_t targetOffset = (m_byteOffset + (index * sizeof(uint32_t))); - details::testAndResize(m_asset->m_buffer, targetOffset + buf.size()); - std::copy(buf.begin(), buf.end(), m_asset->m_buffer.begin() + targetOffset); + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: { + switch(m_indexType) { + case IndexBufferType::Uint32: { + uint32_t v = value; + auto buf = std::span(reinterpret_cast(&v), sizeof(uint32_t)); + const size_t targetOffset = (m_byteOffset + (index * sizeof(uint32_t))); + details::testAndResize(m_asset->m_buffer, targetOffset + buf.size()); + std::copy(buf.begin(), buf.end(), m_asset->m_buffer.begin() + targetOffset); + break; + } + case IndexBufferType::Uint16: { + uint16_t v = value; + auto buf = std::span(reinterpret_cast(&v), sizeof(uint16_t)); + const size_t targetOffset = (m_byteOffset + (index * sizeof(uint16_t))); + details::testAndResize(m_asset->m_buffer, targetOffset + buf.size()); + std::copy(buf.begin(), buf.end(), m_asset->m_buffer.begin() + targetOffset); + break; + } + } break; } - case IndexType::Uint16: { - uint16_t v = value; - auto buf = std::span(reinterpret_cast(&v), sizeof(uint16_t)); - const size_t targetOffset = (m_byteOffset + (index * sizeof(uint16_t))); - details::testAndResize(m_asset->m_buffer, targetOffset + buf.size()); - std::copy(buf.begin(), buf.end(), m_asset->m_buffer.begin() + targetOffset); + case BufferType::MappedBuffer: { + + switch(m_indexType) { + case IndexBufferType::Uint32: { + uint32_t v = value; + auto buf = std::span(reinterpret_cast(&v), sizeof(uint32_t)); + const size_t targetOffset = (m_byteOffset + (index * sizeof(uint32_t))); + details::testAndResize(m_asset->m_buffer, targetOffset + buf.size()); + std::copy(buf.begin(), buf.end(), reinterpret_cast(m_asset->m_mapped.m_mappedData) + targetOffset); + break; + } + case IndexBufferType::Uint16: { + uint16_t v = value; + auto buf = std::span(reinterpret_cast(&v), sizeof(uint16_t)); + const size_t targetOffset = (m_byteOffset + (index * sizeof(uint16_t))); + details::testAndResize(m_asset->m_buffer, targetOffset + buf.size()); + std::copy(buf.begin(), buf.end(), reinterpret_cast(m_asset->m_mapped.m_mappedData) + targetOffset); + break; + } + } break; } } } private: - IndexType m_indexType = IndexType::Uint32; + IndexBufferType m_indexType = IndexBufferType::Uint32; }; template - struct BufferStructuredView: BufferRawView { + struct BufferStructuredView final: BufferRawView { public: BufferStructuredView() {} @@ -232,28 +337,73 @@ namespace hpl { void Write(uint32_t index, const T& value) { auto buf = std::span(reinterpret_cast(&value), sizeof(T)); const size_t targetOffset = (m_byteOffset + (index * m_byteStride)); - details::testAndResize(m_asset->m_buffer, targetOffset + buf.size()); - std::copy(buf.begin(), buf.end(), m_asset->m_buffer.begin() + targetOffset); + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: { + details::testAndResize(m_asset->m_buffer, targetOffset + buf.size()); + std::copy(buf.begin(), buf.end(), m_asset->m_buffer.begin() + targetOffset); + break; + } + case BufferType::MappedBuffer: { + std::copy(buf.begin(), buf.end(), reinterpret_cast(m_asset->m_mapped.m_mappedData) + targetOffset); + break; + } + } } void Write(uint32_t index, const std::span values) { auto buf = std::span(reinterpret_cast(values.data()), values.size() * sizeof(T)); const size_t targetOffset = (m_byteOffset + (index * m_byteStride)); - details::testAndResize(m_asset->m_buffer, targetOffset + buf.size()); - std::copy(buf.begin(), buf.end(), m_asset->m_buffer.begin() + targetOffset); + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: { + details::testAndResize(m_asset->m_buffer, targetOffset + buf.size()); + std::copy(buf.begin(), buf.end(), m_asset->m_buffer.begin() + targetOffset); + break; + } + case BufferType::MappedBuffer: { + std::copy(buf.begin(), buf.end(), reinterpret_cast(m_asset->m_mapped.m_mappedData) + targetOffset); + break; + } + } } void ResizeElements(uint32_t numElements) { - m_asset->m_buffer.resize(m_byteOffset + (numElements * m_byteStride)); + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: { + m_asset->m_buffer.resize(m_byteOffset + (numElements * m_byteStride)); + break; + } + case BufferType::MappedBuffer: { + ASSERT(false); + break; + } + } } void ReserveElements(uint32_t numElements) { - m_asset->m_buffer.reserve(m_byteOffset + (numElements * m_byteStride)); + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: { + m_asset->m_buffer.reserve(m_byteOffset + (numElements * m_byteStride)); + break; + } + case BufferType::MappedBuffer: { + ASSERT(false); + break; + } + } } T Get(uint32_t index) { - ASSERT(m_asset->m_buffer.begin() + (m_byteOffset + (index * m_byteStride)) < m_asset->m_buffer.end()); - return *reinterpret_cast(m_asset->m_buffer.data() + (m_byteOffset + (index * m_byteStride))); + switch(m_asset->m_type) { + case BufferType::ResourceBuffer: { + ASSERT(m_asset->m_buffer.begin() + (m_byteOffset + (index * m_byteStride)) < m_asset->m_buffer.end()); + return *reinterpret_cast(m_asset->m_buffer.data() + (m_byteOffset + (index * m_byteStride))); + } + case BufferType::MappedBuffer: { + ASSERT(false); + break; + } + } + return T(); } protected: uint32_t m_byteStride; @@ -264,19 +414,16 @@ namespace hpl { return BufferStructuredView(this, byteOffset, (byteStride == 0) ? sizeof(Type) : byteStride); } - BufferIndexView CreateIndexView(uint32_t byteOffset = 0, IndexType type = IndexType::Uint32) { + BufferIndexView CreateIndexView(uint32_t byteOffset = 0, IndexBufferType type = IndexBufferType::Uint32) { return BufferIndexView(this, byteOffset, type); } BufferRawView CreateViewRaw(uint32_t byteOffset = 0) { return BufferRawView(this, byteOffset); } - - std::span Data(); private: struct { uint64_t m_size; - uint64_t m_dstOffset; void* m_mappedData; } m_mapped; std::vector m_buffer; diff --git a/HPL2/include/graphics/MeshUtility.h b/HPL2/include/graphics/MeshUtility.h index 9a10ea02b..baf040c9a 100644 --- a/HPL2/include/graphics/MeshUtility.h +++ b/HPL2/include/graphics/MeshUtility.h @@ -91,8 +91,12 @@ namespace hpl::MeshUtility { ); MeshCreateResult CreatePlane( - const std::array corners, - const std::array uvCorners, + Vector3 p1, + Vector3 p2, + Vector2 uv1, + Vector2 uv2, + Vector2 uv3, + Vector2 uv4, GraphicsBuffer::BufferIndexView* index, GraphicsBuffer::BufferStructuredView* position, GraphicsBuffer::BufferStructuredView* color, diff --git a/HPL2/include/graphics/SubMesh.h b/HPL2/include/graphics/SubMesh.h index 2b73ef2f1..f75f78e20 100644 --- a/HPL2/include/graphics/SubMesh.h +++ b/HPL2/include/graphics/SubMesh.h @@ -131,6 +131,22 @@ namespace hpl { IndexBufferInfo() { } + IndexBufferInfo (const IndexBufferInfo& other): + m_buffer(other.m_buffer), + m_numberElements(other.m_numberElements){ + } + IndexBufferInfo(IndexBufferInfo&& other): + m_buffer(std::move(other.m_buffer)), + m_numberElements(other.m_numberElements){ + } + void operator=(const IndexBufferInfo& other) { + m_buffer = other.m_buffer; + m_numberElements = other.m_numberElements; + } + void operator=(IndexBufferInfo&& other) { + m_buffer = std::move(other.m_buffer); + m_numberElements = other.m_numberElements; + } GraphicsBuffer::BufferIndexView GetView() { return m_buffer.CreateIndexView(); } @@ -180,8 +196,8 @@ namespace hpl { void AddCollider(const MeshCollisionResource& def); std::span GetColliders(); - inline std::span GetStreamBuffers() {return m_vertexStreams; } - inline IndexBufferInfo& IndexBuffer() {return m_indexStream; } + inline std::span streamBuffers() {return m_vertexStreams; } + inline IndexBufferInfo& IndexStream() {return m_indexStream; } void SetIsCollideShape(bool abX) { m_collideShape = abX; @@ -227,6 +243,7 @@ namespace hpl { return m_materialName; } + bool hasMesh(); void SetStreamBuffers(iVertexBuffer* buffer, std::vector&& vertexStreams, IndexBufferInfo&& indexStream); void Compile(); private: diff --git a/HPL2/include/resources/TextureManager.h b/HPL2/include/resources/TextureManager.h index 619da0326..063d0c9e3 100644 --- a/HPL2/include/resources/TextureManager.h +++ b/HPL2/include/resources/TextureManager.h @@ -22,10 +22,10 @@ #include #include "Common_3/Graphics/Interfaces/IGraphics.h" #include "graphics/AnimatedImage.h" -#include "graphics/Enum.h" #include "resources/ResourceManager.h" #include "graphics/Texture.h" #include +#include "graphics/Enum.h" namespace hpl { @@ -49,10 +49,9 @@ namespace hpl { struct ImageOptions { ImageOptions(): - - m_UWrap(WrapMode::None), - m_VWrap(WrapMode::None), - m_WWrap(WrapMode::None), + m_UWrap(hpl::WrapMode::None), + m_VWrap(hpl::WrapMode::None), + m_WWrap(hpl::WrapMode::None), m_minFilter(FilterType::FILTER_LINEAR), m_magFilter(FilterType::FILTER_LINEAR), m_mipFilter(FilterType::FILTER_LINEAR){ diff --git a/HPL2/include/scene/SubMeshEntity.h b/HPL2/include/scene/SubMeshEntity.h index 646d00816..f96116f65 100644 --- a/HPL2/include/scene/SubMeshEntity.h +++ b/HPL2/include/scene/SubMeshEntity.h @@ -17,12 +17,12 @@ * along with Amnesia: The Dark Descent. If not, see . */ -#ifndef HPL_SUB_MESH_ENTITY_H -#define HPL_SUB_MESH_ENTITY_H - +#pragma once +#include #include #include +#include "graphics/ForgeHandles.h" #include "math/MathTypes.h" #include "graphics/GraphicsTypes.h" #include "system/SystemTypes.h" @@ -50,7 +50,9 @@ namespace hpl { HPL_RTTI_IMPL_CLASS(iRenderable, cSubMeshEntity, "{285bbdb4-de5b-4960-bf44-ae543432ff40}") friend class cMeshEntity; public: - cSubMeshEntity(const tString &asName,cMeshEntity *apMeshEntity, cSubMesh * apSubMesh,cMaterialManager* apMaterialManager); + static constexpr uint32_t MaxVertexBindings = 15; + + cSubMeshEntity(const tString &asName,cMeshEntity *apMeshEntity, cSubMesh * apSubMesh,cMaterialManager* apMaterialManager); ~cSubMeshEntity(); virtual cMaterial *GetMaterial() override; @@ -90,6 +92,15 @@ namespace hpl { private: virtual void OnTransformUpdated() override; + struct StreamBufferInfo { + SharedBuffer m_buffer; + ShaderSemantic m_semantic; + uint64_t m_stride; + }; + uint32_t m_numberIndecies = 0; + SharedBuffer m_indexBuffer; + folly::small_vector m_vertexStreams; + cSubMesh *mpSubMesh; cMeshEntity *mpMeshEntity; @@ -115,6 +126,4 @@ namespace hpl { typedef std::multimap tSubMeshEntityMap; typedef tSubMeshEntityMap::iterator tSubMeshEntityMapIt; - }; -#endif // HPL_SUB_MESH_ENTITY_H diff --git a/HPL2/sources/graphics/Enum.cpp b/HPL2/sources/graphics/Enum.cpp index 7956670eb..d2fe3239a 100644 --- a/HPL2/sources/graphics/Enum.cpp +++ b/HPL2/sources/graphics/Enum.cpp @@ -2,4 +2,37 @@ namespace hpl { + ShaderSemantic hplToForgeShaderSemantic(eVertexBufferElement element) { + switch (element) { + case eVertexBufferElement_Normal: + return ShaderSemantic::SEMANTIC_NORMAL; + case eVertexBufferElement_Position: + return ShaderSemantic::SEMANTIC_POSITION; + case eVertexBufferElement_Color0: + return ShaderSemantic::SEMANTIC_COLOR; + case eVertexBufferElement_Color1: + return ShaderSemantic::SEMANTIC_TEXCOORD5; + case eVertexBufferElement_Texture1Tangent: + return ShaderSemantic::SEMANTIC_TANGENT; + case eVertexBufferElement_Texture0: + return ShaderSemantic::SEMANTIC_TEXCOORD0; + case eVertexBufferElement_Texture1: + return ShaderSemantic::SEMANTIC_TEXCOORD1; + case eVertexBufferElement_Texture2: + return ShaderSemantic::SEMANTIC_TEXCOORD2; + case eVertexBufferElement_Texture3: + return ShaderSemantic::SEMANTIC_TEXCOORD3; + case eVertexBufferElement_Texture4: + return ShaderSemantic::SEMANTIC_TEXCOORD4; + case eVertexBufferElement_User0: + return ShaderSemantic::SEMANTIC_TEXCOORD6; + case eVertexBufferElement_User1: + return ShaderSemantic::SEMANTIC_TEXCOORD7; + case eVertexBufferElement_User2: + return ShaderSemantic::SEMANTIC_TEXCOORD8; + case eVertexBufferElement_User3: + return ShaderSemantic::SEMANTIC_TEXCOORD9; + } + return ShaderSemantic::SEMANTIC_UNDEFINED; + } } diff --git a/HPL2/sources/graphics/GraphicsBuffer.cpp b/HPL2/sources/graphics/GraphicsBuffer.cpp index 97dc3568a..cd2d21627 100644 --- a/HPL2/sources/graphics/GraphicsBuffer.cpp +++ b/HPL2/sources/graphics/GraphicsBuffer.cpp @@ -10,7 +10,6 @@ namespace hpl { GraphicsBuffer::GraphicsBuffer(const MappedBufferDesc& desc): m_mapped({ desc.m_size, - desc.m_dstOffset, desc.m_mappedData }), m_type(BufferType::MappedBuffer){ @@ -26,10 +25,6 @@ namespace hpl { m_mapped(asset.m_mapped), m_type(asset.m_type){ } - std::span GraphicsBuffer::Data() { - return m_buffer; - } - void GraphicsBuffer::operator=(const GraphicsBuffer& other) { m_buffer = other.m_buffer; m_mapped = other.m_mapped; diff --git a/HPL2/sources/graphics/MeshUtility.cpp b/HPL2/sources/graphics/MeshUtility.cpp index b1ac2b84b..2a97cdd80 100644 --- a/HPL2/sources/graphics/MeshUtility.cpp +++ b/HPL2/sources/graphics/MeshUtility.cpp @@ -369,8 +369,12 @@ namespace hpl::MeshUtility { } MeshCreateResult CreatePlane( - const std::array corners, - const std::array uvCorners, + Vector3 p1, + Vector3 p2, + Vector2 uv1, + Vector2 uv2, + Vector2 uv3, + Vector2 uv4, GraphicsBuffer::BufferIndexView* index, GraphicsBuffer::BufferStructuredView* position, GraphicsBuffer::BufferStructuredView* color, @@ -378,7 +382,7 @@ namespace hpl::MeshUtility { GraphicsBuffer::BufferStructuredView* uv, std::variant*, GraphicsBuffer::BufferStructuredView*> tangent ) { - const Vector3 diff = corners[0] - corners[1]; + const Vector3 diff = p1 - p2; folly::small_vector vPlaneAxes; int lPlaneNormalAxis = -1; int lNumSameCoords = 0; @@ -396,11 +400,11 @@ namespace hpl::MeshUtility { LOGF(LogLevel::eERROR, "CreatePlane failed: plane corners are not coplanar"); return MeshCreateResult{0}; } - Vector3 vCenter = (corners[0] + corners[1]) * 0.5f; + Vector3 vCenter = (p1 + p2) * 0.5f; std::array vTempCoords; - vTempCoords[0] = corners[0]; - vTempCoords[1] = corners[1]; + vTempCoords[0] = p1; + vTempCoords[1] = p2; Vector3 vTest1; Vector3 vTest2; @@ -439,11 +443,17 @@ namespace hpl::MeshUtility { for (int i = 0; i < (int)vCoords.size(); ++i) { vCoords[i] -= vFirstCorner; } + std::array uvs = { + uv1, + uv2, + uv3, + uv4 + }; for (size_t i = 0; i < 4; i++) { position->Write(vertexBufIdx, v3ToF3(vCoords[i])); normal->Write(vertexBufIdx, float3(0.0f, 1.0f, 0.0f)); color->Write(vertexBufIdx, float4(1.0f, 1.0f, 1.0f, 1.0f)); - uv->Write(vertexBufIdx++, v2ToF2(uvCorners[i])); + uv->Write(vertexBufIdx++, v2ToF2(uvs[i])); } for (int i = 0; i < 3; i++) { index->Write(indexBufIndex++, i); diff --git a/HPL2/sources/graphics/RendererDeferred.cpp b/HPL2/sources/graphics/RendererDeferred.cpp index a68e0c9b6..b881e1493 100644 --- a/HPL2/sources/graphics/RendererDeferred.cpp +++ b/HPL2/sources/graphics/RendererDeferred.cpp @@ -2507,8 +2507,12 @@ namespace hpl { for (auto& illuminationItem : m_rendererList.GetRenderableItems(eRenderListType_Illumination)) { cMaterial* pMaterial = illuminationItem->GetMaterial(); - iVertexBuffer* vertexBuffer = illuminationItem->GetVertexBuffer(); - if (pMaterial == nullptr || vertexBuffer == nullptr) { + std::array targets = { + eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + }; + DrawPacket drawPacket = illuminationItem->ResolveDrawPacket(frame, targets); + if (pMaterial == nullptr || drawPacket.m_type == DrawPacket::Unknown) { continue; } ASSERT(pMaterial->Descriptor().m_id == MaterialID::SolidDiffuse && "Invalid material type"); @@ -2516,14 +2520,9 @@ namespace hpl { uint32_t instance = cmdBindMaterialAndObject(cmd, frame, pMaterial, illuminationItem); materialConst.objectId = instance; materialConst.m_sceneAlpha = illuminationItem->GetIlluminationAmount(); - std::array targets = { - eVertexBufferElement_Position, - eVertexBufferElement_Texture0, - }; - DrawPacket pkt = illuminationItem->ResolveDrawPacket(frame, targets); - DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &pkt); + DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &drawPacket); cmdBindPushConstants(cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(cmd, pkt.m_numIndices, 0, 0); + cmdDrawIndexed(cmd, drawPacket.m_numIndices, 0, 0); } } void cRendererDeferred::cmdLightPass( diff --git a/HPL2/sources/graphics/SubMesh.cpp b/HPL2/sources/graphics/SubMesh.cpp index 844fd5ba6..44e138355 100644 --- a/HPL2/sources/graphics/SubMesh.cpp +++ b/HPL2/sources/graphics/SubMesh.cpp @@ -76,7 +76,7 @@ namespace hpl { target->ResizeArray(element, elementCount * srcInfo.m_numberElements); float* destData = target->GetFloatArray(element); for(size_t idx = 0; idx < srcInfo.m_numberElements; idx++) { - auto buf = rawView.RawView(); + auto buf = rawView.rawByteSpan(); std::memcpy(destData + (elementCount * idx), buf.data() + (srcInfo.m_stride * idx), std::min(srcInfo.m_stride, static_cast(sizeof(float) * elementCount))); } } @@ -193,6 +193,9 @@ namespace hpl { } } } + bool cSubMesh::hasMesh() { + return m_vertexStreams.size() > 0 && m_indexStream.m_numberElements > 0; + } void cSubMesh::SetStreamBuffers(iVertexBuffer* buffer, std::vector&& vertexStreams, IndexBufferInfo&& indexStream) { m_vertexStreams = std::move(vertexStreams); m_indexStream = std::move(indexStream); diff --git a/HPL2/sources/impl/MeshLoaderMSH.cpp b/HPL2/sources/impl/MeshLoaderMSH.cpp index 51d59113e..43df4cdb9 100644 --- a/HPL2/sources/impl/MeshLoaderMSH.cpp +++ b/HPL2/sources/impl/MeshLoaderMSH.cpp @@ -255,7 +255,7 @@ namespace hpl { streamBuffer.m_numberElements = lVtxNum; GraphicsBuffer::BufferRawView rawView = streamBuffer.m_buffer.CreateViewRaw(); std::array stage; - std::span floatSpan = rawView.RawDataView(); + std::span floatSpan = rawView.rawSpanByType(); for(size_t vtxIdx = 0; vtxIdx < lVtxNum; vtxIdx++) { for(size_t eleIdx = 0; eleIdx < lElementNum; eleIdx++) { stage[eleIdx] = binBuff.GetFloat32(); diff --git a/HPL2/sources/resources/WorldLoaderHplMap.cpp b/HPL2/sources/resources/WorldLoaderHplMap.cpp index 7d72107e7..03c3896a3 100644 --- a/HPL2/sources/resources/WorldLoaderHplMap.cpp +++ b/HPL2/sources/resources/WorldLoaderHplMap.cpp @@ -19,7 +19,9 @@ #include "resources/WorldLoaderHplMap.h" +#include "Common_3/Graphics/Interfaces/IGraphics.h" #include "Common_3/Utilities/Log/Log.h" +#include "engine/RTTI.h" #include "graphics/GraphicsBuffer.h" #include "graphics/Image.h" #include "graphics/MeshUtility.h" @@ -70,8 +72,7 @@ #include "Common_3/Utilities/Interfaces/ILog.h" #include - - +#include @@ -553,7 +554,7 @@ namespace hpl { streamBuffer.m_numberElements = lElementNum; GraphicsBuffer::BufferRawView rawView = streamBuffer.m_buffer.CreateViewRaw(); std::array stage; - std::span floatSpan = rawView.RawDataView(); + std::span floatSpan = rawView.rawSpanByType(); for(size_t vtxIdx = 0; vtxIdx < lVtxNum; vtxIdx++) { for(size_t eleIdx = 0; eleIdx < lElementNum; eleIdx++) { switch(lCompressionType) { @@ -1240,7 +1241,7 @@ namespace hpl { void cWorldLoaderHplMap::CombineObjectsAndCreateMeshEntity(tRenderableVec &avObjects, int alFirstIdx, int alLastIdx) { - if(gbLog) Log(" Combining objects %d -> %d\n", alFirstIdx, alLastIdx); + LOGF_IF(LogLevel::eDEBUG, gbLog," Combining objects %d -> %d\n", alFirstIdx, alLastIdx); /////////////////////////////////////////// //Iterate objects to get the total amount of vertex data @@ -1250,18 +1251,26 @@ namespace hpl { for(int i=alFirstIdx; i<=alLastIdx; ++i) { //Check if the sub mesh is visible, else skip - cHplMapStaticUserData*pUserData = (cHplMapStaticUserData*)static_cast(avObjects[i])->GetUserData(); - if(pUserData->mbVisible==false) continue; - - //Check add the vertex num and index num from vertex buffer - iVertexBuffer *pVtxBuffer = avObjects[i]->GetVertexBuffer(); + ASSERT(TypeInfo::IsSubtype(*avObjects[i])); + cSubMeshEntity* subMeshEntity = static_cast(avObjects[i]); + cHplMapStaticUserData* pUserData = reinterpret_cast(subMeshEntity->GetUserData()); + if(pUserData->mbVisible == false) { + continue; + } + cSubMesh* mesh = subMeshEntity->GetSubMesh(); + auto streams = mesh->streamBuffers(); + auto& indexStream = mesh->IndexStream(); + auto streamPos = std::find_if(streams.begin(), streams.end(), [&](auto& stream) { + return stream.m_semantic == ShaderSemantic::SEMANTIC_POSITION; + }); + ASSERT(streamPos != streams.end()); - lTotalVtxAmount += pVtxBuffer->GetVertexNum(); - lTotalIdxAmount += pVtxBuffer->GetIndexNum(); + lTotalIdxAmount += indexStream.m_numberElements; + lTotalVtxAmount += streamPos->m_numberElements; - if(gbLog) Log(" '%s' has %d vtx and %d idx\n",avObjects[i]->GetName().c_str(),pVtxBuffer->GetVertexNum(),pVtxBuffer->GetIndexNum()); + LOGF_IF(LogLevel::eDEBUG, gbLog," '%s' has %d vtx and %d idx",avObjects[i]->GetName().c_str(),lTotalVtxAmount,lTotalIdxAmount); } - if(gbLog) Log(" Total amount %d vtx and %d idx\n",lTotalVtxAmount, lTotalIdxAmount); + LOGF_IF(LogLevel::eDEBUG, gbLog," Total amount %d vtx and %d idx",lTotalVtxAmount, lTotalIdxAmount); /////////////////////////////////////////// //If no vertices, return and skip creation @@ -1275,99 +1284,105 @@ namespace hpl { /////////////////////////////////////////// //Create the vertex buffer (skipping color!) - iVertexBuffer *pVtxBuffer = mpGraphics->GetLowLevel()->CreateVertexBuffer(eVertexBufferType_Hardware, eVertexBufferDrawType_Tri, - eVertexBufferUsageType_Static,lTotalVtxAmount, lTotalIdxAmount); - - //Set up what data arrays to use - struct VertexDataTable { - eVertexBufferElement mType; - int mlElementNum; - const hpl::LegacyVertexBuffer::VertexElement* m_targetElement; - size_t offset; - } lDataArrayTypes[5] = { - {eVertexBufferElement_Position, 4, nullptr, 0}, - {eVertexBufferElement_Normal, 3, nullptr, 0}, - {eVertexBufferElement_Color0, 4, nullptr, 0}, - {eVertexBufferElement_Texture0, 3, nullptr, 0}, - {eVertexBufferElement_Texture1Tangent, 4, nullptr, 0} - }; - //Set up the data arrays - for(int i=0;i< std::size(lDataArrayTypes); ++i) - { - pVtxBuffer->CreateElementArray(lDataArrayTypes[i].mType,eVertexBufferElementFormat_Float, lDataArrayTypes[i].mlElementNum); - pVtxBuffer->ResizeArray(lDataArrayTypes[i].mType, lTotalVtxAmount * lDataArrayTypes[i].mlElementNum); - lDataArrayTypes[i].m_targetElement = static_cast(pVtxBuffer)->GetElement(lDataArrayTypes[i].mType); - ASSERT(lDataArrayTypes[i].m_targetElement != nullptr && "Element not found"); - } - - //Set up and get indices - pVtxBuffer->ResizeIndices(lTotalIdxAmount); - unsigned int* pIndexArray = pVtxBuffer->GetIndices(); - - /////////////////////////////////////////// - //Fill vertex buffer with data - int lIdxOffset =0; - for(int vtxbuffer = alFirstIdx; vtxbuffer <= alLastIdx; ++vtxbuffer) - { - //Check if the sub mesh is visible, else skip - cHplMapStaticUserData*pUserData = (cHplMapStaticUserData*)static_cast(avObjects[vtxbuffer])->GetUserData(); - if(pUserData->mbVisible==false) continue; - - iRenderable *pObject = avObjects[vtxbuffer]; - - if(gbLog) Log(" Copying data from '%s'\n", pObject->GetName().c_str()); - - ///////////////////////////////////// - // Create a copy of the vertex buffer and transform it according to object - iVertexBuffer *pSubVtxBuffer = pObject->GetVertexBuffer(); - auto* pTransformedVtxBuffer = static_cast(pSubVtxBuffer->CreateCopy( eVertexBufferType_Software, eVertexBufferUsageType_Static, - pSubVtxBuffer->GetVertexElementFlags())); - pTransformedVtxBuffer->Transform(pObject->GetWorldMatrix()); - ////////////////////////////////////////////////// - //Copy to each data array and increase the data pointer - for(int i=0; i< std::size(lDataArrayTypes);++i) - { - auto* sourceElement = pTransformedVtxBuffer->GetElement(lDataArrayTypes[i].mType); - auto& targetElement = lDataArrayTypes[i].m_targetElement; - ASSERT(targetElement != nullptr && "lDataArrayTypes[i].m_data != nullptr"); - ASSERT(sourceElement != nullptr && "sourceElement != nullptr"); - ASSERT(targetElement->m_type == sourceElement->m_type && "lDataArrayTypes[i].m_data->m_type == sourceElement->m_type"); - ASSERT(targetElement->m_num == sourceElement->m_num && "lDataArrayTypes[i].m_targetElement->m_num == sourceElement->m_num"); - - auto targetElementStart = &(targetElement->Data().data()[lDataArrayTypes[i].offset]); - std::copy(sourceElement->Data().begin(), sourceElement->Data().end(), targetElementStart); - lDataArrayTypes[i].offset += sourceElement->Data().size(); - } - - ////////////////////////////////////////////// - //Copy to index array (using offset from previous max) and increase index pointer and offset - unsigned int* pTransIdxArray = pTransformedVtxBuffer->GetIndices(); - for(int i=0; iGetIndexNum(); ++i) - { - pIndexArray[i] = pTransIdxArray[i] + lIdxOffset; - } - - lIdxOffset += pTransformedVtxBuffer->GetVertexNum(); - pIndexArray += pTransformedVtxBuffer->GetIndexNum(); - - hplDelete(pTransformedVtxBuffer); - } + cSubMesh::IndexBufferInfo indexInfo; + cSubMesh::StreamBufferInfo positionInfo; + cSubMesh::StreamBufferInfo tangentInfo; + cSubMesh::StreamBufferInfo colorInfo; + cSubMesh::StreamBufferInfo normalInfo; + cSubMesh::StreamBufferInfo textureInfo; + cSubMesh::StreamBufferInfo::InitializeBuffer(&positionInfo); + cSubMesh::StreamBufferInfo::InitializeBuffer(&colorInfo); + cSubMesh::StreamBufferInfo::InitializeBuffer(&normalInfo); + cSubMesh::StreamBufferInfo::InitializeBuffer(&textureInfo); + cSubMesh::StreamBufferInfo::InitializeBuffer(&tangentInfo); + + cSubMesh::StreamBufferInfo* vertexLayouts[] = { + &positionInfo, + &tangentInfo, + &normalInfo, + &colorInfo, + &textureInfo + }; + + uint32_t vertexIdx = 0; + uint32_t indexIdx = 0; + for(int subMeshIdx = alFirstIdx; subMeshIdx <= alLastIdx; ++subMeshIdx) { + ASSERT(TypeInfo::IsSubtype(*avObjects[subMeshIdx])); + cSubMeshEntity* subMeshEntity = static_cast(avObjects[subMeshIdx]); + cHplMapStaticUserData* pUserData = reinterpret_cast(subMeshEntity->GetUserData()); + if(pUserData->mbVisible == false) { + continue; + } + cSubMesh* mesh = subMeshEntity->GetSubMesh(); - /////////////////////// - // All meshes batched into one buffer, compile it. - pVtxBuffer->Compile(0); + std::span vertexstreams = mesh->streamBuffers(); + cSubMesh::IndexBufferInfo& indexStream = mesh->IndexStream(); + uint32_t minimumElements = std::accumulate(vertexstreams.begin(), vertexstreams.end(), static_cast(UINT32_MAX), [](uint32_t size, auto& stream) { + if(stream.m_numberElements == 0) { + return size; + } + return std::min(size, stream.m_numberElements); + }); - /////////////////////////////////////////// - //Create the mesh - iRenderable *pFirstObject = avObjects[alFirstIdx]; + for(auto& stream: vertexstreams) { + if(stream.m_numberElements == 0) { + continue; + } + auto foundLayout = std::find_if(std::begin(vertexLayouts), std::end(vertexLayouts), [&](auto& entry) { + return entry->m_semantic == stream.m_semantic; + }); + uint32_t localIdx = vertexIdx; + if(foundLayout != std::end(vertexLayouts)) { + auto src = stream.m_buffer.CreateViewRaw(); + auto dest = (*foundLayout)->m_buffer.CreateViewRaw(); + auto srcRawSpan = src.rawByteSpan(); + for(size_t eleIdx = 0; eleIdx < minimumElements; eleIdx++) { + auto buf = std::span(srcRawSpan.begin() + (eleIdx * stream.m_stride), std::min(stream.m_stride, (*foundLayout)->m_stride)); + dest.WriteRaw((localIdx * (*foundLayout)->m_stride), buf); + localIdx++; + } + } + } + { + auto position = positionInfo.GetStructuredView((vertexIdx * positionInfo.m_stride)); + auto normal = normalInfo.GetStructuredView((vertexIdx * normalInfo.m_stride)); + auto tangent = tangentInfo.GetStructuredView((vertexIdx * tangentInfo.m_stride)); + MeshUtility::Transform(minimumElements, cMath::ToForgeMatrix4(subMeshEntity->GetWorldMatrix()), &position, &normal, &tangent); + } + + { + auto srcIndexView = indexStream.GetView(); + auto destIndexView = indexInfo.GetView(); + for(size_t i = 0; i < indexStream.m_numberElements; i++) { + destIndexView.Write(indexIdx++, srcIndexView.Get(i) + vertexIdx); + } + } + vertexIdx += minimumElements; + } + positionInfo.m_numberElements = vertexIdx; + tangentInfo.m_numberElements = vertexIdx; + colorInfo.m_numberElements = vertexIdx; + normalInfo.m_numberElements = vertexIdx; + textureInfo.m_numberElements = vertexIdx; + indexInfo.m_numberElements = indexIdx; + + iRenderable *pFirstObject = avObjects[alFirstIdx]; cSubMeshEntity *pFirstSubEnt = static_cast(pFirstObject); cMesh *pMesh = hplNew( cMesh, (sName, _W("") ,mpResources->GetMaterialManager(),mpResources->GetAnimationManager()) ); cSubMesh *pSubMesh = pMesh->CreateSubMesh("SubMesh"); - //Set the vertex buffer - pSubMesh->SetVertexBuffer(pVtxBuffer); + std::vector vertexStreams; + vertexStreams.push_back(std::move(positionInfo)); + vertexStreams.push_back(std::move(tangentInfo)); + vertexStreams.push_back(std::move(colorInfo)); + vertexStreams.push_back(std::move(normalInfo)); + vertexStreams.push_back(std::move(textureInfo)); + iVertexBuffer *pVtxBuffer = mpGraphics->GetLowLevel()->CreateVertexBuffer(eVertexBufferType_Hardware, eVertexBufferDrawType_Tri, + eVertexBufferUsageType_Static,0, 0); + pSubMesh->SetStreamBuffers(pVtxBuffer, + std::move(vertexStreams), std::move(indexInfo)); //Set material cMaterial *pMaterial = pFirstObject->GetMaterial(); @@ -1866,8 +1881,12 @@ namespace hpl { } MeshUtility::MeshCreateResult result = MeshUtility::CreatePlane( - {cMath::ToForgeVec3(vStartCorner), cMath::ToForgeVec3(vEndCorner)}, - vUVCorners, + cMath::ToForgeVec3(vStartCorner), + cMath::ToForgeVec3(vEndCorner), + vUVCorners[0], + vUVCorners[1], + vUVCorners[2], + vUVCorners[3], &index, &position, &color, diff --git a/HPL2/sources/scene/SubMeshEntity.cpp b/HPL2/sources/scene/SubMeshEntity.cpp index 25e433a24..e154f4216 100644 --- a/HPL2/sources/scene/SubMeshEntity.cpp +++ b/HPL2/sources/scene/SubMeshEntity.cpp @@ -17,29 +17,37 @@ * along with Amnesia: The Dark Descent. If not, see . */ -#include "scene/SubMeshEntity.h" +#include "Common_3/Graphics/Interfaces/IGraphics.h" +#include "Common_3/Resources/ResourceLoader/Interfaces/IResourceLoader.h" +#include "FixPreprocessor.h" -#include "impl/LegacyVertexBuffer.h" -#include "scene/MeshEntity.h" -#include "resources/MaterialManager.h" -#include "resources/MeshManager.h" #include "graphics/VertexBuffer.h" #include "graphics/Material.h" #include "graphics/Mesh.h" #include "graphics/SubMesh.h" - #include "graphics/Animation.h" #include "graphics/AnimationTrack.h" #include "graphics/Skeleton.h" #include "graphics/Bone.h" +#include "graphics/DrawPacket.h" +#include "graphics/Enum.h" +#include "graphics/ForgeHandles.h" +#include "impl/LegacyVertexBuffer.h" #include "scene/AnimationState.h" #include "scene/NodeState.h" +#include "scene/MeshEntity.h" +#include "scene/SubMeshEntity.h" + +#include "resources/MaterialManager.h" +#include "resources/MeshManager.h" #include "physics/PhysicsBody.h" #include "math/Math.h" +#include + namespace hpl { cSubMeshEntity::cSubMeshEntity(const tString &asName, cMeshEntity *apMeshEntity, cSubMesh * apSubMesh, @@ -60,6 +68,40 @@ namespace hpl { mpDynVtxBuffer = mpSubMesh->GetVertexBuffer()->CreateCopy(eVertexBufferType_Hardware,eVertexBufferUsageType_Dynamic,eFlagBit_All); } + //if(mpSubMesh->hasMesh()) { + for(auto& stream: mpSubMesh->streamBuffers()) { + auto rawView = stream.m_buffer.CreateViewRaw(); + StreamBufferInfo& info = m_vertexStreams.emplace_back(); + info.m_buffer.Load([&](Buffer** buffer) { + BufferLoadDesc loadDesc = {}; + loadDesc.ppBuffer = buffer; + loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; + loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_ONLY; + loadDesc.mDesc.mSize = rawView.NumBytes(); + loadDesc.pData = rawView.rawByteSpan().data(); + addResource(&loadDesc, nullptr); + return true; + }); + info.m_stride = stream.m_stride; + info.m_semantic = stream.m_semantic; + } + { + auto& info = mpSubMesh->IndexStream(); + auto rawView = info.m_buffer.CreateViewRaw(); + m_indexBuffer.Load([&](Buffer** buffer) { + BufferLoadDesc loadDesc = {}; + loadDesc.ppBuffer = buffer; + loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_INDEX_BUFFER; + loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_ONLY; + loadDesc.mDesc.mSize = rawView.NumBytes(); + loadDesc.pData = rawView.rawByteSpan().data(); + addResource(&loadDesc, nullptr); + return true; + }); + m_numberIndecies = info.m_numberElements; + } + //} + mpLocalNode = NULL; mbUpdateBody = false; @@ -221,11 +263,33 @@ namespace hpl { DrawPacket cSubMeshEntity::ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) { - if(mpDynVtxBuffer) + DrawPacket packet; + packet.m_type = DrawPacket::Unknown; + if(mpDynVtxBuffer) { return static_cast(mpDynVtxBuffer)->resolveGeometryBinding(frame.m_currentFrame, elements); } - return static_cast(mpSubMesh->GetVertexBuffer())->resolveGeometryBinding(frame.m_currentFrame, elements); + if(m_numberIndecies == 0) { + return packet; + } + + packet.m_type = DrawPacket::IndvidualBindings; + packet.m_indvidual.m_numStreams = 0; + for(auto& ele: elements) { + ShaderSemantic semantic = hplToForgeShaderSemantic(ele); + auto found = std::find_if(m_vertexStreams.begin(), m_vertexStreams.end(), [&](auto& stream) { + return stream.m_semantic == semantic; + }); + ASSERT(found != m_vertexStreams.end()); + auto& stream = packet.m_indvidual.m_vertexStream[packet.m_indvidual.m_numStreams++]; + stream.m_buffer = &found->m_buffer; + stream.m_offset = 0; + stream.m_stride = found->m_stride; + } + packet.m_indvidual.m_indexStream.m_offset = 0; + packet.m_indvidual.m_indexStream.buffer = &m_indexBuffer; + packet.m_numIndices = m_numberIndecies; + return packet; } iVertexBuffer* cSubMeshEntity::GetVertexBuffer() { diff --git a/tools/editors/common/EntityWrapperPrimitivePlane.cpp b/tools/editors/common/EntityWrapperPrimitivePlane.cpp index 588857785..ade128d39 100644 --- a/tools/editors/common/EntityWrapperPrimitivePlane.cpp +++ b/tools/editors/common/EntityWrapperPrimitivePlane.cpp @@ -498,8 +498,8 @@ cMesh* cEntityWrapperPrimitivePlane::CreatePrimitiveMesh() MeshUtility::MeshCreateResult result; MeshUtility::CreatePlane( - {Vector3(0,0,0), cMath::ToForgeVec3(vEndCorner)}, - {Vector2(1,0), Vector2(0,0), Vector2(0,1), Vector2(1,1)}, + Vector3(0,0,0), cMath::ToForgeVec3(vEndCorner), + Vector2(1,0), Vector2(0,0), Vector2(0,1), Vector2(1,1), &index, &position, &color, From 491292fc60e6d4acca557fae37aafa707a010a78 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Tue, 24 Oct 2023 21:38:41 -0700 Subject: [PATCH 04/17] feat: tweak vertex stage logic Signed-off-by: Michael Pollind --- HPL2/include/graphics/GraphicsBuffer.h | 1 + HPL2/include/graphics/SubMesh.h | 10 + HPL2/include/graphics/offsetAllocator.h | 95 ++++ HPL2/include/scene/SubMeshEntity.h | 54 ++- HPL2/sources/graphics/GraphicsBuffer.cpp | 7 + HPL2/sources/graphics/RenderList.cpp | 17 - HPL2/sources/graphics/SubMesh.cpp | 18 + HPL2/sources/graphics/offsetAllocator.cpp | 486 +++++++++++++++++++ HPL2/sources/impl/MeshLoaderCollada.cpp | 2 +- HPL2/sources/impl/MeshLoaderMSH.cpp | 38 +- HPL2/sources/resources/WorldLoaderHplMap.cpp | 3 - HPL2/sources/scene/SubMeshEntity.cpp | 382 +++++++-------- README.md | 1 + 13 files changed, 867 insertions(+), 247 deletions(-) create mode 100644 HPL2/include/graphics/offsetAllocator.h create mode 100644 HPL2/sources/graphics/offsetAllocator.cpp diff --git a/HPL2/include/graphics/GraphicsBuffer.h b/HPL2/include/graphics/GraphicsBuffer.h index 2b554506a..fd4516e22 100644 --- a/HPL2/include/graphics/GraphicsBuffer.h +++ b/HPL2/include/graphics/GraphicsBuffer.h @@ -42,6 +42,7 @@ namespace hpl { }; GraphicsBuffer() {} + explicit GraphicsBuffer(const BufferUpdateDesc& desc); explicit GraphicsBuffer(const MappedBufferDesc& desc); explicit GraphicsBuffer(const GraphicsBuffer&); explicit GraphicsBuffer(GraphicsBuffer&&); diff --git a/HPL2/include/graphics/SubMesh.h b/HPL2/include/graphics/SubMesh.h index f75f78e20..59414afde 100644 --- a/HPL2/include/graphics/SubMesh.h +++ b/HPL2/include/graphics/SubMesh.h @@ -19,6 +19,8 @@ #pragma once +#include "Common_3/Graphics/Interfaces/IGraphics.h" +#include "graphics/ForgeHandles.h" #include "graphics/GraphicsBuffer.h" #include "graphics/GraphicsTypes.h" #include "math/MathTypes.h" @@ -80,12 +82,14 @@ namespace hpl { } StreamBufferInfo(const StreamBufferInfo& other): + m_gpuBuffer(other.m_gpuBuffer), m_buffer(other.m_buffer), m_semantic(other.m_semantic), m_stride(other.m_stride), m_numberElements(other.m_numberElements){ } StreamBufferInfo(StreamBufferInfo&& other): + m_gpuBuffer(std::move(other.m_gpuBuffer)), m_buffer(std::move(other.m_buffer)), m_semantic(other.m_semantic), m_stride(other.m_stride), @@ -93,12 +97,14 @@ namespace hpl { } void operator=(const StreamBufferInfo& other) { + m_gpuBuffer = other.m_gpuBuffer; m_buffer = other.m_buffer; m_semantic = other.m_semantic; m_stride = other.m_stride; m_numberElements = other.m_numberElements; } void operator=(StreamBufferInfo&& other) { + m_gpuBuffer = std::move(other.m_gpuBuffer); m_buffer = std::move(other.m_buffer); m_semantic = other.m_semantic; m_stride = other.m_stride; @@ -119,7 +125,9 @@ namespace hpl { constexpr GraphicsBuffer::BufferStructuredView GetStructuredView(uint32_t byteOffset = 0) { return m_buffer.CreateStructuredView(byteOffset, m_stride); } + SharedBuffer CommitBuffer(); + SharedBuffer m_gpuBuffer; GraphicsBuffer m_buffer; uint32_t m_stride = 0; uint32_t m_numberElements = 0; @@ -246,6 +254,8 @@ namespace hpl { bool hasMesh(); void SetStreamBuffers(iVertexBuffer* buffer, std::vector&& vertexStreams, IndexBufferInfo&& indexStream); void Compile(); + + void CommitBuffer(ShaderSemantic semantic); private: cMaterialManager* m_materialManager = nullptr; tString m_name; diff --git a/HPL2/include/graphics/offsetAllocator.h b/HPL2/include/graphics/offsetAllocator.h new file mode 100644 index 000000000..155e21dd9 --- /dev/null +++ b/HPL2/include/graphics/offsetAllocator.h @@ -0,0 +1,95 @@ +// (C) Sebastian Aaltonen 2023 +// MIT License (see file: LICENSE) + +//#define USE_16_BIT_OFFSETS + +namespace OffsetAllocator +{ + typedef unsigned char uint8; + typedef unsigned short uint16; + typedef unsigned int uint32; + + // 16 bit offsets mode will halve the metadata storage cost + // But it only supports up to 65536 maximum allocation count +#ifdef USE_16_BIT_NODE_INDICES + typedef uint16 NodeIndex; +#else + typedef uint32 NodeIndex; +#endif + + static constexpr uint32 NUM_TOP_BINS = 32; + static constexpr uint32 BINS_PER_LEAF = 8; + static constexpr uint32 TOP_BINS_INDEX_SHIFT = 3; + static constexpr uint32 LEAF_BINS_INDEX_MASK = 0x7; + static constexpr uint32 NUM_LEAF_BINS = NUM_TOP_BINS * BINS_PER_LEAF; + + struct Allocation + { + static constexpr uint32 NO_SPACE = 0xffffffff; + + uint32 offset = NO_SPACE; + NodeIndex metadata = NO_SPACE; // internal: node index + }; + + struct StorageReport + { + uint32 totalFreeSpace; + uint32 largestFreeRegion; + }; + + struct StorageReportFull + { + struct Region + { + uint32 size; + uint32 count; + }; + + Region freeRegions[NUM_LEAF_BINS]; + }; + + class Allocator + { + public: + Allocator(uint32 size, uint32 maxAllocs = 128 * 1024); + Allocator(Allocator &&other); + ~Allocator(); + void reset(); + + Allocation allocate(uint32 size); + void free(Allocation allocation); + + uint32 allocationSize(Allocation allocation) const; + StorageReport storageReport() const; + StorageReportFull storageReportFull() const; + + private: + uint32 insertNodeIntoBin(uint32 size, uint32 dataOffset); + void removeNodeFromBin(uint32 nodeIndex); + + struct Node + { + static constexpr NodeIndex unused = 0xffffffff; + + uint32 dataOffset = 0; + uint32 dataSize = 0; + NodeIndex binListPrev = unused; + NodeIndex binListNext = unused; + NodeIndex neighborPrev = unused; + NodeIndex neighborNext = unused; + bool used = false; // TODO: Merge as bit flag + }; + + uint32 m_size; + uint32 m_maxAllocs; + uint32 m_freeStorage; + + uint32 m_usedBinsTop; + uint8 m_usedBins[NUM_TOP_BINS]; + NodeIndex m_binIndices[NUM_LEAF_BINS]; + + Node* m_nodes; + NodeIndex* m_freeNodes; + uint32 m_freeOffset; + }; +} diff --git a/HPL2/include/scene/SubMeshEntity.h b/HPL2/include/scene/SubMeshEntity.h index f96116f65..ca328e2b3 100644 --- a/HPL2/include/scene/SubMeshEntity.h +++ b/HPL2/include/scene/SubMeshEntity.h @@ -22,6 +22,7 @@ #include #include +#include "Common_3/Graphics/Interfaces/IGraphics.h" #include "graphics/ForgeHandles.h" #include "math/MathTypes.h" #include "graphics/GraphicsTypes.h" @@ -92,32 +93,63 @@ namespace hpl { private: virtual void OnTransformUpdated() override; + enum StreamBufferType { + StaticBuffer, + DynamicBuffer + }; + struct StreamBufferInfo { + public: + StreamBufferType m_type = StreamBufferType::StaticBuffer; SharedBuffer m_buffer; - ShaderSemantic m_semantic; - uint64_t m_stride; + ShaderSemantic m_semantic = ShaderSemantic::SEMANTIC_UNDEFINED; + uint64_t m_stride = 0; + uint32_t m_numberElements = 0; + StreamBufferInfo() {} + StreamBufferInfo(const StreamBufferInfo& info) = delete; + StreamBufferInfo(StreamBufferInfo&& info): + m_type(info.m_type), + m_buffer(std::move(info.m_buffer)), + m_semantic(info.m_semantic), + m_stride(info.m_stride), + m_numberElements(info.m_numberElements) { + } + void operator=(const StreamBufferInfo& info) = delete; + void operator=(StreamBufferInfo&& info) { + m_type = info.m_type; + m_buffer = std::move(info.m_buffer); + m_semantic = info.m_semantic; + m_stride = info.m_stride; + m_numberElements = info.m_numberElements; + } + }; + uint8_t m_activeCopy = 0; uint32_t m_numberIndecies = 0; SharedBuffer m_indexBuffer; folly::small_vector m_vertexStreams; - cSubMesh *mpSubMesh; - cMeshEntity *mpMeshEntity; + cSubMesh *mpSubMesh= nullptr; + cMeshEntity *mpMeshEntity= nullptr; - cMaterial *mpMaterial; + cMaterial *mpMaterial= nullptr; - cNode3D *mpLocalNode; + cNode3D *mpLocalNode = nullptr; - cMaterialManager* mpMaterialManager; + cMaterialManager* mpMaterialManager= nullptr; iVertexBuffer* mpDynVtxBuffer = nullptr; tTriangleDataVec mvDynTriangles; - bool mbUpdateBody; - - bool mbGraphicsUpdated; + bool mbUpdateBody = false; + bool mbGraphicsUpdated = false; + bool m_skinnedMesh = false; - char mlStaticNullMatrixCount; + //This is used to see if null should be returned. + // 0 = no check made, test if matrix is identity + // -1 = Matrix was not identity + // 1 = matrix was identiy + char mlStaticNullMatrixCount = 0; void *mpUserData; }; diff --git a/HPL2/sources/graphics/GraphicsBuffer.cpp b/HPL2/sources/graphics/GraphicsBuffer.cpp index cd2d21627..e37720504 100644 --- a/HPL2/sources/graphics/GraphicsBuffer.cpp +++ b/HPL2/sources/graphics/GraphicsBuffer.cpp @@ -15,6 +15,13 @@ namespace hpl { m_type(BufferType::MappedBuffer){ } + GraphicsBuffer::GraphicsBuffer(const BufferUpdateDesc& desc): + m_mapped({ + desc.mSize, + desc.pMappedData + }), + m_type(BufferType::MappedBuffer){ + } GraphicsBuffer::GraphicsBuffer(const GraphicsBuffer& asset): m_buffer(asset.m_buffer), m_mapped(asset.m_mapped), diff --git a/HPL2/sources/graphics/RenderList.cpp b/HPL2/sources/graphics/RenderList.cpp index c1ae2cff1..1b057a282 100644 --- a/HPL2/sources/graphics/RenderList.cpp +++ b/HPL2/sources/graphics/RenderList.cpp @@ -69,12 +69,6 @@ namespace hpl { cMaterial* pMatA = apObjectA->GetMaterial(); cMaterial* pMatB = apObjectB->GetMaterial(); - ////////////////////////// - // Vertex buffer - if (apObjectA->GetVertexBuffer() != apObjectB->GetVertexBuffer()) { - return apObjectA->GetVertexBuffer() < apObjectB->GetVertexBuffer(); - } - ////////////////////////// // Matrix if (apObjectA->GetModelMatrixPtr() != apObjectB->GetModelMatrixPtr()) { @@ -108,12 +102,6 @@ namespace hpl { return pMatA->GetImage(eMaterialTexture_Illumination) < pMatB->GetImage(eMaterialTexture_Illumination); } - ////////////////////////// - // Vertex buffer - if (apObjectA->GetVertexBuffer() != apObjectB->GetVertexBuffer()) { - return apObjectA->GetVertexBuffer() < apObjectB->GetVertexBuffer(); - } - ////////////////////////// // Matrix if (apObjectA->GetModelMatrixPtr() != apObjectB->GetModelMatrixPtr()) { @@ -135,11 +123,6 @@ namespace hpl { return pMatA->GetImage(eMaterialTexture_Illumination) < pMatB->GetImage(eMaterialTexture_Illumination); } - ////////////////////////// - // Vertex buffer - if (apObjectA->GetVertexBuffer() != apObjectB->GetVertexBuffer()) { - return apObjectA->GetVertexBuffer() < apObjectB->GetVertexBuffer(); - } ////////////////////////// // Matrix diff --git a/HPL2/sources/graphics/SubMesh.cpp b/HPL2/sources/graphics/SubMesh.cpp index 44e138355..031347428 100644 --- a/HPL2/sources/graphics/SubMesh.cpp +++ b/HPL2/sources/graphics/SubMesh.cpp @@ -268,6 +268,24 @@ namespace hpl { return NULL; } + // not an ideal solution + SharedBuffer cSubMesh::StreamBufferInfo::CommitBuffer() { + if(!m_gpuBuffer.IsValid()) { + auto rawView = m_buffer.CreateViewRaw(); + m_gpuBuffer.Load([&](Buffer** buffer) { + BufferLoadDesc loadDesc = {}; + loadDesc.ppBuffer = buffer; + loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; + loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_ONLY; + loadDesc.mDesc.mSize = rawView.NumBytes(); + loadDesc.pData = rawView.rawByteSpan().data(); + addResource(&loadDesc, nullptr); + return true; + }); + } + return m_gpuBuffer; + } + iCollideShape* cSubMesh::CreateCollideShape(iPhysicsWorld* apWorld, std::span colliders) { if (colliders.empty()) { return nullptr; diff --git a/HPL2/sources/graphics/offsetAllocator.cpp b/HPL2/sources/graphics/offsetAllocator.cpp new file mode 100644 index 000000000..1f547f50c --- /dev/null +++ b/HPL2/sources/graphics/offsetAllocator.cpp @@ -0,0 +1,486 @@ +// (C) Sebastian Aaltonen 2023 +// MIT License (see file: LICENSE) + +#include "graphics/offsetAllocator.h" + +#ifdef DEBUG +#include +#define ASSERT(x) assert(x) +//#define DEBUG_VERBOSE +#else +#define ASSERT(x) +#endif + +#ifdef DEBUG_VERBOSE +#include +#endif + +#ifdef _MSC_VER +#include +#endif + +#include + +namespace OffsetAllocator +{ + inline uint32 lzcnt_nonzero(uint32 v) + { +#ifdef _MSC_VER + unsigned long retVal; + _BitScanReverse(&retVal, v); + return 31 - retVal; +#else + return __builtin_clz(v); +#endif + } + + inline uint32 tzcnt_nonzero(uint32 v) + { +#ifdef _MSC_VER + unsigned long retVal; + _BitScanForward(&retVal, v); + return retVal; +#else + return __builtin_ctz(v); +#endif + } + + namespace SmallFloat + { + static constexpr uint32 MANTISSA_BITS = 3; + static constexpr uint32 MANTISSA_VALUE = 1 << MANTISSA_BITS; + static constexpr uint32 MANTISSA_MASK = MANTISSA_VALUE - 1; + + // Bin sizes follow floating point (exponent + mantissa) distribution (piecewise linear log approx) + // This ensures that for each size class, the average overhead percentage stays the same + uint32 uintToFloatRoundUp(uint32 size) + { + uint32 exp = 0; + uint32 mantissa = 0; + + if (size < MANTISSA_VALUE) + { + // Denorm: 0..(MANTISSA_VALUE-1) + mantissa = size; + } + else + { + // Normalized: Hidden high bit always 1. Not stored. Just like float. + uint32 leadingZeros = lzcnt_nonzero(size); + uint32 highestSetBit = 31 - leadingZeros; + + uint32 mantissaStartBit = highestSetBit - MANTISSA_BITS; + exp = mantissaStartBit + 1; + mantissa = (size >> mantissaStartBit) & MANTISSA_MASK; + + uint32 lowBitsMask = (1 << mantissaStartBit) - 1; + + // Round up! + if ((size & lowBitsMask) != 0) + mantissa++; + } + + return (exp << MANTISSA_BITS) + mantissa; // + allows mantissa->exp overflow for round up + } + + uint32 uintToFloatRoundDown(uint32 size) + { + uint32 exp = 0; + uint32 mantissa = 0; + + if (size < MANTISSA_VALUE) + { + // Denorm: 0..(MANTISSA_VALUE-1) + mantissa = size; + } + else + { + // Normalized: Hidden high bit always 1. Not stored. Just like float. + uint32 leadingZeros = lzcnt_nonzero(size); + uint32 highestSetBit = 31 - leadingZeros; + + uint32 mantissaStartBit = highestSetBit - MANTISSA_BITS; + exp = mantissaStartBit + 1; + mantissa = (size >> mantissaStartBit) & MANTISSA_MASK; + } + + return (exp << MANTISSA_BITS) | mantissa; + } + + uint32 floatToUint(uint32 floatValue) + { + uint32 exponent = floatValue >> MANTISSA_BITS; + uint32 mantissa = floatValue & MANTISSA_MASK; + if (exponent == 0) + { + // Denorms + return mantissa; + } + else + { + return (mantissa | MANTISSA_VALUE) << (exponent - 1); + } + } + } + + // Utility functions + uint32 findLowestSetBitAfter(uint32 bitMask, uint32 startBitIndex) + { + uint32 maskBeforeStartIndex = (1 << startBitIndex) - 1; + uint32 maskAfterStartIndex = ~maskBeforeStartIndex; + uint32 bitsAfter = bitMask & maskAfterStartIndex; + if (bitsAfter == 0) return Allocation::NO_SPACE; + return tzcnt_nonzero(bitsAfter); + } + + // Allocator... + Allocator::Allocator(uint32 size, uint32 maxAllocs) : + m_size(size), + m_maxAllocs(maxAllocs), + m_nodes(nullptr), + m_freeNodes(nullptr) + { + if (sizeof(NodeIndex) == 2) + { + ASSERT(maxAllocs <= 65536); + } + reset(); + } + + Allocator::Allocator(Allocator &&other) : + m_size(other.m_size), + m_maxAllocs(other.m_maxAllocs), + m_freeStorage(other.m_freeStorage), + m_usedBinsTop(other.m_usedBinsTop), + m_nodes(other.m_nodes), + m_freeNodes(other.m_freeNodes), + m_freeOffset(other.m_freeOffset) + { + memcpy(m_usedBins, other.m_usedBins, sizeof(uint8) * NUM_TOP_BINS); + memcpy(m_binIndices, other.m_binIndices, sizeof(NodeIndex) * NUM_LEAF_BINS); + + other.m_nodes = nullptr; + other.m_freeNodes = nullptr; + other.m_freeOffset = 0; + other.m_maxAllocs = 0; + other.m_usedBinsTop = 0; + } + + void Allocator::reset() + { + m_freeStorage = 0; + m_usedBinsTop = 0; + m_freeOffset = m_maxAllocs - 1; + + for (uint32 i = 0 ; i < NUM_TOP_BINS; i++) + m_usedBins[i] = 0; + + for (uint32 i = 0 ; i < NUM_LEAF_BINS; i++) + m_binIndices[i] = Node::unused; + + if (m_nodes) delete[] m_nodes; + if (m_freeNodes) delete[] m_freeNodes; + + m_nodes = new Node[m_maxAllocs]; + m_freeNodes = new NodeIndex[m_maxAllocs]; + + // Freelist is a stack. Nodes in inverse order so that [0] pops first. + for (uint32 i = 0; i < m_maxAllocs; i++) + { + m_freeNodes[i] = m_maxAllocs - i - 1; + } + + // Start state: Whole storage as one big node + // Algorithm will split remainders and push them back as smaller nodes + insertNodeIntoBin(m_size, 0); + } + + Allocator::~Allocator() + { + delete[] m_nodes; + delete[] m_freeNodes; + } + + Allocation Allocator::allocate(uint32 size) + { + // Out of allocations? + if (m_freeOffset == 0) + { + return {.offset = Allocation::NO_SPACE, .metadata = Allocation::NO_SPACE}; + } + + // Round up to bin index to ensure that alloc >= bin + // Gives us min bin index that fits the size + uint32 minBinIndex = SmallFloat::uintToFloatRoundUp(size); + + uint32 minTopBinIndex = minBinIndex >> TOP_BINS_INDEX_SHIFT; + uint32 minLeafBinIndex = minBinIndex & LEAF_BINS_INDEX_MASK; + + uint32 topBinIndex = minTopBinIndex; + uint32 leafBinIndex = Allocation::NO_SPACE; + + // If top bin exists, scan its leaf bin. This can fail (NO_SPACE). + if (m_usedBinsTop & (1 << topBinIndex)) + { + leafBinIndex = findLowestSetBitAfter(m_usedBins[topBinIndex], minLeafBinIndex); + } + + // If we didn't find space in top bin, we search top bin from +1 + if (leafBinIndex == Allocation::NO_SPACE) + { + topBinIndex = findLowestSetBitAfter(m_usedBinsTop, minTopBinIndex + 1); + + // Out of space? + if (topBinIndex == Allocation::NO_SPACE) + { + return {.offset = Allocation::NO_SPACE, .metadata = Allocation::NO_SPACE}; + } + + // All leaf bins here fit the alloc, since the top bin was rounded up. Start leaf search from bit 0. + // NOTE: This search can't fail since at least one leaf bit was set because the top bit was set. + leafBinIndex = tzcnt_nonzero(m_usedBins[topBinIndex]); + } + + uint32 binIndex = (topBinIndex << TOP_BINS_INDEX_SHIFT) | leafBinIndex; + + // Pop the top node of the bin. Bin top = node.next. + uint32 nodeIndex = m_binIndices[binIndex]; + Node& node = m_nodes[nodeIndex]; + uint32 nodeTotalSize = node.dataSize; + node.dataSize = size; + node.used = true; + m_binIndices[binIndex] = node.binListNext; + if (node.binListNext != Node::unused) m_nodes[node.binListNext].binListPrev = Node::unused; + m_freeStorage -= nodeTotalSize; +#ifdef DEBUG_VERBOSE + printf("Free storage: %u (-%u) (allocate)\n", m_freeStorage, nodeTotalSize); +#endif + + // Bin empty? + if (m_binIndices[binIndex] == Node::unused) + { + // Remove a leaf bin mask bit + m_usedBins[topBinIndex] &= ~(1 << leafBinIndex); + + // All leaf bins empty? + if (m_usedBins[topBinIndex] == 0) + { + // Remove a top bin mask bit + m_usedBinsTop &= ~(1 << topBinIndex); + } + } + + // Push back reminder N elements to a lower bin + uint32 reminderSize = nodeTotalSize - size; + if (reminderSize > 0) + { + uint32 newNodeIndex = insertNodeIntoBin(reminderSize, node.dataOffset + size); + + // Link nodes next to each other so that we can merge them later if both are free + // And update the old next neighbor to point to the new node (in middle) + if (node.neighborNext != Node::unused) m_nodes[node.neighborNext].neighborPrev = newNodeIndex; + m_nodes[newNodeIndex].neighborPrev = nodeIndex; + m_nodes[newNodeIndex].neighborNext = node.neighborNext; + node.neighborNext = newNodeIndex; + } + + return {.offset = node.dataOffset, .metadata = nodeIndex}; + } + + void Allocator::free(Allocation allocation) + { + ASSERT(allocation.metadata != Allocation::NO_SPACE); + if (!m_nodes) return; + + uint32 nodeIndex = allocation.metadata; + Node& node = m_nodes[nodeIndex]; + + // Double delete check + ASSERT(node.used == true); + + // Merge with neighbors... + uint32 offset = node.dataOffset; + uint32 size = node.dataSize; + + if ((node.neighborPrev != Node::unused) && (m_nodes[node.neighborPrev].used == false)) + { + // Previous (contiguous) free node: Change offset to previous node offset. Sum sizes + Node& prevNode = m_nodes[node.neighborPrev]; + offset = prevNode.dataOffset; + size += prevNode.dataSize; + + // Remove node from the bin linked list and put it in the freelist + removeNodeFromBin(node.neighborPrev); + + ASSERT(prevNode.neighborNext == nodeIndex); + node.neighborPrev = prevNode.neighborPrev; + } + + if ((node.neighborNext != Node::unused) && (m_nodes[node.neighborNext].used == false)) + { + // Next (contiguous) free node: Offset remains the same. Sum sizes. + Node& nextNode = m_nodes[node.neighborNext]; + size += nextNode.dataSize; + + // Remove node from the bin linked list and put it in the freelist + removeNodeFromBin(node.neighborNext); + + ASSERT(nextNode.neighborPrev == nodeIndex); + node.neighborNext = nextNode.neighborNext; + } + + uint32 neighborNext = node.neighborNext; + uint32 neighborPrev = node.neighborPrev; + + // Insert the removed node to freelist +#ifdef DEBUG_VERBOSE + printf("Putting node %u into freelist[%u] (free)\n", nodeIndex, m_freeOffset + 1); +#endif + m_freeNodes[++m_freeOffset] = nodeIndex; + + // Insert the (combined) free node to bin + uint32 combinedNodeIndex = insertNodeIntoBin(size, offset); + + // Connect neighbors with the new combined node + if (neighborNext != Node::unused) + { + m_nodes[combinedNodeIndex].neighborNext = neighborNext; + m_nodes[neighborNext].neighborPrev = combinedNodeIndex; + } + if (neighborPrev != Node::unused) + { + m_nodes[combinedNodeIndex].neighborPrev = neighborPrev; + m_nodes[neighborPrev].neighborNext = combinedNodeIndex; + } + } + + uint32 Allocator::insertNodeIntoBin(uint32 size, uint32 dataOffset) + { + // Round down to bin index to ensure that bin >= alloc + uint32 binIndex = SmallFloat::uintToFloatRoundDown(size); + + uint32 topBinIndex = binIndex >> TOP_BINS_INDEX_SHIFT; + uint32 leafBinIndex = binIndex & LEAF_BINS_INDEX_MASK; + + // Bin was empty before? + if (m_binIndices[binIndex] == Node::unused) + { + // Set bin mask bits + m_usedBins[topBinIndex] |= 1 << leafBinIndex; + m_usedBinsTop |= 1 << topBinIndex; + } + + // Take a freelist node and insert on top of the bin linked list (next = old top) + uint32 topNodeIndex = m_binIndices[binIndex]; + uint32 nodeIndex = m_freeNodes[m_freeOffset--]; +#ifdef DEBUG_VERBOSE + printf("Getting node %u from freelist[%u]\n", nodeIndex, m_freeOffset + 1); +#endif + m_nodes[nodeIndex] = {.dataOffset = dataOffset, .dataSize = size, .binListNext = topNodeIndex}; + if (topNodeIndex != Node::unused) m_nodes[topNodeIndex].binListPrev = nodeIndex; + m_binIndices[binIndex] = nodeIndex; + + m_freeStorage += size; +#ifdef DEBUG_VERBOSE + printf("Free storage: %u (+%u) (insertNodeIntoBin)\n", m_freeStorage, size); +#endif + + return nodeIndex; + } + + void Allocator::removeNodeFromBin(uint32 nodeIndex) + { + Node &node = m_nodes[nodeIndex]; + + if (node.binListPrev != Node::unused) + { + // Easy case: We have previous node. Just remove this node from the middle of the list. + m_nodes[node.binListPrev].binListNext = node.binListNext; + if (node.binListNext != Node::unused) m_nodes[node.binListNext].binListPrev = node.binListPrev; + } + else + { + // Hard case: We are the first node in a bin. Find the bin. + + // Round down to bin index to ensure that bin >= alloc + uint32 binIndex = SmallFloat::uintToFloatRoundDown(node.dataSize); + + uint32 topBinIndex = binIndex >> TOP_BINS_INDEX_SHIFT; + uint32 leafBinIndex = binIndex & LEAF_BINS_INDEX_MASK; + + m_binIndices[binIndex] = node.binListNext; + if (node.binListNext != Node::unused) m_nodes[node.binListNext].binListPrev = Node::unused; + + // Bin empty? + if (m_binIndices[binIndex] == Node::unused) + { + // Remove a leaf bin mask bit + m_usedBins[topBinIndex] &= ~(1 << leafBinIndex); + + // All leaf bins empty? + if (m_usedBins[topBinIndex] == 0) + { + // Remove a top bin mask bit + m_usedBinsTop &= ~(1 << topBinIndex); + } + } + } + + // Insert the node to freelist +#ifdef DEBUG_VERBOSE + printf("Putting node %u into freelist[%u] (removeNodeFromBin)\n", nodeIndex, m_freeOffset + 1); +#endif + m_freeNodes[++m_freeOffset] = nodeIndex; + + m_freeStorage -= node.dataSize; +#ifdef DEBUG_VERBOSE + printf("Free storage: %u (-%u) (removeNodeFromBin)\n", m_freeStorage, node.dataSize); +#endif + } + + uint32 Allocator::allocationSize(Allocation allocation) const + { + if (allocation.metadata == Allocation::NO_SPACE) return 0; + if (!m_nodes) return 0; + + return m_nodes[allocation.metadata].dataSize; + } + + StorageReport Allocator::storageReport() const + { + uint32 largestFreeRegion = 0; + uint32 freeStorage = 0; + + // Out of allocations? -> Zero free space + if (m_freeOffset > 0) + { + freeStorage = m_freeStorage; + if (m_usedBinsTop) + { + uint32 topBinIndex = 31 - lzcnt_nonzero(m_usedBinsTop); + uint32 leafBinIndex = 31 - lzcnt_nonzero(m_usedBins[topBinIndex]); + largestFreeRegion = SmallFloat::floatToUint((topBinIndex << TOP_BINS_INDEX_SHIFT) | leafBinIndex); + ASSERT(freeStorage >= largestFreeRegion); + } + } + + return {.totalFreeSpace = freeStorage, .largestFreeRegion = largestFreeRegion}; + } + + StorageReportFull Allocator::storageReportFull() const + { + StorageReportFull report; + for (uint32 i = 0; i < NUM_LEAF_BINS; i++) + { + uint32 count = 0; + uint32 nodeIndex = m_binIndices[i]; + while (nodeIndex != Node::unused) + { + nodeIndex = m_nodes[nodeIndex].binListNext; + count++; + } + report.freeRegions[i] = { .size = SmallFloat::floatToUint(i), .count = count }; + } + return report; + } +} diff --git a/HPL2/sources/impl/MeshLoaderCollada.cpp b/HPL2/sources/impl/MeshLoaderCollada.cpp index 9701cda76..dae359273 100644 --- a/HPL2/sources/impl/MeshLoaderCollada.cpp +++ b/HPL2/sources/impl/MeshLoaderCollada.cpp @@ -523,7 +523,7 @@ namespace hpl { indexView.Write(j, Geom.mvIndexVec[idx]); } - // hpl::MeshUtility::MikktSpaceGenerate( + // MeshUtility::MikkTSpaceGenerate( // Geom.mvVertexVec.size(), // Geom.mvIndexVec.size(), // &indexView, diff --git a/HPL2/sources/impl/MeshLoaderMSH.cpp b/HPL2/sources/impl/MeshLoaderMSH.cpp index 43df4cdb9..8bb0a0412 100644 --- a/HPL2/sources/impl/MeshLoaderMSH.cpp +++ b/HPL2/sources/impl/MeshLoaderMSH.cpp @@ -280,25 +280,25 @@ namespace hpl { indexView.Write(i, binBuff.GetInt32()); } } -// TODO: later view these changes -// { -// auto positionInfo = std::find_if(vertexStreams.begin(), vertexStreams.end(), [&](auto& str) { return str.m_semantic == ShaderSemantic::SEMANTIC_POSITION;}) ; -// auto tangentInfo = std::find_if(vertexStreams.begin(), vertexStreams.end(), [&](auto& str) { return str.m_semantic == ShaderSemantic::SEMANTIC_TANGENT;}) ; -// auto normalInfo = std::find_if(vertexStreams.begin(), vertexStreams.end(), [&](auto& str) { return str.m_semantic == ShaderSemantic::SEMANTIC_NORMAL;}) ; -// auto textureInfo = std::find_if(vertexStreams.begin(), vertexStreams.end(), [&](auto& str) { return str.m_semantic == ShaderSemantic::SEMANTIC_TEXCOORD0;}) ; -// auto position = positionInfo->GetStructuredView(); -// auto normal = normalInfo->GetStructuredView(); -// auto uv = textureInfo->GetStructuredView(); -// auto tangent = tangentInfo->GetStructuredView(); -// hpl::MeshUtility::MikktSpaceGenerate( -// positionInfo->m_numberElements, -// indexInfo.m_numberElements, -// &indexView, -// &position, -// &uv, -// &normal, -// &tangent); -// } + // TODO: later view these changes + // { + // auto positionInfo = std::find_if(vertexStreams.begin(), vertexStreams.end(), [&](auto& str) { return str.m_semantic == ShaderSemantic::SEMANTIC_POSITION;}) ; + // auto tangentInfo = std::find_if(vertexStreams.begin(), vertexStreams.end(), [&](auto& str) { return str.m_semantic == ShaderSemantic::SEMANTIC_TANGENT;}) ; + // auto normalInfo = std::find_if(vertexStreams.begin(), vertexStreams.end(), [&](auto& str) { return str.m_semantic == ShaderSemantic::SEMANTIC_NORMAL;}) ; + // auto textureInfo = std::find_if(vertexStreams.begin(), vertexStreams.end(), [&](auto& str) { return str.m_semantic == ShaderSemantic::SEMANTIC_TEXCOORD0;}) ; + // auto position = positionInfo->GetStructuredView(); + // auto normal = normalInfo->GetStructuredView(); + // auto uv = textureInfo->GetStructuredView(); + // auto tangent = tangentInfo->GetStructuredView(); + // hpl::MeshUtility::MikkTSpaceGenerate( + // positionInfo->m_numberElements, + // indexInfo.m_numberElements, + // &indexView, + // &position, + // &uv, + // &normal, + // &tangent); + // } iVertexBuffer* pVtxBuff = mpLowLevelGraphics->CreateVertexBuffer( eVertexBufferType_Hardware, eVertexBufferDrawType_Tri, diff --git a/HPL2/sources/resources/WorldLoaderHplMap.cpp b/HPL2/sources/resources/WorldLoaderHplMap.cpp index 03c3896a3..8ae5f64f2 100644 --- a/HPL2/sources/resources/WorldLoaderHplMap.cpp +++ b/HPL2/sources/resources/WorldLoaderHplMap.cpp @@ -620,9 +620,6 @@ namespace hpl { void cWorldLoaderHplMap::SaveCacheFile(const tWString& asFile) { -#if (defined(__PPC__) || defined(__ppc__)) - return; -#endif if(mbLoadedCache) return; //No need to save if cache was loaded! if(cResources::GetForceCacheLoadingAndSkipSaving()) return; diff --git a/HPL2/sources/scene/SubMeshEntity.cpp b/HPL2/sources/scene/SubMeshEntity.cpp index e154f4216..e5150e9cb 100644 --- a/HPL2/sources/scene/SubMeshEntity.cpp +++ b/HPL2/sources/scene/SubMeshEntity.cpp @@ -22,6 +22,8 @@ #include "FixPreprocessor.h" +#include "graphics/ForgeRenderer.h" +#include "graphics/GraphicsBuffer.h" #include "graphics/VertexBuffer.h" #include "graphics/Material.h" #include "graphics/Mesh.h" @@ -35,6 +37,7 @@ #include "graphics/ForgeHandles.h" #include "impl/LegacyVertexBuffer.h" +#include "math/MathTypes.h" #include "scene/AnimationState.h" #include "scene/NodeState.h" #include "scene/MeshEntity.h" @@ -47,216 +50,205 @@ #include "math/Math.h" #include - +#include namespace hpl { - cSubMeshEntity::cSubMeshEntity(const tString &asName, cMeshEntity *apMeshEntity, cSubMesh * apSubMesh, - cMaterialManager* apMaterialManager) : iRenderable(asName) - { - mpMeshEntity = apMeshEntity; - mpSubMesh = apSubMesh; - - mbIsOneSided = mpSubMesh->GetIsOneSided(); - mvOneSidedNormal = mpSubMesh->GetOneSidedNormal(); - - mpMaterialManager = apMaterialManager; - - mbGraphicsUpdated = false; - - if(mpMeshEntity->GetMesh()->GetSkeleton()) - { - mpDynVtxBuffer = mpSubMesh->GetVertexBuffer()->CreateCopy(eVertexBufferType_Hardware,eVertexBufferUsageType_Dynamic,eFlagBit_All); - } - - //if(mpSubMesh->hasMesh()) { - for(auto& stream: mpSubMesh->streamBuffers()) { - auto rawView = stream.m_buffer.CreateViewRaw(); - StreamBufferInfo& info = m_vertexStreams.emplace_back(); - info.m_buffer.Load([&](Buffer** buffer) { - BufferLoadDesc loadDesc = {}; - loadDesc.ppBuffer = buffer; - loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; - loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_ONLY; - loadDesc.mDesc.mSize = rawView.NumBytes(); - loadDesc.pData = rawView.rawByteSpan().data(); - addResource(&loadDesc, nullptr); - return true; - }); - info.m_stride = stream.m_stride; - info.m_semantic = stream.m_semantic; + cSubMeshEntity::cSubMeshEntity( + const tString& asName, cMeshEntity* apMeshEntity, cSubMesh* apSubMesh, cMaterialManager* apMaterialManager) + : iRenderable(asName) + , mpMeshEntity(apMeshEntity) + , mpSubMesh(apSubMesh) + , mpMaterialManager(apMaterialManager) { + mbIsOneSided = mpSubMesh->GetIsOneSided(); + mvOneSidedNormal = mpSubMesh->GetOneSidedNormal(); + if (mpMeshEntity->GetMesh()->GetSkeleton()) { + mpDynVtxBuffer = + mpSubMesh->GetVertexBuffer()->CreateCopy(eVertexBufferType_Hardware, eVertexBufferUsageType_Dynamic, eFlagBit_All); + } + + m_skinnedMesh = mpMeshEntity->GetMesh()->GetSkeleton(); + for (auto& stream : mpSubMesh->streamBuffers()) { + auto rawView = stream.m_buffer.CreateViewRaw(); + StreamBufferInfo& info = m_vertexStreams.emplace_back(); + info.m_stride = stream.m_stride; + info.m_semantic = stream.m_semantic; + info.m_numberElements = stream.m_numberElements; + if(m_skinnedMesh + && (stream.m_semantic == ShaderSemantic::SEMANTIC_POSITION || + stream.m_semantic == ShaderSemantic::SEMANTIC_TANGENT || + stream.m_semantic == ShaderSemantic::SEMANTIC_NORMAL + )) { + info.m_type = StreamBufferType::DynamicBuffer; + info.m_buffer.Load([&](Buffer** buffer) { + BufferLoadDesc loadDesc = {}; + loadDesc.ppBuffer = buffer; + loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; + loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; + loadDesc.mDesc.mSize = rawView.NumBytes() * ForgeRenderer::SwapChainLength; // will have a copy per frame + loadDesc.pData = rawView.rawByteSpan().data(); + addResource(&loadDesc, nullptr); + return true; + }); + } else { + info.m_type = StreamBufferType::StaticBuffer; + info.m_buffer = stream.CommitBuffer(); + // info.m_buffer.Load([&](Buffer** buffer) { + // BufferLoadDesc loadDesc = {}; + // loadDesc.ppBuffer = buffer; + // loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; + // loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_ONLY; + // loadDesc.mDesc.mSize = rawView.NumBytes(); + // loadDesc.pData = rawView.rawByteSpan().data(); + // addResource(&loadDesc, nullptr); + // return true; + // }); } - { - auto& info = mpSubMesh->IndexStream(); - auto rawView = info.m_buffer.CreateViewRaw(); - m_indexBuffer.Load([&](Buffer** buffer) { - BufferLoadDesc loadDesc = {}; - loadDesc.ppBuffer = buffer; - loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_INDEX_BUFFER; - loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_ONLY; - loadDesc.mDesc.mSize = rawView.NumBytes(); - loadDesc.pData = rawView.rawByteSpan().data(); - addResource(&loadDesc, nullptr); - return true; - }); - m_numberIndecies = info.m_numberElements; - } - //} - - mpLocalNode = NULL; - - mbUpdateBody = false; - - mpMaterial = NULL; - - mpUserData = NULL; - - //This is used to see if null should be returned. - // 0 = no check made, test if matrix is identity - // -1 = Matrix was not identity - // 1 = matrix was identiy - mlStaticNullMatrixCount =0; - } - - cSubMeshEntity::~cSubMeshEntity() - { - if(mpDynVtxBuffer) hplDelete(mpDynVtxBuffer); - - /* Clear any custom textures here*/ - if(mpMaterial) mpMaterialManager->Destroy(mpMaterial); - } - - void cSubMeshEntity::UpdateLogic(float afTimeStep) - { - - } - - - cMaterial* cSubMeshEntity::GetMaterial() - { - if(mpMaterial==NULL && mpSubMesh->GetMaterial()==NULL) - { - //Error("Materials for sub entity %s are NULL!\n",GetName().c_str()); - } - - if(mpMaterial) - return mpMaterial; - else - return mpSubMesh->GetMaterial(); - } - - //----------------------------------------------------------------------- - - // Set Src as private variable to give this a little boost! Or? - static inline void MatrixFloatTransformSet(float *pDest, const cMatrixf &a_mtxA, const float* pSrc, const float fWeight) - { - pDest[0] = ( a_mtxA.m[0][0] * pSrc[0] + a_mtxA.m[0][1] * pSrc[1] + a_mtxA.m[0][2] * pSrc[2] + a_mtxA.m[0][3] ) * fWeight; - pDest[1] = ( a_mtxA.m[1][0] * pSrc[0] + a_mtxA.m[1][1] * pSrc[1] + a_mtxA.m[1][2] * pSrc[2] + a_mtxA.m[1][3] ) * fWeight; - pDest[2] = ( a_mtxA.m[2][0] * pSrc[0] + a_mtxA.m[2][1] * pSrc[1] + a_mtxA.m[2][2] * pSrc[2] + a_mtxA.m[2][3] ) * fWeight; - } - - static inline void MatrixFloatRotateSet(float *pDest, const cMatrixf &a_mtxA, const float* pSrc, const float fWeight) - { - pDest[0] = ( a_mtxA.m[0][0] * pSrc[0] + a_mtxA.m[0][1] * pSrc[1] + a_mtxA.m[0][2] * pSrc[2] ) * fWeight; - pDest[1] = ( a_mtxA.m[1][0] * pSrc[0] + a_mtxA.m[1][1] * pSrc[1] + a_mtxA.m[1][2] * pSrc[2] ) * fWeight; - pDest[2] = ( a_mtxA.m[2][0] * pSrc[0] + a_mtxA.m[2][1] * pSrc[1] + a_mtxA.m[2][2] * pSrc[2] ) * fWeight; - } - - //----------------------------------------------------------------------- - - // Set Src as private variable to give this a little boost!Or? - static inline void MatrixFloatTransformAdd(float *pDest, const cMatrixf &a_mtxA, const float* pSrc, const float fWeight) - { - pDest[0] += ( a_mtxA.m[0][0] * pSrc[0] + a_mtxA.m[0][1] * pSrc[1] + a_mtxA.m[0][2] * pSrc[2] + a_mtxA.m[0][3] ) * fWeight; - pDest[1] += ( a_mtxA.m[1][0] * pSrc[0] + a_mtxA.m[1][1] * pSrc[1] + a_mtxA.m[1][2] * pSrc[2] + a_mtxA.m[1][3] ) * fWeight; - pDest[2] += ( a_mtxA.m[2][0] * pSrc[0] + a_mtxA.m[2][1] * pSrc[1] + a_mtxA.m[2][2] * pSrc[2] + a_mtxA.m[2][3] ) * fWeight; - } - - static inline void MatrixFloatRotateAdd(float *pDest, const cMatrixf &a_mtxA, const float* pSrc, const float fWeight) - { - pDest[0] += ( a_mtxA.m[0][0] * pSrc[0] + a_mtxA.m[0][1] * pSrc[1] + a_mtxA.m[0][2] * pSrc[2] ) * fWeight; - pDest[1] += ( a_mtxA.m[1][0] * pSrc[0] + a_mtxA.m[1][1] * pSrc[1] + a_mtxA.m[1][2] * pSrc[2] ) * fWeight; - pDest[2] += ( a_mtxA.m[2][0] * pSrc[0] + a_mtxA.m[2][1] * pSrc[1] + a_mtxA.m[2][2] * pSrc[2] ) * fWeight; - } - - //----------------------------------------------------------------------- - - void cSubMeshEntity::UpdateGraphicsForFrame(float afFrameTime) - { - //////////////////////////////////// - //Update things in parent first. - mpMeshEntity->UpdateGraphicsForFrame(afFrameTime); - - //////////////////////////////////// - // If it has dynamic mesh, update it. - if(mpDynVtxBuffer) - { - if(mpMeshEntity->mbSkeletonPhysicsSleeping && mbGraphicsUpdated) - { - return; - } - - mbGraphicsUpdated = true; - - const float *pBindPos = mpSubMesh->GetVertexBuffer()->GetFloatArray(eVertexBufferElement_Position); - const float *pBindNormal = mpSubMesh->GetVertexBuffer()->GetFloatArray(eVertexBufferElement_Normal); - const float *pBindTangent = mpSubMesh->GetVertexBuffer()->GetFloatArray(eVertexBufferElement_Texture1Tangent); + } + { + auto& info = mpSubMesh->IndexStream(); + auto rawView = info.m_buffer.CreateViewRaw(); + m_indexBuffer.Load([&](Buffer** buffer) { + BufferLoadDesc loadDesc = {}; + loadDesc.ppBuffer = buffer; + loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_INDEX_BUFFER; + loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_ONLY; + loadDesc.mDesc.mSize = rawView.NumBytes(); + loadDesc.pData = rawView.rawByteSpan().data(); + addResource(&loadDesc, nullptr); + return true; + }); + m_numberIndecies = info.m_numberElements; + } + } - float *pSkinPos = mpDynVtxBuffer->GetFloatArray(eVertexBufferElement_Position); - float *pSkinNormal = mpDynVtxBuffer->GetFloatArray(eVertexBufferElement_Normal); - float *pSkinTangent = mpDynVtxBuffer->GetFloatArray(eVertexBufferElement_Texture1Tangent); + cSubMeshEntity::~cSubMeshEntity() { + if (mpDynVtxBuffer) + hplDelete(mpDynVtxBuffer); - const int lVtxStride = mpDynVtxBuffer->GetElementNum(eVertexBufferElement_Position); - const int lVtxNum = mpDynVtxBuffer->GetVertexNum(); + /* Clear any custom textures here*/ + if (mpMaterial) + mpMaterialManager->Destroy(mpMaterial); + } - for(int vtx=0; vtx < lVtxNum; vtx++) - { - //To count the bone bindings - int lCount = 0; - //Get pointer to weights and bone index. - if(mpSubMesh->m_vertexWeights.size() == 0) { - continue; - } - const float *pWeight = &mpSubMesh->m_vertexWeights[vtx*4]; - const unsigned char *pBoneIdx = &mpSubMesh->m_vertexBones[vtx*4]; + void cSubMeshEntity::UpdateLogic(float afTimeStep) { + } - const cMatrixf &mtxTransform = mpMeshEntity->mvBoneMatrices[*pBoneIdx]; + cMaterial* cSubMeshEntity::GetMaterial() { + if (mpMaterial == NULL && mpSubMesh->GetMaterial() == NULL) { + // Error("Materials for sub entity %s are NULL!\n",GetName().c_str()); + } + if (mpMaterial) + return mpMaterial; + else + return mpSubMesh->GetMaterial(); + } - MatrixFloatTransformSet(pSkinPos,mtxTransform, pBindPos, *pWeight); + static inline float3 WeightTransform(const cMatrixf& a_mtxA, float3 src, float weight) { - MatrixFloatRotateSet(pSkinNormal,mtxTransform, pBindNormal, *pWeight); + return float3((a_mtxA.m[0][0] * src[0] + a_mtxA.m[0][1] * src[1] + a_mtxA.m[0][2] * src[2] + a_mtxA.m[0][3]) * weight, + (a_mtxA.m[1][0] * src[0] + a_mtxA.m[1][1] * src[1] + a_mtxA.m[1][2] * src[2] + a_mtxA.m[1][3]) * weight, + (a_mtxA.m[2][0] * src[0] + a_mtxA.m[2][1] * src[1] + a_mtxA.m[2][2] * src[2] + a_mtxA.m[2][3]) * weight); - MatrixFloatRotateSet(pSkinTangent,mtxTransform, pBindTangent, *pWeight); + } + static inline float3 WeightTransformRotation(const cMatrixf& a_mtxA, float3 src, float weight) { - ++pWeight; ++pBoneIdx; ++lCount; + return float3((a_mtxA.m[0][0] * src[0] + a_mtxA.m[0][1] * src[1] + a_mtxA.m[0][2] * src[2]) * weight, + (a_mtxA.m[1][0] * src[0] + a_mtxA.m[1][1] * src[1] + a_mtxA.m[1][2] * src[2]) * weight, + (a_mtxA.m[2][0] * src[0] + a_mtxA.m[2][1] * src[1] + a_mtxA.m[2][2] * src[2]) * weight); - //Iterate weights until 0 is found or count < 4 - while(*pWeight != 0 && lCount < 4) - { - //Log("Boneidx: %d Count %d Weight: %f\n",(int)*pBoneIdx,lCount, *pWeight); - const cMatrixf &mtxTransform = mpMeshEntity->mvBoneMatrices[*pBoneIdx]; + } - //Transform with the local movement of the bone. - MatrixFloatTransformAdd(pSkinPos,mtxTransform, pBindPos, *pWeight); - MatrixFloatRotateAdd(pSkinNormal,mtxTransform, pBindNormal, *pWeight); + void cSubMeshEntity::UpdateGraphicsForFrame(float afFrameTime) { + //////////////////////////////////// + // Update things in parent first. + mpMeshEntity->UpdateGraphicsForFrame(afFrameTime); - MatrixFloatRotateAdd(pSkinTangent,mtxTransform, pBindTangent, *pWeight); + //////////////////////////////////// + // If it has dynamic mesh, update it. + if (m_skinnedMesh) { + if (mpMeshEntity->mbSkeletonPhysicsSleeping && mbGraphicsUpdated) { + return; + } - ++pWeight; ++pBoneIdx; ++lCount; - } + m_activeCopy = (m_activeCopy + 1) % ForgeRenderer::SwapChainLength; + mbGraphicsUpdated = true; - pBindPos += lVtxStride; - pSkinPos += lVtxStride; + auto staticBindBuffers = mpSubMesh->streamBuffers(); + auto bindPositionIt = std::find_if(staticBindBuffers.begin(), staticBindBuffers.end(), [&](auto& stream) { + return stream.m_semantic == ShaderSemantic::SEMANTIC_POSITION; + }); + auto bindNormalIt = std::find_if(staticBindBuffers.begin(), staticBindBuffers.end(), [&](auto& stream) { + return stream.m_semantic == ShaderSemantic::SEMANTIC_NORMAL; + }); + auto bindTangentIt = std::find_if(staticBindBuffers.begin(), staticBindBuffers.end(), [&](auto& stream) { + return stream.m_semantic == ShaderSemantic::SEMANTIC_TANGENT; + }); + ASSERT(bindPositionIt != staticBindBuffers.end() && + bindNormalIt != staticBindBuffers.end() && + bindTangentIt != staticBindBuffers.end() + ); + auto bindPositonView = bindPositionIt->GetStructuredView(); // the static buffer data is the fixed pose + auto bindNormalView = bindNormalIt->GetStructuredView(); + auto bindTangentView = bindTangentIt->GetStructuredView(); + + auto targetPositionIt = std::find_if(m_vertexStreams.begin(), m_vertexStreams.end(), [&](auto& stream) { + return stream.m_semantic == ShaderSemantic::SEMANTIC_POSITION; + }); + auto targetNormalIt = std::find_if(m_vertexStreams.begin(), m_vertexStreams.end(), [&](auto& stream) { + return stream.m_semantic == ShaderSemantic::SEMANTIC_NORMAL; + }); + auto targetTangentIt = std::find_if(m_vertexStreams.begin(), m_vertexStreams.end(), [&](auto& stream) { + return stream.m_semantic == ShaderSemantic::SEMANTIC_TANGENT; + }); - pBindNormal += 3; - pSkinNormal += 3; + ASSERT(targetPositionIt != m_vertexStreams.end() && + targetNormalIt != m_vertexStreams.end() && + targetTangentIt != m_vertexStreams.end() + ); + BufferUpdateDesc positionUpdateDesc = { targetPositionIt->m_buffer.m_handle, m_activeCopy * (targetPositionIt->m_stride * targetPositionIt->m_numberElements), targetPositionIt->m_stride * targetPositionIt->m_numberElements}; + BufferUpdateDesc tangentUpdateDesc = { targetTangentIt->m_buffer.m_handle, m_activeCopy * (targetTangentIt->m_stride * targetTangentIt->m_numberElements), targetTangentIt->m_stride * targetTangentIt->m_numberElements }; + BufferUpdateDesc normalUpdateDesc = { targetNormalIt->m_buffer.m_handle, m_activeCopy * (targetNormalIt->m_stride * targetNormalIt->m_numberElements), targetNormalIt->m_stride * targetNormalIt->m_numberElements }; + beginUpdateResource(&positionUpdateDesc); + beginUpdateResource(&tangentUpdateDesc); + beginUpdateResource(&normalUpdateDesc); + + GraphicsBuffer positionMapping(positionUpdateDesc); + GraphicsBuffer normalMapping(tangentUpdateDesc); + GraphicsBuffer tangentMapping(normalUpdateDesc); + auto targetPositionView = positionMapping.CreateStructuredView(0, targetPositionIt->m_stride); + auto targetTangentView = tangentMapping.CreateStructuredView(0, targetTangentIt->m_stride); + auto targetNormalView = normalMapping.CreateStructuredView(0, targetNormalIt->m_stride); + + for(size_t i = 0; i < bindPositionIt->m_numberElements; i++) { + + const std::span weights = std::span(&mpSubMesh->m_vertexWeights[(i * 4)], 4); + const std::span boneIdxs = std::span(&mpSubMesh->m_vertexBones[(i * 4)], 4); + + float3 bindPos = bindPositonView.Get(i); + float3 bindNormal = bindNormalView.Get(i); + float3 bindTangent = bindTangentView.Get(i); + + float3 accmulatedPos = float3(0); + float3 accmulatedNormal = float3(0); + float3 accmulatedTangent = float3(0); + + for(size_t boneIdx = 0; boneIdx < 4 && weights[boneIdx] != 0; boneIdx++) { + const float weight = weights[boneIdx]; + const cMatrixf& transform = mpMeshEntity->mvBoneMatrices[boneIdxs[boneIdx]]; + accmulatedPos += WeightTransform(transform, bindPos, weight); + accmulatedNormal += WeightTransformRotation(transform, bindNormal, weight); + accmulatedTangent += WeightTransformRotation(transform, bindTangent, weight); + } + targetPositionView.Write(i, accmulatedPos); + targetNormalView.Write(i, accmulatedNormal); + targetTangentView.Write(i, accmulatedTangent); + } - pBindTangent += 4; - pSkinTangent += 4; - } - //Update buffer - mpDynVtxBuffer->UpdateData(eVertexElementFlag_Position | eVertexElementFlag_Normal | eVertexElementFlag_Texture1,false); + endUpdateResource(&positionUpdateDesc, nullptr); + endUpdateResource(&tangentUpdateDesc, nullptr); + endUpdateResource(&normalUpdateDesc, nullptr); } } @@ -264,11 +256,6 @@ namespace hpl { DrawPacket cSubMeshEntity::ResolveDrawPacket(const ForgeRenderer::Frame& frame,std::span elements) { DrawPacket packet; - packet.m_type = DrawPacket::Unknown; - if(mpDynVtxBuffer) - { - return static_cast(mpDynVtxBuffer)->resolveGeometryBinding(frame.m_currentFrame, elements); - } if(m_numberIndecies == 0) { return packet; } @@ -284,6 +271,9 @@ namespace hpl { auto& stream = packet.m_indvidual.m_vertexStream[packet.m_indvidual.m_numStreams++]; stream.m_buffer = &found->m_buffer; stream.m_offset = 0; + if(found->m_type == StreamBufferType::DynamicBuffer) { + stream.m_offset = m_activeCopy * (found->m_numberElements * found->m_stride); + } stream.m_stride = found->m_stride; } packet.m_indvidual.m_indexStream.m_offset = 0; @@ -392,4 +382,4 @@ namespace hpl { mpMeshEntity->mbUpdateBoundingVolume = true; } -} +} // namespace hpl diff --git a/README.md b/README.md index db1032815..7bc4638c0 100644 --- a/README.md +++ b/README.md @@ -61,3 +61,4 @@ on the system path. - Any code published by `Frictional` is under a GNU GENERAL PUBLIC LICENSE - Some code published by `Open 3D Engine` which is under an Apache-2.0 OR MIT - Any new code that is under my name will use an Apache-2.0 LICENSE +- Sebastian Aaltonen 2023 (MIT License (see file: LICENSE)) \ No newline at end of file From 5635d5fd33afe17af05e4f87afbd77f15b18f72a Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Tue, 24 Oct 2023 21:43:04 -0700 Subject: [PATCH 05/17] feat: cleanup Signed-off-by: Michael Pollind --- HPL2/include/graphics/SubMesh.h | 2 +- HPL2/sources/graphics/SubMesh.cpp | 2 +- HPL2/sources/scene/SubMeshEntity.cpp | 15 ++++----------- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/HPL2/include/graphics/SubMesh.h b/HPL2/include/graphics/SubMesh.h index 59414afde..13fc4c10b 100644 --- a/HPL2/include/graphics/SubMesh.h +++ b/HPL2/include/graphics/SubMesh.h @@ -125,7 +125,7 @@ namespace hpl { constexpr GraphicsBuffer::BufferStructuredView GetStructuredView(uint32_t byteOffset = 0) { return m_buffer.CreateStructuredView(byteOffset, m_stride); } - SharedBuffer CommitBuffer(); + SharedBuffer CommitSharedBuffer(); SharedBuffer m_gpuBuffer; GraphicsBuffer m_buffer; diff --git a/HPL2/sources/graphics/SubMesh.cpp b/HPL2/sources/graphics/SubMesh.cpp index 031347428..fc52d6ab2 100644 --- a/HPL2/sources/graphics/SubMesh.cpp +++ b/HPL2/sources/graphics/SubMesh.cpp @@ -269,7 +269,7 @@ namespace hpl { } // not an ideal solution - SharedBuffer cSubMesh::StreamBufferInfo::CommitBuffer() { + SharedBuffer cSubMesh::StreamBufferInfo::CommitSharedBuffer() { if(!m_gpuBuffer.IsValid()) { auto rawView = m_buffer.CreateViewRaw(); m_gpuBuffer.Load([&](Buffer** buffer) { diff --git a/HPL2/sources/scene/SubMeshEntity.cpp b/HPL2/sources/scene/SubMeshEntity.cpp index e5150e9cb..982cb6ab8 100644 --- a/HPL2/sources/scene/SubMeshEntity.cpp +++ b/HPL2/sources/scene/SubMeshEntity.cpp @@ -91,17 +91,7 @@ namespace hpl { }); } else { info.m_type = StreamBufferType::StaticBuffer; - info.m_buffer = stream.CommitBuffer(); - // info.m_buffer.Load([&](Buffer** buffer) { - // BufferLoadDesc loadDesc = {}; - // loadDesc.ppBuffer = buffer; - // loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; - // loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_ONLY; - // loadDesc.mDesc.mSize = rawView.NumBytes(); - // loadDesc.pData = rawView.rawByteSpan().data(); - // addResource(&loadDesc, nullptr); - // return true; - // }); + info.m_buffer = stream.CommitSharedBuffer(); } } { @@ -207,6 +197,9 @@ namespace hpl { targetNormalIt != m_vertexStreams.end() && targetTangentIt != m_vertexStreams.end() ); + ASSERT(targetPositionIt->m_type == StreamBufferType::DynamicBuffer); + ASSERT(targetNormalIt->m_type == StreamBufferType::DynamicBuffer); + ASSERT(targetTangentIt->m_type == StreamBufferType::DynamicBuffer); BufferUpdateDesc positionUpdateDesc = { targetPositionIt->m_buffer.m_handle, m_activeCopy * (targetPositionIt->m_stride * targetPositionIt->m_numberElements), targetPositionIt->m_stride * targetPositionIt->m_numberElements}; BufferUpdateDesc tangentUpdateDesc = { targetTangentIt->m_buffer.m_handle, m_activeCopy * (targetTangentIt->m_stride * targetTangentIt->m_numberElements), targetTangentIt->m_stride * targetTangentIt->m_numberElements }; BufferUpdateDesc normalUpdateDesc = { targetNormalIt->m_buffer.m_handle, m_activeCopy * (targetNormalIt->m_stride * targetNormalIt->m_numberElements), targetNormalIt->m_stride * targetNormalIt->m_numberElements }; From 65ccf2bfeaf8ccbe61b4b00dcf1e753a44724837 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Wed, 25 Oct 2023 08:00:47 -0700 Subject: [PATCH 06/17] feat: started on forward+ renderer Signed-off-by: Michael Pollind --- HPL2/include/graphics/GraphicsAllocator.h | 37 +++++++++++++++++++++ HPL2/include/graphics/RendererForwardPlus.h | 29 ++++++++++++++++ HPL2/sources/graphics/GraphicsAllocator.cpp | 17 ++++++++++ HPL2/sources/graphics/MeshUtility.cpp | 4 +-- 4 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 HPL2/include/graphics/GraphicsAllocator.h create mode 100644 HPL2/include/graphics/RendererForwardPlus.h create mode 100644 HPL2/sources/graphics/GraphicsAllocator.cpp diff --git a/HPL2/include/graphics/GraphicsAllocator.h b/HPL2/include/graphics/GraphicsAllocator.h new file mode 100644 index 000000000..b768dc036 --- /dev/null +++ b/HPL2/include/graphics/GraphicsAllocator.h @@ -0,0 +1,37 @@ +#pragma once + +#include "graphics/ForgeHandles.h" +#include "graphics/offsetAllocator.h" + +#include "Common_3/Utilities/RingBuffer.h" + +namespace hpl { + class GraphicsAllocator final { + public: + GraphicsAllocator(); + + static constexpr uint32_t SharedVertexBufferSize = 1 << 25; + static constexpr uint32_t SharedIndexBufferSize = 1 << 23; + + struct OffsetAllocHandle { + public: + private: + OffsetAllocator::Allocator* m_allocator; + SharedBuffer m_buffer; + uint32_t m_offset; + uint32_t m_size; + }; + + void allocTransientVertexBuffer(uint32_t size); + void allocTransientIndexBuffer(uint32_t size); + + private: + GPURingBuffer* m_transientVertexBuffer = nullptr; + GPURingBuffer* m_transientIndeciesBuffer = nullptr; + + OffsetAllocator::Allocator m_vertexBufferAllocator; + SharedBuffer m_sharedVertexBuffer; + OffsetAllocator::Allocator m_indexBufferAllocator; + SharedBuffer m_sharedIndexBuffer; + }; +} // namespace hpl diff --git a/HPL2/include/graphics/RendererForwardPlus.h b/HPL2/include/graphics/RendererForwardPlus.h new file mode 100644 index 000000000..dc469fc06 --- /dev/null +++ b/HPL2/include/graphics/RendererForwardPlus.h @@ -0,0 +1,29 @@ + +#pragma once +#include "engine/RTTI.h" + +#include "scene/Viewport.h" +#include "scene/World.h" +#include "windowing/NativeWindow.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace hpl { + class RendererForwardPlus : public iRenderer { + HPL_RTTI_IMPL_CLASS(iRenderer, cRendererDeferred, "{A3E5E5A1-1F9C-4F5C-9B9B-5B9B9B5B9B9B}") + public: + }; +} // namespace hpl diff --git a/HPL2/sources/graphics/GraphicsAllocator.cpp b/HPL2/sources/graphics/GraphicsAllocator.cpp new file mode 100644 index 000000000..83949bd70 --- /dev/null +++ b/HPL2/sources/graphics/GraphicsAllocator.cpp @@ -0,0 +1,17 @@ +#include "graphics/GraphicsAllocator.h" + +namespace hpl { + + GraphicsAllocator::GraphicsAllocator(): + m_vertexBufferAllocator(GraphicsAllocator::SharedVertexBufferSize), + m_indexBufferAllocator(GraphicsAllocator::SharedVertexBufferSize) { + + } + void GraphicsAllocator::allocTransientVertexBuffer(uint32_t size) { + + } + void GraphicsAllocator::allocTransientIndexBuffer(uint32_t size) { + + } + +} diff --git a/HPL2/sources/graphics/MeshUtility.cpp b/HPL2/sources/graphics/MeshUtility.cpp index 2a97cdd80..22736dc60 100644 --- a/HPL2/sources/graphics/MeshUtility.cpp +++ b/HPL2/sources/graphics/MeshUtility.cpp @@ -539,7 +539,7 @@ namespace hpl::MeshUtility { return idx; }; - auto getBoxTex = [](int i, int x, int y, int z, std::array& vAdd) { + auto getBoxTex = [](int i, int x, int y, int z, float3 vAdd[4]) { float3 vTex; if (std::abs(x)) { @@ -573,7 +573,7 @@ namespace hpl::MeshUtility { float3 vDir(0); float3 vSide(0); - std::array vAdd; + float3 vAdd[4]; if (std::abs(x)) { vDir.x = (float)x; From 6aad8a2659b4514dcb484b9ba6630fe454057bd8 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Wed, 25 Oct 2023 18:17:46 -0700 Subject: [PATCH 07/17] feat: rough implmenentation for allocator Signed-off-by: Michael Pollind --- HPL2/include/graphics/GraphicsAllocator.h | 25 ++++++-- HPL2/include/system/Bootstrap.h | 2 + HPL2/sources/graphics/GraphicsAllocator.cpp | 67 +++++++++++++++++++-- HPL2/sources/system/Bootstrap.cpp | 4 ++ 4 files changed, 88 insertions(+), 10 deletions(-) diff --git a/HPL2/include/graphics/GraphicsAllocator.h b/HPL2/include/graphics/GraphicsAllocator.h index b768dc036..f6f228ca4 100644 --- a/HPL2/include/graphics/GraphicsAllocator.h +++ b/HPL2/include/graphics/GraphicsAllocator.h @@ -1,6 +1,7 @@ #pragma once #include "graphics/ForgeHandles.h" +#include "graphics/ForgeRenderer.h" #include "graphics/offsetAllocator.h" #include "Common_3/Utilities/RingBuffer.h" @@ -8,24 +9,38 @@ namespace hpl { class GraphicsAllocator final { public: - GraphicsAllocator(); + GraphicsAllocator(ForgeRenderer* renderer); static constexpr uint32_t SharedVertexBufferSize = 1 << 25; static constexpr uint32_t SharedIndexBufferSize = 1 << 23; + static constexpr uint32_t ImmediateVertexBufferSize = 1 << 25; + static constexpr uint32_t ImmediateIndexBufferSize = 1 << 23; struct OffsetAllocHandle { public: + OffsetAllocHandle(OffsetAllocator::Allocator* allocator, OffsetAllocator::Allocation allocation ,SharedBuffer buffer); + OffsetAllocHandle(); + ~OffsetAllocHandle(); + OffsetAllocHandle(OffsetAllocHandle&& handle); + OffsetAllocHandle(const OffsetAllocHandle& handle) = delete; + + void operator=(const OffsetAllocHandle& handle) = delete; + void operator=(OffsetAllocHandle&& handle); + private: OffsetAllocator::Allocator* m_allocator; + OffsetAllocator::Allocation m_allocation; SharedBuffer m_buffer; - uint32_t m_offset; - uint32_t m_size; }; - void allocTransientVertexBuffer(uint32_t size); - void allocTransientIndexBuffer(uint32_t size); + OffsetAllocHandle allocVertexFromSharedBuffer(uint32_t size); + OffsetAllocHandle allocIndeciesFromSharedBuffer(uint32_t size); + + GPURingBufferOffset allocTransientVertexBuffer(uint32_t size); + GPURingBufferOffset allocTransientIndexBuffer(uint32_t size); private: + ForgeRenderer* m_renderer; GPURingBuffer* m_transientVertexBuffer = nullptr; GPURingBuffer* m_transientIndeciesBuffer = nullptr; diff --git a/HPL2/include/system/Bootstrap.h b/HPL2/include/system/Bootstrap.h index ce3dd1207..73334a788 100644 --- a/HPL2/include/system/Bootstrap.h +++ b/HPL2/include/system/Bootstrap.h @@ -19,6 +19,7 @@ #include "engine/UpdateEventLoop.h" #include "graphics/ForgeRenderer.h" #include "graphics/DebugDraw.h" +#include "graphics/GraphicsAllocator.h" #include "windowing/NativeWindow.h" #include #include @@ -52,6 +53,7 @@ namespace hpl { std::unique_ptr m_primaryViewport; hpl::ForgeRenderer m_renderer; std::unique_ptr m_debug; + std::unique_ptr m_graphicsAlloc; UpdateEventLoop m_updateEventLoop; input::InputManager m_inputManager; diff --git a/HPL2/sources/graphics/GraphicsAllocator.cpp b/HPL2/sources/graphics/GraphicsAllocator.cpp index 83949bd70..377fa3280 100644 --- a/HPL2/sources/graphics/GraphicsAllocator.cpp +++ b/HPL2/sources/graphics/GraphicsAllocator.cpp @@ -1,17 +1,74 @@ #include "graphics/GraphicsAllocator.h" +#include "graphics/ForgeRenderer.h" namespace hpl { - GraphicsAllocator::GraphicsAllocator(): + GraphicsAllocator::GraphicsAllocator(ForgeRenderer* renderer): + m_renderer(renderer), m_vertexBufferAllocator(GraphicsAllocator::SharedVertexBufferSize), - m_indexBufferAllocator(GraphicsAllocator::SharedVertexBufferSize) { - + m_indexBufferAllocator(GraphicsAllocator::SharedIndexBufferSize) { + m_sharedIndexBuffer.Load([&](Buffer** buffer) { + BufferLoadDesc loadDesc = {}; + loadDesc.ppBuffer = buffer; + loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_INDEX_BUFFER; + loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; + loadDesc.mDesc.mSize = GraphicsAllocator::SharedIndexBufferSize; // will have a copy per frame + addResource(&loadDesc, nullptr); + return true; + }); + m_sharedVertexBuffer.Load([&](Buffer** buffer) { + BufferLoadDesc loadDesc = {}; + loadDesc.ppBuffer = buffer; + loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; + loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; + loadDesc.mDesc.mSize = GraphicsAllocator::SharedVertexBufferSize; // will have a copy per frame + addResource(&loadDesc, nullptr); + return true; + }); + { + BufferDesc desc = {}; + desc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; + desc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; + desc.mSize = ImmediateVertexBufferSize; + desc.pName = "Immediate Vertex Buffer"; + addGPURingBuffer(renderer->Rend(), &desc, &m_transientVertexBuffer); + } + { + BufferDesc desc = {}; + desc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; + desc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; + desc.mSize = ImmediateIndexBufferSize; + desc.pName = "Immediate Index Buffer"; + addGPURingBuffer(renderer->Rend(), &desc, &m_transientIndeciesBuffer); + } } - void GraphicsAllocator::allocTransientVertexBuffer(uint32_t size) { + GraphicsAllocator::OffsetAllocHandle::OffsetAllocHandle(OffsetAllocator::Allocator* allocator, OffsetAllocator::Allocation allocation ,SharedBuffer buffer): + m_allocator(allocator), + m_allocation(allocation), + m_buffer(buffer) { } - void GraphicsAllocator::allocTransientIndexBuffer(uint32_t size) { + GraphicsAllocator::OffsetAllocHandle::~OffsetAllocHandle() { + if(m_allocation.offset != OffsetAllocator::Allocation::NO_SPACE) { + ASSERT(m_allocator != nullptr); + m_allocator->free(m_allocation); + } + + } + GPURingBufferOffset GraphicsAllocator::allocTransientVertexBuffer(uint32_t size) { + return getGPURingBufferOffset(m_transientVertexBuffer, size); + } + GPURingBufferOffset GraphicsAllocator::allocTransientIndexBuffer(uint32_t size) { + return getGPURingBufferOffset(m_transientIndeciesBuffer, size); } + GraphicsAllocator::OffsetAllocHandle GraphicsAllocator::allocVertexFromSharedBuffer(uint32_t size) { + OffsetAllocator::Allocation alloc = m_vertexBufferAllocator.allocate(size); + return OffsetAllocHandle(&m_vertexBufferAllocator, alloc, m_sharedVertexBuffer); + } + GraphicsAllocator::OffsetAllocHandle GraphicsAllocator::allocIndeciesFromSharedBuffer(uint32_t size) { + OffsetAllocator::Allocation alloc = m_indexBufferAllocator.allocate(size); + return OffsetAllocHandle(&m_indexBufferAllocator, alloc, m_sharedIndexBuffer); + } } diff --git a/HPL2/sources/system/Bootstrap.cpp b/HPL2/sources/system/Bootstrap.cpp index 79ced3610..eb3bd880c 100644 --- a/HPL2/sources/system/Bootstrap.cpp +++ b/HPL2/sources/system/Bootstrap.cpp @@ -5,6 +5,7 @@ #include "engine/IUpdateEventLoop.h" #include "engine/Interface.h" +#include "graphics/GraphicsAllocator.h" #include "gui/GuiSet.h" #include "input/InputKeyboardDevice.h" #include "input/InputManager.h" @@ -70,6 +71,9 @@ namespace hpl { // core renderer initialization m_renderer.InitializeRenderer(&m_window); + // graphics allocator + m_graphicsAlloc = std::make_unique(&m_renderer); + // initialize gui rendering initResourceLoaderInterface(m_renderer.Rend()); // initializes resources m_renderer.InitializeResource(); From 3c5a52540f8a5adf16e1a64962f5b990cd4dc3a9 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Wed, 25 Oct 2023 18:21:46 -0700 Subject: [PATCH 08/17] testo --- HPL2/include/graphics/GraphicsAllocator.h | 1 + 1 file changed, 1 insertion(+) diff --git a/HPL2/include/graphics/GraphicsAllocator.h b/HPL2/include/graphics/GraphicsAllocator.h index f6f228ca4..ca5f2f89c 100644 --- a/HPL2/include/graphics/GraphicsAllocator.h +++ b/HPL2/include/graphics/GraphicsAllocator.h @@ -20,6 +20,7 @@ namespace hpl { public: OffsetAllocHandle(OffsetAllocator::Allocator* allocator, OffsetAllocator::Allocation allocation ,SharedBuffer buffer); OffsetAllocHandle(); + ~OffsetAllocHandle(); OffsetAllocHandle(OffsetAllocHandle&& handle); OffsetAllocHandle(const OffsetAllocHandle& handle) = delete; From 524edfe4712851cf4aab2a4336040fc6494924fa Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Fri, 27 Oct 2023 08:25:59 -0700 Subject: [PATCH 09/17] feat: added global allocator and migrated subMesh to use scheme Signed-off-by: Michael Pollind --- HPL2/include/graphics/DrawPacket.h | 3 + HPL2/include/graphics/GraphicsAllocator.h | 109 +++++++++---- HPL2/include/graphics/GraphicsBuffer.h | 2 +- HPL2/include/graphics/SubMesh.h | 1 - HPL2/include/graphics/offsetAllocator.h | 18 ++- HPL2/include/scene/SubMeshEntity.h | 42 +---- HPL2/sources/graphics/GraphicsAllocator.cpp | 164 ++++++++++++++------ HPL2/sources/graphics/MeshUtility.cpp | 11 +- HPL2/sources/graphics/offsetAllocator.cpp | 121 +++++++++------ HPL2/sources/scene/SubMeshEntity.cpp | 156 ++++++++----------- HPL2/sources/system/Bootstrap.cpp | 9 +- 11 files changed, 368 insertions(+), 268 deletions(-) diff --git a/HPL2/include/graphics/DrawPacket.h b/HPL2/include/graphics/DrawPacket.h index ebb2838e4..6f00f2215 100644 --- a/HPL2/include/graphics/DrawPacket.h +++ b/HPL2/include/graphics/DrawPacket.h @@ -37,6 +37,9 @@ namespace hpl { VertexStream m_vertexStream[MaxVertexBindings]; IndexStream m_indexStream; } m_indvidual; + struct { + + } m_unified; }; }; diff --git a/HPL2/include/graphics/GraphicsAllocator.h b/HPL2/include/graphics/GraphicsAllocator.h index ca5f2f89c..ed56676fd 100644 --- a/HPL2/include/graphics/GraphicsAllocator.h +++ b/HPL2/include/graphics/GraphicsAllocator.h @@ -1,53 +1,110 @@ #pragma once +#include "Common_3/Graphics/Interfaces/IGraphics.h" #include "graphics/ForgeHandles.h" #include "graphics/ForgeRenderer.h" #include "graphics/offsetAllocator.h" #include "Common_3/Utilities/RingBuffer.h" +#include namespace hpl { - class GraphicsAllocator final { + class GeometrySet final { public: - GraphicsAllocator(ForgeRenderer* renderer); - - static constexpr uint32_t SharedVertexBufferSize = 1 << 25; - static constexpr uint32_t SharedIndexBufferSize = 1 << 23; - static constexpr uint32_t ImmediateVertexBufferSize = 1 << 25; - static constexpr uint32_t ImmediateIndexBufferSize = 1 << 23; + static constexpr uint32_t IndexBufferStride = sizeof(uint32_t); - struct OffsetAllocHandle { + struct GeometryStreamDesc { + const char* m_name; + ShaderSemantic m_semantic; + uint32_t m_stride; + }; + class GeometryStream final { public: - OffsetAllocHandle(OffsetAllocator::Allocator* allocator, OffsetAllocator::Allocation allocation ,SharedBuffer buffer); - OffsetAllocHandle(); - - ~OffsetAllocHandle(); - OffsetAllocHandle(OffsetAllocHandle&& handle); - OffsetAllocHandle(const OffsetAllocHandle& handle) = delete; + GeometryStream(); + GeometryStream(GeometryStream&&); + void operator=(GeometryStream&& stream); - void operator=(const OffsetAllocHandle& handle) = delete; - void operator=(OffsetAllocHandle&& handle); + GeometryStream(const GeometryStream&) = delete; + void operator=(GeometryStream& stream) = delete; + + inline ShaderSemantic semantic() { return m_semantic; } + inline uint32_t stride() { return m_stride; } + inline SharedBuffer& buffer() { return m_buffer; } private: - OffsetAllocator::Allocator* m_allocator; - OffsetAllocator::Allocation m_allocation; + ShaderSemantic m_semantic = ShaderSemantic::SEMANTIC_UNDEFINED; + uint32_t m_stride = 0; SharedBuffer m_buffer; + friend class GeometrySet; + }; + + class GeometrySetSubAllocation final { + public: + + ~GeometrySetSubAllocation(); + GeometrySetSubAllocation(); + GeometrySetSubAllocation(GeometrySetSubAllocation&& allocation); + GeometrySetSubAllocation(const GeometrySetSubAllocation& allocation) = delete; + + void operator=(GeometrySetSubAllocation&& allocation); + void operator=(const GeometrySetSubAllocation& allocation) = delete; + + inline SharedBuffer& indexBuffer() { return m_geometrySet->m_indexBuffer; } + inline std::span vertexStreams() { return m_geometrySet->m_vertexStreams; } + inline std::span::iterator getStreamBySemantic(ShaderSemantic semantic) { + return std::find_if(vertexStreams().begin(), vertexStreams().end(), [&](auto& stream) { + return stream.m_semantic == semantic; + }); + } + inline uint32_t vertextOffset() { return m_vertexAllocation.offset; } + inline uint32_t indexOffset() { return m_indexAllocation.offset; } + private: + OffsetAllocator::Allocation m_vertexAllocation; + OffsetAllocator::Allocation m_indexAllocation; + GeometrySet* m_geometrySet = nullptr; + friend class GeometrySet; + }; + + GeometrySet(GeometrySet&& set); + GeometrySet(const GeometrySet& set) = delete; + GeometrySet(); + explicit GeometrySet(uint32_t numElements, uint32_t numIndecies, std::span stream); + + void operator=(GeometrySet&& set); + void operator=(const GeometrySet& set) = delete; + std::shared_ptr allocate(uint32_t numElements, uint32_t numIndecies); + private: + OffsetAllocator::Allocator m_vertexStreamAllocator; + OffsetAllocator::Allocator m_indexStreamAllocator; + folly::small_vector m_vertexStreams; + SharedBuffer m_indexBuffer; + friend class GeometryStream; + }; + + class GraphicsAllocator final { + HPL_RTTI_CLASS(GraphicsAllocator , "{57396F88-B069-4CEB-AF7C-0A9419D165C3}") + public: + GraphicsAllocator(ForgeRenderer* renderer); + + enum AllocationSet { + OpaqueSet, + NumOfAllocationSets }; - OffsetAllocHandle allocVertexFromSharedBuffer(uint32_t size); - OffsetAllocHandle allocIndeciesFromSharedBuffer(uint32_t size); + static constexpr uint32_t OpaqueVertexBufferSize = 1 << 25; + static constexpr uint32_t OpaqueIndexBufferSize = 1 << 23; + + static constexpr uint32_t ImmediateVertexBufferSize = 1 << 25; + static constexpr uint32_t ImmediateIndexBufferSize = 1 << 23; GPURingBufferOffset allocTransientVertexBuffer(uint32_t size); GPURingBufferOffset allocTransientIndexBuffer(uint32_t size); - + GeometrySet& resolveSet(AllocationSet set); private: + std::array m_geometrySets; + ForgeRenderer* m_renderer; GPURingBuffer* m_transientVertexBuffer = nullptr; GPURingBuffer* m_transientIndeciesBuffer = nullptr; - - OffsetAllocator::Allocator m_vertexBufferAllocator; - SharedBuffer m_sharedVertexBuffer; - OffsetAllocator::Allocator m_indexBufferAllocator; - SharedBuffer m_sharedIndexBuffer; }; } // namespace hpl diff --git a/HPL2/include/graphics/GraphicsBuffer.h b/HPL2/include/graphics/GraphicsBuffer.h index fd4516e22..9816804ab 100644 --- a/HPL2/include/graphics/GraphicsBuffer.h +++ b/HPL2/include/graphics/GraphicsBuffer.h @@ -78,7 +78,7 @@ namespace hpl { break; } case BufferType::MappedBuffer: { - ASSERT(m_asset->m_mapped.m_size == 0 || m_byteOffset + byteOffset + data.size() < m_asset->m_mapped.m_size); + ASSERT(m_asset->m_mapped.m_size == 0 || m_byteOffset + byteOffset + data.size() <= m_asset->m_mapped.m_size); std::copy(data.begin(), data.end(), reinterpret_cast(m_asset->m_mapped.m_mappedData) + m_byteOffset + byteOffset); break; } diff --git a/HPL2/include/graphics/SubMesh.h b/HPL2/include/graphics/SubMesh.h index 13fc4c10b..07e8907dc 100644 --- a/HPL2/include/graphics/SubMesh.h +++ b/HPL2/include/graphics/SubMesh.h @@ -43,7 +43,6 @@ namespace hpl { class cMaterialManager; - class cSubMesh final { friend class cMesh; friend class cSubMeshEntity; diff --git a/HPL2/include/graphics/offsetAllocator.h b/HPL2/include/graphics/offsetAllocator.h index 155e21dd9..7a8f8e746 100644 --- a/HPL2/include/graphics/offsetAllocator.h +++ b/HPL2/include/graphics/offsetAllocator.h @@ -26,7 +26,7 @@ namespace OffsetAllocator struct Allocation { static constexpr uint32 NO_SPACE = 0xffffffff; - + uint32 offset = NO_SPACE; NodeIndex metadata = NO_SPACE; // internal: node index }; @@ -44,7 +44,7 @@ namespace OffsetAllocator uint32 size; uint32 count; }; - + Region freeRegions[NUM_LEAF_BINS]; }; @@ -53,16 +53,20 @@ namespace OffsetAllocator public: Allocator(uint32 size, uint32 maxAllocs = 128 * 1024); Allocator(Allocator &&other); + Allocator(const Allocator &other) = delete; ~Allocator(); void reset(); - + + void operator=(Allocator &&other); + void operator=(const Allocator &other) = delete; + Allocation allocate(uint32 size); void free(Allocation allocation); uint32 allocationSize(Allocation allocation) const; StorageReport storageReport() const; StorageReportFull storageReportFull() const; - + private: uint32 insertNodeIntoBin(uint32 size, uint32 dataOffset); void removeNodeFromBin(uint32 nodeIndex); @@ -70,7 +74,7 @@ namespace OffsetAllocator struct Node { static constexpr NodeIndex unused = 0xffffffff; - + uint32 dataOffset = 0; uint32 dataSize = 0; NodeIndex binListPrev = unused; @@ -79,7 +83,7 @@ namespace OffsetAllocator NodeIndex neighborNext = unused; bool used = false; // TODO: Merge as bit flag }; - + uint32 m_size; uint32 m_maxAllocs; uint32 m_freeStorage; @@ -87,7 +91,7 @@ namespace OffsetAllocator uint32 m_usedBinsTop; uint8 m_usedBins[NUM_TOP_BINS]; NodeIndex m_binIndices[NUM_LEAF_BINS]; - + Node* m_nodes; NodeIndex* m_freeNodes; uint32 m_freeOffset; diff --git a/HPL2/include/scene/SubMeshEntity.h b/HPL2/include/scene/SubMeshEntity.h index ca328e2b3..08ccb5fe3 100644 --- a/HPL2/include/scene/SubMeshEntity.h +++ b/HPL2/include/scene/SubMeshEntity.h @@ -24,6 +24,7 @@ #include "Common_3/Graphics/Interfaces/IGraphics.h" #include "graphics/ForgeHandles.h" +#include "graphics/GraphicsAllocator.h" #include "math/MathTypes.h" #include "graphics/GraphicsTypes.h" #include "system/SystemTypes.h" @@ -92,42 +93,10 @@ namespace hpl { private: virtual void OnTransformUpdated() override; - - enum StreamBufferType { - StaticBuffer, - DynamicBuffer - }; - - struct StreamBufferInfo { - public: - StreamBufferType m_type = StreamBufferType::StaticBuffer; - SharedBuffer m_buffer; - ShaderSemantic m_semantic = ShaderSemantic::SEMANTIC_UNDEFINED; - uint64_t m_stride = 0; - uint32_t m_numberElements = 0; - StreamBufferInfo() {} - StreamBufferInfo(const StreamBufferInfo& info) = delete; - StreamBufferInfo(StreamBufferInfo&& info): - m_type(info.m_type), - m_buffer(std::move(info.m_buffer)), - m_semantic(info.m_semantic), - m_stride(info.m_stride), - m_numberElements(info.m_numberElements) { - } - void operator=(const StreamBufferInfo& info) = delete; - void operator=(StreamBufferInfo&& info) { - m_type = info.m_type; - m_buffer = std::move(info.m_buffer); - m_semantic = info.m_semantic; - m_stride = info.m_stride; - m_numberElements = info.m_numberElements; - } - - }; + std::shared_ptr m_geometry; uint8_t m_activeCopy = 0; uint32_t m_numberIndecies = 0; - SharedBuffer m_indexBuffer; - folly::small_vector m_vertexStreams; + uint32_t m_numberVertices = 0; cSubMesh *mpSubMesh= nullptr; cMeshEntity *mpMeshEntity= nullptr; @@ -138,12 +107,9 @@ namespace hpl { cMaterialManager* mpMaterialManager= nullptr; - iVertexBuffer* mpDynVtxBuffer = nullptr; - tTriangleDataVec mvDynTriangles; - bool mbUpdateBody = false; bool mbGraphicsUpdated = false; - bool m_skinnedMesh = false; + bool m_isSkinnedMesh = false; //This is used to see if null should be returned. // 0 = no check made, test if matrix is identity diff --git a/HPL2/sources/graphics/GraphicsAllocator.cpp b/HPL2/sources/graphics/GraphicsAllocator.cpp index 377fa3280..81b1fbeda 100644 --- a/HPL2/sources/graphics/GraphicsAllocator.cpp +++ b/HPL2/sources/graphics/GraphicsAllocator.cpp @@ -1,74 +1,146 @@ #include "graphics/GraphicsAllocator.h" #include "graphics/ForgeRenderer.h" +#include namespace hpl { - GraphicsAllocator::GraphicsAllocator(ForgeRenderer* renderer): - m_renderer(renderer), - m_vertexBufferAllocator(GraphicsAllocator::SharedVertexBufferSize), - m_indexBufferAllocator(GraphicsAllocator::SharedIndexBufferSize) { - m_sharedIndexBuffer.Load([&](Buffer** buffer) { + + std::shared_ptr GeometrySet::allocate(uint32_t numElements, uint32_t numIndecies) { + auto subAllocation = std::make_shared(); + subAllocation->m_indexAllocation = m_indexStreamAllocator.allocate(numIndecies); + subAllocation->m_vertexAllocation = m_vertexStreamAllocator.allocate(numElements); + subAllocation->m_geometrySet = this; + return subAllocation; + } + + GeometrySet::GeometryStream::GeometryStream(GeometryStream&& stream) + : m_semantic(stream.m_semantic) + , m_stride(stream.m_stride) + , m_buffer(std::move(stream.m_buffer)) { + } + + void GeometrySet::GeometryStream::operator=(GeometryStream&& stream){ + m_semantic = stream.m_semantic; + m_stride = stream.m_stride; + m_buffer = std::move(stream.m_buffer); + } + + GeometrySet::GeometrySet(uint32_t numElements, uint32_t numIndecies, std::span streamDesc) + : m_vertexStreamAllocator(numElements) + , m_indexStreamAllocator(numIndecies) { + for (auto& desc : streamDesc) { + auto& vertexStream = m_vertexStreams.emplace_back(); + vertexStream.m_stride = desc.m_stride; + vertexStream.m_semantic = desc.m_semantic; + vertexStream.m_buffer.Load([&](Buffer** buffer) { + BufferLoadDesc loadDesc = {}; + loadDesc.ppBuffer = buffer; + loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; + loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; + loadDesc.mDesc.mSize = numElements * vertexStream.m_stride; + loadDesc.mDesc.pName = desc.m_name; + addResource(&loadDesc, nullptr); + return true; + }); + } + m_indexBuffer.Load([&](Buffer** buffer) { BufferLoadDesc loadDesc = {}; loadDesc.ppBuffer = buffer; loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_INDEX_BUFFER; loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; - loadDesc.mDesc.mSize = GraphicsAllocator::SharedIndexBufferSize; // will have a copy per frame - addResource(&loadDesc, nullptr); - return true; - }); - m_sharedVertexBuffer.Load([&](Buffer** buffer) { - BufferLoadDesc loadDesc = {}; - loadDesc.ppBuffer = buffer; - loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; - loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; - loadDesc.mDesc.mSize = GraphicsAllocator::SharedVertexBufferSize; // will have a copy per frame + loadDesc.mDesc.mSize = numIndecies * sizeof(uint32_t); + loadDesc.mDesc.pName = "GeometrySet Index"; addResource(&loadDesc, nullptr); return true; }); + } + + GeometrySet::GeometryStream::GeometryStream() { + } + + GeometrySet::GeometrySet() + : m_vertexStreamAllocator(0) + , m_indexStreamAllocator(0) { + } + + GeometrySet::GeometrySet(GeometrySet&& set) + : m_vertexStreamAllocator(std::move(set.m_vertexStreamAllocator)) + , m_indexStreamAllocator(std::move(set.m_indexStreamAllocator)) + , m_vertexStreams(std::move(set.m_vertexStreams)) + , m_indexBuffer(std::move(set.m_indexBuffer)) { + } + + void GeometrySet::operator=(GeometrySet&& set) { + m_vertexStreamAllocator = std::move(set.m_vertexStreamAllocator); + m_indexStreamAllocator = std::move(set.m_indexStreamAllocator); + m_vertexStreams = std::move(set.m_vertexStreams); + m_indexBuffer = std::move(set.m_indexBuffer); + } + + GeometrySet& GraphicsAllocator::resolveSet(AllocationSet set) { + return m_geometrySets[set]; + } + + GeometrySet::GeometrySetSubAllocation::GeometrySetSubAllocation(GeometrySetSubAllocation&& allocation): + m_vertexAllocation(std::move(allocation.m_vertexAllocation)), + m_indexAllocation(std::move(allocation.m_vertexAllocation)), + m_geometrySet(allocation.m_geometrySet){ + } + + GeometrySet::GeometrySetSubAllocation::~GeometrySetSubAllocation() { + if(m_geometrySet) { + m_geometrySet->m_vertexStreamAllocator.free(m_vertexAllocation); + m_geometrySet->m_indexStreamAllocator.free(m_indexAllocation); + } + } + + GeometrySet::GeometrySetSubAllocation::GeometrySetSubAllocation() { + } + + GraphicsAllocator::GraphicsAllocator(ForgeRenderer* renderer) + : m_renderer(renderer) { + { + std::array streamDesc = { + GeometrySet::GeometryStreamDesc("opaque_position", ShaderSemantic::SEMANTIC_POSITION, sizeof(float3)), + GeometrySet::GeometryStreamDesc("opaque_tangent", ShaderSemantic::SEMANTIC_TANGENT, sizeof(float3)), + GeometrySet::GeometryStreamDesc("opaque_normal", ShaderSemantic::SEMANTIC_NORMAL, sizeof(float3)), + GeometrySet::GeometryStreamDesc("opaque_uv0", ShaderSemantic::SEMANTIC_TEXCOORD0, sizeof(float2)), + GeometrySet::GeometryStreamDesc("opaque_color", ShaderSemantic::SEMANTIC_COLOR, sizeof(float4)), + }; + m_geometrySets[AllocationSet::OpaqueSet] = GeometrySet(OpaqueVertexBufferSize, OpaqueIndexBufferSize, streamDesc); + } + { BufferDesc desc = {}; - desc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; + desc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; desc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; desc.mSize = ImmediateVertexBufferSize; desc.pName = "Immediate Vertex Buffer"; - addGPURingBuffer(renderer->Rend(), &desc, &m_transientVertexBuffer); - } + addGPURingBuffer(renderer->Rend(), &desc, &m_transientVertexBuffer); + } { BufferDesc desc = {}; - desc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; + desc.mDescriptors = DESCRIPTOR_TYPE_INDEX_BUFFER; desc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; desc.mSize = ImmediateIndexBufferSize; desc.pName = "Immediate Index Buffer"; - addGPURingBuffer(renderer->Rend(), &desc, &m_transientIndeciesBuffer); - } - } - - GraphicsAllocator::OffsetAllocHandle::OffsetAllocHandle(OffsetAllocator::Allocator* allocator, OffsetAllocator::Allocation allocation ,SharedBuffer buffer): - m_allocator(allocator), - m_allocation(allocation), - m_buffer(buffer) { - } - - GraphicsAllocator::OffsetAllocHandle::~OffsetAllocHandle() { - if(m_allocation.offset != OffsetAllocator::Allocation::NO_SPACE) { - ASSERT(m_allocator != nullptr); - m_allocator->free(m_allocation); + addGPURingBuffer(renderer->Rend(), &desc, &m_transientIndeciesBuffer); } - } + GPURingBufferOffset GraphicsAllocator::allocTransientVertexBuffer(uint32_t size) { - return getGPURingBufferOffset(m_transientVertexBuffer, size); + return getGPURingBufferOffset(m_transientVertexBuffer, size); } - GPURingBufferOffset GraphicsAllocator::allocTransientIndexBuffer(uint32_t size) { - return getGPURingBufferOffset(m_transientIndeciesBuffer, size); + GPURingBufferOffset GraphicsAllocator::allocTransientIndexBuffer(uint32_t size) { + return getGPURingBufferOffset(m_transientIndeciesBuffer, size); } - GraphicsAllocator::OffsetAllocHandle GraphicsAllocator::allocVertexFromSharedBuffer(uint32_t size) { - OffsetAllocator::Allocation alloc = m_vertexBufferAllocator.allocate(size); - return OffsetAllocHandle(&m_vertexBufferAllocator, alloc, m_sharedVertexBuffer); - } - GraphicsAllocator::OffsetAllocHandle GraphicsAllocator::allocIndeciesFromSharedBuffer(uint32_t size) { - OffsetAllocator::Allocation alloc = m_indexBufferAllocator.allocate(size); - return OffsetAllocHandle(&m_indexBufferAllocator, alloc, m_sharedIndexBuffer); - } -} + // GraphicsAllocator::OffsetAllocHandle GraphicsAllocator::allocVertexFromSharedBuffer(uint32_t size) { + // OffsetAllocator::Allocation alloc = m_vertexBufferAllocator.allocate(size); + // return OffsetAllocHandle(&m_vertexBufferAllocator, alloc, m_sharedVertexBuffer); + // } + // GraphicsAllocator::OffsetAllocHandle GraphicsAllocator::allocIndeciesFromSharedBuffer(uint32_t size) { + // OffsetAllocator::Allocation alloc = m_indexBufferAllocator.allocate(size); + // return OffsetAllocHandle(&m_indexBufferAllocator, alloc, m_sharedIndexBuffer); + // } +} // namespace hpl diff --git a/HPL2/sources/graphics/MeshUtility.cpp b/HPL2/sources/graphics/MeshUtility.cpp index 22736dc60..115213412 100644 --- a/HPL2/sources/graphics/MeshUtility.cpp +++ b/HPL2/sources/graphics/MeshUtility.cpp @@ -443,12 +443,11 @@ namespace hpl::MeshUtility { for (int i = 0; i < (int)vCoords.size(); ++i) { vCoords[i] -= vFirstCorner; } - std::array uvs = { - uv1, - uv2, - uv3, - uv4 - }; + std::array uvs; + uvs[0] = uv1; + uvs[1] = uv2; + uvs[2] = uv3; + uvs[3] = uv4; for (size_t i = 0; i < 4; i++) { position->Write(vertexBufIdx, v3ToF3(vCoords[i])); normal->Write(vertexBufIdx, float3(0.0f, 1.0f, 0.0f)); diff --git a/HPL2/sources/graphics/offsetAllocator.cpp b/HPL2/sources/graphics/offsetAllocator.cpp index 1f547f50c..ce1a046ec 100644 --- a/HPL2/sources/graphics/offsetAllocator.cpp +++ b/HPL2/sources/graphics/offsetAllocator.cpp @@ -50,14 +50,14 @@ namespace OffsetAllocator static constexpr uint32 MANTISSA_BITS = 3; static constexpr uint32 MANTISSA_VALUE = 1 << MANTISSA_BITS; static constexpr uint32 MANTISSA_MASK = MANTISSA_VALUE - 1; - + // Bin sizes follow floating point (exponent + mantissa) distribution (piecewise linear log approx) // This ensures that for each size class, the average overhead percentage stays the same uint32 uintToFloatRoundUp(uint32 size) { uint32 exp = 0; uint32 mantissa = 0; - + if (size < MANTISSA_VALUE) { // Denorm: 0..(MANTISSA_VALUE-1) @@ -68,18 +68,18 @@ namespace OffsetAllocator // Normalized: Hidden high bit always 1. Not stored. Just like float. uint32 leadingZeros = lzcnt_nonzero(size); uint32 highestSetBit = 31 - leadingZeros; - + uint32 mantissaStartBit = highestSetBit - MANTISSA_BITS; exp = mantissaStartBit + 1; mantissa = (size >> mantissaStartBit) & MANTISSA_MASK; - + uint32 lowBitsMask = (1 << mantissaStartBit) - 1; - + // Round up! if ((size & lowBitsMask) != 0) mantissa++; } - + return (exp << MANTISSA_BITS) + mantissa; // + allows mantissa->exp overflow for round up } @@ -87,7 +87,7 @@ namespace OffsetAllocator { uint32 exp = 0; uint32 mantissa = 0; - + if (size < MANTISSA_VALUE) { // Denorm: 0..(MANTISSA_VALUE-1) @@ -98,15 +98,15 @@ namespace OffsetAllocator // Normalized: Hidden high bit always 1. Not stored. Just like float. uint32 leadingZeros = lzcnt_nonzero(size); uint32 highestSetBit = 31 - leadingZeros; - + uint32 mantissaStartBit = highestSetBit - MANTISSA_BITS; exp = mantissaStartBit + 1; mantissa = (size >> mantissaStartBit) & MANTISSA_MASK; } - + return (exp << MANTISSA_BITS) | mantissa; } - + uint32 floatToUint(uint32 floatValue) { uint32 exponent = floatValue >> MANTISSA_BITS; @@ -166,6 +166,25 @@ namespace OffsetAllocator other.m_usedBinsTop = 0; } + void Allocator::operator=(Allocator &&other) { + m_size = other.m_size; + m_maxAllocs = other.m_maxAllocs; + m_freeStorage = other.m_freeStorage; + m_usedBinsTop = other.m_usedBinsTop; + m_nodes = other.m_nodes; + m_freeNodes = other.m_freeNodes; + m_freeOffset = other.m_freeOffset; + + memcpy(m_usedBins, other.m_usedBins, sizeof(uint8) * NUM_TOP_BINS); + memcpy(m_binIndices, other.m_binIndices, sizeof(NodeIndex) * NUM_LEAF_BINS); + + other.m_nodes = nullptr; + other.m_freeNodes = nullptr; + other.m_freeOffset = 0; + other.m_maxAllocs = 0; + other.m_usedBinsTop = 0; + } + void Allocator::reset() { m_freeStorage = 0; @@ -174,33 +193,33 @@ namespace OffsetAllocator for (uint32 i = 0 ; i < NUM_TOP_BINS; i++) m_usedBins[i] = 0; - + for (uint32 i = 0 ; i < NUM_LEAF_BINS; i++) m_binIndices[i] = Node::unused; - + if (m_nodes) delete[] m_nodes; if (m_freeNodes) delete[] m_freeNodes; m_nodes = new Node[m_maxAllocs]; m_freeNodes = new NodeIndex[m_maxAllocs]; - + // Freelist is a stack. Nodes in inverse order so that [0] pops first. for (uint32 i = 0; i < m_maxAllocs; i++) { m_freeNodes[i] = m_maxAllocs - i - 1; } - + // Start state: Whole storage as one big node // Algorithm will split remainders and push them back as smaller nodes insertNodeIntoBin(m_size, 0); } Allocator::~Allocator() - { + { delete[] m_nodes; delete[] m_freeNodes; } - + Allocation Allocator::allocate(uint32 size) { // Out of allocations? @@ -208,14 +227,14 @@ namespace OffsetAllocator { return {.offset = Allocation::NO_SPACE, .metadata = Allocation::NO_SPACE}; } - + // Round up to bin index to ensure that alloc >= bin // Gives us min bin index that fits the size uint32 minBinIndex = SmallFloat::uintToFloatRoundUp(size); - + uint32 minTopBinIndex = minBinIndex >> TOP_BINS_INDEX_SHIFT; uint32 minLeafBinIndex = minBinIndex & LEAF_BINS_INDEX_MASK; - + uint32 topBinIndex = minTopBinIndex; uint32 leafBinIndex = Allocation::NO_SPACE; @@ -224,12 +243,12 @@ namespace OffsetAllocator { leafBinIndex = findLowestSetBitAfter(m_usedBins[topBinIndex], minLeafBinIndex); } - + // If we didn't find space in top bin, we search top bin from +1 if (leafBinIndex == Allocation::NO_SPACE) { topBinIndex = findLowestSetBitAfter(m_usedBinsTop, minTopBinIndex + 1); - + // Out of space? if (topBinIndex == Allocation::NO_SPACE) { @@ -240,9 +259,9 @@ namespace OffsetAllocator // NOTE: This search can't fail since at least one leaf bit was set because the top bit was set. leafBinIndex = tzcnt_nonzero(m_usedBins[topBinIndex]); } - + uint32 binIndex = (topBinIndex << TOP_BINS_INDEX_SHIFT) | leafBinIndex; - + // Pop the top node of the bin. Bin top = node.next. uint32 nodeIndex = m_binIndices[binIndex]; Node& node = m_nodes[nodeIndex]; @@ -261,7 +280,7 @@ namespace OffsetAllocator { // Remove a leaf bin mask bit m_usedBins[topBinIndex] &= ~(1 << leafBinIndex); - + // All leaf bins empty? if (m_usedBins[topBinIndex] == 0) { @@ -269,13 +288,13 @@ namespace OffsetAllocator m_usedBinsTop &= ~(1 << topBinIndex); } } - + // Push back reminder N elements to a lower bin uint32 reminderSize = nodeTotalSize - size; if (reminderSize > 0) { uint32 newNodeIndex = insertNodeIntoBin(reminderSize, node.dataOffset + size); - + // Link nodes next to each other so that we can merge them later if both are free // And update the old next neighbor to point to the new node (in middle) if (node.neighborNext != Node::unused) m_nodes[node.neighborNext].neighborPrev = newNodeIndex; @@ -283,55 +302,55 @@ namespace OffsetAllocator m_nodes[newNodeIndex].neighborNext = node.neighborNext; node.neighborNext = newNodeIndex; } - + return {.offset = node.dataOffset, .metadata = nodeIndex}; } - + void Allocator::free(Allocation allocation) { ASSERT(allocation.metadata != Allocation::NO_SPACE); if (!m_nodes) return; - + uint32 nodeIndex = allocation.metadata; Node& node = m_nodes[nodeIndex]; - + // Double delete check ASSERT(node.used == true); - + // Merge with neighbors... uint32 offset = node.dataOffset; uint32 size = node.dataSize; - + if ((node.neighborPrev != Node::unused) && (m_nodes[node.neighborPrev].used == false)) { // Previous (contiguous) free node: Change offset to previous node offset. Sum sizes Node& prevNode = m_nodes[node.neighborPrev]; offset = prevNode.dataOffset; size += prevNode.dataSize; - + // Remove node from the bin linked list and put it in the freelist removeNodeFromBin(node.neighborPrev); - + ASSERT(prevNode.neighborNext == nodeIndex); node.neighborPrev = prevNode.neighborPrev; } - + if ((node.neighborNext != Node::unused) && (m_nodes[node.neighborNext].used == false)) { // Next (contiguous) free node: Offset remains the same. Sum sizes. Node& nextNode = m_nodes[node.neighborNext]; size += nextNode.dataSize; - + // Remove node from the bin linked list and put it in the freelist removeNodeFromBin(node.neighborNext); - + ASSERT(nextNode.neighborPrev == nodeIndex); node.neighborNext = nextNode.neighborNext; } uint32 neighborNext = node.neighborNext; uint32 neighborPrev = node.neighborPrev; - + // Insert the removed node to freelist #ifdef DEBUG_VERBOSE printf("Putting node %u into freelist[%u] (free)\n", nodeIndex, m_freeOffset + 1); @@ -358,10 +377,10 @@ namespace OffsetAllocator { // Round down to bin index to ensure that bin >= alloc uint32 binIndex = SmallFloat::uintToFloatRoundDown(size); - + uint32 topBinIndex = binIndex >> TOP_BINS_INDEX_SHIFT; uint32 leafBinIndex = binIndex & LEAF_BINS_INDEX_MASK; - + // Bin was empty before? if (m_binIndices[binIndex] == Node::unused) { @@ -369,7 +388,7 @@ namespace OffsetAllocator m_usedBins[topBinIndex] |= 1 << leafBinIndex; m_usedBinsTop |= 1 << topBinIndex; } - + // Take a freelist node and insert on top of the bin linked list (next = old top) uint32 topNodeIndex = m_binIndices[binIndex]; uint32 nodeIndex = m_freeNodes[m_freeOffset--]; @@ -379,7 +398,7 @@ namespace OffsetAllocator m_nodes[nodeIndex] = {.dataOffset = dataOffset, .dataSize = size, .binListNext = topNodeIndex}; if (topNodeIndex != Node::unused) m_nodes[topNodeIndex].binListPrev = nodeIndex; m_binIndices[binIndex] = nodeIndex; - + m_freeStorage += size; #ifdef DEBUG_VERBOSE printf("Free storage: %u (+%u) (insertNodeIntoBin)\n", m_freeStorage, size); @@ -387,11 +406,11 @@ namespace OffsetAllocator return nodeIndex; } - + void Allocator::removeNodeFromBin(uint32 nodeIndex) { Node &node = m_nodes[nodeIndex]; - + if (node.binListPrev != Node::unused) { // Easy case: We have previous node. Just remove this node from the middle of the list. @@ -401,13 +420,13 @@ namespace OffsetAllocator else { // Hard case: We are the first node in a bin. Find the bin. - + // Round down to bin index to ensure that bin >= alloc uint32 binIndex = SmallFloat::uintToFloatRoundDown(node.dataSize); - + uint32 topBinIndex = binIndex >> TOP_BINS_INDEX_SHIFT; uint32 leafBinIndex = binIndex & LEAF_BINS_INDEX_MASK; - + m_binIndices[binIndex] = node.binListNext; if (node.binListNext != Node::unused) m_nodes[node.binListNext].binListPrev = Node::unused; @@ -416,7 +435,7 @@ namespace OffsetAllocator { // Remove a leaf bin mask bit m_usedBins[topBinIndex] &= ~(1 << leafBinIndex); - + // All leaf bins empty? if (m_usedBins[topBinIndex] == 0) { @@ -425,7 +444,7 @@ namespace OffsetAllocator } } } - + // Insert the node to freelist #ifdef DEBUG_VERBOSE printf("Putting node %u into freelist[%u] (removeNodeFromBin)\n", nodeIndex, m_freeOffset + 1); @@ -442,7 +461,7 @@ namespace OffsetAllocator { if (allocation.metadata == Allocation::NO_SPACE) return 0; if (!m_nodes) return 0; - + return m_nodes[allocation.metadata].dataSize; } @@ -450,7 +469,7 @@ namespace OffsetAllocator { uint32 largestFreeRegion = 0; uint32 freeStorage = 0; - + // Out of allocations? -> Zero free space if (m_freeOffset > 0) { diff --git a/HPL2/sources/scene/SubMeshEntity.cpp b/HPL2/sources/scene/SubMeshEntity.cpp index 982cb6ab8..85d8e4a70 100644 --- a/HPL2/sources/scene/SubMeshEntity.cpp +++ b/HPL2/sources/scene/SubMeshEntity.cpp @@ -23,6 +23,7 @@ #include "graphics/ForgeRenderer.h" +#include "graphics/GraphicsAllocator.h" #include "graphics/GraphicsBuffer.h" #include "graphics/VertexBuffer.h" #include "graphics/Material.h" @@ -61,60 +62,49 @@ namespace hpl { , mpMaterialManager(apMaterialManager) { mbIsOneSided = mpSubMesh->GetIsOneSided(); mvOneSidedNormal = mpSubMesh->GetOneSidedNormal(); - if (mpMeshEntity->GetMesh()->GetSkeleton()) { - mpDynVtxBuffer = - mpSubMesh->GetVertexBuffer()->CreateCopy(eVertexBufferType_Hardware, eVertexBufferUsageType_Dynamic, eFlagBit_All); - } - - m_skinnedMesh = mpMeshEntity->GetMesh()->GetSkeleton(); - for (auto& stream : mpSubMesh->streamBuffers()) { - auto rawView = stream.m_buffer.CreateViewRaw(); - StreamBufferInfo& info = m_vertexStreams.emplace_back(); - info.m_stride = stream.m_stride; - info.m_semantic = stream.m_semantic; - info.m_numberElements = stream.m_numberElements; - if(m_skinnedMesh - && (stream.m_semantic == ShaderSemantic::SEMANTIC_POSITION || - stream.m_semantic == ShaderSemantic::SEMANTIC_TANGENT || - stream.m_semantic == ShaderSemantic::SEMANTIC_NORMAL - )) { - info.m_type = StreamBufferType::DynamicBuffer; - info.m_buffer.Load([&](Buffer** buffer) { - BufferLoadDesc loadDesc = {}; - loadDesc.ppBuffer = buffer; - loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; - loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; - loadDesc.mDesc.mSize = rawView.NumBytes() * ForgeRenderer::SwapChainLength; // will have a copy per frame - loadDesc.pData = rawView.rawByteSpan().data(); - addResource(&loadDesc, nullptr); - return true; - }); - } else { - info.m_type = StreamBufferType::StaticBuffer; - info.m_buffer = stream.CommitSharedBuffer(); + m_isSkinnedMesh = mpMeshEntity->GetMesh()->GetSkeleton(); + auto* graphicsAllocator = Interface::Get(); + ASSERT(graphicsAllocator); + + auto vertexStreams = mpSubMesh->streamBuffers(); + auto& indexStream = mpSubMesh->IndexStream(); + auto& opaqueSet = graphicsAllocator->resolveSet(GraphicsAllocator::AllocationSet::OpaqueSet); + + m_numberVertices = vertexStreams.begin()->m_numberElements; + m_numberIndecies = indexStream.m_numberElements; + + m_geometry = opaqueSet.allocate(m_numberVertices * (m_isSkinnedMesh ? 2 : 1), m_numberIndecies); + for(auto& localStream: vertexStreams) { + auto gpuStream = m_geometry->getStreamBySemantic(localStream.m_semantic); + ASSERT(gpuStream != m_geometry->vertexStreams().end()); + + BufferUpdateDesc updateDesc = { gpuStream->buffer().m_handle, gpuStream->stride() * m_geometry->vertextOffset(), gpuStream->stride() * m_numberVertices}; + beginUpdateResource(&updateDesc); + + GraphicsBuffer gpuBuffer(updateDesc); + auto dest = gpuBuffer.CreateViewRaw(); + auto source = localStream.m_buffer.CreateViewRaw(); + for(size_t i = 0; i < m_numberVertices; i++) { + auto sp = source.rawByteSpan().subspan(i * localStream.m_stride, std::min(gpuStream->stride(), localStream.m_stride)); + dest.WriteRaw(i * gpuStream->stride(), sp); } + endUpdateResource(&updateDesc, nullptr); } { - auto& info = mpSubMesh->IndexStream(); - auto rawView = info.m_buffer.CreateViewRaw(); - m_indexBuffer.Load([&](Buffer** buffer) { - BufferLoadDesc loadDesc = {}; - loadDesc.ppBuffer = buffer; - loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_INDEX_BUFFER; - loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_ONLY; - loadDesc.mDesc.mSize = rawView.NumBytes(); - loadDesc.pData = rawView.rawByteSpan().data(); - addResource(&loadDesc, nullptr); - return true; - }); - m_numberIndecies = info.m_numberElements; + BufferUpdateDesc updateDesc = { m_geometry->indexBuffer().m_handle, m_geometry->indexOffset() * GeometrySet::IndexBufferStride, GeometrySet::IndexBufferStride * m_numberIndecies}; + beginUpdateResource(&updateDesc); + GraphicsBuffer gpuBuffer(updateDesc); + auto dest = gpuBuffer.CreateIndexView(); + auto src = indexStream.m_buffer.CreateIndexView(); + for(size_t i = 0; i < m_numberIndecies; i++) { + dest.Write(i, src.Get(i)); + } + endUpdateResource(&updateDesc, nullptr); } + } cSubMeshEntity::~cSubMeshEntity() { - if (mpDynVtxBuffer) - hplDelete(mpDynVtxBuffer); - /* Clear any custom textures here*/ if (mpMaterial) mpMaterialManager->Destroy(mpMaterial); @@ -157,7 +147,7 @@ namespace hpl { //////////////////////////////////// // If it has dynamic mesh, update it. - if (m_skinnedMesh) { + if (m_isSkinnedMesh) { if (mpMeshEntity->mbSkeletonPhysicsSleeping && mbGraphicsUpdated) { return; } @@ -183,26 +173,17 @@ namespace hpl { auto bindNormalView = bindNormalIt->GetStructuredView(); auto bindTangentView = bindTangentIt->GetStructuredView(); - auto targetPositionIt = std::find_if(m_vertexStreams.begin(), m_vertexStreams.end(), [&](auto& stream) { - return stream.m_semantic == ShaderSemantic::SEMANTIC_POSITION; - }); - auto targetNormalIt = std::find_if(m_vertexStreams.begin(), m_vertexStreams.end(), [&](auto& stream) { - return stream.m_semantic == ShaderSemantic::SEMANTIC_NORMAL; - }); - auto targetTangentIt = std::find_if(m_vertexStreams.begin(), m_vertexStreams.end(), [&](auto& stream) { - return stream.m_semantic == ShaderSemantic::SEMANTIC_TANGENT; - }); + auto targetPositionIt = m_geometry->getStreamBySemantic(ShaderSemantic::SEMANTIC_POSITION); + auto targetNormalIt = m_geometry->getStreamBySemantic(ShaderSemantic::SEMANTIC_NORMAL); + auto targetTangentIt = m_geometry->getStreamBySemantic(ShaderSemantic::SEMANTIC_TANGENT); - ASSERT(targetPositionIt != m_vertexStreams.end() && - targetNormalIt != m_vertexStreams.end() && - targetTangentIt != m_vertexStreams.end() + ASSERT(targetPositionIt != m_geometry->vertexStreams().end() && + targetNormalIt != m_geometry->vertexStreams().end() && + targetTangentIt != m_geometry->vertexStreams().end() ); - ASSERT(targetPositionIt->m_type == StreamBufferType::DynamicBuffer); - ASSERT(targetNormalIt->m_type == StreamBufferType::DynamicBuffer); - ASSERT(targetTangentIt->m_type == StreamBufferType::DynamicBuffer); - BufferUpdateDesc positionUpdateDesc = { targetPositionIt->m_buffer.m_handle, m_activeCopy * (targetPositionIt->m_stride * targetPositionIt->m_numberElements), targetPositionIt->m_stride * targetPositionIt->m_numberElements}; - BufferUpdateDesc tangentUpdateDesc = { targetTangentIt->m_buffer.m_handle, m_activeCopy * (targetTangentIt->m_stride * targetTangentIt->m_numberElements), targetTangentIt->m_stride * targetTangentIt->m_numberElements }; - BufferUpdateDesc normalUpdateDesc = { targetNormalIt->m_buffer.m_handle, m_activeCopy * (targetNormalIt->m_stride * targetNormalIt->m_numberElements), targetNormalIt->m_stride * targetNormalIt->m_numberElements }; + BufferUpdateDesc positionUpdateDesc = { targetPositionIt->buffer().m_handle, m_activeCopy * (targetPositionIt->stride() * m_numberVertices), targetPositionIt->stride() * m_numberVertices}; + BufferUpdateDesc tangentUpdateDesc = { targetTangentIt->buffer().m_handle, m_activeCopy * (targetTangentIt->stride() * m_numberVertices), targetTangentIt->stride() * m_numberVertices}; + BufferUpdateDesc normalUpdateDesc = { targetNormalIt->buffer().m_handle, m_activeCopy * (targetNormalIt->stride() * m_numberVertices), targetNormalIt->stride() * m_numberVertices}; beginUpdateResource(&positionUpdateDesc); beginUpdateResource(&tangentUpdateDesc); beginUpdateResource(&normalUpdateDesc); @@ -210,9 +191,9 @@ namespace hpl { GraphicsBuffer positionMapping(positionUpdateDesc); GraphicsBuffer normalMapping(tangentUpdateDesc); GraphicsBuffer tangentMapping(normalUpdateDesc); - auto targetPositionView = positionMapping.CreateStructuredView(0, targetPositionIt->m_stride); - auto targetTangentView = tangentMapping.CreateStructuredView(0, targetTangentIt->m_stride); - auto targetNormalView = normalMapping.CreateStructuredView(0, targetNormalIt->m_stride); + auto targetPositionView = positionMapping.CreateStructuredView(0, targetPositionIt->stride()); + auto targetTangentView = tangentMapping.CreateStructuredView(0, targetTangentIt->stride()); + auto targetNormalView = normalMapping.CreateStructuredView(0, targetNormalIt->stride()); for(size_t i = 0; i < bindPositionIt->m_numberElements; i++) { @@ -257,33 +238,32 @@ namespace hpl { packet.m_indvidual.m_numStreams = 0; for(auto& ele: elements) { ShaderSemantic semantic = hplToForgeShaderSemantic(ele); - auto found = std::find_if(m_vertexStreams.begin(), m_vertexStreams.end(), [&](auto& stream) { - return stream.m_semantic == semantic; - }); - ASSERT(found != m_vertexStreams.end()); + auto found = m_geometry->getStreamBySemantic(semantic); + ASSERT(found != m_geometry->vertexStreams().end()); auto& stream = packet.m_indvidual.m_vertexStream[packet.m_indvidual.m_numStreams++]; - stream.m_buffer = &found->m_buffer; - stream.m_offset = 0; - if(found->m_type == StreamBufferType::DynamicBuffer) { - stream.m_offset = m_activeCopy * (found->m_numberElements * found->m_stride); + stream.m_buffer = &found->buffer(); + stream.m_offset = m_geometry->vertextOffset() * found->stride(); + switch(found->semantic()) { + case ShaderSemantic::SEMANTIC_POSITION: + case ShaderSemantic::SEMANTIC_NORMAL: + case ShaderSemantic::SEMANTIC_TANGENT: + stream.m_offset += (m_activeCopy * (m_numberVertices * found->stride())); + break; + default: + break; + } - stream.m_stride = found->m_stride; + + stream.m_stride = found->stride(); } - packet.m_indvidual.m_indexStream.m_offset = 0; - packet.m_indvidual.m_indexStream.buffer = &m_indexBuffer; + packet.m_indvidual.m_indexStream.m_offset = GeometrySet::IndexBufferStride * m_geometry->indexOffset(); + packet.m_indvidual.m_indexStream.buffer = &m_geometry->indexBuffer(); packet.m_numIndices = m_numberIndecies; return packet; } iVertexBuffer* cSubMeshEntity::GetVertexBuffer() { - if(mpDynVtxBuffer) - { - return mpDynVtxBuffer; - } - else - { - return mpSubMesh->GetVertexBuffer(); - } + return mpSubMesh->GetVertexBuffer(); } cBoundingVolume* cSubMeshEntity::GetBoundingVolume() diff --git a/HPL2/sources/system/Bootstrap.cpp b/HPL2/sources/system/Bootstrap.cpp index eb3bd880c..cea7e1288 100644 --- a/HPL2/sources/system/Bootstrap.cpp +++ b/HPL2/sources/system/Bootstrap.cpp @@ -71,11 +71,12 @@ namespace hpl { // core renderer initialization m_renderer.InitializeRenderer(&m_window); + // initialize gui rendering + initResourceLoaderInterface(m_renderer.Rend()); // initializes resources + // graphics allocator m_graphicsAlloc = std::make_unique(&m_renderer); - // initialize gui rendering - initResourceLoaderInterface(m_renderer.Rend()); // initializes resources m_renderer.InitializeResource(); gui::InitializeGui(m_renderer); @@ -90,7 +91,7 @@ namespace hpl { Interface::Register(m_primaryViewport.get()); Interface::Register(&m_inputManager); Interface::Register(&m_window); // storing as a singleton means we can only have one window ... - //Interface::Register(m_debug.get()); + Interface::Register(m_graphicsAlloc.get()); } void Bootstrap::Shutdown() { @@ -99,7 +100,7 @@ namespace hpl { Interface::UnRegister(&m_inputManager); Interface::UnRegister(&m_window); Interface::UnRegister(&m_updateEventLoop); - //Interface::UnRegister(m_debug.get()); + Interface::UnRegister(m_graphicsAlloc.get()); exitLog(); } From 7d47051a7fd2208eeff73f2b9ada3c9e11765dc4 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Tue, 31 Oct 2023 20:41:30 -0700 Subject: [PATCH 10/17] feat: rough working changes for textures .. Signed-off-by: Michael Pollind --- CMakeLists.txt | 5 +- HPL2/include/graphics/DrawPacket.h | 61 +- HPL2/include/graphics/ForgeHandles.h | 6 + HPL2/include/graphics/ForwardMaterial.h | 0 HPL2/include/graphics/GeometrySet.h | 88 + HPL2/include/graphics/GraphicsAllocator.h | 77 +- HPL2/include/graphics/IndexPool.h | 85 + HPL2/include/graphics/Material.h | 8 +- HPL2/include/graphics/MaterialDescriptor.h | 16 + HPL2/include/graphics/Renderer.h | 3 - HPL2/include/graphics/RendererDeferred.h | 4 +- HPL2/include/graphics/RendererForwardPlus.h | 182 ++ HPL2/include/graphics/RendererWireFrame.h | 6 - HPL2/include/graphics/SubMesh.h | 6 +- HPL2/include/graphics/offsetAllocator.h | 1 + HPL2/include/scene/Viewport.h | 3 + HPL2/resource/ShaderList.fsl | 16 + HPL2/resource/forward_diffuse.frag.fsl | 59 + HPL2/resource/forward_diffuse.vert.fsl | 45 + HPL2/resource/forward_resource.h.fsl | 15 + HPL2/resource/forward_shader_common.h.fsl | 66 + HPL2/resource/light_clusters_clear.comp.fsl | 10 + HPL2/resource/light_cull_resources.h.fsl | 16 + HPL2/resource/point_light_clusters.comp.fsl | 63 + HPL2/sources/graphics/DrawPacket.cpp | 34 +- HPL2/sources/graphics/GeometrySet.cpp | 111 ++ HPL2/sources/graphics/Graphics.cpp | 19 +- HPL2/sources/graphics/GraphicsAllocator.cpp | 89 - HPL2/sources/graphics/MeshUtility.cpp | 10 +- HPL2/sources/graphics/Renderable.cpp | 1 + HPL2/sources/graphics/RendererDeferred.cpp | 1609 +++++++++-------- HPL2/sources/graphics/RendererForwardPlus.cpp | 816 +++++++++ HPL2/sources/graphics/RendererWireFrame.cpp | 9 +- HPL2/sources/impl/LegacyVertexBuffer.cpp | 4 +- HPL2/sources/resources/MaterialManager.cpp | 2 +- HPL2/sources/scene/SubMeshEntity.cpp | 59 +- amnesia/game/LuxEffectRenderer.cpp | 10 +- 37 files changed, 2538 insertions(+), 1076 deletions(-) create mode 100644 HPL2/include/graphics/ForwardMaterial.h create mode 100644 HPL2/include/graphics/GeometrySet.h create mode 100644 HPL2/include/graphics/MaterialDescriptor.h create mode 100644 HPL2/resource/forward_diffuse.frag.fsl create mode 100644 HPL2/resource/forward_diffuse.vert.fsl create mode 100644 HPL2/resource/forward_resource.h.fsl create mode 100644 HPL2/resource/forward_shader_common.h.fsl create mode 100644 HPL2/resource/light_clusters_clear.comp.fsl create mode 100644 HPL2/resource/light_cull_resources.h.fsl create mode 100644 HPL2/resource/point_light_clusters.comp.fsl create mode 100644 HPL2/sources/graphics/GeometrySet.cpp create mode 100644 HPL2/sources/graphics/RendererForwardPlus.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 14feb8723..1e5559bbe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ include("${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake") add_definitions( -DUSE_THE_FORGE_LEGACY + -DUSE_FORWARD_PLUS_BACKEND # prototype forward renderer ) @@ -37,10 +38,6 @@ if(WIN32) add_compile_definitions("NOMINMAX=1") endif() -add_definitions( - -DUSE_THE_FORGE_LEGACY -) - option(COPY_GAME_ASSETS "copy games assets into output directory" OFF) option(WITH_TOOLS "build HPL2 with tools" ON) diff --git a/HPL2/include/graphics/DrawPacket.h b/HPL2/include/graphics/DrawPacket.h index 6f00f2215..5332a366d 100644 --- a/HPL2/include/graphics/DrawPacket.h +++ b/HPL2/include/graphics/DrawPacket.h @@ -1,45 +1,68 @@ #pragma once +#include "Common_3/Graphics/Interfaces/IGraphics.h" #include "graphics/ForgeHandles.h" #include "graphics/ForgeRenderer.h" +#include "graphics/GraphicsAllocator.h" +#include "graphics/GraphicsTypes.h" #include namespace hpl { class DrawPacket { public: static constexpr uint32_t MaxVertexBindings = 15; + enum DrawPacketType { Unknown, - IndvidualBindings, // everything will be bound indvidually for the moment until - UnifiedAllocatorBinding + DrawIndvidualBuffers, // everything will be bound indvidually for the moment until + DrawGeometryset }; - struct VertexStream { - SharedBuffer* m_buffer; - uint64_t m_offset; - uint32_t m_stride; + + struct IndvidualBindings { + uint32_t m_numIndices; + uint32_t m_numStreams; + struct { + SharedBuffer* m_buffer; + uint64_t m_offset; + uint32_t m_stride; + } m_vertexStream[MaxVertexBindings]; + struct { + SharedBuffer* buffer; + uint64_t m_offset; + } m_indexStream; }; - struct IndexStream { - SharedBuffer* buffer; - uint64_t m_offset; + + struct GeometrySetBinding { + uint32_t m_numStreams; + eVertexBufferElement m_elements[MaxVertexBindings]; + GraphicsAllocator::AllocationSet m_set; + GeometrySet::GeometrySetSubAllocation* m_subAllocation; + uint32_t m_numIndices; + uint32_t m_vertexOffset; + uint32_t m_indexOffset; }; + inline uint32_t numberOfIndecies() { + switch(m_type) { + case DrawPacketType::DrawGeometryset: + return m_unified.m_numIndices; + case DrawPacketType::DrawIndvidualBuffers: + return m_indvidual.m_numIndices; + default: + break; + } + return 0; + } + static void cmdBindBuffers(Cmd* cmd, ForgeRenderer::CommandResourcePool* resourcePool, DrawPacket* packet); DrawPacket() : m_type(DrawPacketType::Unknown) { } - DrawPacketType m_type; - uint32_t m_numIndices; union { - struct { - uint32_t m_numStreams; - VertexStream m_vertexStream[MaxVertexBindings]; - IndexStream m_indexStream; - } m_indvidual; - struct { - - } m_unified; + struct IndvidualBindings m_indvidual; + struct GeometrySetBinding m_unified; }; }; diff --git a/HPL2/include/graphics/ForgeHandles.h b/HPL2/include/graphics/ForgeHandles.h index 108e9b66c..caa7018fc 100644 --- a/HPL2/include/graphics/ForgeHandles.h +++ b/HPL2/include/graphics/ForgeHandles.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "engine/Event.h" @@ -622,6 +623,11 @@ namespace hpl { Renderer* m_renderer = nullptr; friend struct RefHandle; }; + + using SharedResourceVariant = std::variant; } static bool operator==(const SamplerDesc& lhs, const SamplerDesc& rhs) { diff --git a/HPL2/include/graphics/ForwardMaterial.h b/HPL2/include/graphics/ForwardMaterial.h new file mode 100644 index 000000000..e69de29bb diff --git a/HPL2/include/graphics/GeometrySet.h b/HPL2/include/graphics/GeometrySet.h new file mode 100644 index 000000000..982ef265b --- /dev/null +++ b/HPL2/include/graphics/GeometrySet.h @@ -0,0 +1,88 @@ +#pragma once + +#include "graphics/ForgeHandles.h" +#include "graphics/ForgeRenderer.h" +#include "graphics/offsetAllocator.h" + +#include "Common_3/Graphics/Interfaces/IGraphics.h" +#include "Common_3/Utilities/RingBuffer.h" +#include + +namespace hpl { + + class GeometrySet final { + public: + static constexpr uint32_t IndexBufferStride = sizeof(uint32_t); + + + struct GeometryStreamDesc { + const char* m_name; + ShaderSemantic m_semantic; + uint32_t m_stride; + }; + class GeometryStream final { + public: + GeometryStream(); + GeometryStream(GeometryStream&&); + void operator=(GeometryStream&& stream); + + GeometryStream(const GeometryStream&) = delete; + void operator=(GeometryStream& stream) = delete; + + inline ShaderSemantic semantic() { return m_semantic; } + inline uint32_t stride() { return m_stride; } + inline SharedBuffer& buffer() { return m_buffer; } + private: + ShaderSemantic m_semantic = ShaderSemantic::SEMANTIC_UNDEFINED; + uint32_t m_stride = 0; + SharedBuffer m_buffer; + friend class GeometrySet; + }; + + class GeometrySetSubAllocation final { + public: + ~GeometrySetSubAllocation(); + GeometrySetSubAllocation(); + GeometrySetSubAllocation(GeometrySetSubAllocation&& allocation); + GeometrySetSubAllocation(const GeometrySetSubAllocation& allocation) = delete; + + void operator=(GeometrySetSubAllocation&& allocation); + void operator=(const GeometrySetSubAllocation& allocation) = delete; + + inline SharedBuffer& indexBuffer() { return m_geometrySet->m_indexBuffer; } + inline std::span vertexStreams() { return m_geometrySet->m_vertexStreams; } + inline std::span::iterator getStreamBySemantic(ShaderSemantic semantic) {return m_geometrySet->getStreamBySemantic(semantic);} + inline uint32_t vertextOffset() { return m_vertexAllocation.offset; } + inline uint32_t indexOffset() { return m_indexAllocation.offset; } + + private: + OffsetAllocator::Allocation m_vertexAllocation; + OffsetAllocator::Allocation m_indexAllocation; + GeometrySet* m_geometrySet = nullptr; + friend class GeometrySet; + }; + + GeometrySet(GeometrySet&& set); + GeometrySet(const GeometrySet& set) = delete; + GeometrySet(); + explicit GeometrySet(uint32_t numElements, uint32_t numIndecies, std::span stream); + void cmdBindGeometrySet(Cmd* cmd, std::span semantics); + + inline std::span vertexStreams() { return m_vertexStreams; } + inline std::span::iterator getStreamBySemantic(ShaderSemantic semantic) { + return std::find_if(vertexStreams().begin(), vertexStreams().end(), [&](auto& stream) { + return stream.m_semantic == semantic; + }); + } + inline SharedBuffer& indexBuffer() { return m_indexBuffer; } + void operator=(GeometrySet&& set); + void operator=(const GeometrySet& set) = delete; + std::shared_ptr allocate(uint32_t numElements, uint32_t numIndecies); + private: + OffsetAllocator::Allocator m_vertexStreamAllocator; + OffsetAllocator::Allocator m_indexStreamAllocator; + folly::small_vector m_vertexStreams; + SharedBuffer m_indexBuffer; + friend class GeometryStream; + }; +} diff --git a/HPL2/include/graphics/GraphicsAllocator.h b/HPL2/include/graphics/GraphicsAllocator.h index ed56676fd..8b83ccf0e 100644 --- a/HPL2/include/graphics/GraphicsAllocator.h +++ b/HPL2/include/graphics/GraphicsAllocator.h @@ -1,96 +1,27 @@ #pragma once -#include "Common_3/Graphics/Interfaces/IGraphics.h" #include "graphics/ForgeHandles.h" #include "graphics/ForgeRenderer.h" #include "graphics/offsetAllocator.h" +#include "graphics/GeometrySet.h" +#include "Common_3/Graphics/Interfaces/IGraphics.h" #include "Common_3/Utilities/RingBuffer.h" #include namespace hpl { - class GeometrySet final { - public: - static constexpr uint32_t IndexBufferStride = sizeof(uint32_t); - - struct GeometryStreamDesc { - const char* m_name; - ShaderSemantic m_semantic; - uint32_t m_stride; - }; - class GeometryStream final { - public: - GeometryStream(); - GeometryStream(GeometryStream&&); - void operator=(GeometryStream&& stream); - - GeometryStream(const GeometryStream&) = delete; - void operator=(GeometryStream& stream) = delete; - - inline ShaderSemantic semantic() { return m_semantic; } - inline uint32_t stride() { return m_stride; } - inline SharedBuffer& buffer() { return m_buffer; } - - private: - ShaderSemantic m_semantic = ShaderSemantic::SEMANTIC_UNDEFINED; - uint32_t m_stride = 0; - SharedBuffer m_buffer; - friend class GeometrySet; - }; - - class GeometrySetSubAllocation final { - public: - - ~GeometrySetSubAllocation(); - GeometrySetSubAllocation(); - GeometrySetSubAllocation(GeometrySetSubAllocation&& allocation); - GeometrySetSubAllocation(const GeometrySetSubAllocation& allocation) = delete; - - void operator=(GeometrySetSubAllocation&& allocation); - void operator=(const GeometrySetSubAllocation& allocation) = delete; - - inline SharedBuffer& indexBuffer() { return m_geometrySet->m_indexBuffer; } - inline std::span vertexStreams() { return m_geometrySet->m_vertexStreams; } - inline std::span::iterator getStreamBySemantic(ShaderSemantic semantic) { - return std::find_if(vertexStreams().begin(), vertexStreams().end(), [&](auto& stream) { - return stream.m_semantic == semantic; - }); - } - inline uint32_t vertextOffset() { return m_vertexAllocation.offset; } - inline uint32_t indexOffset() { return m_indexAllocation.offset; } - private: - OffsetAllocator::Allocation m_vertexAllocation; - OffsetAllocator::Allocation m_indexAllocation; - GeometrySet* m_geometrySet = nullptr; - friend class GeometrySet; - }; - - GeometrySet(GeometrySet&& set); - GeometrySet(const GeometrySet& set) = delete; - GeometrySet(); - explicit GeometrySet(uint32_t numElements, uint32_t numIndecies, std::span stream); - - void operator=(GeometrySet&& set); - void operator=(const GeometrySet& set) = delete; - std::shared_ptr allocate(uint32_t numElements, uint32_t numIndecies); - private: - OffsetAllocator::Allocator m_vertexStreamAllocator; - OffsetAllocator::Allocator m_indexStreamAllocator; - folly::small_vector m_vertexStreams; - SharedBuffer m_indexBuffer; - friend class GeometryStream; - }; class GraphicsAllocator final { HPL_RTTI_CLASS(GraphicsAllocator , "{57396F88-B069-4CEB-AF7C-0A9419D165C3}") public: - GraphicsAllocator(ForgeRenderer* renderer); enum AllocationSet { OpaqueSet, NumOfAllocationSets }; + GraphicsAllocator(ForgeRenderer* renderer); + static constexpr uint32_t OpaqueVertexBufferSize = 1 << 25; static constexpr uint32_t OpaqueIndexBufferSize = 1 << 23; diff --git a/HPL2/include/graphics/IndexPool.h b/HPL2/include/graphics/IndexPool.h index 31b79dc19..ae63a6f51 100644 --- a/HPL2/include/graphics/IndexPool.h +++ b/HPL2/include/graphics/IndexPool.h @@ -1,9 +1,11 @@ #pragma once +#include "graphics/ForgeHandles.h" #include #include #include +#include #include namespace hpl { @@ -21,6 +23,7 @@ namespace hpl { folly::small_vector m_avaliable; }; + class IndexPoolHandle { public: explicit inline IndexPoolHandle(): m_pool(nullptr){} @@ -63,10 +66,92 @@ namespace hpl { handle.m_index = UINT32_MAX; return *this; } + + inline IndexPool* pool() { + return m_pool; + } private: uint32_t m_index = UINT32_MAX; IndexPool* m_pool = nullptr; }; + class IndexRingDisposable { + public: + struct DisposableResource { + IndexPoolHandle m_handle; + uint8_t m_count = 0; + + DisposableResource(IndexPoolHandle&& handler): m_handle(std::move(handler)) {}; + DisposableResource(DisposableResource&&) = default; + DisposableResource(const DisposableResource&) = delete; + void operator=(const DisposableResource&) = delete; + DisposableResource& operator=(DisposableResource&&) = default; + }; + + explicit inline IndexRingDisposable(uint32_t size) { + m_ring.resize(size); + } + void reset(std::function handler) { + m_index = ((++m_index) % m_ring.size()); + for (auto& resource : m_ring[m_index]) { + handler(resource.m_handle); + resource.m_count++; + if(resource.m_count <= m_ring.size()) { + m_ring[(m_index + 1) % m_ring.size()].emplace_back(std::move(resource)); + } + } + m_ring[m_index].clear(); + } + + void push(SharedResourceVariant resource, IndexPoolHandle&& handler) { + m_ring[m_index].emplace_back(DisposableResource(std::move(handler))); + } + + private: + uint32_t m_index = 0; + folly::small_vector, 4> m_ring; + }; + + template + class IndexResourceRingDisposable { + public: + struct DisposableResource { + T m_resource; + IndexPoolHandle m_handle; + uint8_t m_count = 0; + + DisposableResource(T&& resource, IndexPoolHandle&& handler): m_resource(std::move(resource)), m_handle(std::move(handler)) {}; + DisposableResource(DisposableResource&&) = default; + DisposableResource(const DisposableResource&) = delete; + void operator=(const DisposableResource&) = delete; + DisposableResource& operator=(DisposableResource&&) = default; + }; + + explicit IndexResourceRingDisposable(uint32_t size) { + m_ring.resize(size); + } + IndexResourceRingDisposable() { + } + + void reset(std::function resetHandle) { + m_index = ((++m_index) % m_ring.size()); + for (auto& resource : m_ring[m_index]) { + resetHandle(resource.m_resource, resource.m_handle); + resource.m_count++; + if(resource.m_count <= m_ring.size()) { + m_ring[(m_index + 1) % m_ring.size()].emplace_back(std::move(resource)); + } + } + m_ring[m_index].clear(); + } + + void push(T&& resource, IndexPoolHandle&& handler) { + m_ring[m_index].emplace_back(DisposableResource(std::move(resource), std::move(handler))); + } + + private: + uint32_t m_index = 0; + folly::small_vector, 4> m_ring; + }; } diff --git a/HPL2/include/graphics/Material.h b/HPL2/include/graphics/Material.h index 7a2ef76df..c3013769d 100644 --- a/HPL2/include/graphics/Material.h +++ b/HPL2/include/graphics/Material.h @@ -92,7 +92,7 @@ namespace hpl { MaterialIDCount }; - struct MaterialDescriptor final { + struct ShaderMaterialData final { MaterialID m_id = MaterialID::Unknown; union { MaterialDecal m_decal; @@ -216,11 +216,11 @@ namespace hpl { void Unload(){} void Destroy(){} - inline void SetDescriptor(const MaterialDescriptor& desc) { + inline void SetDescriptor(const ShaderMaterialData& desc) { m_descriptor = desc; IncreaseGeneration(); } - inline const MaterialDescriptor& Descriptor() const { + inline const ShaderMaterialData& Descriptor() const { return m_descriptor; } @@ -234,7 +234,7 @@ namespace hpl { eTextureFilter m_textureFilter = eTextureFilter::eTextureFilter_Nearest; cResources *mpResources; - MaterialDescriptor m_descriptor; + ShaderMaterialData m_descriptor; IndexPoolHandle m_handle; std::array m_image = {ImageResourceWrapper()}; diff --git a/HPL2/include/graphics/MaterialDescriptor.h b/HPL2/include/graphics/MaterialDescriptor.h new file mode 100644 index 000000000..001050002 --- /dev/null +++ b/HPL2/include/graphics/MaterialDescriptor.h @@ -0,0 +1,16 @@ +#pragma once + +#include "graphics/ForgeHandles.h" + +namespace hpl { + + class ShaderMaterialData { + public: + explicit ShaderMaterialData(); + class MaterialEntry { + + }; + private: + + }; +} // namespace hpl diff --git a/HPL2/include/graphics/Renderer.h b/HPL2/include/graphics/Renderer.h index 82828a100..64f518007 100644 --- a/HPL2/include/graphics/Renderer.h +++ b/HPL2/include/graphics/Renderer.h @@ -172,9 +172,6 @@ namespace hpl { float GetTimeCount(){ return mfTimeCount;} - virtual bool LoadData()=0; - virtual void DestroyData()=0; - virtual SharedRenderTarget GetOutputImage(uint32_t frameIndex, cViewport& viewport) { return SharedRenderTarget();} //Static settings. Must be set before renderer data load. diff --git a/HPL2/include/graphics/RendererDeferred.h b/HPL2/include/graphics/RendererDeferred.h index 43d959277..352138452 100644 --- a/HPL2/include/graphics/RendererDeferred.h +++ b/HPL2/include/graphics/RendererDeferred.h @@ -340,7 +340,7 @@ namespace hpl { cGraphics* apGraphics, cResources* apResources, std::shared_ptr debug); - ~cRendererDeferred(); + virtual ~cRendererDeferred(); inline ViewportData* GetSharedData(cViewport& viewport) { return m_boundViewportData.resolve(viewport); @@ -353,8 +353,6 @@ namespace hpl { return sharedData->m_gBuffer[frameIndex].m_outputBuffer; } - virtual bool LoadData() override; - virtual void DestroyData() override; virtual void Draw( Cmd* cmd, diff --git a/HPL2/include/graphics/RendererForwardPlus.h b/HPL2/include/graphics/RendererForwardPlus.h index dc469fc06..89d7ac1d6 100644 --- a/HPL2/include/graphics/RendererForwardPlus.h +++ b/HPL2/include/graphics/RendererForwardPlus.h @@ -1,7 +1,11 @@ #pragma once + #include "engine/RTTI.h" +#include "graphics/GraphicsTypes.h" +#include "graphics/IndexPool.h" +#include "graphics/offsetAllocator.h" #include "scene/Viewport.h" #include "scene/World.h" #include "windowing/NativeWindow.h" @@ -25,5 +29,183 @@ namespace hpl { class RendererForwardPlus : public iRenderer { HPL_RTTI_IMPL_CLASS(iRenderer, cRendererDeferred, "{A3E5E5A1-1F9C-4F5C-9B9B-5B9B9B5B9B9B}") public: + static constexpr TinyImageFormat DepthBufferFormat = TinyImageFormat_D32_SFLOAT_S8_UINT; + static constexpr TinyImageFormat NormalBufferFormat = TinyImageFormat_R16G16B16A16_SFLOAT; + static constexpr TinyImageFormat PositionBufferFormat = TinyImageFormat_R32G32B32A32_SFLOAT; + static constexpr TinyImageFormat SpecularBufferFormat = TinyImageFormat_R8G8_UNORM; + static constexpr TinyImageFormat ColorBufferFormat = TinyImageFormat_R8G8B8A8_UNORM; + static constexpr TinyImageFormat ShadowDepthBufferFormat = TinyImageFormat_D32_SFLOAT; + + static constexpr uint32_t MaxIndirectDrawArgs = 1024; + static constexpr uint32_t MaxViewportFrameDescriptors = 256; + static constexpr uint32_t MaxObjectUniforms = 4096; + + static constexpr uint32_t LightClusterWidth = 8; + static constexpr uint32_t LightClusterHeight = 8; + static constexpr uint32_t LightClusterLightCount = 128; + + static constexpr uint32_t PointLightCount = 1024; + static constexpr uint32_t MaxTextureCount = 4096; + static constexpr uint32_t MaxOpaqueCount = 512; + + struct ViewportData { + public: + ViewportData() = default; + ViewportData(const ViewportData&) = delete; + ViewportData(ViewportData&& buffer) + : m_size(buffer.m_size) + , m_outputBuffer(std::move(buffer.m_outputBuffer)) + , m_depthBuffer(std::move(buffer.m_depthBuffer)) + , m_testBuffer(std::move(buffer.m_testBuffer)) { + } + + ViewportData& operator=(const ViewportData&) = delete; + void operator=(ViewportData&& buffer) { + m_size = buffer.m_size; + m_outputBuffer = std::move(buffer.m_outputBuffer); + m_depthBuffer = std::move(buffer.m_depthBuffer); + m_testBuffer = std::move(buffer.m_testBuffer); + } + + uint2 m_size = uint2(0, 0); + std::array m_outputBuffer; + std::array m_testBuffer; + std::array m_depthBuffer; + }; + + + struct DiffuseMat { + uint m_texture[4]; + uint m_materialConfig; + float m_heightMapScale; + float m_hiehgtMapBias; + float m_frenselBias; + float m_frenselPow; + }; + + struct PointLightData { + mat4 m_mvp; + float3 m_lightPos; + uint m_config; + float4 m_lightColor; + float m_radius; + }; + + struct UniformPerFrameData { + mat4 m_invViewRotation; + mat4 m_viewMatrix; + mat4 m_invViewMatrix; + mat4 m_projectionMatrix; + mat4 m_viewProjectionMatrix; + + float worldFogStart; + float worldFogLength; + float oneMinusFogAlpha; + float fogFalloffExp; + float4 fogColor; + + float2 viewTexel; + float2 viewportSize; + float afT; + }; + + struct UniformObject { + float m_dissolveAmount; + uint m_materialIndex; + float m_lightLevel; + uint pad; + mat4 m_modelMat; + mat4 m_invModelMat; + mat4 m_uvMat; + }; + + enum LightType { + PointLight, + BoxLight, + }; + + struct PerFrameOption { + float2 m_size; + Matrix4 m_viewMat; + Matrix4 m_projectionMat; + }; + + RendererForwardPlus(cGraphics* apGraphics, cResources* apResources, std::shared_ptr debug); + + virtual ~RendererForwardPlus(); + virtual SharedRenderTarget GetOutputImage(uint32_t frameIndex, cViewport& viewport) override; + virtual void Draw( + Cmd* cmd, + const ForgeRenderer::Frame& context, + cViewport& viewport, + float afFrameTime, + cFrustum* apFrustum, + cWorld* apWorld, + cRenderSettings* apSettings, + bool abSendFrameBufferToPostEffects) override; + + uint32_t resolveObjectId( + const ForgeRenderer::Frame& frame, cMaterial* apMaterial, iRenderable* apObject, std::optional modelMatrix); + + private: + uint32_t updateFrameDescriptor(const ForgeRenderer::Frame& frame, Cmd* cmd, cWorld* apWorld, const PerFrameOption& options); + uint32_t resolveMaterialID(const ForgeRenderer::Frame& frame,cMaterial* material); + + std::array m_perFrameBuffer; + std::array m_objectUniformBuffer; + std::array m_indirectDrawArgsBuffer; + SharedBuffer m_opaqueMaterialBuffer; + + // light clusters + SharedRootSignature m_lightClusterRootSignature; + SharedPipeline m_PointLightClusterPipeline; + SharedPipeline m_clearClusterPipeline; + std::array m_perFrameLightCluster; + std::array m_lightClustersBuffer; + std::array m_lightClusterCountBuffer; + std::array m_pointLightBuffer; + std::array, ForgeRenderer::SwapChainLength> m_pointLightAttenutation; + + folly::F14ValueMap m_objectDescriptorLookup; + + UniqueViewportData m_boundViewportData; + cRenderList m_rendererList; + + uint32_t m_objectIndex = 0; + uint32_t m_activeFrame = 0; + uint32_t m_frameIndex = 0; + + SharedRootSignature m_diffuseRootSignature; + SharedPipeline m_diffusePipeline; + CommandSignature* m_cmdSignatureVBPass = NULL; + std::array m_opaqueFrameSet; + std::array m_opaqueConstSet; + + struct SceneMaterial { + struct SceneTextureEntry { + IndexPoolHandle m_handle; + SharedTexture m_texture; + }; + void* m_material = nullptr; + uint32_t m_version = 0; + uint8_t m_writeMask = 0; + MaterialID m_id; + + IndexPoolHandle m_materialIndex; + std::array m_sceneTextures; + }; + std::array m_sceneMaterial; + IndexResourceRingDisposable m_sceneTextureDisposable; + IndexRingDisposable m_indexResourceDisposable; + IndexPool m_sceneTexturePool; + IndexPool m_opaqueMaterialPool; + + SharedTexture m_emptyTexture; + SharedShader m_diffuseShader; + SharedShader m_pointlightClusterShader; + SharedShader m_clearClusterShader; + + SharedSampler m_nearestClampSampler; + }; } // namespace hpl diff --git a/HPL2/include/graphics/RendererWireFrame.h b/HPL2/include/graphics/RendererWireFrame.h index a50871b37..5b76c0266 100644 --- a/HPL2/include/graphics/RendererWireFrame.h +++ b/HPL2/include/graphics/RendererWireFrame.h @@ -30,15 +30,11 @@ namespace hpl { - //--------------------------------------------- - class iFrameBuffer; class iDepthStencilBuffer; class iTexture; class iLight; - //--------------------------------------------- - class cRendererWireFrame : public iRenderer { public: @@ -80,8 +76,6 @@ namespace hpl { cVector2l m_size = cVector2l(0, 0); std::array m_outputBuffer; }; - bool LoadData() override; - void DestroyData() override; virtual SharedRenderTarget GetOutputImage(uint32_t frameIndex, cViewport& viewport) override; private: diff --git a/HPL2/include/graphics/SubMesh.h b/HPL2/include/graphics/SubMesh.h index 07e8907dc..5c5ec767a 100644 --- a/HPL2/include/graphics/SubMesh.h +++ b/HPL2/include/graphics/SubMesh.h @@ -204,8 +204,12 @@ namespace hpl { void AddCollider(const MeshCollisionResource& def); std::span GetColliders(); inline std::span streamBuffers() {return m_vertexStreams; } + inline std::span::iterator getStreamBySemantic(ShaderSemantic semantic) { + return std::find_if(streamBuffers().begin(), streamBuffers().end(), [&](auto& stream) { + return stream.m_semantic == semantic; + }); + } inline IndexBufferInfo& IndexStream() {return m_indexStream; } - void SetIsCollideShape(bool abX) { m_collideShape = abX; } diff --git a/HPL2/include/graphics/offsetAllocator.h b/HPL2/include/graphics/offsetAllocator.h index 7a8f8e746..1a34f5292 100644 --- a/HPL2/include/graphics/offsetAllocator.h +++ b/HPL2/include/graphics/offsetAllocator.h @@ -1,5 +1,6 @@ // (C) Sebastian Aaltonen 2023 // MIT License (see file: LICENSE) +#pragma once //#define USE_16_BIT_OFFSETS diff --git a/HPL2/include/scene/Viewport.h b/HPL2/include/scene/Viewport.h index f63ab4679..4043c6efd 100644 --- a/HPL2/include/scene/Viewport.h +++ b/HPL2/include/scene/Viewport.h @@ -131,6 +131,9 @@ namespace hpl { const cVector2l GetSize() { return m_size; } + const uint2 GetSizeU2() { + return uint2(m_size.x, m_size.y); + } uint2 GetSizeU() const { return uint2(m_size.x, m_size.y); diff --git a/HPL2/resource/ShaderList.fsl b/HPL2/resource/ShaderList.fsl index dfb9921ed..b39e11d24 100644 --- a/HPL2/resource/ShaderList.fsl +++ b/HPL2/resource/ShaderList.fsl @@ -272,3 +272,19 @@ #frag final_posteffect.frag #include "final_posteffect.frag.fsl" #end + +#vert forward_diffuse.vert + #include "forward_diffuse.vert.fsl" +#end + +#frag forward_diffuse.frag + #include "forward_diffuse.frag.fsl" +#end + +#comp point_light_clusters.comp + #include "point_light_clusters.comp.fsl" +#end + +#comp light_clusters_clear.comp + #include "light_clusters_clear.comp.fsl" +#end diff --git a/HPL2/resource/forward_diffuse.frag.fsl b/HPL2/resource/forward_diffuse.frag.fsl new file mode 100644 index 000000000..cf90d92ae --- /dev/null +++ b/HPL2/resource/forward_diffuse.frag.fsl @@ -0,0 +1,59 @@ +#include "forward_resource.h.fsl" + +STRUCT(PsIn) +{ + DATA(float4, Position, SV_Position); + DATA(float3, pos, POSITION); + DATA(float2, uv, TEXCOORD0); + DATA(float3, normal, NORMAL); + DATA(float3, tangent, TANGENT); + DATA(float3, bitangent, BITANGENT); + DATA(FLAT(uint), drawId, TEXCOORD1); +}; + +STRUCT(PsOut) +{ + DATA(float4, diffuse, SV_Target0); + DATA(float4, test, SV_Target1); +}; + + +PsOut PS_MAIN(PsIn In) +{ + INIT_MAIN; + UniformObject object = Get(sceneObjects)[In.drawId]; + DiffuseMaterial diffuseMat = Get(opaqueMaterial)[MATERIAL_ID(object)]; + uint diffuseTextureId = DiffuseMaterial_DiffuseTexture_ID(diffuseMat); + + float4 diffuseColor = float4(0,0,0,1); + if(diffuseTextureId < SCENE_MAX_TEXTURE_COUNT) { + BeginNonUniformResourceIndex(diffuseTextureId, SCENE_MAX_TEXTURE_COUNT); + diffuseColor = SampleTex2D(Get(sceneTextures)[diffuseTextureId], Get(nearestClampSampler), In.uv.xy); + EndNonUniformResourceIndex(); + } + + float3 normalizedNormal = normalize(In.normal.xyz); + float2 texelPos = (In.Position.xy * Get(viewTexel)); + uint2 clusterCoords = uint2(floor(texelPos * float2(LIGHT_CLUSTER_WIDTH, LIGHT_CLUSTER_HEIGHT))); + uint numLightsInCluster = Get(lightClustersCount)[LIGHT_CLUSTER_COUNT_POS(clusterCoords.x, clusterCoords.y)]; + float4 result = float4(0,0,0,1); + for(uint j = 0; j < numLightsInCluster; j++) { + uint lightId = Get(lightClusters)[LIGHT_CLUSTER_DATA_POS(j, clusterCoords.x, clusterCoords.y)]; + PointLight pl = Get(pointLights)[lightId]; + float4 lightPosWorldSpace = float4(pl.lightPos.xyz, 1.0f); + float4 lightCameraSpace = mul(Get(viewMat), lightPosWorldSpace); + + float3 lightDir = (lightCameraSpace.xyz - In.pos) * (1.0 / pl.lightRadius); + + float attenuation = saturate(1.0f - dot(lightDir , lightDir)); + float3 normalLightDir = normalize(lightDir); + + float fLDotN = max(dot(normalizedNormal, normalLightDir), 0.0); + result += diffuseColor * (attenuation * fLDotN); + } + + PsOut Out; + Out.test.x = diffuseTextureId; + Out.diffuse = result; + RETURN(Out); +} diff --git a/HPL2/resource/forward_diffuse.vert.fsl b/HPL2/resource/forward_diffuse.vert.fsl new file mode 100644 index 000000000..0d27be40d --- /dev/null +++ b/HPL2/resource/forward_diffuse.vert.fsl @@ -0,0 +1,45 @@ +#include "forward_resource.h.fsl" + +STRUCT(VSInput) +{ + DATA(float3, Position, POSITION); + DATA(float2, TexCoord, TEXCOORD0); + DATA(float3, Normal, NORMAL); + DATA(float3, Tangent, TANGENT); + +}; + +STRUCT(VSOutput) +{ + DATA(float4, Position, SV_Position); + DATA(float3, pos, POSITION); + DATA(float2, uv, TEXCOORD0); + DATA(float3, normal, NORMAL); + DATA(float3, tangent, TANGENT); + DATA(float3, bitangent, BITANGENT); + + DATA(FLAT(uint), drawId, TEXCOORD1); +}; + +VSOutput VS_MAIN(VSInput In, SV_InstanceID(uint) InstanceID) +{ + INIT_MAIN; + VSOutput Out; + + float4x4 modelView = mul(Get(viewMat), Get(sceneObjects)[InstanceID].modelMat); + float4x4 modelViewPrj = mul(projMat, modelView); + + Out.pos = mul(modelView, float4(In.Position.xyz, 1.0)).xyz; + Out.uv = mul(Get(sceneObjects)[InstanceID].uvMat, float4(In.TexCoord, 0, 1.0)).xy; + + float3x3 normalMat = ToNormalMat(Get(sceneObjects)[InstanceID].invModelMat, Get(invViewMat)); + Out.normal = normalize(mul(normalMat, In.Normal.xyz)); + Out.tangent = normalize(mul(normalMat, In.Tangent.xyz)); + Out.bitangent = normalize(mul(normalMat, cross(In.Tangent.xyz, In.Normal.xyz))); + Out.drawId = InstanceID; + + float3 viewEye = mul(modelView, float4(In.Position.xyz, 1.0)).xyz; + Out.Position = mul(modelViewPrj, float4(In.Position.xyz, 1.0)); + RETURN(Out); +} + diff --git a/HPL2/resource/forward_resource.h.fsl b/HPL2/resource/forward_resource.h.fsl new file mode 100644 index 000000000..990bd6e6c --- /dev/null +++ b/HPL2/resource/forward_resource.h.fsl @@ -0,0 +1,15 @@ +#include "forward_shader_common.h.fsl" + +RES(SamplerState, nearestClampSampler, UPDATE_FREQ_NONE, s2, binding = 0); +RES(Buffer(UniformObject), sceneObjects, UPDATE_FREQ_NONE, t1, binding = 1); +RES(Buffer(DiffuseMaterial), opaqueMaterial, UPDATE_FREQ_NONE, t0, binding = 2); + +RES(Buffer(uint), lightClustersCount, UPDATE_FREQ_PER_FRAME, t2, binding = 3); +RES(Buffer(uint), lightClusters, UPDATE_FREQ_PER_FRAME, t3, binding = 4); +RES(Buffer(PointLight), pointLights, UPDATE_FREQ_PER_FRAME, t0, binding = 5); + +RES(Tex2D(float4), sceneTextures[SCENE_MAX_TEXTURE_COUNT], UPDATE_FREQ_NONE, t0, binding = 10); + +INLINE float3x3 ToNormalMat(float4x4 invModel, float4x4 invView) { + return transpose(mul(float3x3(invModel[0].xyz, invModel[1].xyz, invModel[2].xyz), float3x3(invView[0].xyz, invView[1].xyz, invView[2].xyz))); +} diff --git a/HPL2/resource/forward_shader_common.h.fsl b/HPL2/resource/forward_shader_common.h.fsl new file mode 100644 index 000000000..2048172a6 --- /dev/null +++ b/HPL2/resource/forward_shader_common.h.fsl @@ -0,0 +1,66 @@ +#ifndef SHADER_DEFS_H +#define SHADER_DEFS_H + +#define LIGHT_CLUSTER_WIDTH 8 +#define LIGHT_CLUSTER_HEIGHT 8 +#define LIGHT_CLUSTER_COUNT 128 + +#define POINT_LIGHT_MAX_COUNT 1024 +#define SCENE_MAX_TEXTURE_COUNT 4096 + +#define SCENE_OPAQUE_COUNT 512 + +#define LIGHT_CLUSTER_COUNT_POS(ix, iy) ( ((iy)*LIGHT_CLUSTER_WIDTH)+(ix) ) +#define LIGHT_CLUSTER_DATA_POS(il, ix, iy) ( LIGHT_CLUSTER_COUNT_POS(ix, iy)*LIGHT_CLUSTER_COUNT + (il) ) + +STRUCT(DiffuseMaterial) { + DATA(uint, tex[4], None); + DATA(uint, materialConfig, None); + DATA(float, heightMapScale, None); + DATA(float, heightMapBias, None); + DATA(float, frenselBias, None); + DATA(float, frenselPow, None); +}; +uint DiffuseMaterial_DiffuseTexture_ID(DiffuseMaterial mat) {return mat.tex[0];} + +STRUCT(UniformObject) +{ + DATA(float, dissolveAmount, None); + DATA(uint, materialID, None); + DATA(float, lightLevel, None); + DATA(uint, __pad1, None); + DATA(float4x4, modelMat, None); + DATA(float4x4, invModelMat, None); + DATA(float4x4, uvMat, None); +}; + +#define MATERIAL_ID(o) ((o).materialID) + +STRUCT(PointLight) { + DATA(float4x4, mvp, None); + DATA(float3, lightPos, none); + DATA(uint, config, none); + DATA(float4, lightColor, none); + DATA(float, lightRadius, none); +}; + +CBUFFER(perFrameConstants, UPDATE_FREQ_PER_FRAME, b0, binding = 0) +{ + DATA(float4x4, invViewRotationMat, None); + DATA(float4x4, viewMat, None); + DATA(float4x4, invViewMat, None); + DATA(float4x4, projMat, None); + DATA(float4x4, viewProjMat, None); + + DATA(float, worldFogStart, None); + DATA(float, worldFogLength, None); + DATA(float, oneMinusFogAlpha, None); + DATA(float, fogFalloffExp, None); + DATA(float4, worldFogColor, None); + + DATA(float2, viewTexel, None); + DATA(float2, viewportSize, None); + DATA(float, afT, None); +}; + +#endif diff --git a/HPL2/resource/light_clusters_clear.comp.fsl b/HPL2/resource/light_clusters_clear.comp.fsl new file mode 100644 index 000000000..6f4b634c4 --- /dev/null +++ b/HPL2/resource/light_clusters_clear.comp.fsl @@ -0,0 +1,10 @@ +#include "light_cull_resources.h.fsl" + +NUM_THREADS(LIGHT_CLUSTER_WIDTH, LIGHT_CLUSTER_HEIGHT, 1) +void CS_MAIN(SV_DispatchThreadID(uint3) threadID) +{ + INIT_MAIN; + AtomicStore(Get(lightClustersCount)[LIGHT_CLUSTER_COUNT_POS(threadID.x, threadID.y)], 0); + RETURN(); +} + diff --git a/HPL2/resource/light_cull_resources.h.fsl b/HPL2/resource/light_cull_resources.h.fsl new file mode 100644 index 000000000..db6785799 --- /dev/null +++ b/HPL2/resource/light_cull_resources.h.fsl @@ -0,0 +1,16 @@ +#include "forward_shader_common.h.fsl" + +#ifndef LIGHT_CULL_RESOURCES_H +#define LIGHT_CULL_RESOURCES_H + +PUSH_CONSTANT(uRootConstants, b0) +{ + DATA(uint2, windowSize, None); +}; + +RES(Buffer(PointLight), pointLights, UPDATE_FREQ_PER_FRAME, t0, binding = 2); + +RES(RWBuffer(atomic_uint), lightClustersCount, UPDATE_FREQ_PER_FRAME, u0, binding = 3); +RES(RWBuffer(atomic_uint), lightClusters, UPDATE_FREQ_PER_FRAME, u1, binding = 4); +#endif // LIGHT_CULL_RESOURCES_H + diff --git a/HPL2/resource/point_light_clusters.comp.fsl b/HPL2/resource/point_light_clusters.comp.fsl new file mode 100644 index 000000000..3b5ad4b0b --- /dev/null +++ b/HPL2/resource/point_light_clusters.comp.fsl @@ -0,0 +1,63 @@ +#include "light_cull_resources.h.fsl" + + +NUM_THREADS(LIGHT_CLUSTER_WIDTH, LIGHT_CLUSTER_HEIGHT, 1) +void CS_MAIN(SV_GroupThreadID(uint3) threadInGroupId, SV_GroupID(uint3) groupId) +{ + INIT_MAIN; + const float invClusterWidth = 1.0f / float(LIGHT_CLUSTER_WIDTH); + const float invClusterHeight = 1.0f / float(LIGHT_CLUSTER_HEIGHT); + const float2 windowSize = Get(windowSize); + + const float aspectRatio = windowSize.x / windowSize.y; + + PointLight lightData = Get(pointLights)[groupId.x]; + + float4 lightPosWorldSpace = float4(lightData.lightPos.xyz, 1.0f); + float4 lightPosClipSpace = mul(Get(viewProjMat), lightPosWorldSpace); + float invLightPosW = 1.0f / lightPosClipSpace.w; + float3 lightPos = lightPosClipSpace.xyz * invLightPosW; + + float fov = 2.0 * atan(1.0/Get(projMat)[1][1]); + float projRadius = 2.0f * lightData.lightRadius * (1 / tan(fov * 0.5f)) * invLightPosW; + projRadius *= windowSize.x > windowSize.y ? aspectRatio : 1 / aspectRatio; + + // Early exit light if it's behind the camera + if (lightPosClipSpace.w < 0.0f && -lightPosClipSpace.w > lightData.lightRadius) { + RETURN(); + } + + lightPos.x *= aspectRatio; + + // Cluster coordinates in post perspective clip space + float clusterLeft = float(threadInGroupId.x) * invClusterWidth; + float clusterTop = float(threadInGroupId.y) * invClusterHeight; + float clusterRight = clusterLeft + invClusterWidth; + float clusterBottom = clusterTop + invClusterHeight; + + // Transform coordinates from range [0..1] to range [-1..1] + clusterLeft = clusterLeft * 2.0f - 1.0f; + clusterTop = clusterTop * 2.0f - 1.0f; + clusterRight = clusterRight * 2.0f - 1.0f; + clusterBottom = clusterBottom * 2.0f - 1.0f; + + clusterLeft *= aspectRatio; + clusterRight *= aspectRatio; + + float clusterCenterX = (clusterLeft + clusterRight) * 0.5f; + float clusterCenterY = (clusterTop + clusterBottom) * 0.5f; + float clusterRadius = distance(float2(clusterLeft, clusterTop), float2(clusterRight, clusterBottom)) * 0.5f; + + // Check if the light projection overlaps the cluster: add the light bit to this cluster coords + float distanceToCenter = distance(float2(clusterCenterX, clusterCenterY), lightPos.xy); + + if (distanceToCenter - clusterRadius < abs(projRadius)) + { + // Increase light count on this cluster + uint lightArrayPos = 0; + AtomicAdd(Get(lightClustersCount)[LIGHT_CLUSTER_COUNT_POS(threadInGroupId.x, threadInGroupId.y)], 1, lightArrayPos); + + // Add light id to cluster + AtomicExchange(Get(lightClusters)[LIGHT_CLUSTER_DATA_POS(lightArrayPos, threadInGroupId.x, threadInGroupId.y)], groupId.x, lightArrayPos); + } +} diff --git a/HPL2/sources/graphics/DrawPacket.cpp b/HPL2/sources/graphics/DrawPacket.cpp index c6677c912..1283d71ac 100644 --- a/HPL2/sources/graphics/DrawPacket.cpp +++ b/HPL2/sources/graphics/DrawPacket.cpp @@ -1,4 +1,7 @@ #include "graphics/DrawPacket.h" +#include "Common_3/Graphics/Interfaces/IGraphics.h" +#include "graphics/Enum.h" +#include "graphics/GeometrySet.h" #include "impl/LegacyVertexBuffer.h" namespace hpl { @@ -7,24 +10,37 @@ namespace hpl { folly::small_vector vbBuffer; folly::small_vector vbOffsets; folly::small_vector vbStride; - switch(packet->m_type) { - case DrawPacketType::IndvidualBindings: { - for(size_t i = 0; i < packet->m_indvidual.m_numStreams; i++) { + switch (packet->m_type) { + case DrawPacketType::DrawIndvidualBuffers: + { + for (size_t i = 0; i < packet->m_indvidual.m_numStreams; i++) { auto& stream = packet->m_indvidual.m_vertexStream[i]; resourcePool->Push(*stream.m_buffer); vbBuffer.push_back(stream.m_buffer->m_handle); vbOffsets.push_back(stream.m_offset); vbStride.push_back(stream.m_stride); } + cmdBindVertexBuffer(cmd, packet->m_indvidual.m_numStreams, vbBuffer.data(), vbStride.data(), vbOffsets.data()); + cmdBindIndexBuffer(cmd, packet->m_indvidual.m_indexStream.buffer->m_handle, INDEX_TYPE_UINT32, packet->m_indvidual.m_indexStream.m_offset); break; } - default: - ASSERT(false); - break; + case DrawPacketType::DrawGeometryset: { + for(size_t i = 0; i < packet->m_unified.m_numStreams; i++) { + ShaderSemantic semantic = hplToForgeShaderSemantic(packet->m_unified.m_elements[i]); + auto stream = packet->m_unified.m_subAllocation->getStreamBySemantic(semantic); + vbBuffer.push_back(stream->buffer().m_handle); + vbOffsets.push_back((packet->m_unified.m_vertexOffset + packet->m_unified.m_subAllocation->vertextOffset()) * stream->stride()); + vbStride.push_back(stream->stride()); + } + cmdBindVertexBuffer(cmd, packet->m_unified.m_numStreams, vbBuffer.data(), vbStride.data(), vbOffsets.data()); + cmdBindIndexBuffer(cmd, packet->m_unified.m_subAllocation->indexBuffer().m_handle, INDEX_TYPE_UINT32, + (packet->m_unified.m_subAllocation->indexOffset() + packet->m_unified.m_indexOffset) * GeometrySet::IndexBufferStride ); + break; + } + default: + ASSERT(false); + break; } - - cmdBindVertexBuffer(cmd, packet->m_indvidual.m_numStreams, vbBuffer.data(), vbStride.data(), vbOffsets.data()); - cmdBindIndexBuffer(cmd, packet->m_indvidual.m_indexStream.buffer->m_handle, INDEX_TYPE_UINT32, packet->m_indvidual.m_indexStream.m_offset); } } diff --git a/HPL2/sources/graphics/GeometrySet.cpp b/HPL2/sources/graphics/GeometrySet.cpp new file mode 100644 index 000000000..c33834628 --- /dev/null +++ b/HPL2/sources/graphics/GeometrySet.cpp @@ -0,0 +1,111 @@ +#include "graphics/GeometrySet.h" +#include "graphics/offsetAllocator.h" + + +namespace hpl { + + void GeometrySet::cmdBindGeometrySet(Cmd* cmd, std::span semantics) { + folly::small_vector bufferArgs; + folly::small_vector offsetArgs; + folly::small_vector strideArgs; + for(auto& semantic: semantics) { + auto stream = getStreamBySemantic(semantic); + bufferArgs.push_back(stream->buffer().m_handle); + offsetArgs.push_back(0); + strideArgs.push_back(stream->stride()); + } + cmdBindVertexBuffer(cmd, bufferArgs.size(), bufferArgs.data(), strideArgs.data(), offsetArgs.data()); + cmdBindIndexBuffer(cmd, indexBuffer().m_handle, INDEX_TYPE_UINT32, 0); + } + + std::shared_ptr GeometrySet::allocate(uint32_t numElements, uint32_t numIndecies) { + auto subAllocation = std::make_shared(); + subAllocation->m_indexAllocation = m_indexStreamAllocator.allocate(numIndecies); + subAllocation->m_vertexAllocation = m_vertexStreamAllocator.allocate(numElements); + subAllocation->m_geometrySet = this; + + return subAllocation; + } + + GeometrySet::GeometryStream::GeometryStream(GeometryStream&& stream) + : m_semantic(stream.m_semantic) + , m_stride(stream.m_stride) + , m_buffer(std::move(stream.m_buffer)) { + } + + void GeometrySet::GeometryStream::operator=(GeometryStream&& stream){ + m_semantic = stream.m_semantic; + m_stride = stream.m_stride; + m_buffer = std::move(stream.m_buffer); + } + + GeometrySet::GeometrySet(uint32_t numElements, uint32_t numIndecies, std::span streamDesc) + : m_vertexStreamAllocator(numElements) + , m_indexStreamAllocator(numIndecies) { + for (auto& desc : streamDesc) { + auto& vertexStream = m_vertexStreams.emplace_back(); + vertexStream.m_stride = desc.m_stride; + vertexStream.m_semantic = desc.m_semantic; + vertexStream.m_buffer.Load([&](Buffer** buffer) { + BufferLoadDesc loadDesc = {}; + loadDesc.ppBuffer = buffer; + loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; + loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; + loadDesc.mDesc.mSize = numElements * vertexStream.m_stride; + loadDesc.mDesc.pName = desc.m_name; + addResource(&loadDesc, nullptr); + return true; + }); + } + m_indexBuffer.Load([&](Buffer** buffer) { + BufferLoadDesc loadDesc = {}; + loadDesc.ppBuffer = buffer; + loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_INDEX_BUFFER; + loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; + loadDesc.mDesc.mSize = numIndecies * sizeof(uint32_t); + loadDesc.mDesc.pName = "GeometrySet Index"; + addResource(&loadDesc, nullptr); + return true; + }); + } + + GeometrySet::GeometryStream::GeometryStream() { + } + + GeometrySet::GeometrySet() + : m_vertexStreamAllocator(0) + , m_indexStreamAllocator(0) { + } + + GeometrySet::GeometrySet(GeometrySet&& set) + : m_vertexStreamAllocator(std::move(set.m_vertexStreamAllocator)) + , m_indexStreamAllocator(std::move(set.m_indexStreamAllocator)) + , m_vertexStreams(std::move(set.m_vertexStreams)) + , m_indexBuffer(std::move(set.m_indexBuffer)) { + } + + void GeometrySet::operator=(GeometrySet&& set) { + m_vertexStreamAllocator = std::move(set.m_vertexStreamAllocator); + m_indexStreamAllocator = std::move(set.m_indexStreamAllocator); + m_vertexStreams = std::move(set.m_vertexStreams); + m_indexBuffer = std::move(set.m_indexBuffer); + } + + + GeometrySet::GeometrySetSubAllocation::GeometrySetSubAllocation(GeometrySetSubAllocation&& allocation): + m_vertexAllocation(std::move(allocation.m_vertexAllocation)), + m_indexAllocation(std::move(allocation.m_vertexAllocation)), + m_geometrySet(allocation.m_geometrySet){ + } + + GeometrySet::GeometrySetSubAllocation::~GeometrySetSubAllocation() { + if(m_geometrySet) { + m_geometrySet->m_vertexStreamAllocator.free(m_vertexAllocation); + m_geometrySet->m_indexStreamAllocator.free(m_indexAllocation); + } + } + + GeometrySet::GeometrySetSubAllocation::GeometrySetSubAllocation() { + } + +} diff --git a/HPL2/sources/graphics/Graphics.cpp b/HPL2/sources/graphics/Graphics.cpp index a01345e5f..c3a518baf 100644 --- a/HPL2/sources/graphics/Graphics.cpp +++ b/HPL2/sources/graphics/Graphics.cpp @@ -24,6 +24,7 @@ #include "engine/Updateable.h" #include "graphics/ForgeRenderer.h" +#include "graphics/RendererForwardPlus.h" #include "system/LowLevelSystem.h" #include "system/String.h" #include "system/Platform.h" @@ -88,7 +89,6 @@ namespace hpl { { if(mvRenderers[i]) { - mvRenderers[i]->DestroyData(); hplDelete(mvRenderers[i]) } } @@ -158,19 +158,12 @@ namespace hpl { mvRenderers.resize(2, NULL); m_debug = std::make_shared(Interface::Get()); - mvRenderers[eRenderer_Main] = new cRendererDeferred(this, apResources, m_debug); + #if USE_FORWARD_PLUS_BACKEND + mvRenderers[eRenderer_Main] = new RendererForwardPlus(this, apResources, m_debug); + #else + mvRenderers[eRenderer_Main] = new cRendererDeferred(this, apResources, m_debug); + #endif mvRenderers[eRenderer_WireFrame] = new cRendererWireFrame(this, apResources, m_debug); - - for(size_t i=0; iLoadData()==false) - { - FatalError("Renderer #%d could not be initialized! Make sure your graphic card drivers are up to date. Check log file for more information.\n", i); - } - } - } } else { diff --git a/HPL2/sources/graphics/GraphicsAllocator.cpp b/HPL2/sources/graphics/GraphicsAllocator.cpp index 81b1fbeda..abb509160 100644 --- a/HPL2/sources/graphics/GraphicsAllocator.cpp +++ b/HPL2/sources/graphics/GraphicsAllocator.cpp @@ -4,99 +4,10 @@ namespace hpl { - - std::shared_ptr GeometrySet::allocate(uint32_t numElements, uint32_t numIndecies) { - auto subAllocation = std::make_shared(); - subAllocation->m_indexAllocation = m_indexStreamAllocator.allocate(numIndecies); - subAllocation->m_vertexAllocation = m_vertexStreamAllocator.allocate(numElements); - subAllocation->m_geometrySet = this; - return subAllocation; - } - - GeometrySet::GeometryStream::GeometryStream(GeometryStream&& stream) - : m_semantic(stream.m_semantic) - , m_stride(stream.m_stride) - , m_buffer(std::move(stream.m_buffer)) { - } - - void GeometrySet::GeometryStream::operator=(GeometryStream&& stream){ - m_semantic = stream.m_semantic; - m_stride = stream.m_stride; - m_buffer = std::move(stream.m_buffer); - } - - GeometrySet::GeometrySet(uint32_t numElements, uint32_t numIndecies, std::span streamDesc) - : m_vertexStreamAllocator(numElements) - , m_indexStreamAllocator(numIndecies) { - for (auto& desc : streamDesc) { - auto& vertexStream = m_vertexStreams.emplace_back(); - vertexStream.m_stride = desc.m_stride; - vertexStream.m_semantic = desc.m_semantic; - vertexStream.m_buffer.Load([&](Buffer** buffer) { - BufferLoadDesc loadDesc = {}; - loadDesc.ppBuffer = buffer; - loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_VERTEX_BUFFER; - loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; - loadDesc.mDesc.mSize = numElements * vertexStream.m_stride; - loadDesc.mDesc.pName = desc.m_name; - addResource(&loadDesc, nullptr); - return true; - }); - } - m_indexBuffer.Load([&](Buffer** buffer) { - BufferLoadDesc loadDesc = {}; - loadDesc.ppBuffer = buffer; - loadDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_INDEX_BUFFER; - loadDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; - loadDesc.mDesc.mSize = numIndecies * sizeof(uint32_t); - loadDesc.mDesc.pName = "GeometrySet Index"; - addResource(&loadDesc, nullptr); - return true; - }); - } - - GeometrySet::GeometryStream::GeometryStream() { - } - - GeometrySet::GeometrySet() - : m_vertexStreamAllocator(0) - , m_indexStreamAllocator(0) { - } - - GeometrySet::GeometrySet(GeometrySet&& set) - : m_vertexStreamAllocator(std::move(set.m_vertexStreamAllocator)) - , m_indexStreamAllocator(std::move(set.m_indexStreamAllocator)) - , m_vertexStreams(std::move(set.m_vertexStreams)) - , m_indexBuffer(std::move(set.m_indexBuffer)) { - } - - void GeometrySet::operator=(GeometrySet&& set) { - m_vertexStreamAllocator = std::move(set.m_vertexStreamAllocator); - m_indexStreamAllocator = std::move(set.m_indexStreamAllocator); - m_vertexStreams = std::move(set.m_vertexStreams); - m_indexBuffer = std::move(set.m_indexBuffer); - } - GeometrySet& GraphicsAllocator::resolveSet(AllocationSet set) { return m_geometrySets[set]; } - GeometrySet::GeometrySetSubAllocation::GeometrySetSubAllocation(GeometrySetSubAllocation&& allocation): - m_vertexAllocation(std::move(allocation.m_vertexAllocation)), - m_indexAllocation(std::move(allocation.m_vertexAllocation)), - m_geometrySet(allocation.m_geometrySet){ - } - - GeometrySet::GeometrySetSubAllocation::~GeometrySetSubAllocation() { - if(m_geometrySet) { - m_geometrySet->m_vertexStreamAllocator.free(m_vertexAllocation); - m_geometrySet->m_indexStreamAllocator.free(m_indexAllocation); - } - } - - GeometrySet::GeometrySetSubAllocation::GeometrySetSubAllocation() { - } - GraphicsAllocator::GraphicsAllocator(ForgeRenderer* renderer) : m_renderer(renderer) { { diff --git a/HPL2/sources/graphics/MeshUtility.cpp b/HPL2/sources/graphics/MeshUtility.cpp index 115213412..630b97546 100644 --- a/HPL2/sources/graphics/MeshUtility.cpp +++ b/HPL2/sources/graphics/MeshUtility.cpp @@ -1,19 +1,19 @@ +#include "Common_3/Utilities/Math/MathTypes.h" +#include "FixPreprocessor.h" + #include "graphics/MeshUtility.h" #include "Common_3/Utilities/Log/Log.h" -#include "Common_3/Utilities/ThirdParty/OpenSource/ModifiedSonyMath/common.hpp" -#include "Common_3/Utilities/ThirdParty/OpenSource/ModifiedSonyMath/sse/vectormath.hpp" #include "graphics/GraphicsBuffer.h" #include "graphics/mikktspace.h" #include "math/Math.h" -#include "Common_3/Utilities/Math/MathTypes.h" -#include "FixPreprocessor.h" - #include #include +#include #include #include + namespace hpl::MeshUtility { namespace details { struct MikktSpaceUser { diff --git a/HPL2/sources/graphics/Renderable.cpp b/HPL2/sources/graphics/Renderable.cpp index 869fc282b..b820d9a4f 100644 --- a/HPL2/sources/graphics/Renderable.cpp +++ b/HPL2/sources/graphics/Renderable.cpp @@ -20,6 +20,7 @@ #include "graphics/Renderable.h" #include "math/Math.h" +#include "math/Frustum.h" #include "math/cFrustum.h" #include "system/LowLevelSystem.h" diff --git a/HPL2/sources/graphics/RendererDeferred.cpp b/HPL2/sources/graphics/RendererDeferred.cpp index b881e1493..97037a7e8 100644 --- a/HPL2/sources/graphics/RendererDeferred.cpp +++ b/HPL2/sources/graphics/RendererDeferred.cpp @@ -19,12 +19,11 @@ #include "graphics/RendererDeferred.h" - #include "engine/Event.h" #include "engine/Interface.h" +#include "graphics/DebugDraw.h" #include "graphics/DrawPacket.h" #include "graphics/ForgeHandles.h" -#include "graphics/DebugDraw.h" #include "graphics/MaterialResource.h" #include "math/cFrustum.h" #include "scene/ParticleEmitter.h" @@ -86,9 +85,9 @@ #include #include -#include "Common_3/Utilities/Math/MathTypes.h" -#include "Common_3/Resources/ResourceLoader/Interfaces/IResourceLoader.h" #include "Common_3/Graphics/Interfaces/IGraphics.h" +#include "Common_3/Resources/ResourceLoader/Interfaces/IResourceLoader.h" +#include "Common_3/Utilities/Math/MathTypes.h" #include "FixPreprocessor.h" namespace hpl { @@ -511,22 +510,15 @@ namespace hpl { enum eDefferredProgramMode { eDefferredProgramMode_Lights, eDefferredProgramMode_Misc, eDefferredProgramMode_LastEnum }; - cRendererDeferred::cRendererDeferred( - cGraphics* apGraphics, - cResources* apResources, - std::shared_ptr debug) - : iRenderer("Deferred", apGraphics, apResources), - m_debug(debug) { + cRendererDeferred::cRendererDeferred(cGraphics* apGraphics, cResources* apResources, std::shared_ptr debug) + : iRenderer("Deferred", apGraphics, apResources) + , m_debug(debug) { m_hbaoPlusPipeline = std::make_unique(); //////////////////////////////////// // Set up render specific things UVector3 shadowSizes[] = { - UVector3(128, 128, 1), - UVector3(256, 256, 1), - UVector3(256, 256, 1), - UVector3(512, 512, 1), - UVector3(1024, 1024, 1) + UVector3(128, 128, 1), UVector3(256, 256, 1), UVector3(256, 256, 1), UVector3(512, 512, 1), UVector3(1024, 1024, 1) }; int startSize = 2; if (mShadowMapResolution == eShadowMapResolution_Medium) { @@ -535,7 +527,6 @@ namespace hpl { startSize = 0; } - m_dissolveImage = mpResources->GetTextureManager()->Create2DImage("core_dissolve.tga", false); auto* forgeRenderer = Interface::Get(); @@ -1257,7 +1248,9 @@ namespace hpl { m_materialRootSignature.Load(forgeRenderer->Rend(), [&](RootSignature** signature) { RootSignatureDesc rootSignatureDesc = {}; const char* pStaticSamplersNames[] = { "nearestSampler", "refractionSampler", "dissolveSampler" }; - Sampler* pStaticSampler[] = { m_samplerPointClampToBorder.m_handle, m_samplerPointClampToEdge.m_handle, m_samplerPointWrap.m_handle }; + Sampler* pStaticSampler[] = { m_samplerPointClampToBorder.m_handle, + m_samplerPointClampToEdge.m_handle, + m_samplerPointWrap.m_handle }; rootSignatureDesc.mStaticSamplerCount = std::size(pStaticSamplersNames); rootSignatureDesc.ppStaticSamplerNames = pStaticSamplersNames; rootSignatureDesc.ppStaticSamplers = pStaticSampler; @@ -1381,7 +1374,6 @@ namespace hpl { RasterizerStateDesc rasterizerStateDesc = {}; rasterizerStateDesc.mCullMode = CULL_MODE_FRONT; - DepthStateDesc depthStateDesc = {}; depthStateDesc.mDepthTest = true; depthStateDesc.mDepthWrite = false; @@ -1686,7 +1678,7 @@ namespace hpl { #ifdef USE_THE_FORGE_LEGACY blendStateDesc.mMasks[0] = ALL; #else - blendStateDesc.mColorWriteMasks[0] = ColorMask::COLOR_MASK_ALL; + blendStateDesc.mColorWriteMasks[0] = ColorMask::COLOR_MASK_ALL; #endif blendStateDesc.mSrcFactors[0] = BC_ONE; blendStateDesc.mDstFactors[0] = BC_ONE; @@ -1729,7 +1721,6 @@ namespace hpl { addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipline); return true; }); - } // translucency pass @@ -2354,11 +2345,11 @@ namespace hpl { m_lightPerFrameSet[setIndex].Load(forgeRenderer->Rend(), [&](DescriptorSet** set) { DescriptorSetDesc perFrameDescSet{ m_lightPassRootSignature.m_handle, DESCRIPTOR_UPDATE_FREQ_PER_FRAME, - MaxViewportFrameDescriptors }; + MaxViewportFrameDescriptors }; addDescriptorSet(forgeRenderer->Rend(), &perFrameDescSet, set); return true; }); - for(uint32_t i = 0; i < MaxViewportFrameDescriptors; i++) { + for (uint32_t i = 0; i < MaxViewportFrameDescriptors; i++) { std::array params = {}; params[0].pName = "lightObjectBuffer"; params[0].ppBuffers = &m_lightPassBuffer[setIndex].m_handle; @@ -2400,13 +2391,13 @@ namespace hpl { return true; }); - shadowMapData.m_cmd.Load(forgeRenderer->Rend(), [&](Cmd** cmd) { + shadowMapData.m_cmd.Load(forgeRenderer->Rend(), [&](Cmd** cmd) { CmdDesc cmdDesc = {}; cmdDesc.pPool = shadowMapData.m_pool.m_handle; addCmd(forgeRenderer->Rend(), &cmdDesc, cmd); return true; }); - shadowMapData.m_shadowFence.Load(forgeRenderer->Rend(), [&](Fence** fence) { + shadowMapData.m_shadowFence.Load(forgeRenderer->Rend(), [&](Fence** fence) { addFence(forgeRenderer->Rend(), fence); return true; }); @@ -2417,7 +2408,8 @@ namespace hpl { m_shadowMapData[eShadowMapResolution_High].emplace_back(createShadowMap(shadowSizes[startSize + eShadowMapResolution_High])); } for (size_t i = 0; i < 32; ++i) { - m_shadowMapData[eShadowMapResolution_Medium].emplace_back(createShadowMap(shadowSizes[startSize + eShadowMapResolution_Medium])); + m_shadowMapData[eShadowMapResolution_Medium].emplace_back( + createShadowMap(shadowSizes[startSize + eShadowMapResolution_Medium])); } for (size_t i = 0; i < 32; ++i) { m_shadowMapData[eShadowMapResolution_Low].emplace_back(createShadowMap(shadowSizes[startSize + eShadowMapResolution_Low])); @@ -2448,13 +2440,6 @@ namespace hpl { cRendererDeferred::~cRendererDeferred() { } - bool cRendererDeferred::LoadData() { - return true; - } - - void cRendererDeferred::DestroyData() { - } - uint32_t cRendererDeferred::updateFrameDescriptor( const ForgeRenderer::Frame& frame, Cmd* cmd, cWorld* apWorld, const PerFrameOption& options) { uint32_t index = m_materialSet.m_frameIndex; @@ -2483,14 +2468,14 @@ namespace hpl { return index; } - void cRendererDeferred::cmdIlluminationPass(Cmd* cmd, + void cRendererDeferred::cmdIlluminationPass( + Cmd* cmd, const ForgeRenderer::Frame& frame, cRenderList& renderList, uint32_t frameDescriptorIndex, RenderTarget* depthBuffer, RenderTarget* outputBuffer, - AdditionalIlluminationPassOptions options - ) { + AdditionalIlluminationPassOptions options) { uint32_t materialObjectIndex = getDescriptorIndexFromName(m_materialRootSignature.m_handle, "materialRootConstant"); LoadActionsDesc loadActions = {}; loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; @@ -2501,7 +2486,7 @@ namespace hpl { cmdBindRenderTargets(cmd, targets.size(), targets.data(), depthBuffer, &loadActions, nullptr, nullptr, -1, -1); cmdSetViewport(cmd, 0.0f, 0.0f, outputBuffer->mWidth, outputBuffer->mHeight, 0.0f, 1.0f); cmdSetScissor(cmd, 0, 0, outputBuffer->mWidth, outputBuffer->mHeight); - cmdBindPipeline(cmd, options.m_invert ? m_solidIlluminationPipelineCW.m_handle: m_solidIlluminationPipelineCCW.m_handle); + cmdBindPipeline(cmd, options.m_invert ? m_solidIlluminationPipelineCW.m_handle : m_solidIlluminationPipelineCCW.m_handle); cmdBindDescriptorSet(cmd, frameDescriptorIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); @@ -2522,7 +2507,7 @@ namespace hpl { materialConst.m_sceneAlpha = illuminationItem->GetIlluminationAmount(); DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &drawPacket); cmdBindPushConstants(cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(cmd, drawPacket.m_numIndices, 0, 0); + cmdDrawIndexed(cmd, drawPacket.numberOfIndecies(), 0, 0); } } void cRendererDeferred::cmdLightPass( @@ -2545,7 +2530,7 @@ namespace hpl { uint32_t materialObjectIndex = getDescriptorIndexFromName(m_materialRootSignature.m_handle, "materialRootConstant"); folly::small_vector occlusionPlanes; - if(apWorld->GetFogActive() && apWorld->GetFogColor().a >= 1.0f && apWorld->GetFogCulling()) { + if (apWorld->GetFogActive() && apWorld->GetFogColor().a >= 1.0f && apWorld->GetFogCulling()) { cPlanef fogPlane; fogPlane.FromNormalPoint(apFrustum->GetForward(), apFrustum->GetOrigin() + apFrustum->GetForward() * -apWorld->GetFogEnd()); occlusionPlanes.push_back(fogPlane); @@ -2555,7 +2540,6 @@ namespace hpl { // Render Light Pass // -------------------------------------------------------------------- { - float fScreenArea = (float)(outputBuffer->mWidth * outputBuffer->mHeight); int mlMinLargeLightArea = (int)(MinLargeLightNormalizedArea * fScreenArea); @@ -2584,7 +2568,12 @@ namespace hpl { apFrustum, kLightRadiusMul_Medium); deferredLightData.m_clipRect = cMath::GetClipRectFromSphere( - deferredLightData.m_mtxViewSpaceRender.GetTranslation(), light->GetRadius(), apFrustum, cVector2l(outputBuffer->mWidth, outputBuffer->mHeight), true, 0); + deferredLightData.m_mtxViewSpaceRender.GetTranslation(), + light->GetRadius(), + apFrustum, + cVector2l(outputBuffer->mWidth, outputBuffer->mHeight), + true, + 0); break; } case eLightType_Spot: @@ -2597,7 +2586,12 @@ namespace hpl { light, apFrustum, kLightRadiusMul_Medium); - cMath::GetClipRectFromBV(deferredLightData.m_clipRect, *light->GetBoundingVolume(), apFrustum, cVector2l(outputBuffer->mWidth, outputBuffer->mHeight), 0); + cMath::GetClipRectFromBV( + deferredLightData.m_clipRect, + *light->GetBoundingVolume(), + apFrustum, + cVector2l(outputBuffer->mWidth, outputBuffer->mHeight), + 0); break; } default: @@ -2658,8 +2652,7 @@ namespace hpl { cFrustum* pLightFrustum = pLightSpot->GetFrustum(); std::vector shadowCasters; - if (castShadow && - detail::SetupShadowMapRendering(shadowCasters, apWorld, pLightFrustum, pLightSpot, occlusionPlanes)) { + if (castShadow && detail::SetupShadowMapRendering(shadowCasters, apWorld, pLightFrustum, pLightSpot, occlusionPlanes)) { auto findBestShadowMap = [&](eShadowMapResolution resolution, iLight* light) -> cRendererDeferred::ShadowMapData* { auto& shadowMapVec = m_shadowMapData[resolution]; uint32_t maxFrameDistance = 0; @@ -2718,7 +2711,8 @@ namespace hpl { RenderTargetBarrier{ shadowMapData->m_target.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_DEPTH_WRITE }, }; - cmdResourceBarrier(shadowMapData->m_cmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + cmdResourceBarrier( + shadowMapData->m_cmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); } LoadActionsDesc loadActions = {}; @@ -2726,7 +2720,15 @@ namespace hpl { loadActions.mLoadActionStencil = LOAD_ACTION_DONTCARE; loadActions.mClearDepth = { .depth = 1.0f, .stencil = 0 }; cmdBindRenderTargets( - shadowMapData->m_cmd.m_handle, 0, NULL, shadowMapData->m_target.m_handle, &loadActions, NULL, NULL, -1, -1); + shadowMapData->m_cmd.m_handle, + 0, + NULL, + shadowMapData->m_target.m_handle, + &loadActions, + NULL, + NULL, + -1, + -1); cmdSetViewport( shadowMapData->m_cmd.m_handle, 0.0f, @@ -2741,7 +2743,9 @@ namespace hpl { 0, shadowMapData->m_target.m_handle->mWidth, shadowMapData->m_target.m_handle->mHeight); - cmdBindPipeline(shadowMapData->m_cmd.m_handle, options.m_invert ? m_zPassShadowPipelineCCW.m_handle : m_zPassShadowPipelineCW.m_handle); + cmdBindPipeline( + shadowMapData->m_cmd.m_handle, + options.m_invert ? m_zPassShadowPipelineCCW.m_handle : m_zPassShadowPipelineCW.m_handle); uint32_t shadowFrameIndex = updateFrameDescriptor( frame, @@ -2756,12 +2760,12 @@ namespace hpl { eMaterialRenderMode renderMode = pObject->GetCoverageAmount() >= 1 ? eMaterialRenderMode_Z : eMaterialRenderMode_Z_Dissolve; cMaterial* pMaterial = pObject->GetMaterial(); - const MaterialDescriptor& descriptor = pMaterial->Descriptor(); + const ShaderMaterialData& descriptor = pMaterial->Descriptor(); std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0, eVertexBufferElement_Normal, eVertexBufferElement_Texture1Tangent }; - DrawPacket packet = pObject->ResolveDrawPacket(frame, targets); + DrawPacket packet = pObject->ResolveDrawPacket(frame, targets); if (packet.m_type == DrawPacket::Unknown || descriptor.m_id == MaterialID::Unknown) { return; } @@ -2770,8 +2774,11 @@ namespace hpl { materialConst.objectId = instance; DrawPacket::cmdBindBuffers(shadowMapData->m_cmd.m_handle, frame.m_resourcePool, &packet); cmdBindPushConstants( - shadowMapData->m_cmd.m_handle, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(shadowMapData->m_cmd.m_handle, packet.m_numIndices, 0, 0); + shadowMapData->m_cmd.m_handle, + m_materialRootSignature.m_handle, + materialObjectIndex, + &materialConst); + cmdDrawIndexed(shadowMapData->m_cmd.m_handle, packet.numberOfIndecies(), 0, 0); } { cmdBindRenderTargets(shadowMapData->m_cmd.m_handle, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); @@ -2779,7 +2786,8 @@ namespace hpl { RenderTargetBarrier{ shadowMapData->m_target.m_handle, RESOURCE_STATE_DEPTH_WRITE, RESOURCE_STATE_SHADER_RESOURCE }, }; - cmdResourceBarrier(shadowMapData->m_cmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + cmdResourceBarrier( + shadowMapData->m_cmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); } endCmd(shadowMapData->m_cmd.m_handle); QueueSubmitDesc submitDesc = {}; @@ -2843,9 +2851,8 @@ namespace hpl { switch (light->m_light->GetLightType()) { case eLightType_Point: { - uniformObjectData.m_common.m_mvp = cMath::ToForgeMatrix4( - cMath::MatrixMul( - viewProjectionMat, cMath::MatrixMul(light->m_light->GetWorldMatrix(), detail::GetLightMtx(*light)))); + uniformObjectData.m_common.m_mvp = cMath::ToForgeMatrix4(cMath::MatrixMul( + viewProjectionMat, cMath::MatrixMul(light->m_light->GetWorldMatrix(), detail::GetLightMtx(*light)))); cVector3f lightViewPos = cMath::MatrixMul(modelViewMtx, detail::GetLightMtx(*light)).GetTranslation(); const auto color = light->m_light->GetDiffuseColor(); @@ -2867,8 +2874,7 @@ namespace hpl { uniformObjectData.m_pointLight.m_radius = light->m_light->GetRadius(); uniformObjectData.m_pointLight.m_lightPos = float3(lightViewPos.x, lightViewPos.y, lightViewPos.z); uniformObjectData.m_pointLight.m_lightColor = float4(color.r, color.g, color.b, color.a); - cMatrixf mtxInvViewRotation = - cMath::MatrixMul(light->m_light->GetWorldMatrix(), invViewMat).GetTranspose(); + cMatrixf mtxInvViewRotation = cMath::MatrixMul(light->m_light->GetWorldMatrix(), invViewMat).GetTranspose(); uniformObjectData.m_pointLight.m_invViewRotation = cMath::ToForgeMatrix4(mtxInvViewRotation.GetTranspose()); break; } @@ -2881,9 +2887,8 @@ namespace hpl { cVector3f lightViewPos = cMath::MatrixMul(modelViewMtx, detail::GetLightMtx(*light)).GetTranslation(); const auto color = pLightSpot->GetDiffuseColor(); - uniformObjectData.m_common.m_mvp = cMath::ToForgeMatrix4( - cMath::MatrixMul( - viewProjectionMat, cMath::MatrixMul(light->m_light->GetWorldMatrix(), detail::GetLightMtx(*light)))); + uniformObjectData.m_common.m_mvp = cMath::ToForgeMatrix4(cMath::MatrixMul( + viewProjectionMat, cMath::MatrixMul(light->m_light->GetWorldMatrix(), detail::GetLightMtx(*light)))); if (light->m_shadowMapData) { uniformObjectData.m_common.m_config |= LightConfiguration::HasShadowMap; @@ -2909,7 +2914,8 @@ namespace hpl { params[paramCount].pName = "goboMap"; params[paramCount++].ppTextures = &light->m_light->GetGoboTexture()->GetTexture().m_handle; frame.m_resourcePool->Push(light->m_light->GetGoboTexture()->GetTexture()); - m_lightResources[frame.m_frameIndex][m_lightIndex].m_goboMap = light->m_light->GetGoboTexture()->GetTexture(); + m_lightResources[frame.m_frameIndex][m_lightIndex].m_goboMap = + light->m_light->GetGoboTexture()->GetTexture(); } else { params[paramCount].pName = "falloffMap"; params[paramCount++].ppTextures = &spotFallOffImage->GetTexture().m_handle; @@ -2939,7 +2945,8 @@ namespace hpl { } } - BufferUpdateDesc updateDesc = { m_lightPassBuffer[frame.m_frameIndex].m_handle, m_lightIndex* sizeof(UniformLightData) }; + BufferUpdateDesc updateDesc = { m_lightPassBuffer[frame.m_frameIndex].m_handle, + m_lightIndex * sizeof(UniformLightData) }; beginUpdateResource(&updateDesc); memcpy(updateDesc.pMappedData, &uniformObjectData, sizeof(UniformLightData)); endUpdateResource(&updateDesc, NULL); @@ -2956,20 +2963,14 @@ namespace hpl { loadActions.mLoadActionsColor[0] = LOAD_ACTION_CLEAR; loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; loadActions.mLoadActionStencil = LOAD_ACTION_CLEAR; - loadActions.mClearColorValues[0] = ClearValue{ .r = options.m_clearColor.getX(),.g = options.m_clearColor.getY(), .b = options.m_clearColor.getZ(),.a = options.m_clearColor.getW()}; + loadActions.mClearColorValues[0] = ClearValue{ .r = options.m_clearColor.getX(), + .g = options.m_clearColor.getY(), + .b = options.m_clearColor.getZ(), + .a = options.m_clearColor.getW() }; std::array targets = { outputBuffer, }; - cmdBindRenderTargets( - cmd, - targets.size(), - targets.data(), - depthBuffer, - &loadActions, - nullptr, - nullptr, - -1, - -1); + cmdBindRenderTargets(cmd, targets.size(), targets.data(), depthBuffer, &loadActions, nullptr, nullptr, -1, -1); } cmdSetViewport(cmd, 0.0f, 0.0f, outputBuffer->mWidth, outputBuffer->mHeight, 0.0f, 1.0f); cmdSetScissor(cmd, 0, 0, outputBuffer->mWidth, outputBuffer->mHeight); @@ -2988,7 +2989,12 @@ namespace hpl { params[paramCount++].ppTextures = &positionBuffer->pTexture; params[paramCount].pName = "specularMap"; params[paramCount++].ppTextures = &specularBuffer->pTexture; - updateDescriptorSet(frame.m_renderer->Rend(), frameDescriptorIndex, m_lightPerFrameSet[frame.m_frameIndex].m_handle, paramCount, params); + updateDescriptorSet( + frame.m_renderer->Rend(), + frameDescriptorIndex, + m_lightPerFrameSet[frame.m_frameIndex].m_handle, + paramCount, + params); } cmdBindDescriptorSet(cmd, frameDescriptorIndex, m_lightPerFrameSet[frame.m_frameIndex].m_handle); @@ -3006,34 +3012,41 @@ namespace hpl { std::array elements = { eVertexBufferElement_Position }; auto lightShape = GetLightShape(light->m_light, eDeferredShapeQuality_High); ASSERT(lightShape && "Light shape not found"); - DrawPacket packet = static_cast(lightShape)->resolveGeometryBinding(frame.m_currentFrame, elements); + DrawPacket packet = + static_cast(lightShape)->resolveGeometryBinding(frame.m_currentFrame, elements); DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &packet); cmdBindPipeline(cmd, options.m_invert ? m_lightStencilPipelineCW.m_handle : m_lightStencilPipelineCCW.m_handle); uint32_t instance = cmdBindLightDescriptor(light); // bind light descriptor light uniforms cmdBindPushConstants(cmd, m_lightPassRootSignature.m_handle, lightRootConstantIndex, &instance); - cmdDrawIndexed(cmd, packet.m_numIndices, 0, 0); + cmdDrawIndexed(cmd, packet.numberOfIndecies(), 0, 0); switch (light->m_light->GetLightType()) { case eLightType_Point: cmdBindPipeline( cmd, m_pointLightPipeline - [(options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW : LightPipelineVariants::LightPipelineVariant_CW) | LightPipelineVariants::LightPipelineVariant_StencilTest] + [(options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW + : LightPipelineVariants::LightPipelineVariant_CW) | + LightPipelineVariants::LightPipelineVariant_StencilTest] .m_handle); break; case eLightType_Spot: cmdBindPipeline( cmd, m_spotLightPipeline - [(options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW : LightPipelineVariants::LightPipelineVariant_CW) | LightPipelineVariants::LightPipelineVariant_StencilTest] + [(options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW + : LightPipelineVariants::LightPipelineVariant_CW) | + LightPipelineVariants::LightPipelineVariant_StencilTest] .m_handle); break; case eLightType_Box: cmdBindPipeline( cmd, m_boxLightPipeline - [(options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW : LightPipelineVariants::LightPipelineVariant_CW) | LightPipelineVariants::LightPipelineVariant_StencilTest] + [(options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW + : LightPipelineVariants::LightPipelineVariant_CW) | + LightPipelineVariants::LightPipelineVariant_StencilTest] .m_handle); break; default: @@ -3041,7 +3054,7 @@ namespace hpl { break; } cmdBindPushConstants(cmd, m_lightPassRootSignature.m_handle, lightRootConstantIndex, &instance); - cmdDrawIndexed(cmd, packet.m_numIndices, 0, 0); + cmdDrawIndexed(cmd, packet.numberOfIndecies(), 0, 0); { LoadActionsDesc loadActions = {}; loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; @@ -3053,29 +3066,18 @@ namespace hpl { cmdBindRenderTargets(cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); { std::array rtBarriers = { - RenderTargetBarrier{ - depthBuffer, RESOURCE_STATE_DEPTH_WRITE, RESOURCE_STATE_PRESENT }, + RenderTargetBarrier{ depthBuffer, RESOURCE_STATE_DEPTH_WRITE, RESOURCE_STATE_PRESENT }, }; cmdResourceBarrier(cmd, 0, NULL, 0, nullptr, rtBarriers.size(), rtBarriers.data()); } { std::array rtBarriers = { - RenderTargetBarrier{ - depthBuffer, RESOURCE_STATE_PRESENT, RESOURCE_STATE_DEPTH_WRITE }, + RenderTargetBarrier{ depthBuffer, RESOURCE_STATE_PRESENT, RESOURCE_STATE_DEPTH_WRITE }, }; cmdResourceBarrier(cmd, 0, NULL, 0, nullptr, rtBarriers.size(), rtBarriers.data()); } - cmdBindRenderTargets( - cmd, - targets.size(), - targets.data(), - depthBuffer, - &loadActions, - nullptr, - nullptr, - -1, - -1); + cmdBindRenderTargets(cmd, targets.size(), targets.data(), depthBuffer, &loadActions, nullptr, nullptr, -1, -1); } } cmdEndDebugMarker(cmd); @@ -3092,12 +3094,20 @@ namespace hpl { .m_handle); break; case eLightType_Spot: - cmdBindPipeline(cmd, m_spotLightPipeline[options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW - : LightPipelineVariants::LightPipelineVariant_CW].m_handle); + cmdBindPipeline( + cmd, + m_spotLightPipeline + [options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW + : LightPipelineVariants::LightPipelineVariant_CW] + .m_handle); break; case eLightType_Box: - cmdBindPipeline(cmd, m_boxLightPipeline[options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW - : LightPipelineVariants::LightPipelineVariant_CW].m_handle); + cmdBindPipeline( + cmd, + m_boxLightPipeline + [options.m_invert ? LightPipelineVariants::LightPipelineVariant_CCW + : LightPipelineVariants::LightPipelineVariant_CW] + .m_handle); break; default: ASSERT(false && "Unsupported light type"); @@ -3107,12 +3117,12 @@ namespace hpl { std::array targets = { eVertexBufferElement_Position }; auto lightShape = GetLightShape(light->m_light, eDeferredShapeQuality_High); ASSERT(lightShape && "Light shape not found"); - DrawPacket packet = static_cast(lightShape)->resolveGeometryBinding(frame.m_currentFrame, targets); + DrawPacket packet = static_cast(lightShape)->resolveGeometryBinding(frame.m_currentFrame, targets); uint32_t instance = cmdBindLightDescriptor(light); DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &packet); cmdBindPushConstants(cmd, m_lightPassRootSignature.m_handle, lightRootConstantIndex, &instance); - cmdDrawIndexed(cmd, packet.m_numIndices, 0, 0); + cmdDrawIndexed(cmd, packet.numberOfIndecies(), 0, 0); } cmdEndDebugMarker(cmd); } @@ -3144,7 +3154,10 @@ namespace hpl { cmdBindRenderTargets(cmd, targets.size(), targets.data(), depthBuffer, &loadActions, NULL, NULL, -1, -1); cmdSetViewport(cmd, 0.0f, 0.0f, colorBuffer->mWidth, colorBuffer->mHeight, 0.0f, 1.0f); cmdSetScissor(cmd, 0, 0, colorBuffer->mWidth, colorBuffer->mHeight); - cmdBindPipeline(cmd, options.m_invert ? m_materialSolidPass.m_solidDiffuseParallaxPipelineCW.m_handle: m_materialSolidPass.m_solidDiffuseParallaxPipeline.m_handle); + cmdBindPipeline( + cmd, + options.m_invert ? m_materialSolidPass.m_solidDiffuseParallaxPipelineCW.m_handle + : m_materialSolidPass.m_solidDiffuseParallaxPipeline.m_handle); cmdBindDescriptorSet(cmd, frameDescriptorIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); @@ -3165,7 +3178,7 @@ namespace hpl { materialConst.objectId = instance; DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &packet); cmdBindPushConstants(cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(cmd, packet.m_numIndices, 0, 0); + cmdDrawIndexed(cmd, packet.numberOfIndecies(), 0, 0); } cmdEndDebugMarker(cmd); } @@ -3189,21 +3202,24 @@ namespace hpl { for (auto& decalItem : m_rendererList.GetRenderableItems(eRenderListType_Decal)) { cMaterial* pMaterial = decalItem->GetMaterial(); std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0, eVertexBufferElement_Color0 }; - DrawPacket packet = decalItem->ResolveDrawPacket(frame, targets); + DrawPacket packet = decalItem->ResolveDrawPacket(frame, targets); if (pMaterial == nullptr || packet.m_type == DrawPacket::Unknown) { continue; } ASSERT(pMaterial->GetBlendMode() < eMaterialBlendMode_LastEnum && "Invalid blend mode"); ASSERT(pMaterial->Descriptor().m_id == MaterialID::Decal && "Invalid material type"); - cmdBindPipeline(cmd, options.m_invert ? m_decalPipelineCW[pMaterial->GetBlendMode()].m_handle : m_decalPipeline[pMaterial->GetBlendMode()].m_handle); + cmdBindPipeline( + cmd, + options.m_invert ? m_decalPipelineCW[pMaterial->GetBlendMode()].m_handle + : m_decalPipeline[pMaterial->GetBlendMode()].m_handle); MaterialRootConstant materialConst = {}; uint32_t instance = cmdBindMaterialAndObject(cmd, frame, pMaterial, decalItem); materialConst.objectId = instance; - //LegacyVertexBuffer::GeometryBinding binding; + // LegacyVertexBuffer::GeometryBinding binding; DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &packet); cmdBindPushConstants(cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(cmd, packet.m_numIndices, 0, 0); + cmdDrawIndexed(cmd, packet.numberOfIndecies(), 0, 0); } cmdEndDebugMarker(cmd); } @@ -3223,7 +3239,6 @@ namespace hpl { cMatrixf viewMat, cMatrixf projectionMat, AdditionalZPassOptions options) { - ASSERT(depthBuffer && "Depth buffer not created"); ASSERT(hiZBuffer && "Depth buffer not created"); @@ -3302,7 +3317,8 @@ namespace hpl { //////////////////////////////////////// // Update per viewport specific and set amtrix point // Skip this for non-decal translucent! This is because the water rendering might mess it up otherwise! - if (pMaterial == NULL || cMaterial::IsTranslucent(pMaterial->Descriptor().m_id) == false || pMaterial->Descriptor().m_id == MaterialID::Decal) { + if (pMaterial == NULL || cMaterial::IsTranslucent(pMaterial->Descriptor().m_id) == false || + pMaterial->Descriptor().m_id == MaterialID::Decal) { // skip rendering if the update return false if (pObject->UpdateGraphicsForViewport(apFrustum, frameTime) == false) { return; @@ -3373,12 +3389,7 @@ namespace hpl { static_cast(depthBuffer->mHeight), 0.0f, 1.0f); - cmdSetScissor( - m_prePassCmd.m_handle, - 0, - 0, - static_cast(depthBuffer->mWidth), - static_cast(depthBuffer->mHeight)); + cmdSetScissor(m_prePassCmd.m_handle, 0, 0, static_cast(depthBuffer->mWidth), static_cast(depthBuffer->mHeight)); cmdBindPipeline(m_prePassCmd.m_handle, options.m_invert ? m_zPassPipelineCW.m_handle : m_zPassPipelineCCW.m_handle); cmdBindDescriptorSet(m_prePassCmd.m_handle, frameDescriptorIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); @@ -3408,7 +3419,7 @@ namespace hpl { eVertexBufferElement_Normal, eVertexBufferElement_Texture1Tangent }; DrawPacket packet = test.m_renderable->ResolveDrawPacket(frame, targets); - if(packet.m_type == DrawPacket::Unknown) { + if (packet.m_type == DrawPacket::Unknown) { continue; } MaterialRootConstant materialConst = {}; @@ -3416,7 +3427,7 @@ namespace hpl { materialConst.objectId = instance; DrawPacket::cmdBindBuffers(m_prePassCmd.m_handle, frame.m_resourcePool, &packet); cmdBindPushConstants(m_prePassCmd.m_handle, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(m_prePassCmd.m_handle, packet.m_numIndices, 0, 0); + cmdDrawIndexed(m_prePassCmd.m_handle, packet.numberOfIndecies(), 0, 0); } uniformPropBlock.maxMipLevel = hiZBuffer->mMipLevels - 1; @@ -3443,9 +3454,8 @@ namespace hpl { if (TypeInfo::IsType(*query.m_renderable)) { cBillboard* pBillboard = static_cast(query.m_renderable); - auto mvp = cMath::ToForgeMatrix4( - cMath::MatrixMul( - viewProj, cMath::MatrixMul(pBillboard->GetWorldMatrix(), cMath::MatrixScale(pBillboard->GetHaloSourceSize())))); + auto mvp = cMath::ToForgeMatrix4(cMath::MatrixMul( + viewProj, cMath::MatrixMul(pBillboard->GetWorldMatrix(), cMath::MatrixScale(pBillboard->GetHaloSourceSize())))); BufferUpdateDesc updateDesc = { m_occlusionUniformBuffer.m_handle, m_occlusionIndex * sizeof(mat4) }; beginUpdateResource(&updateDesc); @@ -3461,14 +3471,14 @@ namespace hpl { queryDesc.mIndex = queryIndex++; cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineOcclusionQuery.m_handle); cmdBeginQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); - cmdDrawIndexed(m_prePassCmd.m_handle, packet.m_numIndices, 0, 0); + cmdDrawIndexed(m_prePassCmd.m_handle, packet.numberOfIndecies(), 0, 0); cmdEndQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); query.m_queryIndex = queryDesc.mIndex; queryDesc.mIndex = queryIndex++; cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineMaxOcclusionQuery.m_handle); cmdBeginQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); - cmdDrawIndexed(m_prePassCmd.m_handle, packet.m_numIndices, 0, 0); + cmdDrawIndexed(m_prePassCmd.m_handle, packet.numberOfIndecies(), 0, 0); cmdEndQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, &queryDesc); query.m_maxQueryIndex = queryDesc.mIndex; @@ -3548,7 +3558,8 @@ namespace hpl { cmdResourceBarrier(m_prePassCmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); } { - std::array rtBarriers = { RenderTargetBarrier { hiZBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE } }; + std::array rtBarriers = { RenderTargetBarrier{ + hiZBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE } }; cmdResourceBarrier(m_prePassCmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); } cmdEndDebugMarker(m_prePassCmd.m_handle); @@ -3572,7 +3583,8 @@ namespace hpl { cmdBindPipeline(m_prePassCmd.m_handle, m_pipelineAABBOcclusionTest.m_handle); cmdDispatch(m_prePassCmd.m_handle, static_cast(uniformTest.size() / 128) + 1, 1, 1); { - std::array rtBarriers = { RenderTargetBarrier { hiZBuffer, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS } }; + std::array rtBarriers = { RenderTargetBarrier{ + hiZBuffer, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS } }; cmdResourceBarrier(m_prePassCmd.m_handle, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); } } @@ -3580,7 +3592,6 @@ namespace hpl { cmdResolveQuery(m_prePassCmd.m_handle, m_occlusionQuery.m_handle, m_occlusionReadBackBuffer.m_handle, 0, queryIndex); endCmd(m_prePassCmd.m_handle); - // Submit the gpu work. QueueSubmitDesc submitDesc = {}; submitDesc.mCmdCount = 1; @@ -3646,17 +3657,16 @@ namespace hpl { eVertexBufferElement_Normal, eVertexBufferElement_Texture1Tangent }; DrawPacket drawPacket = renderable->ResolveDrawPacket(frame, targets); - if(drawPacket.m_type == DrawPacket::Unknown) { + if (drawPacket.m_type == DrawPacket::Unknown) { continue; } - MaterialRootConstant materialConst = {}; uint32_t instance = cmdBindMaterialAndObject(cmd, frame, pMaterial, renderable); materialConst.objectId = instance; DrawPacket::cmdBindBuffers(frame.m_cmd, frame.m_resourcePool, &drawPacket); cmdBindPushConstants(cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(cmd, drawPacket.m_numIndices, 0, 0); + cmdDrawIndexed(cmd, drawPacket.numberOfIndecies(), 0, 0); } } } @@ -3665,11 +3675,7 @@ namespace hpl { } uint32_t cRendererDeferred::cmdBindMaterialAndObject( - Cmd* cmd, - const ForgeRenderer::Frame& frame, - cMaterial* apMaterial, - iRenderable* apObject, - std::optional modelMatrix) { + Cmd* cmd, const ForgeRenderer::Frame& frame, cMaterial* apMaterial, iRenderable* apObject, std::optional modelMatrix) { uint32_t id = folly::hash::fnv32_buf( reinterpret_cast(apObject), sizeof(apObject), @@ -3692,7 +3698,8 @@ namespace hpl { BufferUpdateDesc updateDesc = { m_materialSet.m_materialUniformBuffer.m_handle, apMaterial->Index() * sizeof(hpl::material::UniformMaterialBlock) }; beginUpdateResource(&updateDesc); - (*reinterpret_cast(updateDesc.pMappedData)) = material::UniformMaterialBlock::CreateFromMaterial(*apMaterial); + (*reinterpret_cast(updateDesc.pMappedData)) = + material::UniformMaterialBlock::CreateFromMaterial(*apMaterial); endUpdateResource(&updateDesc, NULL); std::array params{}; @@ -3756,7 +3763,8 @@ namespace hpl { } else { float fDist = cMath::Vector3Dist(light->GetWorldPosition(), vCenterPos); - fLightAmount += maxColorValue(light->GetDiffuseColor()) * cMath::Max(1.0f - (fDist / light->GetRadius()), 0.0f); + fLightAmount += + maxColorValue(light->GetDiffuseColor()) * cMath::Max(1.0f - (fDist / light->GetRadius()), 0.0f); } if (fLightAmount >= 1.0f) { @@ -3785,408 +3793,466 @@ namespace hpl { return index; } -void cRendererDeferred::RebuildGBuffer(ForgeRenderer& renderer, GBuffer& buffer, uint32_t width, uint32_t height) { - ClearValue optimizedColorClearBlack = { { 0.0f, 0.0f, 0.0f, 0.0f } }; - auto deferredRenderTargetDesc = [&]() { - RenderTargetDesc renderTarget = {}; - renderTarget.mArraySize = 1; - renderTarget.mClearValue = optimizedColorClearBlack; - renderTarget.mDepth = 1; - renderTarget.mDescriptors = DESCRIPTOR_TYPE_TEXTURE; - renderTarget.mWidth = width; - renderTarget.mHeight = height; - renderTarget.mSampleCount = SAMPLE_COUNT_1; - renderTarget.mSampleQuality = 0; - renderTarget.mStartState = RESOURCE_STATE_SHADER_RESOURCE; - return renderTarget; - }; - buffer.m_hizDepthBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { - RenderTargetDesc renderTargetDesc = {}; - renderTargetDesc.mArraySize = 1; - renderTargetDesc.mDepth = 1; - renderTargetDesc.mMipLevels = std::min(std::floor(std::log2(std::max(width, height))), MaxHiZMipLevels); - renderTargetDesc.mFormat = TinyImageFormat_R32_SFLOAT; - renderTargetDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE | DESCRIPTOR_TYPE_RW_TEXTURE; - renderTargetDesc.mWidth = width; - renderTargetDesc.mHeight = height; - renderTargetDesc.mSampleCount = SAMPLE_COUNT_1; - renderTargetDesc.mSampleQuality = 0; - renderTargetDesc.mStartState = RESOURCE_STATE_UNORDERED_ACCESS; - renderTargetDesc.pName = "hi-z depth buffer"; - addRenderTarget(renderer.Rend(), &renderTargetDesc, handle); - return true; - }); - - buffer.m_depthBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { - auto targetDesc = deferredRenderTargetDesc(); - targetDesc.mFormat = DepthBufferFormat; - targetDesc.mStartState = RESOURCE_STATE_DEPTH_WRITE; - targetDesc.pName = "Depth RT"; - addRenderTarget(renderer.Rend(), &targetDesc, handle); - return true; - }); - buffer.m_normalBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { - auto targetDesc = deferredRenderTargetDesc(); - targetDesc.mFormat = NormalBufferFormat; - targetDesc.pName = "Normal RT"; - addRenderTarget(renderer.Rend(), &targetDesc, handle); - return true; - }); - buffer.m_positionBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { - auto targetDesc = deferredRenderTargetDesc(); - targetDesc.mFormat = PositionBufferFormat; - targetDesc.pName = "Position RT"; - addRenderTarget(renderer.Rend(), &targetDesc, handle); - return true; - }); - buffer.m_specularBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { - auto targetDesc = deferredRenderTargetDesc(); - targetDesc.mFormat = SpecularBufferFormat; - targetDesc.pName = "Specular RT"; - addRenderTarget(renderer.Rend(), &targetDesc, handle); - return true; - }); - buffer.m_colorBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { - auto targetDesc = deferredRenderTargetDesc(); - targetDesc.mFormat = ColorBufferFormat; - targetDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE | DESCRIPTOR_TYPE_RW_TEXTURE; - targetDesc.pName = "Color RT"; - addRenderTarget(renderer.Rend(), &targetDesc, handle); - return true; - }); - buffer.m_refractionImage.Load([&](Texture** texture) { - TextureLoadDesc loadDesc = {}; - loadDesc.ppTexture = texture; - TextureDesc refractionImageDesc = {}; - refractionImageDesc.mArraySize = 1; - refractionImageDesc.mDepth = 1; - refractionImageDesc.mMipLevels = 1; - refractionImageDesc.mFormat = TinyImageFormat_R8G8B8A8_UNORM; - refractionImageDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE | DESCRIPTOR_TYPE_RW_TEXTURE; - refractionImageDesc.mWidth = width; - refractionImageDesc.mHeight = height; - refractionImageDesc.mSampleCount = SAMPLE_COUNT_1; - refractionImageDesc.mSampleQuality = 0; - refractionImageDesc.mStartState = RESOURCE_STATE_SHADER_RESOURCE; - refractionImageDesc.pName = "Refraction Image"; - loadDesc.pDesc = &refractionImageDesc; - addResource(&loadDesc, nullptr); - return true; - }); - buffer.m_outputBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { - auto targetDesc = deferredRenderTargetDesc(); - targetDesc.mFormat = ColorBufferFormat; - targetDesc.mDescriptors = DESCRIPTOR_TYPE_RW_TEXTURE | DESCRIPTOR_TYPE_TEXTURE; - addRenderTarget(renderer.Rend(), &targetDesc, handle); - return true; - }); -} - -void cRendererDeferred::Draw( - Cmd* cmd, - const ForgeRenderer::Frame& frame, - cViewport& viewport, - float afFrameTime, - cFrustum* apFrustum, - cWorld* apWorld, - cRenderSettings* apSettings, - bool abSendFrameBufferToPostEffects) { - // keep around for the moment ... - BeginRendering(afFrameTime, apFrustum, apWorld, apSettings, abSendFrameBufferToPostEffects); - - if (frame.m_currentFrame != m_activeFrame) { - m_materialSet.m_objectIndex = 0; - m_materialSet.m_objectDescriptorLookup.clear(); - m_lightIndex = 0; - m_lightDescriptorLookup.clear(); - m_activeFrame = frame.m_currentFrame; - } - - const cMatrixf mainFrustumViewInv = cMath::MatrixInverse(apFrustum->GetViewMatrix()); - const cMatrixf mainFrustumView = apFrustum->GetViewMatrix(); - const cMatrixf mainFrustumProj = apFrustum->GetProjectionMatrix(); + void cRendererDeferred::RebuildGBuffer(ForgeRenderer& renderer, GBuffer& buffer, uint32_t width, uint32_t height) { + ClearValue optimizedColorClearBlack = { { 0.0f, 0.0f, 0.0f, 0.0f } }; + auto deferredRenderTargetDesc = [&]() { + RenderTargetDesc renderTarget = {}; + renderTarget.mArraySize = 1; + renderTarget.mClearValue = optimizedColorClearBlack; + renderTarget.mDepth = 1; + renderTarget.mDescriptors = DESCRIPTOR_TYPE_TEXTURE; + renderTarget.mWidth = width; + renderTarget.mHeight = height; + renderTarget.mSampleCount = SAMPLE_COUNT_1; + renderTarget.mSampleQuality = 0; + renderTarget.mStartState = RESOURCE_STATE_SHADER_RESOURCE; + return renderTarget; + }; + buffer.m_hizDepthBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { + RenderTargetDesc renderTargetDesc = {}; + renderTargetDesc.mArraySize = 1; + renderTargetDesc.mDepth = 1; + renderTargetDesc.mMipLevels = std::min(std::floor(std::log2(std::max(width, height))), MaxHiZMipLevels); + renderTargetDesc.mFormat = TinyImageFormat_R32_SFLOAT; + renderTargetDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE | DESCRIPTOR_TYPE_RW_TEXTURE; + renderTargetDesc.mWidth = width; + renderTargetDesc.mHeight = height; + renderTargetDesc.mSampleCount = SAMPLE_COUNT_1; + renderTargetDesc.mSampleQuality = 0; + renderTargetDesc.mStartState = RESOURCE_STATE_UNORDERED_ACCESS; + renderTargetDesc.pName = "hi-z depth buffer"; + addRenderTarget(renderer.Rend(), &renderTargetDesc, handle); + return true; + }); - const Matrix4 mainFrustumViewInvMat = inverse(apFrustum->GetViewMat()); - const Matrix4 mainFrustumViewMat = apFrustum->GetViewMat(); - const Matrix4 mainFrustumProjMat = apFrustum->GetProjectionMat(); + buffer.m_depthBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { + auto targetDesc = deferredRenderTargetDesc(); + targetDesc.mFormat = DepthBufferFormat; + targetDesc.mStartState = RESOURCE_STATE_DEPTH_WRITE; + targetDesc.pName = "Depth RT"; + addRenderTarget(renderer.Rend(), &targetDesc, handle); + return true; + }); + buffer.m_normalBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { + auto targetDesc = deferredRenderTargetDesc(); + targetDesc.mFormat = NormalBufferFormat; + targetDesc.pName = "Normal RT"; + addRenderTarget(renderer.Rend(), &targetDesc, handle); + return true; + }); + buffer.m_positionBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { + auto targetDesc = deferredRenderTargetDesc(); + targetDesc.mFormat = PositionBufferFormat; + targetDesc.pName = "Position RT"; + addRenderTarget(renderer.Rend(), &targetDesc, handle); + return true; + }); + buffer.m_specularBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { + auto targetDesc = deferredRenderTargetDesc(); + targetDesc.mFormat = SpecularBufferFormat; + targetDesc.pName = "Specular RT"; + addRenderTarget(renderer.Rend(), &targetDesc, handle); + return true; + }); + buffer.m_colorBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { + auto targetDesc = deferredRenderTargetDesc(); + targetDesc.mFormat = ColorBufferFormat; + targetDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE | DESCRIPTOR_TYPE_RW_TEXTURE; + targetDesc.pName = "Color RT"; + addRenderTarget(renderer.Rend(), &targetDesc, handle); + return true; + }); + buffer.m_refractionImage.Load([&](Texture** texture) { + TextureLoadDesc loadDesc = {}; + loadDesc.ppTexture = texture; + TextureDesc refractionImageDesc = {}; + refractionImageDesc.mArraySize = 1; + refractionImageDesc.mDepth = 1; + refractionImageDesc.mMipLevels = 1; + refractionImageDesc.mFormat = TinyImageFormat_R8G8B8A8_UNORM; + refractionImageDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE | DESCRIPTOR_TYPE_RW_TEXTURE; + refractionImageDesc.mWidth = width; + refractionImageDesc.mHeight = height; + refractionImageDesc.mSampleCount = SAMPLE_COUNT_1; + refractionImageDesc.mSampleQuality = 0; + refractionImageDesc.mStartState = RESOURCE_STATE_SHADER_RESOURCE; + refractionImageDesc.pName = "Refraction Image"; + loadDesc.pDesc = &refractionImageDesc; + addResource(&loadDesc, nullptr); + return true; + }); + buffer.m_outputBuffer.Load(renderer.Rend(), [&](RenderTarget** handle) { + auto targetDesc = deferredRenderTargetDesc(); + targetDesc.mFormat = ColorBufferFormat; + targetDesc.mDescriptors = DESCRIPTOR_TYPE_RW_TEXTURE | DESCRIPTOR_TYPE_TEXTURE; + addRenderTarget(renderer.Rend(), &targetDesc, handle); + return true; + }); + } - // auto& swapChainImage = frame.m_swapChain->ppRenderTargets[frame.m_swapChainIndex]; - auto common = m_boundViewportData.resolve(viewport); - if (!common || common->m_size != viewport.GetSize()) { - auto* forgeRenderer = Interface::Get(); - auto viewportData = std::make_unique(); - viewportData->m_size = viewport.GetSize(); - for (auto& b : viewportData->m_gBuffer) { - RebuildGBuffer(*forgeRenderer, b, viewportData->m_size.x, viewportData->m_size.y); - } - if(common) { // reusing state from gbuffer - viewportData->m_reflectionBuffer = std::move(common->m_reflectionBuffer); - } - for(auto& reflection: viewportData->m_reflectionBuffer) { - RebuildGBuffer(*forgeRenderer, reflection.m_buffer, viewportData->m_size.x / 2, viewportData->m_size.y / 2); - reflection.m_target = nullptr;// we are clearing targets they are irrelevant when the gbuffer is discarded - if(!reflection.m_pool.IsValid() || - !reflection.m_cmd.IsValid() || - !reflection.m_fence.IsValid()) { - reflection.m_pool.Load(forgeRenderer->Rend(), [&](CmdPool** pool) { - CmdPoolDesc cmdPoolDesc = {}; - cmdPoolDesc.pQueue = forgeRenderer->GetGraphicsQueue(); - addCmdPool(forgeRenderer->Rend(), &cmdPoolDesc, pool); - return true; - }); - reflection.m_cmd.Load(forgeRenderer->Rend(), [&](Cmd** cmd) { - CmdDesc cmdDesc = {}; - cmdDesc.pPool = reflection.m_pool.m_handle; - addCmd(forgeRenderer->Rend(), &cmdDesc, cmd); - return true; - }); - reflection.m_fence.Load(forgeRenderer->Rend(), [&](Fence** fence) { - addFence(forgeRenderer->Rend(), fence); - return true; - }); - } + void cRendererDeferred::Draw( + Cmd* cmd, + const ForgeRenderer::Frame& frame, + cViewport& viewport, + float afFrameTime, + cFrustum* apFrustum, + cWorld* apWorld, + cRenderSettings* apSettings, + bool abSendFrameBufferToPostEffects) { + // keep around for the moment ... + BeginRendering(afFrameTime, apFrustum, apWorld, apSettings, abSendFrameBufferToPostEffects); + + if (frame.m_currentFrame != m_activeFrame) { + m_materialSet.m_objectIndex = 0; + m_materialSet.m_objectDescriptorLookup.clear(); + m_lightIndex = 0; + m_lightDescriptorLookup.clear(); + m_activeFrame = frame.m_currentFrame; } - common = m_boundViewportData.update(viewport, std::move(viewportData)); - } + const cMatrixf mainFrustumViewInv = cMath::MatrixInverse(apFrustum->GetViewMatrix()); + const cMatrixf mainFrustumView = apFrustum->GetViewMatrix(); + const cMatrixf mainFrustumProj = apFrustum->GetProjectionMatrix(); + + const Matrix4 mainFrustumViewInvMat = inverse(apFrustum->GetViewMat()); + const Matrix4 mainFrustumViewMat = apFrustum->GetViewMat(); + const Matrix4 mainFrustumProjMat = apFrustum->GetProjectionMat(); + + // auto& swapChainImage = frame.m_swapChain->ppRenderTargets[frame.m_swapChainIndex]; + auto common = m_boundViewportData.resolve(viewport); + if (!common || common->m_size != viewport.GetSize()) { + auto* forgeRenderer = Interface::Get(); + auto viewportData = std::make_unique(); + viewportData->m_size = viewport.GetSize(); + for (auto& b : viewportData->m_gBuffer) { + RebuildGBuffer(*forgeRenderer, b, viewportData->m_size.x, viewportData->m_size.y); + } + if (common) { // reusing state from gbuffer + viewportData->m_reflectionBuffer = std::move(common->m_reflectionBuffer); + } + for (auto& reflection : viewportData->m_reflectionBuffer) { + RebuildGBuffer(*forgeRenderer, reflection.m_buffer, viewportData->m_size.x / 2, viewportData->m_size.y / 2); + reflection.m_target = nullptr; // we are clearing targets they are irrelevant when the gbuffer is discarded + if (!reflection.m_pool.IsValid() || !reflection.m_cmd.IsValid() || !reflection.m_fence.IsValid()) { + reflection.m_pool.Load(forgeRenderer->Rend(), [&](CmdPool** pool) { + CmdPoolDesc cmdPoolDesc = {}; + cmdPoolDesc.pQueue = forgeRenderer->GetGraphicsQueue(); + addCmdPool(forgeRenderer->Rend(), &cmdPoolDesc, pool); + return true; + }); + reflection.m_cmd.Load(forgeRenderer->Rend(), [&](Cmd** cmd) { + CmdDesc cmdDesc = {}; + cmdDesc.pPool = reflection.m_pool.m_handle; + addCmd(forgeRenderer->Rend(), &cmdDesc, cmd); + return true; + }); + reflection.m_fence.Load(forgeRenderer->Rend(), [&](Fence** fence) { + addFence(forgeRenderer->Rend(), fence); + return true; + }); + } + } - auto& currentGBuffer = common->m_gBuffer[frame.m_frameIndex]; - uint32_t materialObjectIndex = getDescriptorIndexFromName(m_materialRootSignature.m_handle, "materialRootConstant"); + common = m_boundViewportData.update(viewport, std::move(viewportData)); + } - const uint32_t mainFrameIndex = updateFrameDescriptor( - frame, - frame.m_cmd, - apWorld, - { .m_size = float2(common->m_size.x, common->m_size.y), .m_viewMat = mainFrustumView, .m_projectionMat = mainFrustumProj }); + auto& currentGBuffer = common->m_gBuffer[frame.m_frameIndex]; + uint32_t materialObjectIndex = getDescriptorIndexFromName(m_materialRootSignature.m_handle, "materialRootConstant"); - { + const uint32_t mainFrameIndex = updateFrameDescriptor( + frame, + frame.m_cmd, + apWorld, + { .m_size = float2(common->m_size.x, common->m_size.y), .m_viewMat = mainFrustumView, .m_projectionMat = mainFrustumProj }); - std::array reflectionBuffers; - for(size_t i = 0; i < common->m_reflectionBuffer.size(); i++) { - reflectionBuffers[i] = common->m_reflectionBuffer[i].m_buffer.m_outputBuffer.m_handle->pTexture; + { + std::array reflectionBuffers; + for (size_t i = 0; i < common->m_reflectionBuffer.size(); i++) { + reflectionBuffers[i] = common->m_reflectionBuffer[i].m_buffer.m_outputBuffer.m_handle->pTexture; + } + std::array params = {}; + params[0].pName = "refractionMap"; + params[0].ppTextures = ¤tGBuffer.m_refractionImage.m_handle; + params[1].pName = "reflectionMap"; + params[1].ppTextures = reflectionBuffers.data(); + params[1].mCount = reflectionBuffers.size(); + updateDescriptorSet( + frame.m_renderer->Rend(), + mainFrameIndex, + m_materialSet.m_frameSet[frame.m_frameIndex].m_handle, + params.size(), + params.data()); } - std::array params = {}; - params[0].pName = "refractionMap"; - params[0].ppTextures = ¤tGBuffer.m_refractionImage.m_handle; - params[1].pName = "reflectionMap"; - params[1].ppTextures = reflectionBuffers.data(); - params[1].mCount = reflectionBuffers.size(); - updateDescriptorSet( - frame.m_renderer->Rend(), mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle, params.size(), params.data()); - } - - frame.m_resourcePool->Push(currentGBuffer.m_colorBuffer); - frame.m_resourcePool->Push(currentGBuffer.m_normalBuffer); - frame.m_resourcePool->Push(currentGBuffer.m_positionBuffer); - frame.m_resourcePool->Push(currentGBuffer.m_specularBuffer); - frame.m_resourcePool->Push(currentGBuffer.m_depthBuffer); - frame.m_resourcePool->Push(currentGBuffer.m_outputBuffer); - frame.m_resourcePool->Push(currentGBuffer.m_refractionImage); - // Setup far plane coordinates - - /////////////////////////// - // Occlusion testing - m_rendererList.BeginAndReset(afFrameTime, apFrustum); - cmdPreAndPostZ( - frame.m_cmd, - apWorld, - currentGBuffer.m_preZPassRenderables, - frame, - m_rendererList, - afFrameTime, - currentGBuffer.m_depthBuffer.m_handle, - currentGBuffer.m_hizDepthBuffer.m_handle, - apFrustum, - mainFrameIndex, - mainFrustumView, - mainFrustumProj, {}); - m_rendererList.End( - eRenderListCompileFlag_Diffuse | eRenderListCompileFlag_Translucent | eRenderListCompileFlag_Decal | - eRenderListCompileFlag_Illumination | eRenderListCompileFlag_FogArea); - - { - cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); - std::array rtBarriers = { - RenderTargetBarrier{ currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, - RenderTargetBarrier{ currentGBuffer.m_normalBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, - RenderTargetBarrier{ currentGBuffer.m_positionBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, - RenderTargetBarrier{ currentGBuffer.m_specularBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, - }; - cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); - } - cmdBuildPrimaryGBuffer(frame, frame.m_cmd, mainFrameIndex, - m_rendererList, - currentGBuffer.m_colorBuffer.m_handle, - currentGBuffer.m_normalBuffer.m_handle, - currentGBuffer.m_positionBuffer.m_handle, - currentGBuffer.m_specularBuffer.m_handle, - currentGBuffer.m_depthBuffer.m_handle, { - .m_invert = false - }); - { - cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); - std::array rtBarriers = { - RenderTargetBarrier{ currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, - RenderTargetBarrier{ currentGBuffer.m_normalBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, - RenderTargetBarrier{ currentGBuffer.m_positionBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, - RenderTargetBarrier{ currentGBuffer.m_specularBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, - RenderTargetBarrier{ currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, - - }; - cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); - } + frame.m_resourcePool->Push(currentGBuffer.m_colorBuffer); + frame.m_resourcePool->Push(currentGBuffer.m_normalBuffer); + frame.m_resourcePool->Push(currentGBuffer.m_positionBuffer); + frame.m_resourcePool->Push(currentGBuffer.m_specularBuffer); + frame.m_resourcePool->Push(currentGBuffer.m_depthBuffer); + frame.m_resourcePool->Push(currentGBuffer.m_outputBuffer); + frame.m_resourcePool->Push(currentGBuffer.m_refractionImage); + // Setup far plane coordinates + + /////////////////////////// + // Occlusion testing + m_rendererList.BeginAndReset(afFrameTime, apFrustum); + cmdPreAndPostZ( + frame.m_cmd, + apWorld, + currentGBuffer.m_preZPassRenderables, + frame, + m_rendererList, + afFrameTime, + currentGBuffer.m_depthBuffer.m_handle, + currentGBuffer.m_hizDepthBuffer.m_handle, + apFrustum, + mainFrameIndex, + mainFrustumView, + mainFrustumProj, + {}); + m_rendererList.End( + eRenderListCompileFlag_Diffuse | eRenderListCompileFlag_Translucent | eRenderListCompileFlag_Decal | + eRenderListCompileFlag_Illumination | eRenderListCompileFlag_FogArea); - if (mpCurrentSettings->mbSSAOActive) { - ASSERT(m_hbaoPlusPipeline && "Invalid pipeline"); - ASSERT(currentGBuffer.m_depthBuffer.IsValid() && "Invalid depth buffer"); - ASSERT(currentGBuffer.m_normalBuffer.IsValid() && "Invalid depth buffer"); - ASSERT(currentGBuffer.m_colorBuffer.IsValid() && "Invalid depth buffer"); { + cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); std::array rtBarriers = { - RenderTargetBarrier{ currentGBuffer.m_depthBuffer.m_handle, RESOURCE_STATE_DEPTH_WRITE, RESOURCE_STATE_SHADER_RESOURCE }, - RenderTargetBarrier{ currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS }, + RenderTargetBarrier{ currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, + RenderTargetBarrier{ currentGBuffer.m_normalBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, + RenderTargetBarrier{ + currentGBuffer.m_positionBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, + RenderTargetBarrier{ + currentGBuffer.m_specularBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, }; cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); } - m_hbaoPlusPipeline->cmdDraw( + cmdBuildPrimaryGBuffer( frame, - apFrustum, - &viewport, - currentGBuffer.m_depthBuffer.m_handle->pTexture, - currentGBuffer.m_normalBuffer.m_handle->pTexture, - currentGBuffer.m_colorBuffer.m_handle->pTexture); + frame.m_cmd, + mainFrameIndex, + m_rendererList, + currentGBuffer.m_colorBuffer.m_handle, + currentGBuffer.m_normalBuffer.m_handle, + currentGBuffer.m_positionBuffer.m_handle, + currentGBuffer.m_specularBuffer.m_handle, + currentGBuffer.m_depthBuffer.m_handle, + { .m_invert = false }); + { + cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); std::array rtBarriers = { - RenderTargetBarrier{ currentGBuffer.m_depthBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_DEPTH_WRITE }, - RenderTargetBarrier{ currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ currentGBuffer.m_normalBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ + currentGBuffer.m_positionBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ + currentGBuffer.m_specularBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, + }; cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); } - } - cmdLightPass( - frame.m_cmd, - frame, - apWorld, - apFrustum, - m_rendererList, - mainFrameIndex, - currentGBuffer.m_colorBuffer.m_handle, - currentGBuffer.m_normalBuffer.m_handle, - currentGBuffer.m_positionBuffer.m_handle, - currentGBuffer.m_specularBuffer.m_handle, - currentGBuffer.m_depthBuffer.m_handle, - currentGBuffer.m_outputBuffer.m_handle, - mainFrustumView, - mainFrustumViewInv, - mainFrustumProj, { - .m_clearColor = Vector4(apSettings->mClearColor.r,apSettings->mClearColor.g,apSettings->mClearColor.b,apSettings->mClearColor.a) - }); + if (mpCurrentSettings->mbSSAOActive) { + ASSERT(m_hbaoPlusPipeline && "Invalid pipeline"); + ASSERT(currentGBuffer.m_depthBuffer.IsValid() && "Invalid depth buffer"); + ASSERT(currentGBuffer.m_normalBuffer.IsValid() && "Invalid depth buffer"); + ASSERT(currentGBuffer.m_colorBuffer.IsValid() && "Invalid depth buffer"); + { + std::array rtBarriers = { + RenderTargetBarrier{ + currentGBuffer.m_depthBuffer.m_handle, RESOURCE_STATE_DEPTH_WRITE, RESOURCE_STATE_SHADER_RESOURCE }, + RenderTargetBarrier{ + currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS }, + }; + cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + } + m_hbaoPlusPipeline->cmdDraw( + frame, + apFrustum, + &viewport, + currentGBuffer.m_depthBuffer.m_handle->pTexture, + currentGBuffer.m_normalBuffer.m_handle->pTexture, + currentGBuffer.m_colorBuffer.m_handle->pTexture); + { + std::array rtBarriers = { + RenderTargetBarrier{ + currentGBuffer.m_depthBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_DEPTH_WRITE }, + RenderTargetBarrier{ + currentGBuffer.m_colorBuffer.m_handle, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE }, + }; + cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); + } + } - cmdIlluminationPass( - frame.m_cmd, - frame, - m_rendererList, - mainFrameIndex, - currentGBuffer.m_depthBuffer.m_handle, - currentGBuffer.m_outputBuffer.m_handle, - {}); - // ------------------------------------------------------------------------ - // Render Illumination Pass --> renders to output target - // ------------------------------------------------------------------------ - { - LoadActionsDesc loadActions = {}; - loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; - loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; - std::array targets = { + cmdLightPass( + frame.m_cmd, + frame, + apWorld, + apFrustum, + m_rendererList, + mainFrameIndex, + currentGBuffer.m_colorBuffer.m_handle, + currentGBuffer.m_normalBuffer.m_handle, + currentGBuffer.m_positionBuffer.m_handle, + currentGBuffer.m_specularBuffer.m_handle, + currentGBuffer.m_depthBuffer.m_handle, currentGBuffer.m_outputBuffer.m_handle, - }; - cmdBindRenderTargets( - frame.m_cmd, targets.size(), targets.data(), currentGBuffer.m_depthBuffer.m_handle, &loadActions, nullptr, nullptr, -1, -1); - cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, static_cast(common->m_size.x), static_cast(common->m_size.y), 0.0f, 1.0f); - cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); - cmdBindPipeline(frame.m_cmd, m_solidIlluminationPipelineCCW.m_handle); + mainFrustumView, + mainFrustumViewInv, + mainFrustumProj, + { .m_clearColor = + Vector4(apSettings->mClearColor.r, apSettings->mClearColor.g, apSettings->mClearColor.b, apSettings->mClearColor.a) }); - cmdBindDescriptorSet(frame.m_cmd, mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); - - for (auto& illuminationItem : m_rendererList.GetRenderableItems(eRenderListType_Illumination)) { - cMaterial* pMaterial = illuminationItem->GetMaterial(); + cmdIlluminationPass( + frame.m_cmd, + frame, + m_rendererList, + mainFrameIndex, + currentGBuffer.m_depthBuffer.m_handle, + currentGBuffer.m_outputBuffer.m_handle, + {}); + // ------------------------------------------------------------------------ + // Render Illumination Pass --> renders to output target + // ------------------------------------------------------------------------ + { + LoadActionsDesc loadActions = {}; + loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; + loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; std::array targets = { - eVertexBufferElement_Position, - eVertexBufferElement_Texture0, + currentGBuffer.m_outputBuffer.m_handle, }; - DrawPacket packet = illuminationItem->ResolveDrawPacket(frame, targets); + cmdBindRenderTargets( + frame.m_cmd, targets.size(), targets.data(), currentGBuffer.m_depthBuffer.m_handle, &loadActions, nullptr, nullptr, -1, -1); + cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, static_cast(common->m_size.x), static_cast(common->m_size.y), 0.0f, 1.0f); + cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); + cmdBindPipeline(frame.m_cmd, m_solidIlluminationPipelineCCW.m_handle); + + cmdBindDescriptorSet(frame.m_cmd, mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); + + for (auto& illuminationItem : m_rendererList.GetRenderableItems(eRenderListType_Illumination)) { + cMaterial* pMaterial = illuminationItem->GetMaterial(); + std::array targets = { + eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + }; + DrawPacket packet = illuminationItem->ResolveDrawPacket(frame, targets); - if (pMaterial == nullptr || packet.m_type == DrawPacket::Unknown) { - continue; - } - ASSERT(pMaterial->Descriptor().m_id == MaterialID::SolidDiffuse && "Invalid material type"); - MaterialRootConstant materialConst = {}; - uint32_t instance = cmdBindMaterialAndObject(frame.m_cmd, frame, pMaterial, illuminationItem); - materialConst.objectId = instance; + if (pMaterial == nullptr || packet.m_type == DrawPacket::Unknown) { + continue; + } + ASSERT(pMaterial->Descriptor().m_id == MaterialID::SolidDiffuse && "Invalid material type"); + MaterialRootConstant materialConst = {}; + uint32_t instance = cmdBindMaterialAndObject(frame.m_cmd, frame, pMaterial, illuminationItem); + materialConst.objectId = instance; - DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &packet); - cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(frame.m_cmd, packet.m_numIndices, 0, 0); + DrawPacket::cmdBindBuffers(cmd, frame.m_resourcePool, &packet); + cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); + cmdDrawIndexed(frame.m_cmd, packet.numberOfIndecies(), 0, 0); + } } - } - // ------------------------------------------------------------------------ - // Render Fog Pass --> output target - // ------------------------------------------------------------------------ - auto fogRenderData = detail::createFogRenderData(m_rendererList.GetFogAreas(), apFrustum); - { - cmdBeginDebugMarker(frame.m_cmd, 0, 1, 0, "Fog Box Pass "); - - auto createUniformFog = [&](bool isInsideNearPlane, cFogArea* fogArea) { - UniformFogData fogUniformData = {}; - if (isInsideNearPlane) { - fogUniformData.m_flags |= (fogArea->GetShowBacksideWhenInside() ? Fog::PipelineUseBackSide : Fog::PipelineVariantEmpty); - } else { - cMatrixf mtxInvModelView = - cMath::MatrixInverse(cMath::MatrixMul(apFrustum->GetViewMatrix(), *fogArea->GetModelMatrixPtr())); - cVector3f vRayCastStart = cMath::MatrixMul(mtxInvModelView, cVector3f(0)); - - cVector3f vNegPlaneDistNeg( - cMath::PlaneToPointDist(cPlanef(-1, 0, 0, 0.5f), vRayCastStart), - cMath::PlaneToPointDist(cPlanef(0, -1, 0, 0.5f), vRayCastStart), - cMath::PlaneToPointDist(cPlanef(0, 0, -1, 0.5f), vRayCastStart)); - cVector3f vNegPlaneDistPos( - cMath::PlaneToPointDist(cPlanef(1, 0, 0, 0.5f), vRayCastStart), - cMath::PlaneToPointDist(cPlanef(0, 1, 0, 0.5f), vRayCastStart), - cMath::PlaneToPointDist(cPlanef(0, 0, 1, 0.5f), vRayCastStart)); - fogUniformData.m_invModelRotation = cMath::ToForgeMatrix4(mtxInvModelView.GetRotation()); - fogUniformData.m_rayCastStart = float4(vRayCastStart.x, vRayCastStart.y, vRayCastStart.z, 0.0f); - fogUniformData.m_fogNegPlaneDistNeg = - float4(vNegPlaneDistNeg.x * -1.0f, vNegPlaneDistNeg.y * -1.0f, vNegPlaneDistNeg.z * -1.0f, 0.0f); - fogUniformData.m_fogNegPlaneDistPos = - float4(vNegPlaneDistPos.x * -1.0f, vNegPlaneDistPos.y * -1.0f, vNegPlaneDistPos.z * -1.0f, 0.0f); - fogUniformData.m_flags |= Fog::PipelineUseOutsideBox; - fogUniformData.m_flags |= fogArea->GetShowBacksideWhenOutside() ? Fog::PipelineUseBackSide : Fog::PipelineVariantEmpty; + // ------------------------------------------------------------------------ + // Render Fog Pass --> output target + // ------------------------------------------------------------------------ + auto fogRenderData = detail::createFogRenderData(m_rendererList.GetFogAreas(), apFrustum); + { + cmdBeginDebugMarker(frame.m_cmd, 0, 1, 0, "Fog Box Pass "); + + auto createUniformFog = [&](bool isInsideNearPlane, cFogArea* fogArea) { + UniformFogData fogUniformData = {}; + if (isInsideNearPlane) { + fogUniformData.m_flags |= (fogArea->GetShowBacksideWhenInside() ? Fog::PipelineUseBackSide : Fog::PipelineVariantEmpty); + } else { + cMatrixf mtxInvModelView = + cMath::MatrixInverse(cMath::MatrixMul(apFrustum->GetViewMatrix(), *fogArea->GetModelMatrixPtr())); + cVector3f vRayCastStart = cMath::MatrixMul(mtxInvModelView, cVector3f(0)); + + cVector3f vNegPlaneDistNeg( + cMath::PlaneToPointDist(cPlanef(-1, 0, 0, 0.5f), vRayCastStart), + cMath::PlaneToPointDist(cPlanef(0, -1, 0, 0.5f), vRayCastStart), + cMath::PlaneToPointDist(cPlanef(0, 0, -1, 0.5f), vRayCastStart)); + cVector3f vNegPlaneDistPos( + cMath::PlaneToPointDist(cPlanef(1, 0, 0, 0.5f), vRayCastStart), + cMath::PlaneToPointDist(cPlanef(0, 1, 0, 0.5f), vRayCastStart), + cMath::PlaneToPointDist(cPlanef(0, 0, 1, 0.5f), vRayCastStart)); + fogUniformData.m_invModelRotation = cMath::ToForgeMatrix4(mtxInvModelView.GetRotation()); + fogUniformData.m_rayCastStart = float4(vRayCastStart.x, vRayCastStart.y, vRayCastStart.z, 0.0f); + fogUniformData.m_fogNegPlaneDistNeg = + float4(vNegPlaneDistNeg.x * -1.0f, vNegPlaneDistNeg.y * -1.0f, vNegPlaneDistNeg.z * -1.0f, 0.0f); + fogUniformData.m_fogNegPlaneDistPos = + float4(vNegPlaneDistPos.x * -1.0f, vNegPlaneDistPos.y * -1.0f, vNegPlaneDistPos.z * -1.0f, 0.0f); + fogUniformData.m_flags |= Fog::PipelineUseOutsideBox; + fogUniformData.m_flags |= fogArea->GetShowBacksideWhenOutside() ? Fog::PipelineUseBackSide : Fog::PipelineVariantEmpty; + } + const auto fogColor = fogArea->GetColor(); + fogUniformData.m_color = float4(fogColor.r, fogColor.g, fogColor.b, fogColor.a); + fogUniformData.m_start = fogArea->GetStart(); + fogUniformData.m_length = fogArea->GetEnd() - fogArea->GetStart(); + fogUniformData.m_falloffExp = fogArea->GetFalloffExp(); + + const cMatrixf modelMat = fogArea->GetModelMatrixPtr() ? *fogArea->GetModelMatrixPtr() : cMatrixf::Identity; + fogUniformData.m_mv = cMath::ToForgeMatrix4(cMath::MatrixMul(mainFrustumView, modelMat)); + fogUniformData.m_mvp = + cMath::ToForgeMatrix4(cMath::MatrixMul(cMath::MatrixMul(mainFrustumProj, mainFrustumView), modelMat)); + return fogUniformData; + }; + std::vector nearPlanFog; + size_t fogIndex = 0; + for (const auto& fogArea : fogRenderData) { + cMatrixf mtxInvBoxSpace = cMath::MatrixInverse(*fogArea.m_fogArea->GetModelMatrixPtr()); + cVector3f boxSpaceFrustumOrigin = cMath::MatrixMul(mtxInvBoxSpace, apFrustum->GetOrigin()); + // test if inside near plane + if (fogArea.m_insideNearFrustum) { + nearPlanFog.emplace_back(fogArea.m_fogArea); + } else { + UniformFogData uniformData = createUniformFog(false, fogArea.m_fogArea); + BufferUpdateDesc updateDesc = { m_fogPass.m_fogUniformBuffer[frame.m_frameIndex].m_handle, + fogIndex * sizeof(UniformFogData) }; + beginUpdateResource(&updateDesc); + (*reinterpret_cast(updateDesc.pMappedData)) = uniformData; + endUpdateResource(&updateDesc, NULL); + fogIndex++; + } } - const auto fogColor = fogArea->GetColor(); - fogUniformData.m_color = float4(fogColor.r, fogColor.g, fogColor.b, fogColor.a); - fogUniformData.m_start = fogArea->GetStart(); - fogUniformData.m_length = fogArea->GetEnd() - fogArea->GetStart(); - fogUniformData.m_falloffExp = fogArea->GetFalloffExp(); - - const cMatrixf modelMat = fogArea->GetModelMatrixPtr() ? *fogArea->GetModelMatrixPtr() : cMatrixf::Identity; - fogUniformData.m_mv = cMath::ToForgeMatrix4(cMath::MatrixMul(mainFrustumView, modelMat)); - fogUniformData.m_mvp = - cMath::ToForgeMatrix4(cMath::MatrixMul(cMath::MatrixMul(mainFrustumProj, mainFrustumView), modelMat)); - return fogUniformData; - }; - std::vector nearPlanFog; - size_t fogIndex = 0; - for (const auto& fogArea : fogRenderData) { - cMatrixf mtxInvBoxSpace = cMath::MatrixInverse(*fogArea.m_fogArea->GetModelMatrixPtr()); - cVector3f boxSpaceFrustumOrigin = cMath::MatrixMul(mtxInvBoxSpace, apFrustum->GetOrigin()); - // test if inside near plane - if (fogArea.m_insideNearFrustum) { - nearPlanFog.emplace_back(fogArea.m_fogArea); - } else { - UniformFogData uniformData = createUniformFog(false, fogArea.m_fogArea); + std::array targets = { + currentGBuffer.m_outputBuffer.m_handle, + }; + LoadActionsDesc loadActions = {}; + loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; + loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; + cmdBindRenderTargets( + frame.m_cmd, targets.size(), targets.data(), currentGBuffer.m_depthBuffer.m_handle, &loadActions, nullptr, nullptr, -1, -1); + cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, (float)common->m_size.x, (float)common->m_size.y, 0.0f, 1.0f); + cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); + + cmdBindPipeline(frame.m_cmd, m_fogPass.m_pipeline.m_handle); + + std::array geometryStream = { eVertexBufferElement_Position }; + DrawPacket drawPacket = + static_cast(m_box.get())->resolveGeometryBinding(frame.m_currentFrame, geometryStream); + DrawPacket::cmdBindBuffers(frame.m_cmd, frame.m_resourcePool, &drawPacket); + + { + std::array params = {}; + params[0].pName = "positionMap"; + params[0].ppTextures = ¤tGBuffer.m_positionBuffer.m_handle->pTexture; + updateDescriptorSet(frame.m_renderer->Rend(), 0, m_fogPass.m_perFrameSet[frame.m_frameIndex], params.size(), params.data()); + } + uint32_t rootConstantIndex = getDescriptorIndexFromName(m_fogPass.m_fogRootSignature.m_handle, "rootConstant"); + struct { + float2 viewTexel; + uint32_t m_instanceIndex; + uint32_t pad0; + } fogConstant = { float2(1.0f / static_cast(common->m_size.x), 1.0f / static_cast(common->m_size.y)) }; + + cmdBindDescriptorSet(frame.m_cmd, 0, m_fogPass.m_perFrameSet[frame.m_frameIndex]); + cmdBindPushConstants(frame.m_cmd, m_fogPass.m_fogRootSignature.m_handle, rootConstantIndex, &fogConstant); + cmdDrawIndexedInstanced(frame.m_cmd, drawPacket.numberOfIndecies(), 0, fogIndex, 0, 0); + + size_t offsetIndex = fogIndex; + for (auto& fogArea : nearPlanFog) { + UniformFogData uniformData = createUniformFog(true, fogArea); BufferUpdateDesc updateDesc = { m_fogPass.m_fogUniformBuffer[frame.m_frameIndex].m_handle, fogIndex * sizeof(UniformFogData) }; beginUpdateResource(&updateDesc); @@ -4194,179 +4260,138 @@ void cRendererDeferred::Draw( endUpdateResource(&updateDesc, NULL); fogIndex++; } - } - std::array targets = { - currentGBuffer.m_outputBuffer.m_handle, - }; - LoadActionsDesc loadActions = {}; - loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; - loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; - cmdBindRenderTargets( - frame.m_cmd, targets.size(), targets.data(), currentGBuffer.m_depthBuffer.m_handle, &loadActions, nullptr, nullptr, -1, -1); - cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, (float)common->m_size.x, (float)common->m_size.y, 0.0f, 1.0f); - cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); - cmdBindPipeline(frame.m_cmd, m_fogPass.m_pipeline.m_handle); + cmdBindPipeline(frame.m_cmd, m_fogPass.m_pipelineInsideNearFrustum.m_handle); + fogConstant.m_instanceIndex = offsetIndex; + cmdBindPushConstants(frame.m_cmd, m_fogPass.m_fogRootSignature.m_handle, rootConstantIndex, &fogConstant); + cmdDrawIndexedInstanced(frame.m_cmd, drawPacket.numberOfIndecies(), 0, fogIndex - offsetIndex, 0, 0); - std::array geometryStream = { eVertexBufferElement_Position }; - DrawPacket drawPacket = static_cast(m_box.get())->resolveGeometryBinding(frame.m_currentFrame, geometryStream); - DrawPacket::cmdBindBuffers(frame.m_cmd, frame.m_resourcePool, &drawPacket); + cmdEndDebugMarker(frame.m_cmd); + if (apWorld->GetFogActive()) { + BufferUpdateDesc updateDesc = { m_fogPass.m_fogFullscreenUniformBuffer[frame.m_frameIndex].m_handle }; + beginUpdateResource(&updateDesc); + auto* fogData = reinterpret_cast(updateDesc.pMappedData); + auto fogColor = apWorld->GetFogColor(); + fogData->m_color = float4(fogColor.r, fogColor.g, fogColor.b, fogColor.a); + fogData->m_fogStart = apWorld->GetFogStart(); + fogData->m_fogLength = apWorld->GetFogEnd() - apWorld->GetFogStart(); + fogData->m_fogFalloffExp = apWorld->GetFogFalloffExp(); + endUpdateResource(&updateDesc, NULL); - { - std::array params = {}; - params[0].pName = "positionMap"; - params[0].ppTextures = ¤tGBuffer.m_positionBuffer.m_handle->pTexture; - updateDescriptorSet(frame.m_renderer->Rend(), 0, m_fogPass.m_perFrameSet[frame.m_frameIndex], params.size(), params.data()); - } - uint32_t rootConstantIndex = getDescriptorIndexFromName(m_fogPass.m_fogRootSignature.m_handle, "rootConstant"); - struct { - float2 viewTexel; - uint32_t m_instanceIndex; - uint32_t pad0; - } fogConstant = { float2(1.0f / static_cast(common->m_size.x), 1.0f / static_cast(common->m_size.y)) }; - - cmdBindDescriptorSet(frame.m_cmd, 0, m_fogPass.m_perFrameSet[frame.m_frameIndex]); - cmdBindPushConstants(frame.m_cmd, m_fogPass.m_fogRootSignature.m_handle, rootConstantIndex, &fogConstant); - cmdDrawIndexedInstanced(frame.m_cmd, drawPacket.m_numIndices, 0, fogIndex, 0, 0); - - size_t offsetIndex = fogIndex; - for (auto& fogArea : nearPlanFog) { - UniformFogData uniformData = createUniformFog(true, fogArea); - BufferUpdateDesc updateDesc = { m_fogPass.m_fogUniformBuffer[frame.m_frameIndex].m_handle, fogIndex * sizeof(UniformFogData) }; - beginUpdateResource(&updateDesc); - (*reinterpret_cast(updateDesc.pMappedData)) = uniformData; - endUpdateResource(&updateDesc, NULL); - fogIndex++; + cmdBindDescriptorSet(frame.m_cmd, 0, m_fogPass.m_perFrameSet[frame.m_frameIndex]); + cmdBindPipeline(frame.m_cmd, m_fogPass.m_fullScreenPipeline.m_handle); + cmdDraw(frame.m_cmd, 3, 0); + } } - - cmdBindPipeline(frame.m_cmd, m_fogPass.m_pipelineInsideNearFrustum.m_handle); - fogConstant.m_instanceIndex = offsetIndex; - cmdBindPushConstants(frame.m_cmd, m_fogPass.m_fogRootSignature.m_handle, rootConstantIndex, &fogConstant); - cmdDrawIndexedInstanced(frame.m_cmd, drawPacket.m_numIndices, 0, fogIndex - offsetIndex, 0, 0); - cmdEndDebugMarker(frame.m_cmd); - if (apWorld->GetFogActive()) { - BufferUpdateDesc updateDesc = { m_fogPass.m_fogFullscreenUniformBuffer[frame.m_frameIndex].m_handle }; - beginUpdateResource(&updateDesc); - auto* fogData = reinterpret_cast(updateDesc.pMappedData); - auto fogColor = apWorld->GetFogColor(); - fogData->m_color = float4(fogColor.r, fogColor.g, fogColor.b, fogColor.a); - fogData->m_fogStart = apWorld->GetFogStart(); - fogData->m_fogLength = apWorld->GetFogEnd() - apWorld->GetFogStart(); - fogData->m_fogFalloffExp = apWorld->GetFogFalloffExp(); - endUpdateResource(&updateDesc, NULL); - cmdBindDescriptorSet(frame.m_cmd, 0, m_fogPass.m_perFrameSet[frame.m_frameIndex]); - cmdBindPipeline(frame.m_cmd, m_fogPass.m_fullScreenPipeline.m_handle); - cmdDraw(frame.m_cmd, 3, 0); - } - } - cmdEndDebugMarker(frame.m_cmd); + { + cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); - { - cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + { + std::array textureBarriers = { + TextureBarrier{ + currentGBuffer.m_refractionImage.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS }, + }; + std::array rtBarriers = { + RenderTargetBarrier{ + currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, + }; + cmdResourceBarrier( + frame.m_cmd, 0, NULL, textureBarriers.size(), textureBarriers.data(), rtBarriers.size(), rtBarriers.data()); + } - { - std::array textureBarriers = { - TextureBarrier{ - currentGBuffer.m_refractionImage.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS }, - }; - std::array rtBarriers = { - RenderTargetBarrier{ currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, - }; - cmdResourceBarrier(frame.m_cmd, 0, NULL, textureBarriers.size(), textureBarriers.data(), rtBarriers.size(), rtBarriers.data()); + cmdBindPipeline(frame.m_cmd, m_materialTranslucencyPass.m_refractionCopyPipeline.m_handle); + DescriptorData params[2] = {}; + params[0].pName = "sourceInput"; + params[0].ppTextures = ¤tGBuffer.m_outputBuffer.m_handle->pTexture; + params[1].pName = "destOutput"; + params[1].ppTextures = ¤tGBuffer.m_refractionImage.m_handle; + updateDescriptorSet( + frame.m_renderer->Rend(), 0, m_materialTranslucencyPass.m_refractionPerFrameSet[frame.m_frameIndex].m_handle, 2, params); + cmdBindDescriptorSet(frame.m_cmd, 0, m_materialTranslucencyPass.m_refractionPerFrameSet[frame.m_frameIndex].m_handle); + cmdDispatch( + frame.m_cmd, + static_cast(static_cast(common->m_size.x) / 16.0f) + 1, + static_cast(static_cast(common->m_size.y) / 16.0f) + 1, + 1); + { + std::array textureBarriers = { + TextureBarrier{ + currentGBuffer.m_refractionImage.m_handle, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE }, + }; + + std::array rtBarriers = { + RenderTargetBarrier{ + currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, + }; + cmdResourceBarrier( + frame.m_cmd, 0, NULL, textureBarriers.size(), textureBarriers.data(), rtBarriers.size(), rtBarriers.data()); + } } - cmdBindPipeline(frame.m_cmd, m_materialTranslucencyPass.m_refractionCopyPipeline.m_handle); - DescriptorData params[2] = {}; - params[0].pName = "sourceInput"; - params[0].ppTextures = ¤tGBuffer.m_outputBuffer.m_handle->pTexture; - params[1].pName = "destOutput"; - params[1].ppTextures = ¤tGBuffer.m_refractionImage.m_handle; - updateDescriptorSet( - frame.m_renderer->Rend(), 0, m_materialTranslucencyPass.m_refractionPerFrameSet[frame.m_frameIndex].m_handle, 2, params); - cmdBindDescriptorSet(frame.m_cmd, 0, m_materialTranslucencyPass.m_refractionPerFrameSet[frame.m_frameIndex].m_handle); - cmdDispatch( - frame.m_cmd, - static_cast(static_cast(common->m_size.x) / 16.0f) + 1, - static_cast(static_cast(common->m_size.y) / 16.0f) + 1, - 1); + // notify post draw listeners + // DebugDraw postSolidBatch(context, sharedData->m_gBuffer.m_outputTarget, mainFrustumView, mainFrustumProj); + cViewport::PostSolidDrawPacket postSolidEvent = cViewport::PostSolidDrawPacket(); + postSolidEvent.m_frustum = apFrustum; + postSolidEvent.m_frame = &frame; + postSolidEvent.m_outputTarget = ¤tGBuffer.m_outputBuffer; + postSolidEvent.m_viewport = &viewport; + postSolidEvent.m_renderSettings = mpCurrentSettings; + postSolidEvent.m_debug = m_debug.get(); + postSolidEvent.m_renderList = &m_rendererList; + viewport.SignalDraw(postSolidEvent); + m_debug->flush(frame, frame.m_cmd, viewport, *apFrustum, currentGBuffer.m_outputBuffer, currentGBuffer.m_depthBuffer); + + // ------------------------------------------------------------------------ + // Translucency Pass --> output target + // ------------------------------------------------------------------------ { - std::array textureBarriers = { - TextureBarrier{ - currentGBuffer.m_refractionImage.m_handle, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE }, - }; - - std::array rtBarriers = { - RenderTargetBarrier{ currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, + LoadActionsDesc loadActions = {}; + loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; + loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; + std::array targets = { + currentGBuffer.m_outputBuffer.m_handle, }; - cmdResourceBarrier(frame.m_cmd, 0, NULL, textureBarriers.size(), textureBarriers.data(), rtBarriers.size(), rtBarriers.data()); - } - } - - // notify post draw listeners - // DebugDraw postSolidBatch(context, sharedData->m_gBuffer.m_outputTarget, mainFrustumView, mainFrustumProj); - cViewport::PostSolidDrawPacket postSolidEvent = cViewport::PostSolidDrawPacket(); - postSolidEvent.m_frustum = apFrustum; - postSolidEvent.m_frame = &frame; - postSolidEvent.m_outputTarget = ¤tGBuffer.m_outputBuffer; - postSolidEvent.m_viewport = &viewport; - postSolidEvent.m_renderSettings = mpCurrentSettings; - postSolidEvent.m_debug = m_debug.get(); - postSolidEvent.m_renderList = &m_rendererList; - viewport.SignalDraw(postSolidEvent); - m_debug->flush(frame, frame.m_cmd, viewport, *apFrustum, currentGBuffer.m_outputBuffer, currentGBuffer.m_depthBuffer); - - // ------------------------------------------------------------------------ - // Translucency Pass --> output target - // ------------------------------------------------------------------------ - { - LoadActionsDesc loadActions = {}; - loadActions.mLoadActionsColor[0] = LOAD_ACTION_LOAD; - loadActions.mLoadActionDepth = LOAD_ACTION_LOAD; - std::array targets = { - currentGBuffer.m_outputBuffer.m_handle, - }; - cmdBindRenderTargets( - frame.m_cmd, targets.size(), targets.data(), currentGBuffer.m_depthBuffer.m_handle, &loadActions, nullptr, nullptr, -1, -1); - cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, static_cast(common->m_size.x), static_cast(common->m_size.y), 0.0f, 1.0f); - cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); - - - std::array translucencyBlendTable; - translucencyBlendTable[eMaterialBlendMode_None] = TranslucencyPipeline::TranslucencyBlend::BlendAdd; - translucencyBlendTable[eMaterialBlendMode_Add] = TranslucencyPipeline::TranslucencyBlend::BlendAdd; - translucencyBlendTable[eMaterialBlendMode_Mul] = TranslucencyPipeline::TranslucencyBlend::BlendMul; - translucencyBlendTable[eMaterialBlendMode_MulX2] = TranslucencyPipeline::TranslucencyBlend::BlendMulX2; - translucencyBlendTable[eMaterialBlendMode_Alpha] = TranslucencyPipeline::TranslucencyBlend::BlendAlpha; - translucencyBlendTable[eMaterialBlendMode_PremulAlpha] = TranslucencyPipeline::TranslucencyBlend::BlendPremulAlpha; - - cmdBeginDebugMarker(frame.m_cmd, 0, 1, 0, "Translucency Pass"); - cmdBindDescriptorSet(frame.m_cmd, mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); - for (auto& translucencyItem : m_rendererList.GetRenderableItems(eRenderListType_Translucent)) { - cMaterial* pMaterial = translucencyItem->GetMaterial(); - if (pMaterial == nullptr) { - continue; - } + cmdBindRenderTargets( + frame.m_cmd, targets.size(), targets.data(), currentGBuffer.m_depthBuffer.m_handle, &loadActions, nullptr, nullptr, -1, -1); + cmdSetViewport(frame.m_cmd, 0.0f, 0.0f, static_cast(common->m_size.x), static_cast(common->m_size.y), 0.0f, 1.0f); + cmdSetScissor(frame.m_cmd, 0, 0, common->m_size.x, common->m_size.y); + + std::array translucencyBlendTable; + translucencyBlendTable[eMaterialBlendMode_None] = TranslucencyPipeline::TranslucencyBlend::BlendAdd; + translucencyBlendTable[eMaterialBlendMode_Add] = TranslucencyPipeline::TranslucencyBlend::BlendAdd; + translucencyBlendTable[eMaterialBlendMode_Mul] = TranslucencyPipeline::TranslucencyBlend::BlendMul; + translucencyBlendTable[eMaterialBlendMode_MulX2] = TranslucencyPipeline::TranslucencyBlend::BlendMulX2; + translucencyBlendTable[eMaterialBlendMode_Alpha] = TranslucencyPipeline::TranslucencyBlend::BlendAlpha; + translucencyBlendTable[eMaterialBlendMode_PremulAlpha] = TranslucencyPipeline::TranslucencyBlend::BlendPremulAlpha; + + cmdBeginDebugMarker(frame.m_cmd, 0, 1, 0, "Translucency Pass"); + cmdBindDescriptorSet(frame.m_cmd, mainFrameIndex, m_materialSet.m_frameSet[frame.m_frameIndex].m_handle); + for (auto& translucencyItem : m_rendererList.GetRenderableItems(eRenderListType_Translucent)) { + cMaterial* pMaterial = translucencyItem->GetMaterial(); + if (pMaterial == nullptr) { + continue; + } - const bool isRefraction = iRenderer::GetRefractionEnabled() && pMaterial->HasRefraction(); - const bool isReflection = pMaterial->HasWorldReflection() && translucencyItem->GetRenderType() == eRenderableType_SubMesh && - mpCurrentSettings->mbRenderWorldReflection; - const bool isFogActive = apWorld->GetFogActive(); - const bool isParticleEmitter = TypeInfo::IsSubtype(*translucencyItem); - const auto cubeMap = pMaterial->GetImage(eMaterialTexture_CubeMap); - uint32_t reflectionBufferIndex = 0; - cMatrixf* pMatrix = translucencyItem->GetModelMatrix(apFrustum); + const bool isRefraction = iRenderer::GetRefractionEnabled() && pMaterial->HasRefraction(); + const bool isReflection = pMaterial->HasWorldReflection() && translucencyItem->GetRenderType() == eRenderableType_SubMesh && + mpCurrentSettings->mbRenderWorldReflection; + const bool isFogActive = apWorld->GetFogActive(); + const bool isParticleEmitter = TypeInfo::IsSubtype(*translucencyItem); + const auto cubeMap = pMaterial->GetImage(eMaterialTexture_CubeMap); + uint32_t reflectionBufferIndex = 0; + cMatrixf* pMatrix = translucencyItem->GetModelMatrix(apFrustum); - if (translucencyItem->UpdateGraphicsForViewport(apFrustum, afFrameTime) == false) { - continue; - } + if (translucencyItem->UpdateGraphicsForViewport(apFrustum, afFrameTime) == false) { + continue; + } - if (isReflection) { - cSubMeshEntity* pReflectionObject = static_cast(translucencyItem); + if (isReflection) { + cSubMeshEntity* pReflectionObject = static_cast(translucencyItem); - bool bReflectionIsInRange = true; - if (pMaterial->GetMaxReflectionDistance() > 0) { + bool bReflectionIsInRange = true; + if (pMaterial->GetMaxReflectionDistance() > 0) { cVector3f vPoint = apFrustum->GetOrigin() + apFrustum->GetForward() * -1 * pMaterial->GetMaxReflectionDistance(); cVector3f vNormal = apFrustum->GetForward(); @@ -4377,8 +4402,8 @@ void cRendererDeferred::Draw( eCollision_Outside) { bReflectionIsInRange = false; } - } - if (bReflectionIsInRange) { + } + if (bReflectionIsInRange) { /////////////////////////// // Make a frustum, mirrored along the plane cSubMesh* pSubMesh = pReflectionObject->GetSubMesh(); @@ -4469,7 +4494,7 @@ void cRendererDeferred::Draw( }); m_reflectionRendererList.End( eRenderListCompileFlag_Diffuse | eRenderListCompileFlag_Translucent | eRenderListCompileFlag_Decal | - eRenderListCompileFlag_Illumination ); + eRenderListCompileFlag_Illumination); { cmdBindRenderTargets(resolveReflectionBuffer.m_cmd.m_handle, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); @@ -4570,156 +4595,158 @@ void cRendererDeferred::Draw( submitDesc.pSignalFence = resolveReflectionBuffer.m_fence.m_handle; submitDesc.mSubmitDone = true; queueSubmit(frame.m_renderer->GetGraphicsQueue(), &submitDesc); + } } - } - MaterialRootConstant materialConst = { 0 }; - float sceneAlpha = 1; - for (auto& fogArea : fogRenderData) { - sceneAlpha *= detail::GetFogAreaVisibilityForObject(fogArea, *apFrustum, translucencyItem); - } - materialConst.m_sceneAlpha = sceneAlpha; + MaterialRootConstant materialConst = { 0 }; + float sceneAlpha = 1; + for (auto& fogArea : fogRenderData) { + sceneAlpha *= detail::GetFogAreaVisibilityForObject(fogArea, *apFrustum, translucencyItem); + } + materialConst.m_sceneAlpha = sceneAlpha; - switch (pMaterial->Descriptor().m_id) { - case MaterialID::Translucent: - { - //LegacyVertexBuffer::GeometryBinding binding; - DrawPacket drawPacket; - if (isParticleEmitter) { - std::array targets = { eVertexBufferElement_Position, eVertexBufferElement_Texture0, eVertexBufferElement_Color0 }; - drawPacket = translucencyItem->ResolveDrawPacket(frame, targets); - if(drawPacket.m_type == DrawPacket::Unknown && drawPacket.m_numIndices == 0) { - break; - } + switch (pMaterial->Descriptor().m_id) { + case MaterialID::Translucent: + { + // LegacyVertexBuffer::GeometryBinding binding; + DrawPacket drawPacket; + if (isParticleEmitter) { + std::array targets = { eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + eVertexBufferElement_Color0 }; + drawPacket = translucencyItem->ResolveDrawPacket(frame, targets); + if (drawPacket.m_type == DrawPacket::Unknown && drawPacket.numberOfIndecies() == 0) { + break; + } - } else { - std::array targets = { eVertexBufferElement_Position, - eVertexBufferElement_Texture0, - eVertexBufferElement_Normal, - eVertexBufferElement_Texture1Tangent, - eVertexBufferElement_Color0 }; + } else { + std::array targets = { eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + eVertexBufferElement_Normal, + eVertexBufferElement_Texture1Tangent, + eVertexBufferElement_Color0 }; drawPacket = translucencyItem->ResolveDrawPacket(frame, targets); - if(drawPacket.m_type == DrawPacket::Unknown && drawPacket.m_numIndices == 0) { + if (drawPacket.m_type == DrawPacket::Unknown && drawPacket.numberOfIndecies() == 0) { break; } - } + } - uint32_t instance = cmdBindMaterialAndObject( - frame.m_cmd, frame, pMaterial, translucencyItem, std::optional{ pMatrix ? *pMatrix : cMatrixf::Identity }); - materialConst.objectId = instance; - cRendererDeferred::TranslucencyPipeline::TranslucencyKey key = {}; - key.m_field.m_hasDepthTest = pMaterial->GetDepthTest(); + uint32_t instance = cmdBindMaterialAndObject( + frame.m_cmd, frame, pMaterial, translucencyItem, std::optional{ pMatrix ? *pMatrix : cMatrixf::Identity }); + materialConst.objectId = instance; + cRendererDeferred::TranslucencyPipeline::TranslucencyKey key = {}; + key.m_field.m_hasDepthTest = pMaterial->GetDepthTest(); + + ASSERT( + pMaterial->GetBlendMode() < eMaterialBlendMode_LastEnum && + pMaterial->GetBlendMode() != eMaterialBlendMode_None && "Invalid blend mode"); + if (isParticleEmitter) { + cmdBindPipeline( + frame.m_cmd, + m_materialTranslucencyPass.m_particlePipelines[translucencyBlendTable[pMaterial->GetBlendMode()]][key.m_id] + .m_handle); + } else { + cmdBindPipeline( + frame.m_cmd, + (isRefraction + ? m_materialTranslucencyPass.m_refractionPipeline[key.m_id].m_handle + : m_materialTranslucencyPass.m_pipelines[translucencyBlendTable[pMaterial->GetBlendMode()]][key.m_id] + .m_handle)); + } - ASSERT( - pMaterial->GetBlendMode() < eMaterialBlendMode_LastEnum && pMaterial->GetBlendMode() != eMaterialBlendMode_None && - "Invalid blend mode"); - if (isParticleEmitter) { - cmdBindPipeline( - frame.m_cmd, - m_materialTranslucencyPass.m_particlePipelines[translucencyBlendTable[pMaterial->GetBlendMode()]][key.m_id] - .m_handle); - } else { - cmdBindPipeline( - frame.m_cmd, - (isRefraction - ? m_materialTranslucencyPass.m_refractionPipeline[key.m_id].m_handle - : m_materialTranslucencyPass.m_pipelines[translucencyBlendTable[pMaterial->GetBlendMode()]][key.m_id] - .m_handle)); - } + DrawPacket::cmdBindBuffers(frame.m_cmd, frame.m_resourcePool, &drawPacket); - DrawPacket::cmdBindBuffers(frame.m_cmd, frame.m_resourcePool, &drawPacket); + materialConst.m_options = (isFogActive ? TranslucencyFlags::UseFog : 0) | + (isRefraction ? TranslucencyFlags::UseRefractionTrans : 0) | translucencyBlendTable[pMaterial->GetBlendMode()]; - materialConst.m_options = (isFogActive ? TranslucencyFlags::UseFog : 0) | - (isRefraction ? TranslucencyFlags::UseRefractionTrans : 0) | translucencyBlendTable[pMaterial->GetBlendMode()]; + cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); + cmdDrawIndexed(frame.m_cmd, drawPacket.numberOfIndecies(), 0, 0); - cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(frame.m_cmd, drawPacket.m_numIndices, 0, 0); + if (cubeMap && !isRefraction) { + materialConst.m_options = TranslucencyFlags::UseIlluminationTrans | + (isFogActive ? TranslucencyFlags::UseFog : 0) | TranslucencyPipeline::TranslucencyBlend::BlendAdd; - if (cubeMap && !isRefraction) { - materialConst.m_options = TranslucencyFlags::UseIlluminationTrans | (isFogActive ? TranslucencyFlags::UseFog : 0) | - TranslucencyPipeline::TranslucencyBlend::BlendAdd; + cmdBindPipeline( + frame.m_cmd, + m_materialTranslucencyPass.m_pipelines[TranslucencyPipeline::TranslucencyBlend::BlendAdd][key.m_id] + .m_handle); + cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); + cmdDrawIndexed(frame.m_cmd, drawPacket.numberOfIndecies(), 0, 0); + } + } + break; + case MaterialID::Water: + { + std::array targets = { eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + eVertexBufferElement_Normal, + eVertexBufferElement_Texture1Tangent, + eVertexBufferElement_Color0 }; + DrawPacket packet = translucencyItem->ResolveDrawPacket(frame, targets); + if (packet.m_type == DrawPacket::Unknown) { + break; + } - cmdBindPipeline( - frame.m_cmd, - m_materialTranslucencyPass.m_pipelines[TranslucencyPipeline::TranslucencyBlend::BlendAdd][key.m_id].m_handle); + materialConst.m_options = (isFogActive ? TranslucencyFlags::UseFog : 0) | + (isRefraction ? TranslucencyFlags::UseRefractionTrans : 0) | + (isReflection ? TranslucencyFlags::UseReflectionTrans : 0) | + (isRefraction ? translucencyBlendTable[eMaterialBlendMode_None] + : translucencyBlendTable[eMaterialBlendMode_Mul]) | + (((reflectionBufferIndex & TranslucencyReflectionBufferMask) << TranslucencyReflectionBufferOffset)); + + cRendererDeferred::TranslucencyPipeline::TranslucencyWaterKey key = {}; + key.m_field.m_hasDepthTest = pMaterial->GetDepthTest(); + + // LegacyVertexBuffer::cmdBindGeometry(frame.m_cmd, frame.m_resourcePool, binding); + DrawPacket::cmdBindBuffers(frame.m_cmd, frame.m_resourcePool, &packet); + cmdBindPipeline(frame.m_cmd, m_materialTranslucencyPass.m_waterPipeline[key.m_id].m_handle); + uint32_t instance = cmdBindMaterialAndObject( + frame.m_cmd, frame, pMaterial, translucencyItem, std::optional{ pMatrix ? *pMatrix : cMatrixf::Identity }); + materialConst.objectId = instance; cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(frame.m_cmd, drawPacket.m_numIndices, 0, 0); + cmdDrawIndexed(frame.m_cmd, packet.numberOfIndecies(), 0, 0); } + break; + default: + ASSERT(false && "Invalid material type"); + continue; } - break; - case MaterialID::Water: - { - std::array targets = { eVertexBufferElement_Position, - eVertexBufferElement_Texture0, - eVertexBufferElement_Normal, - eVertexBufferElement_Texture1Tangent, - eVertexBufferElement_Color0 }; - DrawPacket packet = translucencyItem->ResolveDrawPacket(frame, targets); - if(packet.m_type == DrawPacket::Unknown) { - break; - } - - materialConst.m_options = (isFogActive ? TranslucencyFlags::UseFog : 0) | - (isRefraction ? TranslucencyFlags::UseRefractionTrans : 0) | - (isReflection ? TranslucencyFlags::UseReflectionTrans : 0) | - (isRefraction ? translucencyBlendTable[eMaterialBlendMode_None]: translucencyBlendTable[eMaterialBlendMode_Mul]) | - (((reflectionBufferIndex & TranslucencyReflectionBufferMask) << TranslucencyReflectionBufferOffset)); - - - cRendererDeferred::TranslucencyPipeline::TranslucencyWaterKey key = {}; - key.m_field.m_hasDepthTest = pMaterial->GetDepthTest(); + } + cmdEndDebugMarker(frame.m_cmd); + } - //LegacyVertexBuffer::cmdBindGeometry(frame.m_cmd, frame.m_resourcePool, binding); - DrawPacket::cmdBindBuffers(frame.m_cmd, frame.m_resourcePool, &packet); - cmdBindPipeline(frame.m_cmd, m_materialTranslucencyPass.m_waterPipeline[key.m_id].m_handle); - uint32_t instance = cmdBindMaterialAndObject( - frame.m_cmd, frame, pMaterial, translucencyItem, std::optional{ pMatrix ? *pMatrix : cMatrixf::Identity }); - materialConst.objectId = instance; - cmdBindPushConstants(frame.m_cmd, m_materialRootSignature.m_handle, materialObjectIndex, &materialConst); - cmdDrawIndexed(frame.m_cmd, packet.m_numIndices, 0, 0); + // DebugDraw postTransBatch(context, sharedData->m_gBuffer.m_outputTarget, mainFrustumView, mainFrustumProj); + cViewport::PostTranslucenceDrawPacket translucenceEvent = cViewport::PostTranslucenceDrawPacket(); + translucenceEvent.m_frustum = apFrustum; + translucenceEvent.m_frame = &frame; + translucenceEvent.m_outputTarget = ¤tGBuffer.m_outputBuffer; + translucenceEvent.m_viewport = &viewport; + translucenceEvent.m_renderSettings = mpCurrentSettings; + translucenceEvent.m_debug = m_debug.get(); + translucenceEvent.m_renderList = &m_rendererList; + viewport.SignalDraw(translucenceEvent); + m_debug->flush(frame, frame.m_cmd, viewport, *apFrustum, currentGBuffer.m_outputBuffer, currentGBuffer.m_depthBuffer); - } - break; - default: - ASSERT(false && "Invalid material type"); - continue; - } + { + cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + std::array rtBarriers = { + RenderTargetBarrier{ currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, + }; + cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); } - cmdEndDebugMarker(frame.m_cmd); } - // DebugDraw postTransBatch(context, sharedData->m_gBuffer.m_outputTarget, mainFrustumView, mainFrustumProj); - cViewport::PostTranslucenceDrawPacket translucenceEvent = cViewport::PostTranslucenceDrawPacket(); - translucenceEvent.m_frustum = apFrustum; - translucenceEvent.m_frame = &frame; - translucenceEvent.m_outputTarget = ¤tGBuffer.m_outputBuffer; - translucenceEvent.m_viewport = &viewport; - translucenceEvent.m_renderSettings = mpCurrentSettings; - translucenceEvent.m_debug = m_debug.get(); - translucenceEvent.m_renderList = &m_rendererList; - viewport.SignalDraw(translucenceEvent); - m_debug->flush(frame, frame.m_cmd, viewport, *apFrustum, currentGBuffer.m_outputBuffer, currentGBuffer.m_depthBuffer); - - { - cmdBindRenderTargets(frame.m_cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); - std::array rtBarriers = { - RenderTargetBarrier{ currentGBuffer.m_outputBuffer.m_handle, RESOURCE_STATE_RENDER_TARGET, RESOURCE_STATE_SHADER_RESOURCE }, - }; - cmdResourceBarrier(frame.m_cmd, 0, NULL, 0, NULL, rtBarriers.size(), rtBarriers.data()); - } -} - -iVertexBuffer* cRendererDeferred::GetLightShape(iLight* apLight, eDeferredShapeQuality aQuality) const { - switch (apLight->GetLightType()) { - case eLightType_Point: - return m_shapeSphere[aQuality].get(); - case eLightType_Spot: - return m_shapePyramid.get(); - case eLightType_Box: - return m_box.get(); - default: - break; + iVertexBuffer* cRendererDeferred::GetLightShape(iLight* apLight, eDeferredShapeQuality aQuality) const { + switch (apLight->GetLightType()) { + case eLightType_Point: + return m_shapeSphere[aQuality].get(); + case eLightType_Spot: + return m_shapePyramid.get(); + case eLightType_Box: + return m_box.get(); + default: + break; + } + return nullptr; } - return nullptr; -} } // namespace hpl diff --git a/HPL2/sources/graphics/RendererForwardPlus.cpp b/HPL2/sources/graphics/RendererForwardPlus.cpp new file mode 100644 index 000000000..903d76367 --- /dev/null +++ b/HPL2/sources/graphics/RendererForwardPlus.cpp @@ -0,0 +1,816 @@ +#include "graphics/RendererForwardPlus.h" + +#include "Common_3/Utilities/ThirdParty/OpenSource/ModifiedSonyMath/common.hpp" +#include "Common_3/Utilities/ThirdParty/OpenSource/ModifiedSonyMath/sse/vectormath.hpp" +#include "graphics/Color.h" +#include "graphics/ForgeHandles.h" +#include "graphics/ForgeRenderer.h" +#include "graphics/GraphicsAllocator.h" +#include "graphics/GraphicsTypes.h" +#include "graphics/IndexPool.h" +#include "scene/Light.h" +#include "scene/RenderableContainer.h" + +#include "Common_3/Utilities/Math/MathTypes.h" +#include "Common_3/Resources/ResourceLoader/Interfaces/IResourceLoader.h" +#include "Common_3/Graphics/Interfaces/IGraphics.h" +#include "FixPreprocessor.h" +#include "tinyimageformat_base.h" +#include +#include +#include + +namespace hpl { + + SharedRenderTarget RendererForwardPlus::GetOutputImage(uint32_t frameIndex, cViewport& viewport) { + auto sharedData = m_boundViewportData.resolve(viewport); + if (!sharedData) { + return SharedRenderTarget(); + } + return sharedData->m_outputBuffer[frameIndex]; + } + + RendererForwardPlus::RendererForwardPlus(cGraphics* apGraphics, cResources* apResources, std::shared_ptr debug) + : iRenderer("ForwardPlus", apGraphics, apResources), + m_sceneTexturePool(MaxTextureCount), + m_sceneTextureDisposable(ForgeRenderer::SwapChainLength), + m_opaqueMaterialPool(MaxOpaqueCount), + m_indexResourceDisposable(ForgeRenderer::SwapChainLength) { + auto* forgeRenderer = Interface::Get(); + + // shaders + m_nearestClampSampler.Load(forgeRenderer->Rend(), [&](Sampler** sampler) { + SamplerDesc samplerDesc = {}; + samplerDesc.mMinFilter = FILTER_NEAREST; + samplerDesc.mMagFilter = FILTER_NEAREST; + samplerDesc.mMipMapMode = MIPMAP_MODE_NEAREST; + samplerDesc.mAddressU = ADDRESS_MODE_CLAMP_TO_BORDER; + samplerDesc.mAddressV = ADDRESS_MODE_CLAMP_TO_BORDER; + samplerDesc.mAddressW = ADDRESS_MODE_CLAMP_TO_BORDER; + addSampler(forgeRenderer->Rend(), &samplerDesc, sampler); + return true; + }); + + m_emptyTexture.Load([&](Texture** texture) { + TextureDesc textureDesc = {}; + textureDesc.mArraySize = 1; + textureDesc.mMipLevels = 1; + textureDesc.mDepth = 1; + textureDesc.mFormat = TinyImageFormat_R8G8B8A8_UNORM; + textureDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE; + textureDesc.mWidth = 16; + textureDesc.mHeight = 16; + textureDesc.mSampleCount = SAMPLE_COUNT_1; + textureDesc.mStartState = RESOURCE_STATE_COMMON; + textureDesc.pName = "empty texture"; + TextureLoadDesc loadDesc = {}; + loadDesc.ppTexture = texture; + loadDesc.pDesc = &textureDesc; + addResource(&loadDesc, nullptr); + return true; + }); + + m_pointlightClusterShader.Load(forgeRenderer->Rend(), [&](Shader** shader) { + ShaderLoadDesc loadDesc = {}; + loadDesc.mStages[0].pFileName = "point_light_clusters.comp"; + addShader(forgeRenderer->Rend(), &loadDesc, shader); + return true; + }); + m_clearClusterShader.Load(forgeRenderer->Rend(), [&](Shader** shader) { + ShaderLoadDesc loadDesc = {}; + loadDesc.mStages[0].pFileName = "light_clusters_clear.comp"; + addShader(forgeRenderer->Rend(), &loadDesc, shader); + return true; + }); + m_diffuseShader.Load(forgeRenderer->Rend(), [&](Shader** shader) { + ShaderLoadDesc loadDesc = {}; + loadDesc.mStages[0].pFileName = "forward_diffuse.vert"; + loadDesc.mStages[1].pFileName = "forward_diffuse.frag"; + addShader(forgeRenderer->Rend(), &loadDesc, shader); + return true; + }); + + // Root signautres + m_diffuseRootSignature.Load(forgeRenderer->Rend(), [&](RootSignature** sig) { + ASSERT(m_diffuseShader.IsValid()); + std::array shaders = { m_diffuseShader.m_handle }; + Sampler* vbShadeSceneSamplers[] = { m_nearestClampSampler.m_handle }; + const char* vbShadeSceneSamplersNames[] = { "nearestClampSampler" }; + RootSignatureDesc rootSignatureDesc = {}; + rootSignatureDesc.ppShaders = shaders.data(); + rootSignatureDesc.mShaderCount = shaders.size(); + rootSignatureDesc.mStaticSamplerCount = std::size(vbShadeSceneSamplersNames); + rootSignatureDesc.ppStaticSamplers = vbShadeSceneSamplers; + rootSignatureDesc.ppStaticSamplerNames = vbShadeSceneSamplersNames; + addRootSignature(forgeRenderer->Rend(), &rootSignatureDesc, sig); + return true; + }); + m_lightClusterRootSignature.Load(forgeRenderer->Rend(), [&](RootSignature** sig) { + ASSERT(m_pointlightClusterShader.IsValid()); + ASSERT(m_clearClusterShader.IsValid()); + std::array shaders = { m_pointlightClusterShader.m_handle, m_clearClusterShader.m_handle }; + RootSignatureDesc rootSignatureDesc = {}; + rootSignatureDesc.ppShaders = shaders.data(); + rootSignatureDesc.mShaderCount = shaders.size(); + addRootSignature(forgeRenderer->Rend(), &rootSignatureDesc, sig); + return true; + }); + + // Indirect Argument signature + { + std::array indirectArgs = {}; + { + IndirectArgumentDescriptor arg{}; + arg.mType = INDIRECT_DRAW_INDEX; + indirectArgs[0] = arg; + } + CommandSignatureDesc vbPassDesc = { + m_diffuseRootSignature.m_handle, + indirectArgs.data(), + indirectArgs.size() }; + vbPassDesc.mPacked = true; + addIndirectCommandSignature(forgeRenderer->Rend(), &vbPassDesc, &m_cmdSignatureVBPass); + } + + for(auto& buffer: m_perFrameBuffer) { + buffer.Load([&](Buffer** buffer) { + BufferLoadDesc desc = {}; + desc.mDesc.mDescriptors = DESCRIPTOR_TYPE_UNIFORM_BUFFER; + desc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; + desc.mDesc.mElementCount = 1; + desc.mDesc.mStructStride = sizeof(UniformPerFrameData); + desc.mDesc.mSize = sizeof(UniformPerFrameData); + desc.mDesc.mFlags = BUFFER_CREATION_FLAG_PERSISTENT_MAP_BIT; + desc.ppBuffer = buffer; + addResource(&desc, nullptr); + return true; + }); + } + for(size_t swapChainIndex = 0; swapChainIndex < ForgeRenderer::SwapChainLength; swapChainIndex++) { + m_indirectDrawArgsBuffer[swapChainIndex].Load([&](Buffer** buffer) { + BufferLoadDesc indirectBufferDesc = {}; + indirectBufferDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_INDIRECT_BUFFER | DESCRIPTOR_TYPE_BUFFER; + indirectBufferDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_TO_CPU; + indirectBufferDesc.mDesc.mElementCount = MaxIndirectDrawArgs; + indirectBufferDesc.mDesc.mStructStride = sizeof(IndirectDrawIndexArguments); + indirectBufferDesc.mDesc.mStartState = RESOURCE_STATE_SHADER_RESOURCE | RESOURCE_STATE_INDIRECT_ARGUMENT; + indirectBufferDesc.mDesc.mSize = indirectBufferDesc.mDesc.mElementCount * indirectBufferDesc.mDesc.mStructStride; + indirectBufferDesc.mDesc.pName = "Indirect Buffer"; + indirectBufferDesc.ppBuffer = buffer; + addResource(&indirectBufferDesc, NULL); + return true; + }); + m_opaqueMaterialBuffer.Load([&](Buffer** buffer) { + BufferLoadDesc desc = {}; + desc.mDesc.mDescriptors = DESCRIPTOR_TYPE_BUFFER; + desc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; + desc.mDesc.mFlags = BUFFER_CREATION_FLAG_PERSISTENT_MAP_BIT; + desc.mDesc.mFirstElement = 0; + desc.mDesc.mElementCount = MaxOpaqueCount; + desc.mDesc.mStructStride = sizeof(DiffuseMat); + desc.mDesc.mSize = desc.mDesc.mElementCount * desc.mDesc.mStructStride; + desc.ppBuffer = buffer; + addResource(&desc, nullptr); + return true; + }); + + m_objectUniformBuffer[swapChainIndex].Load([&](Buffer** buffer) { + BufferLoadDesc desc = {}; + desc.mDesc.mDescriptors = DESCRIPTOR_TYPE_BUFFER; + desc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; + desc.mDesc.mFlags = BUFFER_CREATION_FLAG_PERSISTENT_MAP_BIT; + desc.mDesc.mFirstElement = 0; + desc.mDesc.mElementCount = MaxObjectUniforms; + desc.mDesc.mStructStride = sizeof(UniformObject); + desc.mDesc.mSize = desc.mDesc.mElementCount * desc.mDesc.mStructStride; + desc.ppBuffer = buffer; + addResource(&desc, nullptr); + return true; + }); + + m_lightClustersBuffer[swapChainIndex].Load([&](Buffer** buffer) { + BufferLoadDesc bufferDesc = {}; + bufferDesc.mDesc.mElementCount = LightClusterLightCount * LightClusterWidth * LightClusterHeight; + bufferDesc.mDesc.mSize = bufferDesc.mDesc.mElementCount * sizeof(uint32_t); + bufferDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_BUFFER_RAW | DESCRIPTOR_TYPE_RW_BUFFER; + bufferDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_ONLY; + bufferDesc.mDesc.mFirstElement = 0; + bufferDesc.mDesc.mStructStride = sizeof(uint32_t); + bufferDesc.mDesc.mStartState = RESOURCE_STATE_UNORDERED_ACCESS; + bufferDesc.mDesc.pName = "Light Cluster"; + bufferDesc.ppBuffer = buffer; + addResource(&bufferDesc, nullptr); + return true; + }); + + m_lightClusterCountBuffer[swapChainIndex].Load([&](Buffer** buffer) { + BufferLoadDesc bufferDesc = {}; + bufferDesc.mDesc.mElementCount = LightClusterWidth * LightClusterHeight; + bufferDesc.mDesc.mSize = bufferDesc.mDesc.mElementCount * sizeof(uint32_t); + bufferDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_BUFFER_RAW | DESCRIPTOR_TYPE_RW_BUFFER; + bufferDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_GPU_ONLY; + bufferDesc.mDesc.mFirstElement = 0; + bufferDesc.mDesc.mStructStride = sizeof(uint32_t); + bufferDesc.mDesc.mStartState = RESOURCE_STATE_UNORDERED_ACCESS; + bufferDesc.pData = nullptr; + bufferDesc.mDesc.pName = "Light Cluster Count"; + bufferDesc.ppBuffer = buffer; + addResource(&bufferDesc, nullptr); + return true; + }); + m_pointLightBuffer[swapChainIndex].Load([&](Buffer** buffer) { + BufferLoadDesc bufferDesc = {}; + bufferDesc.mDesc.mDescriptors = DESCRIPTOR_TYPE_BUFFER_RAW | DESCRIPTOR_TYPE_RW_BUFFER; + bufferDesc.mDesc.mMemoryUsage = RESOURCE_MEMORY_USAGE_CPU_TO_GPU; + bufferDesc.mDesc.mFirstElement = 0; + bufferDesc.mDesc.mStructStride = sizeof(PointLightData); + bufferDesc.mDesc.mElementCount = PointLightCount; + bufferDesc.mDesc.mSize = bufferDesc.mDesc.mElementCount * bufferDesc.mDesc.mStructStride; + bufferDesc.mDesc.mStartState = RESOURCE_STATE_UNORDERED_ACCESS; + bufferDesc.pData = nullptr; + bufferDesc.mDesc.pName = "Point Light"; + bufferDesc.ppBuffer = buffer; + addResource(&bufferDesc, nullptr); + return true; + }); + } + + { + RasterizerStateDesc rasterizerStateDesc = {}; + rasterizerStateDesc.mCullMode = CULL_MODE_FRONT; + rasterizerStateDesc.mFrontFace = FRONT_FACE_CCW; + + VertexLayout vertexLayout = {}; +#ifndef USE_THE_FORGE_LEGACY + vertexLayout.mBindingCount = 4; + vertexLayout.mBindings[0].mStride = sizeof(float3); + vertexLayout.mBindings[1].mStride = sizeof(float2); + vertexLayout.mBindings[2].mStride = sizeof(float3); + vertexLayout.mBindings[3].mStride = sizeof(float3); +#endif + vertexLayout.mAttribCount = 4; + vertexLayout.mAttribs[0].mSemantic = SEMANTIC_POSITION; + vertexLayout.mAttribs[0].mFormat = TinyImageFormat_R32G32B32_SFLOAT; + vertexLayout.mAttribs[0].mBinding = 0; + vertexLayout.mAttribs[0].mLocation = 0; + vertexLayout.mAttribs[0].mOffset = 0; + + vertexLayout.mAttribs[1].mSemantic = SEMANTIC_TEXCOORD0; + vertexLayout.mAttribs[1].mFormat = TinyImageFormat_R32G32_SFLOAT; + vertexLayout.mAttribs[1].mBinding = 1; + vertexLayout.mAttribs[1].mLocation = 1; + vertexLayout.mAttribs[1].mOffset = 0; + + vertexLayout.mAttribs[2].mSemantic = SEMANTIC_NORMAL; + vertexLayout.mAttribs[2].mFormat = TinyImageFormat_R32G32B32_SFLOAT; + vertexLayout.mAttribs[2].mBinding = 2; + vertexLayout.mAttribs[2].mLocation = 2; + vertexLayout.mAttribs[2].mOffset = 0; + + vertexLayout.mAttribs[3].mSemantic = SEMANTIC_TANGENT; + vertexLayout.mAttribs[3].mFormat = TinyImageFormat_R32G32B32_SFLOAT; + vertexLayout.mAttribs[3].mBinding = 3; + vertexLayout.mAttribs[3].mLocation = 3; + vertexLayout.mAttribs[3].mOffset = 0; + std::array colorFormats = { ColorBufferFormat , TinyImageFormat_R32G32B32A32_SFLOAT}; + + DepthStateDesc depthStateDesc = {}; + depthStateDesc.mDepthTest = true; + depthStateDesc.mDepthWrite = true; + depthStateDesc.mDepthFunc = CMP_LEQUAL; + + PipelineDesc pipelineDesc = {}; + pipelineDesc.mType = PIPELINE_TYPE_GRAPHICS; + auto& pipelineSettings = pipelineDesc.mGraphicsDesc; + pipelineSettings.mPrimitiveTopo = PRIMITIVE_TOPO_TRI_LIST; + pipelineSettings.mRenderTargetCount = colorFormats.size(); + pipelineSettings.pColorFormats = colorFormats.data(); + pipelineSettings.pDepthState = &depthStateDesc; + pipelineSettings.mSampleCount = SAMPLE_COUNT_1; + pipelineSettings.mDepthStencilFormat = DepthBufferFormat; + pipelineSettings.mSampleQuality = 0; + pipelineSettings.pRootSignature = m_diffuseRootSignature.m_handle; + pipelineSettings.pShaderProgram = m_diffuseShader.m_handle; + pipelineSettings.pRasterizerState = &rasterizerStateDesc; + pipelineSettings.pVertexLayout = &vertexLayout; + pipelineSettings.mSupportIndirectCommandBuffer = true; + + m_diffusePipeline.Load(forgeRenderer->Rend(), [&](Pipeline** pipeline) { + addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipeline); + return true; + }); + } + + m_PointLightClusterPipeline.Load(forgeRenderer->Rend(), [&](Pipeline** pipeline) { + PipelineDesc pipelineDesc = {}; + pipelineDesc.mType = PIPELINE_TYPE_COMPUTE; + ComputePipelineDesc& computePipelineDesc = pipelineDesc.mComputeDesc; + computePipelineDesc.pShaderProgram = m_pointlightClusterShader.m_handle; + computePipelineDesc.pRootSignature = m_lightClusterRootSignature.m_handle; + addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipeline); + return true; + }); + m_clearClusterPipeline.Load(forgeRenderer->Rend(), [&](Pipeline** pipeline) { + PipelineDesc pipelineDesc = {}; + pipelineDesc.mType = PIPELINE_TYPE_COMPUTE; + ComputePipelineDesc& computePipelineDesc = pipelineDesc.mComputeDesc; + computePipelineDesc.pShaderProgram = m_clearClusterShader.m_handle; + computePipelineDesc.pRootSignature = m_lightClusterRootSignature.m_handle; + addPipeline(forgeRenderer->Rend(), &pipelineDesc, pipeline); + return true; + }); + + for (size_t swapChainIndex = 0; swapChainIndex < ForgeRenderer::SwapChainLength; swapChainIndex++) { + m_opaqueFrameSet[swapChainIndex].Load(forgeRenderer->Rend(), [&](DescriptorSet** descSet) { + DescriptorSetDesc perFrameDescSet{ m_diffuseRootSignature.m_handle, + DESCRIPTOR_UPDATE_FREQ_PER_FRAME, + MaxViewportFrameDescriptors }; + addDescriptorSet(forgeRenderer->Rend(), &perFrameDescSet, descSet); + return true; + }); + m_opaqueConstSet[swapChainIndex].Load(forgeRenderer->Rend(), [&](DescriptorSet** descriptorSet) { + DescriptorSetDesc constSetDesc{ m_diffuseRootSignature.m_handle, + DESCRIPTOR_UPDATE_FREQ_NONE, + 1 }; + addDescriptorSet(forgeRenderer->Rend(), &constSetDesc, descriptorSet); + return true; + }); + { + + std::array params = { + DescriptorData {.pName = "sceneObjects", .ppBuffers = &m_objectUniformBuffer[swapChainIndex].m_handle}, + DescriptorData {.pName = "opaqueMaterial", .ppBuffers = &m_opaqueMaterialBuffer.m_handle}, + }; + updateDescriptorSet( + forgeRenderer->Rend(), 0, m_opaqueConstSet[swapChainIndex].m_handle, params.size(), params.data()); + } + + + for (size_t i = 0; i < MaxViewportFrameDescriptors; i++) { + std::array params = { + DescriptorData {.pName = "pointLights", .ppBuffers = &m_pointLightBuffer[swapChainIndex].m_handle}, + DescriptorData {.pName = "lightClustersCount", .ppBuffers = &m_lightClusterCountBuffer[swapChainIndex].m_handle}, + DescriptorData {.pName = "lightClusters", .ppBuffers = &m_lightClustersBuffer[swapChainIndex].m_handle}, + DescriptorData {.pName = "perFrameConstants", .ppBuffers = &m_perFrameBuffer[i].m_handle}, + }; + updateDescriptorSet( + forgeRenderer->Rend(), i, m_opaqueFrameSet[swapChainIndex].m_handle, params.size(), params.data()); + } + + m_perFrameLightCluster[swapChainIndex].Load(forgeRenderer->Rend(), [&](DescriptorSet** descSet) { + DescriptorSetDesc perFrameDescSet{ m_lightClusterRootSignature.m_handle, + DESCRIPTOR_UPDATE_FREQ_PER_FRAME, + MaxViewportFrameDescriptors }; + addDescriptorSet(forgeRenderer->Rend(), &perFrameDescSet, descSet); + return true; + }); + for (size_t i = 0; i < MaxViewportFrameDescriptors; i++) { + std::array params = { + DescriptorData {.pName = "perFrameConstants", .ppBuffers = &m_perFrameBuffer[i].m_handle}, + DescriptorData {.pName = "pointLights", .ppBuffers = &m_pointLightBuffer[swapChainIndex].m_handle}, + DescriptorData {.pName = "lightClustersCount", .ppBuffers = &m_lightClusterCountBuffer[swapChainIndex].m_handle}, + DescriptorData {.pName = "lightClusters", .ppBuffers = &m_lightClustersBuffer[swapChainIndex].m_handle}, + }; + updateDescriptorSet( + forgeRenderer->Rend(), i, m_perFrameLightCluster[swapChainIndex].m_handle, params.size(), params.data()); + } + } + } + RendererForwardPlus::~RendererForwardPlus() { + } + + uint32_t RendererForwardPlus::resolveObjectId( + const ForgeRenderer::Frame& frame, + cMaterial* apMaterial, + iRenderable* apObject, + std::optional modelMatrix) { + uint32_t id = folly::hash::fnv32_buf( + reinterpret_cast(apObject), + sizeof(apObject), + modelMatrix.has_value() ? folly::hash::fnv32_buf(modelMatrix->v, sizeof(modelMatrix->v)) : folly::hash::fnv32_hash_start); + + auto objectLookup = m_objectDescriptorLookup.find(apObject); + auto& materialDesc = apMaterial->Descriptor(); + + + auto metaInfo = std::find_if(cMaterial::MaterialMetaTable.begin(), cMaterial::MaterialMetaTable.end(), [&](auto& info) { + return info.m_id == materialDesc.m_id; + }); + + const bool isFound = objectLookup != m_objectDescriptorLookup.end(); + uint32_t index = isFound ? objectLookup->second : m_objectIndex++; + if (!isFound) { + cMatrixf modelMat = modelMatrix.value_or(apObject->GetModelMatrixPtr() ? *apObject->GetModelMatrixPtr() : cMatrixf::Identity); + + UniformObject uniformObjectData = {}; + uniformObjectData.m_dissolveAmount = apObject->GetCoverageAmount(); + uniformObjectData.m_materialIndex = apMaterial->Index(); + uniformObjectData.m_modelMat = cMath::ToForgeMatrix4(modelMat); + uniformObjectData.m_invModelMat = cMath::ToForgeMatrix4(cMath::MatrixInverse(modelMat)); + uniformObjectData.m_lightLevel = 1.0f; + uniformObjectData.m_materialIndex = resolveMaterialID(frame, apMaterial); + if(apMaterial) { + uniformObjectData.m_uvMat = cMath::ToForgeMatrix4(apMaterial->GetUvMatrix().GetTranspose()); + } else { + uniformObjectData.m_uvMat = Matrix4::identity(); + } + BufferUpdateDesc updateDesc = { m_objectUniformBuffer[frame.m_frameIndex].m_handle, + sizeof(UniformObject) * index }; + beginUpdateResource(&updateDesc); + (*reinterpret_cast(updateDesc.pMappedData)) = uniformObjectData; + endUpdateResource(&updateDesc, NULL); + + m_objectDescriptorLookup[apObject] = index; + } + return index; + } + void RendererForwardPlus::Draw( + Cmd* cmd, + const ForgeRenderer::Frame& frame, + cViewport& viewport, + float frameTime, + cFrustum* apFrustum, + cWorld* apWorld, + cRenderSettings* apSettings, + bool abSendFrameBufferToPostEffects) { + auto* forgeRenderer = Interface::Get(); + auto* graphicsAllocator = Interface::Get(); + // keep around for the moment ... + BeginRendering(frameTime, apFrustum, apWorld, apSettings, abSendFrameBufferToPostEffects); + + if (frame.m_currentFrame != m_activeFrame) { + m_objectIndex = 0; + m_sceneTextureDisposable.reset([&](SharedTexture& texture, IndexPoolHandle& handler) { + + }); + m_objectDescriptorLookup.clear(); + m_activeFrame = frame.m_currentFrame; + } + const Matrix4 mainFrustumViewInvMat = inverse(apFrustum->GetViewMat()); + const Matrix4 mainFrustumViewMat = apFrustum->GetViewMat(); + const Matrix4 mainFrustumProjMat = apFrustum->GetProjectionMat(); + + auto common = m_boundViewportData.resolve(viewport); + if (!common || common->m_size != viewport.GetSizeU2()) { + auto viewportData = std::make_unique(); + viewportData->m_size = viewport.GetSizeU2(); + for (auto& buffer : viewportData->m_outputBuffer) { + buffer.Load(forgeRenderer->Rend(), [&](RenderTarget** target) { + ClearValue optimizedColorClearBlack = { { 0.0f, 0.0f, 0.0f, 0.0f } }; + RenderTargetDesc renderTargetDesc = {}; + renderTargetDesc.mArraySize = 1; + renderTargetDesc.mClearValue = optimizedColorClearBlack; + renderTargetDesc.mDepth = 1; + renderTargetDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE; + renderTargetDesc.mWidth = viewportData->m_size.x; + renderTargetDesc.mHeight = viewportData->m_size.y; + renderTargetDesc.mSampleCount = SAMPLE_COUNT_1; + renderTargetDesc.mSampleQuality = 0; + renderTargetDesc.mStartState = RESOURCE_STATE_SHADER_RESOURCE; + renderTargetDesc.mFormat = TinyImageFormat_R8G8B8A8_UNORM; + renderTargetDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE; + addRenderTarget(forgeRenderer->Rend(), &renderTargetDesc, target); + return true; + }); + } + for (auto& buffer : viewportData->m_depthBuffer) { + buffer.Load(forgeRenderer->Rend(), [&](RenderTarget** handle) { + RenderTargetDesc renderTargetDesc = {}; + renderTargetDesc.mArraySize = 1; + renderTargetDesc.mClearValue = { .depth = 1.0f, .stencil = 0 }; + renderTargetDesc.mDepth = 1; + renderTargetDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE; + renderTargetDesc.mWidth = viewportData->m_size.x; + renderTargetDesc.mHeight = viewportData->m_size.y; + renderTargetDesc.mSampleCount = SAMPLE_COUNT_1; + renderTargetDesc.mSampleQuality = 0; + renderTargetDesc.mFormat = DepthBufferFormat; + renderTargetDesc.mStartState = RESOURCE_STATE_DEPTH_WRITE; + renderTargetDesc.pName = "Depth RT"; + addRenderTarget(forgeRenderer->Rend(), &renderTargetDesc, handle); + return true; + }); + } + for (auto& buffer : viewportData->m_testBuffer) { + buffer.Load(forgeRenderer->Rend(), [&](RenderTarget** handle) { + RenderTargetDesc renderTargetDesc = {}; + renderTargetDesc.mArraySize = 1; + renderTargetDesc.mClearValue = { .depth = 1.0f, .stencil = 0 }; + renderTargetDesc.mDepth = 1; + renderTargetDesc.mDescriptors = DESCRIPTOR_TYPE_TEXTURE; + renderTargetDesc.mWidth = viewportData->m_size.x; + renderTargetDesc.mHeight = viewportData->m_size.y; + renderTargetDesc.mSampleCount = SAMPLE_COUNT_1; + renderTargetDesc.mSampleQuality = 0; + renderTargetDesc.mFormat = TinyImageFormat_R32G32B32A32_SFLOAT; + renderTargetDesc.mStartState = RESOURCE_STATE_RENDER_TARGET; + addRenderTarget(forgeRenderer->Rend(), &renderTargetDesc, handle); + return true; + }); + } + common = m_boundViewportData.update(viewport, std::move(viewportData)); + } + uint32_t mainFrameIndex = updateFrameDescriptor(frame, frame.m_cmd, apWorld, { + .m_size = float2(common->m_size.x, common->m_size.y), + .m_viewMat = mainFrustumViewMat, + .m_projectionMat = mainFrustumProjMat + }); + + m_rendererList.BeginAndReset(frameTime, apFrustum); + struct RenderableContainer { + iRenderableContainer* m_continer; + eWorldContainerType m_type; + }; + std::array worldContainers = { + RenderableContainer{ apWorld->GetRenderableContainer(eWorldContainerType_Dynamic), eWorldContainerType_Dynamic }, + RenderableContainer{ apWorld->GetRenderableContainer(eWorldContainerType_Static), eWorldContainerType_Static } + }; + + for (auto& container : worldContainers) { + container.m_continer->UpdateBeforeRendering(); + } + std::function walkRenderables; + walkRenderables = [&](iRenderableContainerNode* childNode, eWorldContainerType containerType) { + childNode->UpdateBeforeUse(); + for (auto& childNode : childNode->GetChildNodes()) { + childNode->UpdateBeforeUse(); + eCollision frustumCollision = apFrustum->CollideNode(childNode); + if (frustumCollision == eCollision_Outside) { + continue; + } + if (apFrustum->CheckAABBNearPlaneIntersection(childNode->GetMin(), childNode->GetMax())) { + cVector3f vViewSpacePos = cMath::MatrixMul(apFrustum->GetViewMatrix(), childNode->GetCenter()); + childNode->SetViewDistance(vViewSpacePos.z); + childNode->SetInsideView(true); + } else { + // Frustum origin is outside of node. Do intersection test. + cVector3f vIntersection; + cMath::CheckAABBLineIntersection( + childNode->GetMin(), childNode->GetMax(), apFrustum->GetOrigin(), childNode->GetCenter(), &vIntersection, NULL); + cVector3f vViewSpacePos = cMath::MatrixMul(apFrustum->GetViewMatrix(), vIntersection); + childNode->SetViewDistance(vViewSpacePos.z); + childNode->SetInsideView(false); + } + walkRenderables(childNode, containerType); + } + for (auto& pObject : childNode->GetObjects()) { + if (!rendering::detail::IsObjectIsVisible(pObject, eRenderableFlag_VisibleInNonReflection, {})) { + continue; + } + cMaterial* pMaterial = pObject->GetMaterial(); + m_rendererList.AddObject(pObject); + + if (pObject && pObject->GetRenderFrameCount() != iRenderer::GetRenderFrameCount()) { + pObject->SetRenderFrameCount(iRenderer::GetRenderFrameCount()); + pObject->UpdateGraphicsForFrame(frameTime); + } + + if (pMaterial && pMaterial->GetRenderFrameCount() != iRenderer::GetRenderFrameCount()) { + pMaterial->SetRenderFrameCount(iRenderer::GetRenderFrameCount()); + pMaterial->UpdateBeforeRendering(frameTime); + } + //////////////////////////////////////// + // Update per viewport specific and set amtrix point + // Skip this for non-decal translucent! This is because the water rendering might mess it up otherwise! + if (pMaterial == NULL || cMaterial::IsTranslucent(pMaterial->Descriptor().m_id) == false || + pMaterial->Descriptor().m_id == MaterialID::Decal) { + // skip rendering if the update return false + if (pObject->UpdateGraphicsForViewport(apFrustum, frameTime) == false) { + return; + } + + pObject->SetModelMatrixPtr(pObject->GetModelMatrix(apFrustum)); + } + // Only set a matrix used for sorting. Calculate the proper in the trans rendering! + else { + pObject->SetModelMatrixPtr(pObject->GetModelMatrix(NULL)); + } + } + }; + for (auto& it : worldContainers) { + iRenderableContainerNode* pNode = it.m_continer->GetRoot(); + pNode->UpdateBeforeUse(); // Make sure node is updated. + pNode->SetInsideView(true); // We never want to check root! Assume player is inside. + walkRenderables(pNode, it.m_type); + } + m_rendererList.End( + eRenderListCompileFlag_Diffuse | eRenderListCompileFlag_Translucent | eRenderListCompileFlag_Decal | + eRenderListCompileFlag_Illumination | eRenderListCompileFlag_FogArea); + // prepare point light data + + // diffuse + { + auto diffuseItems = m_rendererList.GetRenderableItems(eRenderListType_Diffuse); + BufferUpdateDesc updateDesc = { m_indirectDrawArgsBuffer[frame.m_frameIndex].m_handle, + 0, + sizeof(IndirectDrawIndexArguments) * diffuseItems.size()}; + beginUpdateResource(&updateDesc); + for (size_t i = 0; i < diffuseItems.size(); i++) { + cMaterial* pMaterial = diffuseItems[i]->GetMaterial(); + std::array targets = { eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + eVertexBufferElement_Normal, + eVertexBufferElement_Texture1Tangent }; + DrawPacket packet = diffuseItems[i]->ResolveDrawPacket(frame, targets); + if (pMaterial == nullptr || packet.m_type == DrawPacket::Unknown) { + continue; + } + ASSERT(pMaterial->Descriptor().m_id == MaterialID::SolidDiffuse && "Invalid material type"); + ASSERT(packet.m_type == DrawPacket::DrawPacketType::DrawGeometryset); + ASSERT(packet.m_unified.m_set == GraphicsAllocator::AllocationSet::OpaqueSet); + + auto& args = reinterpret_cast(updateDesc.pMappedData)[i]; + args.mIndexCount = packet.m_unified.m_numIndices; + args.mStartIndex = packet.m_unified.m_subAllocation->indexOffset(); + args.mVertexOffset = packet.m_unified.m_subAllocation->vertextOffset(); + args.mStartInstance = resolveObjectId(frame, pMaterial, diffuseItems[i], {}); // for DX12 this won't work + args.mInstanceCount = 1; + } + endUpdateResource(&updateDesc, nullptr); + } + + { + auto lights = m_rendererList.GetLights(); + uint32_t numPointLights = std::count_if(lights.begin(), lights.end(), [&](auto& light) { + return light->GetLightType() == eLightType_Point; + }); + { + uint32_t pointLightIndex = 0; + BufferUpdateDesc pointlightUpdateDesc = { m_pointLightBuffer[frame.m_frameIndex].m_handle, + 0, + sizeof(PointLightData) * numPointLights}; + beginUpdateResource(&pointlightUpdateDesc); + for(auto& light: m_rendererList.GetLights()) { + switch(light->GetLightType()) { + case eLightType_Point: { + m_pointLightAttenutation[frame.m_frameIndex][pointLightIndex] = light->GetFalloffMap()->GetTexture(); + + auto& data = reinterpret_cast(pointlightUpdateDesc.pMappedData)[pointLightIndex++]; + const cColor color = light->GetDiffuseColor(); + data.m_radius = light->GetRadius(); + data.m_lightPos = v3ToF3(cMath::ToForgeVec3(light->GetWorldPosition())); + data.m_lightColor = float4(color.r, color.g, color.b, color.a); + break; + } + default: + break; + } + } + endUpdateResource(&pointlightUpdateDesc, nullptr); + } + cmdBindRenderTargets(cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + + uint32_t rootConstantIndex = getDescriptorIndexFromName(m_lightClusterRootSignature.m_handle, "uRootConstants"); + cmdBindDescriptorSet(cmd, mainFrameIndex, m_perFrameLightCluster[frame.m_frameIndex].m_handle); + cmdBindPushConstants(frame.m_cmd, m_lightClusterRootSignature.m_handle, rootConstantIndex, &common->m_size); + cmdBindPipeline(cmd, m_clearClusterPipeline.m_handle); + cmdDispatch(cmd, 1, 1, 1); + { + std::array barriers = { BufferBarrier{ m_lightClusterCountBuffer[frame.m_frameIndex].m_handle, + RESOURCE_STATE_UNORDERED_ACCESS, + RESOURCE_STATE_UNORDERED_ACCESS } }; + cmdResourceBarrier( + cmd, barriers.size(), barriers.data(), 0, nullptr, 0, nullptr); + } + + cmdBindDescriptorSet(frame.m_cmd, mainFrameIndex, m_perFrameLightCluster[frame.m_frameIndex].m_handle); + cmdBindPipeline(cmd, m_PointLightClusterPipeline.m_handle); + cmdDispatch(cmd, numPointLights, 1, 1); + } + { + cmdBindRenderTargets(cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + std::array bufferBarrier = { + BufferBarrier{ m_lightClustersBuffer[frame.m_frameIndex].m_handle, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE }, + BufferBarrier{ m_lightClusterCountBuffer[frame.m_frameIndex].m_handle, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE }, + BufferBarrier{ m_pointLightBuffer[frame.m_frameIndex].m_handle, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE }, + }; + std::array rtBarriers = { + RenderTargetBarrier{ common->m_outputBuffer[frame.m_frameIndex].m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_RENDER_TARGET }, + }; + cmdResourceBarrier( + cmd, bufferBarrier.size(), bufferBarrier.data(), 0, NULL, rtBarriers.size(), rtBarriers.data()); + } + { + auto diffuseItems = m_rendererList.GetRenderableItems(eRenderListType_Diffuse); + auto& opaqueSet = graphicsAllocator->resolveSet(GraphicsAllocator::AllocationSet::OpaqueSet); + + std::array semantics = { ShaderSemantic::SEMANTIC_POSITION, + ShaderSemantic::SEMANTIC_TEXCOORD0, + ShaderSemantic::SEMANTIC_NORMAL, + ShaderSemantic::SEMANTIC_NORMAL }; + cmdBeginDebugMarker(cmd, 0, 1, 0, "Forward Diffuse Pass"); + LoadActionsDesc loadActions = {}; + loadActions.mLoadActionsColor[0] = LOAD_ACTION_CLEAR; + loadActions.mLoadActionsColor[1] = LOAD_ACTION_CLEAR; + loadActions.mClearColorValues[0] = { .r = 0.0f, .g = 0.0f, .b = 0.0f, .a = 0.0f }; + loadActions.mClearDepth = { .depth = 1.0f, .stencil = 0 }; + loadActions.mLoadActionDepth = LOAD_ACTION_CLEAR; + std::array targets = { + common->m_outputBuffer[frame.m_frameIndex].m_handle, + common->m_testBuffer[frame.m_frameIndex].m_handle + }; + cmdBindRenderTargets(cmd, targets.size(), targets.data(), common->m_depthBuffer[frame.m_frameIndex].m_handle, &loadActions, NULL, NULL, -1, -1); + cmdSetViewport(cmd, 0.0f, 0.0f, common->m_size.x, common->m_size.y, 0.0f, 1.0f); + cmdSetScissor(cmd, 0, 0, common->m_size.x, common->m_size.y); + + cmdBindPipeline(cmd, m_diffusePipeline.m_handle); + opaqueSet.cmdBindGeometrySet(cmd, semantics); + cmdBindIndexBuffer(cmd, opaqueSet.indexBuffer().m_handle, INDEX_TYPE_UINT32, 0); + cmdBindDescriptorSet(cmd, 0, m_opaqueConstSet[frame.m_frameIndex].m_handle); + cmdBindDescriptorSet(cmd, mainFrameIndex, m_opaqueFrameSet[frame.m_frameIndex].m_handle); + cmdExecuteIndirect( + cmd, m_cmdSignatureVBPass, diffuseItems.size(), m_indirectDrawArgsBuffer[frame.m_frameIndex].m_handle, 0, nullptr, 0); + cmdEndDebugMarker(cmd); + } + { + cmdBindRenderTargets(cmd, 0, NULL, NULL, NULL, NULL, NULL, -1, -1); + std::array bufferBarrier = { + BufferBarrier{ m_lightClustersBuffer[frame.m_frameIndex].m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS }, + BufferBarrier{ m_lightClusterCountBuffer[frame.m_frameIndex].m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS }, + BufferBarrier{ m_pointLightBuffer[frame.m_frameIndex].m_handle, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS }, + }; + std::array rtBarriers = { + RenderTargetBarrier{ common->m_outputBuffer[frame.m_frameIndex].m_handle, RESOURCE_STATE_RENDER_TARGET ,RESOURCE_STATE_SHADER_RESOURCE}, + }; + cmdResourceBarrier( + cmd, bufferBarrier.size(), bufferBarrier.data(), 0, NULL, rtBarriers.size(), rtBarriers.data()); + } + + } + + uint32_t RendererForwardPlus::resolveMaterialID(const ForgeRenderer::Frame& frame,cMaterial* material) { + auto* forgeRenderer = Interface::Get(); + auto& sceneMaterial = m_sceneMaterial[material->Index()]; + uint8_t writeMask = 1 << frame.m_frameIndex; + if (sceneMaterial.m_material != material || + sceneMaterial.m_version != material->Generation() || + (sceneMaterial.m_writeMask & writeMask) == 0) { + + auto& descriptor = material->Descriptor(); + sceneMaterial.m_version = material->Generation(); + sceneMaterial.m_material = material; + + if(sceneMaterial.m_writeMask == 0) { + sceneMaterial.m_materialIndex = IndexPoolHandle(&m_opaqueMaterialPool); + for(auto& res: sceneMaterial.m_sceneTextures) { + if(res.m_handle.isValid()) { + m_sceneTextureDisposable.push(std::move(res.m_texture), std::move(res.m_handle)); + } + } + sceneMaterial.m_sceneTextures[eMaterialTexture_Diffuse] = SceneMaterial::SceneTextureEntry { + IndexPoolHandle(&m_sceneTexturePool), material->GetImage(eMaterialTexture_Diffuse)->GetTexture() + }; + } + sceneMaterial.m_writeMask |= writeMask; + for(auto& scene: sceneMaterial.m_sceneTextures) { + if(scene.m_handle.isValid()) { + std::array params = { + DescriptorData {.pName = "sceneTextures", .mCount = 1, .mArrayOffset = scene.m_handle.get(), .ppTextures = &scene.m_texture.m_handle } + }; + updateDescriptorSet( + forgeRenderer->Rend(), + 0, + m_opaqueConstSet[frame.m_frameIndex].m_handle, + params.size(), + params.data()); + } + } + { + BufferUpdateDesc updateDesc = { m_opaqueMaterialBuffer.m_handle, + sizeof(DiffuseMat) * sceneMaterial.m_materialIndex.get()}; + beginUpdateResource(&updateDesc); + auto& material = (*reinterpret_cast(updateDesc.pMappedData)); + material.m_texture[0] = sceneMaterial.m_sceneTextures[eMaterialTexture_Diffuse].m_handle.get(); + endUpdateResource(&updateDesc, NULL); + } + } + return sceneMaterial.m_materialIndex.get(); + //return (sceneMaterial.m_materialIndex.get() << 8) | static_cast(sceneMaterial.m_id) ; + } + + uint32_t RendererForwardPlus::updateFrameDescriptor( const ForgeRenderer::Frame& frame, Cmd* cmd, cWorld* apWorld, const PerFrameOption& options) { + uint32_t index = m_frameIndex; + BufferUpdateDesc updatePerFrameConstantsDesc = { m_perFrameBuffer[index].m_handle, 0 }; + beginUpdateResource(&updatePerFrameConstantsDesc); + auto* uniformFrameData = reinterpret_cast(updatePerFrameConstantsDesc.pMappedData); + uniformFrameData->m_viewMatrix = options.m_viewMat; + uniformFrameData->m_invViewMatrix = inverse(options.m_viewMat); + uniformFrameData->m_projectionMatrix = options.m_projectionMat; + uniformFrameData->m_viewProjectionMatrix = options.m_projectionMat * options.m_viewMat; + + uniformFrameData->worldFogStart = apWorld->GetFogStart(); + uniformFrameData->worldFogLength = apWorld->GetFogEnd() - apWorld->GetFogStart(); + uniformFrameData->oneMinusFogAlpha = 1.0f - apWorld->GetFogColor().a; + uniformFrameData->fogFalloffExp = apWorld->GetFogFalloffExp(); + + uniformFrameData->m_invViewRotation = Matrix4(Matrix4::identity()).setUpper3x3(transpose(options.m_viewMat).getUpper3x3()); + uniformFrameData->viewTexel = float2(1.0f / options.m_size.x, 1.0f / options.m_size.y); + uniformFrameData->viewportSize = float2(options.m_size.x, options.m_size.y); + uniformFrameData->afT = GetTimeCount(); + const auto fogColor = apWorld->GetFogColor(); + uniformFrameData->fogColor = float4(fogColor.r, fogColor.g, fogColor.b, fogColor.a); + endUpdateResource(&updatePerFrameConstantsDesc, NULL); + m_frameIndex = (m_frameIndex + 1) % MaxViewportFrameDescriptors; + return index; + } +} // namespace hpl diff --git a/HPL2/sources/graphics/RendererWireFrame.cpp b/HPL2/sources/graphics/RendererWireFrame.cpp index 071c64789..22af198f5 100644 --- a/HPL2/sources/graphics/RendererWireFrame.cpp +++ b/HPL2/sources/graphics/RendererWireFrame.cpp @@ -192,13 +192,6 @@ namespace hpl { cRendererWireFrame::~cRendererWireFrame() { } - bool cRendererWireFrame::LoadData() { - return true; - } - - void cRendererWireFrame::DestroyData() { - } - uint32_t cRendererWireFrame::prepareObjectData(const ForgeRenderer::Frame& frame, iRenderable* apObject) { auto objectLookup = m_objectDescriptorLookup.find(apObject); const bool isFound = objectLookup != m_objectDescriptorLookup.end(); @@ -336,7 +329,7 @@ namespace hpl { DrawPacket::cmdBindBuffers(frame.m_cmd, frame.m_resourcePool, &packet); uint32_t objectIndex = prepareObjectData(frame, diffuseItem); cmdBindPushConstants(frame.m_cmd, m_rootSignature.m_handle, rootConstantIndex, &objectIndex); - cmdDrawIndexed(frame.m_cmd, packet.m_numIndices, 0, 0); + cmdDrawIndexed(frame.m_cmd, packet.numberOfIndecies(), 0, 0); } cViewport::PostSolidDrawPacket postSolidEvent = cViewport::PostSolidDrawPacket(); diff --git a/HPL2/sources/impl/LegacyVertexBuffer.cpp b/HPL2/sources/impl/LegacyVertexBuffer.cpp index 770e7648c..03a7facfd 100644 --- a/HPL2/sources/impl/LegacyVertexBuffer.cpp +++ b/HPL2/sources/impl/LegacyVertexBuffer.cpp @@ -455,7 +455,7 @@ namespace hpl { DrawPacket LegacyVertexBuffer::resolveGeometryBinding( uint32_t frameIndex, std::span elements) { DrawPacket packet; - packet.m_type = DrawPacket::IndvidualBindings; + packet.m_type = DrawPacket::DrawIndvidualBuffers; if(m_updateFlags) { for (auto& element : m_vertexElements) { const bool isDynamicAccess = detail::IsDynamicMemory(mUsageType); @@ -542,7 +542,7 @@ namespace hpl { } uint32_t numIndecies = (GetRequestNumberIndecies() > 0) ? GetRequestNumberIndecies() : static_cast(m_indices.size()) ; packet.m_indvidual.m_indexStream.m_offset = m_indexBufferActiveCopy * m_indices.size() * sizeof(uint32_t); - packet.m_numIndices = numIndecies; + packet.m_indvidual.m_numIndices = numIndecies; packet.m_indvidual.m_indexStream.buffer = &m_indexBuffer; return packet; } diff --git a/HPL2/sources/resources/MaterialManager.cpp b/HPL2/sources/resources/MaterialManager.cpp index e0bc3c090..f720284e4 100644 --- a/HPL2/sources/resources/MaterialManager.cpp +++ b/HPL2/sources/resources/MaterialManager.cpp @@ -378,7 +378,7 @@ namespace hpl { for (auto& meta : cMaterial::MaterialMetaTable) { if (normalizedMaterialName == meta.m_name) { pMat->SetHandle(IndexPoolHandle(&internal::m_MaterialIndexPool)); - MaterialDescriptor materialDescriptor; + ShaderMaterialData materialDescriptor; materialDescriptor.m_id = meta.m_id; switch (meta.m_id) { case MaterialID::SolidDiffuse: diff --git a/HPL2/sources/scene/SubMeshEntity.cpp b/HPL2/sources/scene/SubMeshEntity.cpp index 85d8e4a70..814ef4547 100644 --- a/HPL2/sources/scene/SubMeshEntity.cpp +++ b/HPL2/sources/scene/SubMeshEntity.cpp @@ -71,7 +71,7 @@ namespace hpl { auto& opaqueSet = graphicsAllocator->resolveSet(GraphicsAllocator::AllocationSet::OpaqueSet); m_numberVertices = vertexStreams.begin()->m_numberElements; - m_numberIndecies = indexStream.m_numberElements; + m_numberIndecies = indexStream.m_numberElements; m_geometry = opaqueSet.allocate(m_numberVertices * (m_isSkinnedMesh ? 2 : 1), m_numberIndecies); for(auto& localStream: vertexStreams) { @@ -83,9 +83,9 @@ namespace hpl { GraphicsBuffer gpuBuffer(updateDesc); auto dest = gpuBuffer.CreateViewRaw(); - auto source = localStream.m_buffer.CreateViewRaw(); + auto src = localStream.m_buffer.CreateViewRaw(); for(size_t i = 0; i < m_numberVertices; i++) { - auto sp = source.rawByteSpan().subspan(i * localStream.m_stride, std::min(gpuStream->stride(), localStream.m_stride)); + auto sp = src.rawByteSpan().subspan(i * localStream.m_stride, std::min(gpuStream->stride(), localStream.m_stride)); dest.WriteRaw(i * gpuStream->stride(), sp); } endUpdateResource(&updateDesc, nullptr); @@ -156,18 +156,12 @@ namespace hpl { mbGraphicsUpdated = true; auto staticBindBuffers = mpSubMesh->streamBuffers(); - auto bindPositionIt = std::find_if(staticBindBuffers.begin(), staticBindBuffers.end(), [&](auto& stream) { - return stream.m_semantic == ShaderSemantic::SEMANTIC_POSITION; - }); - auto bindNormalIt = std::find_if(staticBindBuffers.begin(), staticBindBuffers.end(), [&](auto& stream) { - return stream.m_semantic == ShaderSemantic::SEMANTIC_NORMAL; - }); - auto bindTangentIt = std::find_if(staticBindBuffers.begin(), staticBindBuffers.end(), [&](auto& stream) { - return stream.m_semantic == ShaderSemantic::SEMANTIC_TANGENT; - }); - ASSERT(bindPositionIt != staticBindBuffers.end() && - bindNormalIt != staticBindBuffers.end() && - bindTangentIt != staticBindBuffers.end() + auto bindPositionIt = mpSubMesh->getStreamBySemantic(ShaderSemantic::SEMANTIC_POSITION); + auto bindNormalIt = mpSubMesh->getStreamBySemantic(ShaderSemantic::SEMANTIC_NORMAL); + auto bindTangentIt = mpSubMesh->getStreamBySemantic(ShaderSemantic::SEMANTIC_TANGENT); + ASSERT(bindPositionIt != mpSubMesh->streamBuffers().end() && + bindNormalIt != mpSubMesh->streamBuffers().end() && + bindTangentIt != mpSubMesh->streamBuffers().end() ); auto bindPositonView = bindPositionIt->GetStructuredView(); // the static buffer data is the fixed pose auto bindNormalView = bindNormalIt->GetStructuredView(); @@ -234,31 +228,16 @@ namespace hpl { return packet; } - packet.m_type = DrawPacket::IndvidualBindings; - packet.m_indvidual.m_numStreams = 0; - for(auto& ele: elements) { - ShaderSemantic semantic = hplToForgeShaderSemantic(ele); - auto found = m_geometry->getStreamBySemantic(semantic); - ASSERT(found != m_geometry->vertexStreams().end()); - auto& stream = packet.m_indvidual.m_vertexStream[packet.m_indvidual.m_numStreams++]; - stream.m_buffer = &found->buffer(); - stream.m_offset = m_geometry->vertextOffset() * found->stride(); - switch(found->semantic()) { - case ShaderSemantic::SEMANTIC_POSITION: - case ShaderSemantic::SEMANTIC_NORMAL: - case ShaderSemantic::SEMANTIC_TANGENT: - stream.m_offset += (m_activeCopy * (m_numberVertices * found->stride())); - break; - default: - break; - - } - - stream.m_stride = found->stride(); - } - packet.m_indvidual.m_indexStream.m_offset = GeometrySet::IndexBufferStride * m_geometry->indexOffset(); - packet.m_indvidual.m_indexStream.buffer = &m_geometry->indexBuffer(); - packet.m_numIndices = m_numberIndecies; + DrawPacket::GeometrySetBinding binding{}; + packet.m_type = DrawPacket::DrawGeometryset; + std::copy(elements.begin(), elements.end(), binding.m_elements); + binding.m_numStreams = elements.size(); + binding.m_subAllocation = m_geometry.get(); + binding.m_indexOffset = 0; + binding.m_set = GraphicsAllocator::AllocationSet::OpaqueSet; + binding.m_numIndices = m_numberIndecies; + binding.m_vertexOffset = (m_activeCopy * m_numberVertices); + packet.m_unified = binding; return packet; } iVertexBuffer* cSubMeshEntity::GetVertexBuffer() diff --git a/amnesia/game/LuxEffectRenderer.cpp b/amnesia/game/LuxEffectRenderer.cpp index 74acdb78d..961506285 100644 --- a/amnesia/game/LuxEffectRenderer.cpp +++ b/amnesia/game/LuxEffectRenderer.cpp @@ -663,7 +663,7 @@ void cLuxEffectRenderer::RenderTrans(cViewport::PostTranslucenceDrawPacket& inp { continue; } - + uint32_t requestSize = round_up(sizeof(LuxEffectObjectUniform::FlashUniform), 256); #ifdef USE_THE_FORGE_LEGACY @@ -698,7 +698,7 @@ void cLuxEffectRenderer::RenderTrans(cViewport::PostTranslucenceDrawPacket& inp cmdBindDescriptorSet(input.m_frame->m_cmd, objectIndex++, m_perObjectDescriptorSet[frame->m_frameIndex]); DrawPacket::cmdBindBuffers(frame->m_cmd, frame->m_resourcePool, &packet); for(size_t i = 0; i < 2; i++) { - cmdDrawIndexed(input.m_frame->m_cmd, packet.m_numIndices, 0, 0); + cmdDrawIndexed(input.m_frame->m_cmd, packet.numberOfIndecies(), 0, 0); } } cmdEndDebugMarker(input.m_frame->m_cmd); @@ -747,7 +747,7 @@ void cLuxEffectRenderer::RenderTrans(cViewport::PostTranslucenceDrawPacket& inp cmdBindDescriptorSet(input.m_frame->m_cmd, objectIndex++, m_perObjectDescriptorSet[frame->m_frameIndex]); DrawPacket::cmdBindBuffers(frame->m_cmd, frame->m_resourcePool, &packet); - cmdDrawIndexed(input.m_frame->m_cmd, packet.m_numIndices, 0, 0); + cmdDrawIndexed(input.m_frame->m_cmd, packet.numberOfIndecies(), 0, 0); } cmdEndDebugMarker(input.m_frame->m_cmd); @@ -817,7 +817,7 @@ void cLuxEffectRenderer::RenderTrans(cViewport::PostTranslucenceDrawPacket& inp cmdBindDescriptorSet(input.m_frame->m_cmd, objectIndex++, m_perObjectDescriptorSet[frame->m_frameIndex]); DrawPacket::cmdBindBuffers(input.m_frame->m_cmd, frame->m_resourcePool, &packet); - cmdDrawIndexed(input.m_frame->m_cmd, packet.m_numIndices, 0, 0); + cmdDrawIndexed(input.m_frame->m_cmd, packet.numberOfIndecies(), 0, 0); } cmdEndDebugMarker(input.m_frame->m_cmd); @@ -869,7 +869,7 @@ void cLuxEffectRenderer::RenderTrans(cViewport::PostTranslucenceDrawPacket& inp cmdBindDescriptorSet(input.m_frame->m_cmd, objectIndex++, m_perObjectDescriptorSet[frame->m_frameIndex]); DrawPacket::cmdBindBuffers(input.m_frame->m_cmd, input.m_frame->m_resourcePool, &drawPacket); - cmdDrawIndexed(input.m_frame->m_cmd, drawPacket.m_numIndices, 0, 0); + cmdDrawIndexed(input.m_frame->m_cmd, drawPacket.numberOfIndecies(), 0, 0); } cmdEndDebugMarker(input.m_frame->m_cmd); From 2705116fd5a439156012651e31c0edf3c8b223e8 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Thu, 2 Nov 2023 21:17:32 -0700 Subject: [PATCH 11/17] feat: add forward resources and basic lights Signed-off-by: Michael Pollind --- HPL2/include/graphics/ForwardResources.h | 49 +++ HPL2/include/graphics/MaterialResource.h | 5 +- HPL2/include/graphics/RenderList.h | 13 +- HPL2/include/graphics/Renderer.h | 2 + HPL2/include/graphics/RendererForwardPlus.h | 35 +- HPL2/include/graphics/TextureDescriptorPool.h | 31 ++ HPL2/resource/ShaderList.fsl | 1 + HPL2/resource/forward_diffuse.frag.fsl | 48 ++- HPL2/resource/forward_resource.h.fsl | 30 +- HPL2/resource/forward_shader_common.h.fsl | 12 +- HPL2/resource/solid_diffuse.frag.fsl | 2 +- HPL2/sources/graphics/ForwardResources.cpp | 80 ++++ HPL2/sources/graphics/RenderList.cpp | 158 -------- HPL2/sources/graphics/Renderer.cpp | 41 +++ HPL2/sources/graphics/RendererDeferred.cpp | 8 +- HPL2/sources/graphics/RendererForwardPlus.cpp | 343 ++++++++++-------- .../graphics/TextureDescriptorPool.cpp | 50 +++ 17 files changed, 560 insertions(+), 348 deletions(-) create mode 100644 HPL2/include/graphics/ForwardResources.h create mode 100644 HPL2/include/graphics/TextureDescriptorPool.h create mode 100644 HPL2/sources/graphics/ForwardResources.cpp create mode 100644 HPL2/sources/graphics/TextureDescriptorPool.cpp diff --git a/HPL2/include/graphics/ForwardResources.h b/HPL2/include/graphics/ForwardResources.h new file mode 100644 index 000000000..bb9d225cc --- /dev/null +++ b/HPL2/include/graphics/ForwardResources.h @@ -0,0 +1,49 @@ +#pragma once + +#include "graphics/GraphicsTypes.h" +#include "graphics/TextureDescriptorPool.h" +#include "scene/LightPoint.h" +#include +#include +#include +#include + +namespace hpl::resource { + class iLight; + struct PointLightResource { + mat4 m_mvp; + float3 m_lightPos; + uint m_config; + float4 m_lightColor; + float m_radius; + }; + using LightResourceVariants = std::variant; + static LightResourceVariants CreateFromLight(iLight& light); + + struct DiffuseMaterial { + union { + uint m_texture[4]; + struct { + uint16_t m_diffues; + uint16_t m_normal; + + uint16_t m_alpha; + uint16_t m_specular; + + uint16_t m_height; + uint16_t m_illuminiation; + + uint16_t m_dissolveAlpha; + uint16_t m_cubeMapAlpha; + } m_tex; + }; + uint m_materialConfig; + float m_heightMapScale; + float m_heigtMapBias; + float m_frenselBias; + float m_frenselPow; + }; + using MaterialTypes = std::variant; + void visitTextures(MaterialTypes& material, std::function handler); + MaterialTypes createMaterial(TextureDescriptorPool& pool, cMaterial* material); +} diff --git a/HPL2/include/graphics/MaterialResource.h b/HPL2/include/graphics/MaterialResource.h index 2f5d36303..051b5ff39 100644 --- a/HPL2/include/graphics/MaterialResource.h +++ b/HPL2/include/graphics/MaterialResource.h @@ -5,8 +5,11 @@ namespace hpl { class cMaterial; - namespace material { + namespace forward { + + } + enum TextureConfigFlags { EnableDiffuse = 1 << 0, EnableNormal = 1 << 1, diff --git a/HPL2/include/graphics/RenderList.h b/HPL2/include/graphics/RenderList.h index f21749172..8c4712252 100644 --- a/HPL2/include/graphics/RenderList.h +++ b/HPL2/include/graphics/RenderList.h @@ -19,7 +19,9 @@ #pragma once #include "graphics/Enum.h" +#include #include +#include #include #include @@ -29,10 +31,17 @@ namespace hpl { class iLight; class cFrustum; class cFogArea; + class iRenderableContainer; + class cRenderList { public: +// static bool DefaultSortZ(iRenderable* apObjectA, iRenderable* apObjectB); +// static bool DefaultSortDiffuse(iRenderable* apObjectA, iRenderable* apObjectB); +// static bool DefaultSortTranslucent(iRenderable* apObjectA, iRenderable* apObjectB); +// static bool DefaultSortDecal(iRenderable* apObjectA, iRenderable* apObjectB); +// static bool DefaultSortIllumination(iRenderable* apObjectA, iRenderable* apObjectB); cRenderList(); ~cRenderList(); @@ -44,9 +53,6 @@ namespace hpl { void AddObject(iRenderable *apObject); - [[deprecated("Use End")]] - void Compile(tRenderListCompileFlag aFlags); - bool ArrayHasObjects(eRenderListType aType); std::span GetRenderableItems(eRenderListType aType); @@ -59,6 +65,7 @@ namespace hpl { void BeginAndReset(float frameTime, cFrustum* frustum); void End(tRenderListCompileFlag aFlags); + iLight* GetLight(int alIdx){ return m_lights[alIdx];} int GetLightNum(){ return(int)m_lights.size();} diff --git a/HPL2/include/graphics/Renderer.h b/HPL2/include/graphics/Renderer.h index 64f518007..5b25c4211 100644 --- a/HPL2/include/graphics/Renderer.h +++ b/HPL2/include/graphics/Renderer.h @@ -78,6 +78,8 @@ namespace hpl { bool IsRenderableNodeIsVisible(iRenderableContainerNode* apNode, std::span clipPlanes); bool IsObjectIsVisible(iRenderable* object, tRenderableFlag neededFlags, std::span clipPlanes = {}); + void WalkAndPrepareRenderList(iRenderableContainer* container,cFrustum* frustum, std::function handler, tRenderableFlag renderableFlag); + void UpdateRenderListWalkAllNodesTestFrustumAndVisibility( cRenderList* apRenderList, cFrustum* frustum, diff --git a/HPL2/include/graphics/RendererForwardPlus.h b/HPL2/include/graphics/RendererForwardPlus.h index 89d7ac1d6..16a7b7cc9 100644 --- a/HPL2/include/graphics/RendererForwardPlus.h +++ b/HPL2/include/graphics/RendererForwardPlus.h @@ -3,8 +3,10 @@ #include "engine/RTTI.h" +#include "graphics/ForwardResources.h" #include "graphics/GraphicsTypes.h" #include "graphics/IndexPool.h" +#include "graphics/TextureDescriptorPool.h" #include "graphics/offsetAllocator.h" #include "scene/Viewport.h" #include "scene/World.h" @@ -36,6 +38,8 @@ namespace hpl { static constexpr TinyImageFormat ColorBufferFormat = TinyImageFormat_R8G8B8A8_UNORM; static constexpr TinyImageFormat ShadowDepthBufferFormat = TinyImageFormat_D32_SFLOAT; + static constexpr uint32_t MaxMaterialSamplers = static_cast(eTextureWrap_LastEnum) * static_cast(eTextureFilter_LastEnum) * static_cast(cMaterial::TextureAntistropy::Antistropy_Count); + static constexpr uint32_t MaxIndirectDrawArgs = 1024; static constexpr uint32_t MaxViewportFrameDescriptors = 256; static constexpr uint32_t MaxObjectUniforms = 4096; @@ -73,16 +77,6 @@ namespace hpl { std::array m_depthBuffer; }; - - struct DiffuseMat { - uint m_texture[4]; - uint m_materialConfig; - float m_heightMapScale; - float m_hiehgtMapBias; - float m_frenselBias; - float m_frenselPow; - }; - struct PointLightData { mat4 m_mvp; float3 m_lightPos; @@ -151,6 +145,7 @@ namespace hpl { uint32_t updateFrameDescriptor(const ForgeRenderer::Frame& frame, Cmd* cmd, cWorld* apWorld, const PerFrameOption& options); uint32_t resolveMaterialID(const ForgeRenderer::Frame& frame,cMaterial* material); + std::array m_perFrameBuffer; std::array m_objectUniformBuffer; std::array m_indirectDrawArgsBuffer; @@ -180,30 +175,26 @@ namespace hpl { CommandSignature* m_cmdSignatureVBPass = NULL; std::array m_opaqueFrameSet; std::array m_opaqueConstSet; + SharedDescriptorSet m_opaqueBatchSet; struct SceneMaterial { - struct SceneTextureEntry { - IndexPoolHandle m_handle; - SharedTexture m_texture; - }; + public: void* m_material = nullptr; uint32_t m_version = 0; - uint8_t m_writeMask = 0; - MaterialID m_id; - - IndexPoolHandle m_materialIndex; - std::array m_sceneTextures; + IndexPoolHandle m_slot; + resource::MaterialTypes m_resource = std::monostate{}; }; + + std::array m_batchSampler; std::array m_sceneMaterial; - IndexResourceRingDisposable m_sceneTextureDisposable; - IndexRingDisposable m_indexResourceDisposable; - IndexPool m_sceneTexturePool; IndexPool m_opaqueMaterialPool; + TextureDescriptorPool m_sceneDescriptorPool; SharedTexture m_emptyTexture; SharedShader m_diffuseShader; SharedShader m_pointlightClusterShader; SharedShader m_clearClusterShader; + SharedTexture m_falloff; SharedSampler m_nearestClampSampler; diff --git a/HPL2/include/graphics/TextureDescriptorPool.h b/HPL2/include/graphics/TextureDescriptorPool.h new file mode 100644 index 000000000..21d859b2c --- /dev/null +++ b/HPL2/include/graphics/TextureDescriptorPool.h @@ -0,0 +1,31 @@ +#pragma once + +#include "graphics/ForgeHandles.h" +#include "graphics/IndexPool.h" + +namespace hpl { + class TextureDescriptorPool final { + public: + enum Action { + UpdateSlot, + RemoveSlot + }; + using DescriptorHandler = std::function; + TextureDescriptorPool(uint32_t ringsize, uint32_t poolSize); + void reset(DescriptorHandler handler); + uint32_t request(SharedTexture& texture); + void dispose(uint32_t slot); + private: + + struct RingEntry { + Action m_action; + uint32_t slot; + uint8_t m_count; + }; + uint32_t m_index = 0; + IndexPool m_pool; + folly::small_vector> m_ring; + std::vector m_slot; + DescriptorHandler m_actionHandler; + }; +} // namespace hpl diff --git a/HPL2/resource/ShaderList.fsl b/HPL2/resource/ShaderList.fsl index b39e11d24..c7c365a84 100644 --- a/HPL2/resource/ShaderList.fsl +++ b/HPL2/resource/ShaderList.fsl @@ -278,6 +278,7 @@ #end #frag forward_diffuse.frag + #define ALPHA_REJECT 0.5 #include "forward_diffuse.frag.fsl" #end diff --git a/HPL2/resource/forward_diffuse.frag.fsl b/HPL2/resource/forward_diffuse.frag.fsl index cf90d92ae..93009f1ed 100644 --- a/HPL2/resource/forward_diffuse.frag.fsl +++ b/HPL2/resource/forward_diffuse.frag.fsl @@ -23,37 +23,55 @@ PsOut PS_MAIN(PsIn In) INIT_MAIN; UniformObject object = Get(sceneObjects)[In.drawId]; DiffuseMaterial diffuseMat = Get(opaqueMaterial)[MATERIAL_ID(object)]; - uint diffuseTextureId = DiffuseMaterial_DiffuseTexture_ID(diffuseMat); float4 diffuseColor = float4(0,0,0,1); - if(diffuseTextureId < SCENE_MAX_TEXTURE_COUNT) { - BeginNonUniformResourceIndex(diffuseTextureId, SCENE_MAX_TEXTURE_COUNT); - diffuseColor = SampleTex2D(Get(sceneTextures)[diffuseTextureId], Get(nearestClampSampler), In.uv.xy); - EndNonUniformResourceIndex(); + const bool hasDiffuse = fetchSceneTextureFloat4(DiffuseMaterial_DiffuseTexture_ID(diffuseMat), In.uv, diffuseColor); + if(diffuseColor.w < ALPHA_REJECT ) { + discard; + } + + float2 specular = float2(0,0); + const bool hasSpecular = fetchSceneTextureFloat2(DiffuseMaterial_SpecularTexture_ID(diffuseMat), In.uv, specular); + + float3 normal = float3(0,0,0); + float3 normalSample = float3(0,0,0); + const bool hasNormal = fetchSceneTextureFloat3(DiffuseMaterial_NormalTexture_ID(diffuseMat), In.uv, normalSample); + if (hasNormal) { + normalSample -= 0.5; + normal = normalize(normalSample.x * In.tangent + normalSample.y * In.bitangent + normalSample.z * In.normal); + } else { + normal = normalize(In.normal); } float3 normalizedNormal = normalize(In.normal.xyz); float2 texelPos = (In.Position.xy * Get(viewTexel)); uint2 clusterCoords = uint2(floor(texelPos * float2(LIGHT_CLUSTER_WIDTH, LIGHT_CLUSTER_HEIGHT))); uint numLightsInCluster = Get(lightClustersCount)[LIGHT_CLUSTER_COUNT_POS(clusterCoords.x, clusterCoords.y)]; - float4 result = float4(0,0,0,1); + float3 result = float3(0,0,0); for(uint j = 0; j < numLightsInCluster; j++) { uint lightId = Get(lightClusters)[LIGHT_CLUSTER_DATA_POS(j, clusterCoords.x, clusterCoords.y)]; PointLight pl = Get(pointLights)[lightId]; float4 lightPosWorldSpace = float4(pl.lightPos.xyz, 1.0f); float4 lightCameraSpace = mul(Get(viewMat), lightPosWorldSpace); - float3 lightDir = (lightCameraSpace.xyz - In.pos) * (1.0 / pl.lightRadius); - - float attenuation = saturate(1.0f - dot(lightDir , lightDir)); - float3 normalLightDir = normalize(lightDir); - - float fLDotN = max(dot(normalizedNormal, normalLightDir), 0.0); - result += diffuseColor * (attenuation * fLDotN); + const float3 lightDir = (lightCameraSpace.xyz - In.pos) * (1.0 / pl.lightRadius); + const float3 normalLightDir = normalize(lightDir); + const float attenuation = saturate(1.0f - dot(lightDir , lightDir)); + const float fLDotN = max(dot(normalizedNormal, normalLightDir), 0.0); + + float specularValue = 0.0; + float3 lightDiffuseColor = pl.lightColor.xyz * fLDotN; + if(pl.lightColor.w > 0.0) { + float3 halfVec = normalize(normalLightDir + normalize(-In.pos.xyz)); + float specIntensity = specular.x; + float specPower = exp2(specular.y * 10.0) + 1.0; + specularValue = pl.lightColor.w * specIntensity * pow( clamp( dot( halfVec, normalizedNormal), 0.0, 1.0), specPower ); + } + + result += ((specularValue.xxx * pl.lightColor.xyz) + (diffuseColor.xyz * pl.lightColor.xyz * fLDotN)) * attenuation; } PsOut Out; - Out.test.x = diffuseTextureId; - Out.diffuse = result; + Out.diffuse = float4(result, 1.0); RETURN(Out); } diff --git a/HPL2/resource/forward_resource.h.fsl b/HPL2/resource/forward_resource.h.fsl index 990bd6e6c..a833a66db 100644 --- a/HPL2/resource/forward_resource.h.fsl +++ b/HPL2/resource/forward_resource.h.fsl @@ -8,8 +8,36 @@ RES(Buffer(uint), lightClustersCount, UPDATE_FREQ_PER_FRAME, t2, binding = 3); RES(Buffer(uint), lightClusters, UPDATE_FREQ_PER_FRAME, t3, binding = 4); RES(Buffer(PointLight), pointLights, UPDATE_FREQ_PER_FRAME, t0, binding = 5); -RES(Tex2D(float4), sceneTextures[SCENE_MAX_TEXTURE_COUNT], UPDATE_FREQ_NONE, t0, binding = 10); +RES(SamplerState, materialSampler, UPDATE_FREQ_PER_BATCH, s4, binding = 13); + +RES(Tex2D(float4), sceneTextures[SCENE_MAX_TEXTURE_COUNT], UPDATE_FREQ_NONE, t1, binding = 10); INLINE float3x3 ToNormalMat(float4x4 invModel, float4x4 invView) { return transpose(mul(float3x3(invModel[0].xyz, invModel[1].xyz, invModel[2].xyz), float3x3(invView[0].xyz, invView[1].xyz, invView[2].xyz))); } + +INLINE bool fetchSceneTextureFloat4(uint index, float2 uv, inout float4 value) { + if(index < SCENE_MAX_TEXTURE_COUNT) { + BeginNonUniformResourceIndex(index, SCENE_MAX_TEXTURE_COUNT); + value = SampleTex2D(Get(sceneTextures)[index], Get(materialSampler), uv); + EndNonUniformResourceIndex(); + } + return !(index == INVALID_TEXTURE_INDEX); +} +INLINE bool fetchSceneTextureFloat3(uint index, float2 uv, inout float3 value) { + if(index < SCENE_MAX_TEXTURE_COUNT) { + BeginNonUniformResourceIndex(index, SCENE_MAX_TEXTURE_COUNT); + value = SampleTex2D(Get(sceneTextures)[index], Get(materialSampler), uv).xyz; + EndNonUniformResourceIndex(); + } + return !(index == INVALID_TEXTURE_INDEX); +} + +INLINE bool fetchSceneTextureFloat2(uint index, float2 uv, inout float2 value) { + if(index < SCENE_MAX_TEXTURE_COUNT) { + BeginNonUniformResourceIndex(index, SCENE_MAX_TEXTURE_COUNT); + value = SampleTex2D(Get(sceneTextures)[index], Get(materialSampler), uv).xy; + EndNonUniformResourceIndex(); + } + return !(index == INVALID_TEXTURE_INDEX); +} diff --git a/HPL2/resource/forward_shader_common.h.fsl b/HPL2/resource/forward_shader_common.h.fsl index 2048172a6..7b21e2167 100644 --- a/HPL2/resource/forward_shader_common.h.fsl +++ b/HPL2/resource/forward_shader_common.h.fsl @@ -13,6 +13,8 @@ #define LIGHT_CLUSTER_COUNT_POS(ix, iy) ( ((iy)*LIGHT_CLUSTER_WIDTH)+(ix) ) #define LIGHT_CLUSTER_DATA_POS(il, ix, iy) ( LIGHT_CLUSTER_COUNT_POS(ix, iy)*LIGHT_CLUSTER_COUNT + (il) ) +#define INVALID_TEXTURE_INDEX (0xffff) + STRUCT(DiffuseMaterial) { DATA(uint, tex[4], None); DATA(uint, materialConfig, None); @@ -21,7 +23,15 @@ STRUCT(DiffuseMaterial) { DATA(float, frenselBias, None); DATA(float, frenselPow, None); }; -uint DiffuseMaterial_DiffuseTexture_ID(DiffuseMaterial mat) {return mat.tex[0];} +uint DiffuseMaterial_DiffuseTexture_ID(DiffuseMaterial mat) {return (mat.tex[0] & 0xffff);} +uint DiffuseMaterial_NormalTexture_ID(DiffuseMaterial mat) {return ((mat.tex[0] >> 16) & 0xffff);} +uint DiffuseMaterial_AlphaTexture_ID(DiffuseMaterial mat) {return (mat.tex[1] & 0xffff);} +uint DiffuseMaterial_SpecularTexture_ID(DiffuseMaterial mat) {return ((mat.tex[1] >> 16) & 0xffff);} +uint DiffuseMaterial_HeightTexture_ID(DiffuseMaterial mat) {return (mat.tex[2] & 0xffff);} +uint DiffuseMaterial_IlluminiationTexture_ID(DiffuseMaterial mat) {return ((mat.tex[2] >> 16) & 0xffff);} +uint DiffuseMaterial_DissolveAlphaTexture_ID(DiffuseMaterial mat) {return (mat.tex[3] & 0xffff);} +uint DiffuseMaterial_CubeMapAlphaTexture_ID(DiffuseMaterial mat) {return ((mat.tex[3] >> 16) & 0xffff);} + STRUCT(UniformObject) { diff --git a/HPL2/resource/solid_diffuse.frag.fsl b/HPL2/resource/solid_diffuse.frag.fsl index 5280d3db6..d1365a342 100644 --- a/HPL2/resource/solid_diffuse.frag.fsl +++ b/HPL2/resource/solid_diffuse.frag.fsl @@ -34,7 +34,7 @@ PsOut PS_MAIN(PsIn In) texCoord.xy += ParallaxAdvance(texCoord, 0.0, 32.0, - Get(uniformMaterialBuffer)[materialID].heightMapScale , + Get(uniformMaterialBuffer)[materialID].heightMapScale * PARALAX_MULTIPLIER, In.pos, In.normal, In.tangent, diff --git a/HPL2/sources/graphics/ForwardResources.cpp b/HPL2/sources/graphics/ForwardResources.cpp new file mode 100644 index 000000000..9004b6d3d --- /dev/null +++ b/HPL2/sources/graphics/ForwardResources.cpp @@ -0,0 +1,80 @@ +#include "graphics/ForwardResources.h" +#include "graphics/GraphicsTypes.h" +#include "graphics/Material.h" + +#include +#include + +namespace hpl::resource { + + LightResourceVariants CreateFromLight(iLight& light) { + return std::monostate{}; + } + + void visitTextures(MaterialTypes& material, std::function handler) { + if(auto* item = std::get_if(&material)) { + struct { + eMaterialTexture m_type; + uint16_t* m_value; + } m_textures[] = { + {eMaterialTexture_Diffuse, &item->m_tex.m_diffues}, + {eMaterialTexture_NMap, &item->m_tex.m_normal}, + {eMaterialTexture_Specular, &item->m_tex.m_specular}, + {eMaterialTexture_Alpha, &item->m_tex.m_alpha}, + {eMaterialTexture_Height, &item->m_tex.m_height}, + {eMaterialTexture_Illumination, &item->m_tex.m_illuminiation}, + {eMaterialTexture_DissolveAlpha, &item->m_tex.m_dissolveAlpha}, + {eMaterialTexture_CubeMapAlpha, &item->m_tex.m_cubeMapAlpha}, + }; + for(auto& tex: m_textures) { + if(*tex.m_value != UINT16_MAX) { + handler(tex.m_type, *tex.m_value); + } + } + } + } + std::variant createMaterial(TextureDescriptorPool& pool, cMaterial* material) { + ASSERT(material); + auto& descriptor = material->Descriptor(); + switch (descriptor.m_id) { + case hpl::MaterialID::SolidDiffuse: { + DiffuseMaterial result = {}; + struct { + eMaterialTexture m_type; + uint16_t* m_value; + } m_textures[] = { + {eMaterialTexture_Diffuse, &result.m_tex.m_diffues}, + {eMaterialTexture_NMap, &result.m_tex.m_normal}, + {eMaterialTexture_Alpha, &result.m_tex.m_alpha}, + {eMaterialTexture_Specular, &result.m_tex.m_specular}, + {eMaterialTexture_Height, &result.m_tex.m_height}, + {eMaterialTexture_Illumination, &result.m_tex.m_illuminiation}, + {eMaterialTexture_DissolveAlpha, &result.m_tex.m_dissolveAlpha}, + {eMaterialTexture_CubeMapAlpha, &result.m_tex.m_cubeMapAlpha}, + }; + for(auto& tex: m_textures) { + auto* image = material->GetImage(tex.m_type); + (*tex.m_value) = UINT16_MAX; + if(image) { + uint32_t handle = pool.request(image->GetTexture()); + (*tex.m_value) = static_cast(handle); + } + } + result.m_heightMapScale = descriptor.m_solid.m_heightMapScale; + result.m_heigtMapBias = descriptor.m_solid.m_heightMapBias; + result.m_frenselBias = descriptor.m_solid.m_frenselBias; + result.m_frenselPow = descriptor.m_solid.m_frenselPow; + return result; + } + case hpl::MaterialID::Decal: + break; + case hpl::MaterialID::Translucent: + break; + case hpl::MaterialID::Water: + break; + default: + break; + } + return std::monostate{}; + } +} diff --git a/HPL2/sources/graphics/RenderList.cpp b/HPL2/sources/graphics/RenderList.cpp index 1b057a282..5e16f98f1 100644 --- a/HPL2/sources/graphics/RenderList.cpp +++ b/HPL2/sources/graphics/RenderList.cpp @@ -63,20 +63,15 @@ namespace hpl { // return apObjectA < apObjectB; } - //----------------------------------------------------------------------- static bool SortFunc_Diffuse(iRenderable* apObjectA, iRenderable* apObjectB) { cMaterial* pMatA = apObjectA->GetMaterial(); cMaterial* pMatB = apObjectB->GetMaterial(); - ////////////////////////// - // Matrix if (apObjectA->GetModelMatrixPtr() != apObjectB->GetModelMatrixPtr()) { return apObjectA->GetModelMatrixPtr() < apObjectB->GetModelMatrixPtr(); } - ////////////////////////// - // Object return apObjectA < apObjectB; } @@ -96,20 +91,14 @@ namespace hpl { cMaterial* pMatA = apObjectA->GetMaterial(); cMaterial* pMatB = apObjectB->GetMaterial(); - ////////////////////////// - // Texture if (pMatA->GetImage(eMaterialTexture_Illumination) != pMatB->GetImage(eMaterialTexture_Illumination)) { return pMatA->GetImage(eMaterialTexture_Illumination) < pMatB->GetImage(eMaterialTexture_Illumination); } - ////////////////////////// - // Matrix if (apObjectA->GetModelMatrixPtr() != apObjectB->GetModelMatrixPtr()) { return apObjectA->GetModelMatrixPtr() < apObjectB->GetModelMatrixPtr(); } - ////////////////////////// - // Vector (just so that order stays the same return apObjectA->GetWorldPosition() < apObjectB->GetWorldPosition(); } @@ -117,21 +106,14 @@ namespace hpl { cMaterial* pMatA = apObjectA->GetMaterial(); cMaterial* pMatB = apObjectB->GetMaterial(); - ////////////////////////// - // Texture if (pMatA->GetImage(eMaterialTexture_Illumination) != pMatB->GetImage(eMaterialTexture_Illumination)) { return pMatA->GetImage(eMaterialTexture_Illumination) < pMatB->GetImage(eMaterialTexture_Illumination); } - - ////////////////////////// - // Matrix if (apObjectA->GetModelMatrixPtr() != apObjectB->GetModelMatrixPtr()) { return apObjectA->GetModelMatrixPtr() < apObjectB->GetModelMatrixPtr(); } - ////////////////////////// - // Illumination amount return apObjectA->GetIlluminationAmount() < apObjectB->GetIlluminationAmount(); } @@ -217,14 +199,12 @@ namespace hpl { }); } if (aFlags & eRenderListCompileFlag_Translucent) { - //////////////////////////////////// // Setup variables cPlanef nearestSurfacePlane; bool bHasLargeSurfacePlane = false; float fClosestDist = 0; iRenderable* pLargeSurfaceObject = NULL; - //////////////////////////////////// // Find the neareest surface plane for (size_t i = 0; i < m_transObjects.size(); ++i) { ///////////////////////////////// @@ -272,7 +252,6 @@ namespace hpl { } } - //////////////////////////////////// // Check if objects are above or below surface plane if (bHasLargeSurfacePlane) { for (size_t i = 0; i < m_transObjects.size(); ++i) { @@ -406,143 +385,6 @@ namespace hpl { } } - //----------------------------------------------------------------------- - - void cRenderList::Compile(tRenderListCompileFlag aFlags) { - auto sortRenderType = [&](eRenderListType type) { - switch (type) { - case eRenderListType_Translucent: - m_sortedArrays[type] = m_transObjects; - break; - case eRenderListType_Decal: - m_sortedArrays[type] = m_decalObjects; - break; - case eRenderListType_Illumination: - m_sortedArrays[type] = m_illumObjects; - break; - default: - m_sortedArrays[type] = m_solidObjects; - break; - } - switch (type) { - case eRenderListType_Z: - std::sort(m_sortedArrays[type].begin(), m_sortedArrays[type].end(), SortFunc_Z); - break; - case eRenderListType_Diffuse: - std::sort(m_sortedArrays[type].begin(), m_sortedArrays[type].end(), SortFunc_Diffuse); - break; - case eRenderListType_Translucent: - std::sort(m_sortedArrays[type].begin(), m_sortedArrays[type].end(), SortFunc_Translucent); - break; - case eRenderListType_Decal: - std::sort(m_sortedArrays[type].begin(), m_sortedArrays[type].end(), SortFunc_Decal); - break; - case eRenderListType_Illumination: - std::sort(m_sortedArrays[type].begin(), m_sortedArrays[type].end(), SortFunc_Illumination); - break; - default: - break; - } - }; - - if (aFlags & eRenderListCompileFlag_Z) { - sortRenderType(eRenderListType_Z); - } - if (aFlags & eRenderListCompileFlag_Diffuse) { - sortRenderType(eRenderListType_Diffuse); - } - if (aFlags & eRenderListCompileFlag_Decal) { - sortRenderType(eRenderListType_Decal); - } - if (aFlags & eRenderListCompileFlag_Illumination) { - sortRenderType(eRenderListType_Illumination); - } - if(aFlags & eRenderListCompileFlag_FogArea) { - std::sort(m_fogAreas.begin(), m_fogAreas.end(), [](cFogArea* a, cFogArea* b) { - return a->GetViewSpaceZ() < b->GetViewSpaceZ(); - }); - } - if (aFlags & eRenderListCompileFlag_Translucent) { - //////////////////////////////////// - // Setup variables - cPlanef nearestSurfacePlane; - bool bHasLargeSurfacePlane = false; - float fClosestDist = 0; - iRenderable* pLargeSurfaceObject = NULL; - - //////////////////////////////////// - // Find the neareest surface plane - for (size_t i = 0; i < m_transObjects.size(); ++i) { - ///////////////////////////////// - // Check so object is of right type - iRenderable* pObject = m_transObjects[i]; - if (pObject->GetRenderType() != eRenderableType_SubMesh) { - continue; - } - - cMaterial* pMat = pObject->GetMaterial(); - if (pMat->GetLargeTransperantSurface() == false) { - continue; - } - - ///////////////////////////////// - // Check so sub mesh is one sided - cSubMeshEntity* pSubEnt = static_cast(pObject); - cSubMesh* pSubMesh = pSubEnt->GetSubMesh(); - if (pSubMesh->GetIsOneSided() == false) { - continue; - } - - cVector3f vSurfaceNormal = - cMath::Vector3Normalize(cMath::MatrixMul3x3(pSubEnt->GetWorldMatrix(), pSubMesh->GetOneSidedNormal())); - cVector3f vSurfacePos = cMath::MatrixMul(pSubEnt->GetWorldMatrix(), pSubMesh->GetOneSidedPoint()); - - ///////////////////////////////// - // Make sure it does not face away from frustum. - float fDot = cMath::Vector3Dot(vSurfacePos - m_frustum->GetOrigin(), vSurfaceNormal); - if (fDot >= 0) { - continue; - } - - ///////////////////////////////// - // Create surface normal and check if nearest. - cPlanef surfacePlane; - surfacePlane.FromNormalPoint(vSurfaceNormal, vSurfacePos); - - float fDist = cMath::PlaneToPointDist(surfacePlane, m_frustum->GetOrigin()); - if (fDist < fClosestDist || bHasLargeSurfacePlane == false) { - bHasLargeSurfacePlane = true; - fClosestDist = fDist; - nearestSurfacePlane = surfacePlane; - pLargeSurfaceObject = pObject; - } - } - - //////////////////////////////////// - // Check if objects are above or below surface plane - if (bHasLargeSurfacePlane) { - for (size_t i = 0; i < m_transObjects.size(); ++i) { - iRenderable* pObject = m_transObjects[i]; - - // If this is large plane, then set value to 0 - if (pObject == pLargeSurfaceObject) { - pObject->SetLargePlaneSurfacePlacement(0); - continue; - } - - float fDist = cMath::PlaneToPointDist(nearestSurfacePlane, pObject->GetBoundingVolume()->GetWorldCenter()); - pObject->SetLargePlaneSurfacePlacement(fDist < 0 ? -1 : 1); - } - } else { - for (size_t i = 0; i < m_transObjects.size(); ++i) { - iRenderable* pObject = m_transObjects[i]; - pObject->SetLargePlaneSurfacePlacement(0); - } - } - sortRenderType(eRenderListType_Translucent); - } - } - void cRenderList::Clear() { // Use resize instead of clear, because that way capacity is preserved and allocation is never // needed unless there is a need to increase the vector size. diff --git a/HPL2/sources/graphics/Renderer.cpp b/HPL2/sources/graphics/Renderer.cpp index 24c3273b1..8af40b57c 100644 --- a/HPL2/sources/graphics/Renderer.cpp +++ b/HPL2/sources/graphics/Renderer.cpp @@ -96,6 +96,46 @@ namespace hpl return clipRect; } + void WalkAndPrepareRenderList(iRenderableContainer* container,cFrustum* frustum, std::function handler, tRenderableFlag renderableFlag) { + + std::function walkRenderables; + walkRenderables = [&](iRenderableContainerNode* childNode) { + childNode->UpdateBeforeUse(); + for (auto& childNode : childNode->GetChildNodes()) { + childNode->UpdateBeforeUse(); + eCollision frustumCollision = frustum->CollideNode(childNode); + if (frustumCollision == eCollision_Outside) { + continue; + } + if (frustum->CheckAABBNearPlaneIntersection(childNode->GetMin(), childNode->GetMax())) { + cVector3f vViewSpacePos = cMath::MatrixMul(frustum->GetViewMatrix(), childNode->GetCenter()); + childNode->SetViewDistance(vViewSpacePos.z); + childNode->SetInsideView(true); + } else { + // Frustum origin is outside of node. Do intersection test. + cVector3f vIntersection; + cMath::CheckAABBLineIntersection( + childNode->GetMin(), childNode->GetMax(), frustum->GetOrigin(), childNode->GetCenter(), &vIntersection, NULL); + cVector3f vViewSpacePos = cMath::MatrixMul(frustum->GetViewMatrix(), vIntersection); + childNode->SetViewDistance(vViewSpacePos.z); + childNode->SetInsideView(false); + } + walkRenderables(childNode); + } + for (auto& pObject : childNode->GetObjects()) { + if (!rendering::detail::IsObjectIsVisible(pObject, renderableFlag, {})) { + continue; + } + handler(pObject); + } + }; + auto rootNode = container->GetRoot(); + rootNode->UpdateBeforeUse(); + rootNode->SetInsideView(true); + walkRenderables(rootNode); + } + + void UpdateRenderListWalkAllNodesTestFrustumAndVisibility( cRenderList* apRenderList, cFrustum* frustum, @@ -297,6 +337,7 @@ namespace hpl { } + iRenderer::iRenderer(const tString& asName, cGraphics* apGraphics, cResources* apResources) { mpResources = apResources; diff --git a/HPL2/sources/graphics/RendererDeferred.cpp b/HPL2/sources/graphics/RendererDeferred.cpp index 97037a7e8..1acf84a98 100644 --- a/HPL2/sources/graphics/RendererDeferred.cpp +++ b/HPL2/sources/graphics/RendererDeferred.cpp @@ -103,7 +103,7 @@ namespace hpl { static constexpr uint32_t SSAONumOfSamples = 8; namespace detail { - uint32_t resolveMaterialID(cMaterial::TextureAntistropy anisotropy, eTextureWrap wrap, eTextureFilter filter) { + uint32_t resolveTextureFilterGroup(cMaterial::TextureAntistropy anisotropy, eTextureWrap wrap, eTextureFilter filter) { const uint32_t anisotropyGroup = (static_cast(eTextureFilter_LastEnum) * static_cast(eTextureWrap_LastEnum)) * static_cast(anisotropy); @@ -1579,7 +1579,7 @@ namespace hpl { for (size_t antistropy = 0; antistropy < cMaterial::Antistropy_Count; antistropy++) { for (size_t textureWrap = 0; textureWrap < eTextureWrap_LastEnum; textureWrap++) { for (size_t textureFilter = 0; textureFilter < eTextureFilter_LastEnum; textureFilter++) { - uint32_t materialID = detail::resolveMaterialID( + uint32_t materialID = detail::resolveTextureFilterGroup( static_cast(antistropy), static_cast(textureWrap), static_cast(textureFilter)); @@ -3321,7 +3321,7 @@ namespace hpl { pMaterial->Descriptor().m_id == MaterialID::Decal) { // skip rendering if the update return false if (pObject->UpdateGraphicsForViewport(apFrustum, frameTime) == false) { - return; + continue; } pObject->SetModelMatrixPtr(pObject->GetModelMatrix(apFrustum)); @@ -3787,7 +3787,7 @@ namespace hpl { } cmdBindDescriptorSet( cmd, - detail::resolveMaterialID(apMaterial->GetTextureAntistropy(), apMaterial->GetTextureWrap(), apMaterial->GetTextureFilter()), + detail::resolveTextureFilterGroup(apMaterial->GetTextureAntistropy(), apMaterial->GetTextureWrap(), apMaterial->GetTextureFilter()), m_materialSet.m_materialConstSet.m_handle); cmdBindDescriptorSet(cmd, apMaterial->Index(), m_materialSet.m_perBatchSet[frame.m_frameIndex].m_handle); return index; diff --git a/HPL2/sources/graphics/RendererForwardPlus.cpp b/HPL2/sources/graphics/RendererForwardPlus.cpp index 903d76367..7ea923913 100644 --- a/HPL2/sources/graphics/RendererForwardPlus.cpp +++ b/HPL2/sources/graphics/RendererForwardPlus.cpp @@ -1,13 +1,16 @@ #include "graphics/RendererForwardPlus.h" -#include "Common_3/Utilities/ThirdParty/OpenSource/ModifiedSonyMath/common.hpp" -#include "Common_3/Utilities/ThirdParty/OpenSource/ModifiedSonyMath/sse/vectormath.hpp" #include "graphics/Color.h" #include "graphics/ForgeHandles.h" #include "graphics/ForgeRenderer.h" +#include "graphics/ForwardResources.h" #include "graphics/GraphicsAllocator.h" #include "graphics/GraphicsTypes.h" #include "graphics/IndexPool.h" +#include "graphics/Material.h" +#include "graphics/Renderable.h" +#include "graphics/Renderer.h" +#include "graphics/TextureDescriptorPool.h" #include "scene/Light.h" #include "scene/RenderableContainer.h" @@ -22,6 +25,16 @@ namespace hpl { + namespace detail { + uint32_t resolveTextureFilterGroup(cMaterial::TextureAntistropy anisotropy, eTextureWrap wrap, eTextureFilter filter) { + const uint32_t anisotropyGroup = + (static_cast(eTextureFilter_LastEnum) * static_cast(eTextureWrap_LastEnum)) * + static_cast(anisotropy); + return anisotropyGroup + + ((static_cast(wrap) * static_cast(eTextureFilter_LastEnum)) + static_cast(filter)); + } + } + SharedRenderTarget RendererForwardPlus::GetOutputImage(uint32_t frameIndex, cViewport& viewport) { auto sharedData = m_boundViewportData.resolve(viewport); if (!sharedData) { @@ -32,12 +45,11 @@ namespace hpl { RendererForwardPlus::RendererForwardPlus(cGraphics* apGraphics, cResources* apResources, std::shared_ptr debug) : iRenderer("ForwardPlus", apGraphics, apResources), - m_sceneTexturePool(MaxTextureCount), - m_sceneTextureDisposable(ForgeRenderer::SwapChainLength), m_opaqueMaterialPool(MaxOpaqueCount), - m_indexResourceDisposable(ForgeRenderer::SwapChainLength) { + m_sceneDescriptorPool(ForgeRenderer::SwapChainLength, MaxTextureCount) { auto* forgeRenderer = Interface::Get(); + // shaders m_nearestClampSampler.Load(forgeRenderer->Rend(), [&](Sampler** sampler) { SamplerDesc samplerDesc = {}; @@ -167,7 +179,7 @@ namespace hpl { desc.mDesc.mFlags = BUFFER_CREATION_FLAG_PERSISTENT_MAP_BIT; desc.mDesc.mFirstElement = 0; desc.mDesc.mElementCount = MaxOpaqueCount; - desc.mDesc.mStructStride = sizeof(DiffuseMat); + desc.mDesc.mStructStride = sizeof(resource::DiffuseMaterial); desc.mDesc.mSize = desc.mDesc.mElementCount * desc.mDesc.mStructStride; desc.ppBuffer = buffer; addResource(&desc, nullptr); @@ -320,6 +332,83 @@ namespace hpl { return true; }); + m_opaqueBatchSet.Load(forgeRenderer->Rend(), [&](DescriptorSet** descSet) { + DescriptorSetDesc perFrameDescSet{ m_diffuseRootSignature.m_handle, + DESCRIPTOR_UPDATE_FREQ_PER_BATCH, + MaxMaterialSamplers }; + addDescriptorSet(forgeRenderer->Rend(), &perFrameDescSet, descSet); + return true; + }); + for (size_t antistropy = 0; antistropy < cMaterial::Antistropy_Count; antistropy++) { + for (size_t textureWrap = 0; textureWrap < eTextureWrap_LastEnum; textureWrap++) { + for (size_t textureFilter = 0; textureFilter < eTextureFilter_LastEnum; textureFilter++) { + uint32_t batchID = detail::resolveTextureFilterGroup( + static_cast(antistropy), + static_cast(textureWrap), + static_cast(textureFilter)); + m_batchSampler[batchID].Load(forgeRenderer->Rend(), [&](Sampler** sampler) { + SamplerDesc samplerDesc = {}; + switch (textureWrap) { + case eTextureWrap_Repeat: + samplerDesc.mAddressU = ADDRESS_MODE_REPEAT; + samplerDesc.mAddressV = ADDRESS_MODE_REPEAT; + samplerDesc.mAddressW = ADDRESS_MODE_REPEAT; + break; + case eTextureWrap_Clamp: + samplerDesc.mAddressU = ADDRESS_MODE_CLAMP_TO_EDGE; + samplerDesc.mAddressV = ADDRESS_MODE_CLAMP_TO_EDGE; + samplerDesc.mAddressW = ADDRESS_MODE_CLAMP_TO_EDGE; + break; + case eTextureWrap_ClampToBorder: + samplerDesc.mAddressU = ADDRESS_MODE_CLAMP_TO_BORDER; + samplerDesc.mAddressV = ADDRESS_MODE_CLAMP_TO_BORDER; + samplerDesc.mAddressW = ADDRESS_MODE_CLAMP_TO_BORDER; + break; + default: + ASSERT(false && "Invalid wrap mode"); + break; + } + switch (textureFilter) { + case eTextureFilter_Nearest: + samplerDesc.mMinFilter = FilterType::FILTER_NEAREST; + samplerDesc.mMagFilter = FilterType::FILTER_NEAREST; + samplerDesc.mMipMapMode = MipMapMode::MIPMAP_MODE_NEAREST; + break; + case eTextureFilter_Bilinear: + samplerDesc.mMinFilter = FilterType::FILTER_LINEAR; + samplerDesc.mMagFilter = FilterType::FILTER_LINEAR; + samplerDesc.mMipMapMode = MipMapMode::MIPMAP_MODE_NEAREST; + break; + case eTextureFilter_Trilinear: + samplerDesc.mMinFilter = FilterType::FILTER_LINEAR; + samplerDesc.mMagFilter = FilterType::FILTER_LINEAR; + samplerDesc.mMipMapMode = MipMapMode::MIPMAP_MODE_LINEAR; + break; + default: + ASSERT(false && "Invalid filter"); + break; + } + switch (antistropy) { + case cMaterial::Antistropy_8: + samplerDesc.mMaxAnisotropy = 8.0f; + break; + case cMaterial::Antistropy_16: + samplerDesc.mMaxAnisotropy = 16.0f; + break; + default: + break; + } + addSampler(forgeRenderer->Rend(), &samplerDesc, sampler); + return true; + }); + std::array params = { + DescriptorData {.pName = "materialSampler", .ppSamplers = &m_batchSampler[batchID].m_handle}, + }; + updateDescriptorSet( + forgeRenderer->Rend(), batchID, m_opaqueBatchSet.m_handle, params.size(), params.data()); + } + } + } for (size_t swapChainIndex = 0; swapChainIndex < ForgeRenderer::SwapChainLength; swapChainIndex++) { m_opaqueFrameSet[swapChainIndex].Load(forgeRenderer->Rend(), [&](DescriptorSet** descSet) { DescriptorSetDesc perFrameDescSet{ m_diffuseRootSignature.m_handle, @@ -440,8 +529,16 @@ namespace hpl { if (frame.m_currentFrame != m_activeFrame) { m_objectIndex = 0; - m_sceneTextureDisposable.reset([&](SharedTexture& texture, IndexPoolHandle& handler) { - + m_sceneDescriptorPool.reset([&](TextureDescriptorPool::Action action, uint32_t slot, SharedTexture& texture) { + std::array params = { + DescriptorData {.pName = "sceneTextures", .mCount = 1, .mArrayOffset = slot, .ppTextures = (action == TextureDescriptorPool::Action::UpdateSlot ? &texture.m_handle: &m_emptyTexture.m_handle ) } + }; + updateDescriptorSet( + forgeRenderer->Rend(), + 0, + m_opaqueConstSet[frame.m_frameIndex].m_handle, + params.size(), + params.data()); }); m_objectDescriptorLookup.clear(); m_activeFrame = frame.m_currentFrame; @@ -516,115 +613,97 @@ namespace hpl { .m_projectionMat = mainFrustumProjMat }); - m_rendererList.BeginAndReset(frameTime, apFrustum); - struct RenderableContainer { - iRenderableContainer* m_continer; - eWorldContainerType m_type; - }; - std::array worldContainers = { - RenderableContainer{ apWorld->GetRenderableContainer(eWorldContainerType_Dynamic), eWorldContainerType_Dynamic }, - RenderableContainer{ apWorld->GetRenderableContainer(eWorldContainerType_Static), eWorldContainerType_Static } - }; + { + m_rendererList.BeginAndReset(frameTime, apFrustum); + auto* dynamicContainer = apWorld->GetRenderableContainer(eWorldContainerType_Dynamic); + auto* staticContainer = apWorld->GetRenderableContainer(eWorldContainerType_Static); + dynamicContainer->UpdateBeforeRendering(); + staticContainer->UpdateBeforeRendering(); - for (auto& container : worldContainers) { - container.m_continer->UpdateBeforeRendering(); - } - std::function walkRenderables; - walkRenderables = [&](iRenderableContainerNode* childNode, eWorldContainerType containerType) { - childNode->UpdateBeforeUse(); - for (auto& childNode : childNode->GetChildNodes()) { - childNode->UpdateBeforeUse(); - eCollision frustumCollision = apFrustum->CollideNode(childNode); - if (frustumCollision == eCollision_Outside) { - continue; - } - if (apFrustum->CheckAABBNearPlaneIntersection(childNode->GetMin(), childNode->GetMax())) { - cVector3f vViewSpacePos = cMath::MatrixMul(apFrustum->GetViewMatrix(), childNode->GetCenter()); - childNode->SetViewDistance(vViewSpacePos.z); - childNode->SetInsideView(true); - } else { - // Frustum origin is outside of node. Do intersection test. - cVector3f vIntersection; - cMath::CheckAABBLineIntersection( - childNode->GetMin(), childNode->GetMax(), apFrustum->GetOrigin(), childNode->GetCenter(), &vIntersection, NULL); - cVector3f vViewSpacePos = cMath::MatrixMul(apFrustum->GetViewMatrix(), vIntersection); - childNode->SetViewDistance(vViewSpacePos.z); - childNode->SetInsideView(false); - } - walkRenderables(childNode, containerType); - } - for (auto& pObject : childNode->GetObjects()) { + auto prepareObjectHandler = [&](iRenderable* pObject) { if (!rendering::detail::IsObjectIsVisible(pObject, eRenderableFlag_VisibleInNonReflection, {})) { - continue; + return; } - cMaterial* pMaterial = pObject->GetMaterial(); m_rendererList.AddObject(pObject); - - if (pObject && pObject->GetRenderFrameCount() != iRenderer::GetRenderFrameCount()) { - pObject->SetRenderFrameCount(iRenderer::GetRenderFrameCount()); - pObject->UpdateGraphicsForFrame(frameTime); - } - - if (pMaterial && pMaterial->GetRenderFrameCount() != iRenderer::GetRenderFrameCount()) { - pMaterial->SetRenderFrameCount(iRenderer::GetRenderFrameCount()); - pMaterial->UpdateBeforeRendering(frameTime); - } - //////////////////////////////////////// - // Update per viewport specific and set amtrix point - // Skip this for non-decal translucent! This is because the water rendering might mess it up otherwise! - if (pMaterial == NULL || cMaterial::IsTranslucent(pMaterial->Descriptor().m_id) == false || - pMaterial->Descriptor().m_id == MaterialID::Decal) { - // skip rendering if the update return false - if (pObject->UpdateGraphicsForViewport(apFrustum, frameTime) == false) { - return; - } - - pObject->SetModelMatrixPtr(pObject->GetModelMatrix(apFrustum)); - } - // Only set a matrix used for sorting. Calculate the proper in the trans rendering! - else { - pObject->SetModelMatrixPtr(pObject->GetModelMatrix(NULL)); - } - } - }; - for (auto& it : worldContainers) { - iRenderableContainerNode* pNode = it.m_continer->GetRoot(); - pNode->UpdateBeforeUse(); // Make sure node is updated. - pNode->SetInsideView(true); // We never want to check root! Assume player is inside. - walkRenderables(pNode, it.m_type); + }; + rendering::detail::WalkAndPrepareRenderList(dynamicContainer, apFrustum, prepareObjectHandler, eRenderableFlag_VisibleInNonReflection); + rendering::detail::WalkAndPrepareRenderList(staticContainer, apFrustum, prepareObjectHandler, eRenderableFlag_VisibleInNonReflection); + m_rendererList.End( + eRenderListCompileFlag_Diffuse | eRenderListCompileFlag_Translucent | eRenderListCompileFlag_Decal | + eRenderListCompileFlag_Illumination | eRenderListCompileFlag_FogArea); } - m_rendererList.End( - eRenderListCompileFlag_Diffuse | eRenderListCompileFlag_Translucent | eRenderListCompileFlag_Decal | - eRenderListCompileFlag_Illumination | eRenderListCompileFlag_FogArea); - // prepare point light data // diffuse + struct IndirectDrawGroup { + size_t m_offset; + uint32_t m_count; + uint32_t m_batchID; + }; + std::vector diffuseFilterGroup; { - auto diffuseItems = m_rendererList.GetRenderableItems(eRenderListType_Diffuse); + std::vector renderables; + renderables.assign(m_rendererList.GetSolidObjects().begin(), m_rendererList.GetSolidObjects().end()); + std::sort(renderables.begin(), renderables.end(), [](iRenderable* objectA, iRenderable* objectB) { + cMaterial* pMatA = objectA->GetMaterial(); + cMaterial* pMatB = objectB->GetMaterial(); + uint32_t filterA = detail::resolveTextureFilterGroup( + pMatA->GetTextureAntistropy(), pMatA->GetTextureWrap(), pMatA->GetTextureFilter()); + + uint32_t filterB = detail::resolveTextureFilterGroup( + pMatB->GetTextureAntistropy(), pMatB->GetTextureWrap(), pMatB->GetTextureFilter()); + return filterA < filterB; + }); + + + auto isSameGroup = [](iRenderable* objectA, iRenderable* objectB) { + cMaterial* pMatA = objectA->GetMaterial(); + cMaterial* pMatB = objectB->GetMaterial(); + return pMatA->GetTextureAntistropy() == pMatB->GetTextureAntistropy() && + pMatA->GetTextureWrap() == pMatB->GetTextureWrap() && + pMatA->GetTextureFilter() == pMatB->GetTextureFilter(); + }; + BufferUpdateDesc updateDesc = { m_indirectDrawArgsBuffer[frame.m_frameIndex].m_handle, 0, - sizeof(IndirectDrawIndexArguments) * diffuseItems.size()}; + sizeof(IndirectDrawIndexArguments) * renderables.size()}; beginUpdateResource(&updateDesc); - for (size_t i = 0; i < diffuseItems.size(); i++) { - cMaterial* pMaterial = diffuseItems[i]->GetMaterial(); - std::array targets = { eVertexBufferElement_Position, - eVertexBufferElement_Texture0, - eVertexBufferElement_Normal, - eVertexBufferElement_Texture1Tangent }; - DrawPacket packet = diffuseItems[i]->ResolveDrawPacket(frame, targets); - if (pMaterial == nullptr || packet.m_type == DrawPacket::Unknown) { - continue; + + auto it = renderables.begin(); + auto lastIt = renderables.begin(); + uint32_t index = 0; + uint32_t lastIndex = 0; + uint32_t lastBatchID = 0; + while(it != renderables.end()) { + lastIndex = index; + { + cMaterial* pMaterial = (*it)->GetMaterial(); + lastBatchID = detail::resolveTextureFilterGroup( + pMaterial->GetTextureAntistropy(), pMaterial->GetTextureWrap(), pMaterial->GetTextureFilter()); } - ASSERT(pMaterial->Descriptor().m_id == MaterialID::SolidDiffuse && "Invalid material type"); - ASSERT(packet.m_type == DrawPacket::DrawPacketType::DrawGeometryset); - ASSERT(packet.m_unified.m_set == GraphicsAllocator::AllocationSet::OpaqueSet); - - auto& args = reinterpret_cast(updateDesc.pMappedData)[i]; - args.mIndexCount = packet.m_unified.m_numIndices; - args.mStartIndex = packet.m_unified.m_subAllocation->indexOffset(); - args.mVertexOffset = packet.m_unified.m_subAllocation->vertextOffset(); - args.mStartInstance = resolveObjectId(frame, pMaterial, diffuseItems[i], {}); // for DX12 this won't work - args.mInstanceCount = 1; + do { + cMaterial* pMaterial = (*it)->GetMaterial(); + std::array targets = { eVertexBufferElement_Position, + eVertexBufferElement_Texture0, + eVertexBufferElement_Normal, + eVertexBufferElement_Texture1Tangent }; + DrawPacket packet = (*it)->ResolveDrawPacket(frame, targets); + if (pMaterial == nullptr || packet.m_type == DrawPacket::Unknown) { + continue; + } + ASSERT(pMaterial->Descriptor().m_id == MaterialID::SolidDiffuse && "Invalid material type"); + ASSERT(packet.m_type == DrawPacket::DrawPacketType::DrawGeometryset); + ASSERT(packet.m_unified.m_set == GraphicsAllocator::AllocationSet::OpaqueSet); + + auto& args = reinterpret_cast(updateDesc.pMappedData)[index++]; + args.mIndexCount = packet.m_unified.m_numIndices; + args.mStartIndex = packet.m_unified.m_subAllocation->indexOffset(); + args.mVertexOffset = packet.m_unified.m_subAllocation->vertextOffset(); + args.mStartInstance = resolveObjectId(frame, pMaterial, (*it), {}); // for DX12 this won't work + args.mInstanceCount = 1; + lastIt = it; + it++; + } while(it != renderables.end() && isSameGroup(*it, *lastIt)); + diffuseFilterGroup.push_back({lastIndex * sizeof(IndirectDrawArguments), index - lastIndex, lastBatchID}); } endUpdateResource(&updateDesc, nullptr); } @@ -644,7 +723,6 @@ namespace hpl { switch(light->GetLightType()) { case eLightType_Point: { m_pointLightAttenutation[frame.m_frameIndex][pointLightIndex] = light->GetFalloffMap()->GetTexture(); - auto& data = reinterpret_cast(pointlightUpdateDesc.pMappedData)[pointLightIndex++]; const cColor color = light->GetDiffuseColor(); data.m_radius = light->GetRadius(); @@ -718,8 +796,11 @@ namespace hpl { cmdBindIndexBuffer(cmd, opaqueSet.indexBuffer().m_handle, INDEX_TYPE_UINT32, 0); cmdBindDescriptorSet(cmd, 0, m_opaqueConstSet[frame.m_frameIndex].m_handle); cmdBindDescriptorSet(cmd, mainFrameIndex, m_opaqueFrameSet[frame.m_frameIndex].m_handle); - cmdExecuteIndirect( - cmd, m_cmdSignatureVBPass, diffuseItems.size(), m_indirectDrawArgsBuffer[frame.m_frameIndex].m_handle, 0, nullptr, 0); + for(auto& group: diffuseFilterGroup) { + cmdBindDescriptorSet(cmd, group.m_batchID, m_opaqueBatchSet.m_handle); + cmdExecuteIndirect( + cmd, m_cmdSignatureVBPass, group.m_count, m_indirectDrawArgsBuffer[frame.m_frameIndex].m_handle, group.m_offset, nullptr, 0); + } cmdEndDebugMarker(cmd); } { @@ -738,54 +819,32 @@ namespace hpl { } + uint32_t RendererForwardPlus::resolveMaterialID(const ForgeRenderer::Frame& frame,cMaterial* material) { auto* forgeRenderer = Interface::Get(); auto& sceneMaterial = m_sceneMaterial[material->Index()]; - uint8_t writeMask = 1 << frame.m_frameIndex; if (sceneMaterial.m_material != material || - sceneMaterial.m_version != material->Generation() || - (sceneMaterial.m_writeMask & writeMask) == 0) { + sceneMaterial.m_version != material->Generation()) { auto& descriptor = material->Descriptor(); sceneMaterial.m_version = material->Generation(); sceneMaterial.m_material = material; - if(sceneMaterial.m_writeMask == 0) { - sceneMaterial.m_materialIndex = IndexPoolHandle(&m_opaqueMaterialPool); - for(auto& res: sceneMaterial.m_sceneTextures) { - if(res.m_handle.isValid()) { - m_sceneTextureDisposable.push(std::move(res.m_texture), std::move(res.m_handle)); - } - } - sceneMaterial.m_sceneTextures[eMaterialTexture_Diffuse] = SceneMaterial::SceneTextureEntry { - IndexPoolHandle(&m_sceneTexturePool), material->GetImage(eMaterialTexture_Diffuse)->GetTexture() - }; - } - sceneMaterial.m_writeMask |= writeMask; - for(auto& scene: sceneMaterial.m_sceneTextures) { - if(scene.m_handle.isValid()) { - std::array params = { - DescriptorData {.pName = "sceneTextures", .mCount = 1, .mArrayOffset = scene.m_handle.get(), .ppTextures = &scene.m_texture.m_handle } - }; - updateDescriptorSet( - forgeRenderer->Rend(), - 0, - m_opaqueConstSet[frame.m_frameIndex].m_handle, - params.size(), - params.data()); - } - } - { + resource::visitTextures(sceneMaterial.m_resource, [&](eMaterialTexture texture, uint32_t slot) { + m_sceneDescriptorPool.dispose(slot); + }); + sceneMaterial.m_resource = hpl::resource::createMaterial(m_sceneDescriptorPool, material); + if(resource::DiffuseMaterial* mat = std::get_if(&sceneMaterial.m_resource)) { + sceneMaterial.m_slot = IndexPoolHandle(&m_opaqueMaterialPool); BufferUpdateDesc updateDesc = { m_opaqueMaterialBuffer.m_handle, - sizeof(DiffuseMat) * sceneMaterial.m_materialIndex.get()}; + sizeof(resource::DiffuseMaterial) * sceneMaterial.m_slot.get()}; beginUpdateResource(&updateDesc); - auto& material = (*reinterpret_cast(updateDesc.pMappedData)); - material.m_texture[0] = sceneMaterial.m_sceneTextures[eMaterialTexture_Diffuse].m_handle.get(); + (*reinterpret_cast(updateDesc.pMappedData)) = *mat; endUpdateResource(&updateDesc, NULL); } + } - return sceneMaterial.m_materialIndex.get(); - //return (sceneMaterial.m_materialIndex.get() << 8) | static_cast(sceneMaterial.m_id) ; + return sceneMaterial.m_slot.get(); } uint32_t RendererForwardPlus::updateFrameDescriptor( const ForgeRenderer::Frame& frame, Cmd* cmd, cWorld* apWorld, const PerFrameOption& options) { diff --git a/HPL2/sources/graphics/TextureDescriptorPool.cpp b/HPL2/sources/graphics/TextureDescriptorPool.cpp new file mode 100644 index 000000000..a50988b42 --- /dev/null +++ b/HPL2/sources/graphics/TextureDescriptorPool.cpp @@ -0,0 +1,50 @@ +#include "graphics/TextureDescriptorPool.h" +#include "graphics/ForgeHandles.h" + +namespace hpl { + + TextureDescriptorPool::TextureDescriptorPool(uint32_t ringsize, uint32_t poolSize): + m_pool(poolSize) { + m_ring.resize(ringsize); + m_slot.resize(poolSize); + } + void TextureDescriptorPool::reset(DescriptorHandler handler) { + m_actionHandler = handler; + m_index = (m_index + 1) % m_ring.size(); + for(auto& ringEntry: m_ring[m_index]) { + handler(ringEntry.m_action, ringEntry.slot, m_slot[ringEntry.slot]); + switch(ringEntry.m_action) { + case Action::UpdateSlot: { + if((++ringEntry.m_count) < m_ring.size()) { + m_ring[(m_index + 1) % m_ring.size()].push_back(ringEntry); + } + break; + } + case Action::RemoveSlot: { + if((++ringEntry.m_count) < m_ring.size()) { + m_ring[(m_index + 1) % m_ring.size()].push_back(ringEntry); + } else { + m_pool.returnId(ringEntry.slot); + m_slot[ringEntry.slot] = SharedTexture(); + } + break; + } + } + + } + m_ring[m_index].clear(); + + } + uint32_t TextureDescriptorPool::request(SharedTexture& texture) { + uint32_t slot = m_pool.requestId(); + m_slot[slot] = texture; + m_actionHandler(Action::UpdateSlot, slot, m_slot[slot]); + if(m_ring.size() > 1) { + m_ring[(m_index + 1) % m_ring.size()].push_back(RingEntry {Action::UpdateSlot, slot, 1}); + } + return slot; + } + void TextureDescriptorPool::dispose(uint32_t slot) { + m_ring[(m_index + 1) % m_ring.size()].push_back(RingEntry {Action::RemoveSlot, slot, 0}); + } +} // namespace hpl From 9ed20e348483d88d639c97533c1c925c465f39b1 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Thu, 2 Nov 2023 21:46:55 -0700 Subject: [PATCH 12/17] feat: add illuminiation amount Signed-off-by: Michael Pollind --- HPL2/include/graphics/RendererForwardPlus.h | 2 +- HPL2/resource/forward_diffuse.frag.fsl | 17 ++++++++++++++--- HPL2/resource/forward_shader_common.h.fsl | 2 +- HPL2/sources/graphics/RendererForwardPlus.cpp | 1 + 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/HPL2/include/graphics/RendererForwardPlus.h b/HPL2/include/graphics/RendererForwardPlus.h index 16a7b7cc9..d4b1dbffc 100644 --- a/HPL2/include/graphics/RendererForwardPlus.h +++ b/HPL2/include/graphics/RendererForwardPlus.h @@ -107,7 +107,7 @@ namespace hpl { float m_dissolveAmount; uint m_materialIndex; float m_lightLevel; - uint pad; + float m_illuminationAmount; mat4 m_modelMat; mat4 m_invModelMat; mat4 m_uvMat; diff --git a/HPL2/resource/forward_diffuse.frag.fsl b/HPL2/resource/forward_diffuse.frag.fsl index 93009f1ed..cff117aac 100644 --- a/HPL2/resource/forward_diffuse.frag.fsl +++ b/HPL2/resource/forward_diffuse.frag.fsl @@ -33,6 +33,7 @@ PsOut PS_MAIN(PsIn In) float2 specular = float2(0,0); const bool hasSpecular = fetchSceneTextureFloat2(DiffuseMaterial_SpecularTexture_ID(diffuseMat), In.uv, specular); + float3 normal = float3(0,0,0); float3 normalSample = float3(0,0,0); const bool hasNormal = fetchSceneTextureFloat3(DiffuseMaterial_NormalTexture_ID(diffuseMat), In.uv, normalSample); @@ -47,7 +48,7 @@ PsOut PS_MAIN(PsIn In) float2 texelPos = (In.Position.xy * Get(viewTexel)); uint2 clusterCoords = uint2(floor(texelPos * float2(LIGHT_CLUSTER_WIDTH, LIGHT_CLUSTER_HEIGHT))); uint numLightsInCluster = Get(lightClustersCount)[LIGHT_CLUSTER_COUNT_POS(clusterCoords.x, clusterCoords.y)]; - float3 result = float3(0,0,0); + float4 result = float4(0,0,0, 0); for(uint j = 0; j < numLightsInCluster; j++) { uint lightId = Get(lightClusters)[LIGHT_CLUSTER_DATA_POS(j, clusterCoords.x, clusterCoords.y)]; PointLight pl = Get(pointLights)[lightId]; @@ -68,10 +69,20 @@ PsOut PS_MAIN(PsIn In) specularValue = pl.lightColor.w * specIntensity * pow( clamp( dot( halfVec, normalizedNormal), 0.0, 1.0), specPower ); } - result += ((specularValue.xxx * pl.lightColor.xyz) + (diffuseColor.xyz * pl.lightColor.xyz * fLDotN)) * attenuation; + result += float4(((specularValue.xxx * pl.lightColor.xyz) + (diffuseColor.xyz * pl.lightColor.xyz * fLDotN)) * attenuation, 0.0); + } + + float4 illumination = float4(0,0,0,0); + + if(object.illuminationAmount > 0) { + float4 illuminationColor = float4(0,0,0,0); + const bool hasIlluminiation = fetchSceneTextureFloat4(DiffuseMaterial_IlluminiationTexture_ID(diffuseMat), In.uv, illuminationColor); + if(hasIlluminiation) { + result += object.illuminationAmount * illuminationColor; + } } PsOut Out; - Out.diffuse = float4(result, 1.0); + Out.diffuse = result; RETURN(Out); } diff --git a/HPL2/resource/forward_shader_common.h.fsl b/HPL2/resource/forward_shader_common.h.fsl index 7b21e2167..a83ae819f 100644 --- a/HPL2/resource/forward_shader_common.h.fsl +++ b/HPL2/resource/forward_shader_common.h.fsl @@ -38,7 +38,7 @@ STRUCT(UniformObject) DATA(float, dissolveAmount, None); DATA(uint, materialID, None); DATA(float, lightLevel, None); - DATA(uint, __pad1, None); + DATA(float, illuminationAmount, None); DATA(float4x4, modelMat, None); DATA(float4x4, invModelMat, None); DATA(float4x4, uvMat, None); diff --git a/HPL2/sources/graphics/RendererForwardPlus.cpp b/HPL2/sources/graphics/RendererForwardPlus.cpp index 7ea923913..342dcc61d 100644 --- a/HPL2/sources/graphics/RendererForwardPlus.cpp +++ b/HPL2/sources/graphics/RendererForwardPlus.cpp @@ -497,6 +497,7 @@ namespace hpl { uniformObjectData.m_modelMat = cMath::ToForgeMatrix4(modelMat); uniformObjectData.m_invModelMat = cMath::ToForgeMatrix4(cMath::MatrixInverse(modelMat)); uniformObjectData.m_lightLevel = 1.0f; + uniformObjectData.m_illuminationAmount = apObject->GetIlluminationAmount(); uniformObjectData.m_materialIndex = resolveMaterialID(frame, apMaterial); if(apMaterial) { uniformObjectData.m_uvMat = cMath::ToForgeMatrix4(apMaterial->GetUvMatrix().GetTranspose()); From 3f1a251056cbb3f52cf944b0cb2af1a7c632ecd5 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Thu, 2 Nov 2023 21:55:56 -0700 Subject: [PATCH 13/17] feat: update subproject Signed-off-by: Michael Pollind --- external/The-Forge | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/The-Forge b/external/The-Forge index 80ddbfe6b..d652ccdb3 160000 --- a/external/The-Forge +++ b/external/The-Forge @@ -1 +1 @@ -Subproject commit 80ddbfe6b935d792b2a3e53da9c4f7c92edd5ec7 +Subproject commit d652ccdb321666b286753f5cb2a2fc81354ac739 From 0bf661311917137215a03a3413df01ace0f54cc9 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Thu, 2 Nov 2023 21:56:52 -0700 Subject: [PATCH 14/17] update vcpkg Signed-off-by: Michael Pollind --- vcpkg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vcpkg b/vcpkg index 4a600e9fe..5c82f7e63 160000 --- a/vcpkg +++ b/vcpkg @@ -1 +1 @@ -Subproject commit 4a600e9fea71bd7872080cbb716797e04d30e6d3 +Subproject commit 5c82f7e6372c9b0ea25e1fd829dd50235ef37629 From 5306642743a28f29b00957d0f2b1512964dae342 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Fri, 3 Nov 2023 07:49:57 -0700 Subject: [PATCH 15/17] bugfix: resolve memory corruption when updating skinned meshes Signed-off-by: Michael Pollind --- HPL2/include/graphics/GraphicsBuffer.h | 5 ++-- HPL2/resource/forward_shader_common.h.fsl | 4 ++-- HPL2/resource/srgb_utils.h.fsl | 28 +++++++++++++++++++++++ HPL2/sources/scene/SubMeshEntity.cpp | 24 ++++++++++++------- 4 files changed, 48 insertions(+), 13 deletions(-) create mode 100644 HPL2/resource/srgb_utils.h.fsl diff --git a/HPL2/include/graphics/GraphicsBuffer.h b/HPL2/include/graphics/GraphicsBuffer.h index 9816804ab..8e04ee3b2 100644 --- a/HPL2/include/graphics/GraphicsBuffer.h +++ b/HPL2/include/graphics/GraphicsBuffer.h @@ -273,7 +273,6 @@ namespace hpl { break; } case BufferType::MappedBuffer: { - switch(m_indexType) { case IndexBufferType::Uint32: { uint32_t v = value; @@ -345,7 +344,7 @@ namespace hpl { break; } case BufferType::MappedBuffer: { - std::copy(buf.begin(), buf.end(), reinterpret_cast(m_asset->m_mapped.m_mappedData) + targetOffset); + std::copy(buf.begin(), buf.end(), reinterpret_cast(m_asset->m_mapped.m_mappedData) + m_byteOffset + targetOffset); break; } } @@ -361,7 +360,7 @@ namespace hpl { break; } case BufferType::MappedBuffer: { - std::copy(buf.begin(), buf.end(), reinterpret_cast(m_asset->m_mapped.m_mappedData) + targetOffset); + std::copy(buf.begin(), buf.end(), reinterpret_cast(m_asset->m_mapped.m_mappedData) + m_byteOffset + targetOffset); break; } } diff --git a/HPL2/resource/forward_shader_common.h.fsl b/HPL2/resource/forward_shader_common.h.fsl index a83ae819f..83a8d267a 100644 --- a/HPL2/resource/forward_shader_common.h.fsl +++ b/HPL2/resource/forward_shader_common.h.fsl @@ -1,5 +1,5 @@ -#ifndef SHADER_DEFS_H -#define SHADER_DEFS_H +#ifndef FORWARD_COMMON_DEFS_H +#define FORWARD_COMMON_DEFS_H #define LIGHT_CLUSTER_WIDTH 8 #define LIGHT_CLUSTER_HEIGHT 8 diff --git a/HPL2/resource/srgb_utils.h.fsl b/HPL2/resource/srgb_utils.h.fsl new file mode 100644 index 000000000..aa1d1125e --- /dev/null +++ b/HPL2/resource/srgb_utils.h.fsl @@ -0,0 +1,28 @@ +#ifndef SRGB_UTILS_H +#define SRGB_UTILS_H + float3 approximationSRgbToLinear (float3 sRGBCol ) + { + return pow ( sRGBCol , 2.2) ; + } + + float3 approximationLinearToSRGB (float3 linearCol ) + { + return pow ( linearCol , 1 / 2.2) ; + } + + float3 accurateSRGBToLinear (float3 sRGBCol ) + { + float3 linearRGBLo = sRGBCol / 12.92; + float3 linearRGBHi = pow (( sRGBCol + 0.055) / 1.055 , 2.4) ; + float3 linearRGB = ( sRGBCol <= 0.04045) ? linearRGBLo : linearRGBHi ; + return linearRGB ; + } + + float3 accurateLinearToSRGB (float3 linearCol ) + { + float3 sRGBLo = linearCol * 12.92; + float3 sRGBHi = ( pow ( abs ( linearCol ) , 1.0/2.4) * 1.055) - 0.055; + float3 sRGB = ( linearCol <= 0.0031308) ? sRGBLo : sRGBHi ; + return sRGB ; + } +#endif diff --git a/HPL2/sources/scene/SubMeshEntity.cpp b/HPL2/sources/scene/SubMeshEntity.cpp index 814ef4547..5d875f13f 100644 --- a/HPL2/sources/scene/SubMeshEntity.cpp +++ b/HPL2/sources/scene/SubMeshEntity.cpp @@ -62,7 +62,7 @@ namespace hpl { , mpMaterialManager(apMaterialManager) { mbIsOneSided = mpSubMesh->GetIsOneSided(); mvOneSidedNormal = mpSubMesh->GetOneSidedNormal(); - m_isSkinnedMesh = mpMeshEntity->GetMesh()->GetSkeleton(); + m_isSkinnedMesh = (mpMeshEntity->GetMesh()->GetSkeleton() != nullptr); auto* graphicsAllocator = Interface::Get(); ASSERT(graphicsAllocator); @@ -73,12 +73,13 @@ namespace hpl { m_numberVertices = vertexStreams.begin()->m_numberElements; m_numberIndecies = indexStream.m_numberElements; - m_geometry = opaqueSet.allocate(m_numberVertices * (m_isSkinnedMesh ? 2 : 1), m_numberIndecies); + const uint32_t reservedVerticies = m_numberVertices * (m_isSkinnedMesh ? 2 : 1); + m_geometry = opaqueSet.allocate(reservedVerticies, m_numberIndecies); for(auto& localStream: vertexStreams) { auto gpuStream = m_geometry->getStreamBySemantic(localStream.m_semantic); ASSERT(gpuStream != m_geometry->vertexStreams().end()); - BufferUpdateDesc updateDesc = { gpuStream->buffer().m_handle, gpuStream->stride() * m_geometry->vertextOffset(), gpuStream->stride() * m_numberVertices}; + BufferUpdateDesc updateDesc = { gpuStream->buffer().m_handle, gpuStream->stride() * m_geometry->vertextOffset(), gpuStream->stride() * reservedVerticies}; beginUpdateResource(&updateDesc); GraphicsBuffer gpuBuffer(updateDesc); @@ -88,6 +89,12 @@ namespace hpl { auto sp = src.rawByteSpan().subspan(i * localStream.m_stride, std::min(gpuStream->stride(), localStream.m_stride)); dest.WriteRaw(i * gpuStream->stride(), sp); } + if(m_isSkinnedMesh) { + for(size_t i = 0; i < m_numberVertices; i++) { + auto sp = src.rawByteSpan().subspan(i * localStream.m_stride, std::min(gpuStream->stride(), localStream.m_stride)); + dest.WriteRaw(((i + m_numberVertices) * gpuStream->stride()), sp); + } + } endUpdateResource(&updateDesc, nullptr); } { @@ -175,9 +182,10 @@ namespace hpl { targetNormalIt != m_geometry->vertexStreams().end() && targetTangentIt != m_geometry->vertexStreams().end() ); - BufferUpdateDesc positionUpdateDesc = { targetPositionIt->buffer().m_handle, m_activeCopy * (targetPositionIt->stride() * m_numberVertices), targetPositionIt->stride() * m_numberVertices}; - BufferUpdateDesc tangentUpdateDesc = { targetTangentIt->buffer().m_handle, m_activeCopy * (targetTangentIt->stride() * m_numberVertices), targetTangentIt->stride() * m_numberVertices}; - BufferUpdateDesc normalUpdateDesc = { targetNormalIt->buffer().m_handle, m_activeCopy * (targetNormalIt->stride() * m_numberVertices), targetNormalIt->stride() * m_numberVertices}; + + BufferUpdateDesc positionUpdateDesc = { targetPositionIt->buffer().m_handle, (m_geometry->vertextOffset() * targetPositionIt->stride()) + m_activeCopy * (targetPositionIt->stride() * m_numberVertices), targetPositionIt->stride() * m_numberVertices}; + BufferUpdateDesc tangentUpdateDesc = { targetTangentIt->buffer().m_handle, (m_geometry->vertextOffset() * targetTangentIt->stride()) + m_activeCopy * (targetTangentIt->stride() * m_numberVertices), targetTangentIt->stride() * m_numberVertices}; + BufferUpdateDesc normalUpdateDesc = { targetNormalIt->buffer().m_handle, (m_geometry->vertextOffset() * targetNormalIt->stride()) + m_activeCopy * (targetNormalIt->stride() * m_numberVertices), targetNormalIt->stride() * m_numberVertices}; beginUpdateResource(&positionUpdateDesc); beginUpdateResource(&tangentUpdateDesc); beginUpdateResource(&normalUpdateDesc); @@ -189,8 +197,8 @@ namespace hpl { auto targetTangentView = tangentMapping.CreateStructuredView(0, targetTangentIt->stride()); auto targetNormalView = normalMapping.CreateStructuredView(0, targetNormalIt->stride()); - for(size_t i = 0; i < bindPositionIt->m_numberElements; i++) { - + ASSERT(bindPositionIt->m_numberElements == m_numberVertices); + for(size_t i = 0; i < m_numberVertices; i++) { const std::span weights = std::span(&mpSubMesh->m_vertexWeights[(i * 4)], 4); const std::span boneIdxs = std::span(&mpSubMesh->m_vertexBones[(i * 4)], 4); From d3002eb9200e9e62d4e2e2c2c8729c4698a1a3f7 Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Fri, 3 Nov 2023 17:15:17 -0700 Subject: [PATCH 16/17] bugfix: address compiling shader problems windows Signed-off-by: Michael Pollind --- CMakeLists.txt | 2 +- HPL2/resource/forward_resource.h.fsl | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e5559bbe..f103a19fa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,7 +16,7 @@ include("${CMAKE_CURRENT_SOURCE_DIR}/vcpkg/scripts/buildsystems/vcpkg.cmake") add_definitions( -DUSE_THE_FORGE_LEGACY - -DUSE_FORWARD_PLUS_BACKEND # prototype forward renderer + # -DUSE_FORWARD_PLUS_BACKEND # prototype forward renderer ) diff --git a/HPL2/resource/forward_resource.h.fsl b/HPL2/resource/forward_resource.h.fsl index a833a66db..298e83209 100644 --- a/HPL2/resource/forward_resource.h.fsl +++ b/HPL2/resource/forward_resource.h.fsl @@ -1,16 +1,17 @@ #include "forward_shader_common.h.fsl" -RES(SamplerState, nearestClampSampler, UPDATE_FREQ_NONE, s2, binding = 0); -RES(Buffer(UniformObject), sceneObjects, UPDATE_FREQ_NONE, t1, binding = 1); -RES(Buffer(DiffuseMaterial), opaqueMaterial, UPDATE_FREQ_NONE, t0, binding = 2); +RES(SamplerState, nearestClampSampler, UPDATE_FREQ_NONE, s0, binding = 0); + +RES(Buffer(UniformObject), sceneObjects, UPDATE_FREQ_NONE, t0, binding = 1); +RES(Buffer(DiffuseMaterial), opaqueMaterial, UPDATE_FREQ_NONE, t1, binding = 2); RES(Buffer(uint), lightClustersCount, UPDATE_FREQ_PER_FRAME, t2, binding = 3); RES(Buffer(uint), lightClusters, UPDATE_FREQ_PER_FRAME, t3, binding = 4); -RES(Buffer(PointLight), pointLights, UPDATE_FREQ_PER_FRAME, t0, binding = 5); +RES(Buffer(PointLight), pointLights, UPDATE_FREQ_PER_FRAME, t4, binding = 5); -RES(SamplerState, materialSampler, UPDATE_FREQ_PER_BATCH, s4, binding = 13); +RES(SamplerState, materialSampler, UPDATE_FREQ_PER_BATCH, s1, binding = 13); -RES(Tex2D(float4), sceneTextures[SCENE_MAX_TEXTURE_COUNT], UPDATE_FREQ_NONE, t1, binding = 10); +RES(Tex2D(float4), sceneTextures[SCENE_MAX_TEXTURE_COUNT], UPDATE_FREQ_NONE, t5, binding = 10); INLINE float3x3 ToNormalMat(float4x4 invModel, float4x4 invView) { return transpose(mul(float3x3(invModel[0].xyz, invModel[1].xyz, invModel[2].xyz), float3x3(invView[0].xyz, invView[1].xyz, invView[2].xyz))); From 46991400ac1520b96c56cedc8d5f7f773eba066a Mon Sep 17 00:00:00 2001 From: Michael Pollind Date: Fri, 3 Nov 2023 23:04:26 -0700 Subject: [PATCH 17/17] tweak fsl compiler error Signed-off-by: Michael Pollind --- HPL2/resource/point_light_clusters.comp.fsl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/HPL2/resource/point_light_clusters.comp.fsl b/HPL2/resource/point_light_clusters.comp.fsl index 3b5ad4b0b..e421ce7a1 100644 --- a/HPL2/resource/point_light_clusters.comp.fsl +++ b/HPL2/resource/point_light_clusters.comp.fsl @@ -1,15 +1,14 @@ #include "light_cull_resources.h.fsl" - NUM_THREADS(LIGHT_CLUSTER_WIDTH, LIGHT_CLUSTER_HEIGHT, 1) void CS_MAIN(SV_GroupThreadID(uint3) threadInGroupId, SV_GroupID(uint3) groupId) { INIT_MAIN; const float invClusterWidth = 1.0f / float(LIGHT_CLUSTER_WIDTH); const float invClusterHeight = 1.0f / float(LIGHT_CLUSTER_HEIGHT); - const float2 windowSize = Get(windowSize); + const float2 size = Get(windowSize); - const float aspectRatio = windowSize.x / windowSize.y; + const float aspectRatio = size.x / size.y; PointLight lightData = Get(pointLights)[groupId.x]; @@ -20,7 +19,7 @@ void CS_MAIN(SV_GroupThreadID(uint3) threadInGroupId, SV_GroupID(uint3) groupId) float fov = 2.0 * atan(1.0/Get(projMat)[1][1]); float projRadius = 2.0f * lightData.lightRadius * (1 / tan(fov * 0.5f)) * invLightPosW; - projRadius *= windowSize.x > windowSize.y ? aspectRatio : 1 / aspectRatio; + projRadius *= size.x > size.y ? aspectRatio : 1 / aspectRatio; // Early exit light if it's behind the camera if (lightPosClipSpace.w < 0.0f && -lightPosClipSpace.w > lightData.lightRadius) {