Skip to content

Commit

Permalink
Render to cubemap slices and mipmaps from compute shaders
Browse files Browse the repository at this point in the history
  • Loading branch information
Benualdo committed Nov 11, 2024
1 parent 3eb9602 commit 6f7fea8
Show file tree
Hide file tree
Showing 25 changed files with 409 additions and 153 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/Build_Win64_DX12.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ jobs:
- name: Send Discord Notification
shell: pwsh
run: |
$DISCORD_WEBHOOK_URL = "${{ secrets.DISCORD_WEBHOOK_URL }}"
$DISCORD_RELEASE_WEBHOOK_URL = "${{ secrets.DISCORD_RELEASE_WEBHOOK_URL }}"
$versionContent = Get-Content "src/version.h"
$major, $minor, $patch = "", "", ""
Expand Down Expand Up @@ -192,7 +192,7 @@ jobs:
{
"type": "rich",
"title": "VGFramework $fullVersion ($gitRevision)",
"description": "A new version is available",
"description": "A new version of VGFramework is available",
"color": 15579707,
"thumbnail": {
"url": "https://github.com/vimontgames/vgframework/blob/master/doc/img/newversion.png?raw=true"
Expand All @@ -209,7 +209,7 @@ jobs:
"@
# Send the notification using curl
$RESPONSE = curl -H "Content-Type: application/json" -X POST -d $jsonPayload $DISCORD_WEBHOOK_URL
$RESPONSE = curl -H "Content-Type: application/json" -X POST -d $jsonPayload $DISCORD_RELEASE_WEBHOOK_URL
# Output the response from the server
Write-Output "Webhook server response: $RESPONSE"
27 changes: 23 additions & 4 deletions data/Shaders/lighting/PrecomputeIBL.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -61,16 +61,35 @@ float2 IntegrateBRDF(float NdotV, float roughness)
}

//--------------------------------------------------------------------------------------
[numthreads(PRECOMPUTE_IBL_THREADGROUP_SIZE_X, PRECOMPUTE_IBL_THREADGROUP_SIZE_X, 1)]
[numthreads(PRECOMPUTE_IBL_THREADGROUP_SIZE_X, PRECOMPUTE_IBL_THREADGROUP_SIZE_Y, PRECOMPUTE_IBL_THREADGROUP_SIZE_Z)]
void CS_GenerateSpecularBRDF(int2 dispatchThreadID : SV_DispatchThreadID)
{
const int2 size = precomputeIBLConstants.getSize();
const int2 size = precomputeIBLConstants.getDestinationSize();

float cosLo = (float)(dispatchThreadID.x) / (float)(size.x-1);
float roughness = (float)(size.y-dispatchThreadID.y-1) / (float)(size.y-1);

// clamp cosLo to avoid NaN
cosLo = max(cosLo, 0.001);

getRWTexture2D_float2(precomputeIBLConstants.getSpecularBRDF())[dispatchThreadID.xy] = IntegrateBRDF(cosLo, roughness);
}
getRWTexture2D_float2(precomputeIBLConstants.getDestination())[dispatchThreadID.xy] = IntegrateBRDF(cosLo, roughness);
}

//--------------------------------------------------------------------------------------
[numthreads(PRECOMPUTE_IBL_THREADGROUP_SIZE_X, PRECOMPUTE_IBL_THREADGROUP_SIZE_Y, PRECOMPUTE_IBL_THREADGROUP_SIZE_Z)]
void CS_GenerateIrradianceCubemap(int3 dispatchThreadID : SV_DispatchThreadID)
{
const int2 size = precomputeIBLConstants.getDestinationSize();

getRWTexture2DArray(precomputeIBLConstants.getDestination())[dispatchThreadID.xyz] = float4(1,0,1,1);
}

//--------------------------------------------------------------------------------------
[numthreads(PRECOMPUTE_IBL_THREADGROUP_SIZE_X, PRECOMPUTE_IBL_THREADGROUP_SIZE_Y, PRECOMPUTE_IBL_THREADGROUP_SIZE_Z)]
void CS_GenerateSpecularReflectionCubemap(int3 dispatchThreadID : SV_DispatchThreadID)
{
const int2 size = precomputeIBLConstants.getDestinationSize();

getRWTexture2DArray(precomputeIBLConstants.getDestination())[dispatchThreadID.xyz] = float4(size / 256.0, (float)dispatchThreadID.z / 6.0f, 1);
}

