diff --git a/data/Shaders/debugdraw/debugdraw.hlsl b/data/Shaders/debugdraw/debugdraw.hlsl index 8abf24c89..c2a28940d 100644 --- a/data/Shaders/debugdraw/debugdraw.hlsl +++ b/data/Shaders/debugdraw/debugdraw.hlsl @@ -15,10 +15,10 @@ VS_Output VS_DebugDraw(uint _vertexID : VertexID) { VS_Output output = (VS_Output) 0; - ByteAddressBuffer buf = getBuffer(debugDrawRootConstants3D.getBufferHandle()); + ByteAddressBuffer buf = getBuffer(debugDrawRootConstants3D.getVertexBufferHandle()); Vertex vert; - vert.Load(buf, debugDrawRootConstants3D.getVertexFormat(), _vertexID, debugDrawRootConstants3D.getBufferOffset()); + vert.Load(buf, debugDrawRootConstants3D.getVertexFormat(), _vertexID, debugDrawRootConstants3D.getVertexBufferOffset()); ViewConstants viewConstants; viewConstants.Load(getBuffer(RESERVEDSLOT_BUFSRV_VIEWCONSTANTS)); diff --git a/data/Shaders/debugdraw/debugdraw.hlsli b/data/Shaders/debugdraw/debugdraw.hlsli index 08665d3e2..412c5ca61 100644 --- a/data/Shaders/debugdraw/debugdraw.hlsli +++ b/data/Shaders/debugdraw/debugdraw.hlsli @@ -54,18 +54,18 @@ struct DebugDrawRootConstants3D return taper; } - void setBufferHandle(uint _stream0, uint _offset = 0) + void setVertexBufferHandle(uint _stream0, uint _offset = 0) { stream0 = packUint16low(stream0, _stream0); stream0Offset = _offset; } - uint getBufferHandle() + uint getVertexBufferHandle() { return unpackUint16low(stream0); } - uint getBufferOffset() + uint getVertexBufferOffset() { return stream0Offset; } diff --git a/data/Shaders/default/default.hlsl b/data/Shaders/default/default.hlsl index c9c116a73..cae118e04 100644 --- a/data/Shaders/default/default.hlsl +++ b/data/Shaders/default/default.hlsl @@ -65,7 +65,7 @@ VS_Output VS_Forward(uint _vertexID : VertexID) GPUMaterialData materialData = instanceDataHeader.getGPUMaterialData(instanceDataOffset, rootConstants3D.getMatID()); Vertex vert; - vert.Load(getBuffer(rootConstants3D.getBufferHandle()), rootConstants3D.getVertexFormat(), _vertexID, rootConstants3D.getBufferOffset()); + vert.Load(getBuffer(rootConstants3D.getVertexBufferHandle()), rootConstants3D.getVertexFormat(), _vertexID, rootConstants3D.getVertexBufferOffset()); ViewConstants viewConstants; viewConstants.Load(getBuffer(RESERVEDSLOT_BUFSRV_VIEWCONSTANTS)); @@ -290,7 +290,7 @@ VS_Output VS_Deferred(uint _vertexID : VertexID) GPUMaterialData materialData = instanceDataHeader.getGPUMaterialData(instanceDataOffset, rootConstants3D.getMatID()); Vertex vert; - vert.Load(getBuffer(rootConstants3D.getBufferHandle()), rootConstants3D.getVertexFormat(), _vertexID, rootConstants3D.getBufferOffset()); + vert.Load(getBuffer(rootConstants3D.getVertexBufferHandle()), rootConstants3D.getVertexFormat(), _vertexID, rootConstants3D.getVertexBufferOffset()); ViewConstants viewConstants; viewConstants.Load(getBuffer(RESERVEDSLOT_BUFSRV_VIEWCONSTANTS)); diff --git a/data/Shaders/postprocess/postprocess.hlsl b/data/Shaders/postprocess/postprocess.hlsl index 63ab5e58c..2e2c9d829 100644 --- a/data/Shaders/postprocess/postprocess.hlsl +++ b/data/Shaders/postprocess/postprocess.hlsl @@ -4,6 +4,7 @@ #include "system/view.hlsli" #include "system/depthstencil.hlsli" #include "system/msaa.hlsli" +#include "system/instancedata.hlsli" #if _FXAA #include "FXAA.hlsli" @@ -151,6 +152,19 @@ float4 DebugRayTracing(float4 color, float2 uv, uint2 screenSize, ViewConstants color.rgb = float3(frac(primitiveIndex.xxx / 256.0f)); } break; + + case DisplayMode::RayTracing_Material: + { + uint instanceDataOffset = query.CommittedInstanceID(); + GPUInstanceData instanceDataHeader = getBuffer(RESERVEDSLOT_BUFSRV_INSTANCEDATA).Load(instanceDataOffset); + float4 instanceColor = instanceDataHeader.getInstanceColor(); + + GPUMaterialData materialData = instanceDataHeader.getGPUMaterialData(instanceDataOffset, query.CommittedGeometryIndex()); + float4 materialColor = materialData.getAlbedoColor(); + + color.rgb = instanceColor.rgb * materialColor.rgb; + } + break; } } break; diff --git a/data/Shaders/system/displaymodes.hlsli b/data/Shaders/system/displaymodes.hlsli index 9c8056d59..d06e48ce6 100644 --- a/data/Shaders/system/displaymodes.hlsli +++ b/data/Shaders/system/displaymodes.hlsli @@ -55,7 +55,8 @@ vg_enum_class(DisplayMode, uint, RayTracing_Barycentrics, RayTracing_InstanceID, RayTracing_GeometryIndex, - RayTracing_PrimitiveIndex, + RayTracing_PrimitiveIndex, + RayTracing_Material, PostProcess_Depth, PostProcess_LinearDepth, diff --git a/data/Shaders/system/instancedata.hlsli b/data/Shaders/system/instancedata.hlsli index b265e37fd..6d4280e1b 100644 --- a/data/Shaders/system/instancedata.hlsli +++ b/data/Shaders/system/instancedata.hlsli @@ -2,71 +2,27 @@ #include "system/packing.hlsli" #include "system/table.hlsli" -#include "system/material_consts.hlsli" +#include "system/materialdata.hlsli" -struct GPUMaterialData -{ - #ifdef __cplusplus - GPUMaterialData() - { - setAlbedoTextureHandle(RESERVEDSLOT_TEXSRV_DEFAULT_ALBEDO); - setNormalTextureHandle(RESERVEDSLOT_TEXSRV_DEFAULT_NORMAL); - setPBRTextureHandle(RESERVEDSLOT_TEXSRV_DEFAULT_PBR); - - setAlbedoColor(float4(1,1,1,1)); - setNormalStrength(1.0f); - setOcclusion(1.0f); - setRoughness(0.25f); - setMetalness(0.0f); - setTiling(float2(1.0f, 1.0f)); - } - #endif - - uint4 textures; // .x = albedo | normal, .y = pbr | unused, .y = unused, .w = flags - float4 albedoColor; - float4 data; - float4 tiling; - - void setAlbedoTextureHandle (uint _value) { textures.x = packUint16low(textures.x, _value); } - uint getAlbedoTextureHandle () { return unpackUint16low(textures.x); } - - void setNormalTextureHandle (uint _value) { textures.x = packUint16high(textures.x, _value); } - uint getNormalTextureHandle () { return unpackUint16high(textures.x); } - - void setPBRTextureHandle (uint _value) { textures.y = packUint16low(textures.y, _value); } - uint getPBRTextureHandle () { return unpackUint16low(textures.y); } - - void setUVSource (UVSource _value) { textures.w = packA8(textures.w, (uint)_value); } - UVSource getUVSource () { return (UVSource)unpackA8(textures.w);} - - void setAlbedoColor (float4 _value) { albedoColor = _value; } - float4 getAlbedoColor () { return albedoColor; } - - void setNormalStrength (float _value) { data.w = _value; } - float getNormalStrength () { return data.w; } - - void setOcclusion (float _value) { data.x = _value; } - float getOcclusion () { return data.x; } - - void setRoughness (float _value) { data.y = _value; } - float getRoughness () { return data.y; } - - void setMetalness (float _value) { data.z = _value; } - float getMetalness () { return data.z; } - - void setTiling (float2 _value) { tiling.xy = _value; } - float2 getTiling () { return tiling.xy; } -}; +#define MAX_MATERIAL_PER_INSTANCE 16 +//-------------------------------------------------------------------------------------- +// GPUInstanceData +// Materials use 16-bits indices and up to 16 materials per instance are supported +//-------------------------------------------------------------------------------------- struct GPUInstanceData { - uint4 data; + uint4 m_header; + uint m_materials[MAX_MATERIAL_PER_INSTANCE]; - void setMaterialCount (uint _count) { data.x = packUint16low(data.x, _count); } - uint getMaterialCount () { return unpackUint16low(data.x); } + void setMaterialCount (uint _count) { m_header.x = packUint16low(m_header.x, _count); } + uint getMaterialCount () { return unpackUint16low(m_header.x); } - void setInstanceColor (float4 _color) { data.y = packRGBA8(_color); } - float4 getInstanceColor () { return unpackRGBA8(data.y); } + void setInstanceColor (float4 _color) { m_header.y = packRGBA8(_color); } + float4 getInstanceColor () { return unpackRGBA8(m_header.y); } + + void setMaterialHandle (uint _index, uint _handle) { m_materials[_index] = _handle; } + uint getMaterialHandle (uint _index) { return _index < MAX_MATERIAL_PER_INSTANCE ? m_materials[_index] : 0; } #ifndef __cplusplus //-------------------------------------------------------------------------------------- @@ -75,15 +31,9 @@ struct GPUInstanceData //-------------------------------------------------------------------------------------- GPUMaterialData getGPUMaterialData (uint instanceDataOffset, uint _matID) { - uint matIndex = _matID; - uint matOffset; - - if (matIndex < getMaterialCount()) - matOffset = instanceDataOffset + sizeof(GPUInstanceData) + matIndex * sizeof(GPUMaterialData); - else - matOffset = 0 + sizeof(GPUInstanceData) + 0 * sizeof(GPUMaterialData); - - return getBuffer(RESERVEDSLOT_BUFSRV_INSTANCEDATA).Load(matOffset); + uint matIndex = getMaterialHandle(_matID); + uint matOffset = matIndex * sizeof(GPUMaterialData); + return getBuffer(RESERVEDSLOT_BUFSRV_MATERIALDATA).Load(matOffset); } #endif }; \ No newline at end of file diff --git a/data/Shaders/system/materialdata.hlsli b/data/Shaders/system/materialdata.hlsli new file mode 100644 index 000000000..78297583f --- /dev/null +++ b/data/Shaders/system/materialdata.hlsli @@ -0,0 +1,61 @@ +#pragma once + +#include "system/packing.hlsli" +#include "system/table.hlsli" +#include "system/material_consts.hlsli" + +struct GPUMaterialData +{ + #ifdef __cplusplus + GPUMaterialData() + { + setAlbedoTextureHandle(RESERVEDSLOT_TEXSRV_DEFAULT_ALBEDO); + setNormalTextureHandle(RESERVEDSLOT_TEXSRV_DEFAULT_NORMAL); + setPBRTextureHandle(RESERVEDSLOT_TEXSRV_DEFAULT_PBR); + + setAlbedoColor(float4(1,1,1,1)); + setNormalStrength(1.0f); + setOcclusion(1.0f); + setRoughness(0.25f); + setMetalness(0.0f); + setTiling(float2(1.0f, 1.0f)); + + tiling.zw = 0; // unused + } + #endif + + uint4 textures; // .x = albedo | normal, .y = pbr | unused, .y = unused, .w = flags + float4 albedoColor; + float4 data; + float4 tiling; + + void setAlbedoTextureHandle (uint _value) { textures.x = packUint16low(textures.x, _value); } + uint getAlbedoTextureHandle () { return unpackUint16low(textures.x); } + + void setNormalTextureHandle (uint _value) { textures.x = packUint16high(textures.x, _value); } + uint getNormalTextureHandle () { return unpackUint16high(textures.x); } + + void setPBRTextureHandle (uint _value) { textures.y = packUint16low(textures.y, _value); } + uint getPBRTextureHandle () { return unpackUint16low(textures.y); } + + void setUVSource (UVSource _value) { textures.w = packA8(textures.w, (uint)_value); } + UVSource getUVSource () { return (UVSource)unpackA8(textures.w);} + + void setAlbedoColor (float4 _value) { albedoColor = _value; } + float4 getAlbedoColor () { return albedoColor; } + + void setNormalStrength (float _value) { data.w = _value; } + float getNormalStrength () { return data.w; } + + void setOcclusion (float _value) { data.x = _value; } + float getOcclusion () { return data.x; } + + void setRoughness (float _value) { data.y = _value; } + float getRoughness () { return data.y; } + + void setMetalness (float _value) { data.z = _value; } + float getMetalness () { return data.z; } + + void setTiling (float2 _value) { tiling.xy = _value; } + float2 getTiling () { return tiling.xy; } +}; \ No newline at end of file diff --git a/data/Shaders/system/rootConstants3D.hlsli b/data/Shaders/system/rootConstants3D.hlsli index 80f28bf39..e023b76e1 100644 --- a/data/Shaders/system/rootConstants3D.hlsli +++ b/data/Shaders/system/rootConstants3D.hlsli @@ -52,21 +52,21 @@ struct RootConstants3D return instanceDataOffset; } - // buffer + // vertex buffer // stream0 address : 16; // stream0 offset : 16 - void setBufferHandle(uint _stream0, uint _offset = 0) + void setVertexBufferHandle(uint _stream0, uint _offset = 0) { stream0 = packUint16low(stream0, _stream0); stream0Offset = _offset; } - uint getBufferHandle() + uint getVertexBufferHandle() { return unpackUint16low(stream0); } - uint getBufferOffset() + uint getVertexBufferOffset() { return stream0Offset; } diff --git a/data/Shaders/system/table.hlsli b/data/Shaders/system/table.hlsli index 1fc306145..45e0b2e36 100644 --- a/data/Shaders/system/table.hlsli +++ b/data/Shaders/system/table.hlsli @@ -49,6 +49,7 @@ vg_enum_class(ReservedSlot, uint, LastTexture = InvalidTexture2D, // Buffer + MaterialDataBufSrv = BINDLESS_BUFFER_INVALID - 5, InstanceDataBufSrv = BINDLESS_BUFFER_INVALID - 4, SkinningMatricesBufSrv = BINDLESS_BUFFER_INVALID - 3, LightsConstantBufSrv = BINDLESS_BUFFER_INVALID - 2, @@ -82,6 +83,7 @@ vg_enum_class(ReservedSlot, uint, #define RESERVEDSLOT_TEXSRV_IMGUIFONTTEX (BINDLESS_TEXTURE_INVALID - 1) // Buffer SRV +#define RESERVEDSLOT_BUFSRV_MATERIALDATA (BINDLESS_BUFFER_INVALID - 5) #define RESERVEDSLOT_BUFSRV_INSTANCEDATA (BINDLESS_BUFFER_INVALID - 4) #define RESERVEDSLOT_BUFSRV_SKINNINGMATRICES (BINDLESS_BUFFER_INVALID - 3) #define RESERVEDSLOT_BUFSRV_LIGHTSCONSTANTS (BINDLESS_BUFFER_INVALID - 2) diff --git a/src/gfx/Raytracing/TLAS.hpp b/src/gfx/Raytracing/TLAS.hpp index b7d7a1aa1..e69965676 100644 --- a/src/gfx/Raytracing/TLAS.hpp +++ b/src/gfx/Raytracing/TLAS.hpp @@ -65,6 +65,6 @@ namespace vg::gfx //-------------------------------------------------------------------------------------- void TLAS::addInstance(const gfx::BLAS * _blas, const core::float4x4 & _world, const core::u32 _instanceID) { - super::addInstance(_blas, _world, 0/*_instanceID*/); + super::addInstance(_blas, _world, _instanceID); } } \ No newline at end of file diff --git a/src/renderer/DebugDraw/DebugDraw.cpp b/src/renderer/DebugDraw/DebugDraw.cpp index 4348ccb53..853930cd0 100644 --- a/src/renderer/DebugDraw/DebugDraw.cpp +++ b/src/renderer/DebugDraw/DebugDraw.cpp @@ -500,7 +500,7 @@ namespace vg::renderer DebugDrawRootConstants3D debugDraw3D; { debugDraw3D.setWorldMatrix(transpose(aabbMatrixWS)); - debugDraw3D.setBufferHandle(m_box->getVertexBuffer()->getBufferHandle(), m_box->getVertexBufferOffset()); + debugDraw3D.setVertexBufferHandle(m_box->getVertexBuffer()->getBufferHandle(), m_box->getVertexBufferOffset()); debugDraw3D.setVertexFormat(VertexFormat::DebugDraw); } @@ -564,7 +564,7 @@ namespace vg::renderer DebugDrawRootConstants3D debugDrawRoot3D; debugDrawRoot3D.setWorldMatrix(float4x4::identity()); - debugDrawRoot3D.setBufferHandle(m_gridVB->getBufferHandle()); + debugDrawRoot3D.setVertexBufferHandle(m_gridVB->getBufferHandle()); debugDrawRoot3D.setVertexFormat(VertexFormat::DebugDraw); debugDrawRoot3D.setColor(float4(1, 1, 1, 1)); @@ -587,7 +587,7 @@ namespace vg::renderer DebugDrawRootConstants3D debugDrawRoot3D; debugDrawRoot3D.setWorldMatrix(float4x4::identity()); - debugDrawRoot3D.setBufferHandle(m_axisVB->getBufferHandle()); + debugDrawRoot3D.setVertexBufferHandle(m_axisVB->getBufferHandle()); debugDrawRoot3D.setVertexFormat(VertexFormat::DebugDraw); debugDrawRoot3D.setColor(float4(1, 1, 1, 1)); @@ -854,7 +854,7 @@ namespace vg::renderer // Root constants DebugDrawRootConstants3D debugDrawRoot3D; debugDrawRoot3D.setWorldMatrix(float4x4::identity()); - debugDrawRoot3D.setBufferHandle(drawData.m_debugDrawVB->getBufferHandle(), drawData.m_linesVBOffset); + debugDrawRoot3D.setVertexBufferHandle(drawData.m_debugDrawVB->getBufferHandle(), drawData.m_linesVBOffset); debugDrawRoot3D.setVertexFormat(VertexFormat::DebugDraw); debugDrawRoot3D.setColor(float4(1, 1, 1, 1)); @@ -934,7 +934,7 @@ namespace vg::renderer // Root constants DebugDrawRootConstants3D debugDraw3D; - debugDraw3D.setBufferHandle(_geometry->getVertexBuffer()->getBufferHandle()); + debugDraw3D.setVertexBufferHandle(_geometry->getVertexBuffer()->getBufferHandle()); debugDraw3D.setVertexFormat(VertexFormat::DebugDraw); // Transparent diff --git a/src/renderer/Instance/Mesh/MeshInstance.hpp b/src/renderer/Instance/Mesh/MeshInstance.hpp index 6a157fb88..8087232d7 100644 --- a/src/renderer/Instance/Mesh/MeshInstance.hpp +++ b/src/renderer/Instance/Mesh/MeshInstance.hpp @@ -235,7 +235,10 @@ namespace vg::renderer auto * tlas = _view->getTLAS(); if (const auto * blas = getInstanceBLAS()) - tlas->addInstance(blas, getGlobalMatrix(), _index); + { + u32 rayTracingID = getGPUInstanceDataOffset(); + tlas->addInstance(blas, getGlobalMatrix(), rayTracingID); + } return true; } @@ -260,9 +263,9 @@ namespace vg::renderer root3D.setGPUInstanceDataOffset(getGPUInstanceDataOffset()); if (IsSkinned()) - root3D.setBufferHandle(m_skinnedMeshBuffer->getBufferHandle(), m_skinnedMeshBufferOffset); + root3D.setVertexBufferHandle(m_skinnedMeshBuffer->getBufferHandle(), m_skinnedMeshBufferOffset); else - root3D.setBufferHandle(geo->getVertexBuffer()->getBufferHandle(), geo->getVertexBufferOffset()); + root3D.setVertexBufferHandle(geo->getVertexBuffer()->getBufferHandle(), geo->getVertexBufferOffset()); u16 flags = 0; root3D.setFlags(flags); diff --git a/src/renderer/Model/Material/DefaultMaterial/DefaultMaterialModel.h b/src/renderer/Model/Material/DefaultMaterial/DefaultMaterialModel.h index 6be23e801..9873e5bf2 100644 --- a/src/renderer/Model/Material/DefaultMaterial/DefaultMaterialModel.h +++ b/src/renderer/Model/Material/DefaultMaterial/DefaultMaterialModel.h @@ -12,32 +12,32 @@ namespace vg::renderer DefaultMaterialModel(const core::string & _name, IObject * _parent); ~DefaultMaterialModel(); - void SetSurfaceType (gfx::SurfaceType _surfaceType) final override; - void SetColor (const core::string & _name, core::float4 _value) final override; - void SetTexture (const core::string & _name, gfx::ITexture * _value) final override; - void SetFloat (const core::string & _name, float _value) final override; - void SetFloat2 (const core::string & _name, core::float2 _value) final override; + void SetSurfaceType (gfx::SurfaceType _surfaceType) final override; + void SetColor (const core::string & _name, core::float4 _value) final override; + void SetTexture (const core::string & _name, gfx::ITexture * _value) final override; + void SetFloat (const core::string & _name, float _value) final override; + void SetFloat2 (const core::string & _name, core::float2 _value) final override; - void FillGPUMaterialData (GPUMaterialData * _data) const final override; + void FillGPUMaterialData (GPUMaterialData * _data) const final override; - void Setup (const RenderContext & _renderContext, gfx::CommandList * _cmdList, RootConstants3D * _root3D, core::uint _index) const final override; + void Setup (const RenderContext & _renderContext, gfx::CommandList * _cmdList, RootConstants3D * _root3D, core::uint _index) const final override; protected: - void assignTexture (gfx::Texture ** _texture, gfx::Texture * _value); + void assignTexture (gfx::Texture ** _texture, gfx::Texture * _value); private: - UVSource m_UVSource = UVSource::UV0; - core::float2 m_tiling = core::float2(1,1); + UVSource m_UVSource = UVSource::UV0; + core::float2 m_tiling = core::float2(1,1); - gfx::Texture * m_albedoMap = nullptr; - core::float4 m_albedoColor = core::float4(1,1,1,1); + gfx::Texture * m_albedoMap = nullptr; + core::float4 m_albedoColor = core::float4(1,1,1,1); - gfx::Texture * m_normalMap = nullptr; - float m_normalStrength = 1.0f; + gfx::Texture * m_normalMap = nullptr; + float m_normalStrength = 1.0f; - gfx::Texture * m_pbrMap = nullptr; - float m_occlusion = 1.0f; - float m_roughness = 1.0f; - float m_metalness = 1.0f; + gfx::Texture * m_pbrMap = nullptr; + float m_occlusion = 1.0f; + float m_roughness = 1.0f; + float m_metalness = 1.0f; }; } \ No newline at end of file diff --git a/src/renderer/Model/Material/DefaultMaterial/DefaultMaterialModel.hpp b/src/renderer/Model/Material/DefaultMaterial/DefaultMaterialModel.hpp index 40c4f7268..f40019953 100644 --- a/src/renderer/Model/Material/DefaultMaterial/DefaultMaterialModel.hpp +++ b/src/renderer/Model/Material/DefaultMaterial/DefaultMaterialModel.hpp @@ -1,6 +1,7 @@ #include "DefaultMaterialModel.h" #include "Shaders/default/default.hlsl.h" -#include "Shaders/system/instancedata.hlsli" +#include "Shaders/system/materialdata.hlsli" +#include "renderer/Model/Material/MaterialManager.h" namespace vg::renderer { @@ -39,13 +40,15 @@ namespace vg::renderer DefaultMaterialModel::DefaultMaterialModel(const core::string & _name, IObject * _parent) : MaterialModel(_name, _parent) { - + // Register slot for material GPU data + m_gpuDataHandle = Renderer::get()->getMaterialManager()->allocMaterialDataGPUHandle(this); } //-------------------------------------------------------------------------------------- DefaultMaterialModel::~DefaultMaterialModel() { - + // Unregister slot for material GPU data + Renderer::get()->getMaterialManager()->freeMaterialDataGPUHandle(m_gpuDataHandle); } //-------------------------------------------------------------------------------------- diff --git a/src/renderer/Model/Material/MaterialManager.cpp b/src/renderer/Model/Material/MaterialManager.cpp new file mode 100644 index 000000000..50b154513 --- /dev/null +++ b/src/renderer/Model/Material/MaterialManager.cpp @@ -0,0 +1,22 @@ +#include "renderer/Precomp.h" +#include "MaterialManager.h" + +namespace vg::renderer +{ + //-------------------------------------------------------------------------------------- + MaterialDataGPUHandle MaterialManager::allocMaterialDataGPUHandle(MaterialModel * _material) + { + MaterialDataGPUHandle handle = m_handles.alloc(); + if (m_materials.size() < handle + 1) + m_materials.resize(handle + 1); + m_materials[handle] = _material; + return handle; + } + + //-------------------------------------------------------------------------------------- + void MaterialManager::freeMaterialDataGPUHandle(MaterialDataGPUHandle & _handle) + { + m_materials[_handle] = nullptr; + m_handles.dealloc(_handle); + } +} \ No newline at end of file diff --git a/src/renderer/Model/Material/MaterialManager.h b/src/renderer/Model/Material/MaterialManager.h new file mode 100644 index 000000000..b167a1fe5 --- /dev/null +++ b/src/renderer/Model/Material/MaterialManager.h @@ -0,0 +1,22 @@ +#pragma once + +#include "core/Singleton/Singleton.h" +#include "Material_Consts.h" +#include "core/Pool/IndexPool.h" + +namespace vg::renderer +{ + class MaterialModel; + class MaterialManager : public core::Singleton + { + public: + MaterialDataGPUHandle allocMaterialDataGPUHandle (MaterialModel * _material); + void freeMaterialDataGPUHandle (MaterialDataGPUHandle & _handle); + + VG_INLINE const core::vector getMaterials() const { return m_materials; } + + private: + core::IndexPool m_handles; + core::vector m_materials; + }; +} \ No newline at end of file diff --git a/src/renderer/Model/Material/MaterialModel.h b/src/renderer/Model/Material/MaterialModel.h index c4abeb06e..d268529f8 100644 --- a/src/renderer/Model/Material/MaterialModel.h +++ b/src/renderer/Model/Material/MaterialModel.h @@ -38,24 +38,27 @@ namespace vg public: - const char * GetClassName () const = 0; + const char * GetClassName () const = 0; - static bool registerProperties (core::IClassDesc & _desc); + static bool registerProperties (core::IClassDesc & _desc); - MaterialModel (const core::string & _name, core::IObject * _parent = nullptr); - ~MaterialModel (); + MaterialModel (const core::string & _name, core::IObject * _parent = nullptr); + ~MaterialModel (); - virtual void FillGPUMaterialData (GPUMaterialData * _data) const = 0; + virtual void FillGPUMaterialData (GPUMaterialData * _data) const = 0; - virtual void Setup (const RenderContext & _renderContext, gfx::CommandList * _cmdList, RootConstants3D * _root3DConstants, core::uint _index) const = 0; + virtual void Setup (const RenderContext & _renderContext, gfx::CommandList * _cmdList, RootConstants3D * _root3DConstants, core::uint _index) const = 0; - VG_INLINE gfx::SurfaceType getSurfaceType () const { return m_surfaceType; } + VG_INLINE gfx::SurfaceType getSurfaceType () const { return m_surfaceType; } + VG_INLINE MaterialDataGPUHandle getMaterialDataGPUHandle() const { return m_gpuDataHandle; } protected: - gfx::SurfaceType m_surfaceType; - gfx::CullMode m_cullMode; - gfx::RootSignatureHandle m_rootSignature; - gfx::ShaderKey m_shaderKey[core::enumCount()]; + + MaterialDataGPUHandle m_gpuDataHandle = (MaterialDataGPUHandle)-1; + gfx::SurfaceType m_surfaceType; + gfx::CullMode m_cullMode; + gfx::RootSignatureHandle m_rootSignature; + gfx::ShaderKey m_shaderKey[core::enumCount()]; }; } } \ No newline at end of file diff --git a/src/renderer/Model/Material/Material_Consts.h b/src/renderer/Model/Material/Material_Consts.h index aaa11c0ab..70cfa3b0d 100644 --- a/src/renderer/Model/Material/Material_Consts.h +++ b/src/renderer/Model/Material/Material_Consts.h @@ -5,6 +5,9 @@ namespace vg::renderer { + static const auto s_MaxMaterialCount = 65536; + using MaterialDataGPUHandle = u16; + vg_enum_class(MaterialTextureType, core::u8, Albedo = 0, Normal, diff --git a/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.h b/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.h index c16fb2328..ff78a7b7e 100644 --- a/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.h +++ b/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.h @@ -21,6 +21,6 @@ namespace vg::renderer void BeforeRender(const gfx::RenderPassContext & _renderPassContext, gfx::CommandList * _cmdList) final override; private: - gfx::Buffer * m_InstanceDataConstantsBuffer = nullptr; + gfx::Buffer * m_instanceDataBuffer = nullptr; }; } \ No newline at end of file diff --git a/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.hpp b/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.hpp index 0932ead72..08bdd2534 100644 --- a/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.hpp +++ b/src/renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.hpp @@ -1,9 +1,6 @@ #include "InstanceDataUpdatePass.h" #include "Shaders/system/instancedata.hlsli" -// TODO : handle different material data & size? -//#include "renderer/Model/Material/DefaultMaterial/DefaultMaterialModel.h" - namespace vg::renderer { static const uint s_InstanceDataBufferSize = 16 * 1024; @@ -15,13 +12,13 @@ namespace vg::renderer auto * device = Device::get(); BufferDesc instanceDataBufferDesc = BufferDesc(Usage::Default, BindFlags::ShaderResource, CPUAccessFlags::Write, BufferFlags::None, s_InstanceDataBufferSize); - m_InstanceDataConstantsBuffer = device->createBuffer(instanceDataBufferDesc, "InstanceData", nullptr, ReservedSlot::InstanceDataBufSrv); + m_instanceDataBuffer = device->createBuffer(instanceDataBufferDesc, "InstanceData", nullptr, ReservedSlot::InstanceDataBufSrv); } //-------------------------------------------------------------------------------------- InstanceDataUpdatePass::~InstanceDataUpdatePass() { - VG_SAFE_RELEASE(m_InstanceDataConstantsBuffer); + VG_SAFE_RELEASE(m_instanceDataBuffer); } //-------------------------------------------------------------------------------------- @@ -34,18 +31,19 @@ namespace vg::renderer const auto & instances = cullingJobOutput->m_instances; const auto * defaultMaterial = renderer->getDefaultMaterial(); VG_ASSERT(defaultMaterial); + const auto defaultMaterialHandle = defaultMaterial->getMaterialDataGPUHandle(); + VG_ASSERT(defaultMaterialHandle == 0); size_t mapSize = 0; - // Fill empty instance data and default material at the beginning of the Buffer - mapSize += sizeof(GPUInstanceData) + 1 * sizeof(GPUMaterialData); + mapSize += sizeof(GPUInstanceData); for (uint i = 0; i < instances.size(); ++i) { GraphicInstance * instance = instances[i]; const uint materialCount = (uint)instance->getMaterials().size(); - mapSize += sizeof(GPUInstanceData) + materialCount * sizeof(GPUMaterialData); + mapSize += sizeof(GPUInstanceData); // clear atomic flag after processing instance->removeAtomicFlags(GraphicInstance::AtomicFlags::Instance); @@ -54,60 +52,47 @@ namespace vg::renderer if (mapSize > 0) { uint offset = 0; - const u8 * data = (const u8 *)_cmdList->map(m_InstanceDataConstantsBuffer, mapSize).data; + const u8 * data = (const u8 *)_cmdList->map(m_instanceDataBuffer, mapSize).data; { // Whenever an instance data or material data is missing default instance/material data can be used instead { - GPUInstanceData * defaultHeader = (GPUInstanceData *)(data + offset); + GPUInstanceData * defaultInstanceData = (GPUInstanceData *)(data + offset); { - defaultHeader->setMaterialCount(1); - defaultHeader->setInstanceColor(float4(1,1,1,1)); + defaultInstanceData->setMaterialCount(1); + defaultInstanceData->setInstanceColor(float4(1,1,1,1)); + defaultInstanceData->setMaterialHandle(0, defaultMaterialHandle); } offset += sizeof(GPUInstanceData); - - GPUMaterialData * defaultMatData = (GPUMaterialData *)(data + offset); - { - defaultMaterial->FillGPUMaterialData(defaultMatData); - } - offset += sizeof(GPUMaterialData); } for (uint i = 0; i < instances.size(); ++i) { - //VG_PROFILE_CPU("GPUInstanceData"); - GraphicInstance * instance = instances[i]; const auto & materials = instance->getMaterials(); - const uint materialCount = (uint)materials.size(); + + VG_ASSERT(materials.size() < MAX_MATERIAL_PER_INSTANCE); + const uint materialCount = min((uint)materials.size(), (uint)MAX_MATERIAL_PER_INSTANCE); instance->setGPUInstanceDataOffset(offset); - GPUInstanceData * instanceHeader = (GPUInstanceData *)(data + offset); + GPUInstanceData * instanceData = (GPUInstanceData *)(data + offset); { - instanceHeader->setMaterialCount(materialCount); - instanceHeader->setInstanceColor(instance->getColor()); - } - offset += sizeof(GPUInstanceData); - - // Materials - { - //VG_PROFILE_CPU("GPUMaterialData"); + instanceData->setMaterialCount(materialCount); + instanceData->setInstanceColor(instance->getColor()); + for (uint m = 0; m < materialCount; ++m) { - GPUMaterialData * matData = (GPUMaterialData *)(data + offset); - const MaterialModel * matModel = materials[m]; - if (nullptr == matModel) - matModel = defaultMaterial; - - if (matModel) - matModel->FillGPUMaterialData(matData); - - offset += sizeof(GPUMaterialData); + const MaterialModel * mat = materials[m]; + if (nullptr != mat) + instanceData->setMaterialHandle(m, mat->getMaterialDataGPUHandle()); + else + instanceData->setMaterialHandle(m, defaultMaterialHandle); } } + offset += sizeof(GPUInstanceData); } } - _cmdList->unmap(m_InstanceDataConstantsBuffer); + _cmdList->unmap(m_instanceDataBuffer); VG_ASSERT(offset == mapSize); } diff --git a/src/renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.h b/src/renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.h new file mode 100644 index 000000000..f581bcf52 --- /dev/null +++ b/src/renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.h @@ -0,0 +1,26 @@ +#pragma once + +#include "Renderer/RenderPass/Update/UpdatePass.h" + +namespace vg::gfx +{ + class Buffer; +} + +namespace vg::renderer +{ + //-------------------------------------------------------------------------------------- + class MaterialDataUpdatePass : public UpdatePass + { + public: + const char * GetClassName() const final { return "MaterialDataUpdatePass"; } + + MaterialDataUpdatePass(); + ~MaterialDataUpdatePass(); + + void BeforeRender(const gfx::RenderPassContext & _renderPassContext, gfx::CommandList * _cmdList) final override; + + private: + gfx::Buffer * m_materialDataBuffer = nullptr; + }; +} \ No newline at end of file diff --git a/src/renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.hpp b/src/renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.hpp new file mode 100644 index 000000000..ecddf7059 --- /dev/null +++ b/src/renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.hpp @@ -0,0 +1,63 @@ +#include "MaterialDataUpdatePass.h" +#include "Shaders/system/materialdata.hlsli" +#include "renderer\Model\Material\MaterialManager.h" + +namespace vg::renderer +{ + static const uint s_MaterialDataBufferSize = 16 * 1024; + + //-------------------------------------------------------------------------------------- + MaterialDataUpdatePass::MaterialDataUpdatePass() : + UpdatePass("MaterialDataUpdatePass") + { + auto * device = Device::get(); + + BufferDesc materialDataBufferDesc = BufferDesc(Usage::Default, BindFlags::ShaderResource, CPUAccessFlags::Write, BufferFlags::None, s_MaterialDataBufferSize); + m_materialDataBuffer = device->createBuffer(materialDataBufferDesc, "MaterialData", nullptr, ReservedSlot::MaterialDataBufSrv); + } + + //-------------------------------------------------------------------------------------- + MaterialDataUpdatePass::~MaterialDataUpdatePass() + { + VG_SAFE_RELEASE(m_materialDataBuffer); + } + + //-------------------------------------------------------------------------------------- + void MaterialDataUpdatePass::BeforeRender(const gfx::RenderPassContext & _renderPassContext, gfx::CommandList * _cmdList) + { + auto renderer = Renderer::get(); + const auto * cullingJobOutput = renderer->getSharedCullingJobOutput(); + VG_ASSERT(nullptr != cullingJobOutput); + + const auto & instances = cullingJobOutput->m_instances; + const auto * defaultMaterial = renderer->getDefaultMaterial(); + VG_ASSERT(defaultMaterial); + + MaterialManager * materialManager = MaterialManager::get(); + + const auto & materials = materialManager->getMaterials(); + size_t mapSize = materials.size() * sizeof(GPUMaterialData); + + if (mapSize > 0) + { + uint offset = 0; + const u8 * data = (const u8 *)_cmdList->map(m_materialDataBuffer, mapSize).data; + { + for (uint i = 0; i < materials.size(); ++i) + { + GPUMaterialData * dst = (GPUMaterialData *)(data + offset); + + const auto * material = materials[i]; + if (nullptr == material) + material = defaultMaterial; + + material->FillGPUMaterialData(dst); + offset += sizeof(GPUMaterialData); + } + } + _cmdList->unmap(m_materialDataBuffer); + + VG_ASSERT(offset == mapSize); + } + } +} diff --git a/src/renderer/RenderPass/Update/UpdatePass.hpp b/src/renderer/RenderPass/Update/UpdatePass.hpp index bf8dd02b0..d683008fe 100644 --- a/src/renderer/RenderPass/Update/UpdatePass.hpp +++ b/src/renderer/RenderPass/Update/UpdatePass.hpp @@ -2,6 +2,7 @@ #include "Update/GPUDebug/GPUDebugUpdatePass.hpp" #include "Update/InstanceData/InstanceDataUpdatePass.hpp" +#include "Update/MaterialData/MaterialDataUpdatePass.hpp" #include "Update/TLAS/TLASUpdatePass.hpp" #include "Update/BLAS/BLASUpdatePass.hpp" #include "Update/ViewConstants/ViewConstantsUpdatePass.hpp" diff --git a/src/renderer/Renderer.cpp b/src/renderer/Renderer.cpp index ba54db5d9..51a0afdd2 100644 --- a/src/renderer/Renderer.cpp +++ b/src/renderer/Renderer.cpp @@ -22,6 +22,7 @@ #include "renderer/RenderPass/ImGui/imguiAdapter.h" #include "renderer/RenderPass/Update/GPUDebug/GPUDebugUpdatePass.h" #include "renderer/RenderPass/Update/InstanceData/InstanceDataUpdatePass.h" +#include "renderer/RenderPass/Update/MaterialData/MaterialDataUpdatePass.h" #include "renderer/RenderPass/Compute/ComputeSkinning/ComputeSkinningPass.h" #include "renderer/RenderPass/Update/BLAS/BLASUpdatePass.h" #include "renderer/RenderPass/Render2D/HDROutput/HDROutputPass.h" @@ -44,6 +45,7 @@ #include "renderer/Instance/Light/Directional/DirectionalLightInstance.h" #include "renderer/Instance/Light/Omni/OmniLightInstance.h" #include "renderer/UI/UIManager.h" +#include "renderer/Model/Material/MaterialManager.h" #if !VG_ENABLE_INLINE #include "Renderer.inl" @@ -203,6 +205,7 @@ namespace vg::renderer // Create passes not bound to a View m_gpuDebugUpdatePass = new GPUDebugUpdatePass(); m_instanceDataUpdatePass = new InstanceDataUpdatePass(); + m_materialDataUpdatePass = new MaterialDataUpdatePass(); m_computeSkinningPass = new ComputeSkinningPass(); m_computeSpecularBRDFPass = new ComputeSpecularBRDFPass(); m_computeIBLCubemapsPass = new ComputeIBLCubemapsPass(); @@ -216,6 +219,8 @@ namespace vg::renderer RendererOptions * options = new RendererOptions("Renderer Options", this); + m_materialManager = new MaterialManager(); + initDefaultTextures(); initDefaultMaterials(); @@ -300,6 +305,7 @@ namespace vg::renderer VG_SAFE_RELEASE(m_gpuDebugUpdatePass); VG_SAFE_RELEASE(m_instanceDataUpdatePass); + VG_SAFE_RELEASE(m_materialDataUpdatePass); VG_SAFE_DELETE(m_computeSkinningPass); VG_SAFE_DELETE(m_computeSpecularBRDFPass); VG_SAFE_DELETE(m_computeIBLCubemapsPass); @@ -309,9 +315,10 @@ namespace vg::renderer VG_SAFE_DELETE(m_hdrOutputPass); m_frameGraph.Release(); - + m_device.deinit(); + VG_SAFE_DELETE(m_materialManager); VG_SAFE_RELEASE(m_picking); } @@ -489,6 +496,7 @@ namespace vg::renderer m_frameGraph.addUserPass(mainViewRenderPassContext, m_gpuDebugUpdatePass, "GPU Debug"); m_frameGraph.addUserPass(mainViewRenderPassContext, m_instanceDataUpdatePass, "Instance Data"); + m_frameGraph.addUserPass(mainViewRenderPassContext, m_materialDataUpdatePass, "Material Data"); m_frameGraph.addUserPass(mainViewRenderPassContext, m_computeSkinningPass, "Skinning"); if (options->isRayTracingEnabled()) @@ -1121,6 +1129,7 @@ namespace vg::renderer { VG_ASSERT(nullptr == m_defaultMaterial); m_defaultMaterial = new DefaultMaterialModel("Default Material", this); + VG_ASSERT(m_defaultMaterial->getMaterialDataGPUHandle() == 0); } //-------------------------------------------------------------------------------------- @@ -1285,4 +1294,6 @@ namespace vg::renderer if (m_computeSpecularBRDFPass) m_computeSpecularBRDFPass->setSpecularBRDFTexture(nullptr); } + + } \ No newline at end of file diff --git a/src/renderer/Renderer.h b/src/renderer/Renderer.h index 7a22800b2..795d225cb 100644 --- a/src/renderer/Renderer.h +++ b/src/renderer/Renderer.h @@ -19,6 +19,7 @@ namespace vg::renderer class FBXImporter; class GPUDebugUpdatePass; class InstanceDataUpdatePass; + class MaterialDataUpdatePass; class ComputeSkinningPass; class BLASUpdatePass; class ComputeSpecularBRDFPass; @@ -30,6 +31,7 @@ namespace vg::renderer class View; class Viewport; class DebugDraw; + class MaterialManager; struct SharedCullingJobOutput; @@ -134,8 +136,10 @@ namespace vg::renderer public: // internal gfx::Texture * getBackbuffer () const; - ImGuiAdapter * getImGuiAdapter () const { return m_imgui; } - SharedCullingJobOutput * getSharedCullingJobOutput () const { return m_sharedCullingJobOutput; } + + VG_INLINE ImGuiAdapter * getImGuiAdapter () const; + VG_INLINE SharedCullingJobOutput * getSharedCullingJobOutput () const; + VG_INLINE MaterialManager * getMaterialManager () const; private: void registerShaders (); @@ -159,6 +163,7 @@ namespace vg::renderer FBXImporter * m_fbxImporter = nullptr; GPUDebugUpdatePass * m_gpuDebugUpdatePass = nullptr; InstanceDataUpdatePass * m_instanceDataUpdatePass = nullptr; + MaterialDataUpdatePass * m_materialDataUpdatePass = nullptr; ComputeSkinningPass * m_computeSkinningPass = nullptr; BLASUpdatePass * m_BLASUpdatePass = nullptr; ComputeSpecularBRDFPass * m_computeSpecularBRDFPass = nullptr; @@ -179,6 +184,8 @@ namespace vg::renderer gfx::Texture * m_bakedSpecularBRDF = nullptr; gfx::Texture * m_generatedSpecularBRDF = nullptr; + + MaterialManager * m_materialManager = nullptr; }; } diff --git a/src/renderer/Renderer.inl b/src/renderer/Renderer.inl index 3394b90d8..ee970718a 100644 --- a/src/renderer/Renderer.inl +++ b/src/renderer/Renderer.inl @@ -1,14 +1,32 @@ namespace vg::renderer { //-------------------------------------------------------------------------------------- - gfx::Texture * Renderer::getDefaultTexture(MaterialTextureType _type) const + VG_INLINE gfx::Texture * Renderer::getDefaultTexture(MaterialTextureType _type) const { return m_defaultTextures[core::asInteger(_type)]; } //-------------------------------------------------------------------------------------- - MaterialModel * Renderer::getDefaultMaterial() const + VG_INLINE MaterialModel * Renderer::getDefaultMaterial() const { return m_defaultMaterial; } + + //-------------------------------------------------------------------------------------- + VG_INLINE ImGuiAdapter * Renderer::getImGuiAdapter() const + { + return m_imgui; + } + + //-------------------------------------------------------------------------------------- + VG_INLINE SharedCullingJobOutput * Renderer::getSharedCullingJobOutput() const + { + return m_sharedCullingJobOutput; + } + + //-------------------------------------------------------------------------------------- + VG_INLINE MaterialManager * Renderer::getMaterialManager() const + { + return m_materialManager; + } } \ No newline at end of file diff --git a/src/renderer/renderer.vcxproj b/src/renderer/renderer.vcxproj index 50243e6eb..d8284f00a 100644 --- a/src/renderer/renderer.vcxproj +++ b/src/renderer/renderer.vcxproj @@ -58,6 +58,7 @@ + @@ -156,6 +157,7 @@ + @@ -227,6 +229,8 @@ + + diff --git a/src/renderer/renderer.vcxproj.filters b/src/renderer/renderer.vcxproj.filters index b6639028f..a80649c35 100644 --- a/src/renderer/renderer.vcxproj.filters +++ b/src/renderer/renderer.vcxproj.filters @@ -54,6 +54,9 @@ UI + + Model\Material + @@ -497,6 +500,15 @@ Pass\Compute\ComputeIrradianceCubemap + + Pass\Update\MaterialData + + + Pass\Update\MaterialData + + + Model\Material + @@ -685,5 +697,8 @@ {5557cf22-dc6c-4619-ab24-5164c9d8934b} + + {bafa5eb6-d76f-4359-a079-bbc20e7b6743} + \ No newline at end of file diff --git a/vgframework.sln b/vgframework.sln index 823f5e394..dc3b62ccb 100644 --- a/vgframework.sln +++ b/vgframework.sln @@ -92,6 +92,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "system", "system", "{34ABDE data\Shaders\system\instancedata.hlsli = data\Shaders\system\instancedata.hlsli data\Shaders\system\lighting.hlsli = data\Shaders\system\lighting.hlsli data\Shaders\system\lightsBuffer.hlsli = data\Shaders\system\lightsBuffer.hlsli + data\Shaders\system\materialdata.hlsli = data\Shaders\system\materialdata.hlsli data\Shaders\system\material_consts.hlsli = data\Shaders\system\material_consts.hlsli data\Shaders\system\msaa.hlsli = data\Shaders\system\msaa.hlsli data\Shaders\system\packing.hlsli = data\Shaders\system\packing.hlsli