11 changes: 10 additions & 1 deletion data/Shaders/lighting/PrecomputeIBL.hlsl.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,16 @@ namespace vg::gfx
auto & generateSpecularBRDFTech = declTechnique("GenerateSpecularBRDF");
{
generateSpecularBRDFTech.cs = declCS("CS_GenerateSpecularBRDF");
generateSpecularBRDFTech.flags = (Flags)0;
}

auto & generateIrradianceCubemapTech = declTechnique("GenerateIrradianceCubemap");
{
generateIrradianceCubemapTech.cs = declCS("CS_GenerateIrradianceCubemap");
}

auto & generateSpecularReflectionCubemapTech = declTechnique("GenerateSpecularReflectionCubemap");
{
generateSpecularReflectionCubemapTech.cs = declCS("CS_GenerateSpecularReflectionCubemap");
}
}
};
Expand Down
16 changes: 10 additions & 6 deletions data/Shaders/lighting/PrecomputeIBL.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#define PRECOMPUTE_IBL_THREADGROUP_SIZE_X 16
#define PRECOMPUTE_IBL_THREADGROUP_SIZE_Y 16
#define PRECOMPUTE_IBL_THREADGROUP_SIZE_Z 1

#include "system/constants.hlsli"
#include "system/packing.hlsli"
Expand All @@ -11,17 +12,20 @@ struct PrecomputeIBLConstants
#ifdef __cplusplus
PrecomputeIBLConstants()
{
textureUAV = 0x0;
src_dst = 0x0;
}
#endif

void setSpecularBRDF (uint _rwtex2D) { textureUAV = packUint16low(_rwtex2D, _rwtex2D); }
uint getSpecularBRDF () { return unpackUint16low(textureUAV); }
void setSource (uint _tex2D) { src_dst = packUint16low(src_dst, _tex2D); }
uint getSource () { return unpackUint16low(src_dst); }

void setSize (uint2 _size) { size = _size.x | (_size.y << 16); }
uint2 getSize () { return uint2(size & 0xFFFF, size >> 16); }
void setDestination (uint _rwtex2D) { src_dst = packUint16high(src_dst, _rwtex2D); }
uint getDestination () { return unpackUint16high(src_dst); }

uint textureUAV;
void setDestinationSize (uint2 _size) { size = _size.x | (_size.y << 16); }
uint2 getDestinationSize () { return uint2(size & 0xFFFF, size >> 16); }

uint src_dst;
uint size;
};

Expand Down
28 changes: 15 additions & 13 deletions data/Shaders/system/bindless.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,25 @@
#endif

// Read-only textures
DECL_DESCRIPTOR_RANGE_RO(Texture1D, g_Texture1D, BINDLESS_TEXTURE_BINDING_1D, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(Texture2D, g_Texture2D, BINDLESS_TEXTURE_BINDING_2D, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(TextureCube, g_TextureCube, BINDLESS_TEXTURE_BINDING_CUBE, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(Texture2DMS<float4>, g_Texture2DMS, BINDLESS_TEXTURE_BINDING_2DMS, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(Texture2D<uint2>, g_Texture2D_UInt2, BINDLESS_TEXTURE_BINDING_2D_UINT2, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(Texture3D, g_Texture3D, BINDLESS_TEXTURE_BINDING_3D, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(Texture1D, g_Texture1D, BINDLESS_TEXTURE_BINDING_1D, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(Texture2D, g_Texture2D, BINDLESS_TEXTURE_BINDING_2D, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(TextureCube, g_TextureCube, BINDLESS_TEXTURE_BINDING_CUBE, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(Texture2DMS<float4>, g_Texture2DMS, BINDLESS_TEXTURE_BINDING_2DMS, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(Texture2D<uint2>, g_Texture2D_UInt2, BINDLESS_TEXTURE_BINDING_2D_UINT2, BINDLESS_TEXTURE_START);
DECL_DESCRIPTOR_RANGE_RO(Texture3D, g_Texture3D, BINDLESS_TEXTURE_BINDING_3D, BINDLESS_TEXTURE_START);

// Read-only buffers
DECL_DESCRIPTOR_RANGE_RO(ByteAddressBuffer, g_Buffer, BINDLESS_BUFFER_BINDING, BINDLESS_BUFFER_START);
DECL_DESCRIPTOR_RANGE_RO(ByteAddressBuffer, g_Buffer, BINDLESS_BUFFER_BINDING, BINDLESS_BUFFER_START);

// Read-Only buffers
DECL_DESCRIPTOR_RANGE_RW(RWTexture1D<float4>, g_RWTexture1D, BINDLESS_RWTEXTURE_BINDING_1D, BINDLESS_RWTEXTURE_START);
DECL_DESCRIPTOR_RANGE_RW(RWTexture2D<float4>, g_RWTexture2DTable, BINDLESS_RWTEXTURE_BINDING_2D, BINDLESS_RWTEXTURE_START);
DECL_DESCRIPTOR_RANGE_RW(RWTexture2D<float2>, g_RWTexture2D_float2, BINDLESS_RWTEXTURE_BINDING_2D, BINDLESS_RWTEXTURE_START);
DECL_DESCRIPTOR_RANGE_RW(RWTexture3D<float4>, g_RWTexture3D, BINDLESS_RWTEXTURE_BINDING_3D, BINDLESS_RWTEXTURE_START);
DECL_DESCRIPTOR_RANGE_RW(RWTexture1D<float4>, g_RWTexture1D, BINDLESS_RWTEXTURE_BINDING_1D, BINDLESS_RWTEXTURE_START);
DECL_DESCRIPTOR_RANGE_RW(RWTexture2D<float4>, g_RWTexture2D, BINDLESS_RWTEXTURE_BINDING_2D, BINDLESS_RWTEXTURE_START);
DECL_DESCRIPTOR_RANGE_RW(RWTexture2D<float2>, g_RWTexture2D_float2, BINDLESS_RWTEXTURE_BINDING_2D_FLOAT2, BINDLESS_RWTEXTURE_START);
DECL_DESCRIPTOR_RANGE_RW(RWTexture2DArray<float4>, g_RWTexture2DArray, BINDLESS_RWTEXTURE_BINDING_2D_ARRAY, BINDLESS_RWTEXTURE_START);
DECL_DESCRIPTOR_RANGE_RW(RWTexture3D<float4>, g_RWTexture3D, BINDLESS_RWTEXTURE_BINDING_3D, BINDLESS_RWTEXTURE_START);

// Read-Write buffers
DECL_DESCRIPTOR_RANGE_RW(RWByteAddressBuffer, g_RWBuffer, BINDLESS_RWBUFFER_BINDING, BINDLESS_RWBUFFER_START);
DECL_DESCRIPTOR_RANGE_RW(RWByteAddressBuffer, g_RWBuffer, BINDLESS_RWBUFFER_BINDING, BINDLESS_RWBUFFER_START);

// TLAS is a different descriptor type on Vulkan, hence the separate bindless table
// The table cannot be declared in shader (even if unused) when RayTracing is not allowed (not supported or Renderdoc capture) otherwise Vulkan will complain about SPIR-V Extension being used
Expand All @@ -55,8 +56,9 @@ DECL_DESCRIPTOR_RANGE_RO(RaytracingAccelerationStructure, g_TLAS, BINDLESS_TLAS_
#define getBuffer(_handle) (g_Buffer[_handle - BINDLESS_BUFFER_START])

#define getRWTexture1D(_handle) (g_RWTexture1D[_handle - BINDLESS_RWTEXTURE_START])
#define getRWTexture2D(_handle) (g_RWTexture2DTable[_handle - BINDLESS_RWTEXTURE_START])
#define getRWTexture2D(_handle) (g_RWTexture2D[_handle - BINDLESS_RWTEXTURE_START])
#define getRWTexture2D_float2(_handle) (g_RWTexture2D_float2[_handle - BINDLESS_RWTEXTURE_START])
#define getRWTexture2DArray(_handle) (g_RWTexture2DArray[_handle - BINDLESS_RWTEXTURE_START])
#define getRWTexture3D(_handle) (g_RWTexture3D[_handle - BINDLESS_RWTEXTURE_START])

#define getRWBuffer(_handle) (g_RWBuffer[_handle - BINDLESS_RWBUFFER_START])
Expand Down
5 changes: 4 additions & 1 deletion data/Shaders/system/table.hlsli
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ vg_enum_class(ReservedSlot, uint,

#define BINDLESS_RWTEXTURE_BINDING_1D 210
#define BINDLESS_RWTEXTURE_BINDING_2D 220
#define BINDLESS_RWTEXTURE_BINDING_2D_FLOAT2 221
#define BINDLESS_RWTEXTURE_BINDING_2D_ARRAY 222
#define BINDLESS_RWTEXTURE_BINDING_3D 230

#elif defined(VG_VULKAN)
Expand All @@ -116,7 +118,8 @@ vg_enum_class(ReservedSlot, uint,

#define BINDLESS_RWTEXTURE_BINDING_1D 2 // <=> BINDLESS_RWTEXTURE_BINDING
#define BINDLESS_RWTEXTURE_BINDING_2D 2
#define BINDLESS_RWTEXTURE_BINDING_2D_UINT2 2
#define BINDLESS_RWTEXTURE_BINDING_2D_FLOAT2 2
#define BINDLESS_RWTEXTURE_BINDING_2D_ARRAY 2
#define BINDLESS_RWTEXTURE_BINDING_3D 2
#endif

Expand Down
Binary file added doc/img/VGF_Boy_BotPP.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/img/newversion.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
30 changes: 16 additions & 14 deletions src/gfx/BindlessTable/BindlessTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,28 +23,30 @@ namespace vg::gfx
m_tableDesc.setShaderStageFlags(ShaderStageFlags::All);

#ifdef VG_VULKAN
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
#else
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_1D, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_2D, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_CUBE, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_2DMS, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_2D_UINT2, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_3D, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_1D, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_2D, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_CUBE, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_2DMS, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_2D_UINT2, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
m_tableDesc.addTextures(BINDLESS_TEXTURE_BINDING_3D, BINDLESS_TEXTURE_START, BINDLESS_TEXTURE_COUNT);
#endif

m_tableDesc.addBuffers(BINDLESS_BUFFER_BINDING, BINDLESS_BUFFER_START, BINDLESS_BUFFER_COUNT);
m_tableDesc.addBuffers(BINDLESS_BUFFER_BINDING, BINDLESS_BUFFER_START, BINDLESS_BUFFER_COUNT);

#ifdef VG_VULKAN
m_tableDesc.addRWTextures(BINDLESS_RWTEXTURE_BINDING, BINDLESS_RWTEXTURE_START, BINDLESS_RWTEXTURE_COUNT);
m_tableDesc.addRWTextures(BINDLESS_RWTEXTURE_BINDING, BINDLESS_RWTEXTURE_START, BINDLESS_RWTEXTURE_COUNT);
#else
m_tableDesc.addRWTextures(BINDLESS_RWTEXTURE_BINDING_1D, BINDLESS_RWTEXTURE_START, BINDLESS_RWTEXTURE_COUNT);
m_tableDesc.addRWTextures(BINDLESS_RWTEXTURE_BINDING_2D, BINDLESS_RWTEXTURE_START, BINDLESS_RWTEXTURE_COUNT);
m_tableDesc.addRWTextures(BINDLESS_RWTEXTURE_BINDING_3D, BINDLESS_RWTEXTURE_START, BINDLESS_RWTEXTURE_COUNT);
m_tableDesc.addRWTextures(BINDLESS_RWTEXTURE_BINDING_1D, BINDLESS_RWTEXTURE_START, BINDLESS_RWTEXTURE_COUNT);
m_tableDesc.addRWTextures(BINDLESS_RWTEXTURE_BINDING_2D, BINDLESS_RWTEXTURE_START, BINDLESS_RWTEXTURE_COUNT);
m_tableDesc.addRWTextures(BINDLESS_RWTEXTURE_BINDING_2D_FLOAT2, BINDLESS_RWTEXTURE_START, BINDLESS_RWTEXTURE_COUNT);
m_tableDesc.addRWTextures(BINDLESS_RWTEXTURE_BINDING_2D_ARRAY, BINDLESS_RWTEXTURE_START, BINDLESS_RWTEXTURE_COUNT);
m_tableDesc.addRWTextures(BINDLESS_RWTEXTURE_BINDING_3D, BINDLESS_RWTEXTURE_START, BINDLESS_RWTEXTURE_COUNT);
#endif

m_tableDesc.addRWBuffers(BINDLESS_RWBUFFER_BINDING, BINDLESS_RWBUFFER_START, BINDLESS_RWBUFFER_COUNT);
m_tableDesc.addTLAS(BINDLESS_TLAS_BINDING, BINDLESS_TLAS_START, BINDLESS_TLAS_COUNT);
m_tableDesc.addRWBuffers(BINDLESS_RWBUFFER_BINDING, BINDLESS_RWBUFFER_START, BINDLESS_RWBUFFER_COUNT);
m_tableDesc.addTLAS(BINDLESS_TLAS_BINDING, BINDLESS_TLAS_START, BINDLESS_TLAS_COUNT);
}

//--------------------------------------------------------------------------------------
Expand Down
5 changes: 2 additions & 3 deletions src/gfx/Resource/Texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ namespace vg::gfx
VG_INLINE const gfx::BindlessTextureHandle getTextureHandle () const;
VG_INLINE const gfx::BindlessTextureHandle getDepthTextureHandle () const;
VG_INLINE const gfx::BindlessTextureHandle getStencilTextureHandle () const;
VG_INLINE const gfx::BindlessRWTextureHandle getRWTextureHandle () const;
VG_INLINE const gfx::BindlessRWTextureHandle getRWTextureHandle (uint _mipLevel = 0) const;

static core::u32 getPixelFormatSize (PixelFormat _format);
VG_INLINE static bool isDepthStencilFormat (PixelFormat _format);
Expand All @@ -50,8 +50,7 @@ namespace vg::gfx
};
};

// [slice][mip]
core::vector<core::vector<gfx::BindlessRWTextureHandle>> m_rwTextureHandles;
core::vector<gfx::BindlessRWTextureHandle> m_rwTextureMipHandles;
};
}
}
Expand Down
13 changes: 5 additions & 8 deletions src/gfx/Resource/Texture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,11 @@ namespace vg::gfx
bindlessTable->freeBindlessTextureHandle(m_textureHandle);
}

for (uint s = 0; s < m_rwTextureHandles.size(); ++s)
for (uint m = 0; m < m_rwTextureMipHandles.size(); ++m)
{
for (uint m = 0; m < m_rwTextureHandles[s].size(); ++m)
{
auto & rwTextureHandle = m_rwTextureHandles[s][m];
if (rwTextureHandle.isValid())
bindlessTable->freeBindlessRWTextureHandle(rwTextureHandle);
}
}
auto & rwTextureHandle = m_rwTextureMipHandles[m];
if (rwTextureHandle.isValid())
bindlessTable->freeBindlessRWTextureHandle(rwTextureHandle);
}
}
}
5 changes: 3 additions & 2 deletions src/gfx/Resource/Texture.inl
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@ namespace vg::gfx
}

//--------------------------------------------------------------------------------------
VG_INLINE const gfx::BindlessRWTextureHandle Texture::getRWTextureHandle() const
VG_INLINE const gfx::BindlessRWTextureHandle Texture::getRWTextureHandle(uint _mipLevel) const
{
const auto & rwTextureHandle = m_rwTextureHandles[0][0];
VG_ASSERT(_mipLevel < m_rwTextureMipHandles.size());
const auto & rwTextureHandle = m_rwTextureMipHandles[_mipLevel];
VG_ASSERT(rwTextureHandle.isValid());
return rwTextureHandle;
}
Expand Down
Loading

0 comments on commit 6f7fea8

Please sign in to comment.