diff --git a/extensions/pl_debug_ext.c b/extensions/pl_debug_ext.c index b218e93..26a602b 100644 --- a/extensions/pl_debug_ext.c +++ b/extensions/pl_debug_ext.c @@ -20,7 +20,7 @@ Index of this file: // core #include #include "pl.h" -#include "pl_ds.h" + #include "pl_debug_ext.h" #define PL_MATH_INCLUDE_FUNCTIONS #include "pl_math.h" @@ -103,6 +103,8 @@ static plDebugContext* gptDebugCtx = NULL; #endif +#include "pl_ds.h" + //----------------------------------------------------------------------------- // [SECTION] internal api //----------------------------------------------------------------------------- diff --git a/extensions/pl_draw_backend_ext.c b/extensions/pl_draw_backend_ext.c index 8be97b8..4780592 100644 --- a/extensions/pl_draw_backend_ext.c +++ b/extensions/pl_draw_backend_ext.c @@ -20,7 +20,6 @@ Index of this file: #include #include "pl.h" #include "pl_memory.h" -#include "pl_ds.h" #define PL_MATH_INCLUDE_FUNCTIONS #include "pl_math.h" @@ -33,8 +32,21 @@ Index of this file: #ifdef PL_UNITY_BUILD #include "pl_unity_ext.inc" +#else + static const plMemoryI* gptMemory = NULL; + #define PL_ALLOC(x) gptMemory->tracked_realloc(NULL, (x), __FILE__, __LINE__) + #define PL_REALLOC(x, y) gptMemory->tracked_realloc((x), (y), __FILE__, __LINE__) + #define PL_FREE(x) gptMemory->tracked_realloc((x), 0, __FILE__, __LINE__) + + #ifndef PL_DS_ALLOC + #define PL_DS_ALLOC(x) gptMemory->tracked_realloc(NULL, (x), __FILE__, __LINE__) + #define PL_DS_ALLOC_INDIRECT(x, FILE, LINE) gptMemory->tracked_realloc(NULL, (x), FILE, LINE) + #define PL_DS_FREE(x) gptMemory->tracked_realloc((x), 0, __FILE__, __LINE__) + #endif #endif +#include "pl_ds.h" + //----------------------------------------------------------------------------- // [SECTION] internal structs //----------------------------------------------------------------------------- @@ -85,18 +97,6 @@ typedef struct _plDrawBackendContext static plDrawBackendContext* gptDrawBackendCtx = NULL; -#ifndef PL_UNITY_BUILD - static const plMemoryI* gptMemory = NULL; - #define PL_ALLOC(x) gptMemory->tracked_realloc(NULL, (x), __FILE__, __LINE__) - #define PL_REALLOC(x, y) gptMemory->tracked_realloc((x), (y), __FILE__, __LINE__) - #define PL_FREE(x) gptMemory->tracked_realloc((x), 0, __FILE__, __LINE__) - - static const plGraphicsI* gptGfx = NULL; - static const plStatsI* gptStats = NULL; - static const plDrawI* gptDraw = NULL; - static const plShaderI* gptShader = NULL; -#endif - //----------------------------------------------------------------------------- // [SECTION] internal api //----------------------------------------------------------------------------- diff --git a/extensions/pl_draw_ext.c b/extensions/pl_draw_ext.c index 94da87a..9d60162 100644 --- a/extensions/pl_draw_ext.c +++ b/extensions/pl_draw_ext.c @@ -23,7 +23,6 @@ Index of this file: #include "pl.h" #define PL_MATH_INCLUDE_FUNCTIONS #include "pl_draw_ext.h" -#include "pl_ds.h" #include "pl_memory.h" #include "pl_string.h" @@ -140,6 +139,8 @@ static unsigned char* ptrDOut_ = NULL; static const plFileI* gptFile = NULL; #endif +#include "pl_ds.h" + //----------------------------------------------------------------------------- // [SECTION] internal api //----------------------------------------------------------------------------- diff --git a/extensions/pl_ecs_ext.c b/extensions/pl_ecs_ext.c index 0588844..4d0ffa4 100644 --- a/extensions/pl_ecs_ext.c +++ b/extensions/pl_ecs_ext.c @@ -21,7 +21,6 @@ Index of this file: #define PL_MATH_INCLUDE_FUNCTIONS #include "pl.h" #include "pl_ecs_ext.h" -#include "pl_ds.h" #include "pl_math.h" // extensions @@ -51,6 +50,8 @@ Index of this file: static const plLogI* gptLog = NULL; #endif +#include "pl_ds.h" + //----------------------------------------------------------------------------- // [SECTION] structs //----------------------------------------------------------------------------- @@ -114,6 +115,9 @@ static void pl_run_hierarchy_update_system (plComponentLibrary* ptLibrar static void pl_run_animation_update_system (plComponentLibrary* ptLibrary, float fDeltaTime); static void pl_run_inverse_kinematics_update_system(plComponentLibrary* ptLibrary); static void pl_run_script_update_system (plComponentLibrary* ptLibrary); +static void pl_run_camera_update_system (plComponentLibrary* ptLibrary); +static void pl_run_light_update_system (plComponentLibrary* ptLibrary); +static void pl_run_probe_update_system (plComponentLibrary* ptLibrary); // misc. static void pl_calculate_normals (plMeshComponent* atMeshes, uint32_t uComponentCount); @@ -590,7 +594,7 @@ pl_ecs_add_component(plComponentLibrary* ptLibrary, plComponentType tType, plEnt ptManager->pComponents = sbComponents; sbComponents[uComponentIndex] = (plMaterialComponent){ .tBlendMode = PL_BLEND_MODE_OPAQUE, - .tFlags = PL_MATERIAL_FLAG_NONE, + .tFlags = PL_MATERIAL_FLAG_CAST_SHADOW | PL_MATERIAL_FLAG_CAST_RECEIVE_SHADOW, .tShaderType = PL_SHADER_TYPE_PBR, .tBaseColor = {1.0f, 1.0f, 1.0f, 1.0f}, .tEmissiveColor = {0.0f, 0.0f, 0.0f, 0.0f}, @@ -724,7 +728,8 @@ pl_ecs_add_component(plComponentLibrary* ptLibrary, plComponentType tType, plEnt ptManager->pComponents = sbComponents; sbComponents[uComponentIndex] = (plEnvironmentProbeComponent){ .fRange = 10.0f, - .uResolution = 128 + .uResolution = 128, + .tFlags = PL_ENVIRONMENT_PROBE_FLAGS_DIRTY }; return &sbComponents[uComponentIndex]; } @@ -1220,6 +1225,74 @@ pl_run_script_update_system(plComponentLibrary* ptLibrary) pl_end_cpu_sample(gptProfile, 0); } +static void +pl_run_camera_update_system(plComponentLibrary* ptLibrary) +{ + pl_begin_cpu_sample(gptProfile, 0, __FUNCTION__); + + plCameraComponent* sbtComponents = ptLibrary->tCameraComponentManager.pComponents; + + const uint32_t uComponentCount = pl_sb_size(sbtComponents); + for(uint32_t i = 0; i < uComponentCount; i++) + { + plEntity tEntity = ptLibrary->tCameraComponentManager.sbtEntities[i]; + if(pl_ecs_has_entity(&ptLibrary->tTransformComponentManager, tEntity)) + { + plCameraComponent* ptCamera = &sbtComponents[i]; + plTransformComponent* ptTransform = pl_ecs_get_component(ptLibrary, PL_COMPONENT_TYPE_TRANSFORM, tEntity); + ptCamera->tPos = ptTransform->tWorld.col[3].xyz; + pl_camera_update(ptCamera); + } + } + pl_end_cpu_sample(gptProfile, 0); +} + +static void +pl_run_light_update_system(plComponentLibrary* ptLibrary) +{ + pl_begin_cpu_sample(gptProfile, 0, __FUNCTION__); + + plLightComponent* sbtComponents = ptLibrary->tLightComponentManager.pComponents; + + const uint32_t uComponentCount = pl_sb_size(sbtComponents); + for(uint32_t i = 0; i < uComponentCount; i++) + { + plEntity tEntity = ptLibrary->tLightComponentManager.sbtEntities[i]; + if(pl_ecs_has_entity(&ptLibrary->tTransformComponentManager, tEntity)) + { + plLightComponent* ptLight = &sbtComponents[i]; + plTransformComponent* ptTransform = pl_ecs_get_component(ptLibrary, PL_COMPONENT_TYPE_TRANSFORM, tEntity); + ptLight->tPosition = ptTransform->tWorld.col[3].xyz; + + // TODO: direction + } + } + pl_end_cpu_sample(gptProfile, 0); +} + +static void +pl_run_probe_update_system(plComponentLibrary* ptLibrary) +{ + pl_begin_cpu_sample(gptProfile, 0, __FUNCTION__); + + plEnvironmentProbeComponent* sbtComponents = ptLibrary->tEnvironmentProbeCompManager.pComponents; + + const uint32_t uComponentCount = pl_sb_size(sbtComponents); + for(uint32_t i = 0; i < uComponentCount; i++) + { + plEntity tEntity = ptLibrary->tEnvironmentProbeCompManager.sbtEntities[i]; + if(pl_ecs_has_entity(&ptLibrary->tTransformComponentManager, tEntity)) + { + plEnvironmentProbeComponent* ptProbe = &sbtComponents[i]; + plTransformComponent* ptTransform = pl_ecs_get_component(ptLibrary, PL_COMPONENT_TYPE_TRANSFORM, tEntity); + ptProbe->tPosition = ptTransform->tWorld.col[3].xyz; + + // TODO: direction + } + } + pl_end_cpu_sample(gptProfile, 0); +} + static void pl_run_animation_update_system(plComponentLibrary* ptLibrary, float fDeltaTime) { @@ -1851,7 +1924,10 @@ pl_load_ecs_ext(plApiRegistryI* ptApiRegistry, bool bReload) .run_skin_update_system = pl_run_skin_update_system, .run_animation_update_system = pl_run_animation_update_system, .run_inverse_kinematics_update_system = pl_run_inverse_kinematics_update_system, - .run_script_update_system = pl_run_script_update_system + .run_script_update_system = pl_run_script_update_system, + .run_camera_update_system = pl_run_camera_update_system, + .run_light_update_system = pl_run_light_update_system, + .run_environment_probe_update_system = pl_run_probe_update_system }; pl_set_api(ptApiRegistry, plEcsI, &tApi0); diff --git a/extensions/pl_ecs_ext.h b/extensions/pl_ecs_ext.h index 6b6cdd2..c5f312d 100644 --- a/extensions/pl_ecs_ext.h +++ b/extensions/pl_ecs_ext.h @@ -157,6 +157,9 @@ typedef struct _plEcsI void (*run_animation_update_system) (plComponentLibrary*, float fDeltaTime); void (*run_inverse_kinematics_update_system)(plComponentLibrary*); void (*run_script_update_system) (plComponentLibrary*); + void (*run_camera_update_system) (plComponentLibrary*); + void (*run_light_update_system) (plComponentLibrary*); + void (*run_environment_probe_update_system) (plComponentLibrary*); } plEcsI; typedef struct _plCameraI @@ -218,9 +221,11 @@ enum _plShaderType enum _plMaterialFlags { - PL_MATERIAL_FLAG_NONE = 0, - PL_MATERIAL_FLAG_DOUBLE_SIDED = 1 << 0, - PL_MATERIAL_FLAG_OUTLINE = 1 << 1, + PL_MATERIAL_FLAG_NONE = 0, + PL_MATERIAL_FLAG_DOUBLE_SIDED = 1 << 0, + PL_MATERIAL_FLAG_OUTLINE = 1 << 1, + PL_MATERIAL_FLAG_CAST_SHADOW = 1 << 2, + PL_MATERIAL_FLAG_CAST_RECEIVE_SHADOW = 1 << 3 }; enum _plBlendMode diff --git a/extensions/pl_gpu_allocators_ext.c b/extensions/pl_gpu_allocators_ext.c index 5482e80..84c7a47 100644 --- a/extensions/pl_gpu_allocators_ext.c +++ b/extensions/pl_gpu_allocators_ext.c @@ -20,7 +20,6 @@ Index of this file: #include "pl_graphics_ext.h" #define PL_MATH_INCLUDE_FUNCTIONS #include "pl_math.h" -#include "pl_ds.h" #ifdef PL_UNITY_BUILD #include "pl_unity_ext.inc" @@ -40,6 +39,8 @@ Index of this file: static const plDataRegistryI* gptDataRegistry = NULL; #endif +#include "pl_ds.h" + //----------------------------------------------------------------------------- // [SECTION] defines //----------------------------------------------------------------------------- diff --git a/extensions/pl_graphics_ext.c b/extensions/pl_graphics_ext.c index a1cc9ac..d6fd803 100644 --- a/extensions/pl_graphics_ext.c +++ b/extensions/pl_graphics_ext.c @@ -716,6 +716,7 @@ pl_load_graphics_ext(plApiRegistryI* ptApiRegistry, bool bReload) .present = pl_present, .copy_buffer_to_texture = pl_copy_buffer_to_texture, .copy_texture_to_buffer = pl_copy_texture_to_buffer, + .copy_texture = pl_copy_texture, .generate_mipmaps = pl_generate_mipmaps, .copy_buffer = pl_copy_buffer, .signal_semaphore = pl_signal_semaphore, diff --git a/extensions/pl_graphics_ext.h b/extensions/pl_graphics_ext.h index 4e838c5..5ce8561 100644 --- a/extensions/pl_graphics_ext.h +++ b/extensions/pl_graphics_ext.h @@ -48,7 +48,7 @@ Index of this file: // [SECTION] apis //----------------------------------------------------------------------------- -#define plGraphicsI_version (plVersion){1, 2, 0} +#define plGraphicsI_version (plVersion){1, 2, 1} //----------------------------------------------------------------------------- // [SECTION] includes @@ -95,6 +95,7 @@ typedef struct _plRenderEncoder plRenderEncoder; // opaque type for typedef struct _plComputeEncoder plComputeEncoder; // opaque type for command buffer encoder for compute ops typedef struct _plBlitEncoder plBlitEncoder; // opaque type for command buffer encoder for blit ops typedef struct _plBufferImageCopy plBufferImageCopy; // used for copying between buffers & textures with blit encoder +typedef struct _plImageCopy plImageCopy; // used for copying between textures with blit encoder typedef struct _plPassTextureResource plPassTextureResource; typedef struct _plPassBufferResource plPassBufferResource; typedef struct _plPassResources plPassResources; @@ -299,6 +300,7 @@ typedef struct _plGraphicsI void (*set_texture_usage) (plBlitEncoder*, plTextureHandle, plTextureUsage tNewUsage, plTextureUsage tOldUsage); void (*copy_buffer_to_texture) (plBlitEncoder*, plBufferHandle, plTextureHandle, uint32_t regionCount, const plBufferImageCopy*); void (*copy_texture_to_buffer) (plBlitEncoder*, plTextureHandle, plBufferHandle, uint32_t regionCount, const plBufferImageCopy*); + void (*copy_texture) (plBlitEncoder*, plTextureHandle, plTextureHandle, uint32_t regionCount, const plImageCopy*); void (*generate_mipmaps) (plBlitEncoder*, plTextureHandle); void (*copy_buffer) (plBlitEncoder*, plBufferHandle source, plBufferHandle destination, uint32_t sourceOffset, uint32_t destinationOffset, size_t); @@ -556,8 +558,10 @@ typedef struct _plBindGroupUpdateBufferData { plBufferHandle tBuffer; uint32_t uSlot; - size_t szOffset; size_t szBufferRange; + + // [INTERNAL] + size_t _szOffset; // vulkan only :( } plBindGroupUpdateBufferData; typedef struct _plBindGroupUpdateData @@ -630,6 +634,7 @@ typedef struct _plBindGroup // [INTERNAL] uint16_t _uGeneration; + plTextureHandle* _sbtTextures; } plBindGroup; //-------------------------------shaders--------------------------------------- @@ -885,6 +890,30 @@ typedef struct _plBufferImageCopy plTextureUsage tCurrentImageUsage; } plBufferImageCopy; +typedef struct _plImageCopy +{ + // source info + int iSourceOffsetX; + int iSourceOffsetY; + int iSourceOffsetZ; + uint32_t uSourceExtentX; + uint32_t uSourceExtentY; + uint32_t uSourceExtentZ; + uint32_t uSourceMipLevel; + uint32_t uSourceBaseArrayLayer; + uint32_t uSourceLayerCount; + plTextureUsage tSourceImageUsage; + + // destination offset + int iDestinationOffsetX; + int iDestinationOffsetY; + int iDestinationOffsetZ; + uint32_t uDestinationMipLevel; + uint32_t uDestinationBaseArrayLayer; + uint32_t uDestinationLayerCount; + plTextureUsage tDestinationImageUsage; +} plImageCopy; + typedef struct _plDrawArea { plRenderViewport atViewports[PL_MAX_VIEWPORTS]; diff --git a/extensions/pl_graphics_internal.h b/extensions/pl_graphics_internal.h index b3fdb96..c916351 100644 --- a/extensions/pl_graphics_internal.h +++ b/extensions/pl_graphics_internal.h @@ -2,7 +2,6 @@ #define PL_GRAPHICS_INTERNAL_EXT_H #include "pl.h" -#include "pl_ds.h" #include "pl_log_ext.h" #include "pl_threads_ext.h" #include "pl_graphics_ext.h" @@ -34,6 +33,8 @@ static plIO* gptIO = NULL; #endif +#include "pl_ds.h" + //----------------------------------------------------------------------------- // [SECTION] global data //----------------------------------------------------------------------------- diff --git a/extensions/pl_graphics_metal.m b/extensions/pl_graphics_metal.m index 807cb37..1bb6e2e 100644 --- a/extensions/pl_graphics_metal.m +++ b/extensions/pl_graphics_metal.m @@ -148,7 +148,6 @@ plSamplerHandle atSamplerBindings[PL_MAX_TEXTURES_PER_BIND_GROUP]; uint64_t uHeapUsageMask; uint32_t uOffset; - plTextureHandle* sbtTextures; } plMetalBindGroup; typedef struct _plMetalShader @@ -549,6 +548,44 @@ } } +void +pl_copy_texture(plBlitEncoder* ptEncoder, plTextureHandle tSrcHandle, plTextureHandle tDstHandle, uint32_t uRegionCount, const plImageCopy* ptRegions) +{ + plCommandBuffer* ptCmdBuffer = ptEncoder->ptCommandBuffer; + plDevice* ptDevice = ptCmdBuffer->ptDevice; + const plMetalTexture* ptMetalSrcTexture = &ptDevice->sbtTexturesHot[tSrcHandle.uIndex]; + const plMetalTexture* ptMetalDstTexture = &ptDevice->sbtTexturesHot[tDstHandle.uIndex]; + + for(uint32_t i = 0; i < uRegionCount; i++) + { + + MTLOrigin tSrcOrigin; + tSrcOrigin.x = ptRegions[i].iSourceOffsetX; + tSrcOrigin.y = ptRegions[i].iSourceOffsetY; + tSrcOrigin.z = ptRegions[i].iSourceOffsetZ; + + MTLOrigin tDestOrigin; + tDestOrigin.x = ptRegions[i].iDestinationOffsetX; + tDestOrigin.y = ptRegions[i].iDestinationOffsetY; + tDestOrigin.z = ptRegions[i].iDestinationOffsetZ; + + MTLSize tSourceSize; + tSourceSize.width = ptRegions[i].uSourceExtentX; + tSourceSize.height = ptRegions[i].uSourceExtentY; + tSourceSize.depth = ptRegions[i].uSourceExtentZ; + + [ptEncoder->tEncoder copyFromTexture:ptMetalSrcTexture->tTexture + sourceSlice:ptRegions[i].uSourceBaseArrayLayer + sourceLevel:ptRegions[i].uSourceMipLevel + sourceOrigin:tSrcOrigin + sourceSize:tSourceSize + toTexture:ptMetalDstTexture->tTexture + destinationSlice:ptRegions[i].uDestinationBaseArrayLayer + destinationLevel:ptRegions[i].uDestinationMipLevel + destinationOrigin:tDestOrigin]; + } +} + static void pl_copy_texture_to_buffer(plBlitEncoder* ptEncoder, plTextureHandle tTextureHandle, plBufferHandle tBufferHandle, uint32_t uRegionCount, const plBufferImageCopy* ptRegions) { @@ -900,6 +937,8 @@ plBindGroup* ptBindGroup = pl__get_bind_group(ptDevice, tHandle); const char* pcDescriptorStart = ptMetalBindGroup->tShaderArgumentBuffer.contents; + pl_sb_reset(ptBindGroup->_sbtTextures); + uint64_t* pulDescriptorStart = (uint64_t*)&pcDescriptorStart[ptMetalBindGroup->uOffset]; for(uint32_t i = 0; i < ptData->uBufferCount; i++) @@ -908,7 +947,6 @@ plMetalBuffer* ptMetalBuffer = &ptDevice->sbtBuffersHot[ptUpdate->tBuffer.uIndex]; uint64_t* ppfDestination = &pulDescriptorStart[ptUpdate->uSlot]; *ppfDestination = ptMetalBuffer->tBuffer.gpuAddress; - ptMetalBindGroup->uHeapUsageMask |= (1ULL << ptMetalBuffer->uHeap); } @@ -923,7 +961,7 @@ int iCommonBits = ptTexture->tDesc.tUsage & (PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT | PL_TEXTURE_USAGE_COLOR_ATTACHMENT |PL_TEXTURE_USAGE_INPUT_ATTACHMENT | PL_TEXTURE_USAGE_STORAGE); if(iCommonBits) { - pl_sb_push(ptMetalBindGroup->sbtTextures, ptUpdate->tTexture); + pl_sb_push(ptBindGroup->_sbtTextures, ptUpdate->tTexture); } ptMetalBindGroup->uHeapUsageMask |= (1ULL << ptMetalTexture->uHeap); @@ -2168,9 +2206,10 @@ for(uint32_t i = 0; i < uCount; i++) { - plMetalBindGroup* ptBindGroup = &ptDevice->sbtBindGroupsHot[atBindGroups[i].uIndex]; + plBindGroup* ptBindGroup = &ptDevice->sbtBindGroupsCold[atBindGroups[i].uIndex]; + plMetalBindGroup* ptMetalBindGroup = &ptDevice->sbtBindGroupsHot[atBindGroups[i].uIndex]; - ptEncoder->uHeapUsageMask |= ptBindGroup->uHeapUsageMask; + ptEncoder->uHeapUsageMask |= ptMetalBindGroup->uHeapUsageMask; for(uint64_t k = 0; k < 64; k++) { @@ -2180,10 +2219,10 @@ } } - const uint32_t uTextureCount = pl_sb_size(ptBindGroup->sbtTextures); + const uint32_t uTextureCount = pl_sb_size(ptBindGroup->_sbtTextures); for(uint32_t k = 0; k < uTextureCount; k++) { - const plTextureHandle tTextureHandle = ptBindGroup->sbtTextures[k]; + const plTextureHandle tTextureHandle = ptBindGroup->_sbtTextures[k]; plTexture* ptTexture = pl__get_texture(ptDevice, tTextureHandle); if(ptTexture->tDesc.tUsage & PL_TEXTURE_USAGE_STORAGE) { @@ -2195,8 +2234,8 @@ } } - [ptEncoder->tEncoder setBuffer:ptBindGroup->tShaderArgumentBuffer - offset:ptBindGroup->uOffset + [ptEncoder->tEncoder setBuffer:ptMetalBindGroup->tShaderArgumentBuffer + offset:ptMetalBindGroup->uOffset atIndex:uFirst + i]; } } @@ -2216,9 +2255,10 @@ for(uint32_t i = 0; i < uCount; i++) { - plMetalBindGroup* ptBindGroup = &ptDevice->sbtBindGroupsHot[atBindGroups[i].uIndex]; + plBindGroup* ptBindGroup = &ptDevice->sbtBindGroupsCold[atBindGroups[i].uIndex]; + plMetalBindGroup* ptMetalBindGroup = &ptDevice->sbtBindGroupsHot[atBindGroups[i].uIndex]; - ptEncoder->uHeapUsageMask |= ptBindGroup->uHeapUsageMask; + ptEncoder->uHeapUsageMask |= ptMetalBindGroup->uHeapUsageMask; for(uint64_t k = 0; k < 64; k++) { @@ -2228,16 +2268,16 @@ } } - const uint32_t uTextureCount = pl_sb_size(ptBindGroup->sbtTextures); + const uint32_t uTextureCount = pl_sb_size(ptBindGroup->_sbtTextures); for(uint32_t k = 0; k < uTextureCount; k++) { - const plTextureHandle tTextureHandle = ptBindGroup->sbtTextures[k]; + const plTextureHandle tTextureHandle = ptBindGroup->_sbtTextures[k]; plTexture* ptTexture = pl__get_texture(ptDevice, tTextureHandle); [ptEncoder->tEncoder useResource:ptDevice->sbtTexturesHot[tTextureHandle.uIndex].tTexture usage:MTLResourceUsageRead stages:MTLRenderStageVertex | MTLRenderStageFragment]; } - [ptEncoder->tEncoder setVertexBuffer:ptBindGroup->tShaderArgumentBuffer offset:ptBindGroup->uOffset atIndex:uFirst + i]; - [ptEncoder->tEncoder setFragmentBuffer:ptBindGroup->tShaderArgumentBuffer offset:ptBindGroup->uOffset atIndex:uFirst + i]; + [ptEncoder->tEncoder setVertexBuffer:ptMetalBindGroup->tShaderArgumentBuffer offset:ptMetalBindGroup->uOffset atIndex:uFirst + i]; + [ptEncoder->tEncoder setFragmentBuffer:ptMetalBindGroup->tShaderArgumentBuffer offset:ptMetalBindGroup->uOffset atIndex:uFirst + i]; } } @@ -2439,6 +2479,7 @@ if(uDirtyMask & PL_DRAW_STREAM_BIT_BINDGROUP_0) { const plBindGroupHandle tBindGroupHandle = {.uData = ptStream->_auStream[uCurrentStreamIndex] }; + plBindGroup* ptBindGroup = &ptDevice->sbtBindGroupsCold[tBindGroupHandle.uIndex]; plMetalBindGroup* ptMetalBindGroup = &ptDevice->sbtBindGroupsHot[tBindGroupHandle.uIndex]; ptEncoder->uHeapUsageMask |= ptMetalBindGroup->uHeapUsageMask; @@ -2452,10 +2493,10 @@ } } - const uint32_t uTextureCount = pl_sb_size(ptMetalBindGroup->sbtTextures); + const uint32_t uTextureCount = pl_sb_size(ptBindGroup->_sbtTextures); for(uint32_t k = 0; k < uTextureCount; k++) { - const plTextureHandle tTextureHandle = ptMetalBindGroup->sbtTextures[k]; + const plTextureHandle tTextureHandle = ptBindGroup->_sbtTextures[k]; plTexture* ptTexture = pl__get_texture(ptDevice, tTextureHandle); [ptEncoder->tEncoder useResource:ptDevice->sbtTexturesHot[tTextureHandle.uIndex].tTexture usage:MTLResourceUsageRead stages:MTLRenderStageVertex | MTLRenderStageFragment]; } @@ -2469,6 +2510,7 @@ { const plBindGroupHandle tBindGroupHandle = {.uData = ptStream->_auStream[uCurrentStreamIndex] }; plMetalBindGroup* ptMetalBindGroup = &ptDevice->sbtBindGroupsHot[tBindGroupHandle.uIndex]; + plBindGroup* ptBindGroup = &ptDevice->sbtBindGroupsCold[tBindGroupHandle.uIndex]; ptEncoder->uHeapUsageMask |= ptMetalBindGroup->uHeapUsageMask; @@ -2481,10 +2523,10 @@ } } - const uint32_t uTextureCount = pl_sb_size(ptMetalBindGroup->sbtTextures); + const uint32_t uTextureCount = pl_sb_size(ptBindGroup->_sbtTextures); for(uint32_t k = 0; k < uTextureCount; k++) { - const plTextureHandle tTextureHandle = ptMetalBindGroup->sbtTextures[k]; + const plTextureHandle tTextureHandle = ptBindGroup->_sbtTextures[k]; plTexture* ptTexture = pl__get_texture(ptDevice, tTextureHandle); [ptEncoder->tEncoder useResource:ptDevice->sbtTexturesHot[tTextureHandle.uIndex].tTexture usage:MTLResourceUsageRead stages:MTLRenderStageVertex | MTLRenderStageFragment]; } @@ -2498,6 +2540,7 @@ { const plBindGroupHandle tBindGroupHandle = {.uData = ptStream->_auStream[uCurrentStreamIndex] }; plMetalBindGroup* ptMetalBindGroup = &ptDevice->sbtBindGroupsHot[tBindGroupHandle.uIndex]; + plBindGroup* ptBindGroup = &ptDevice->sbtBindGroupsCold[tBindGroupHandle.uIndex]; ptEncoder->uHeapUsageMask |= ptMetalBindGroup->uHeapUsageMask; @@ -2510,10 +2553,10 @@ } } - const uint32_t uTextureCount = pl_sb_size(ptMetalBindGroup->sbtTextures); + const uint32_t uTextureCount = pl_sb_size(ptBindGroup->_sbtTextures); for(uint32_t k = 0; k < uTextureCount; k++) { - const plTextureHandle tTextureHandle = ptMetalBindGroup->sbtTextures[k]; + const plTextureHandle tTextureHandle = ptBindGroup->_sbtTextures[k]; [ptEncoder->tEncoder useResource:ptDevice->sbtTexturesHot[tTextureHandle.uIndex].tTexture usage:MTLResourceUsageRead stages:MTLRenderStageVertex | MTLRenderStageFragment]; } @@ -3144,8 +3187,9 @@ for(uint32_t i = 0; i < pl_sb_size(ptGarbage->sbtBindGroups); i++) { const uint16_t iBindGroupIndex = ptGarbage->sbtBindGroups[i].uIndex; + plBindGroup* ptResource = &ptDevice->sbtBindGroupsCold[iBindGroupIndex]; plMetalBindGroup* ptMetalResource = &ptDevice->sbtBindGroupsHot[iBindGroupIndex]; - pl_sb_reset(ptMetalResource->sbtTextures); + pl_sb_reset(ptResource->_sbtTextures); [ptMetalResource->tShaderArgumentBuffer release]; ptMetalResource->tShaderArgumentBuffer = nil; pl_sb_push(ptDevice->sbtBindGroupFreeIndices, iBindGroupIndex); @@ -3320,6 +3364,8 @@ pl_sb_push(ptDevice->sbtBindGroupFreeIndices, tHandle.uIndex); plMetalBindGroup* ptMetalResource = &ptDevice->sbtBindGroupsHot[tHandle.uIndex]; + plBindGroup* ptResource = &ptDevice->sbtBindGroupsCold[tHandle.uIndex]; + pl_sb_free(ptResource->_sbtTextures); [ptMetalResource->tShaderArgumentBuffer release]; ptMetalResource->tShaderArgumentBuffer = nil; } diff --git a/extensions/pl_graphics_vulkan.c b/extensions/pl_graphics_vulkan.c index 85b9893..3c649e9 100644 --- a/extensions/pl_graphics_vulkan.c +++ b/extensions/pl_graphics_vulkan.c @@ -19,7 +19,6 @@ Index of this file: //----------------------------------------------------------------------------- #include "pl.h" -#include "pl_ds.h" #include "pl_string.h" #include "pl_memory.h" #include "pl_graphics_internal.h" @@ -627,6 +626,115 @@ pl_copy_texture_to_buffer(plBlitEncoder* ptEncoder, plTextureHandle tTextureHand pl_temp_allocator_reset(&gptGraphics->tTempAllocator); } +void +pl_copy_texture(plBlitEncoder* ptEncoder, plTextureHandle tSrcHandle, plTextureHandle tDstHandle, uint32_t uRegionCount, const plImageCopy* ptRegions) +{ + plCommandBuffer* ptCmdBuffer = ptEncoder->ptCommandBuffer; + plDevice* ptDevice = ptCmdBuffer->ptDevice; + + // allocate temporary memory + VkImageCopy* atCopyRegions = pl_temp_allocator_alloc(&gptGraphics->tTempAllocator, sizeof(VkImageCopy) * uRegionCount); + memset(atCopyRegions, 0, sizeof(VkImageCopy) * uRegionCount); + + VkImageSubresourceRange* atSubResourceRanges = pl_temp_allocator_alloc(&gptGraphics->tTempAllocator, sizeof(VkImageSubresourceRange) * uRegionCount); + memset(atSubResourceRanges, 0, sizeof(VkImageSubresourceRange) * uRegionCount * 2); + + // setup copy regions + plTexture* ptColdSrcTexture = pl__get_texture(ptDevice, tSrcHandle); + plTexture* ptColdDstTexture = pl__get_texture(ptDevice, tDstHandle); + + uint32_t uCurrentSrcBaseArrayLevel = UINT32_MAX; + uint32_t uCurrentSrcMipLevel = UINT32_MAX; + + uint32_t uCurrentDestBaseArrayLevel = UINT32_MAX; + uint32_t uCurrentDestMipLevel = UINT32_MAX; + + for (uint32_t i = 0; i < uRegionCount; i++) + { + + atSubResourceRanges[i].aspectMask = ptColdSrcTexture->tDesc.tUsage & PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; + atSubResourceRanges[i].baseMipLevel = ptRegions[i].uSourceMipLevel; + atSubResourceRanges[i].levelCount = ptRegions[i].uSourceLayerCount; + atSubResourceRanges[i].baseArrayLayer = ptRegions[i].uSourceBaseArrayLayer; + atSubResourceRanges[i].layerCount = ptRegions[i].uSourceLayerCount; + + atSubResourceRanges[i + uRegionCount].aspectMask = ptColdDstTexture->tDesc.tUsage & PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; + atSubResourceRanges[i + uRegionCount].baseMipLevel = ptRegions[i].uDestinationMipLevel; + atSubResourceRanges[i + uRegionCount].levelCount = ptRegions[i].uDestinationLayerCount; + atSubResourceRanges[i + uRegionCount].baseArrayLayer = ptRegions[i].uDestinationBaseArrayLayer; + atSubResourceRanges[i + uRegionCount].layerCount = ptRegions[i].uDestinationLayerCount; + + + if(uCurrentSrcBaseArrayLevel != atSubResourceRanges[i].baseArrayLayer || uCurrentSrcMipLevel != atSubResourceRanges[i].baseMipLevel) + { + pl__transition_image_layout(ptCmdBuffer->tCmdBuffer, ptDevice->sbtTexturesHot[tSrcHandle.uIndex].tImage, pl__vulkan_layout(ptRegions[i].tSourceImageUsage), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, atSubResourceRanges[i], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + uCurrentSrcBaseArrayLevel = atSubResourceRanges[i].baseArrayLayer; + uCurrentSrcMipLevel = atSubResourceRanges[i].baseMipLevel; + } + + if(uCurrentDestBaseArrayLevel != atSubResourceRanges[i + uRegionCount].baseArrayLayer || uCurrentDestMipLevel != atSubResourceRanges[i + uRegionCount].baseMipLevel) + { + pl__transition_image_layout(ptCmdBuffer->tCmdBuffer, ptDevice->sbtTexturesHot[tDstHandle.uIndex].tImage, pl__vulkan_layout(ptRegions[i].tDestinationImageUsage), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, atSubResourceRanges[i + uRegionCount], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + uCurrentDestBaseArrayLevel = atSubResourceRanges[i + uRegionCount].baseArrayLayer; + uCurrentDestMipLevel = atSubResourceRanges[i + uRegionCount].baseMipLevel; + } + + + atCopyRegions[i].srcOffset.x = ptRegions[i].iSourceOffsetX; + atCopyRegions[i].srcOffset.y = ptRegions[i].iSourceOffsetY; + atCopyRegions[i].srcOffset.z = ptRegions[i].iSourceOffsetZ; + + atCopyRegions[i].extent.width = ptRegions[i].uSourceExtentX; + atCopyRegions[i].extent.height = ptRegions[i].uSourceExtentY; + atCopyRegions[i].extent.depth = ptRegions[i].uSourceExtentZ; + + atCopyRegions[i].srcSubresource.baseArrayLayer = ptRegions[i].uSourceBaseArrayLayer; + atCopyRegions[i].srcSubresource.layerCount = ptRegions[i].uSourceLayerCount; + atCopyRegions[i].srcSubresource.mipLevel = ptRegions[i].uSourceMipLevel; + atCopyRegions[i].srcSubresource.aspectMask = ptColdSrcTexture->tDesc.tUsage & PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; + + atCopyRegions[i].dstOffset.x = ptRegions[i].iDestinationOffsetX; + atCopyRegions[i].dstOffset.y = ptRegions[i].iDestinationOffsetY; + atCopyRegions[i].dstOffset.z = ptRegions[i].iDestinationOffsetZ; + + atCopyRegions[i].dstSubresource.baseArrayLayer = ptRegions[i].uDestinationBaseArrayLayer; + atCopyRegions[i].dstSubresource.layerCount = ptRegions[i].uDestinationLayerCount; + atCopyRegions[i].dstSubresource.mipLevel = ptRegions[i].uDestinationMipLevel; + atCopyRegions[i].dstSubresource.aspectMask = ptColdDstTexture->tDesc.tUsage & PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT; + } + + vkCmdCopyImage(ptCmdBuffer->tCmdBuffer, + ptDevice->sbtTexturesHot[tSrcHandle.uIndex].tImage, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + ptDevice->sbtTexturesHot[tDstHandle.uIndex].tImage, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + uRegionCount, + atCopyRegions); + + uCurrentSrcBaseArrayLevel = UINT32_MAX; + uCurrentSrcMipLevel = UINT32_MAX; + uCurrentDestBaseArrayLevel = UINT32_MAX; + uCurrentDestMipLevel = UINT32_MAX; + + for (uint32_t i = 0; i < uRegionCount; i++) + { + if(uCurrentSrcBaseArrayLevel != atSubResourceRanges[i].baseArrayLayer || uCurrentSrcMipLevel != atSubResourceRanges[i].baseMipLevel) + { + pl__transition_image_layout(ptCmdBuffer->tCmdBuffer, ptDevice->sbtTexturesHot[tSrcHandle.uIndex].tImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, pl__vulkan_layout(ptRegions[i].tSourceImageUsage), atSubResourceRanges[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + uCurrentSrcBaseArrayLevel = atSubResourceRanges[i].baseArrayLayer; + uCurrentSrcMipLevel = atSubResourceRanges[i].baseMipLevel; + } + if(uCurrentDestBaseArrayLevel != atSubResourceRanges[i + uRegionCount].baseArrayLayer || uCurrentDestMipLevel != atSubResourceRanges[i + uRegionCount].baseMipLevel) + { + pl__transition_image_layout(ptCmdBuffer->tCmdBuffer, ptDevice->sbtTexturesHot[tDstHandle.uIndex].tImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, pl__vulkan_layout(ptRegions[i].tDestinationImageUsage), atSubResourceRanges[i + uRegionCount], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT); + uCurrentDestBaseArrayLevel = atSubResourceRanges[i + uRegionCount].baseArrayLayer; + uCurrentDestMipLevel = atSubResourceRanges[i + uRegionCount].baseMipLevel; + } + } + + pl_temp_allocator_reset(&gptGraphics->tTempAllocator); +} + void pl_generate_mipmaps(plBlitEncoder* ptEncoder, plTextureHandle tTexture) { @@ -686,18 +794,18 @@ pl_generate_mipmaps(plBlitEncoder* ptEncoder, plTextureHandle tTexture) .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .mipLevel = i - 1, .baseArrayLayer = 0, - .layerCount = 1 + .layerCount = ptTexture->tDesc.uLayers }, .dstOffsets[1] = { - .x = 1, - .y = 1, + .x = 0, + .y = 0, .z = 1 }, .dstSubresource = { .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, .mipLevel = i, .baseArrayLayer = 0, - .layerCount = 1 + .layerCount = ptTexture->tDesc.uLayers } }; @@ -946,7 +1054,7 @@ pl_update_bind_group(plDevice* ptDevice, plBindGroupHandle tHandle, const plBind const plVulkanBuffer* ptVulkanBuffer = &ptDevice->sbtBuffersHot[ptData->atBufferBindings[i].tBuffer.uIndex]; sbtBufferDescInfos[i].buffer = ptVulkanBuffer->tBuffer; - sbtBufferDescInfos[i].offset = ptData->atBufferBindings[i].szOffset; + sbtBufferDescInfos[i].offset = ptData->atBufferBindings[i]._szOffset; sbtBufferDescInfos[i].range = ptData->atBufferBindings[i].szBufferRange == 0 ? VK_WHOLE_SIZE : ptData->atBufferBindings[i].szBufferRange; sbtWrites[uCurrentWrite].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; @@ -1293,7 +1401,6 @@ pl_create_shader(plDevice* ptDevice, const plShaderDesc* ptDescription) plShaderHandle tHandle = pl__get_new_shader_handle(ptDevice); plShader* ptShader = pl__get_shader(ptDevice, tHandle); ptShader->tDesc = *ptDescription; - uint32_t uStageCount = 1; plVulkanShader* ptVulkanShader = &ptDevice->sbtShadersHot[tHandle.uIndex]; @@ -4229,7 +4336,7 @@ pl__fill_common_render_pass_data(plRenderPassLayoutDesc* ptDesc, plRenderPassLay .srcSubpass = ptDesc->_uSubpassCount - 1, .dstSubpass = VK_SUBPASS_EXTERNAL, .srcStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, - .dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, + .dstStageMask = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, .srcAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, .dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT, .dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT diff --git a/extensions/pl_model_loader_ext.c b/extensions/pl_model_loader_ext.c index 3c82123..f1f1aa9 100644 --- a/extensions/pl_model_loader_ext.c +++ b/extensions/pl_model_loader_ext.c @@ -20,7 +20,6 @@ Index of this file: #include "pl.h" #include "pl_model_loader_ext.h" #include "pl_stl.h" -#include "pl_ds.h" #include "pl_string.h" #define PL_MATH_INCLUDE_FUNCTIONS #include "pl_math.h" @@ -49,6 +48,8 @@ Index of this file: static const plFileI* gptFile = NULL; #endif +#include "pl_ds.h" + // misc #include "cgltf.h" diff --git a/extensions/pl_renderer_ext.c b/extensions/pl_renderer_ext.c index fbc0c52..a7eb365 100644 --- a/extensions/pl_renderer_ext.c +++ b/extensions/pl_renderer_ext.c @@ -37,7 +37,6 @@ static void pl_refr_resize(void); // loading static void pl_refr_load_skybox_from_panorama(uint32_t, const char*, int); -static void pl_create_environment_map_from_skybox(uint32_t); static void pl_refr_finalize_scene(uint32_t); static void pl_refr_reload_scene_shaders(uint32_t); @@ -88,6 +87,7 @@ pl_refr_initialize(plWindow* ptWindow) gptData->uOutlineWidth = 4; gptData->bFrustumCulling = true; gptData->bImageBasedLighting = true; + gptData->bPunctualLighting = true; gptData->fShadowConstantDepthBias = -1.25f; gptData->fShadowSlopeDepthBias = -10.75f; @@ -238,10 +238,11 @@ pl_refr_initialize(plWindow* ptWindow) .fMaxMip = 64.0f, .tVAddressMode = PL_ADDRESS_MODE_WRAP, .tUAddressMode = PL_ADDRESS_MODE_WRAP, + .tMipmapMode = PL_MIPMAP_MODE_NEAREST, .pcDebugName = "default sampler" }; gptData->tDefaultSampler = gptGfx->create_sampler(gptData->ptDevice, &tSamplerDesc); - + const plSamplerDesc tShadowSamplerDesc = { .tMagFilter = PL_FILTER_NEAREST, .tMinFilter = PL_FILTER_NEAREST, @@ -255,13 +256,28 @@ pl_refr_initialize(plWindow* ptWindow) }; gptData->tShadowSampler = gptGfx->create_sampler(gptData->ptDevice, &tShadowSamplerDesc); - const plSamplerDesc tEnvSamplerDesc = { + const plSamplerDesc tSkyboxSamplerDesc = { .tMagFilter = PL_FILTER_LINEAR, .tMinFilter = PL_FILTER_LINEAR, .fMinMip = 0.0f, .fMaxMip = 64.0f, - .tVAddressMode = PL_ADDRESS_MODE_CLAMP, - .tUAddressMode = PL_ADDRESS_MODE_CLAMP, + .fMaxAnisotropy = 1.0f, + .tVAddressMode = PL_ADDRESS_MODE_WRAP, + .tUAddressMode = PL_ADDRESS_MODE_WRAP, + .tMipmapMode = PL_MIPMAP_MODE_LINEAR, + .pcDebugName = "skybox sampler" + }; + gptData->tSkyboxSampler = gptGfx->create_sampler(gptData->ptDevice, &tSkyboxSamplerDesc); + + const plSamplerDesc tEnvSamplerDesc = { + .tMagFilter = PL_FILTER_NEAREST, + .tMinFilter = PL_FILTER_NEAREST, + .fMinMip = 0.0f, + .fMaxMip = 64.0f, + .fMaxAnisotropy = 1.0f, + .tVAddressMode = PL_ADDRESS_MODE_WRAP, + .tUAddressMode = PL_ADDRESS_MODE_WRAP, + .tMipmapMode = PL_MIPMAP_MODE_LINEAR, .pcDebugName = "ENV sampler" }; gptData->tEnvSampler = gptGfx->create_sampler(gptData->ptDevice, &tEnvSamplerDesc); @@ -271,7 +287,7 @@ pl_refr_initialize(plWindow* ptWindow) .atRenderTargets = { { .tFormat = PL_FORMAT_D32_FLOAT_S8_UINT, .bDepth = true }, // depth buffer { .tFormat = PL_FORMAT_R16G16B16A16_FLOAT }, // final output - { .tFormat = PL_FORMAT_R8G8B8A8_SRGB }, // albedo + { .tFormat = PL_FORMAT_R8G8B8A8_UNORM }, // albedo { .tFormat = PL_FORMAT_R16G16_FLOAT }, // normal { .tFormat = PL_FORMAT_R16G16B16A16_FLOAT }, // AO, roughness, metallic, mip count }, @@ -492,6 +508,28 @@ pl_refr_initialize(plWindow* ptWindow) atMainAttachmentSets[i].atViewAttachments[1] = gptData->tMSAATexture; } gptData->tMainRenderPass = gptGfx->create_render_pass(gptData->ptDevice, &tMainRenderPassDesc, atMainAttachmentSets); + + plComputeShaderDesc tFilterComputeShaderDesc = { + .tShader = gptShader->load_glsl("../shaders/filter_environment.comp", "main", NULL, NULL), + .atBindGroupLayouts = { + { + .atTextureBindings = { + {.uSlot = 1, .tStages = PL_STAGE_COMPUTE, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED} + }, + .atBufferBindings = { + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 2, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 3, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 4, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 5, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 6, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 7, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 8, .tStages = PL_STAGE_COMPUTE}, + }, + .atSamplerBindings = { {.uSlot = 0, .tStages = PL_STAGE_COMPUTE}} + } + } + }; + gptData->tEnvFilterShader = gptGfx->create_compute_shader(gptData->ptDevice, &tFilterComputeShaderDesc); }; static uint32_t @@ -556,11 +594,6 @@ pl_refr_create_scene(void) gptGfx->update_bind_group(gptData->ptDevice, ptScene->tGlobalBindGroup, &tGlobalBindGroupData); - ptScene->uGGXLUT = pl__get_bindless_texture_index(uSceneHandle, gptData->tDummyTexture); - ptScene->uLambertianEnvSampler = pl__get_bindless_cube_texture_index(uSceneHandle, gptData->tDummyTextureCube); - ptScene->uGGXEnvSampler = pl__get_bindless_cube_texture_index(uSceneHandle, gptData->tDummyTextureCube); - - const plBufferDesc atLightShadowDataBufferDesc = { .tUsage = PL_BUFFER_USAGE_STORAGE | PL_BUFFER_USAGE_STAGING, .szByteSize = 134217728, @@ -583,6 +616,18 @@ pl_refr_create_scene(void) } + for(uint32_t i = 0; i < 7; i++) + { + const size_t uMaxFaceSize = ((size_t)1024 * (size_t)1024) * 4 * sizeof(float); + + const plBufferDesc tInputBufferDesc = { + .tUsage = PL_BUFFER_USAGE_STORAGE, + .szByteSize = uMaxFaceSize, + .pcDebugName = "filter buffers" + }; + ptScene->atFilterWorkingBuffers[i] = pl__refr_create_local_buffer(&tInputBufferDesc, "filter buffer", i, NULL); + } + return uSceneHandle; } @@ -645,7 +690,7 @@ pl_refr_create_view(uint32_t uSceneHandle, plVec2 tDimensions) const plTextureDesc tAlbedoTextureDesc = { .tDimensions = {ptView->tTargetSize.x, ptView->tTargetSize.y, 1}, - .tFormat = PL_FORMAT_R8G8B8A8_SRGB, + .tFormat = PL_FORMAT_R8G8B8A8_UNORM, .uLayers = 1, .uMips = 1, .tType = PL_TEXTURE_TYPE_2D, @@ -720,77 +765,82 @@ pl_refr_create_view(uint32_t uSceneHandle, plVec2 tDimensions) ptView->tPickTexture = pl__refr_create_texture(&tPickTextureDesc, "pick original", 0, PL_TEXTURE_USAGE_SAMPLED); ptView->tPickDepthTexture = pl__refr_create_texture(&tPickDepthTextureDesc, "pick depth original", 0, PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT); + ptView->tRawOutputTexture = pl__refr_create_texture(&tRawOutputTextureDesc, "offscreen raw", 0, PL_TEXTURE_USAGE_SAMPLED); + ptView->tAlbedoTexture = pl__refr_create_texture(&tAlbedoTextureDesc, "albedo original", 0, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); + ptView->tNormalTexture = pl__refr_create_texture(&tNormalTextureDesc, "normal original", 0, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); + ptView->tAOMetalRoughnessTexture = pl__refr_create_texture(&tEmmissiveTexDesc, "metalroughness original", 0, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); + ptView->tDepthTexture = pl__refr_create_texture(&tDepthTextureDesc, "offscreen depth original", 0, PL_TEXTURE_USAGE_SAMPLED); + ptView->atUVMaskTexture0 = pl__refr_create_texture(&tMaskTextureDesc, "uv mask texture 0", 0, PL_TEXTURE_USAGE_STORAGE); + ptView->atUVMaskTexture1 = pl__refr_create_texture(&tMaskTextureDesc, "uv mask texture 1", 0, PL_TEXTURE_USAGE_STORAGE); + ptView->tFinalTexture = pl__refr_create_texture(&tRawOutputTextureDesc, "offscreen final", 0, PL_TEXTURE_USAGE_SAMPLED); + ptView->tFinalTextureHandle = gptDrawBackend->create_bind_group_for_texture(ptView->tFinalTexture); + + // lighting bind group + const plBindGroupDesc tLightingBindGroupDesc = { + .ptPool = gptData->ptBindGroupPool, + .ptLayout = &tLightingBindGroupLayout, + .pcDebugName = "lighting bind group" + }; + ptView->tLightingBindGroup = gptGfx->create_bind_group(gptData->ptDevice, &tLightingBindGroupDesc); + + const plBindGroupUpdateTextureData atBGTextureData[] = { + { + .tTexture = ptView->tAlbedoTexture, + .uSlot = 0, + .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT + }, + { + .tTexture = ptView->tNormalTexture, + .uSlot = 1, + .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT + }, + { + .tTexture = ptView->tAOMetalRoughnessTexture, + .uSlot = 2, + .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT + }, + { + .tTexture = ptView->tDepthTexture, + .uSlot = 3, + .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT + } + }; + const plBindGroupUpdateData tBGData = { + .uTextureCount = 4, + .atTextureBindings = atBGTextureData + }; + gptGfx->update_bind_group(gptData->ptDevice, ptView->tLightingBindGroup, &tBGData); + for(uint32_t i = 0; i < gptGfx->get_frames_in_flight(); i++) { // textures - ptView->tFinalTexture[i] = pl__refr_create_texture(&tRawOutputTextureDesc, "offscreen final", i, PL_TEXTURE_USAGE_SAMPLED); - ptView->tFinalTextureHandle[i] = gptDrawBackend->create_bind_group_for_texture(ptView->tFinalTexture[i]); - ptView->tRawOutputTexture[i] = pl__refr_create_texture(&tRawOutputTextureDesc, "offscreen raw", i, PL_TEXTURE_USAGE_SAMPLED); - ptView->tAlbedoTexture[i] = pl__refr_create_texture(&tAlbedoTextureDesc, "albedo original", i, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); - ptView->tNormalTexture[i] = pl__refr_create_texture(&tNormalTextureDesc, "normal original", i, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); - ptView->tAOMetalRoughnessTexture[i] = pl__refr_create_texture(&tEmmissiveTexDesc, "metalroughness original", i, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); - ptView->tDepthTexture[i] = pl__refr_create_texture(&tDepthTextureDesc, "offscreen depth original", i, PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT); - ptView->atUVMaskTexture0[i] = pl__refr_create_texture(&tMaskTextureDesc, "uv mask texture 0", i, PL_TEXTURE_USAGE_STORAGE); - ptView->atUVMaskTexture1[i] = pl__refr_create_texture(&tMaskTextureDesc, "uv mask texture 1", i, PL_TEXTURE_USAGE_STORAGE); + + // buffers ptView->atGlobalBuffers[i] = pl__refr_create_staging_buffer(&atGlobalBuffersDesc, "global", i); - // lighting bind group - const plBindGroupDesc tLightingBindGroupDesc = { - .ptPool = gptData->ptBindGroupPool, - .ptLayout = &tLightingBindGroupLayout, - .pcDebugName = "lighting bind group" - }; - ptView->tLightingBindGroup[i] = gptGfx->create_bind_group(gptData->ptDevice, &tLightingBindGroupDesc); - const plBindGroupUpdateTextureData atBGTextureData[] = { - { - .tTexture = ptView->tAlbedoTexture[i], - .uSlot = 0, - .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT - }, - { - .tTexture = ptView->tNormalTexture[i], - .uSlot = 1, - .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT - }, - { - .tTexture = ptView->tAOMetalRoughnessTexture[i], - .uSlot = 2, - .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT - }, - { - .tTexture = ptView->tDepthTexture[i], - .uSlot = 3, - .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT - } - }; - const plBindGroupUpdateData tBGData = { - .uTextureCount = 4, - .atTextureBindings = atBGTextureData - }; - gptGfx->update_bind_group(gptData->ptDevice, ptView->tLightingBindGroup[i], &tBGData); pl_temp_allocator_reset(&gptData->tTempAllocator); // attachment sets atPickAttachmentSets[i].atViewAttachments[0] = ptView->tPickDepthTexture; atPickAttachmentSets[i].atViewAttachments[1] = ptView->tPickTexture; - atAttachmentSets[i].atViewAttachments[0] = ptView->tDepthTexture[i]; - atAttachmentSets[i].atViewAttachments[1] = ptView->tRawOutputTexture[i]; - atAttachmentSets[i].atViewAttachments[2] = ptView->tAlbedoTexture[i]; - atAttachmentSets[i].atViewAttachments[3] = ptView->tNormalTexture[i]; - atAttachmentSets[i].atViewAttachments[4] = ptView->tAOMetalRoughnessTexture[i]; + atAttachmentSets[i].atViewAttachments[0] = ptView->tDepthTexture; + atAttachmentSets[i].atViewAttachments[1] = ptView->tRawOutputTexture; + atAttachmentSets[i].atViewAttachments[2] = ptView->tAlbedoTexture; + atAttachmentSets[i].atViewAttachments[3] = ptView->tNormalTexture; + atAttachmentSets[i].atViewAttachments[4] = ptView->tAOMetalRoughnessTexture; - atUVAttachmentSets[i].atViewAttachments[0] = ptView->tDepthTexture[i]; - atUVAttachmentSets[i].atViewAttachments[1] = ptView->atUVMaskTexture0[i]; + atUVAttachmentSets[i].atViewAttachments[0] = ptView->tDepthTexture; + atUVAttachmentSets[i].atViewAttachments[1] = ptView->atUVMaskTexture0; - atPostProcessAttachmentSets[i].atViewAttachments[0] = ptView->tDepthTexture[i]; - atPostProcessAttachmentSets[i].atViewAttachments[1] = ptView->tFinalTexture[i]; + atPostProcessAttachmentSets[i].atViewAttachments[0] = ptView->tDepthTexture; + atPostProcessAttachmentSets[i].atViewAttachments[1] = ptView->tFinalTexture; - ptView->atDLightShadowDataBuffer[i] = pl__refr_create_staging_buffer(&atLightShadowDataBufferDesc, "d shadow", i); - ptView->atDShadowCameraBuffers[i] = pl__refr_create_staging_buffer(&atCameraBuffersDesc, "d shadow buffer", i); + ptView->tDirectionLightShadowData.atDLightShadowDataBuffer[i] = pl__refr_create_staging_buffer(&atLightShadowDataBufferDesc, "d shadow", i); + ptView->tDirectionLightShadowData.atDShadowCameraBuffers[i] = pl__refr_create_staging_buffer(&atCameraBuffersDesc, "d shadow buffer", i); } @@ -801,8 +851,8 @@ pl_refr_create_view(uint32_t uSceneHandle, plVec2 tDimensions) .tStoreOp = PL_STORE_OP_DONT_CARE, .tStencilLoadOp = PL_LOAD_OP_CLEAR, .tStencilStoreOp = PL_STORE_OP_STORE, - .tCurrentUsage = PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT, - .tNextUsage = PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT, + .tCurrentUsage = PL_TEXTURE_USAGE_SAMPLED, + .tNextUsage = PL_TEXTURE_USAGE_SAMPLED, .fClearZ = 0.0f }, .atColorTargets = { @@ -877,8 +927,8 @@ pl_refr_create_view(uint32_t uSceneHandle, plVec2 tDimensions) .tStoreOp = PL_STORE_OP_DONT_CARE, .tStencilLoadOp = PL_LOAD_OP_LOAD, .tStencilStoreOp = PL_STORE_OP_STORE, - .tCurrentUsage = PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT, - .tNextUsage = PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT, + .tCurrentUsage = PL_TEXTURE_USAGE_SAMPLED, + .tNextUsage = PL_TEXTURE_USAGE_SAMPLED, .fClearZ = 0.0f }, .atColorTargets = { @@ -909,8 +959,8 @@ pl_refr_create_view(uint32_t uSceneHandle, plVec2 tDimensions) .tStoreOp = PL_STORE_OP_DONT_CARE, .tStencilLoadOp = PL_LOAD_OP_LOAD, .tStencilStoreOp = PL_STORE_OP_STORE, - .tCurrentUsage = PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT, - .tNextUsage = PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT, + .tCurrentUsage = PL_TEXTURE_USAGE_SAMPLED, + .tNextUsage = PL_TEXTURE_USAGE_SAMPLED, .fClearZ = 0.0f }, .atColorTargets = { @@ -981,7 +1031,7 @@ pl_refr_resize_view(uint32_t uSceneHandle, uint32_t uViewHandle, plVec2 tDimensi const plTextureDesc tAlbedoTextureDesc = { .tDimensions = {ptView->tTargetSize.x, ptView->tTargetSize.y, 1}, - .tFormat = PL_FORMAT_R8G8B8A8_SRGB, + .tFormat = PL_FORMAT_R8G8B8A8_UNORM, .uLayers = 1, .uMips = 1, .tType = PL_TEXTURE_TYPE_2D, @@ -1035,84 +1085,80 @@ pl_refr_resize_view(uint32_t uSceneHandle, uint32_t uViewHandle, plVec2 tDimensi ptView->tPickTexture = pl__refr_create_texture(&tPickTextureDesc, "pick", 0, PL_TEXTURE_USAGE_SAMPLED); ptView->tPickDepthTexture = pl__refr_create_texture(&tPickDepthTextureDesc, "pick depth", 0, PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT); + // queue old resources for deletion + gptGfx->queue_texture_for_deletion(ptDevice, ptView->tFinalTexture); + gptGfx->queue_texture_for_deletion(ptDevice, ptView->atUVMaskTexture0); + gptGfx->queue_texture_for_deletion(ptDevice, ptView->atUVMaskTexture1); + gptGfx->queue_texture_for_deletion(ptDevice, ptView->tRawOutputTexture); + gptGfx->queue_texture_for_deletion(ptDevice, ptView->tAlbedoTexture); + gptGfx->queue_texture_for_deletion(ptDevice, ptView->tNormalTexture); + gptGfx->queue_texture_for_deletion(ptDevice, ptView->tAOMetalRoughnessTexture); + gptGfx->queue_texture_for_deletion(ptDevice, ptView->tDepthTexture); + gptGfx->queue_bind_group_for_deletion(ptDevice, ptView->tLightingBindGroup); + + // textures + ptView->tRawOutputTexture = pl__refr_create_texture(&tRawOutputTextureDesc, "offscreen raw", 0, PL_TEXTURE_USAGE_SAMPLED); + ptView->tAlbedoTexture = pl__refr_create_texture(&tAlbedoTextureDesc, "albedo original", 0, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); + ptView->tNormalTexture = pl__refr_create_texture(&tNormalTextureDesc, "normal resize", 0, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); + ptView->tAOMetalRoughnessTexture = pl__refr_create_texture(&tEmmissiveTexDesc, "metalroughness original", 0, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); + ptView->tDepthTexture = pl__refr_create_texture(&tDepthTextureDesc, "offscreen depth original", 0, PL_TEXTURE_USAGE_SAMPLED); + ptView->atUVMaskTexture0 = pl__refr_create_texture(&tMaskTextureDesc, "uv mask texture 0", 0, PL_TEXTURE_USAGE_STORAGE); + ptView->atUVMaskTexture1 = pl__refr_create_texture(&tMaskTextureDesc, "uv mask texture 1", 0, PL_TEXTURE_USAGE_STORAGE); + ptView->tFinalTexture = pl__refr_create_texture(&tRawOutputTextureDesc, "offscreen final", 0, PL_TEXTURE_USAGE_SAMPLED); + ptView->tFinalTextureHandle = gptDrawBackend->create_bind_group_for_texture(ptView->tFinalTexture); + + // lighting bind group + const plBindGroupDesc tLightingBindGroupDesc = { + .ptPool = gptData->ptBindGroupPool, + .ptLayout = &tLightingBindGroupLayout, + .pcDebugName = "lighting bind group" + }; + ptView->tLightingBindGroup = gptGfx->create_bind_group(gptData->ptDevice, &tLightingBindGroupDesc); + const plBindGroupUpdateTextureData atBGTextureData[] = { + { + .tTexture = ptView->tAlbedoTexture, + .uSlot = 0, + .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT + }, + { + .tTexture = ptView->tNormalTexture, + .uSlot = 1, + .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT + }, + { + .tTexture = ptView->tAOMetalRoughnessTexture, + .uSlot = 2, + .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT + }, + { + .tTexture = ptView->tDepthTexture, + .uSlot = 3, + .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT + } + }; + const plBindGroupUpdateData tBGData = { + .uTextureCount = 4, + .atTextureBindings = atBGTextureData + }; + gptGfx->update_bind_group(gptData->ptDevice, ptView->tLightingBindGroup, &tBGData); + for(uint32_t i = 0; i < gptGfx->get_frames_in_flight(); i++) { - - // queue old resources for deletion - gptGfx->queue_texture_for_deletion(ptDevice, ptView->atUVMaskTexture0[i]); - gptGfx->queue_texture_for_deletion(ptDevice, ptView->atUVMaskTexture1[i]); - gptGfx->queue_texture_for_deletion(ptDevice, ptView->tFinalTexture[i]); - gptGfx->queue_texture_for_deletion(ptDevice, ptView->tRawOutputTexture[i]); - gptGfx->queue_texture_for_deletion(ptDevice, ptView->tAlbedoTexture[i]); - gptGfx->queue_texture_for_deletion(ptDevice, ptView->tNormalTexture[i]); - gptGfx->queue_texture_for_deletion(ptDevice, ptView->tAOMetalRoughnessTexture[i]); - gptGfx->queue_texture_for_deletion(ptDevice, ptView->tDepthTexture[i]); - gptGfx->queue_bind_group_for_deletion(ptDevice, ptView->tLightingBindGroup[i]); - - // textures - ptView->tFinalTexture[i] = pl__refr_create_texture(&tRawOutputTextureDesc, "offscreen final", i, PL_TEXTURE_USAGE_SAMPLED); - ptView->tFinalTextureHandle[i] = gptDrawBackend->create_bind_group_for_texture(ptView->tFinalTexture[i]); - ptView->tRawOutputTexture[i] = pl__refr_create_texture(&tRawOutputTextureDesc, "offscreen raw", i, PL_TEXTURE_USAGE_SAMPLED); - ptView->tAlbedoTexture[i] = pl__refr_create_texture(&tAlbedoTextureDesc, "albedo original", i, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); - ptView->tNormalTexture[i] = pl__refr_create_texture(&tNormalTextureDesc, "normal resize", i, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); - ptView->tAOMetalRoughnessTexture[i] = pl__refr_create_texture(&tEmmissiveTexDesc, "metalroughness original", i, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); - ptView->tDepthTexture[i] = pl__refr_create_texture(&tDepthTextureDesc, "offscreen depth original", i, PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT); - ptView->atUVMaskTexture0[i] = pl__refr_create_texture(&tMaskTextureDesc, "uv mask texture 0", i, PL_TEXTURE_USAGE_STORAGE); - ptView->atUVMaskTexture1[i] = pl__refr_create_texture(&tMaskTextureDesc, "uv mask texture 1", i, PL_TEXTURE_USAGE_STORAGE); - - - // lighting bind group - plTempAllocator tTempAllocator = {0}; - const plBindGroupDesc tLightingBindGroupDesc = { - .ptPool = gptData->ptBindGroupPool, - .ptLayout = &tLightingBindGroupLayout, - .pcDebugName = "lighting bind group" - }; - ptView->tLightingBindGroup[i] = gptGfx->create_bind_group(gptData->ptDevice, &tLightingBindGroupDesc); - const plBindGroupUpdateTextureData atBGTextureData[] = { - { - .tTexture = ptView->tAlbedoTexture[i], - .uSlot = 0, - .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT - }, - { - .tTexture = ptView->tNormalTexture[i], - .uSlot = 1, - .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT - }, - { - .tTexture = ptView->tAOMetalRoughnessTexture[i], - .uSlot = 2, - .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT - }, - { - .tTexture = ptView->tDepthTexture[i], - .uSlot = 3, - .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT - } - }; - const plBindGroupUpdateData tBGData = { - .uTextureCount = 4, - .atTextureBindings = atBGTextureData - }; - gptGfx->update_bind_group(gptData->ptDevice, ptView->tLightingBindGroup[i], &tBGData); - pl_temp_allocator_free(&tTempAllocator); - // attachment sets atPickAttachmentSets[i].atViewAttachments[0] = ptView->tPickDepthTexture; atPickAttachmentSets[i].atViewAttachments[1] = ptView->tPickTexture; - atAttachmentSets[i].atViewAttachments[0] = ptView->tDepthTexture[i]; - atAttachmentSets[i].atViewAttachments[1] = ptView->tRawOutputTexture[i]; - atAttachmentSets[i].atViewAttachments[2] = ptView->tAlbedoTexture[i]; - atAttachmentSets[i].atViewAttachments[3] = ptView->tNormalTexture[i]; - atAttachmentSets[i].atViewAttachments[4] = ptView->tAOMetalRoughnessTexture[i]; + atAttachmentSets[i].atViewAttachments[0] = ptView->tDepthTexture; + atAttachmentSets[i].atViewAttachments[1] = ptView->tRawOutputTexture; + atAttachmentSets[i].atViewAttachments[2] = ptView->tAlbedoTexture; + atAttachmentSets[i].atViewAttachments[3] = ptView->tNormalTexture; + atAttachmentSets[i].atViewAttachments[4] = ptView->tAOMetalRoughnessTexture; - atPostProcessAttachmentSets[i].atViewAttachments[0] = ptView->tDepthTexture[i]; - atPostProcessAttachmentSets[i].atViewAttachments[1] = ptView->tFinalTexture[i]; + atPostProcessAttachmentSets[i].atViewAttachments[0] = ptView->tDepthTexture; + atPostProcessAttachmentSets[i].atViewAttachments[1] = ptView->tFinalTexture; - atUVAttachmentSets[i].atViewAttachments[0] = ptView->tDepthTexture[i]; - atUVAttachmentSets[i].atViewAttachments[1] = ptView->atUVMaskTexture0[i]; + atUVAttachmentSets[i].atViewAttachments[0] = ptView->tDepthTexture; + atUVAttachmentSets[i].atViewAttachments[1] = ptView->atUVMaskTexture0; } gptGfx->update_render_pass_attachments(ptDevice, ptView->tRenderPass, ptView->tTargetSize, atAttachmentSets); gptGfx->update_render_pass_attachments(ptDevice, ptView->tPostProcessRenderPass, ptView->tTargetSize, atPostProcessAttachmentSets); @@ -1134,22 +1180,43 @@ pl_refr_cleanup(void) plRefView* ptView = &ptScene->atViews[j]; pl_sb_free(ptView->sbtVisibleOpaqueDrawables); pl_sb_free(ptView->sbtVisibleTransparentDrawables); - pl_sb_free(ptView->sbtDLightShadowData); + pl_sb_free(ptView->tDirectionLightShadowData.sbtDLightShadowData); + } + + for(uint32_t j = 0; j < pl_sb_size(ptScene->sbtProbeData); j++) + { + plEnvironmentProbeData* ptProbe = &ptScene->sbtProbeData[j]; + + for(uint32_t k = 0; k < 6; k++) + { + pl_sb_free(ptProbe->sbtVisibleOpaqueDrawables[k]); + pl_sb_free(ptProbe->sbtVisibleTransparentDrawables[k]); + } + pl_sb_free(ptProbe->tDirectionLightShadowData.sbtDLightShadowData); } + + pl_sb_free(ptScene->sbtProbeData); + pl_sb_free(ptScene->sbtShadowRects); + pl_sb_free(ptScene->sbuShadowDeferredDrawables); + pl_sb_free(ptScene->sbuShadowForwardDrawables); pl_sb_free(ptScene->sbtPLightShadowData); pl_sb_free(ptScene->sbtSLightShadowData); pl_sb_free(ptScene->sbtPLightData); pl_sb_free(ptScene->sbtDLightData); + pl_sb_free(ptScene->sbtSLightData); pl_sb_free(ptScene->sbtVertexPosBuffer); pl_sb_free(ptScene->sbtVertexDataBuffer); pl_sb_free(ptScene->sbuIndexBuffer); pl_sb_free(ptScene->sbtMaterialBuffer); pl_sb_free(ptScene->sbtDeferredDrawables); pl_sb_free(ptScene->sbtForwardDrawables); + pl_sb_free(ptScene->sbtNewDeferredDrawables); + pl_sb_free(ptScene->sbtNewForwardDrawables); pl_sb_free(ptScene->sbtSkinData); pl_sb_free(ptScene->sbtSkinVertexDataBuffer); pl_sb_free(ptScene->sbtOutlineDrawables); pl_sb_free(ptScene->sbtOutlineDrawablesOldShaders); + pl_sb_free(ptScene->sbtOutlineDrawablesOldEnvShaders); pl_hm_free(ptScene->ptDeferredHashmap); pl_hm_free(ptScene->ptForwardHashmap); pl_hm_free(ptScene->ptMaterialHashmap); @@ -1163,7 +1230,9 @@ pl_refr_cleanup(void) gptGfx->queue_shader_for_deletion(gptData->ptDevice, gptData->_sbtVariantHandles[i]); } pl_sb_free(gptData->_sbtVariantHandles); + pl_sb_free(gptData->sbtTextureHandles); pl_hm_free(gptData->ptVariantHashmap); + pl_hm_free(gptData->ptTextureHashmap); gptGfx->flush_device(gptData->ptDevice); gptGfx->destroy_texture(gptData->ptDevice, gptData->tMSAATexture); @@ -1209,7 +1278,7 @@ pl_refr_get_swapchain(void) } static void -pl_create_environment_map_from_skybox(uint32_t uSceneHandle) +pl_refr_load_skybox_from_panorama(uint32_t uSceneHandle, const char* pcPath, int iResolution) { pl_begin_cpu_sample(gptProfile, 0, __FUNCTION__); const int iSamples = 512; @@ -1217,532 +1286,102 @@ pl_create_environment_map_from_skybox(uint32_t uSceneHandle) plDevice* ptDevice = gptData->ptDevice; plCommandPool* ptCmdPool = gptData->atCmdPools[gptGfx->get_current_frame_index()]; - plTexture* ptSkyboxTexture = gptGfx->get_texture(ptDevice, ptScene->tSkyboxTexture); - const int iResolution = (int)ptSkyboxTexture->tDesc.tDimensions.x; - const size_t uFaceSize = ((size_t)iResolution * (size_t)iResolution) * 4 * sizeof(float); - - pl_begin_cpu_sample(gptProfile, 0, "step 1"); - - plComputeShaderDesc tFilterComputeShaderDesc = { - .tShader = gptShader->load_glsl("../shaders/filter_environment.comp", "main", NULL, NULL), - .atConstants = { - { .uID = 0, .uOffset = 0, .tType = PL_DATA_TYPE_INT}, - { .uID = 1, .uOffset = 4, .tType = PL_DATA_TYPE_FLOAT}, - { .uID = 2, .uOffset = 8, .tType = PL_DATA_TYPE_INT}, - { .uID = 3, .uOffset = 12, .tType = PL_DATA_TYPE_INT}, - { .uID = 4, .uOffset = 16, .tType = PL_DATA_TYPE_FLOAT}, - { .uID = 5, .uOffset = 20, .tType = PL_DATA_TYPE_INT}, - { .uID = 6, .uOffset = 24, .tType = PL_DATA_TYPE_INT}, - { .uID = 7, .uOffset = 28, .tType = PL_DATA_TYPE_INT} - }, - .atBindGroupLayouts = { - { - .atTextureBindings = { - {.uSlot = 1, .tStages = PL_STAGE_COMPUTE, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED} - }, - .atBufferBindings = { - { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 2, .tStages = PL_STAGE_COMPUTE}, - { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 3, .tStages = PL_STAGE_COMPUTE}, - { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 4, .tStages = PL_STAGE_COMPUTE}, - { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 5, .tStages = PL_STAGE_COMPUTE}, - { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 6, .tStages = PL_STAGE_COMPUTE}, - { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 7, .tStages = PL_STAGE_COMPUTE}, - { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 8, .tStages = PL_STAGE_COMPUTE}, + // create skybox shader if we haven't + if(gptData->tSkyboxShader.uIndex == 0) + { + // create skybox shader + plShaderDesc tSkyboxShaderDesc = { + .tPixelShader = gptShader->load_glsl("../shaders/skybox.frag", "main", NULL, NULL), + .tVertexShader = gptShader->load_glsl("../shaders/skybox.vert", "main", NULL, NULL), + .tGraphicsState = { + .ulDepthWriteEnabled = 0, + .ulDepthMode = PL_COMPARE_MODE_EQUAL, + .ulCullMode = PL_CULL_MODE_NONE, + .ulStencilMode = PL_COMPARE_MODE_ALWAYS, + .ulStencilRef = 0xff, + .ulStencilMask = 0xff, + .ulStencilOpFail = PL_STENCIL_OP_KEEP, + .ulStencilOpDepthFail = PL_STENCIL_OP_KEEP, + .ulStencilOpPass = PL_STENCIL_OP_KEEP + }, + .atVertexBufferLayouts = { + { + .uByteStride = sizeof(float) * 3, + .atAttributes = { {.uByteOffset = 0, .tFormat = PL_VERTEX_FORMAT_FLOAT3}} + } + }, + .atBlendStates = { + pl__get_blend_state(PL_BLEND_MODE_OPAQUE) + }, + .tRenderPassLayout = gptData->tRenderPassLayout, + .uSubpassIndex = 2, + .atBindGroupLayouts = { + { + .atBufferBindings = { + { .uSlot = 0, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, + { .uSlot = 1, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, + { .uSlot = 2, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL} + }, + .atSamplerBindings = { + {.uSlot = 3, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, + {.uSlot = 4, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, + }, + .atTextureBindings = { + {.uSlot = 5, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED, .uDescriptorCount = 1}, + {.uSlot = 6, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED, .uDescriptorCount = 1}, + {.uSlot = 7, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED, .uDescriptorCount = 1} + } }, - .atSamplerBindings = { {.uSlot = 0, .tStages = PL_STAGE_COMPUTE}} + { + .atTextureBindings = { + { .uSlot = 0, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL} + }, + } } - } - }; - - typedef struct _FilterShaderSpecData{ - int resolution; - float u_roughness; - int u_sampleCount; - int u_width; - float u_lodBias; - int u_distribution; - int u_isGeneratingLUT; - int currentMipLevel; - } FilterShaderSpecData; - - FilterShaderSpecData tFilterData0 = { - .resolution = iResolution, - .u_roughness = 0.0f, - .u_width = iResolution, - .u_distribution = 0, - .u_lodBias = 0, - .u_sampleCount = iSamples, - .u_isGeneratingLUT = 0, - .currentMipLevel = 0, - }; - - FilterShaderSpecData tFilterDatas[16] = {0}; - - tFilterDatas[0].resolution = iResolution; - tFilterDatas[0].u_roughness = 0.0f; - tFilterDatas[0].u_width = iResolution; - tFilterDatas[0].u_distribution = 1; - tFilterDatas[0].u_lodBias = 1; - tFilterDatas[0].u_sampleCount = iSamples; - tFilterDatas[0].u_isGeneratingLUT = 1; - tFilterDatas[0].currentMipLevel = 0; - for(int i = 0; i < ptScene->iEnvironmentMips; i++) - { - int currentWidth = iResolution >> i; - tFilterDatas[i + 1].resolution = iResolution; - tFilterDatas[i + 1].u_roughness = (float)i / (float)(ptScene->iEnvironmentMips - 1); - tFilterDatas[i + 1].u_width = currentWidth; - tFilterDatas[i + 1].u_distribution = 1; - tFilterDatas[i + 1].u_lodBias = 1; - tFilterDatas[i + 1].u_sampleCount = iSamples; - tFilterDatas[i + 1].u_isGeneratingLUT = 0; - tFilterDatas[i + 1].currentMipLevel = i; - // tVariants[i+1].pTempConstantData = &tFilterDatas[i + 1]; + }; + gptData->tSkyboxShader = gptGfx->create_shader(gptData->ptDevice, &tSkyboxShaderDesc); } - tFilterComputeShaderDesc.pTempConstantData = &tFilterData0; - plComputeShaderHandle tIrradianceShader = gptGfx->create_compute_shader(ptDevice, &tFilterComputeShaderDesc); - - tFilterComputeShaderDesc.pTempConstantData = &tFilterDatas[0]; - plComputeShaderHandle tLUTShader = gptGfx->create_compute_shader(ptDevice, &tFilterComputeShaderDesc); - - plComputeShaderHandle atSpecularComputeShaders[16] = {0}; - for(int i = 0; i < ptScene->iEnvironmentMips + 1; i++) - { - tFilterComputeShaderDesc.pTempConstantData = &tFilterDatas[i + 1]; - atSpecularComputeShaders[i] = gptGfx->create_compute_shader(ptDevice, &tFilterComputeShaderDesc); - } - pl_temp_allocator_reset(&gptData->tTempAllocator); + int iPanoramaWidth = 0; + int iPanoramaHeight = 0; + int iUnused = 0; + pl_begin_cpu_sample(gptProfile, 0, "load image"); + size_t szImageFileSize = 0; + gptFile->binary_read(pcPath, &szImageFileSize, NULL); + unsigned char* pucBuffer = PL_ALLOC(szImageFileSize); + gptFile->binary_read(pcPath, &szImageFileSize, pucBuffer); + float* pfPanoramaData = gptImage->load_hdr(pucBuffer, (int)szImageFileSize, &iPanoramaWidth, &iPanoramaHeight, &iUnused, 4); + PL_FREE(pucBuffer); pl_end_cpu_sample(gptProfile, 0); + PL_ASSERT(pfPanoramaData); - // create lut - + const size_t uFaceSize = ((size_t)iResolution * (size_t)iResolution) * 4 * sizeof(float); { - - pl_begin_cpu_sample(gptProfile, 0, "step 2"); - plBufferHandle atLutBuffers[7] = {0}; - const plBufferDesc tInputBufferDesc = { - .tUsage = PL_BUFFER_USAGE_STORAGE | PL_BUFFER_USAGE_STAGING, - .szByteSize = uFaceSize, - .pcDebugName = "lut output buffer" + int aiSkyboxSpecializationData[] = {iResolution, iPanoramaWidth, iPanoramaHeight}; + const plComputeShaderDesc tSkyboxComputeShaderDesc = { + .tShader = gptShader->load_glsl("../shaders/panorama_to_cubemap.comp", "main", NULL, NULL), + .pTempConstantData = aiSkyboxSpecializationData, + .atConstants = { + { .uID = 0, .uOffset = 0, .tType = PL_DATA_TYPE_INT}, + { .uID = 1, .uOffset = sizeof(int), .tType = PL_DATA_TYPE_INT}, + { .uID = 2, .uOffset = 2 * sizeof(int), .tType = PL_DATA_TYPE_INT} + }, + .atBindGroupLayouts = { + { + .atBufferBindings = { + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 0, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 1, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 2, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 3, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 4, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 5, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 6, .tStages = PL_STAGE_COMPUTE}, + } + } + } }; - atLutBuffers[6] = pl__refr_create_staging_buffer(&tInputBufferDesc, "lut output", 0); - - for(uint32_t i = 0; i < 6; i++) - atLutBuffers[i] = pl__refr_create_local_buffer(&tInputBufferDesc, "lut output", i, NULL); - - const plBindGroupDesc tFilterBindGroupDesc = { - .ptPool = gptData->aptTempGroupPools[gptGfx->get_current_frame_index()], - .ptLayout = &tFilterComputeShaderDesc.atBindGroupLayouts[0], - .pcDebugName = "lut bind group" - }; - plBindGroupHandle tLutBindGroup = gptGfx->create_bind_group(ptDevice, &tFilterBindGroupDesc); - const plBindGroupUpdateBufferData atBGBufferData[] = { - { .uSlot = 2, .tBuffer = atLutBuffers[0], .szBufferRange = uFaceSize}, - { .uSlot = 3, .tBuffer = atLutBuffers[1], .szBufferRange = uFaceSize}, - { .uSlot = 4, .tBuffer = atLutBuffers[2], .szBufferRange = uFaceSize}, - { .uSlot = 5, .tBuffer = atLutBuffers[3], .szBufferRange = uFaceSize}, - { .uSlot = 6, .tBuffer = atLutBuffers[4], .szBufferRange = uFaceSize}, - { .uSlot = 7, .tBuffer = atLutBuffers[5], .szBufferRange = uFaceSize}, - { .uSlot = 8, .tBuffer = atLutBuffers[6], .szBufferRange = uFaceSize}, - }; - - const plBindGroupUpdateSamplerData tSamplerData = { - .tSampler = gptData->tDefaultSampler, - .uSlot = 0 - }; - const plBindGroupUpdateTextureData tTextureData = { - .tTexture = ptScene->tSkyboxTexture, - .uSlot = 1, - .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED - }; - const plBindGroupUpdateData tBGData = { - .uBufferCount = 7, - .atBufferBindings = atBGBufferData, - .uSamplerCount = 1, - .atSamplerBindings = &tSamplerData, - .uTextureCount = 1, - .atTextureBindings = &tTextureData - }; - gptGfx->update_bind_group(ptDevice, tLutBindGroup, &tBGData); - gptGfx->queue_bind_group_for_deletion(ptDevice, tLutBindGroup); - - const plDispatch tDispach = { - .uGroupCountX = (uint32_t)iResolution / 16, - .uGroupCountY = (uint32_t)iResolution / 16, - .uGroupCountZ = 3, - .uThreadPerGroupX = 16, - .uThreadPerGroupY = 16, - .uThreadPerGroupZ = 3 - }; - pl_end_cpu_sample(gptProfile, 0); - - pl_begin_cpu_sample(gptProfile, 0, "step 3"); - plBuffer* ptLutBuffer = gptGfx->get_buffer(ptDevice, atLutBuffers[6]); - memset(ptLutBuffer->tMemoryAllocation.pHostMapped, 0, uFaceSize); - plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, NULL); - - const plPassBufferResource atPassBuffers[] = { - { .tHandle = atLutBuffers[0], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, - { .tHandle = atLutBuffers[1], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, - { .tHandle = atLutBuffers[2], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, - { .tHandle = atLutBuffers[3], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, - { .tHandle = atLutBuffers[4], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, - { .tHandle = atLutBuffers[5], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, - { .tHandle = atLutBuffers[6], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, - }; - - const plPassResources tPassResources = { - .uBufferCount = 7, - .atBuffers = atPassBuffers - }; - - plComputeEncoder* ptComputeEncoder = gptGfx->begin_compute_pass(ptCommandBuffer, &tPassResources); - gptGfx->pipeline_barrier_compute(ptComputeEncoder, PL_STAGE_VERTEX | PL_STAGE_COMPUTE, PL_ACCESS_SHADER_READ, PL_STAGE_COMPUTE, PL_ACCESS_SHADER_WRITE); - gptGfx->bind_compute_bind_groups(ptComputeEncoder, tLUTShader, 0, 1, &tLutBindGroup, 0, NULL); - gptGfx->bind_compute_shader(ptComputeEncoder, tLUTShader); - gptGfx->dispatch(ptComputeEncoder, 1, &tDispach); - gptGfx->pipeline_barrier_compute(ptComputeEncoder, PL_STAGE_COMPUTE, PL_ACCESS_SHADER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE, PL_ACCESS_SHADER_READ); - gptGfx->end_compute_pass(ptComputeEncoder); - gptGfx->end_command_recording(ptCommandBuffer); - gptGfx->submit_command_buffer(ptCommandBuffer, NULL); - gptGfx->wait_on_command_buffer(ptCommandBuffer); - gptGfx->return_command_buffer(ptCommandBuffer); - gptGfx->queue_compute_shader_for_deletion(ptDevice, tLUTShader); - - const plTextureDesc tTextureDesc = { - .tDimensions = {(float)iResolution, (float)iResolution, 1}, - .tFormat = PL_FORMAT_R32G32B32A32_FLOAT, - .uLayers = 1, - .uMips = 1, - .tType = PL_TEXTURE_TYPE_2D, - .tUsage = PL_TEXTURE_USAGE_SAMPLED - }; - ptScene->tGGXLUTTexture = pl__refr_create_texture_with_data(&tTextureDesc, "lut texture", 0, ptLutBuffer->tMemoryAllocation.pHostMapped, uFaceSize); - pl_end_cpu_sample(gptProfile, 0); - - pl_begin_cpu_sample(gptProfile, 0, "step 4"); - ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, NULL); - ptComputeEncoder = gptGfx->begin_compute_pass(ptCommandBuffer, &tPassResources); - gptGfx->pipeline_barrier_compute(ptComputeEncoder, PL_STAGE_VERTEX | PL_STAGE_COMPUTE, PL_ACCESS_SHADER_READ, PL_STAGE_COMPUTE, PL_ACCESS_SHADER_WRITE); - gptGfx->bind_compute_bind_groups(ptComputeEncoder, tIrradianceShader, 0, 1, &tLutBindGroup, 0, NULL); - gptGfx->bind_compute_shader(ptComputeEncoder, tIrradianceShader); - gptGfx->dispatch(ptComputeEncoder, 1, &tDispach); - gptGfx->pipeline_barrier_compute(ptComputeEncoder, PL_STAGE_COMPUTE, PL_ACCESS_SHADER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE, PL_ACCESS_SHADER_READ); - gptGfx->end_compute_pass(ptComputeEncoder); - gptGfx->end_command_recording(ptCommandBuffer); - gptGfx->submit_command_buffer(ptCommandBuffer, NULL); - gptGfx->wait_on_command_buffer(ptCommandBuffer); - gptGfx->return_command_buffer(ptCommandBuffer); - gptGfx->queue_compute_shader_for_deletion(ptDevice, tIrradianceShader); - - const plTextureDesc tSpecularTextureDesc = { - .tDimensions = {(float)iResolution, (float)iResolution, 1}, - .tFormat = PL_FORMAT_R32G32B32A32_FLOAT, - .uLayers = 6, - .uMips = 1, - .tType = PL_TEXTURE_TYPE_CUBE, - .tUsage = PL_TEXTURE_USAGE_SAMPLED - }; - ptScene->tLambertianEnvTexture = pl__refr_create_texture(&tSpecularTextureDesc, "specular texture", uSceneHandle, PL_TEXTURE_USAGE_SAMPLED); - - ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, NULL); - plBlitEncoder* ptBlitEncoder = gptGfx->begin_blit_pass(ptCommandBuffer); - gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE); - - for(uint32_t i = 0; i < 6; i++) - { - const plBufferImageCopy tBufferImageCopy = { - .uImageWidth = iResolution, - .uImageHeight = iResolution, - .uImageDepth = 1, - .uLayerCount = 1, - .szBufferOffset = 0, - .uBaseArrayLayer = i, - }; - gptGfx->copy_buffer_to_texture(ptBlitEncoder, atLutBuffers[i], ptScene->tLambertianEnvTexture, 1, &tBufferImageCopy); - } - gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ); - gptGfx->end_blit_pass(ptBlitEncoder); - gptGfx->end_command_recording(ptCommandBuffer); - gptGfx->submit_command_buffer(ptCommandBuffer, NULL); - gptGfx->wait_on_command_buffer(ptCommandBuffer); - gptGfx->return_command_buffer(ptCommandBuffer); - - for(uint32_t i = 0; i < 7; i++) - gptGfx->destroy_buffer(ptDevice, atLutBuffers[i]); - pl_end_cpu_sample(gptProfile, 0); - } - - - pl_begin_cpu_sample(gptProfile, 0, "step 5"); - { - const plTextureDesc tTextureDesc = { - .tDimensions = {(float)iResolution, (float)iResolution, 1}, - .tFormat = PL_FORMAT_R32G32B32A32_FLOAT, - .uLayers = 6, - .uMips = ptScene->iEnvironmentMips, - .tType = PL_TEXTURE_TYPE_CUBE, - .tUsage = PL_TEXTURE_USAGE_SAMPLED - }; - ptScene->tGGXEnvTexture = pl__refr_create_texture(&tTextureDesc, "tGGXEnvTexture", uSceneHandle, PL_TEXTURE_USAGE_SAMPLED); - - const plBindGroupUpdateSamplerData tSamplerData = { - .tSampler = gptData->tDefaultSampler, - .uSlot = 0 - }; - const plBindGroupUpdateTextureData tTextureData = { - .tTexture = ptScene->tSkyboxTexture, - .uSlot = 1, - .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED - }; - - const size_t uMaxFaceSize = (size_t)iResolution * (size_t)iResolution * 4 * sizeof(float); - - static const char* apcBufferNames[] = { - "output buffer 0", - "output buffer 1", - "output buffer 2", - "output buffer 3", - "output buffer 4", - "output buffer 5", - "output buffer 6" - }; - - plBufferHandle atInnerComputeBuffers[7] = {0}; - for(uint32_t j = 0; j < 7; j++) - { - const plBufferDesc tOutputBufferDesc = { - .tUsage = PL_BUFFER_USAGE_STORAGE, - .szByteSize = uMaxFaceSize, - .pcDebugName = apcBufferNames[j] - }; - atInnerComputeBuffers[j] = pl__refr_create_local_buffer(&tOutputBufferDesc, "inner buffer", j, NULL); - } - - const plBindGroupDesc tFilterComputeBindGroupDesc = { - .ptPool = gptData->aptTempGroupPools[gptGfx->get_current_frame_index()], - .ptLayout = &tFilterComputeShaderDesc.atBindGroupLayouts[0], - .pcDebugName = "lut bindgroup" - }; - plBindGroupHandle tLutBindGroup = gptGfx->create_bind_group(ptDevice, &tFilterComputeBindGroupDesc); - - const plBindGroupUpdateBufferData atBGBufferData[] = { - { .uSlot = 2, .tBuffer = atInnerComputeBuffers[0], .szBufferRange = uMaxFaceSize}, - { .uSlot = 3, .tBuffer = atInnerComputeBuffers[1], .szBufferRange = uMaxFaceSize}, - { .uSlot = 4, .tBuffer = atInnerComputeBuffers[2], .szBufferRange = uMaxFaceSize}, - { .uSlot = 5, .tBuffer = atInnerComputeBuffers[3], .szBufferRange = uMaxFaceSize}, - { .uSlot = 6, .tBuffer = atInnerComputeBuffers[4], .szBufferRange = uMaxFaceSize}, - { .uSlot = 7, .tBuffer = atInnerComputeBuffers[5], .szBufferRange = uMaxFaceSize}, - { .uSlot = 8, .tBuffer = atInnerComputeBuffers[6], .szBufferRange = uMaxFaceSize} - }; - - const plBindGroupUpdateData tBGData = { - .uBufferCount = 7, - .atBufferBindings = atBGBufferData, - .uSamplerCount = 1, - .atSamplerBindings = &tSamplerData, - .uTextureCount = 1, - .atTextureBindings = &tTextureData - }; - gptGfx->update_bind_group(ptDevice, tLutBindGroup, &tBGData); - gptGfx->queue_bind_group_for_deletion(ptDevice, tLutBindGroup); - - for (int i = ptScene->iEnvironmentMips - 1; i != -1; i--) - { - int currentWidth = iResolution >> i; - - // const size_t uCurrentFaceSize = (size_t)currentWidth * (size_t)currentWidth * 4 * sizeof(float); - - const plDispatch tDispach = { - .uGroupCountX = (uint32_t)currentWidth / 16, - .uGroupCountY = (uint32_t)currentWidth / 16, - .uGroupCountZ = 2, - .uThreadPerGroupX = 16, - .uThreadPerGroupY = 16, - .uThreadPerGroupZ = 3 - }; - - plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, NULL); - - const plPassBufferResource atInnerPassBuffers[] = { - { .tHandle = atInnerComputeBuffers[0], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, - { .tHandle = atInnerComputeBuffers[1], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, - { .tHandle = atInnerComputeBuffers[2], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, - { .tHandle = atInnerComputeBuffers[3], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, - { .tHandle = atInnerComputeBuffers[4], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, - { .tHandle = atInnerComputeBuffers[5], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, - { .tHandle = atInnerComputeBuffers[6], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, - }; - - const plPassResources tInnerPassResources = { - .uBufferCount = 7, - .atBuffers = atInnerPassBuffers - }; - - plComputeEncoder* ptComputeEncoder = gptGfx->begin_compute_pass(ptCommandBuffer, &tInnerPassResources); - gptGfx->pipeline_barrier_compute(ptComputeEncoder, PL_STAGE_VERTEX | PL_STAGE_COMPUTE, PL_ACCESS_SHADER_READ, PL_STAGE_COMPUTE, PL_ACCESS_SHADER_WRITE); - gptGfx->bind_compute_bind_groups(ptComputeEncoder, atSpecularComputeShaders[i], 0, 1, &tLutBindGroup, 0, NULL); - gptGfx->bind_compute_shader(ptComputeEncoder, atSpecularComputeShaders[i]); - gptGfx->dispatch(ptComputeEncoder, 1, &tDispach); - gptGfx->pipeline_barrier_compute(ptComputeEncoder, PL_STAGE_COMPUTE, PL_ACCESS_SHADER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE, PL_ACCESS_SHADER_READ); - gptGfx->end_compute_pass(ptComputeEncoder); - gptGfx->end_command_recording(ptCommandBuffer); - gptGfx->submit_command_buffer(ptCommandBuffer, NULL); - gptGfx->wait_on_command_buffer(ptCommandBuffer); - gptGfx->return_command_buffer(ptCommandBuffer); - gptGfx->queue_compute_shader_for_deletion(ptDevice, atSpecularComputeShaders[i]); - - ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, NULL); - plBlitEncoder* ptBlitEncoder = gptGfx->begin_blit_pass(ptCommandBuffer); - gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE); - - for(uint32_t j = 0; j < 6; j++) - { - const plBufferImageCopy tBufferImageCopy = { - .uImageWidth = currentWidth, - .uImageHeight = currentWidth, - .uImageDepth = 1, - .uLayerCount = 1, - .szBufferOffset = 0, - .uBaseArrayLayer = j, - .uMipLevel = i - }; - gptGfx->copy_buffer_to_texture(ptBlitEncoder, atInnerComputeBuffers[j], ptScene->tGGXEnvTexture, 1, &tBufferImageCopy); - } - gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ); - gptGfx->end_blit_pass(ptBlitEncoder); - gptGfx->end_command_recording(ptCommandBuffer); - gptGfx->submit_command_buffer(ptCommandBuffer, NULL); - gptGfx->wait_on_command_buffer(ptCommandBuffer); - gptGfx->return_command_buffer(ptCommandBuffer); - - } - for(uint32_t j = 0; j < 7; j++) - gptGfx->queue_buffer_for_deletion(ptDevice, atInnerComputeBuffers[j]); - } - - ptScene->uGGXLUT = pl__get_bindless_texture_index(uSceneHandle, ptScene->tGGXLUTTexture); - ptScene->uLambertianEnvSampler = pl__get_bindless_cube_texture_index(uSceneHandle, ptScene->tLambertianEnvTexture); - ptScene->uGGXEnvSampler = pl__get_bindless_cube_texture_index(uSceneHandle, ptScene->tGGXEnvTexture); - - pl_end_cpu_sample(gptProfile, 0); - pl_end_cpu_sample(gptProfile, 0); -} - -static void -pl_refr_load_skybox_from_panorama(uint32_t uSceneHandle, const char* pcPath, int iResolution) -{ - pl_begin_cpu_sample(gptProfile, 0, __FUNCTION__); - const int iSamples = 512; - plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; - plDevice* ptDevice = gptData->ptDevice; - plCommandPool* ptCmdPool = gptData->atCmdPools[gptGfx->get_current_frame_index()]; - - // create skybox shader if we haven't - if(gptData->tSkyboxShader.uIndex == 0) - { - // create skybox shader - plShaderDesc tSkyboxShaderDesc = { - .tPixelShader = gptShader->load_glsl("../shaders/skybox.frag", "main", NULL, NULL), - .tVertexShader = gptShader->load_glsl("../shaders/skybox.vert", "main", NULL, NULL), - .tGraphicsState = { - .ulDepthWriteEnabled = 0, - .ulDepthMode = PL_COMPARE_MODE_EQUAL, - .ulCullMode = PL_CULL_MODE_NONE, - .ulStencilMode = PL_COMPARE_MODE_ALWAYS, - .ulStencilRef = 0xff, - .ulStencilMask = 0xff, - .ulStencilOpFail = PL_STENCIL_OP_KEEP, - .ulStencilOpDepthFail = PL_STENCIL_OP_KEEP, - .ulStencilOpPass = PL_STENCIL_OP_KEEP - }, - .atVertexBufferLayouts = { - { - .uByteStride = sizeof(float) * 3, - .atAttributes = { {.uByteOffset = 0, .tFormat = PL_VERTEX_FORMAT_FLOAT3}} - } - }, - .atBlendStates = { - pl__get_blend_state(PL_BLEND_MODE_OPAQUE) - }, - .tRenderPassLayout = gptData->tRenderPassLayout, - .uSubpassIndex = 2, - .atBindGroupLayouts = { - { - .atBufferBindings = { - { .uSlot = 0, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, - { .uSlot = 1, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, - { .uSlot = 2, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL} - }, - .atSamplerBindings = { - {.uSlot = 3, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, - {.uSlot = 4, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, - }, - .atTextureBindings = { - {.uSlot = 5, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED, .uDescriptorCount = 1}, - {.uSlot = 6, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED, .uDescriptorCount = 1}, - {.uSlot = 7, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED, .uDescriptorCount = 1} - } - }, - { - .atTextureBindings = { - { .uSlot = 0, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL} - }, - } - } - }; - gptData->tSkyboxShader = gptGfx->create_shader(gptData->ptDevice, &tSkyboxShaderDesc); - } - - int iPanoramaWidth = 0; - int iPanoramaHeight = 0; - int iUnused = 0; - pl_begin_cpu_sample(gptProfile, 0, "load image"); - size_t szImageFileSize = 0; - gptFile->binary_read(pcPath, &szImageFileSize, NULL); - unsigned char* pucBuffer = PL_ALLOC(szImageFileSize); - gptFile->binary_read(pcPath, &szImageFileSize, pucBuffer); - float* pfPanoramaData = gptImage->load_hdr(pucBuffer, (int)szImageFileSize, &iPanoramaWidth, &iPanoramaHeight, &iUnused, 4); - PL_FREE(pucBuffer); - pl_end_cpu_sample(gptProfile, 0); - PL_ASSERT(pfPanoramaData); - - ptScene->iEnvironmentMips = (uint32_t)floorf(log2f((float)pl_maxi(iResolution, iResolution))) - 3; // guarantee final dispatch during filtering is 16 threads - - const size_t uFaceSize = ((size_t)iResolution * (size_t)iResolution) * 4 * sizeof(float); - - { - int aiSkyboxSpecializationData[] = {iResolution, iPanoramaWidth, iPanoramaHeight}; - const plComputeShaderDesc tSkyboxComputeShaderDesc = { - .tShader = gptShader->load_glsl("../shaders/panorama_to_cubemap.comp", "main", NULL, NULL), - .pTempConstantData = aiSkyboxSpecializationData, - .atConstants = { - { .uID = 0, .uOffset = 0, .tType = PL_DATA_TYPE_INT}, - { .uID = 1, .uOffset = sizeof(int), .tType = PL_DATA_TYPE_INT}, - { .uID = 2, .uOffset = 2 * sizeof(int), .tType = PL_DATA_TYPE_INT} - }, - .atBindGroupLayouts = { - { - .atBufferBindings = { - { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 0, .tStages = PL_STAGE_COMPUTE}, - { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 1, .tStages = PL_STAGE_COMPUTE}, - { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 2, .tStages = PL_STAGE_COMPUTE}, - { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 3, .tStages = PL_STAGE_COMPUTE}, - { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 4, .tStages = PL_STAGE_COMPUTE}, - { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 5, .tStages = PL_STAGE_COMPUTE}, - { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 6, .tStages = PL_STAGE_COMPUTE}, - } - } - } - }; - plComputeShaderHandle tPanoramaShader = gptGfx->create_compute_shader(ptDevice, &tSkyboxComputeShaderDesc); - pl_temp_allocator_reset(&gptData->tTempAllocator); + plComputeShaderHandle tPanoramaShader = gptGfx->create_compute_shader(ptDevice, &tSkyboxComputeShaderDesc); + pl_temp_allocator_reset(&gptData->tTempAllocator); plBufferHandle atComputeBuffers[7] = {0}; const uint32_t uPanoramaSize = iPanoramaHeight * iPanoramaWidth * 4 * sizeof(float); @@ -1867,6 +1506,9 @@ pl_refr_load_skybox_from_panorama(uint32_t uSceneHandle, const char* pcPath, int }; gptGfx->copy_buffer_to_texture(ptBlitEncoder, atComputeBuffers[i + 1], ptScene->tSkyboxTexture, 1, &tBufferImageCopy); } + + gptGfx->generate_mipmaps(ptBlitEncoder, ptScene->tSkyboxTexture); + gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ); gptGfx->end_blit_pass(ptBlitEncoder); gptGfx->end_command_recording(ptCommandBuffer); @@ -1887,12 +1529,15 @@ pl_refr_load_skybox_from_panorama(uint32_t uSceneHandle, const char* pcPath, int .pcDebugName = "skybox bind group" }; ptScene->tSkyboxBindGroup = gptGfx->create_bind_group(ptDevice, &tSkyboxBindGroupDesc); - const plBindGroupUpdateTextureData tTextureData1 = {.tTexture = ptScene->tSkyboxTexture, .uSlot = 0, .uIndex = 0, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED}; - const plBindGroupUpdateData tBGData1 = { - .uTextureCount = 1, - .atTextureBindings = &tTextureData1 - }; - gptGfx->update_bind_group(ptDevice, ptScene->tSkyboxBindGroup, &tBGData1); + + { + const plBindGroupUpdateTextureData tTextureData1 = {.tTexture = ptScene->tSkyboxTexture, .uSlot = 0, .uIndex = 0, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED}; + const plBindGroupUpdateData tBGData1 = { + .uTextureCount = 1, + .atTextureBindings = &tTextureData1 + }; + gptGfx->update_bind_group(ptDevice, ptScene->tSkyboxBindGroup, &tBGData1); + } const uint32_t uStartIndex = pl_sb_size(ptScene->sbtVertexPosBuffer); const uint32_t uIndexStart = pl_sb_size(ptScene->sbuIndexBuffer); @@ -1969,14 +1614,16 @@ static void pl_refr_select_entities(uint32_t uSceneHandle, uint32_t uCount, plEntity* atEntities) { // for convience - plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; - plDevice* ptDevice = gptData->ptDevice; + plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; + plDevice* ptDevice = gptData->ptDevice; if(uCount == 0) gptData->tPickedEntity = (plEntity){.ulData = UINT64_MAX}; - int iSceneWideRenderingFlags = PL_RENDERING_FLAG_USE_PUNCTUAL; - if(ptScene->tGGXEnvTexture.uIndex != 0 && gptData->bImageBasedLighting) + int iSceneWideRenderingFlags = 0; + if(gptData->bPunctualLighting) + iSceneWideRenderingFlags |= PL_RENDERING_FLAG_USE_PUNCTUAL; + if(gptData->bImageBasedLighting) iSceneWideRenderingFlags |= PL_RENDERING_FLAG_USE_IBL; // reset old entities @@ -2005,13 +1652,20 @@ pl_refr_select_entities(uint32_t uSceneHandle, uint32_t uCount, plEntity* atEnti iTextureMappingFlags |= 1 << j; } + int iObjectRenderingFlags = iSceneWideRenderingFlags; + + if(ptMaterial->tFlags & PL_MATERIAL_FLAG_CAST_RECEIVE_SHADOW) + { + iObjectRenderingFlags |= PL_RENDERING_FLAG_SHADOWS; + } + // choose shader variant int aiConstantData0[5] = { (int)ptMesh->ulVertexStreamMask, iDataStride, iTextureMappingFlags, PL_INFO_MATERIAL_METALLICROUGHNESS, - iSceneWideRenderingFlags + iObjectRenderingFlags }; // use stencil buffer @@ -2049,20 +1703,21 @@ pl_refr_select_entities(uint32_t uSceneHandle, uint32_t uCount, plEntity* atEnti uint64_t ulIndex = pl_hm_lookup(ptScene->ptDeferredHashmap, tEntity.ulData); plDrawable* ptDrawable = &ptScene->sbtDeferredDrawables[ulIndex]; ptDrawable->tShader = ptScene->sbtOutlineDrawablesOldShaders[i]; + ptDrawable->tEnvShader = ptScene->sbtOutlineDrawablesOldEnvShaders[i]; } else if(pl_hm_has_key(ptScene->ptForwardHashmap, tEntity.ulData)) { uint64_t ulIndex = pl_hm_lookup(ptScene->ptForwardHashmap, tEntity.ulData); plDrawable* ptDrawable = &ptScene->sbtForwardDrawables[ulIndex]; ptDrawable->tShader = ptScene->sbtOutlineDrawablesOldShaders[i]; + ptDrawable->tEnvShader = ptScene->sbtOutlineDrawablesOldEnvShaders[i]; } // gptGfx->queue_shader_for_deletion(ptDevice, ptScene->sbtOutlineDrawables[i].tShader); } - pl_sb_reset(ptScene->sbtOutlineDrawables) - pl_sb_reset(ptScene->sbtOutlineDrawablesOldShaders) - - + pl_sb_reset(ptScene->sbtOutlineDrawables); + pl_sb_reset(ptScene->sbtOutlineDrawablesOldShaders); + pl_sb_reset(ptScene->sbtOutlineDrawablesOldEnvShaders); for(uint32_t i = 0; i < uCount; i++) { @@ -2093,13 +1748,20 @@ pl_refr_select_entities(uint32_t uSceneHandle, uint32_t uCount, plEntity* atEnti iTextureMappingFlags |= 1 << j; } + int iObjectRenderingFlags = iSceneWideRenderingFlags; + + if(ptMaterial->tFlags & PL_MATERIAL_FLAG_CAST_RECEIVE_SHADOW) + { + iObjectRenderingFlags |= PL_RENDERING_FLAG_SHADOWS; + } + // choose shader variant int aiConstantData0[] = { (int)ptMesh->ulVertexStreamMask, iDataStride, iTextureMappingFlags, PL_INFO_MATERIAL_METALLICROUGHNESS, - iSceneWideRenderingFlags, + iObjectRenderingFlags, pl_sb_capacity(ptScene->sbtDLightData), pl_sb_capacity(ptScene->sbtPLightData), pl_sb_capacity(ptScene->sbtSLightData) @@ -2151,6 +1813,7 @@ pl_refr_select_entities(uint32_t uSceneHandle, uint32_t uCount, plEntity* atEnti }; pl_sb_push(ptScene->sbtOutlineDrawablesOldShaders, ptDrawable->tShader); + pl_sb_push(ptScene->sbtOutlineDrawablesOldEnvShaders, ptDrawable->tEnvShader); ptDrawable->tShader = pl__get_shader_variant(uSceneHandle, gptData->tDeferredShader, &tVariant); } else if(pl_hm_has_key(ptScene->ptForwardHashmap, tEntity.ulData)) @@ -2199,6 +1862,7 @@ pl_refr_select_entities(uint32_t uSceneHandle, uint32_t uCount, plEntity* atEnti }; pl_sb_push(ptScene->sbtOutlineDrawablesOldShaders, ptDrawable->tShader); + pl_sb_push(ptScene->sbtOutlineDrawablesOldEnvShaders, ptDrawable->tEnvShader); ptDrawable->tShader = pl__get_shader_variant(uSceneHandle, gptData->tForwardShader, &tVariant); } } @@ -2213,6 +1877,10 @@ pl_refr_reload_scene_shaders(uint32_t uSceneHandle) // fill CPU buffers & drawable list pl_begin_cpu_sample(gptProfile, 0, "recreate shaders"); + pl_sb_reset(ptScene->sbtOutlineDrawables); + pl_sb_reset(ptScene->sbtOutlineDrawablesOldShaders); + pl_sb_reset(ptScene->sbtOutlineDrawablesOldEnvShaders); + // old cleanup for(uint32_t i = 0; i < pl_sb_size(gptData->_sbtVariantHandles); i++) { @@ -2231,11 +1899,15 @@ pl_refr_reload_scene_shaders(uint32_t uSceneHandle) gptGfx->queue_shader_for_deletion(gptData->ptDevice, gptData->tSkyboxShader); gptGfx->queue_shader_for_deletion(gptData->ptDevice, ptScene->tLightingShader); gptGfx->queue_shader_for_deletion(gptData->ptDevice, ptScene->tTonemapShader); + gptGfx->queue_shader_for_deletion(gptData->ptDevice, ptScene->tEnvLightingShader); + gptGfx->queue_compute_shader_for_deletion(gptData->ptDevice, gptData->tEnvFilterShader); pl_refr_create_global_shaders(); - int iSceneWideRenderingFlags = PL_RENDERING_FLAG_USE_PUNCTUAL; - if(ptScene->tGGXEnvTexture.uIndex != 0 && gptData->bImageBasedLighting) + int iSceneWideRenderingFlags = 0; + if(gptData->bPunctualLighting) + iSceneWideRenderingFlags |= PL_RENDERING_FLAG_USE_PUNCTUAL; + if(gptData->bImageBasedLighting) iSceneWideRenderingFlags |= PL_RENDERING_FLAG_USE_IBL; // create lighting shader @@ -2305,7 +1977,7 @@ pl_refr_reload_scene_shaders(uint32_t uSceneHandle) }, { .atBufferBindings = { - { .uSlot = 0, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, + { .uSlot = 0, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, { .uSlot = 1, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, { .uSlot = 2, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, { .uSlot = 3, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, @@ -2326,6 +1998,8 @@ pl_refr_reload_scene_shaders(uint32_t uSceneHandle) tLightingShaderDesc.atConstants[i].tType = PL_DATA_TYPE_INT; } ptScene->tLightingShader = gptGfx->create_shader(gptData->ptDevice, &tLightingShaderDesc); + aiLightingConstantData[0] = gptData->bPunctualLighting ? PL_RENDERING_FLAG_USE_PUNCTUAL : 0; + ptScene->tEnvLightingShader = gptGfx->create_shader(gptData->ptDevice, &tLightingShaderDesc); } const plShaderDesc tTonemapShaderDesc = { @@ -2369,139 +2043,7 @@ pl_refr_reload_scene_shaders(uint32_t uSceneHandle) }; ptScene->tTonemapShader = gptGfx->create_shader(gptData->ptDevice, &tTonemapShaderDesc); - plHashMap* ptMaterialBindGroupDict = {0}; - plBindGroupHandle* sbtMaterialBindGroups = NULL; - plMaterialComponent* sbtMaterials = ptScene->tComponentLibrary.tMaterialComponentManager.pComponents; - const uint32_t uMaterialCount = pl_sb_size(sbtMaterials); - pl_sb_resize(sbtMaterialBindGroups, uMaterialCount); - - for(uint32_t i = 0; i < uMaterialCount; i++) - { - plMaterialComponent* ptMaterial = &sbtMaterials[i]; - pl_hm_insert(ptMaterialBindGroupDict, (uint64_t)ptMaterial, (uint64_t)i); - } - - plDrawable* sbtDrawables[] = { - ptScene->sbtDeferredDrawables, - ptScene->sbtForwardDrawables, - }; - - plShaderHandle atTemplateShaders[] = { - gptData->tDeferredShader, - gptData->tForwardShader - }; - - plShaderHandle atTemplateShadowShaders[] = { - gptData->tShadowShader, - gptData->tAlphaShadowShader - }; - - plGraphicsState atTemplateVariants[] = { - { - .ulDepthWriteEnabled = 1, - .ulDepthMode = PL_COMPARE_MODE_GREATER, - .ulCullMode = PL_CULL_MODE_CULL_BACK, - .ulStencilMode = PL_COMPARE_MODE_ALWAYS, - .ulStencilRef = 0xff, - .ulStencilMask = 0xff, - .ulStencilOpFail = PL_STENCIL_OP_KEEP, - .ulStencilOpDepthFail = PL_STENCIL_OP_KEEP, - .ulStencilOpPass = PL_STENCIL_OP_KEEP, - .ulWireframe = gptData->bWireframe - }, - { - .ulDepthWriteEnabled = 1, - .ulDepthMode = PL_COMPARE_MODE_GREATER_OR_EQUAL, - .ulCullMode = PL_CULL_MODE_NONE, - .ulStencilMode = PL_COMPARE_MODE_ALWAYS, - .ulStencilRef = 0xff, - .ulStencilMask = 0xff, - .ulStencilOpFail = PL_STENCIL_OP_KEEP, - .ulStencilOpDepthFail = PL_STENCIL_OP_KEEP, - .ulStencilOpPass = PL_STENCIL_OP_KEEP, - .ulWireframe = gptData->bWireframe - } - }; - - for(uint32_t uDrawableBatchIndex = 0; uDrawableBatchIndex < 2; uDrawableBatchIndex++) - { - const uint32_t uDrawableCount = pl_sb_size(sbtDrawables[uDrawableBatchIndex]); - for(uint32_t i = 0; i < uDrawableCount; i++) - { - - plEntity tEntity = (sbtDrawables[uDrawableBatchIndex])[i].tEntity; - - // get actual components - plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tEntity); - plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptObject->tMesh); - plMaterialComponent* ptMaterial = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MATERIAL, ptMesh->tMaterial); - - - const uint64_t ulMaterialIndex = pl_hm_lookup(ptMaterialBindGroupDict, (uint64_t)ptMaterial); - - int iDataStride = 0; - int iFlagCopy0 = (int)ptMesh->ulVertexStreamMask; - while(iFlagCopy0) - { - iDataStride += iFlagCopy0 & 1; - iFlagCopy0 >>= 1; - } - - int iTextureMappingFlags = 0; - for(uint32_t j = 0; j < PL_TEXTURE_SLOT_COUNT; j++) - { - if((ptMaterial->atTextureMaps[j].acName[0] != 0)) - iTextureMappingFlags |= 1 << j; - } - - // choose shader variant - int aiConstantData0[] = { - (int)ptMesh->ulVertexStreamMask, - iDataStride, - iTextureMappingFlags, - PL_INFO_MATERIAL_METALLICROUGHNESS, - iSceneWideRenderingFlags, - pl_sb_capacity(ptScene->sbtDLightData), - pl_sb_capacity(ptScene->sbtPLightData), - pl_sb_capacity(ptScene->sbtSLightData) - }; - - plGraphicsState tVariantTemp = atTemplateVariants[uDrawableBatchIndex]; - - if(ptMaterial->tFlags & PL_MATERIAL_FLAG_DOUBLE_SIDED) - tVariantTemp.ulCullMode = PL_CULL_MODE_NONE; - - const plShaderVariant tVariant = { - .pTempConstantData = aiConstantData0, - .tGraphicsState = tVariantTemp - }; - - (sbtDrawables[uDrawableBatchIndex])[i].tShader = pl__get_shader_variant(uSceneHandle, atTemplateShaders[uDrawableBatchIndex], &tVariant); - - if(uDrawableBatchIndex > 0) - { - const plShaderVariant tShadowVariant = { - .pTempConstantData = aiConstantData0, - .tGraphicsState = { - .ulDepthWriteEnabled = 1, - .ulDepthClampEnabled = 1, - .ulDepthMode = PL_COMPARE_MODE_GREATER_OR_EQUAL, - .ulCullMode = PL_CULL_MODE_NONE, - .ulWireframe = 0, - .ulStencilMode = PL_COMPARE_MODE_ALWAYS, - .ulStencilRef = 0xff, - .ulStencilMask = 0xff, - .ulStencilOpFail = PL_STENCIL_OP_KEEP, - .ulStencilOpDepthFail = PL_STENCIL_OP_KEEP, - .ulStencilOpPass = PL_STENCIL_OP_KEEP - } - }; - (sbtDrawables[uDrawableBatchIndex])[i].tShadowShader = pl__get_shader_variant(uSceneHandle, atTemplateShadowShaders[uDrawableBatchIndex], &tShadowVariant); - } - } - } - - pl_sb_free(sbtMaterialBindGroups); + pl__refr_process_drawables(uSceneHandle, true); pl_end_cpu_sample(gptProfile, 0); } @@ -2510,8 +2052,12 @@ static void pl_refr_finalize_scene(uint32_t uSceneHandle) { // for convience - plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; - plDevice* ptDevice = gptData->ptDevice; + plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; + plDevice* ptDevice = gptData->ptDevice; + + plEntity* sbtProbes = ptScene->tComponentLibrary.tEnvironmentProbeCompManager.sbtEntities; + for(uint32_t i = 0; i < pl_sb_size(sbtProbes); i++) + pl__create_probe_data(uSceneHandle, sbtProbes[i]); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~textures~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2528,59 +2074,6 @@ pl_refr_finalize_scene(uint32_t uSceneHandle) gptJob->wait_for_counter(ptCounter); pl_end_cpu_sample(gptProfile, 0); - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~CPU Buffers~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - int iSceneWideRenderingFlags = PL_RENDERING_FLAG_USE_PUNCTUAL; - if(ptScene->tGGXEnvTexture.uIndex != 0 && gptData->bImageBasedLighting) - iSceneWideRenderingFlags |= PL_RENDERING_FLAG_USE_IBL; - - // fill CPU buffers & drawable list - pl_begin_cpu_sample(gptProfile, 0, "create shaders"); - - plDrawable* sbtDrawables[] = { - ptScene->sbtDeferredDrawables, - ptScene->sbtForwardDrawables, - }; - - plShaderHandle atTemplateShaders[] = { - gptData->tDeferredShader, - gptData->tForwardShader - }; - - plShaderHandle atTemplateShadowShaders[] = { - gptData->tShadowShader, - gptData->tAlphaShadowShader - }; - - plGraphicsState atTemplateVariants[] = { - { - .ulDepthWriteEnabled = 1, - .ulDepthMode = PL_COMPARE_MODE_GREATER, - .ulCullMode = PL_CULL_MODE_CULL_BACK, - .ulStencilMode = PL_COMPARE_MODE_ALWAYS, - .ulStencilRef = 0xff, - .ulStencilMask = 0xff, - .ulStencilOpFail = PL_STENCIL_OP_KEEP, - .ulStencilOpDepthFail = PL_STENCIL_OP_KEEP, - .ulStencilOpPass = PL_STENCIL_OP_KEEP - }, - { - .ulDepthWriteEnabled = 1, - .ulDepthMode = PL_COMPARE_MODE_GREATER_OR_EQUAL, - .ulCullMode = PL_CULL_MODE_NONE, - .ulStencilMode = PL_COMPARE_MODE_ALWAYS, - .ulStencilRef = 0xff, - .ulStencilMask = 0xff, - .ulStencilOpFail = PL_STENCIL_OP_KEEP, - .ulStencilOpDepthFail = PL_STENCIL_OP_KEEP, - .ulStencilOpPass = PL_STENCIL_OP_KEEP - } - }; - - plHashMap* atHashmaps[] = { - ptScene->ptDeferredHashmap, - ptScene->ptForwardHashmap - }; const plLightComponent* sbtLights = ptScene->tComponentLibrary.tLightComponentManager.pComponents; pl_sb_reserve(ptScene->sbtVertexDataBuffer, 40000000); @@ -2602,149 +2095,7 @@ pl_refr_finalize_scene(uint32_t uSceneHandle) pl_sb_reserve(ptScene->sbtPLightData, iPLightCount); pl_sb_reserve(ptScene->sbtSLightData, iSLightCount); - for(uint32_t uDrawableBatchIndex = 0; uDrawableBatchIndex < 2; uDrawableBatchIndex++) - { - plHashMap* ptHashmap = atHashmaps[uDrawableBatchIndex]; - const uint32_t uDrawableCount = pl_sb_size(sbtDrawables[uDrawableBatchIndex]); - pl_hm_resize(ptHashmap, uDrawableCount); - for(uint32_t i = 0; i < uDrawableCount; i++) - { - - (sbtDrawables[uDrawableBatchIndex])[i].uSkinIndex = UINT32_MAX; - plEntity tEntity = (sbtDrawables[uDrawableBatchIndex])[i].tEntity; - pl_hm_insert(ptHashmap, tEntity.ulData, i); - - // get actual components - plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tEntity); - plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptObject->tMesh); - plMaterialComponent* ptMaterial = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MATERIAL, ptMesh->tMaterial); - - uint32_t uMaterialIndex = UINT32_MAX; - - if(pl_hm_has_key(ptScene->ptMaterialHashmap, ptMesh->tMaterial.ulData)) - { - uMaterialIndex = (uint32_t)pl_hm_lookup(ptScene->ptMaterialHashmap, ptMesh->tMaterial.ulData); - } - else - { - - uint64_t ulValue = pl_hm_get_free_index(ptScene->ptMaterialHashmap); - if(ulValue == UINT64_MAX) - { - ulValue = pl_sb_size(ptScene->sbtMaterialBuffer); - pl_sb_add(ptScene->sbtMaterialBuffer); - } - - uMaterialIndex = (uint32_t)ulValue; - - plTextureHandle tBaseColorTex = pl__create_texture_helper(ptMaterial, PL_TEXTURE_SLOT_BASE_COLOR_MAP, true, 0); - plTextureHandle tNormalTex = pl__create_texture_helper(ptMaterial, PL_TEXTURE_SLOT_NORMAL_MAP, false, 0); - plTextureHandle tEmissiveTex = pl__create_texture_helper(ptMaterial, PL_TEXTURE_SLOT_EMISSIVE_MAP, true, 0); - plTextureHandle tMetallicRoughnessTex = pl__create_texture_helper(ptMaterial, PL_TEXTURE_SLOT_METAL_ROUGHNESS_MAP, false, 0); - plTextureHandle tOcclusionTex = pl__create_texture_helper(ptMaterial, PL_TEXTURE_SLOT_OCCLUSION_MAP, false, 1); - - int iBaseColorTexIdx = (int)pl__get_bindless_texture_index(uSceneHandle, tBaseColorTex); - int iNormalTexIdx = (int)pl__get_bindless_texture_index(uSceneHandle, tNormalTex); - int iEmissiveTexIdx = (int)pl__get_bindless_texture_index(uSceneHandle, tEmissiveTex); - int iMetallicRoughnessTexIdx = (int)pl__get_bindless_texture_index(uSceneHandle, tMetallicRoughnessTex); - int iOcclusionTexIdx = (int)pl__get_bindless_texture_index(uSceneHandle, tOcclusionTex); - - plGPUMaterial tMaterial = { - .iMipCount = ptScene->iEnvironmentMips, - .fMetallicFactor = ptMaterial->fMetalness, - .fRoughnessFactor = ptMaterial->fRoughness, - .tBaseColorFactor = ptMaterial->tBaseColor, - .tEmissiveFactor = ptMaterial->tEmissiveColor.rgb, - .fAlphaCutoff = ptMaterial->fAlphaCutoff, - .fOcclusionStrength = 1.0f, - .fEmissiveStrength = 1.0f, - .iBaseColorUVSet = (int)ptMaterial->atTextureMaps[PL_TEXTURE_SLOT_BASE_COLOR_MAP].uUVSet, - .iNormalUVSet = (int)ptMaterial->atTextureMaps[PL_TEXTURE_SLOT_NORMAL_MAP].uUVSet, - .iEmissiveUVSet = (int)ptMaterial->atTextureMaps[PL_TEXTURE_SLOT_EMISSIVE_MAP].uUVSet, - .iOcclusionUVSet = (int)ptMaterial->atTextureMaps[PL_TEXTURE_SLOT_OCCLUSION_MAP].uUVSet, - .iMetallicRoughnessUVSet = (int)ptMaterial->atTextureMaps[PL_TEXTURE_SLOT_METAL_ROUGHNESS_MAP].uUVSet, - .iBaseColorTexIdx = iBaseColorTexIdx, - .iNormalTexIdx = iNormalTexIdx, - .iEmissiveTexIdx = iEmissiveTexIdx, - .iMetallicRoughnessTexIdx = iMetallicRoughnessTexIdx, - .iOcclusionTexIdx = iOcclusionTexIdx, - }; - ptScene->sbtMaterialBuffer[uMaterialIndex] = tMaterial; - pl_hm_insert(ptScene->ptMaterialHashmap, ptMesh->tMaterial.ulData, ulValue); - } - - (sbtDrawables[uDrawableBatchIndex])[i].uMaterialIndex = uMaterialIndex; - - // add data to global buffers - pl__add_drawable_data_to_global_buffer(ptScene, i, (sbtDrawables[uDrawableBatchIndex])); - pl__add_drawable_skin_data_to_global_buffer(ptScene, i, (sbtDrawables[uDrawableBatchIndex])); - - int iDataStride = 0; - int iFlagCopy0 = (int)ptMesh->ulVertexStreamMask; - while(iFlagCopy0) - { - iDataStride += iFlagCopy0 & 1; - iFlagCopy0 >>= 1; - } - - int iTextureMappingFlags = 0; - for(uint32_t j = 0; j < PL_TEXTURE_SLOT_COUNT; j++) - { - if((ptMaterial->atTextureMaps[j].acName[0] != 0)) - iTextureMappingFlags |= 1 << j; - } - - // choose shader variant - int aiConstantData0[] = { - (int)ptMesh->ulVertexStreamMask, - iDataStride, - iTextureMappingFlags, - PL_INFO_MATERIAL_METALLICROUGHNESS, - iSceneWideRenderingFlags, - iDLightCount, - iPLightCount, - iSLightCount - }; - - plGraphicsState tVariantTemp = atTemplateVariants[uDrawableBatchIndex]; - - if(ptMaterial->tFlags & PL_MATERIAL_FLAG_DOUBLE_SIDED) - tVariantTemp.ulCullMode = PL_CULL_MODE_NONE; - - const plShaderVariant tVariant = { - .pTempConstantData = aiConstantData0, - .tGraphicsState = tVariantTemp - }; - - (sbtDrawables[uDrawableBatchIndex])[i].tShader = pl__get_shader_variant(uSceneHandle, atTemplateShaders[uDrawableBatchIndex], &tVariant); - - if(uDrawableBatchIndex > 0) - { - const plShaderVariant tShadowVariant = { - .pTempConstantData = aiConstantData0, - .tGraphicsState = { - .ulDepthWriteEnabled = 1, - .ulDepthMode = PL_COMPARE_MODE_GREATER_OR_EQUAL, - .ulCullMode = PL_CULL_MODE_NONE, - .ulWireframe = 0, - .ulStencilMode = PL_COMPARE_MODE_ALWAYS, - .ulStencilRef = 0xff, - .ulStencilMask = 0xff, - .ulStencilOpFail = PL_STENCIL_OP_KEEP, - .ulStencilOpDepthFail = PL_STENCIL_OP_KEEP, - .ulStencilOpPass = PL_STENCIL_OP_KEEP - } - }; - (sbtDrawables[uDrawableBatchIndex])[i].tShadowShader = pl__get_shader_variant(uSceneHandle, atTemplateShadowShaders[uDrawableBatchIndex], &tShadowVariant); - } - } - atHashmaps[uDrawableBatchIndex] = ptHashmap; - } - - ptScene->ptDeferredHashmap = atHashmaps[0]; - ptScene->ptForwardHashmap = atHashmaps[1]; - - pl_end_cpu_sample(gptProfile, 0); + pl__refr_process_drawables(uSceneHandle, false); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~GPU Buffers~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -2850,6 +2201,12 @@ pl_refr_finalize_scene(uint32_t uSceneHandle) gptGfx->update_bind_group(gptData->ptDevice, ptScene->tSkinBindGroup0, &tBGData0); } + int iSceneWideRenderingFlags = 0; + if(gptData->bPunctualLighting) + iSceneWideRenderingFlags |= PL_RENDERING_FLAG_USE_PUNCTUAL; + if(gptData->bImageBasedLighting) + iSceneWideRenderingFlags |= PL_RENDERING_FLAG_USE_IBL; + // create lighting shader { int aiLightingConstantData[] = {iSceneWideRenderingFlags, pl_sb_capacity(ptScene->sbtDLightData), pl_sb_capacity(ptScene->sbtPLightData), pl_sb_capacity(ptScene->sbtSLightData)}; @@ -2915,7 +2272,7 @@ pl_refr_finalize_scene(uint32_t uSceneHandle) }, { .atBufferBindings = { - { .uSlot = 0, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, + { .uSlot = 0, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, { .uSlot = 1, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, { .uSlot = 2, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, { .uSlot = 3, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, @@ -2936,6 +2293,8 @@ pl_refr_finalize_scene(uint32_t uSceneHandle) tLightingShaderDesc.atConstants[i].tType = PL_DATA_TYPE_INT; } ptScene->tLightingShader = gptGfx->create_shader(gptData->ptDevice, &tLightingShaderDesc); + aiLightingConstantData[0] = gptData->bPunctualLighting ? PL_RENDERING_FLAG_USE_PUNCTUAL : 0; + ptScene->tEnvLightingShader = gptGfx->create_shader(gptData->ptDevice, &tLightingShaderDesc); } const plShaderDesc tTonemapShaderDesc = { @@ -3048,13 +2407,11 @@ pl_refr_finalize_scene(uint32_t uSceneHandle) }; plRenderPassAttachments atShadowAttachmentSets[PL_MAX_FRAMES_IN_FLIGHT] = {0}; - + ptScene->tShadowTexture = pl__refr_create_local_texture(&tShadowDepthTextureDesc, "shadow map", 0, PL_TEXTURE_USAGE_SAMPLED); + ptScene->atShadowTextureBindlessIndices = pl__get_bindless_texture_index(uSceneHandle, ptScene->tShadowTexture); for(uint32_t i = 0; i < gptGfx->get_frames_in_flight(); i++) { - ptScene->tShadowTexture[i] = pl__refr_create_local_texture(&tShadowDepthTextureDesc, "shadow map", i, PL_TEXTURE_USAGE_SAMPLED); - ptScene->atShadowTextureBindlessIndices[i] = pl__get_bindless_texture_index(uSceneHandle, ptScene->tShadowTexture[i]); - - atShadowAttachmentSets[i].atViewAttachments[0] = ptScene->tShadowTexture[i]; + atShadowAttachmentSets[i].atViewAttachments[0] = ptScene->tShadowTexture; } ptScene->tShadowRenderPass = gptGfx->create_render_pass(gptData->ptDevice, &tDepthRenderPassDesc, atShadowAttachmentSets); @@ -3072,6 +2429,9 @@ pl_refr_run_ecs(uint32_t uSceneHandle) gptECS->run_animation_update_system(&ptScene->tComponentLibrary, gptIOI->get_io()->fDeltaTime); gptECS->run_transform_update_system(&ptScene->tComponentLibrary); gptECS->run_hierarchy_update_system(&ptScene->tComponentLibrary); + gptECS->run_light_update_system(&ptScene->tComponentLibrary); + gptECS->run_environment_probe_update_system(&ptScene->tComponentLibrary); + gptECS->run_camera_update_system(&ptScene->tComponentLibrary); gptECS->run_inverse_kinematics_update_system(&ptScene->tComponentLibrary); gptECS->run_skin_update_system(&ptScene->tComponentLibrary); gptECS->run_object_update_system(&ptScene->tComponentLibrary); @@ -3089,102 +2449,272 @@ pl_refr_render_scene(uint32_t uSceneHandle, const uint32_t* auViewHandles, const { pl_begin_cpu_sample(gptProfile, 0, __FUNCTION__); - const uint32_t uFrameIdx = gptGfx->get_current_frame_index(); - // for convience - plCommandPool* ptCmdPool = gptData->atCmdPools[gptGfx->get_current_frame_index()]; - plDevice* ptDevice = gptData->ptDevice; - plDrawStream* ptStream = &gptData->tDrawStream; - plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; - const plLightComponent* sbtLights = ptScene->tComponentLibrary.tLightComponentManager.pComponents; - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~update skin textures~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + const uint32_t uFrameIdx = gptGfx->get_current_frame_index(); + plCommandPool* ptCmdPool = gptData->atCmdPools[uFrameIdx]; + plDevice* ptDevice = gptData->ptDevice; + plDrawStream* ptStream = &gptData->tDrawStream; + plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; uint64_t ulValue = gptData->aulNextTimelineValue[uFrameIdx]; plTimelineSemaphore* tSemHandle = gptData->aptSemaphores[uFrameIdx]; - { - const plBeginCommandInfo tBeginInfo = { - .uWaitSemaphoreCount = 1, - .atWaitSempahores = {tSemHandle}, - .auWaitSemaphoreValues = {ulValue}, - }; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~update skin textures~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo); + const plBeginCommandInfo tSkinUpdateBeginInfo = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; - pl_refr_update_skin_textures(ptCommandBuffer, uSceneHandle); - gptGfx->end_command_recording(ptCommandBuffer); + plCommandBuffer* ptSkinUpdateCmdBuffer = gptGfx->request_command_buffer(ptCmdPool); + gptGfx->begin_command_recording(ptSkinUpdateCmdBuffer, &tSkinUpdateBeginInfo); - const plSubmitInfo tSubmitInfo = { - .uSignalSemaphoreCount = 1, - .atSignalSempahores = {tSemHandle}, - .auSignalSemaphoreValues = {++ulValue} - }; - gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo); - gptGfx->return_command_buffer(ptCommandBuffer); - } + pl_refr_update_skin_textures(ptSkinUpdateCmdBuffer, uSceneHandle); + gptGfx->end_command_recording(ptSkinUpdateCmdBuffer); + + const plSubmitInfo tSkinUpdateSubmitInfo = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptSkinUpdateCmdBuffer, &tSkinUpdateSubmitInfo); + gptGfx->return_command_buffer(ptSkinUpdateCmdBuffer); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~perform skinning~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + const plBeginCommandInfo tSkinningBeginInfo = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; + + plCommandBuffer* ptSkinningCmdBuffer = gptGfx->request_command_buffer(ptCmdPool); + gptGfx->begin_command_recording(ptSkinningCmdBuffer, &tSkinningBeginInfo); + + pl_refr_perform_skinning(ptSkinningCmdBuffer, uSceneHandle); + gptGfx->end_command_recording(ptSkinningCmdBuffer); + + const plSubmitInfo tSkinningSubmitInfo = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptSkinningCmdBuffer, &tSkinningSubmitInfo); + gptGfx->return_command_buffer(ptSkinningCmdBuffer); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~generate shadow maps~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // prep + pl_refr_pack_shadow_atlas(uSceneHandle, auViewHandles, uViewCount); + pl_sb_reset(ptScene->sbtPLightShadowData); + pl_sb_reset(ptScene->sbtSLightShadowData); + + const plBeginCommandInfo tShadowBeginInfo = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; + + plCommandBuffer* ptShadowCmdBuffer = gptGfx->request_command_buffer(ptCmdPool); + gptGfx->begin_command_recording(ptShadowCmdBuffer, &tShadowBeginInfo); + + plRenderEncoder* ptShadowEncoder = gptGfx->begin_render_pass(ptShadowCmdBuffer, ptScene->tFirstShadowRenderPass, NULL); + + pl_refr_generate_shadow_maps(ptShadowEncoder, ptShadowCmdBuffer, uSceneHandle); + + gptGfx->end_render_pass(ptShadowEncoder); + gptGfx->end_command_recording(ptShadowCmdBuffer); + + const plSubmitInfo tShadowSubmitInfo = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptShadowCmdBuffer, &tShadowSubmitInfo); + gptGfx->return_command_buffer(ptShadowCmdBuffer); + + plBuffer* ptPShadowDataBuffer = gptGfx->get_buffer(ptDevice, ptScene->atPLightShadowDataBuffer[uFrameIdx]); + memcpy(ptPShadowDataBuffer->tMemoryAllocation.pHostMapped, ptScene->sbtPLightShadowData, sizeof(plGPULightShadowData) * pl_sb_size(ptScene->sbtPLightShadowData)); + + plBuffer* ptSShadowDataBuffer = gptGfx->get_buffer(ptDevice, ptScene->atSLightShadowDataBuffer[uFrameIdx]); + memcpy(ptSShadowDataBuffer->tMemoryAllocation.pHostMapped, ptScene->sbtSLightShadowData, sizeof(plGPULightShadowData) * pl_sb_size(ptScene->sbtSLightShadowData)); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~add scene lights~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + pl_sb_reset(ptScene->sbtDLightData); + pl_sb_reset(ptScene->sbtPLightData); + pl_sb_reset(ptScene->sbtSLightData); + + // update light CPU side buffers + const plLightComponent* sbtLights = ptScene->tComponentLibrary.tLightComponentManager.pComponents; + const uint32_t uLightCount = pl_sb_size(sbtLights); + for(uint32_t i = 0; i < uLightCount; i++) { - const plBeginCommandInfo tBeginInfo = { - .uWaitSemaphoreCount = 1, - .atWaitSempahores = {tSemHandle}, - .auWaitSemaphoreValues = {ulValue}, - }; + const plLightComponent* ptLight = &sbtLights[i]; + + if(ptLight->tType == PL_LIGHT_TYPE_POINT) + { + const plGPULight tLight = { + .fIntensity = ptLight->fIntensity, + .fRange = ptLight->fRange, + .tPosition = ptLight->tPosition, + .tDirection = ptLight->tDirection, + .tColor = ptLight->tColor, + .iShadowIndex = ptLight->tFlags & PL_LIGHT_FLAG_CAST_SHADOW ? pl_sb_size(ptScene->sbtPLightData) : 0, + .iCastShadow = ptLight->tFlags & PL_LIGHT_FLAG_CAST_SHADOW, + .iType = ptLight->tType + }; + pl_sb_push(ptScene->sbtPLightData, tLight); + } + else if(ptLight->tType == PL_LIGHT_TYPE_SPOT) + { + const plGPULight tLight = { + .fIntensity = ptLight->fIntensity, + .fRange = ptLight->fRange, + .tPosition = ptLight->tPosition, + .tDirection = ptLight->tDirection, + .tColor = ptLight->tColor, + .iShadowIndex = ptLight->tFlags & PL_LIGHT_FLAG_CAST_SHADOW ? pl_sb_size(ptScene->sbtSLightData) : 0, + .iCastShadow = ptLight->tFlags & PL_LIGHT_FLAG_CAST_SHADOW, + .iType = ptLight->tType, + .fInnerConeCos = cosf(ptLight->fInnerConeAngle), + .fOuterConeCos = cosf(ptLight->fOuterConeAngle), + }; + pl_sb_push(ptScene->sbtSLightData, tLight); + } + else if(ptLight->tType == PL_LIGHT_TYPE_DIRECTIONAL) + { + + const plGPULight tLight = { + .fIntensity = ptLight->fIntensity, + .fRange = ptLight->fRange, + .tPosition = ptLight->tPosition, + .tDirection = ptLight->tDirection, + .tColor = ptLight->tColor, + .iShadowIndex = ptLight->tFlags & PL_LIGHT_FLAG_CAST_SHADOW ? pl_sb_size(ptScene->sbtDLightData) : 0, + .iCastShadow = ptLight->tFlags & PL_LIGHT_FLAG_CAST_SHADOW, + .iCascadeCount = (int)ptLight->uCascadeCount, + .iType = ptLight->tType + }; + pl_sb_push(ptScene->sbtDLightData, tLight); + } + } - plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo); + // update light GPU side buffers + plBuffer* ptPLightingBuffer = gptGfx->get_buffer(ptDevice, ptScene->atPLightBuffer[uFrameIdx]); + plBuffer* ptSLightingBuffer = gptGfx->get_buffer(ptDevice, ptScene->atSLightBuffer[uFrameIdx]); + plBuffer* ptDLightingBuffer = gptGfx->get_buffer(ptDevice, ptScene->atDLightBuffer[uFrameIdx]); + memcpy(ptPLightingBuffer->tMemoryAllocation.pHostMapped, ptScene->sbtPLightData, sizeof(plGPULight) * pl_sb_size(ptScene->sbtPLightData)); + memcpy(ptSLightingBuffer->tMemoryAllocation.pHostMapped, ptScene->sbtSLightData, sizeof(plGPULight) * pl_sb_size(ptScene->sbtSLightData)); + memcpy(ptDLightingBuffer->tMemoryAllocation.pHostMapped, ptScene->sbtDLightData, sizeof(plGPULight) * pl_sb_size(ptScene->sbtDLightData)); - pl_refr_perform_skinning(ptCommandBuffer, uSceneHandle); - gptGfx->end_command_recording(ptCommandBuffer); + // update environment probes + ulValue = pl__update_environment_probes(uSceneHandle, ulValue); + + // common + const plBindGroupUpdateSamplerData tSkyboxSamplerData = { + .tSampler = gptData->tSkyboxSampler, + .uSlot = 1 + }; + + const plBindGroupLayout tSkyboxBG0Layout = { + .atBufferBindings = { + { + .tType = PL_BUFFER_BINDING_TYPE_STORAGE, + .uSlot = 0, + .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL + } + }, + .atSamplerBindings = { + {.uSlot = 1, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL} + } + }; + + const plBindGroupDesc tSkyboxBG0Desc = { + .ptPool = gptData->aptTempGroupPools[uFrameIdx], + .ptLayout = &tSkyboxBG0Layout, + .pcDebugName = "skybox view specific bindgroup" + }; + + const plBindGroupLayout tDeferredBG1Layout = { + .atBufferBindings = { + { + .tType = PL_BUFFER_BINDING_TYPE_STORAGE, + .uSlot = 0, + .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL + } + } + }; - const plSubmitInfo tSubmitInfo = { - .uSignalSemaphoreCount = 1, - .atSignalSempahores = {tSemHandle}, - .auSignalSemaphoreValues = {++ulValue} - }; - gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo); - gptGfx->return_command_buffer(ptCommandBuffer); - } + const plBindGroupDesc tDeferredBG1Desc = { + .ptPool = gptData->aptTempGroupPools[uFrameIdx], + .ptLayout = &tDeferredBG1Layout, + .pcDebugName = "view specific bindgroup" + }; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~generate shadow maps~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - pl_refr_pack_shadow_atlas(uSceneHandle, auViewHandles, uViewCount); + const plBindGroupLayout tSceneBGLayout = { + .atBufferBindings = { + { .uSlot = 0, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, + { .uSlot = 1, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, + { .uSlot = 2, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, + { .uSlot = 3, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, + { .uSlot = 4, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, + { .uSlot = 5, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, + { .uSlot = 6, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, + }, + .atSamplerBindings = { + {.uSlot = 7, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL} + }, + }; - { - const plBeginCommandInfo tBeginInfo = { - .uWaitSemaphoreCount = 1, - .atWaitSempahores = {tSemHandle}, - .auWaitSemaphoreValues = {ulValue}, - }; + const plBindGroupDesc tSceneBGDesc = { + .ptPool = gptData->aptTempGroupPools[gptGfx->get_current_frame_index()], + .ptLayout = &tSceneBGLayout, + .pcDebugName = "light bind group 2" + }; - plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo); + const plBindGroupUpdateSamplerData tShadowSamplerData = { + .tSampler = gptData->tShadowSampler, + .uSlot = 7 + }; - pl_sb_reset(ptScene->sbtPLightShadowData); - pl_sb_reset(ptScene->sbtSLightShadowData); + const plBindGroupLayout tPickBG0Layout = { + .atBufferBindings = { + { + .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, + .uSlot = 0, + .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL + } + } - plRenderEncoder* ptEncoder = gptGfx->begin_render_pass(ptCommandBuffer, ptScene->tFirstShadowRenderPass, NULL); + }; - pl_refr_generate_shadow_maps(ptEncoder, ptCommandBuffer, uSceneHandle); + const plBindGroupDesc tPickBGDesc = { + .ptPool = gptData->aptTempGroupPools[uFrameIdx], + .ptLayout = &tPickBG0Layout, + .pcDebugName = "temp pick bind group" + }; - gptGfx->end_render_pass(ptEncoder); - gptGfx->end_command_recording(ptCommandBuffer); + const plBindGroupLayout tJFABindGroupLayout = { + .atTextureBindings = { + {.uSlot = 0, .tStages = PL_STAGE_COMPUTE, .tType = PL_TEXTURE_BINDING_TYPE_STORAGE}, + {.uSlot = 1, .tStages = PL_STAGE_COMPUTE, .tType = PL_TEXTURE_BINDING_TYPE_STORAGE} + } + }; - const plSubmitInfo tSubmitInfo = { - .uSignalSemaphoreCount = 1, - .atSignalSempahores = {tSemHandle}, - .auSignalSemaphoreValues = {++ulValue} - }; - gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo); - gptGfx->return_command_buffer(ptCommandBuffer); - } + const plBindGroupDesc tJFABindGroupDesc = { + .ptPool = gptData->aptTempGroupPools[uFrameIdx], + .ptLayout = &tJFABindGroupLayout, + .pcDebugName = "temp jfa bind group" + }; + // render views for(uint32_t uViewIndex = 0; uViewIndex < uViewCount; uViewIndex++) { const uint32_t uViewHandle = auViewHandles[uViewIndex]; - plRefView* ptView = &ptScene->atViews[uViewHandle]; - plCameraComponent* ptCamera = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_CAMERA, *atOptions[uViewIndex].ptViewCamera); + plRefView* ptView = &ptScene->atViews[uViewHandle]; + plCameraComponent* ptCamera = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_CAMERA, *atOptions[uViewIndex].ptViewCamera); plCameraComponent* ptCullCamera = atOptions[uViewIndex].ptCullCamera ? gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_CAMERA, *atOptions[uViewIndex].ptCullCamera) : ptCamera; const plMat4 tMVP = pl_mul_mat4(&ptCamera->tProjMat, &ptCamera->tViewMat); @@ -3196,1073 +2726,908 @@ pl_refr_render_scene(uint32_t uSceneHandle, const uint32_t* auViewHandles, const //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~culling~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - const uint32_t uOpaqueDrawableCount = pl_sb_size(ptScene->sbtDeferredDrawables); - const uint32_t uTransparentDrawableCount = pl_sb_size(ptScene->sbtForwardDrawables); + const uint32_t uDeferredDrawableCount = pl_sb_size(ptScene->sbtDeferredDrawables); + const uint32_t uForwardDrawableCount = pl_sb_size(ptScene->sbtForwardDrawables); - plAtomicCounter* ptOpaqueCounter = NULL; - plAtomicCounter* ptTransparentCounter = NULL; + plAtomicCounter* ptDeferredCounter = NULL; + plAtomicCounter* ptForwardCounter = NULL; if(ptCullCamera) { - // opaque objects - plCullData tOpaqueCullData = { + plCullData tDeferredCullData = { .ptScene = ptScene, .ptCullCamera = ptCullCamera, .atDrawables = ptScene->sbtDeferredDrawables }; - plJobDesc tOpaqueJobDesc = { + plJobDesc tDeferredJobDesc = { .task = pl__refr_cull_job, - .pData = &tOpaqueCullData + .pData = &tDeferredCullData }; - gptJob->dispatch_batch(uOpaqueDrawableCount, 0, tOpaqueJobDesc, &ptOpaqueCounter); + gptJob->dispatch_batch(uDeferredDrawableCount, 0, tDeferredJobDesc, &ptDeferredCounter); - // transparent objects - plCullData tTransparentCullData = { + plCullData tForwardCullData = { .ptScene = ptScene, .ptCullCamera = ptCullCamera, .atDrawables = ptScene->sbtForwardDrawables }; - plJobDesc tTransparentJobDesc = { - .task = pl__refr_cull_job, - .pData = &tTransparentCullData + plJobDesc tForwardJobDesc = { + .task = pl__refr_cull_job, + .pData = &tForwardCullData }; - gptJob->dispatch_batch(uTransparentDrawableCount, 0, tTransparentJobDesc, &ptTransparentCounter); + gptJob->dispatch_batch(uForwardDrawableCount, 0, tForwardJobDesc, &ptForwardCounter); } - else + else // no culling, just copy drawables over { - if(pl_sb_size(ptView->sbtVisibleOpaqueDrawables) != uOpaqueDrawableCount) + if(pl_sb_size(ptView->sbtVisibleOpaqueDrawables) != uDeferredDrawableCount) { - pl_sb_resize(ptView->sbtVisibleOpaqueDrawables, uOpaqueDrawableCount); - memcpy(ptView->sbtVisibleOpaqueDrawables, ptScene->sbtDeferredDrawables, sizeof(plDrawable) * uOpaqueDrawableCount); + pl_sb_resize(ptView->sbtVisibleOpaqueDrawables, uDeferredDrawableCount); + memcpy(ptView->sbtVisibleOpaqueDrawables, ptScene->sbtDeferredDrawables, sizeof(plDrawable) * uDeferredDrawableCount); } - if(pl_sb_size(ptView->sbtVisibleTransparentDrawables) != uTransparentDrawableCount) + if(pl_sb_size(ptView->sbtVisibleTransparentDrawables) != uForwardDrawableCount) { - pl_sb_resize(ptView->sbtVisibleTransparentDrawables, uTransparentDrawableCount); - memcpy(ptView->sbtVisibleTransparentDrawables, ptScene->sbtForwardDrawables, sizeof(plDrawable) * uTransparentDrawableCount); + pl_sb_resize(ptView->sbtVisibleTransparentDrawables, uForwardDrawableCount); + memcpy(ptView->sbtVisibleTransparentDrawables, ptScene->sbtForwardDrawables, sizeof(plDrawable) * uForwardDrawableCount); } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~update bind groups~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const BindGroup_0 tBindGroupBuffer = { - .tViewportSize = {.xy = ptView->tTargetSize}, + .tViewportSize = {.xy = ptView->tTargetSize, .ignored0_ = 1.0f, .ignored1_ = 1.0f}, + .tViewportInfo = {0}, .tCameraPos = ptCamera->tPos, .tCameraProjection = ptCamera->tProjMat, .tCameraView = ptCamera->tViewMat, - .tCameraViewProjection = pl_mul_mat4(&ptCamera->tProjMat, &ptCamera->tViewMat), - .uGGXEnvSampler = ptScene->uGGXEnvSampler, - .uGGXLUT = ptScene->uGGXLUT, - .uLambertianEnvSampler = ptScene->uLambertianEnvSampler + .tCameraViewProjection = pl_mul_mat4(&ptCamera->tProjMat, &ptCamera->tViewMat) }; memcpy(gptGfx->get_buffer(ptDevice, ptView->atGlobalBuffers[uFrameIdx])->tMemoryAllocation.pHostMapped, &tBindGroupBuffer, sizeof(BindGroup_0)); - const uint32_t uFrameIndex = gptGfx->get_current_frame_index(); - - plBindGroupLayout tSkyboxViewBindGroupLayout = { - .atBufferBindings = { - { - .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, - .uSlot = 0, - .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL - } - }, - .atSamplerBindings = { - {.uSlot = 1, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL} - } - }; - - const plBindGroupDesc tSkyboxViewBindGroupDesc = { - .ptPool = gptData->aptTempGroupPools[uFrameIndex], - .ptLayout = &tSkyboxViewBindGroupLayout, - .pcDebugName = "skybox view specific bindgroup" - }; - plBindGroupHandle tSkyboxViewBindGroup = gptGfx->create_bind_group(ptDevice, &tSkyboxViewBindGroupDesc); - - plBindGroupLayout tViewBindGroupLayout = { - .atBufferBindings = { - { - .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, - .uSlot = 0, - .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL - } - } - }; - - const plBindGroupDesc tViewBindGroupDesc = { - .ptPool = gptData->aptTempGroupPools[uFrameIndex], - .ptLayout = &tViewBindGroupLayout, - .pcDebugName = "view specific bindgroup" - }; - plBindGroupHandle tViewBindGroup = gptGfx->create_bind_group(ptDevice, &tViewBindGroupDesc); - - plBindGroupUpdateSamplerData tSamplerData[] = { - { - .tSampler = gptData->tDefaultSampler, - .uSlot = 1 - } - }; - - const plBindGroupUpdateBufferData atNewBufferData[] = - { - { - .tBuffer = ptView->atGlobalBuffers[uFrameIdx], - .uSlot = 0, - .szBufferRange = sizeof(BindGroup_0) - } + const plBindGroupUpdateBufferData tDeferredBG1BufferData = { + .tBuffer = ptView->atGlobalBuffers[uFrameIdx], + .uSlot = 0, + .szBufferRange = sizeof(BindGroup_0) }; - const plBindGroupUpdateBufferData atBufferData[] = - { - { - .tBuffer = ptView->atGlobalBuffers[uFrameIdx], - .uSlot = 0, - .szBufferRange = sizeof(BindGroup_0) - } + plBindGroupUpdateData tDeferredBG1Data = { + .uBufferCount = 1, + .atBufferBindings = &tDeferredBG1BufferData }; + + plBindGroupHandle tDeferredBG1 = gptGfx->create_bind_group(ptDevice, &tDeferredBG1Desc); + gptGfx->update_bind_group(gptData->ptDevice, tDeferredBG1, &tDeferredBG1Data); + gptGfx->queue_bind_group_for_deletion(ptDevice, tDeferredBG1); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~generate CSMs~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - plBindGroupUpdateData tSkyboxViewBindGroupData = { - .uBufferCount = 1, - .atBufferBindings = atBufferData, - .uSamplerCount = 1, - .atSamplerBindings = tSamplerData, - }; - plBindGroupUpdateData tViewBindGroupData = { - .uBufferCount = 1, - .atBufferBindings = atNewBufferData + const plBeginCommandInfo tCSMBeginInfo = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, }; - gptGfx->update_bind_group(gptData->ptDevice, tSkyboxViewBindGroup, &tSkyboxViewBindGroupData); - gptGfx->update_bind_group(gptData->ptDevice, tViewBindGroup, &tViewBindGroupData); - gptGfx->queue_bind_group_for_deletion(ptDevice, tSkyboxViewBindGroup); - gptGfx->queue_bind_group_for_deletion(ptDevice, tViewBindGroup); - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~generate shadow maps~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - { - const plBeginCommandInfo tBeginInfo = { - .uWaitSemaphoreCount = 1, - .atWaitSempahores = {tSemHandle}, - .auWaitSemaphoreValues = {ulValue}, - }; + plCommandBuffer* ptCSMCmdBuffer = gptGfx->request_command_buffer(ptCmdPool); + gptGfx->begin_command_recording(ptCSMCmdBuffer, &tCSMBeginInfo); - plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo); + pl_sb_reset(ptView->tDirectionLightShadowData.sbtDLightShadowData); + ptView->tDirectionLightShadowData.uOffset = 0; + ptView->tDirectionLightShadowData.uOffsetIndex = 0; - pl_sb_reset(ptView->sbtDLightShadowData); + plRenderEncoder* ptCSMEncoder = gptGfx->begin_render_pass(ptCSMCmdBuffer, ptScene->tShadowRenderPass, NULL); - plRenderEncoder* ptEncoder = gptGfx->begin_render_pass(ptCommandBuffer, ptScene->tShadowRenderPass, NULL); + plCameraComponent* ptSceneCamera = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_CAMERA, *atOptions[uViewIndex].ptViewCamera); + pl_refr_generate_cascaded_shadow_map(ptCSMEncoder, ptCSMCmdBuffer, uSceneHandle, uViewHandle, 0, 0, &ptView->tDirectionLightShadowData, ptSceneCamera); - pl_refr_generate_cascaded_shadow_map(ptEncoder, ptCommandBuffer, uSceneHandle, uViewHandle, uViewCount, *atOptions[uViewIndex].ptViewCamera); + gptGfx->end_render_pass(ptCSMEncoder); + gptGfx->end_command_recording(ptCSMCmdBuffer); - gptGfx->end_render_pass(ptEncoder); - gptGfx->end_command_recording(ptCommandBuffer); + const plSubmitInfo tCSMSubmitInfo = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptCSMCmdBuffer, &tCSMSubmitInfo); + gptGfx->return_command_buffer(ptCSMCmdBuffer); - const plSubmitInfo tSubmitInfo = { - .uSignalSemaphoreCount = 1, - .atSignalSempahores = {tSemHandle}, - .auSignalSemaphoreValues = {++ulValue} - }; - gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo); - gptGfx->return_command_buffer(ptCommandBuffer); - } + plBuffer* ptDShadowDataBuffer = gptGfx->get_buffer(ptDevice, ptView->tDirectionLightShadowData.atDLightShadowDataBuffer[uFrameIdx]); + memcpy(ptDShadowDataBuffer->tMemoryAllocation.pHostMapped, ptView->tDirectionLightShadowData.sbtDLightShadowData, sizeof(plGPULightShadowData) * pl_sb_size(ptView->tDirectionLightShadowData.sbtDLightShadowData)); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~render scene~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ const plVec2 tDimensions = gptGfx->get_render_pass(ptDevice, ptView->tRenderPass)->tDesc.tDimensions; plDrawArea tArea = { - .ptDrawStream = ptStream, - .atScissors = - { - { - .uWidth = (uint32_t)tDimensions.x, - .uHeight = (uint32_t)tDimensions.y, - } - }, - .atViewports = - { - { - .fWidth = tDimensions.x, - .fHeight = tDimensions.y, - .fMaxDepth = 1.0f - } - } + .ptDrawStream = ptStream, + .atScissors = + { + { + .uWidth = (uint32_t)tDimensions.x, + .uHeight = (uint32_t)tDimensions.y, + } + }, + .atViewports = + { + { + .fWidth = tDimensions.x, + .fHeight = tDimensions.y, + .fMaxDepth = 1.0f + } + } }; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~render scene~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - { - const plBeginCommandInfo tBeginInfo = { - .uWaitSemaphoreCount = 1, - .atWaitSempahores = {tSemHandle}, - .auWaitSemaphoreValues = {ulValue}, - }; + const plBeginCommandInfo tSceneBeginInfo = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; - plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo); + plCommandBuffer* ptSceneCmdBuffer = gptGfx->request_command_buffer(ptCmdPool); + gptGfx->begin_command_recording(ptSceneCmdBuffer, &tSceneBeginInfo); - //~~~~~~~~~~~~~~~~~~~~~~~~~~subpass 0 - g buffer fill~~~~~~~~~~~~~~~~~~~~~~~~~~ + //~~~~~~~~~~~~~~~~~~~~~~~~~~subpass 0 - g buffer fill~~~~~~~~~~~~~~~~~~~~~~~~~~ - plRenderEncoder* ptEncoder = gptGfx->begin_render_pass(ptCommandBuffer, ptView->tRenderPass, NULL); - gptGfx->set_depth_bias(ptEncoder, 0.0f, 0.0f, 0.0f); + plRenderEncoder* ptSceneEncoder = gptGfx->begin_render_pass(ptSceneCmdBuffer, ptView->tRenderPass, NULL); + gptGfx->set_depth_bias(ptSceneEncoder, 0.0f, 0.0f, 0.0f); - gptJob->wait_for_counter(ptOpaqueCounter); - pl_end_cpu_sample(gptProfile, 0); // prep scene - if(ptCullCamera) + gptJob->wait_for_counter(ptDeferredCounter); + pl_end_cpu_sample(gptProfile, 0); // prep scene + if(ptCullCamera) + { + pl_sb_reset(ptView->sbtVisibleOpaqueDrawables); + for(uint32_t uDrawableIndex = 0; uDrawableIndex < uDeferredDrawableCount; uDrawableIndex++) { - pl_sb_reset(ptView->sbtVisibleOpaqueDrawables); - for(uint32_t uDrawableIndex = 0; uDrawableIndex < uOpaqueDrawableCount; uDrawableIndex++) - { - const plDrawable tDrawable = ptScene->sbtDeferredDrawables[uDrawableIndex]; - if(!tDrawable.bCulled) - pl_sb_push(ptView->sbtVisibleOpaqueDrawables, tDrawable); - } + const plDrawable tDrawable = ptScene->sbtDeferredDrawables[uDrawableIndex]; + if(!tDrawable.bCulled) + pl_sb_push(ptView->sbtVisibleOpaqueDrawables, tDrawable); } + } - const uint32_t uVisibleOpaqueDrawCount = pl_sb_size(ptView->sbtVisibleOpaqueDrawables); - *gptData->pdDrawCalls += (double)uVisibleOpaqueDrawCount; - gptGfx->reset_draw_stream(ptStream, uVisibleOpaqueDrawCount); - for(uint32_t i = 0; i < uVisibleOpaqueDrawCount; i++) - { - const plDrawable tDrawable = ptView->sbtVisibleOpaqueDrawables[i]; - plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); - plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); - - plDynamicBinding tDynamicBinding = pl__allocate_dynamic_data(ptDevice); + const uint32_t uVisibleDeferredDrawCount = pl_sb_size(ptView->sbtVisibleOpaqueDrawables); + *gptData->pdDrawCalls += (double)uVisibleDeferredDrawCount; + gptGfx->reset_draw_stream(ptStream, uVisibleDeferredDrawCount); + for(uint32_t i = 0; i < uVisibleDeferredDrawCount; i++) + { + const plDrawable tDrawable = ptView->sbtVisibleOpaqueDrawables[i]; + plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); + plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); + + plDynamicBinding tDynamicBinding = pl__allocate_dynamic_data(ptDevice); - DynamicData* ptDynamicData = (DynamicData*)tDynamicBinding.pcData; - ptDynamicData->iDataOffset = tDrawable.uDataOffset; - ptDynamicData->iVertexOffset = tDrawable.uIndexCount == 0 ? 0 : tDrawable.uVertexOffset; - ptDynamicData->tModel = ptTransform->tWorld; - ptDynamicData->iMaterialOffset = tDrawable.uMaterialIndex; + DynamicData* ptDynamicData = (DynamicData*)tDynamicBinding.pcData; + ptDynamicData->iDataOffset = tDrawable.uDataOffset; + ptDynamicData->iVertexOffset = tDrawable.uIndexCount == 0 ? 0 : tDrawable.uVertexOffset; + ptDynamicData->tModel = ptTransform->tWorld; + ptDynamicData->iMaterialOffset = tDrawable.uMaterialIndex; + ptDynamicData->uGlobalIndex = 0; - pl_add_to_draw_stream(ptStream, (plDrawStreamData) - { - .tShader = tDrawable.tShader, - .auDynamicBuffers = { - tDynamicBinding.uBufferHandle - }, - .atVertexBuffers = { - ptScene->tVertexBuffer, - }, - .tIndexBuffer = tDrawable.uIndexCount == 0 ? (plBufferHandle){0} : ptScene->tIndexBuffer, - .uIndexOffset = tDrawable.uIndexOffset, - .uTriangleCount = tDrawable.uIndexCount == 0 ? tDrawable.uVertexCount / 3 : tDrawable.uIndexCount / 3, - .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, - .atBindGroups = { - ptScene->tGlobalBindGroup, - tViewBindGroup - }, - .auDynamicBufferOffsets = { - tDynamicBinding.uByteOffset - }, - .uInstanceOffset = 0, - .uInstanceCount = 1 - }); - } + pl_add_to_draw_stream(ptStream, (plDrawStreamData) + { + .tShader = tDrawable.tShader, + .auDynamicBuffers = { + tDynamicBinding.uBufferHandle + }, + .atVertexBuffers = { + ptScene->tVertexBuffer, + }, + .tIndexBuffer = tDrawable.uIndexCount == 0 ? (plBufferHandle){0} : ptScene->tIndexBuffer, + .uIndexOffset = tDrawable.uIndexOffset, + .uTriangleCount = tDrawable.uIndexCount == 0 ? tDrawable.uVertexCount / 3 : tDrawable.uIndexCount / 3, + .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, + .atBindGroups = { + ptScene->tGlobalBindGroup, + tDeferredBG1 + }, + .auDynamicBufferOffsets = { + tDynamicBinding.uByteOffset + }, + .uInstanceOffset = 0, + .uInstanceCount = 1 + }); + } - gptGfx->draw_stream(ptEncoder, 1, &tArea); - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~subpass 1 - lighting~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + gptGfx->draw_stream(ptSceneEncoder, 1, &tArea); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~subpass 1 - lighting~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - gptGfx->next_subpass(ptEncoder, NULL); + gptGfx->next_subpass(ptSceneEncoder, NULL); - plBuffer* ptDShadowDataBuffer = gptGfx->get_buffer(ptDevice, ptView->atDLightShadowDataBuffer[uFrameIdx]); - memcpy(ptDShadowDataBuffer->tMemoryAllocation.pHostMapped, ptView->sbtDLightShadowData, sizeof(plGPULightShadowData) * pl_sb_size(ptView->sbtDLightShadowData)); - + const plBindGroupUpdateBufferData atSceneBGBufferData[] = + { + { .uSlot = 0, .tBuffer = ptView->atGlobalBuffers[uFrameIdx], .szBufferRange = sizeof(BindGroup_0) }, + { .uSlot = 1, .tBuffer = ptScene->atDLightBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULight) * pl_sb_size(ptScene->sbtDLightData)}, + { .uSlot = 2, .tBuffer = ptScene->atPLightBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULight) * pl_sb_size(ptScene->sbtPLightData)}, + { .uSlot = 3, .tBuffer = ptScene->atSLightBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULight) * pl_sb_size(ptScene->sbtSLightData)}, + { .uSlot = 4, .tBuffer = ptView->tDirectionLightShadowData.atDLightShadowDataBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULightShadowData) * pl_sb_size(ptView->tDirectionLightShadowData.sbtDLightShadowData)}, + { .uSlot = 5, .tBuffer = ptScene->atPLightShadowDataBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULightShadowData) * pl_sb_size(ptScene->sbtPLightShadowData)}, + { .uSlot = 6, .tBuffer = ptScene->atSLightShadowDataBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULightShadowData) * pl_sb_size(ptScene->sbtSLightShadowData)}, + }; + + const plBindGroupUpdateData tSceneBGData = { + .uBufferCount = 7, + .atBufferBindings = atSceneBGBufferData, + .uSamplerCount = 1, + .atSamplerBindings = &tShadowSamplerData + }; + plBindGroupHandle tSceneBG = gptGfx->create_bind_group(ptDevice, &tSceneBGDesc); + gptGfx->update_bind_group(gptData->ptDevice, tSceneBG, &tSceneBGData); + gptGfx->queue_bind_group_for_deletion(ptDevice, tSceneBG); + + typedef struct _plLightingDynamicData { + uint32_t uLambertianEnvSampler; + uint32_t uGGXEnvSampler; + uint32_t uGGXLUT; + uint32_t uGlobalIndex; + } plLightingDynamicData; + + plDynamicBinding tLightingDynamicData = pl__allocate_dynamic_data(ptDevice); + plLightingDynamicData* ptLightingDynamicData = (plLightingDynamicData*)tLightingDynamicData.pcData; + + // TODO: decide on probes + + ptLightingDynamicData->uGGXEnvSampler = ptScene->sbtProbeData[0].uGGXEnvSampler; + ptLightingDynamicData->uGGXLUT = ptScene->sbtProbeData[0].uGGXLUT; + ptLightingDynamicData->uLambertianEnvSampler = ptScene->sbtProbeData[0].uLambertianEnvSampler; + ptLightingDynamicData->uGlobalIndex = 0; + + gptGfx->reset_draw_stream(ptStream, 1); + *gptData->pdDrawCalls += 1.0; + pl_add_to_draw_stream(ptStream, (plDrawStreamData) + { + .tShader = ptScene->tLightingShader, + .auDynamicBuffers = { + tLightingDynamicData.uBufferHandle + }, + .atVertexBuffers = { + gptData->tFullQuadVertexBuffer + }, + .tIndexBuffer = gptData->tFullQuadIndexBuffer, + .uIndexOffset = 0, + .uTriangleCount = 2, + .atBindGroups = { + ptScene->tGlobalBindGroup, + ptView->tLightingBindGroup, + tSceneBG + }, + .auDynamicBufferOffsets = { + tLightingDynamicData.uByteOffset + }, + .uInstanceOffset = 0, + .uInstanceCount = 1 + }); + gptGfx->draw_stream(ptSceneEncoder, 1, &tArea); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~subpass 2 - forward~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - plBuffer* ptPShadowDataBuffer = gptGfx->get_buffer(ptDevice, ptScene->atPLightShadowDataBuffer[uFrameIdx]); - memcpy(ptPShadowDataBuffer->tMemoryAllocation.pHostMapped, ptScene->sbtPLightShadowData, sizeof(plGPULightShadowData) * pl_sb_size(ptScene->sbtPLightShadowData)); - - plBuffer* ptSShadowDataBuffer = gptGfx->get_buffer(ptDevice, ptScene->atSLightShadowDataBuffer[uFrameIdx]); - memcpy(ptSShadowDataBuffer->tMemoryAllocation.pHostMapped, ptScene->sbtSLightShadowData, sizeof(plGPULightShadowData) * pl_sb_size(ptScene->sbtSLightShadowData)); - - pl_sb_reset(ptScene->sbtPLightData); - pl_sb_reset(ptScene->sbtDLightData); - pl_sb_reset(ptScene->sbtSLightData); - for(uint32_t i = 0; i < pl_sb_size(sbtLights); i++) - { - const plLightComponent* ptLight = &sbtLights[i]; - - if(ptLight->tType == PL_LIGHT_TYPE_DIRECTIONAL) - { - - const plGPULight tLight = { - .fIntensity = ptLight->fIntensity, - .fRange = ptLight->fRange, - .tPosition = ptLight->tPosition, - .tDirection = ptLight->tDirection, - .tColor = ptLight->tColor, - .iShadowIndex = ptLight->tFlags & PL_LIGHT_FLAG_CAST_SHADOW ? pl_sb_size(ptScene->sbtDLightData) : 0, - .iCastShadow = ptLight->tFlags & PL_LIGHT_FLAG_CAST_SHADOW, - .iCascadeCount = (int)ptLight->uCascadeCount, - .iType = ptLight->tType - }; + gptGfx->next_subpass(ptSceneEncoder, NULL); - pl_sb_push(ptScene->sbtDLightData, tLight); - } - else if(ptLight->tType == PL_LIGHT_TYPE_POINT) - { - const plGPULight tLight = { - .fIntensity = ptLight->fIntensity, - .fRange = ptLight->fRange, - .tPosition = ptLight->tPosition, - .tDirection = ptLight->tDirection, - .tColor = ptLight->tColor, - .iShadowIndex = ptLight->tFlags & PL_LIGHT_FLAG_CAST_SHADOW ? pl_sb_size(ptScene->sbtPLightData) : 0, - .iCastShadow = ptLight->tFlags & PL_LIGHT_FLAG_CAST_SHADOW, - .iType = ptLight->tType - }; - pl_sb_push(ptScene->sbtPLightData, tLight); - } - else if(ptLight->tType == PL_LIGHT_TYPE_SPOT) - { - const plGPULight tLight = { - .fIntensity = ptLight->fIntensity, - .fRange = ptLight->fRange, - .tPosition = ptLight->tPosition, - .tDirection = ptLight->tDirection, - .tColor = ptLight->tColor, - .iShadowIndex = ptLight->tFlags & PL_LIGHT_FLAG_CAST_SHADOW ? pl_sb_size(ptScene->sbtSLightData) : 0, - .iCastShadow = ptLight->tFlags & PL_LIGHT_FLAG_CAST_SHADOW, - .iType = ptLight->tType, - .fInnerConeCos = cosf(ptLight->fInnerConeAngle), - .fOuterConeCos = cosf(ptLight->fOuterConeAngle), - }; - pl_sb_push(ptScene->sbtSLightData, tLight); - } - } + if(ptScene->tSkyboxTexture.uIndex != 0) + { - const plBindGroupLayout tLightBindGroupLayout2 = { - .atBufferBindings = { - { .uSlot = 0, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, - { .uSlot = 1, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, - { .uSlot = 2, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, - { .uSlot = 3, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, - { .uSlot = 4, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, - { .uSlot = 5, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, - { .uSlot = 6, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, - }, - .atSamplerBindings = { - {.uSlot = 7, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL} - }, - }; - const plBindGroupDesc tLightBGDesc = { - .ptPool = gptData->aptTempGroupPools[gptGfx->get_current_frame_index()], - .ptLayout = &tLightBindGroupLayout2, - .pcDebugName = "light bind group 2" + const plBindGroupUpdateBufferData tSkyboxBG0BufferData = { + .tBuffer = ptView->atGlobalBuffers[uFrameIdx], + .uSlot = 0, + .szBufferRange = sizeof(BindGroup_0) }; - plBindGroupHandle tLightBindGroup2 = gptGfx->create_bind_group(ptDevice, &tLightBGDesc); - const plBindGroupUpdateBufferData atLightBufferData[] = - { - { .uSlot = 0, .tBuffer = ptView->atGlobalBuffers[uFrameIdx], .szBufferRange = sizeof(BindGroup_0) }, - { .uSlot = 1, .tBuffer = ptScene->atDLightBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULight) * pl_sb_size(ptScene->sbtDLightData)}, - { .uSlot = 2, .tBuffer = ptScene->atPLightBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULight) * pl_sb_size(ptScene->sbtPLightData)}, - { .uSlot = 3, .tBuffer = ptScene->atSLightBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULight) * pl_sb_size(ptScene->sbtSLightData)}, - { .uSlot = 4, .tBuffer = ptView->atDLightShadowDataBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULightShadowData) * pl_sb_size(ptView->sbtDLightShadowData)}, - { .uSlot = 5, .tBuffer = ptScene->atPLightShadowDataBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULightShadowData) * pl_sb_size(ptScene->sbtPLightShadowData)}, - { .uSlot = 6, .tBuffer = ptScene->atSLightShadowDataBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULightShadowData) * pl_sb_size(ptScene->sbtSLightShadowData)}, + plBindGroupUpdateData tSkyboxBG0Data = { + .uBufferCount = 1, + .atBufferBindings = &tSkyboxBG0BufferData, + .uSamplerCount = 1, + .atSamplerBindings = &tSkyboxSamplerData, }; - plBindGroupUpdateSamplerData tShadowSamplerData[] = { - { - .tSampler = gptData->tShadowSampler, - .uSlot = 7 - } - }; + plBindGroupHandle tSkyboxBG0 = gptGfx->create_bind_group(ptDevice, &tSkyboxBG0Desc); + gptGfx->update_bind_group(gptData->ptDevice, tSkyboxBG0, &tSkyboxBG0Data); + gptGfx->queue_bind_group_for_deletion(ptDevice, tSkyboxBG0); + + plDynamicBinding tSkyboxDynamicData = pl__allocate_dynamic_data(ptDevice); + plSkyboxDynamicData* ptSkyboxDynamicData = (plSkyboxDynamicData*)tSkyboxDynamicData.pcData; + ptSkyboxDynamicData->tModel = pl_mat4_translate_vec3(ptCamera->tPos); + ptSkyboxDynamicData->uGlobalIndex = 0; - plBindGroupUpdateData tBGData2 = { - .uBufferCount = 7, - .atBufferBindings = atLightBufferData, - .uSamplerCount = 1, - .atSamplerBindings = tShadowSamplerData - }; - gptGfx->update_bind_group(gptData->ptDevice, tLightBindGroup2, &tBGData2); - gptGfx->queue_bind_group_for_deletion(ptDevice, tLightBindGroup2); - plBuffer* ptDLightingBuffer = gptGfx->get_buffer(ptDevice, ptScene->atDLightBuffer[uFrameIdx]); - plBuffer* ptPLightingBuffer = gptGfx->get_buffer(ptDevice, ptScene->atPLightBuffer[uFrameIdx]); - plBuffer* ptSLightingBuffer = gptGfx->get_buffer(ptDevice, ptScene->atSLightBuffer[uFrameIdx]); - memcpy(ptDLightingBuffer->tMemoryAllocation.pHostMapped, ptScene->sbtDLightData, sizeof(plGPULight) * pl_sb_size(ptScene->sbtDLightData)); - memcpy(ptPLightingBuffer->tMemoryAllocation.pHostMapped, ptScene->sbtPLightData, sizeof(plGPULight) * pl_sb_size(ptScene->sbtPLightData)); - memcpy(ptSLightingBuffer->tMemoryAllocation.pHostMapped, ptScene->sbtSLightData, sizeof(plGPULight) * pl_sb_size(ptScene->sbtSLightData)); - - typedef struct _plLightingDynamicData{ - int iDataOffset; - int iVertexOffset; - int unused[2]; - } plLightingDynamicData; - plDynamicBinding tLightingDynamicData = pl__allocate_dynamic_data(ptDevice); - gptGfx->reset_draw_stream(ptStream, 1); *gptData->pdDrawCalls += 1.0; pl_add_to_draw_stream(ptStream, (plDrawStreamData) { - .tShader = ptScene->tLightingShader, + .tShader = gptData->tSkyboxShader, .auDynamicBuffers = { - tLightingDynamicData.uBufferHandle + tSkyboxDynamicData.uBufferHandle }, .atVertexBuffers = { - gptData->tFullQuadVertexBuffer + ptScene->tVertexBuffer, }, - .tIndexBuffer = gptData->tFullQuadIndexBuffer, - .uIndexOffset = 0, - .uTriangleCount = 2, + .tIndexBuffer = ptScene->tIndexBuffer, + .uIndexOffset = ptScene->tSkyboxDrawable.uIndexOffset, + .uTriangleCount = ptScene->tSkyboxDrawable.uIndexCount / 3, .atBindGroups = { - ptScene->tGlobalBindGroup, - ptView->tLightingBindGroup[uFrameIdx], - tLightBindGroup2 + tSkyboxBG0, + ptScene->tSkyboxBindGroup }, .auDynamicBufferOffsets = { - tLightingDynamicData.uByteOffset + tSkyboxDynamicData.uByteOffset }, .uInstanceOffset = 0, - .uInstanceCount = 1 + .uInstanceCount = 1 }); - gptGfx->draw_stream(ptEncoder, 1, &tArea); - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~subpass 2 - forward~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - gptGfx->next_subpass(ptEncoder, NULL); - - if(ptScene->tSkyboxTexture.uIndex != 0) + gptGfx->draw_stream(ptSceneEncoder, 1, &tArea); + } + + gptJob->wait_for_counter(ptForwardCounter); + if(ptCullCamera) + { + pl_sb_reset(ptView->sbtVisibleTransparentDrawables); + for(uint32_t uDrawableIndex = 0; uDrawableIndex < uForwardDrawableCount; uDrawableIndex++) { - - plDynamicBinding tSkyboxDynamicData = pl__allocate_dynamic_data(ptDevice); - plMat4* ptSkyboxDynamicData = (plMat4*)tSkyboxDynamicData.pcData; - *ptSkyboxDynamicData = pl_mat4_translate_vec3(ptCamera->tPos); - - gptGfx->reset_draw_stream(ptStream, 1); - *gptData->pdDrawCalls += 1.0; - pl_add_to_draw_stream(ptStream, (plDrawStreamData) - { - .tShader = gptData->tSkyboxShader, - .auDynamicBuffers = { - tSkyboxDynamicData.uBufferHandle - }, - .atVertexBuffers = { - ptScene->tVertexBuffer, - }, - .tIndexBuffer = ptScene->tIndexBuffer, - .uIndexOffset = ptScene->tSkyboxDrawable.uIndexOffset, - .uTriangleCount = ptScene->tSkyboxDrawable.uIndexCount / 3, - .atBindGroups = { - tSkyboxViewBindGroup, - ptScene->tSkyboxBindGroup - }, - .auDynamicBufferOffsets = { - tSkyboxDynamicData.uByteOffset - }, - .uInstanceOffset = 0, - .uInstanceCount = 1 - }); - gptGfx->draw_stream(ptEncoder, 1, &tArea); + const plDrawable tDrawable = ptScene->sbtForwardDrawables[uDrawableIndex]; + if(!tDrawable.bCulled) + pl_sb_push(ptView->sbtVisibleTransparentDrawables, tDrawable); } - + } - // transparent & complex material objects - gptJob->wait_for_counter(ptTransparentCounter); - if(ptCullCamera) - { - pl_sb_reset(ptView->sbtVisibleTransparentDrawables); - for(uint32_t uDrawableIndex = 0; uDrawableIndex < uTransparentDrawableCount; uDrawableIndex++) - { - const plDrawable tDrawable = ptScene->sbtForwardDrawables[uDrawableIndex]; - if(!tDrawable.bCulled) - pl_sb_push(ptView->sbtVisibleTransparentDrawables, tDrawable); - } - } + const uint32_t uVisibleForwardDrawCount = pl_sb_size(ptView->sbtVisibleTransparentDrawables); + gptGfx->reset_draw_stream(ptStream, uVisibleForwardDrawCount); + *gptData->pdDrawCalls += (double)uVisibleForwardDrawCount; + for(uint32_t i = 0; i < uVisibleForwardDrawCount; i++) + { + const plDrawable tDrawable = ptView->sbtVisibleTransparentDrawables[i]; + plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); + plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); + + plDynamicBinding tDynamicBinding = pl__allocate_dynamic_data(ptDevice); + + DynamicData* ptDynamicData = (DynamicData*)tDynamicBinding.pcData; + ptDynamicData->iDataOffset = tDrawable.uDataOffset; + ptDynamicData->iVertexOffset = tDrawable.uIndexCount == 0 ? 0 : tDrawable.uVertexOffset; + ptDynamicData->tModel = ptTransform->tWorld; + ptDynamicData->iMaterialOffset = tDrawable.uMaterialIndex; + ptDynamicData->uGGXEnvSampler = ptScene->sbtProbeData[0].uGGXEnvSampler; + ptDynamicData->uGGXLUT = ptScene->sbtProbeData[0].uGGXLUT; + ptDynamicData->uLambertianEnvSampler = ptScene->sbtProbeData[0].uLambertianEnvSampler; + ptDynamicData->uGlobalIndex = 0; - const uint32_t uVisibleTransparentDrawCount = pl_sb_size(ptView->sbtVisibleTransparentDrawables); - gptGfx->reset_draw_stream(ptStream, uVisibleTransparentDrawCount); - *gptData->pdDrawCalls += (double)uVisibleTransparentDrawCount; - for(uint32_t i = 0; i < uVisibleTransparentDrawCount; i++) + pl_add_to_draw_stream(ptStream, (plDrawStreamData) { - const plDrawable tDrawable = ptView->sbtVisibleTransparentDrawables[i]; - plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); - plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); - - plDynamicBinding tDynamicBinding = pl__allocate_dynamic_data(ptDevice); - - DynamicData* ptDynamicData = (DynamicData*)tDynamicBinding.pcData; - ptDynamicData->iDataOffset = tDrawable.uDataOffset; - ptDynamicData->iVertexOffset = tDrawable.uIndexCount == 0 ? 0 : tDrawable.uVertexOffset; - ptDynamicData->tModel = ptTransform->tWorld; - ptDynamicData->iMaterialOffset = tDrawable.uMaterialIndex; - - pl_add_to_draw_stream(ptStream, (plDrawStreamData) - { - .tShader = tDrawable.tShader, - .auDynamicBuffers = { - tDynamicBinding.uBufferHandle - }, - .atVertexBuffers = { - ptScene->tVertexBuffer, - }, - .tIndexBuffer = tDrawable.uIndexCount == 0 ? (plBufferHandle){0} : ptScene->tIndexBuffer, - .uIndexOffset = tDrawable.uIndexOffset, - .uTriangleCount = tDrawable.uIndexCount == 0 ? tDrawable.uVertexCount / 3 : tDrawable.uIndexCount / 3, - .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, - .atBindGroups = { - ptScene->tGlobalBindGroup, - tLightBindGroup2 - }, - .auDynamicBufferOffsets = { - tDynamicBinding.uByteOffset - }, - .uInstanceOffset = 0, - .uInstanceCount = 1 - }); - } - gptGfx->draw_stream(ptEncoder, 1, &tArea); + .tShader = tDrawable.tShader, + .auDynamicBuffers = { + tDynamicBinding.uBufferHandle + }, + .atVertexBuffers = { + ptScene->tVertexBuffer, + }, + .tIndexBuffer = tDrawable.uIndexCount == 0 ? (plBufferHandle){0} : ptScene->tIndexBuffer, + .uIndexOffset = tDrawable.uIndexOffset, + .uTriangleCount = tDrawable.uIndexCount == 0 ? tDrawable.uVertexCount / 3 : tDrawable.uIndexCount / 3, + .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, + .atBindGroups = { + ptScene->tGlobalBindGroup, + tSceneBG + }, + .auDynamicBufferOffsets = { + tDynamicBinding.uByteOffset + }, + .uInstanceOffset = 0, + .uInstanceCount = 1 + }); + } + gptGfx->draw_stream(ptSceneEncoder, 1, &tArea); - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~debug drawing~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~debug drawing~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // bounding boxes - const uint32_t uOutlineDrawableCount = pl_sb_size(ptScene->sbtOutlineDrawables); - if(uOutlineDrawableCount > 0 && gptData->bShowSelectedBoundingBox) + // bounding boxes + const uint32_t uOutlineDrawableCount = pl_sb_size(ptScene->sbtOutlineDrawables); + if(uOutlineDrawableCount > 0 && gptData->bShowSelectedBoundingBox) + { + const plVec4 tOutlineColor = (plVec4){0.0f, (float)sin(gptIOI->get_io()->dTime * 3.0) * 0.25f + 0.75f, 0.0f, 1.0f}; + for(uint32_t i = 0; i < uOutlineDrawableCount; i++) { - const plVec4 tOutlineColor = (plVec4){0.0f, (float)sin(gptIOI->get_io()->dTime * 3.0) * 0.25f + 0.75f, 0.0f, 1.0f}; - for(uint32_t i = 0; i < uOutlineDrawableCount; i++) - { - const plDrawable tDrawable = ptScene->sbtOutlineDrawables[i]; - plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); - plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptObject->tMesh); - gptDraw->add_3d_aabb(ptView->pt3DSelectionDrawList, ptMesh->tAABBFinal.tMin, ptMesh->tAABBFinal.tMax, (plDrawLineOptions){.uColor = PL_COLOR_32_VEC4(tOutlineColor), .fThickness = 0.01f}); - - } + const plDrawable tDrawable = ptScene->sbtOutlineDrawables[i]; + plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); + plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptObject->tMesh); + gptDraw->add_3d_aabb(ptView->pt3DSelectionDrawList, ptMesh->tAABBFinal.tMin, ptMesh->tAABBFinal.tMax, (plDrawLineOptions){.uColor = PL_COLOR_32_VEC4(tOutlineColor), .fThickness = 0.01f}); + } + } - // light drawing (temporary) - for(uint32_t i = 0; i < pl_sb_size(sbtLights); i++) + // light drawing + for(uint32_t i = 0; i < uLightCount; i++) + { + if(sbtLights[i].tFlags & PL_LIGHT_FLAG_VISUALIZER) { - if(sbtLights[i].tFlags & PL_LIGHT_FLAG_VISUALIZER) + const plVec4 tColor = {.rgb = sbtLights[i].tColor, .a = 1.0f}; + if(sbtLights[i].tType == PL_LIGHT_TYPE_POINT) { - const plVec4 tColor = {.rgb = sbtLights[i].tColor, .a = 1.0f}; - if(sbtLights[i].tType == PL_LIGHT_TYPE_POINT) - { - plDrawSphereDesc tSphere = { - .fRadius = sbtLights[i].fRadius, - .tCenter = sbtLights[i].tPosition, - .uLatBands = 6, - .uLongBands = 6 - }; - gptDraw->add_3d_sphere(ptView->pt3DDrawList, tSphere, (plDrawLineOptions){.uColor = PL_COLOR_32_VEC4(tColor), .fThickness = 0.005f}); - tSphere.fRadius = sbtLights[i].fRange; - plDrawSphereDesc tSphere2 = { - .fRadius = sbtLights[i].fRange, - .tCenter = sbtLights[i].tPosition - }; - gptDraw->add_3d_sphere(ptView->pt3DDrawList, tSphere2, (plDrawLineOptions){.uColor = PL_COLOR_32_VEC4(tColor), .fThickness = 0.01f}); - } - else if(sbtLights[i].tType == PL_LIGHT_TYPE_SPOT) + plDrawSphereDesc tSphere = { + .fRadius = sbtLights[i].fRadius, + .tCenter = sbtLights[i].tPosition, + .uLatBands = 6, + .uLongBands = 6 + }; + gptDraw->add_3d_sphere(ptView->pt3DDrawList, tSphere, (plDrawLineOptions){.uColor = PL_COLOR_32_VEC4(tColor), .fThickness = 0.005f}); + tSphere.fRadius = sbtLights[i].fRange; + plDrawSphereDesc tSphere2 = { + .fRadius = sbtLights[i].fRange, + .tCenter = sbtLights[i].tPosition + }; + gptDraw->add_3d_sphere(ptView->pt3DDrawList, tSphere2, (plDrawLineOptions){.uColor = PL_COLOR_32_VEC4(tColor), .fThickness = 0.01f}); + } + else if(sbtLights[i].tType == PL_LIGHT_TYPE_SPOT) + { + plDrawConeDesc tCone0 = { + .fRadius = tanf(sbtLights[i].fOuterConeAngle) * sbtLights[i].fRange, + .tTipPos = sbtLights[i].tPosition, + .tBasePos = pl_add_vec3(sbtLights[i].tPosition, pl_mul_vec3_scalarf(sbtLights[i].tDirection, sbtLights[i].fRange)) + }; + gptDraw->add_3d_cone(ptView->pt3DDrawList, tCone0, (plDrawLineOptions){.uColor = PL_COLOR_32_VEC4(tColor), .fThickness = 0.01f}); + + if(sbtLights[i].fInnerConeAngle > 0.0f) { - plDrawConeDesc tCone0 = { - .fRadius = tanf(sbtLights[i].fOuterConeAngle) * sbtLights[i].fRange, + plDrawConeDesc tCone1 = { + .fRadius = tanf(sbtLights[i].fInnerConeAngle) * sbtLights[i].fRange, .tTipPos = sbtLights[i].tPosition, .tBasePos = pl_add_vec3(sbtLights[i].tPosition, pl_mul_vec3_scalarf(sbtLights[i].tDirection, sbtLights[i].fRange)) }; - gptDraw->add_3d_cone(ptView->pt3DDrawList, tCone0, (plDrawLineOptions){.uColor = PL_COLOR_32_VEC4(tColor), .fThickness = 0.01f}); - - if(sbtLights[i].fInnerConeAngle > 0.0f) - { - plDrawConeDesc tCone1 = { - .fRadius = tanf(sbtLights[i].fInnerConeAngle) * sbtLights[i].fRange, - .tTipPos = sbtLights[i].tPosition, - .tBasePos = pl_add_vec3(sbtLights[i].tPosition, pl_mul_vec3_scalarf(sbtLights[i].tDirection, sbtLights[i].fRange)) - }; - gptDraw->add_3d_cone(ptView->pt3DDrawList, tCone1, (plDrawLineOptions){.uColor = PL_COLOR_32_VEC4(tColor), .fThickness = 0.01f}); - } + gptDraw->add_3d_cone(ptView->pt3DDrawList, tCone1, (plDrawLineOptions){.uColor = PL_COLOR_32_VEC4(tColor), .fThickness = 0.01f}); } + } - else if(sbtLights[i].tType == PL_LIGHT_TYPE_DIRECTIONAL) - { - plVec3 tDirection = pl_norm_vec3(sbtLights[i].tDirection); - plDrawConeDesc tCone0 = { - .fRadius = 0.125f, - .tBasePos = (plVec3){0.0f, 3.0f, 0.0f}, - .tTipPos = pl_add_vec3((plVec3){0.0f, 3.0f, 0.0f}, pl_mul_vec3_scalarf(tDirection, 0.25f)) - }; - gptDraw->add_3d_cone(ptView->pt3DDrawList, tCone0, (plDrawLineOptions){.uColor = PL_COLOR_32_VEC4(tColor), .fThickness = 0.01f}); - plDrawCylinderDesc tCylinder = { - .fRadius = 0.0625f, - .tBasePos = tCone0.tBasePos, - .tTipPos = pl_add_vec3((plVec3){0.0f, 3.0f, 0.0f}, pl_mul_vec3_scalarf(tDirection, -0.25f)) - }; - gptDraw->add_3d_cylinder(ptView->pt3DDrawList, tCylinder, (plDrawLineOptions){.uColor = PL_COLOR_32_VEC4(tColor), .fThickness = 0.01f}); - } + else if(sbtLights[i].tType == PL_LIGHT_TYPE_DIRECTIONAL) + { + plVec3 tDirection = pl_norm_vec3(sbtLights[i].tDirection); + plDrawConeDesc tCone0 = { + .fRadius = 0.125f, + .tBasePos = (plVec3){0.0f, 3.0f, 0.0f}, + .tTipPos = pl_add_vec3((plVec3){0.0f, 3.0f, 0.0f}, pl_mul_vec3_scalarf(tDirection, 0.25f)) + }; + gptDraw->add_3d_cone(ptView->pt3DDrawList, tCone0, (plDrawLineOptions){.uColor = PL_COLOR_32_VEC4(tColor), .fThickness = 0.01f}); + plDrawCylinderDesc tCylinder = { + .fRadius = 0.0625f, + .tBasePos = tCone0.tBasePos, + .tTipPos = pl_add_vec3((plVec3){0.0f, 3.0f, 0.0f}, pl_mul_vec3_scalarf(tDirection, -0.25f)) + }; + gptDraw->add_3d_cylinder(ptView->pt3DDrawList, tCylinder, (plDrawLineOptions){.uColor = PL_COLOR_32_VEC4(tColor), .fThickness = 0.01f}); } } + } - // debug drawing - if(gptData->bDrawAllBoundingBoxes) + // debug drawing + if(gptData->bDrawAllBoundingBoxes) + { + for(uint32_t i = 0; i < uDeferredDrawableCount; i++) { - for(uint32_t i = 0; i < uOpaqueDrawableCount; i++) - { - plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptScene->sbtDeferredDrawables[i].tEntity); + plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptScene->sbtDeferredDrawables[i].tEntity); - gptDraw->add_3d_aabb(ptView->pt3DDrawList, ptMesh->tAABBFinal.tMin, ptMesh->tAABBFinal.tMax, (plDrawLineOptions){.uColor = PL_COLOR_32_RGB(1.0f, 0.0f, 0.0f), .fThickness = 0.02f}); - } - for(uint32_t i = 0; i < uTransparentDrawableCount; i++) - { - plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptScene->sbtForwardDrawables[i].tEntity); - - gptDraw->add_3d_aabb(ptView->pt3DDrawList, ptMesh->tAABBFinal.tMin, ptMesh->tAABBFinal.tMax, (plDrawLineOptions){.uColor = PL_COLOR_32_RGB(1.0f, 0.0f, 0.0f), .fThickness = 0.02f}); - } + gptDraw->add_3d_aabb(ptView->pt3DDrawList, ptMesh->tAABBFinal.tMin, ptMesh->tAABBFinal.tMax, (plDrawLineOptions){.uColor = PL_COLOR_32_RGB(1.0f, 0.0f, 0.0f), .fThickness = 0.02f}); } - else if(gptData->bDrawVisibleBoundingBoxes) + for(uint32_t i = 0; i < uForwardDrawableCount; i++) { - for(uint32_t i = 0; i < uVisibleOpaqueDrawCount; i++) - { - plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptView->sbtVisibleOpaqueDrawables[i].tEntity); - - gptDraw->add_3d_aabb(ptView->pt3DDrawList, ptMesh->tAABBFinal.tMin, ptMesh->tAABBFinal.tMax, (plDrawLineOptions){.uColor = PL_COLOR_32_RGB(1.0f, 0.0f, 0.0f), .fThickness = 0.02f}); - } - for(uint32_t i = 0; i < uVisibleTransparentDrawCount; i++) - { - plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptView->sbtVisibleTransparentDrawables[i].tEntity); + plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptScene->sbtForwardDrawables[i].tEntity); - gptDraw->add_3d_aabb(ptView->pt3DDrawList, ptMesh->tAABBFinal.tMin, ptMesh->tAABBFinal.tMax, (plDrawLineOptions){.uColor = PL_COLOR_32_RGB(1.0f, 0.0f, 0.0f), .fThickness = 0.02f}); - } + gptDraw->add_3d_aabb(ptView->pt3DDrawList, ptMesh->tAABBFinal.tMin, ptMesh->tAABBFinal.tMax, (plDrawLineOptions){.uColor = PL_COLOR_32_RGB(1.0f, 0.0f, 0.0f), .fThickness = 0.02f}); } - - if(gptData->bShowOrigin) + } + else if(gptData->bDrawVisibleBoundingBoxes) + { + for(uint32_t i = 0; i < uVisibleDeferredDrawCount; i++) { - const plMat4 tTransform = pl_identity_mat4(); - gptDraw->add_3d_transform(ptView->pt3DDrawList, &tTransform, 10.0f, (plDrawLineOptions){.fThickness = 0.02f}); - } + plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptView->sbtVisibleOpaqueDrawables[i].tEntity); - if(ptCullCamera && ptCullCamera != ptCamera) + gptDraw->add_3d_aabb(ptView->pt3DDrawList, ptMesh->tAABBFinal.tMin, ptMesh->tAABBFinal.tMax, (plDrawLineOptions){.uColor = PL_COLOR_32_RGB(1.0f, 0.0f, 0.0f), .fThickness = 0.02f}); + } + for(uint32_t i = 0; i < uVisibleForwardDrawCount; i++) { - plDrawFrustumDesc tFrustumDesc = { - .fAspectRatio = ptCullCamera->fAspectRatio, - .fFarZ = ptCullCamera->fFarZ, - .fNearZ = ptCullCamera->fNearZ, - .fYFov = ptCullCamera->fFieldOfView - }; - gptDraw->add_3d_frustum(ptView->pt3DSelectionDrawList, &ptCullCamera->tTransformMat, tFrustumDesc, (plDrawLineOptions){.uColor = PL_COLOR_32_YELLOW, .fThickness = 0.02f}); + plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptView->sbtVisibleTransparentDrawables[i].tEntity); + + gptDraw->add_3d_aabb(ptView->pt3DDrawList, ptMesh->tAABBFinal.tMin, ptMesh->tAABBFinal.tMax, (plDrawLineOptions){.uColor = PL_COLOR_32_RGB(1.0f, 0.0f, 0.0f), .fThickness = 0.02f}); } + } + + if(gptData->bShowOrigin) + { + const plMat4 tTransform = pl_identity_mat4(); + gptDraw->add_3d_transform(ptView->pt3DDrawList, &tTransform, 10.0f, (plDrawLineOptions){.fThickness = 0.02f}); + } + + if(ptCullCamera && ptCullCamera != ptCamera) + { + const plDrawFrustumDesc tFrustumDesc = { + .fAspectRatio = ptCullCamera->fAspectRatio, + .fFarZ = ptCullCamera->fFarZ, + .fNearZ = ptCullCamera->fNearZ, + .fYFov = ptCullCamera->fFieldOfView + }; + gptDraw->add_3d_frustum(ptView->pt3DSelectionDrawList, &ptCullCamera->tTransformMat, tFrustumDesc, (plDrawLineOptions){.uColor = PL_COLOR_32_YELLOW, .fThickness = 0.02f}); + } + + gptDrawBackend->submit_3d_drawlist(ptView->pt3DDrawList, ptSceneEncoder, tDimensions.x, tDimensions.y, &tMVP, PL_DRAW_FLAG_REVERSE_Z_DEPTH | PL_DRAW_FLAG_DEPTH_TEST | PL_DRAW_FLAG_DEPTH_WRITE, 1); + gptDrawBackend->submit_3d_drawlist(ptView->pt3DSelectionDrawList, ptSceneEncoder, tDimensions.x, tDimensions.y, &tMVP, 0, 1); + gptGfx->end_render_pass(ptSceneEncoder); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~entity selection~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // TODO: decide on selection from multiple views + + if(gptData->uClickedFrame == uFrameIdx && uViewHandle == 0) + { + gptData->uClickedFrame = UINT32_MAX; + plTexture* ptTexture = gptGfx->get_texture(ptDevice, ptView->tPickTexture); + plBuffer* ptCachedStagingBuffer = gptGfx->get_buffer(ptDevice, gptData->tCachedStagingBuffer); + const plVec2 tMousePos = gptIOI->get_mouse_pos(); + + uint32_t uRowWidth = (uint32_t)ptTexture->tDesc.tDimensions.x * 4; + uint32_t uPos = uRowWidth * (uint32_t)tMousePos.y + (uint32_t)tMousePos.x * 4; + + unsigned char* pucMapping2 = (unsigned char*)ptCachedStagingBuffer->tMemoryAllocation.pHostMapped; + unsigned char* pucMapping = &pucMapping2[uPos]; + gptData->tPickedEntity.uIndex = pucMapping[0] + 256 * pucMapping[1] + 65536 * pucMapping[2]; + gptData->tPickedEntity.uGeneration = ptScene->tComponentLibrary.sbtEntityGenerations[gptData->tPickedEntity.uIndex]; + + // plImageWriteInfo tBlah = { + // .iWidth = (int)ptTexture->tDesc.tDimensions.x, + // .iHeight = (int)ptTexture->tDesc.tDimensions.y, + // .iComponents = 4, + // .iByteStride = 4 * (int)ptTexture->tDesc.tDimensions.x + // }; + // gptImage->write("pick.png", pucMapping2, &tBlah); + } + + bool bOwnMouse = gptUI->wants_mouse_capture(); + bool bRenderPickTexture = false; + if(!bOwnMouse && gptIOI->is_mouse_clicked(PL_MOUSE_BUTTON_RIGHT, false) && uViewHandle == 0) + { + gptData->uClickedFrame = uFrameIdx; + + const plBindGroupUpdateBufferData tPickBG0BufferData = { + .tBuffer = ptView->atGlobalBuffers[uFrameIdx], + .uSlot = 0, + .szBufferRange = sizeof(BindGroup_0) + }; - gptDrawBackend->submit_3d_drawlist(ptView->pt3DDrawList, ptEncoder, tDimensions.x, tDimensions.y, &tMVP, PL_DRAW_FLAG_REVERSE_Z_DEPTH | PL_DRAW_FLAG_DEPTH_TEST | PL_DRAW_FLAG_DEPTH_WRITE, 1); - gptDrawBackend->submit_3d_drawlist(ptView->pt3DSelectionDrawList, ptEncoder, tDimensions.x, tDimensions.y, &tMVP, 0, 1); - gptGfx->end_render_pass(ptEncoder); + const plBindGroupUpdateData tPickBGData0 = { + .uBufferCount = 1, + .atBufferBindings = &tPickBG0BufferData, + }; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~entity selection~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + plBindGroupHandle tPickBG0 = gptGfx->create_bind_group(ptDevice, &tPickBGDesc); + gptGfx->update_bind_group(gptData->ptDevice, tPickBG0, &tPickBGData0); + gptGfx->queue_bind_group_for_deletion(ptDevice, tPickBG0); - if(gptData->uClickedFrame == uFrameIdx && uViewHandle == 0) + typedef struct _plPickDynamicData { - gptData->uClickedFrame = UINT32_MAX; - plTexture* ptTexture = gptGfx->get_texture(ptDevice, ptView->tPickTexture); - plBuffer* ptCachedStagingBuffer = gptGfx->get_buffer(ptDevice, gptData->tCachedStagingBuffer); - const plVec2 tMousePos = gptIOI->get_mouse_pos(); - - uint32_t uRowWidth = (uint32_t)ptTexture->tDesc.tDimensions.x * 4; - uint32_t uPos = uRowWidth * (uint32_t)tMousePos.y + (uint32_t)tMousePos.x * 4; - - unsigned char* pucMapping2 = (unsigned char*)ptCachedStagingBuffer->tMemoryAllocation.pHostMapped; - unsigned char* pucMapping = &pucMapping2[uPos]; - gptData->tPickedEntity.uIndex = pucMapping[0] + 256 * pucMapping[1] + 65536 * pucMapping[2]; - gptData->tPickedEntity.uGeneration = ptScene->tComponentLibrary.sbtEntityGenerations[gptData->tPickedEntity.uIndex]; - - // plImageWriteInfo tBlah = { - // .iWidth = (int)ptTexture->tDesc.tDimensions.x, - // .iHeight = (int)ptTexture->tDesc.tDimensions.y, - // .iComponents = 4, - // .iByteStride = 4 * (int)ptTexture->tDesc.tDimensions.x - // }; - // gptImage->write("pick.png", pucMapping2, &tBlah); - } + plVec4 tColor; + plMat4 tModel; + } plPickDynamicData; + plRenderEncoder* ptPickEncoder = gptGfx->begin_render_pass(ptSceneCmdBuffer, ptView->tPickRenderPass, NULL); - bool bOwnMouse = gptUI->wants_mouse_capture(); - bool bRenderPickTexture = false; - if(!bOwnMouse && gptIOI->is_mouse_clicked(PL_MOUSE_BUTTON_RIGHT, false) && uViewHandle == 0) + gptGfx->bind_shader(ptPickEncoder, gptData->tPickShader); + gptGfx->bind_vertex_buffer(ptPickEncoder, ptScene->tVertexBuffer); + *gptData->pdDrawCalls += (double)uVisibleDeferredDrawCount; + for(uint32_t i = 0; i < uVisibleDeferredDrawCount; i++) { - gptData->uClickedFrame = uFrameIdx; + const plDrawable tDrawable = ptView->sbtVisibleOpaqueDrawables[i]; - plBindGroupLayout tPickBindGroupLayout0 = { - .atBufferBindings = { - { - .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, - .uSlot = 0, - .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL - } - } + uint32_t uId = tDrawable.tEntity.uIndex; + + plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); + plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); + + plDynamicBinding tDynamicBinding = pl__allocate_dynamic_data(ptDevice); + plPickDynamicData* ptDynamicData = (plPickDynamicData*)tDynamicBinding.pcData; + + ptDynamicData->tColor = (plVec4){ + ((float)(uId & 0x000000ff) / 255.0f), + ((float)((uId & 0x0000ff00) >> 8) / 255.0f), + ((float)((uId & 0x00ff0000) >> 16) / 255.0f), + 1.0f}; + ptDynamicData->tModel = ptTransform->tWorld; - }; - const plBindGroupDesc tPickBGDesc = { - .ptPool = gptData->aptTempGroupPools[gptGfx->get_current_frame_index()], - .ptLayout = &tPickBindGroupLayout0, - .pcDebugName = "temp pick bind group" - }; - plBindGroupHandle tPickBindGroup = gptGfx->create_bind_group(ptDevice, &tPickBGDesc); + gptGfx->bind_graphics_bind_groups(ptPickEncoder, gptData->tPickShader, 0, 1, &tPickBG0, 1, &tDynamicBinding); - const plBindGroupUpdateBufferData atPickBufferData[] = - { - { - .tBuffer = ptView->atGlobalBuffers[uFrameIdx], - .uSlot = 0, - .szBufferRange = sizeof(BindGroup_0) - } - }; - plBindGroupUpdateData tPickBGData0 = { - .uBufferCount = 1, - .atBufferBindings = atPickBufferData, - }; - gptGfx->update_bind_group(gptData->ptDevice, tPickBindGroup, &tPickBGData0); - gptGfx->queue_bind_group_for_deletion(ptDevice, tPickBindGroup); - - typedef struct _plPickDynamicData + if(tDrawable.uIndexCount > 0) { - plVec4 tColor; - plMat4 tModel; - } plPickDynamicData; - ptEncoder = gptGfx->begin_render_pass(ptCommandBuffer, ptView->tPickRenderPass, NULL); - - gptGfx->bind_shader(ptEncoder, gptData->tPickShader); - gptGfx->bind_vertex_buffer(ptEncoder, ptScene->tVertexBuffer); - *gptData->pdDrawCalls += (double)uVisibleOpaqueDrawCount; - for(uint32_t i = 0; i < uVisibleOpaqueDrawCount; i++) - { - const plDrawable tDrawable = ptView->sbtVisibleOpaqueDrawables[i]; - - uint32_t uId = tDrawable.tEntity.uIndex; - - plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); - plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); - - plDynamicBinding tDynamicBinding = pl__allocate_dynamic_data(ptDevice); - plPickDynamicData* ptDynamicData = (plPickDynamicData*)tDynamicBinding.pcData; - - ptDynamicData->tColor = (plVec4){ - ((float)(uId & 0x000000ff) / 255.0f), - ((float)((uId & 0x0000ff00) >> 8) / 255.0f), - ((float)((uId & 0x00ff0000) >> 16) / 255.0f), - 1.0f}; - ptDynamicData->tModel = ptTransform->tWorld; - - gptGfx->bind_graphics_bind_groups(ptEncoder, gptData->tPickShader, 0, 1, &tPickBindGroup, 1, &tDynamicBinding); - - if(tDrawable.uIndexCount > 0) - { - plDrawIndex tDraw = { - .tIndexBuffer = ptScene->tIndexBuffer, - .uIndexCount = tDrawable.uIndexCount, - .uIndexStart = tDrawable.uIndexOffset, - .uInstanceCount = 1 - }; - gptGfx->draw_indexed(ptEncoder, 1, &tDraw); - } - else - { - plDraw tDraw = { - .uVertexStart = tDrawable.uVertexOffset, - .uInstanceCount = 1, - .uVertexCount = tDrawable.uVertexCount - }; - gptGfx->draw(ptEncoder, 1, &tDraw); - } + plDrawIndex tDraw = { + .tIndexBuffer = ptScene->tIndexBuffer, + .uIndexCount = tDrawable.uIndexCount, + .uIndexStart = tDrawable.uIndexOffset, + .uInstanceCount = 1 + }; + gptGfx->draw_indexed(ptPickEncoder, 1, &tDraw); } - - *gptData->pdDrawCalls += (double)uVisibleTransparentDrawCount; - for(uint32_t i = 0; i < uVisibleTransparentDrawCount; i++) + else { - const plDrawable tDrawable = ptView->sbtVisibleTransparentDrawables[i]; - - plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); - plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); - - plDynamicBinding tDynamicBinding = pl__allocate_dynamic_data(ptDevice); - plPickDynamicData* ptDynamicData = (plPickDynamicData*)tDynamicBinding.pcData; - const uint32_t uId = tDrawable.tEntity.uIndex; - ptDynamicData->tColor = (plVec4){ - ((float)(uId & 0x000000ff) / 255.0f), - ((float)((uId & 0x0000ff00) >> 8) / 255.0f), - ((float)((uId & 0x00ff0000) >> 16) / 255.0f), - 1.0f}; - ptDynamicData->tModel = ptTransform->tWorld; - - gptGfx->bind_graphics_bind_groups(ptEncoder, gptData->tPickShader, 0, 1, &tPickBindGroup, 1, &tDynamicBinding); - - if(tDrawable.uIndexCount > 0) - { - plDrawIndex tDraw = { - .tIndexBuffer = ptScene->tIndexBuffer, - .uIndexCount = tDrawable.uIndexCount, - .uIndexStart = tDrawable.uIndexOffset, - .uInstanceCount = 1 - }; - gptGfx->draw_indexed(ptEncoder, 1, &tDraw); - } - else - { - plDraw tDraw = { - .uVertexStart = tDrawable.uVertexOffset, - .uInstanceCount = 1, - .uVertexCount = tDrawable.uVertexCount - }; - gptGfx->draw(ptEncoder, 1, &tDraw); - } + plDraw tDraw = { + .uVertexStart = tDrawable.uVertexOffset, + .uInstanceCount = 1, + .uVertexCount = tDrawable.uVertexCount + }; + gptGfx->draw(ptPickEncoder, 1, &tDraw); } - gptGfx->end_render_pass(ptEncoder); + } + + *gptData->pdDrawCalls += (double)uVisibleForwardDrawCount; + for(uint32_t i = 0; i < uVisibleForwardDrawCount; i++) + { + const plDrawable tDrawable = ptView->sbtVisibleTransparentDrawables[i]; + + plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); + plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); + + plDynamicBinding tDynamicBinding = pl__allocate_dynamic_data(ptDevice); + plPickDynamicData* ptDynamicData = (plPickDynamicData*)tDynamicBinding.pcData; + const uint32_t uId = tDrawable.tEntity.uIndex; + ptDynamicData->tColor = (plVec4){ + ((float)(uId & 0x000000ff) / 255.0f), + ((float)((uId & 0x0000ff00) >> 8) / 255.0f), + ((float)((uId & 0x00ff0000) >> 16) / 255.0f), + 1.0f}; + ptDynamicData->tModel = ptTransform->tWorld; - plBuffer* ptCachedStagingBuffer = gptGfx->get_buffer(ptDevice, gptData->tCachedStagingBuffer); - memset(ptCachedStagingBuffer->tMemoryAllocation.pHostMapped, 0, ptCachedStagingBuffer->tDesc.szByteSize); + gptGfx->bind_graphics_bind_groups(ptPickEncoder, gptData->tPickShader, 0, 1, &tPickBG0, 1, &tDynamicBinding); - bRenderPickTexture = true; + if(tDrawable.uIndexCount > 0) + { + plDrawIndex tDraw = { + .tIndexBuffer = ptScene->tIndexBuffer, + .uIndexCount = tDrawable.uIndexCount, + .uIndexStart = tDrawable.uIndexOffset, + .uInstanceCount = 1 + }; + gptGfx->draw_indexed(ptPickEncoder, 1, &tDraw); + } + else + { + plDraw tDraw = { + .uVertexStart = tDrawable.uVertexOffset, + .uInstanceCount = 1, + .uVertexCount = tDrawable.uVertexCount + }; + gptGfx->draw(ptPickEncoder, 1, &tDraw); + } } + gptGfx->end_render_pass(ptPickEncoder); - gptGfx->end_command_recording(ptCommandBuffer); + plBuffer* ptCachedStagingBuffer = gptGfx->get_buffer(ptDevice, gptData->tCachedStagingBuffer); + memset(ptCachedStagingBuffer->tMemoryAllocation.pHostMapped, 0, ptCachedStagingBuffer->tDesc.szByteSize); - const plSubmitInfo tSubmitInfo = { - .uSignalSemaphoreCount = 1, - .atSignalSempahores = {tSemHandle}, - .auSignalSemaphoreValues = {++ulValue} - }; - gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo); - gptGfx->return_command_buffer(ptCommandBuffer); + bRenderPickTexture = true; + } + gptGfx->end_command_recording(ptSceneCmdBuffer); - ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); + const plSubmitInfo tSceneSubmitInfo = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptSceneCmdBuffer, &tSceneSubmitInfo); + gptGfx->return_command_buffer(ptSceneCmdBuffer); - const plBeginCommandInfo tBeginInfo2 = { - .uWaitSemaphoreCount = 1, - .atWaitSempahores = {tSemHandle}, - .auWaitSemaphoreValues = {ulValue}, - }; - gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo2); - if(bRenderPickTexture) - { - plBlitEncoder* ptBlitEncoder = gptGfx->begin_blit_pass(ptCommandBuffer); - gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE); - - plTexture* ptTexture = gptGfx->get_texture(ptDevice, ptView->tPickTexture); - const plBufferImageCopy tBufferImageCopy = { - .uImageWidth = (uint32_t)ptTexture->tDesc.tDimensions.x, - .uImageHeight = (uint32_t)ptTexture->tDesc.tDimensions.y, - .uImageDepth = 1, - .uLayerCount = 1 - }; - gptGfx->copy_texture_to_buffer(ptBlitEncoder, ptView->tPickTexture, gptData->tCachedStagingBuffer, 1, &tBufferImageCopy); - gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ); - gptGfx->end_blit_pass(ptBlitEncoder); - } + plCommandBuffer* ptPickingDecodeCmdBuffer = gptGfx->request_command_buffer(ptCmdPool); + + const plBeginCommandInfo tPickingDecodeBeginInfo = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; + gptGfx->begin_command_recording(ptPickingDecodeCmdBuffer, &tPickingDecodeBeginInfo); - gptGfx->end_command_recording(ptCommandBuffer); + if(bRenderPickTexture) + { + plBlitEncoder* ptBlitEncoder = gptGfx->begin_blit_pass(ptPickingDecodeCmdBuffer); + gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE); - const plSubmitInfo tSubmitInfo2 = { - .uSignalSemaphoreCount = 1, - .atSignalSempahores = {tSemHandle}, - .auSignalSemaphoreValues = {++ulValue} + plTexture* ptTexture = gptGfx->get_texture(ptDevice, ptView->tPickTexture); + const plBufferImageCopy tBufferImageCopy = { + .uImageWidth = (uint32_t)ptTexture->tDesc.tDimensions.x, + .uImageHeight = (uint32_t)ptTexture->tDesc.tDimensions.y, + .uImageDepth = 1, + .uLayerCount = 1 }; - gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo2); - gptGfx->return_command_buffer(ptCommandBuffer); + gptGfx->copy_texture_to_buffer(ptBlitEncoder, ptView->tPickTexture, gptData->tCachedStagingBuffer, 1, &tBufferImageCopy); + gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ); + gptGfx->end_blit_pass(ptBlitEncoder); } + gptGfx->end_command_recording(ptPickingDecodeCmdBuffer); + + const plSubmitInfo tPickingDecodeSubmitInfo = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptPickingDecodeCmdBuffer, &tPickingDecodeSubmitInfo); + gptGfx->return_command_buffer(ptPickingDecodeCmdBuffer); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~uv map pass for JFA~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - { - const plBeginCommandInfo tBeginInfo = { - .uWaitSemaphoreCount = 1, - .atWaitSempahores = {tSemHandle}, - .auWaitSemaphoreValues = {ulValue}, - }; - plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo); + const plBeginCommandInfo tUVBeginInfo = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; + + plCommandBuffer* ptUVCmdBuffer = gptGfx->request_command_buffer(ptCmdPool); + gptGfx->begin_command_recording(ptUVCmdBuffer, &tUVBeginInfo); - plRenderEncoder* ptEncoder = gptGfx->begin_render_pass(ptCommandBuffer, ptView->tUVRenderPass, NULL); + plRenderEncoder* ptUVEncoder = gptGfx->begin_render_pass(ptUVCmdBuffer, ptView->tUVRenderPass, NULL); - // submit nonindexed draw using basic API - gptGfx->bind_shader(ptEncoder, gptData->tUVShader); - gptGfx->bind_vertex_buffer(ptEncoder, gptData->tFullQuadVertexBuffer); + // submit nonindexed draw using basic API + gptGfx->bind_shader(ptUVEncoder, gptData->tUVShader); + gptGfx->bind_vertex_buffer(ptUVEncoder, gptData->tFullQuadVertexBuffer); - plDrawIndex tDraw = { - .tIndexBuffer = gptData->tFullQuadIndexBuffer, - .uIndexCount = 6, - .uInstanceCount = 1, - }; - *gptData->pdDrawCalls += 1.0; - gptGfx->draw_indexed(ptEncoder, 1, &tDraw); + plDrawIndex tDraw = { + .tIndexBuffer = gptData->tFullQuadIndexBuffer, + .uIndexCount = 6, + .uInstanceCount = 1, + }; + *gptData->pdDrawCalls += 1.0; + gptGfx->draw_indexed(ptUVEncoder, 1, &tDraw); - // end render pass - gptGfx->end_render_pass(ptEncoder); + // end render pass + gptGfx->end_render_pass(ptUVEncoder); - gptGfx->end_command_recording(ptCommandBuffer); + gptGfx->end_command_recording(ptUVCmdBuffer); - const plSubmitInfo tSubmitInfo = { - .uSignalSemaphoreCount = 1, - .atSignalSempahores = {tSemHandle}, - .auSignalSemaphoreValues = {++ulValue} - }; - gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo); - gptGfx->return_command_buffer(ptCommandBuffer); - } + const plSubmitInfo tUVSubmitInfo = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptUVCmdBuffer, &tUVSubmitInfo); + gptGfx->return_command_buffer(ptUVCmdBuffer); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~jump flood~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - { - const uint32_t uOutlineDrawableCount = pl_sb_size(ptScene->sbtOutlineDrawables); - - // find next power of 2 - uint32_t uJumpDistance = 1; - uint32_t uHalfWidth = gptData->uOutlineWidth / 2; - if (uHalfWidth && !(uHalfWidth & (uHalfWidth - 1))) - uJumpDistance = uHalfWidth; - while(uJumpDistance < uHalfWidth) - uJumpDistance <<= 1; - - // calculate number of jumps necessary - uint32_t uJumpSteps = 0; - while(uJumpDistance) - { - uJumpSteps++; - uJumpDistance >>= 1; - } - - float fJumpDistance = (float)uHalfWidth; - if(uOutlineDrawableCount == 0) - uJumpSteps = 1; - - const plDispatch tDispach = { - .uGroupCountX = (uint32_t)tDimensions.x / 8, - .uGroupCountY = (uint32_t)tDimensions.y / 8, - .uGroupCountZ = 1, - .uThreadPerGroupX = 8, - .uThreadPerGroupY = 8, - .uThreadPerGroupZ = 1 - }; + // find next power of 2 + uint32_t uJumpDistance = 1; + uint32_t uHalfWidth = gptData->uOutlineWidth / 2; + if (uHalfWidth && !(uHalfWidth & (uHalfWidth - 1))) + uJumpDistance = uHalfWidth; + while(uJumpDistance < uHalfWidth) + uJumpDistance <<= 1; + + // calculate number of jumps necessary + uint32_t uJumpSteps = 0; + while(uJumpDistance) + { + uJumpSteps++; + uJumpDistance >>= 1; + } - const plBindGroupLayout tJFABindGroupLayout = { - .atTextureBindings = { - {.uSlot = 0, .tStages = PL_STAGE_COMPUTE, .tType = PL_TEXTURE_BINDING_TYPE_STORAGE}, - {.uSlot = 1, .tStages = PL_STAGE_COMPUTE, .tType = PL_TEXTURE_BINDING_TYPE_STORAGE} - } - }; + float fJumpDistance = (float)uHalfWidth; + if(uOutlineDrawableCount == 0) + uJumpSteps = 1; - const plBindGroupDesc tJFABindGroupDesc = { - .ptPool = gptData->aptTempGroupPools[gptGfx->get_current_frame_index()], - .ptLayout = &tJFABindGroupLayout, - .pcDebugName = "temp jfa bind group" - }; - plBindGroupHandle atJFABindGroups[] = { - gptGfx->create_bind_group(gptData->ptDevice, &tJFABindGroupDesc), - gptGfx->create_bind_group(gptData->ptDevice, &tJFABindGroupDesc) - }; + const plDispatch tDispach = { + .uGroupCountX = (uint32_t)tDimensions.x / 8, + .uGroupCountY = (uint32_t)tDimensions.y / 8, + .uGroupCountZ = 1, + .uThreadPerGroupX = 8, + .uThreadPerGroupY = 8, + .uThreadPerGroupZ = 1 + }; - const plBindGroupUpdateTextureData atJFATextureData0[] = - { - { - .tTexture = ptView->atUVMaskTexture0[uFrameIdx], - .uSlot = 0, - .tType = PL_TEXTURE_BINDING_TYPE_STORAGE, - .tCurrentUsage = PL_TEXTURE_USAGE_STORAGE - }, - { - .tTexture = ptView->atUVMaskTexture1[uFrameIdx], - .uSlot = 1, - .tType = PL_TEXTURE_BINDING_TYPE_STORAGE, - .tCurrentUsage = PL_TEXTURE_USAGE_STORAGE - } - }; + plBindGroupHandle atJFABindGroups[] = { + gptGfx->create_bind_group(gptData->ptDevice, &tJFABindGroupDesc), + gptGfx->create_bind_group(gptData->ptDevice, &tJFABindGroupDesc) + }; - const plBindGroupUpdateTextureData atJFATextureData1[] = + const plBindGroupUpdateTextureData atJFATextureData0[] = + { { - { - .tTexture = ptView->atUVMaskTexture1[uFrameIdx], - .uSlot = 0, - .tType = PL_TEXTURE_BINDING_TYPE_STORAGE, + .tTexture = ptView->atUVMaskTexture0, + .uSlot = 0, + .tType = PL_TEXTURE_BINDING_TYPE_STORAGE, .tCurrentUsage = PL_TEXTURE_USAGE_STORAGE - }, - { - .tTexture = ptView->atUVMaskTexture0[uFrameIdx], - .uSlot = 1, - .tType = PL_TEXTURE_BINDING_TYPE_STORAGE, + }, + { + .tTexture = ptView->atUVMaskTexture1, + .uSlot = 1, + .tType = PL_TEXTURE_BINDING_TYPE_STORAGE, .tCurrentUsage = PL_TEXTURE_USAGE_STORAGE - } - }; - - const plBindGroupUpdateData tJFABGData0 = { - .uTextureCount = 2, - .atTextureBindings = atJFATextureData0 - }; - const plBindGroupUpdateData tJFABGData1 = { - .uTextureCount = 2, - .atTextureBindings = atJFATextureData1 - }; - gptGfx->update_bind_group(gptData->ptDevice, atJFABindGroups[0], &tJFABGData0); - gptGfx->update_bind_group(gptData->ptDevice, atJFABindGroups[1], &tJFABGData1); - gptGfx->queue_bind_group_for_deletion(gptData->ptDevice, atJFABindGroups[0]); - gptGfx->queue_bind_group_for_deletion(gptData->ptDevice, atJFABindGroups[1]); + } + }; - for(uint32_t i = 0; i < uJumpSteps; i++) + const plBindGroupUpdateTextureData atJFATextureData1[] = + { { - const plBeginCommandInfo tBeginInfo = { - .uWaitSemaphoreCount = 1, - .atWaitSempahores = {tSemHandle}, - .auWaitSemaphoreValues = {ulValue}, - }; - - plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo); - - // begin main renderpass (directly to swapchain) - plComputeEncoder* ptComputeEncoder = gptGfx->begin_compute_pass(ptCommandBuffer, NULL); - gptGfx->pipeline_barrier_compute(ptComputeEncoder, PL_STAGE_VERTEX | PL_STAGE_COMPUTE, PL_ACCESS_SHADER_READ, PL_STAGE_COMPUTE, PL_ACCESS_SHADER_WRITE); - - ptView->tLastUVMask = (i % 2 == 0) ? ptView->atUVMaskTexture1[uFrameIdx] : ptView->atUVMaskTexture0[uFrameIdx]; - - // submit nonindexed draw using basic API - gptGfx->bind_compute_shader(ptComputeEncoder, gptData->tJFAShader); - - plDynamicBinding tDynamicBinding = pl__allocate_dynamic_data(ptDevice); - plVec4* ptJumpDistance = (plVec4*)tDynamicBinding.pcData; - ptJumpDistance->x = fJumpDistance; - - gptGfx->bind_compute_bind_groups(ptComputeEncoder, gptData->tJFAShader, 0, 1, &atJFABindGroups[i % 2], 1, &tDynamicBinding); - gptGfx->dispatch(ptComputeEncoder, 1, &tDispach); - - // end render pass - gptGfx->pipeline_barrier_compute(ptComputeEncoder, PL_STAGE_COMPUTE, PL_ACCESS_SHADER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE, PL_ACCESS_SHADER_READ); - gptGfx->end_compute_pass(ptComputeEncoder); - - // end recording - gptGfx->end_command_recording(ptCommandBuffer); - - const plSubmitInfo tSubmitInfo = { - .uSignalSemaphoreCount = 1, - .atSignalSempahores = {tSemHandle}, - .auSignalSemaphoreValues = {++ulValue}, - }; - gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo); - gptGfx->return_command_buffer(ptCommandBuffer); - - fJumpDistance = fJumpDistance / 2.0f; - if(fJumpDistance < 1.0f) - fJumpDistance = 1.0f; + .tTexture = ptView->atUVMaskTexture1, + .uSlot = 0, + .tType = PL_TEXTURE_BINDING_TYPE_STORAGE, + .tCurrentUsage = PL_TEXTURE_USAGE_STORAGE + }, + { + .tTexture = ptView->atUVMaskTexture0, + .uSlot = 1, + .tType = PL_TEXTURE_BINDING_TYPE_STORAGE, + .tCurrentUsage = PL_TEXTURE_USAGE_STORAGE } - } + }; - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~post process~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + const plBindGroupUpdateData tJFABGData0 = { + .uTextureCount = 2, + .atTextureBindings = atJFATextureData0 + }; + const plBindGroupUpdateData tJFABGData1 = { + .uTextureCount = 2, + .atTextureBindings = atJFATextureData1 + }; + gptGfx->update_bind_group(gptData->ptDevice, atJFABindGroups[0], &tJFABGData0); + gptGfx->update_bind_group(gptData->ptDevice, atJFABindGroups[1], &tJFABGData1); + gptGfx->queue_bind_group_for_deletion(gptData->ptDevice, atJFABindGroups[0]); + gptGfx->queue_bind_group_for_deletion(gptData->ptDevice, atJFABindGroups[1]); + + for(uint32_t i = 0; i < uJumpSteps; i++) { - const plBeginCommandInfo tBeginInfo = { + const plBeginCommandInfo tJumpBeginInfo = { .uWaitSemaphoreCount = 1, .atWaitSempahores = {tSemHandle}, .auWaitSemaphoreValues = {ulValue}, }; - plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo); + plCommandBuffer* ptJumpCmdBuffer = gptGfx->request_command_buffer(ptCmdPool); + gptGfx->begin_command_recording(ptJumpCmdBuffer, &tJumpBeginInfo); + + // begin main renderpass (directly to swapchain) + plComputeEncoder* ptJumpEncoder = gptGfx->begin_compute_pass(ptJumpCmdBuffer, NULL); + gptGfx->pipeline_barrier_compute(ptJumpEncoder, PL_STAGE_VERTEX | PL_STAGE_COMPUTE, PL_ACCESS_SHADER_READ, PL_STAGE_COMPUTE, PL_ACCESS_SHADER_WRITE); + + ptView->tLastUVMask = (i % 2 == 0) ? ptView->atUVMaskTexture1 : ptView->atUVMaskTexture0; - pl_refr_post_process_scene(ptCommandBuffer, uSceneHandle, uViewHandle, &tMVP); - gptGfx->end_command_recording(ptCommandBuffer); + // submit nonindexed draw using basic API + gptGfx->bind_compute_shader(ptJumpEncoder, gptData->tJFAShader); + + plDynamicBinding tDynamicBinding = pl__allocate_dynamic_data(ptDevice); + plVec4* ptJumpDistance = (plVec4*)tDynamicBinding.pcData; + ptJumpDistance->x = fJumpDistance; + + gptGfx->bind_compute_bind_groups(ptJumpEncoder, gptData->tJFAShader, 0, 1, &atJFABindGroups[i % 2], 1, &tDynamicBinding); + gptGfx->dispatch(ptJumpEncoder, 1, &tDispach); + + // end render pass + gptGfx->pipeline_barrier_compute(ptJumpEncoder, PL_STAGE_COMPUTE, PL_ACCESS_SHADER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_PIXEL, PL_ACCESS_SHADER_READ); + gptGfx->end_compute_pass(ptJumpEncoder); + + // end recording + gptGfx->end_command_recording(ptJumpCmdBuffer); - const plSubmitInfo tSubmitInfo = { + const plSubmitInfo tJumpSubmitInfo = { .uSignalSemaphoreCount = 1, .atSignalSempahores = {tSemHandle}, - .auSignalSemaphoreValues = {++ulValue} + .auSignalSemaphoreValues = {++ulValue}, }; - gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo); - gptGfx->return_command_buffer(ptCommandBuffer); + gptGfx->submit_command_buffer(ptJumpCmdBuffer, &tJumpSubmitInfo); + gptGfx->return_command_buffer(ptJumpCmdBuffer); + + fJumpDistance = fJumpDistance / 2.0f; + if(fJumpDistance < 1.0f) + fJumpDistance = 1.0f; } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~post process~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + const plBeginCommandInfo tPostBeginInfo = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; + + plCommandBuffer* ptPostCmdBuffer = gptGfx->request_command_buffer(ptCmdPool); + gptGfx->begin_command_recording(ptPostCmdBuffer, &tPostBeginInfo); + + pl_refr_post_process_scene(ptPostCmdBuffer, uSceneHandle, uViewHandle, &tMVP); + gptGfx->end_command_recording(ptPostCmdBuffer); + + const plSubmitInfo tPostSubmitInfo = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptPostCmdBuffer, &tPostSubmitInfo); + gptGfx->return_command_buffer(ptPostCmdBuffer); + gptData->aulNextTimelineValue[uFrameIdx] = ulValue; // update stats @@ -4464,6 +3829,8 @@ pl_refr_end_frame(void) } gptGfx->return_command_buffer(ptCommandBuffer); + + // *gptData->pdDrawCalls = 0.0f; pl_end_cpu_sample(gptProfile, 0); } @@ -4488,8 +3855,7 @@ pl_refr_get_view_color_texture(uint32_t uSceneHandle, uint32_t uViewHandle) { plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; plRefView* ptView = &ptScene->atViews[uViewHandle]; - const uint32_t uFrameIdx = gptGfx->get_current_frame_index(); - return ptView->tFinalTextureHandle[uFrameIdx]; + return ptView->tFinalTextureHandle; } static void @@ -4498,39 +3864,39 @@ pl_add_drawable_objects_to_scene(uint32_t uSceneHandle, uint32_t uDeferredCount, plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; #if 1 - const uint32_t uTransparentStart = pl_sb_size(ptScene->sbtForwardDrawables); - pl_sb_add_n(ptScene->sbtForwardDrawables, uForwardCount); + const uint32_t uTransparentStart = pl_sb_size(ptScene->sbtNewForwardDrawables); + pl_sb_add_n(ptScene->sbtNewForwardDrawables, uForwardCount); - const uint32_t uOpaqueStart = pl_sb_size(ptScene->sbtDeferredDrawables); - pl_sb_add_n(ptScene->sbtDeferredDrawables, uDeferredCount); + const uint32_t uOpaqueStart = pl_sb_size(ptScene->sbtNewDeferredDrawables); + pl_sb_add_n(ptScene->sbtNewDeferredDrawables, uDeferredCount); for(uint32_t i = 0; i < uDeferredCount; i++) - ptScene->sbtDeferredDrawables[uOpaqueStart + i].tEntity = atDeferredObjects[i]; + ptScene->sbtNewDeferredDrawables[uOpaqueStart + i].tEntity = atDeferredObjects[i]; for(uint32_t i = 0; i < uForwardCount; i++) - ptScene->sbtForwardDrawables[uTransparentStart + i].tEntity = atForwardObjects[i]; + ptScene->sbtNewForwardDrawables[uTransparentStart + i].tEntity = atForwardObjects[i]; #endif #if 0 // send through forward pass only - const uint32_t uTransparentStart = pl_sb_size(ptScene->sbtForwardDrawables); - pl_sb_add_n(ptScene->sbtForwardDrawables, uForwardCount + uDeferredCount); + const uint32_t uTransparentStart = pl_sb_size(ptScene->sbtNewForwardDrawables); + pl_sb_add_n(ptScene->sbtNewForwardDrawables, uForwardCount + uDeferredCount); for(uint32_t i = 0; i < uDeferredCount; i++) - ptScene->sbtForwardDrawables[uTransparentStart + i].tEntity = atDeferredObjects[i]; + ptScene->sbtNewForwardDrawables[uTransparentStart + i].tEntity = atDeferredObjects[i]; for(uint32_t i = 0; i < uForwardCount; i++) - ptScene->sbtForwardDrawables[uDeferredCount + uTransparentStart + i].tEntity = atForwardObjects[i]; + ptScene->sbtNewForwardDrawables[uDeferredCount + uTransparentStart + i].tEntity = atForwardObjects[i]; #endif #if 0 // send through deferred pass only - const uint32_t uTransparentStart = pl_sb_size(ptScene->sbtDeferredDrawables); - pl_sb_add_n(ptScene->sbtDeferredDrawables, uForwardCount + uDeferredCount); + const uint32_t uTransparentStart = pl_sb_size(ptScene->sbtNewDeferredDrawables); + pl_sb_add_n(ptScene->sbtNewDeferredDrawables, uForwardCount + uDeferredCount); for(uint32_t i = 0; i < uDeferredCount; i++) - ptScene->sbtDeferredDrawables[uTransparentStart + i].tEntity = atDeferredObjects[i]; + ptScene->sbtNewDeferredDrawables[uTransparentStart + i].tEntity = atDeferredObjects[i]; for(uint32_t i = 0; i < uForwardCount; i++) - ptScene->sbtDeferredDrawables[uDeferredCount + uTransparentStart + i].tEntity = atForwardObjects[i]; + ptScene->sbtNewDeferredDrawables[uDeferredCount + uTransparentStart + i].tEntity = atForwardObjects[i]; #endif } @@ -4546,6 +3912,7 @@ pl_show_graphics_options(const char* pcTitle) if(gptUI->checkbox("Wireframe", &gptData->bWireframe)) bReloadShaders = true; if(gptUI->checkbox("MultiViewport Shadows", &gptData->bMultiViewportShadows)) bReloadShaders = true; if(gptUI->checkbox("Image Based Lighting", &gptData->bImageBasedLighting)) bReloadShaders = true; + if(gptUI->checkbox("Punctual Lighting", &gptData->bPunctualLighting)) bReloadShaders = true; if(bReloadShaders) { @@ -4595,7 +3962,6 @@ pl_load_renderer_ext(plApiRegistryI* ptApiRegistry, bool bReload) .get_device = pl_refr_get_device, .get_swapchain = pl_refr_get_swapchain, .load_skybox_from_panorama = pl_refr_load_skybox_from_panorama, - .create_environment_map_from_skybox = pl_create_environment_map_from_skybox, .finalize_scene = pl_refr_finalize_scene, .reload_scene_shaders = pl_refr_reload_scene_shaders, .select_entities = pl_refr_select_entities, @@ -4671,4 +4037,4 @@ pl_unload_renderer_ext(plApiRegistryI* ptApiRegistry, bool bReload) #undef STB_SPRINTF_IMPLEMENTATION #endif -#endif \ No newline at end of file +#endif diff --git a/extensions/pl_renderer_ext.h b/extensions/pl_renderer_ext.h index eac32ae..10fef64 100644 --- a/extensions/pl_renderer_ext.h +++ b/extensions/pl_renderer_ext.h @@ -73,7 +73,6 @@ typedef struct _plRendererI // loading void (*load_skybox_from_panorama)(uint32_t uSceneHandle, const char* pcPath, int iResolution); - void (*create_environment_map_from_skybox)(uint32_t uSceneHandle); void (*finalize_scene)(uint32_t uSceneHandle); void (*reload_scene_shaders)(uint32_t uSceneHandle); diff --git a/extensions/pl_renderer_internal.c b/extensions/pl_renderer_internal.c index 8e70eee..02196f0 100644 --- a/extensions/pl_renderer_internal.c +++ b/extensions/pl_renderer_internal.c @@ -795,9 +795,13 @@ pl_refr_pack_shadow_atlas(uint32_t uSceneHandle, const uint32_t* auViewHandles, pl_sb_reset(ptScene->sbtShadowRects); + const plEnvironmentProbeComponent* sbtProbes = ptScene->tComponentLibrary.tEnvironmentProbeCompManager.pComponents; const plLightComponent* sbtLights = ptScene->tComponentLibrary.tLightComponentManager.pComponents; + const uint32_t uProbeCount = pl_sb_size(sbtProbes); const uint32_t uLightCount = pl_sb_size(sbtLights); + // for packing, using rect id as (16 bits) + (3 bits) + (11 bits) + (2bit) for light, view, probe, mode + for(uint32_t uLightIndex = 0; uLightIndex < uLightCount; uLightIndex++) { const plLightComponent* ptLight = &sbtLights[uLightIndex]; @@ -810,20 +814,33 @@ pl_refr_pack_shadow_atlas(uint32_t uSceneHandle, const uint32_t* auViewHandles, if(ptLight->tType == PL_LIGHT_TYPE_DIRECTIONAL) { - for(uint32_t i = 0; i < uViewCount; i++) + for(uint32_t uView = 0; uView < uViewCount; uView++) { - plPackRect tPackRect = { + const plPackRect tPackRect = { .iWidth = (int)(ptLight->uShadowResolution * ptLight->uCascadeCount), .iHeight = (int)ptLight->uShadowResolution, - .iId = (int)uLightIndex + .iId = (int)uLightIndex + ((int)(uView) << 16) }; pl_sb_push(ptScene->sbtShadowRects, tPackRect); } + + for(uint32_t uProbe = 0; uProbe < uProbeCount; uProbe++) + { + for(uint32_t uView = 0; uView < 6; uView++) + { + const plPackRect tPackRect = { + .iWidth = (int)(ptLight->uShadowResolution), + .iHeight = (int)ptLight->uShadowResolution, + .iId = (int)uLightIndex + ((int)uView << 16) + ((int)(uProbe) << 18) + (1 << 30) + }; + pl_sb_push(ptScene->sbtShadowRects, tPackRect); + } + } } else if(ptLight->tType == PL_LIGHT_TYPE_POINT) { - plPackRect tPackRect = { + const plPackRect tPackRect = { .iWidth = (int)(ptLight->uShadowResolution * 2), .iHeight = (int)(ptLight->uShadowResolution * 3), .iId = (int)uLightIndex @@ -833,7 +850,7 @@ pl_refr_pack_shadow_atlas(uint32_t uSceneHandle, const uint32_t* auViewHandles, else if(ptLight->tType == PL_LIGHT_TYPE_SPOT) { - plPackRect tPackRect = { + const plPackRect tPackRect = { .iWidth = (int)ptLight->uShadowResolution, .iHeight = (int)ptLight->uShadowResolution, .iId = (int)uLightIndex @@ -842,10 +859,11 @@ pl_refr_pack_shadow_atlas(uint32_t uSceneHandle, const uint32_t* auViewHandles, } } + // pack rects const uint32_t uRectCount = pl_sb_size(ptScene->sbtShadowRects); - gptRect->pack_rects(ptScene->uShadowAtlasResolution, ptScene->uShadowAtlasResolution, - ptScene->sbtShadowRects, uRectCount); + gptRect->pack_rects(ptScene->uShadowAtlasResolution, ptScene->uShadowAtlasResolution, ptScene->sbtShadowRects, uRectCount); + // ensure rects are packed bool bPacked = true; for(uint32_t i = 0; i < uRectCount; i++) { @@ -880,14 +898,20 @@ pl_refr_generate_shadow_maps(plRenderEncoder* ptEncoder, plCommandBuffer* ptComm for(uint32_t uLightIndex = 0; uLightIndex < uLightCount; uLightIndex++) { const plPackRect* ptRect = &ptScene->sbtShadowRects[uLightIndex]; - const plLightComponent* ptLight = &sbtLights[ptRect->iId]; + + int iLight = ptRect->iId & ~(~0u << 16); + int iView = (ptRect->iId >> 16) & ~(~0u << 3); + int iProbe = (ptRect->iId >> 19) & ~(~0u << 12); + int iMode = ptRect->iId >> 31; + + const plLightComponent* ptLight = &sbtLights[iLight]; if(ptLight->tType == PL_LIGHT_TYPE_POINT) { pl_sb_add(ptScene->sbtPLightShadowData); plGPULightShadowData* ptShadowData = &ptScene->sbtPLightShadowData[pl_sb_size(ptScene->sbtPLightShadowData) - 1]; - ptShadowData->iShadowMapTexIdx = ptScene->atShadowTextureBindlessIndices[uFrameIdx]; + ptShadowData->iShadowMapTexIdx = ptScene->atShadowTextureBindlessIndices; ptShadowData->fFactor = (float)ptLight->uShadowResolution / (float)ptScene->uShadowAtlasResolution; ptShadowData->fXOffset = (float)ptRect->iX / (float)ptScene->uShadowAtlasResolution; ptShadowData->fYOffset = (float)ptRect->iY / (float)ptScene->uShadowAtlasResolution; @@ -931,7 +955,7 @@ pl_refr_generate_shadow_maps(plRenderEncoder* ptEncoder, plCommandBuffer* ptComm pl_sb_add(ptScene->sbtSLightShadowData); plGPULightShadowData* ptShadowData = &ptScene->sbtSLightShadowData[pl_sb_size(ptScene->sbtSLightShadowData) - 1]; - ptShadowData->iShadowMapTexIdx = ptScene->atShadowTextureBindlessIndices[uFrameIdx]; + ptShadowData->iShadowMapTexIdx = ptScene->atShadowTextureBindlessIndices; ptShadowData->fFactor = (float)ptLight->uShadowResolution / (float)ptScene->uShadowAtlasResolution; ptShadowData->fXOffset = (float)ptRect->iX / (float)ptScene->uShadowAtlasResolution; ptShadowData->fYOffset = (float)ptRect->iY / (float)ptScene->uShadowAtlasResolution; @@ -952,10 +976,7 @@ pl_refr_generate_shadow_maps(plRenderEncoder* ptEncoder, plCommandBuffer* ptComm gptCamera->update(&tShadowCamera); tCamViewProjs = pl_mul_mat4(&tShadowCamera.tProjMat, &tShadowCamera.tViewMat); ptShadowData->viewProjMat[0] = tCamViewProjs; - - // plVec4 tBlah = {-8.0f, 3.96422f, -0.13079f, 1.0f}; - // tBlah = pl_mul_mat4_vec4(&tCamViewProjs, tBlah); - + char* pcBufferStart = gptGfx->get_buffer(ptDevice, ptScene->atSShadowCameraBuffers[uFrameIdx])->tMemoryAllocation.pHostMapped; memcpy(&pcBufferStart[uSCameraBufferOffset], &tCamViewProjs, sizeof(plMat4)); uSCameraBufferOffset += sizeof(plMat4); @@ -1010,8 +1031,8 @@ pl_refr_generate_shadow_maps(plRenderEncoder* ptEncoder, plCommandBuffer* ptComm gptGfx->queue_bind_group_for_deletion(ptDevice, tGlobalBG0); gptGfx->queue_bind_group_for_deletion(ptDevice, tGlobalBG1); - const uint32_t uOpaqueDrawableCount = pl_sb_size(ptScene->sbtDeferredDrawables); - const uint32_t uTransparentDrawableCount = pl_sb_size(ptScene->sbtForwardDrawables); + const uint32_t uVisibleOpaqueDrawCount = pl_sb_size(ptScene->sbuShadowDeferredDrawables); + const uint32_t uVisibleTransparentDrawCount = pl_sb_size(ptScene->sbuShadowForwardDrawables); // const plVec2 tDimensions = gptGfx->get_render_pass(ptDevice, ptView->tShadowData.tOpaqueRenderPass)->tDesc.tDimensions; @@ -1030,14 +1051,17 @@ pl_refr_generate_shadow_maps(plRenderEncoder* ptEncoder, plCommandBuffer* ptComm { const plPackRect* ptRect = &ptScene->sbtShadowRects[uLightIndex]; - const plLightComponent* ptLight = &sbtLights[ptRect->iId]; + + int iLight = ptRect->iId & ~(~0u << 16); + int iView = (ptRect->iId >> 16) & ~(~0u << 3); + int iProbe = (ptRect->iId >> 19) & ~(~0u << 12); + int iMode = ptRect->iId >> 31; + + const plLightComponent* ptLight = &sbtLights[iLight]; if(ptLight->tType == PL_LIGHT_TYPE_POINT) { - const uint32_t uVisibleOpaqueDrawCount = pl_sb_size(ptScene->sbtDeferredDrawables); - const uint32_t uVisibleTransparentDrawCount = pl_sb_size(ptScene->sbtForwardDrawables); - if(gptData->bMultiViewportShadows) { @@ -1046,7 +1070,7 @@ pl_refr_generate_shadow_maps(plRenderEncoder* ptEncoder, plCommandBuffer* ptComm *gptData->pdDrawCalls += (double)uVisibleOpaqueDrawCount; for(uint32_t i = 0; i < uVisibleOpaqueDrawCount; i++) { - const plDrawable tDrawable = ptScene->sbtDeferredDrawables[i]; + const plDrawable tDrawable = ptScene->sbtDeferredDrawables[ptScene->sbuShadowDeferredDrawables[i]]; plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); @@ -1087,7 +1111,7 @@ pl_refr_generate_shadow_maps(plRenderEncoder* ptEncoder, plCommandBuffer* ptComm *gptData->pdDrawCalls += (double)uVisibleTransparentDrawCount; for(uint32_t i = 0; i < uVisibleTransparentDrawCount; i++) { - const plDrawable tDrawable = ptScene->sbtForwardDrawables[i]; + const plDrawable tDrawable = ptScene->sbtForwardDrawables[ptScene->sbuShadowForwardDrawables[i]]; plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); @@ -1344,9 +1368,6 @@ pl_refr_generate_shadow_maps(plRenderEncoder* ptEncoder, plCommandBuffer* ptComm else if(ptLight->tType == PL_LIGHT_TYPE_SPOT) { - const uint32_t uVisibleOpaqueDrawCount = pl_sb_size(ptScene->sbtDeferredDrawables); - const uint32_t uVisibleTransparentDrawCount = pl_sb_size(ptScene->sbtForwardDrawables); - gptGfx->reset_draw_stream(ptStream, uVisibleOpaqueDrawCount + uVisibleTransparentDrawCount); gptGfx->set_depth_bias(ptEncoder, gptData->fShadowConstantDepthBias, 0.0f, gptData->fShadowSlopeDepthBias); *gptData->pdDrawCalls += (double)uVisibleOpaqueDrawCount; @@ -1463,18 +1484,19 @@ pl_refr_generate_shadow_maps(plRenderEncoder* ptEncoder, plCommandBuffer* ptComm } static void -pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer* ptCommandBuffer, uint32_t uSceneHandle, uint32_t uViewHandle, uint32_t uViewCount, plEntity tCamera) +pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer* ptCommandBuffer, uint32_t uSceneHandle, uint32_t uViewHandle, uint32_t uProbeIndex, int iRequestMode, plDirectionLightShadowData* ptDShadowData, plCameraComponent* ptSceneCamera) { pl_begin_cpu_sample(gptProfile, 0, __FUNCTION__); // for convience - plDevice* ptDevice = gptData->ptDevice; - plDrawStream* ptStream = &gptData->tDrawStream; - plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; - plRefView* ptView = &ptScene->atViews[uViewHandle]; + plDevice* ptDevice = gptData->ptDevice; + plDrawStream* ptStream = &gptData->tDrawStream; + plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; const uint32_t uFrameIdx = gptGfx->get_current_frame_index(); - plCameraComponent* ptSceneCamera = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_CAMERA, tCamera); + const plLightComponent* sbtLights = ptScene->tComponentLibrary.tLightComponentManager.pComponents; + const uint32_t uInitialOffset = ptDShadowData->uOffset; + const float g = 1.0f / tanf(ptSceneCamera->fFieldOfView / 2.0f); const float s = ptSceneCamera->fAspectRatio; @@ -1489,48 +1511,57 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer const float fRange = fMaxZ - fMinZ; const float fRatio = fMaxZ / fMinZ; - const plLightComponent* sbtLights = ptScene->tComponentLibrary.tLightComponentManager.pComponents; - const uint32_t uLightCount = pl_sb_size(ptScene->sbtShadowRects); + // TODO: we shouldn't have to check all rects, optimize this - int iLastIndex = -1; - int iCurrentView = -1; - uint32_t uDCameraBufferOffset = 0; - for(uint32_t uLightIndex = 0; uLightIndex < uLightCount; uLightIndex++) + const uint32_t uAtlasRectCount = pl_sb_size(ptScene->sbtShadowRects); + for(uint32_t uRectIndex = 0; uRectIndex < uAtlasRectCount; uRectIndex++) { - const plPackRect* ptRect = &ptScene->sbtShadowRects[uLightIndex]; - const plLightComponent* ptLight = &sbtLights[ptRect->iId]; + const plPackRect* ptRect = &ptScene->sbtShadowRects[uRectIndex]; - if(ptRect->iId == iLastIndex) - { - iCurrentView++; - } - else - { - iLastIndex = ptRect->iId; - iCurrentView = 0; - } + // decode rect info + int iLight = ptRect->iId & ~(~0u << 16); + int iView = (ptRect->iId >> 16) & ~(~0u << 3); + int iProbe = (ptRect->iId >> 18) & ~(~0u << 11); + int iMode = ptRect->iId >> 30; - if(ptLight->tType != PL_LIGHT_TYPE_DIRECTIONAL || iCurrentView != (int)uViewHandle) + const plLightComponent* ptLight = &sbtLights[iLight]; + + // check if light applies + if(ptLight->tType != PL_LIGHT_TYPE_DIRECTIONAL || iView != (int)uViewHandle || iMode != iRequestMode || iProbe != (int)uProbeIndex) { continue; } - const uint32_t uDataOffset = pl_sb_size(ptView->sbtDLightShadowData); - pl_sb_add(ptView->sbtDLightShadowData); + const uint32_t uDataOffset = pl_sb_size(ptDShadowData->sbtDLightShadowData); + pl_sb_add(ptDShadowData->sbtDLightShadowData); - plGPULightShadowData* ptShadowData = &ptView->sbtDLightShadowData[uDataOffset]; - ptShadowData->iShadowMapTexIdx = ptScene->atShadowTextureBindlessIndices[uFrameIdx]; - ptShadowData->fFactor = (float)ptLight->uShadowResolution / (float)ptScene->uShadowAtlasResolution; - ptShadowData->fXOffset = (float)ptRect->iX / (float)ptScene->uShadowAtlasResolution; - ptShadowData->fYOffset = (float)ptRect->iY / (float)ptScene->uShadowAtlasResolution; + // copy GPU light shadow data + plGPULightShadowData* ptShadowData = &ptDShadowData->sbtDLightShadowData[uDataOffset]; + ptShadowData->iShadowMapTexIdx = ptScene->atShadowTextureBindlessIndices; + ptShadowData->fFactor = (float)ptLight->uShadowResolution / (float)ptScene->uShadowAtlasResolution; + ptShadowData->fXOffset = (float)ptRect->iX / (float)ptScene->uShadowAtlasResolution; + ptShadowData->fYOffset = (float)ptRect->iY / (float)ptScene->uShadowAtlasResolution; + ptShadowData->tCascadeSplits.d[0] = 10000.0f; + ptShadowData->tCascadeSplits.d[1] = 10000.0f; + ptShadowData->tCascadeSplits.d[2] = 10000.0f; + ptShadowData->tCascadeSplits.d[3] = 10000.0f; plMat4 atCamViewProjs[PL_MAX_SHADOW_CASCADES] = {0}; float fLastSplitDist = 0.0f; const plVec3 tDirection = pl_norm_vec3(ptLight->tDirection); - for(uint32_t uCascade = 0; uCascade < ptLight->uCascadeCount; uCascade++) + const uint32_t uCascadeCount = iMode == 0 ? ptLight->uCascadeCount : 1; // probe only needs single cascade + + const float afCascadeSplits[4] = { + iMode == 0 ? ptLight->afCascadeSplits[0] : ptSceneCamera->fFarZ, // use whole frustum for environment probes + ptLight->afCascadeSplits[1], + ptLight->afCascadeSplits[2], + ptLight->afCascadeSplits[3] + }; + + for(uint32_t uCascade = 0; uCascade < uCascadeCount; uCascade++) { - float fSplitDist = ptLight->afCascadeSplits[uCascade]; - ptShadowData->tCascadeSplits.d[uCascade] = ptLight->afCascadeSplits[uCascade]; + float fSplitDist = afCascadeSplits[uCascade]; + ptShadowData->tCascadeSplits.d[uCascade] = afCascadeSplits[uCascade]; // camera space plVec3 atCameraCorners2[] = { @@ -1544,15 +1575,14 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer { fSplitDist * s / g, fSplitDist / g, fSplitDist }, }; - // find max diagonal + // find max diagonal in camera space float fD0 = ceilf(pl_length_vec3(pl_sub_vec3(atCameraCorners2[0], atCameraCorners2[6]))); float fD1 = ceilf(pl_length_vec3(pl_sub_vec3(atCameraCorners2[6], atCameraCorners2[4]))); float fD = pl_max(fD0, fD1) * 1.0f; const float fUnitPerTexel = fD / (float)ptLight->uShadowResolution; - plMat4 tCameraInversion = pl_mat4_invert(&ptSceneCamera->tViewMat); - // convert to world space + const plMat4 tCameraInversion = pl_mat4_invert(&ptSceneCamera->tViewMat); for(uint32_t i = 0; i < 8; i++) { plVec4 tInvCorner = pl_mul_mat4_vec4(&tCameraInversion, (plVec4){.xyz = atCameraCorners2[i], .w = 1.0f}); @@ -1564,10 +1594,10 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer .tType = PL_CAMERA_TYPE_ORTHOGRAPHIC }; gptCamera->look_at(&tShadowCamera, (plVec3){0}, tDirection); - tShadowCamera.fWidth = fD; + tShadowCamera.fWidth = fD; tShadowCamera.fHeight = fD; - tShadowCamera.fNearZ = 0.0f; - tShadowCamera.fFarZ = fD; + tShadowCamera.fNearZ = 0.0f; + tShadowCamera.fFarZ = fD; gptCamera->update(&tShadowCamera); for(uint32_t i = 0; i < 8; i++) @@ -1593,16 +1623,15 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer fZMax = pl_max(atCameraCorners2[i].z, fZMax); } - plVec4 tLightPosLightSpace = { - fUnitPerTexel * floorf((fXMax + fXMin) / (fUnitPerTexel * 2.0f)), - fUnitPerTexel * floorf((fYMax + fYMin) / (fUnitPerTexel * 2.0f)), + const plVec4 tLightPosLightSpace = { + fUnitPerTexel * floorf((fXMax + fXMin) / (fUnitPerTexel * 2.0f)), // texel snapping + fUnitPerTexel * floorf((fYMax + fYMin) / (fUnitPerTexel * 2.0f)), // texel snapping fZMin, 1.0f }; - - plMat4 tLightInversion = pl_mat4_invert(&tShadowCamera.tViewMat); - plVec4 tLightPos = pl_mul_mat4_vec4(&tLightInversion, (plVec4){.xyz = tLightPosLightSpace.xyz, .w = 1.0f}); + const plMat4 tLightInversion = pl_mat4_invert(&tShadowCamera.tViewMat); + const plVec4 tLightPos = pl_mul_mat4_vec4(&tLightInversion, (plVec4){.xyz = tLightPosLightSpace.xyz, .w = 1.0f}); gptCamera->look_at(&tShadowCamera, tLightPos.xyz, pl_add_vec3(tLightPos.xyz, tDirection)); gptCamera->update(&tShadowCamera); @@ -1612,9 +1641,12 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer fLastSplitDist = fSplitDist; } - char* pcBufferStart = gptGfx->get_buffer(ptDevice, ptView->atDShadowCameraBuffers[uFrameIdx])->tMemoryAllocation.pHostMapped; - memcpy(&pcBufferStart[uDCameraBufferOffset], atCamViewProjs, sizeof(plMat4) * PL_MAX_SHADOW_CASCADES); - uDCameraBufferOffset += sizeof(plMat4) * PL_MAX_SHADOW_CASCADES; + // TODO: rework to not waste so much space (don't use max cascades as stride) + + // copy data to GPU buffer + char* pcBufferStart = gptGfx->get_buffer(ptDevice, ptDShadowData->atDShadowCameraBuffers[uFrameIdx])->tMemoryAllocation.pHostMapped; + memcpy(&pcBufferStart[ptDShadowData->uOffset], atCamViewProjs, sizeof(plMat4) * PL_MAX_SHADOW_CASCADES); + ptDShadowData->uOffset += sizeof(plMat4) * PL_MAX_SHADOW_CASCADES; } plBindGroupLayout tBindGroupLayout0 = { @@ -1631,29 +1663,29 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer .ptLayout = &tBindGroupLayout0, .pcDebugName = "temporary global bind group 0" }; - plBindGroupHandle tGlobalBG = gptGfx->create_bind_group(ptDevice, &tGlobalBGDesc); + const plBindGroupUpdateBufferData atBufferData[] = { { - .tBuffer = ptView->atDShadowCameraBuffers[uFrameIdx], + .tBuffer = ptDShadowData->atDShadowCameraBuffers[uFrameIdx], .uSlot = 0, - .szBufferRange = uDCameraBufferOffset + .szBufferRange = ptDShadowData->uOffset } }; + const uint32_t uIndexingOffset = uInitialOffset / (sizeof(plMat4) * PL_MAX_SHADOW_CASCADES); + plBindGroupUpdateData tBGData0 = { .uBufferCount = 1, .atBufferBindings = atBufferData }; - gptGfx->update_bind_group(gptData->ptDevice, tGlobalBG, &tBGData0); - - gptGfx->queue_bind_group_for_deletion(ptDevice, tGlobalBG); + plBindGroupHandle tShadowBG1 = gptGfx->create_bind_group(ptDevice, &tGlobalBGDesc); + gptGfx->update_bind_group(gptData->ptDevice, tShadowBG1, &tBGData0); + gptGfx->queue_bind_group_for_deletion(ptDevice, tShadowBG1); - const uint32_t uOpaqueDrawableCount = pl_sb_size(ptScene->sbtDeferredDrawables); - const uint32_t uTransparentDrawableCount = pl_sb_size(ptScene->sbtForwardDrawables); - - // const plVec2 tDimensions = gptGfx->get_render_pass(ptDevice, ptView->tShadowData.tOpaqueRenderPass)->tDesc.tDimensions; + const uint32_t uOpaqueDrawableCount = pl_sb_size(ptScene->sbuShadowDeferredDrawables); + const uint32_t uTransparentDrawableCount = pl_sb_size(ptScene->sbuShadowForwardDrawables); typedef struct _plShadowDynamicData { @@ -1664,44 +1696,34 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer plMat4 tModel; } plShadowDynamicData; - iLastIndex = -1; - iCurrentView = -1; - uint32_t uDOffset = 0; - for(uint32_t uLightIndex = 0; uLightIndex < uLightCount; uLightIndex++) + for(uint32_t uRectIndex = 0; uRectIndex < uAtlasRectCount; uRectIndex++) { - const plPackRect* ptRect = &ptScene->sbtShadowRects[uLightIndex]; - const plLightComponent* ptLight = &sbtLights[ptRect->iId]; + const plPackRect* ptRect = &ptScene->sbtShadowRects[uRectIndex]; - if(ptRect->iId == iLastIndex) - { - iCurrentView++; - } - else - { - iLastIndex = ptRect->iId; - iCurrentView = 0; - } + // decode rect info + int iLight = ptRect->iId & ~(~0u << 16); + int iView = (ptRect->iId >> 16) & ~(~0u << 3); + int iProbe = (ptRect->iId >> 18) & ~(~0u << 11); + int iMode = ptRect->iId >> 30; + + const plLightComponent* ptLight = &sbtLights[iLight]; - if(ptLight->tType != PL_LIGHT_TYPE_DIRECTIONAL || iCurrentView != (int)uViewHandle) + // check if light applies + if(ptLight->tType != PL_LIGHT_TYPE_DIRECTIONAL || iView != (int)uViewHandle || iMode != iRequestMode || iProbe != (int)uProbeIndex) { continue; } - const uint32_t uVisibleOpaqueDrawCount = pl_sb_size(ptScene->sbtDeferredDrawables); - const uint32_t uVisibleTransparentDrawCount = pl_sb_size(ptScene->sbtForwardDrawables); - - + const uint32_t uCascadeCount = iMode == 0 ? ptLight->uCascadeCount : 1; // probe only needs single cascade if(gptData->bMultiViewportShadows) { - - - gptGfx->reset_draw_stream(ptStream, uVisibleOpaqueDrawCount + uVisibleTransparentDrawCount); + gptGfx->reset_draw_stream(ptStream, uOpaqueDrawableCount + uTransparentDrawableCount); gptGfx->set_depth_bias(ptEncoder, gptData->fShadowConstantDepthBias, 0.0f, gptData->fShadowSlopeDepthBias); - *gptData->pdDrawCalls += (double)uVisibleOpaqueDrawCount; - for(uint32_t i = 0; i < uVisibleOpaqueDrawCount; i++) + *gptData->pdDrawCalls += (double)uOpaqueDrawableCount; + for(uint32_t i = 0; i < uOpaqueDrawableCount; i++) { - const plDrawable tDrawable = ptScene->sbtDeferredDrawables[i]; + const plDrawable tDrawable = ptScene->sbtDeferredDrawables[ptScene->sbuShadowDeferredDrawables[i]]; plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); @@ -1712,7 +1734,7 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer ptDynamicData->iVertexOffset = tDrawable.uIndexCount == 0 ? 0 : tDrawable.uVertexOffset; ptDynamicData->tModel = ptTransform->tWorld; ptDynamicData->iMaterialIndex = tDrawable.uMaterialIndex; - ptDynamicData->iIndex = (int)uDOffset; + ptDynamicData->iIndex = (int)ptDShadowData->uOffsetIndex + (int)uIndexingOffset; pl_add_to_draw_stream(ptStream, (plDrawStreamData) { @@ -1729,20 +1751,20 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, .atBindGroups = { ptScene->tGlobalBindGroup, - tGlobalBG + tShadowBG1 }, .auDynamicBufferOffsets = { tDynamicBinding.uByteOffset }, .uInstanceOffset = 0, - .uInstanceCount = ptLight->uCascadeCount + .uInstanceCount = uCascadeCount }); } - *gptData->pdDrawCalls += (double)uVisibleTransparentDrawCount; - for(uint32_t i = 0; i < uVisibleTransparentDrawCount; i++) + *gptData->pdDrawCalls += (double)uTransparentDrawableCount; + for(uint32_t i = 0; i < uTransparentDrawableCount; i++) { - const plDrawable tDrawable = ptScene->sbtForwardDrawables[i]; + const plDrawable tDrawable = ptScene->sbtForwardDrawables[ptScene->sbuShadowForwardDrawables[i]]; plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); @@ -1753,7 +1775,7 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer ptDynamicData->iVertexOffset = tDrawable.uIndexCount == 0 ? 0 : tDrawable.uVertexOffset; ptDynamicData->tModel = ptTransform->tWorld; ptDynamicData->iMaterialIndex = tDrawable.uMaterialIndex; - ptDynamicData->iIndex = (int)uDOffset; + ptDynamicData->iIndex = (int)ptDShadowData->uOffsetIndex + (int)uIndexingOffset; pl_add_to_draw_stream(ptStream, (plDrawStreamData) { @@ -1770,13 +1792,13 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, .atBindGroups = { ptScene->tGlobalBindGroup, - tGlobalBG + tShadowBG1 }, .auDynamicBufferOffsets = { tDynamicBinding.uByteOffset }, .uInstanceOffset = 0, - .uInstanceCount = ptLight->uCascadeCount + .uInstanceCount = uCascadeCount }); }; @@ -1821,21 +1843,21 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer { .fX = (float)(ptRect->iX + 1 * ptLight->uShadowResolution), .fY = (float)ptRect->iY, - .fWidth = (float)ptLight->uShadowResolution, + .fWidth = uCascadeCount > 1 ? (float)ptLight->uShadowResolution : 0.0f, .fHeight = (float)ptLight->uShadowResolution, .fMaxDepth = 1.0f }, { .fX = (float)(ptRect->iX + 2 * ptLight->uShadowResolution), .fY = (float)ptRect->iY, - .fWidth = (float)ptLight->uShadowResolution, + .fWidth = uCascadeCount > 1 ? (float)ptLight->uShadowResolution : 0.0f, .fHeight = (float)ptLight->uShadowResolution, .fMaxDepth = 1.0f }, { .fX = (float)(ptRect->iX + 3 * ptLight->uShadowResolution), .fY = (float)ptRect->iY, - .fWidth = (float)ptLight->uShadowResolution, + .fWidth = uCascadeCount > 1 ? (float)ptLight->uShadowResolution : 0.0f, .fHeight = (float)ptLight->uShadowResolution, .fMaxDepth = 1.0f }, @@ -1846,15 +1868,15 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer } else { - for(uint32_t uCascade = 0; uCascade < ptLight->uCascadeCount; uCascade++) + for(uint32_t uCascade = 0; uCascade < uCascadeCount; uCascade++) { - gptGfx->reset_draw_stream(ptStream, uVisibleOpaqueDrawCount + uVisibleTransparentDrawCount); + gptGfx->reset_draw_stream(ptStream, uOpaqueDrawableCount + uTransparentDrawableCount); gptGfx->set_depth_bias(ptEncoder, gptData->fShadowConstantDepthBias, 0.0f, gptData->fShadowSlopeDepthBias); - *gptData->pdDrawCalls += (double)uVisibleOpaqueDrawCount; - for(uint32_t i = 0; i < uVisibleOpaqueDrawCount; i++) + *gptData->pdDrawCalls += (double)uOpaqueDrawableCount; + for(uint32_t i = 0; i < uOpaqueDrawableCount; i++) { - const plDrawable tDrawable = ptScene->sbtDeferredDrawables[i]; + const plDrawable tDrawable = ptScene->sbtDeferredDrawables[ptScene->sbuShadowDeferredDrawables[i]]; plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); @@ -1865,7 +1887,7 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer ptDynamicData->iVertexOffset = tDrawable.uIndexCount == 0 ? 0 : tDrawable.uVertexOffset; ptDynamicData->tModel = ptTransform->tWorld; ptDynamicData->iMaterialIndex = tDrawable.uMaterialIndex; - ptDynamicData->iIndex = (int)uCascade + (int)uDOffset; + ptDynamicData->iIndex = (int)uCascade + (int)ptDShadowData->uOffsetIndex; pl_add_to_draw_stream(ptStream, (plDrawStreamData) { @@ -1882,20 +1904,20 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, .atBindGroups = { ptScene->tGlobalBindGroup, - tGlobalBG + tShadowBG1 }, .auDynamicBufferOffsets = { tDynamicBinding.uByteOffset }, .uInstanceOffset = 0, - .uInstanceCount = ptLight->uCascadeCount + .uInstanceCount = uCascadeCount }); } - *gptData->pdDrawCalls += (double)uVisibleTransparentDrawCount; - for(uint32_t i = 0; i < uVisibleTransparentDrawCount; i++) + *gptData->pdDrawCalls += (double)uTransparentDrawableCount; + for(uint32_t i = 0; i < uTransparentDrawableCount; i++) { - const plDrawable tDrawable = ptScene->sbtForwardDrawables[i]; + const plDrawable tDrawable = ptScene->sbtForwardDrawables[ptScene->sbuShadowForwardDrawables[i]]; plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); @@ -1906,7 +1928,7 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer ptDynamicData->iVertexOffset = tDrawable.uIndexCount == 0 ? 0 : tDrawable.uVertexOffset; ptDynamicData->tModel = ptTransform->tWorld; ptDynamicData->iMaterialIndex = tDrawable.uMaterialIndex; - ptDynamicData->iIndex = (int)uCascade + (int)uDOffset; + ptDynamicData->iIndex = (int)uCascade + (int)ptDShadowData->uOffsetIndex; pl_add_to_draw_stream(ptStream, (plDrawStreamData) { @@ -1923,13 +1945,13 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, .atBindGroups = { ptScene->tGlobalBindGroup, - tGlobalBG + tShadowBG1 }, .auDynamicBufferOffsets = { tDynamicBinding.uByteOffset }, .uInstanceOffset = 0, - .uInstanceCount = ptLight->uCascadeCount + .uInstanceCount = uCascadeCount }); }; @@ -1959,7 +1981,7 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer gptGfx->draw_stream(ptEncoder, 1, &tArea); } } - uDOffset+=4; + ptDShadowData->uOffsetIndex+=4; } pl_end_cpu_sample(gptProfile, 0); @@ -2014,7 +2036,7 @@ pl_refr_post_process_scene(plCommandBuffer* ptCommandBuffer, uint32_t uSceneHand const plBindGroupUpdateTextureData tOutlineTextureData[] = { { - .tTexture = ptView->tRawOutputTexture[uFrameIdx], + .tTexture = ptView->tRawOutputTexture, .uSlot = 1, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED }, @@ -2105,6 +2127,29 @@ pl__get_shader_variant(uint32_t uSceneHandle, plShaderHandle tHandle, const plSh static void pl_refr_create_global_shaders(void) { + + plComputeShaderDesc tFilterComputeShaderDesc = { + .tShader = gptShader->load_glsl("../shaders/filter_environment.comp", "main", NULL, NULL), + .atBindGroupLayouts = { + { + .atTextureBindings = { + {.uSlot = 1, .tStages = PL_STAGE_COMPUTE, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED} + }, + .atBufferBindings = { + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 2, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 3, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 4, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 5, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 6, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 7, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 8, .tStages = PL_STAGE_COMPUTE}, + }, + .atSamplerBindings = { {.uSlot = 0, .tStages = PL_STAGE_COMPUTE}} + } + } + }; + gptData->tEnvFilterShader = gptGfx->create_compute_shader(gptData->ptDevice, &tFilterComputeShaderDesc); + int aiConstantData[8] = {0, 0, 0, 0, 0, 0, 0, 0}; plShaderDesc tDeferredShaderDescription = { @@ -2163,7 +2208,7 @@ pl_refr_create_global_shaders(void) { .atBufferBindings = { { - .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, + .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 0, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL } @@ -2231,7 +2276,7 @@ pl_refr_create_global_shaders(void) }, { .atBufferBindings = { - { .uSlot = 0, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, + { .uSlot = 0, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, { .uSlot = 1, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, { .uSlot = 2, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, { .uSlot = 3, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, @@ -2442,7 +2487,7 @@ pl_refr_create_global_shaders(void) .atBindGroupLayouts = { { .atBufferBindings = { - { .uSlot = 0, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL} + { .uSlot = 0, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL} }, .atSamplerBindings = { {.uSlot = 1, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL}, @@ -2989,3 +3034,1580 @@ pl__get_bindless_cube_texture_index(uint32_t uSceneHandle, plTextureHandle tText return (uint32_t)ulValue; } + +static void +pl__create_probe_data(uint32_t uSceneHandle, plEntity tProbeHandle) +{ + // for convience + plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; + + plEnvironmentProbeComponent* ptProbe = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_ENVIRONMENT_PROBE, tProbeHandle); + + plEnvironmentProbeData tProbeData = { + .tEntity = tProbeHandle, + .tTargetSize = {(float)ptProbe->uResolution, (float)ptProbe->uResolution} + }; + + // create offscreen per-frame resources + const plTextureDesc tRawOutputTextureDesc = { + .tDimensions = {tProbeData.tTargetSize.x * 2.0f, tProbeData.tTargetSize.y * 3.0f, 1}, + .tFormat = PL_FORMAT_R16G16B16A16_FLOAT, + .uLayers = 1, + .uMips = 1, + .tType = PL_TEXTURE_TYPE_2D, + .tUsage = PL_TEXTURE_USAGE_SAMPLED | PL_TEXTURE_USAGE_COLOR_ATTACHMENT | PL_TEXTURE_USAGE_INPUT_ATTACHMENT, + .pcDebugName = "offscreen final" + }; + + const plTextureDesc tRawOutputTextureCubeDesc = { + .tDimensions = {tProbeData.tTargetSize.x, tProbeData.tTargetSize.y, 1}, + .tFormat = PL_FORMAT_R16G16B16A16_FLOAT, + .uLayers = 6, + .uMips = 0, + .tType = PL_TEXTURE_TYPE_CUBE, + .tUsage = PL_TEXTURE_USAGE_SAMPLED, + .pcDebugName = "offscreen final cube" + }; + + const plTextureDesc tNormalTextureDesc = { + .tDimensions = {tProbeData.tTargetSize.x * 2.0f, tProbeData.tTargetSize.y * 3.0f, 1}, + .tFormat = PL_FORMAT_R16G16_FLOAT, + .uLayers = 1, + .uMips = 1, + .tType = PL_TEXTURE_TYPE_2D, + .tUsage = PL_TEXTURE_USAGE_SAMPLED | PL_TEXTURE_USAGE_COLOR_ATTACHMENT | PL_TEXTURE_USAGE_INPUT_ATTACHMENT, + .pcDebugName = "g-buffer normal" + }; + + const plTextureDesc tAlbedoTextureDesc = { + .tDimensions = {tProbeData.tTargetSize.x * 2.0f, tProbeData.tTargetSize.y * 3.0f, 1}, + .tFormat = PL_FORMAT_R8G8B8A8_UNORM, + .uLayers = 1, + .uMips = 1, + .tType = PL_TEXTURE_TYPE_2D, + .tUsage = PL_TEXTURE_USAGE_SAMPLED | PL_TEXTURE_USAGE_COLOR_ATTACHMENT | PL_TEXTURE_USAGE_INPUT_ATTACHMENT, + .pcDebugName = "albedo texture" + }; + + const plTextureDesc tDepthTextureDesc = { + .tDimensions = {tProbeData.tTargetSize.x * 2.0f, tProbeData.tTargetSize.y * 3.0f, 1}, + .tFormat = PL_FORMAT_D32_FLOAT_S8_UINT, + .uLayers = 1, + .uMips = 1, + .tType = PL_TEXTURE_TYPE_2D, + .tUsage = PL_TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT | PL_TEXTURE_USAGE_SAMPLED | PL_TEXTURE_USAGE_INPUT_ATTACHMENT, + .pcDebugName = "offscreen depth texture" + }; + + const plTextureDesc tMaskTextureDesc = { + .tDimensions = {tProbeData.tTargetSize.x * 2.0f, tProbeData.tTargetSize.y * 3.0f, 1}, + .tFormat = PL_FORMAT_R32G32_FLOAT, + .uLayers = 1, + .uMips = 1, + .tType = PL_TEXTURE_TYPE_2D, + .tUsage = PL_TEXTURE_USAGE_SAMPLED | PL_TEXTURE_USAGE_COLOR_ATTACHMENT | PL_TEXTURE_USAGE_STORAGE, + .pcDebugName = "mask texture" + }; + + const plTextureDesc tEmmissiveTexDesc = { + .tDimensions = {tProbeData.tTargetSize.x * 2.0f, tProbeData.tTargetSize.y * 3.0f, 1}, + .tFormat = PL_FORMAT_R16G16B16A16_FLOAT, + .uLayers = 1, + .uMips = 1, + .tType = PL_TEXTURE_TYPE_2D, + .tUsage = PL_TEXTURE_USAGE_SAMPLED | PL_TEXTURE_USAGE_COLOR_ATTACHMENT | PL_TEXTURE_USAGE_INPUT_ATTACHMENT, + .pcDebugName = "emissive texture" + }; + + const plBufferDesc atGlobalBuffersDesc = { + .tUsage = PL_BUFFER_USAGE_UNIFORM | PL_BUFFER_USAGE_STAGING, + .szByteSize = 134217728, + .pcDebugName = "global buffer" + }; + + const plBufferDesc atCameraBuffersDesc = { + .tUsage = PL_BUFFER_USAGE_STORAGE | PL_BUFFER_USAGE_STAGING, + .szByteSize = 4096, + .pcDebugName = "camera buffers" + }; + + const plBufferDesc atLightShadowDataBufferDesc = { + .tUsage = PL_BUFFER_USAGE_STORAGE | PL_BUFFER_USAGE_STAGING, + .szByteSize = 134217728, + .pcDebugName = "shadow data buffer" + }; + + const plBindGroupLayout tLightingBindGroupLayout = { + .atTextureBindings = { + {.uSlot = 0, .tStages = PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT}, + {.uSlot = 1, .tStages = PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT}, + {.uSlot = 2, .tStages = PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT}, + {.uSlot = 3, .tStages = PL_STAGE_PIXEL, .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT} + } + }; + + // create offscreen render pass + plRenderPassAttachments atAttachmentSets[PL_MAX_FRAMES_IN_FLIGHT] = {0}; + plRenderPassAttachments atShadowAttachmentSets[PL_MAX_FRAMES_IN_FLIGHT] = {0}; + + // textures + tProbeData.tRawOutputTexture = pl__refr_create_texture(&tRawOutputTextureDesc, "offscreen raw", 0, PL_TEXTURE_USAGE_SAMPLED); + tProbeData.tRawOutputCubeTexture = pl__refr_create_texture(&tRawOutputTextureCubeDesc, "offscreen raw cube", 0, PL_TEXTURE_USAGE_SAMPLED); + tProbeData.tAlbedoTexture = pl__refr_create_texture(&tAlbedoTextureDesc, "albedo original", 0, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); + tProbeData.tNormalTexture = pl__refr_create_texture(&tNormalTextureDesc, "normal original", 0, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); + tProbeData.tAOMetalRoughnessTexture = pl__refr_create_texture(&tEmmissiveTexDesc, "metalroughness original", 0, PL_TEXTURE_USAGE_COLOR_ATTACHMENT); + tProbeData.tDepthTexture = pl__refr_create_texture(&tDepthTextureDesc, "offscreen depth original", 0, PL_TEXTURE_USAGE_SAMPLED); + + // lighting bind group + const plBindGroupDesc tLightingBindGroupDesc = { + .ptPool = gptData->ptBindGroupPool, + .ptLayout = &tLightingBindGroupLayout, + .pcDebugName = "lighting bind group" + }; + tProbeData.tLightingBindGroup = gptGfx->create_bind_group(gptData->ptDevice, &tLightingBindGroupDesc); + + const plBindGroupUpdateTextureData atBGTextureData[] = { + { + .tTexture = tProbeData.tAlbedoTexture, + .uSlot = 0, + .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT + }, + { + .tTexture = tProbeData.tNormalTexture, + .uSlot = 1, + .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT + }, + { + .tTexture = tProbeData.tAOMetalRoughnessTexture, + .uSlot = 2, + .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT + }, + { + .tTexture = tProbeData.tDepthTexture, + .uSlot = 3, + .tType = PL_TEXTURE_BINDING_TYPE_INPUT_ATTACHMENT + } + }; + const plBindGroupUpdateData tBGData = { + .uTextureCount = 4, + .atTextureBindings = atBGTextureData + }; + gptGfx->update_bind_group(gptData->ptDevice, tProbeData.tLightingBindGroup, &tBGData); + + for(uint32_t i = 0; i < gptGfx->get_frames_in_flight(); i++) + { + + // buffers + tProbeData.atGlobalBuffers[i] = pl__refr_create_staging_buffer(&atGlobalBuffersDesc, "global", i); + + // attachment sets + atAttachmentSets[i].atViewAttachments[0] = tProbeData.tDepthTexture; + atAttachmentSets[i].atViewAttachments[1] = tProbeData.tRawOutputTexture; + atAttachmentSets[i].atViewAttachments[2] = tProbeData.tAlbedoTexture; + atAttachmentSets[i].atViewAttachments[3] = tProbeData.tNormalTexture; + atAttachmentSets[i].atViewAttachments[4] = tProbeData.tAOMetalRoughnessTexture; + + tProbeData.tDirectionLightShadowData.atDLightShadowDataBuffer[i] = pl__refr_create_staging_buffer(&atLightShadowDataBufferDesc, "d shadow", i); + tProbeData.tDirectionLightShadowData.atDShadowCameraBuffers[i] = pl__refr_create_staging_buffer(&atCameraBuffersDesc, "d shadow buffer", i); + + } + + const plRenderPassDesc tRenderPassDesc = { + .tLayout = gptData->tRenderPassLayout, + .tDepthTarget = { + .tLoadOp = PL_LOAD_OP_CLEAR, + .tStoreOp = PL_STORE_OP_STORE, + .tStencilLoadOp = PL_LOAD_OP_CLEAR, + .tStencilStoreOp = PL_STORE_OP_STORE, + .tCurrentUsage = PL_TEXTURE_USAGE_SAMPLED, + .tNextUsage = PL_TEXTURE_USAGE_SAMPLED, + .fClearZ = 0.0f + }, + .atColorTargets = { + { + .tLoadOp = PL_LOAD_OP_CLEAR, + .tStoreOp = PL_STORE_OP_STORE, + .tCurrentUsage = PL_TEXTURE_USAGE_SAMPLED, + .tNextUsage = PL_TEXTURE_USAGE_SAMPLED, + .tClearColor = {0.0f, 0.0f, 0.0f, 1.0f} + }, + { + .tLoadOp = PL_LOAD_OP_CLEAR, + .tStoreOp = PL_STORE_OP_STORE, + .tCurrentUsage = PL_TEXTURE_USAGE_COLOR_ATTACHMENT, + .tNextUsage = PL_TEXTURE_USAGE_COLOR_ATTACHMENT, + .tClearColor = {0.0f, 0.0f, 0.0f, 1.0f} + }, + { + .tLoadOp = PL_LOAD_OP_CLEAR, + .tStoreOp = PL_STORE_OP_STORE, + .tCurrentUsage = PL_TEXTURE_USAGE_COLOR_ATTACHMENT, + .tNextUsage = PL_TEXTURE_USAGE_COLOR_ATTACHMENT, + .tClearColor = {0.0f, 0.0f, 0.0f, 1.0f} + }, + { + .tLoadOp = PL_LOAD_OP_CLEAR, + .tStoreOp = PL_STORE_OP_STORE, + .tCurrentUsage = PL_TEXTURE_USAGE_COLOR_ATTACHMENT, + .tNextUsage = PL_TEXTURE_USAGE_COLOR_ATTACHMENT, + .tClearColor = {0.0f, 0.0f, 0.0f, 1.0f} + }, + { + .tLoadOp = PL_LOAD_OP_CLEAR, + .tStoreOp = PL_STORE_OP_STORE, + .tCurrentUsage = PL_TEXTURE_USAGE_COLOR_ATTACHMENT, + .tNextUsage = PL_TEXTURE_USAGE_COLOR_ATTACHMENT, + .tClearColor = {0.0f, 0.0f, 0.0f, 0.0f} + } + }, + .tDimensions = {.x = tProbeData.tTargetSize.x * 2.0f, .y = tProbeData.tTargetSize.y * 3.0f} + }; + tProbeData.tRenderPass = gptGfx->create_render_pass(gptData->ptDevice, &tRenderPassDesc, atAttachmentSets); + + const plTextureDesc tLutTextureDesc = { + .tDimensions = {(float)ptProbe->uResolution, (float)ptProbe->uResolution, 1}, + .tFormat = PL_FORMAT_R32G32B32A32_FLOAT, + .uLayers = 1, + .uMips = 1, + .tType = PL_TEXTURE_TYPE_2D, + .tUsage = PL_TEXTURE_USAGE_SAMPLED + }; + tProbeData.tGGXLUTTexture = pl__refr_create_texture(&tLutTextureDesc, "lut texture", uSceneHandle, PL_TEXTURE_USAGE_SAMPLED); + + const plTextureDesc tSpecularTextureDesc = { + .tDimensions = {(float)ptProbe->uResolution, (float)ptProbe->uResolution, 1}, + .tFormat = PL_FORMAT_R32G32B32A32_FLOAT, + .uLayers = 6, + .uMips = 1, + .tType = PL_TEXTURE_TYPE_CUBE, + .tUsage = PL_TEXTURE_USAGE_SAMPLED + }; + tProbeData.tLambertianEnvTexture = pl__refr_create_texture(&tSpecularTextureDesc, "specular texture", uSceneHandle, PL_TEXTURE_USAGE_SAMPLED); + + const plTextureDesc tTextureDesc = { + .tDimensions = {(float)ptProbe->uResolution, (float)ptProbe->uResolution, 1}, + .tFormat = PL_FORMAT_R32G32B32A32_FLOAT, + .uLayers = 6, + .uMips = (uint32_t)floorf(log2f((float)ptProbe->uResolution)) - 3, // guarantee final dispatch during filtering is 16 threads + .tType = PL_TEXTURE_TYPE_CUBE, + .tUsage = PL_TEXTURE_USAGE_SAMPLED + }; + tProbeData.tGGXEnvTexture = pl__refr_create_texture(&tTextureDesc, "tGGXEnvTexture", uSceneHandle, PL_TEXTURE_USAGE_SAMPLED); + + tProbeData.uGGXLUT = pl__get_bindless_texture_index(uSceneHandle, tProbeData.tGGXLUTTexture); + tProbeData.uLambertianEnvSampler = pl__get_bindless_cube_texture_index(uSceneHandle, tProbeData.tLambertianEnvTexture); + tProbeData.uGGXEnvSampler = pl__get_bindless_cube_texture_index(uSceneHandle, tProbeData.tGGXEnvTexture); + + pl_sb_push(ptScene->sbtProbeData, tProbeData); + + plMaterialComponent* ptMaterial = NULL; + plEntity tMaterial = gptECS->create_material(&ptScene->tComponentLibrary, "Probe Material", &ptMaterial); + ptMaterial->tBlendMode = PL_BLEND_MODE_OPAQUE; + ptMaterial->tShaderType = PL_SHADER_TYPE_PBR; + ptMaterial->tFlags = PL_MATERIAL_FLAG_CAST_RECEIVE_SHADOW; + ptMaterial->tBaseColor = (plVec4){1.0f, 1.0f, 1.0f, 1.0f}; + ptMaterial->fRoughness = 0.0f; + ptMaterial->fMetalness = 1.0f; + + plObjectComponent* ptProbeObj = gptECS->add_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tProbeHandle); + ptProbeObj->tMesh = tProbeHandle; + ptProbeObj->tTransform = tProbeHandle; + + plTransformComponent* ptProbeTransform = gptECS->add_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, tProbeHandle); + + ptProbe = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_ENVIRONMENT_PROBE, tProbeHandle); + ptProbeTransform->tTranslation = ptProbe->tPosition; + + plMeshComponent* ptMesh = gptECS->add_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, tProbeHandle); + ptMesh->tMaterial = tMaterial; + ptMesh->ulVertexStreamMask = PL_MESH_FORMAT_FLAG_HAS_NORMAL; + ptMesh->tAABB.tMin = (plVec3){-0.5f, -0.5f, -0.5f}; + ptMesh->tAABB.tMax = (plVec3){0.5f, 0.5f, 0.5f}; + + uint32_t uLatBands = 32; + uint32_t uLongBands = 32; + + pl_sb_resize(ptMesh->sbtVertexPositions, (uLatBands + 1) * (uLongBands + 1)); + pl_sb_resize(ptMesh->sbtVertexNormals, (uLatBands + 1) * (uLongBands + 1)); + pl_sb_resize(ptMesh->sbuIndices, uLatBands * uLongBands * 6); + + uint32_t uCurrentPoint = 0; + + ptProbe = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_ENVIRONMENT_PROBE, tProbeHandle); + float fRadius = 0.25f; + + for(uint32_t uLatNumber = 0; uLatNumber <= uLatBands; uLatNumber++) + { + const float fTheta = (float)uLatNumber * PL_PI / (float)uLatBands; + const float fSinTheta = sinf(fTheta); + const float fCosTheta = cosf(fTheta); + for(uint32_t uLongNumber = 0; uLongNumber <= uLongBands; uLongNumber++) + { + const float fPhi = (float)uLongNumber * 2 * PL_PI / (float)uLongBands; + const float fSinPhi = sinf(fPhi); + const float fCosPhi = cosf(fPhi); + ptMesh->sbtVertexPositions[uCurrentPoint] = (plVec3){ + fCosPhi * fSinTheta * fRadius, + fCosTheta * fRadius, + fSinPhi * fSinTheta * fRadius + }; + ptMesh->sbtVertexNormals[uCurrentPoint] = pl_norm_vec3(ptMesh->sbtVertexPositions[uCurrentPoint]); + uCurrentPoint++; + } + } + + uCurrentPoint = 0; + for(uint32_t uLatNumber = 0; uLatNumber < uLatBands; uLatNumber++) + { + + for(uint32_t uLongNumber = 0; uLongNumber < uLongBands; uLongNumber++) + { + const uint32_t uFirst = (uLatNumber * (uLongBands + 1)) + uLongNumber; + const uint32_t uSecond = uFirst + uLongBands + 1; + + ptMesh->sbuIndices[uCurrentPoint + 0] = uFirst + 1; + ptMesh->sbuIndices[uCurrentPoint + 1] = uSecond; + ptMesh->sbuIndices[uCurrentPoint + 2] = uFirst; + + ptMesh->sbuIndices[uCurrentPoint + 3] = uFirst + 1; + ptMesh->sbuIndices[uCurrentPoint + 4] = uSecond + 1; + ptMesh->sbuIndices[uCurrentPoint + 5] = uSecond; + + uCurrentPoint += 6; + } + } + + pl_add_drawable_objects_to_scene(uSceneHandle, 0, NULL, 1, &tProbeHandle); +}; + +static uint64_t +pl__update_environment_probes(uint32_t uSceneHandle, uint64_t ulValue) +{ + + // for convience + plDevice* ptDevice = gptData->ptDevice; + plDrawStream* ptStream = &gptData->tDrawStream; + plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; + + const uint32_t uFrameIdx = gptGfx->get_current_frame_index(); + plCommandPool* ptCmdPool = gptData->atCmdPools[uFrameIdx]; + plTimelineSemaphore* tSemHandle = gptData->aptSemaphores[uFrameIdx]; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~common data~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // pitch/yaw by face index + // const plVec2 atPitchYaw[6] = { + // { 0.0, PL_PI }, + // { 0.0, 0.0 }, + // { 0.0, PL_PI_2 }, + // { 0.0, -PL_PI_2 }, + // { PL_PI_2, 0.0 }, + // { -PL_PI_2, 0.0 } + // }; + + const plVec2 atPitchYaw[6] = { + { 0.0f, PL_PI_2 }, + { 0.0f, -PL_PI_2 }, + { PL_PI_2, PL_PI }, + { -PL_PI_2, PL_PI }, + + { PL_PI, 0.0f }, + { 0.0f, 0.0f }, + + }; + + // multiplication factors by face index (multiply by resolution) + const plVec2 atRenderOffset[6] = { + { 0.0f, 0.0f}, + { 1.0f, 0.0f}, + { 0.0f, 1.0f}, + { 1.0f, 1.0f}, + { 0.0f, 2.0f}, + { 1.0f, 2.0f}, + }; + + const plBindGroupLayout tSceneBGLayout = { + .atBufferBindings = { + { .uSlot = 0, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, + { .uSlot = 1, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, + { .uSlot = 2, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, + { .uSlot = 3, .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, + { .uSlot = 4, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, + { .uSlot = 5, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, + { .uSlot = 6, .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .tStages = PL_STAGE_PIXEL | PL_STAGE_VERTEX}, + }, + .atSamplerBindings = { + {.uSlot = 7, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL} + }, + }; + const plBindGroupDesc tSceneBGDesc = { + .ptPool = gptData->aptTempGroupPools[uFrameIdx], + .ptLayout = &tSceneBGLayout, + .pcDebugName = "probe scene bg" + }; + + plBindGroupLayout tSkyboxBG1Layout = { + .atBufferBindings = { + { + .tType = PL_BUFFER_BINDING_TYPE_STORAGE, + .uSlot = 0, + .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL + } + }, + .atSamplerBindings = { + {.uSlot = 1, .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL} + } + }; + + const plBindGroupDesc tSkyboxBG1Desc = { + .ptPool = gptData->aptTempGroupPools[uFrameIdx], + .ptLayout = &tSkyboxBG1Layout, + .pcDebugName = "skybox bg 1" + }; + + const plBindGroupUpdateSamplerData tSkyboxBG1SamplerData = { + .tSampler = gptData->tSkyboxSampler, + .uSlot = 1 + }; + + const plBindGroupUpdateSamplerData tShadowSamplerData = { + .tSampler = gptData->tShadowSampler, + .uSlot = 7 + }; + + const plBindGroupLayout tGBufferFillBG1Layout = { + .atBufferBindings = { + { + .tType = PL_BUFFER_BINDING_TYPE_STORAGE, + .uSlot = 0, + .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, + } + } + }; + + const plBindGroupDesc tGBufferFillBG1Desc = { + .ptPool = gptData->aptTempGroupPools[uFrameIdx], + .ptLayout = &tGBufferFillBG1Layout, + .pcDebugName = "gbuffer fille bg1" + }; + + const uint32_t uProbeCount = pl_sb_size(ptScene->sbtProbeData); + for(uint32_t uProbeIndex = 0; uProbeIndex < uProbeCount; uProbeIndex++) + { + plEnvironmentProbeData* ptProbe = &ptScene->sbtProbeData[uProbeIndex]; + plEnvironmentProbeComponent* ptProbeComp = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_ENVIRONMENT_PROBE, ptProbe->tEntity); + + if(!((ptProbeComp->tFlags & PL_ENVIRONMENT_PROBE_FLAGS_REALTIME) || (ptProbeComp->tFlags & PL_ENVIRONMENT_PROBE_FLAGS_DIRTY))) + { + continue; + } + + ptProbeComp->tFlags &= ~PL_ENVIRONMENT_PROBE_FLAGS_DIRTY; + + // reset probe data + pl_sb_reset(ptProbe->tDirectionLightShadowData.sbtDLightShadowData); + ptProbe->tDirectionLightShadowData.uOffset = 0; + ptProbe->tDirectionLightShadowData.uOffsetIndex = 0; + + const uint32_t uOpaqueDrawableCount = pl_sb_size(ptScene->sbtDeferredDrawables); + const uint32_t uTransparentDrawableCount = pl_sb_size(ptScene->sbtForwardDrawables); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~probe face pre-calc~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // temporary data for probes + + // create scene bind group (camera, lights, shadows) + const plBindGroupUpdateBufferData tSceneBGBufferData[7] = + { + { .uSlot = 0, .tBuffer = ptProbe->atGlobalBuffers[uFrameIdx], .szBufferRange = sizeof(BindGroup_0) * 6 }, + { .uSlot = 1, .tBuffer = ptScene->atDLightBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULight) * pl_sb_size(ptScene->sbtDLightData)}, + { .uSlot = 2, .tBuffer = ptScene->atPLightBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULight) * pl_sb_size(ptScene->sbtPLightData)}, + { .uSlot = 3, .tBuffer = ptScene->atSLightBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULight) * pl_sb_size(ptScene->sbtSLightData)}, + { .uSlot = 4, .tBuffer = ptProbe->tDirectionLightShadowData.atDLightShadowDataBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULightShadowData) * pl_sb_size(ptProbe->tDirectionLightShadowData.sbtDLightShadowData)}, + { .uSlot = 5, .tBuffer = ptScene->atPLightShadowDataBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULightShadowData) * pl_sb_size(ptScene->sbtPLightShadowData)}, + { .uSlot = 6, .tBuffer = ptScene->atSLightShadowDataBuffer[uFrameIdx], .szBufferRange = sizeof(plGPULightShadowData) * pl_sb_size(ptScene->sbtSLightShadowData)}, + }; + + const plBindGroupUpdateData tSceneBGData = { + .uBufferCount = 7, + .atBufferBindings = tSceneBGBufferData, + .uSamplerCount = 1, + .atSamplerBindings = &tShadowSamplerData + }; + plBindGroupHandle tSceneBG = gptGfx->create_bind_group(ptDevice, &tSceneBGDesc); + gptGfx->update_bind_group(gptData->ptDevice, tSceneBG, &tSceneBGData); + gptGfx->queue_bind_group_for_deletion(ptDevice, tSceneBG); + + // create skybox bind group 1 + const plBindGroupUpdateBufferData tSkyboxBG1BufferData = { + .tBuffer = ptProbe->atGlobalBuffers[uFrameIdx], + .uSlot = 0, + .szBufferRange = sizeof(BindGroup_0) * 6 + }; + + const plBindGroupUpdateData tSkyboxBG1Data = { + .uBufferCount = 1, + .atBufferBindings = &tSkyboxBG1BufferData, + .uSamplerCount = 1, + .atSamplerBindings = &tSkyboxBG1SamplerData, + }; + + plBindGroupHandle tSkyboxBG1 = gptGfx->create_bind_group(ptDevice, &tSkyboxBG1Desc); + gptGfx->update_bind_group(gptData->ptDevice, tSkyboxBG1, &tSkyboxBG1Data); + gptGfx->queue_bind_group_for_deletion(ptDevice, tSkyboxBG1); + + plDrawArea atAreas[6] = {0}; + + + plCameraComponent atEnvironmentCamera[6] = {0}; + + for(uint32_t uFace = 0; uFace < 6; uFace++) + { + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~culling~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // pl_sb_reset(ptProbe->sbtVisibleOpaqueDrawables[uFace]); + // pl_sb_reset(ptProbe->sbtVisibleTransparentDrawables[uFace]); + + // if(pl_sb_size(ptProbe->sbtVisibleOpaqueDrawables[uFace]) != uOpaqueDrawableCount) + // { + // pl_sb_resize(ptProbe->sbtVisibleOpaqueDrawables[uFace], uOpaqueDrawableCount); + // memcpy(ptProbe->sbtVisibleOpaqueDrawables[uFace], ptScene->sbtDeferredDrawables, sizeof(plDrawable) * uOpaqueDrawableCount); + // } + // if(pl_sb_size(ptProbe->sbtVisibleTransparentDrawables[uFace]) != uTransparentDrawableCount) + // { + // pl_sb_resize(ptProbe->sbtVisibleTransparentDrawables[uFace], uTransparentDrawableCount); + // memcpy(ptProbe->sbtVisibleTransparentDrawables[uFace], ptScene->sbtForwardDrawables, sizeof(plDrawable) * uTransparentDrawableCount); + // } + + atAreas[uFace] = (plDrawArea) { + .ptDrawStream = ptStream, + .atScissors = + { + { + .uWidth = (uint32_t)ptProbeComp->uResolution, + .uHeight = (uint32_t)ptProbeComp->uResolution, + .iOffsetX = (int)(atRenderOffset[uFace].x * (float)ptProbeComp->uResolution), + .iOffsetY = (int)(atRenderOffset[uFace].y * (float)ptProbeComp->uResolution), + } + }, + .atViewports = + { + { + .fX = atRenderOffset[uFace].x * (float)ptProbeComp->uResolution, + .fY = atRenderOffset[uFace].y * (float)ptProbeComp->uResolution, + .fWidth = (float)ptProbeComp->uResolution, + .fHeight = (float)ptProbeComp->uResolution, + .fMaxDepth = 1.0f + } + } + }; + + atEnvironmentCamera[uFace] = (plCameraComponent){ + .tType = PL_CAMERA_TYPE_PERSPECTIVE_REVERSE_Z, + .tPos = ptProbeComp->tPosition, + .fNearZ = 0.26f, + .fFarZ = ptProbeComp->fRange, + .fFieldOfView = PL_PI_2, + .fAspectRatio = 1.0f, + }; + gptCamera->set_pitch_yaw(&atEnvironmentCamera[uFace], atPitchYaw[uFace].x, atPitchYaw[uFace].y); + gptCamera->update(&atEnvironmentCamera[uFace]); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~cascaded shadow maps~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // TODO: these can be parallel + + const plBeginCommandInfo tBeginCSMInfo = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; + + plCommandBuffer* ptCSMCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); + gptGfx->begin_command_recording(ptCSMCommandBuffer, &tBeginCSMInfo); + + plRenderEncoder* ptCSMEncoder = gptGfx->begin_render_pass(ptCSMCommandBuffer, ptScene->tShadowRenderPass, NULL); + + pl_refr_generate_cascaded_shadow_map(ptCSMEncoder, ptCSMCommandBuffer, uSceneHandle, uFace, uProbeIndex, 1, &ptProbe->tDirectionLightShadowData, &atEnvironmentCamera[uFace]); + + gptGfx->end_render_pass(ptCSMEncoder); + gptGfx->end_command_recording(ptCSMCommandBuffer); + + const plSubmitInfo tSubmitCSMInfo = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptCSMCommandBuffer, &tSubmitCSMInfo); + gptGfx->return_command_buffer(ptCSMCommandBuffer); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~probe render prep~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + const BindGroup_0 tProbeBindGroupBuffer = { + .tViewportSize = {.x = ptProbe->tTargetSize.x, .y = ptProbe->tTargetSize.y, .z = 0.5f, .w = 1.0f / 3.0f}, + .tViewportInfo = {atRenderOffset[uFace].x * (float)ptProbeComp->uResolution, atRenderOffset[uFace].y * (float)ptProbeComp->uResolution}, + .tCameraPos = atEnvironmentCamera[uFace].tPos, + .tCameraProjection = atEnvironmentCamera[uFace].tProjMat, + .tCameraView = atEnvironmentCamera[uFace].tViewMat, + .tCameraViewProjection = pl_mul_mat4(&atEnvironmentCamera[uFace].tProjMat, &atEnvironmentCamera[uFace].tViewMat) + }; + + // copy global buffer data for probe rendering + const uint32_t uProbeGlobalBufferOffset = sizeof(BindGroup_0) * uFace; + plBuffer* ptProbeGlobalBuffer = gptGfx->get_buffer(ptDevice, ptProbe->atGlobalBuffers[uFrameIdx]); + memcpy(&ptProbeGlobalBuffer->tMemoryAllocation.pHostMapped[uProbeGlobalBufferOffset], &tProbeBindGroupBuffer, sizeof(BindGroup_0)); + } + + // copy probe shadow data to GPU buffer + plBuffer* ptDShadowDataBuffer = gptGfx->get_buffer(ptDevice, ptProbe->tDirectionLightShadowData.atDLightShadowDataBuffer[uFrameIdx]); + memcpy(ptDShadowDataBuffer->tMemoryAllocation.pHostMapped, ptProbe->tDirectionLightShadowData.sbtDLightShadowData, sizeof(plGPULightShadowData) * pl_sb_size(ptProbe->tDirectionLightShadowData.sbtDLightShadowData)); + + // create g-buffer fill bind group 1 + const plBindGroupUpdateBufferData tGBufferFillBG1BufferData = { + .tBuffer = ptProbe->atGlobalBuffers[uFrameIdx], + .uSlot = 0, + .szBufferRange = sizeof(BindGroup_0) * 6 + }; + + const plBindGroupUpdateData tGBufferFillBG1Data = { + .uBufferCount = 1, + .atBufferBindings = &tGBufferFillBG1BufferData + }; + + plBindGroupHandle tGBufferFillBG1 = gptGfx->create_bind_group(ptDevice, &tGBufferFillBG1Desc); + gptGfx->update_bind_group(gptData->ptDevice, tGBufferFillBG1, &tGBufferFillBG1Data); + gptGfx->queue_bind_group_for_deletion(ptDevice, tGBufferFillBG1); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~probe rendering~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + const plBeginCommandInfo tProbeBeginInfo = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; + + plCommandBuffer* ptCmdBuffer = gptGfx->request_command_buffer(ptCmdPool); + gptGfx->begin_command_recording(ptCmdBuffer, &tProbeBeginInfo); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~subpass 0 - g buffer fill~~~~~~~~~~~~~~~~~~~~~~~~~~ + + plRenderEncoder* ptProbeEncoder = gptGfx->begin_render_pass(ptCmdBuffer, ptProbe->tRenderPass, NULL); + gptGfx->set_depth_bias(ptProbeEncoder, 0.0f, 0.0f, 0.0f); + + for(uint32_t uFace = 0; uFace < 6; uFace++) + { + + plCullData tDeferredCullData = { + .ptScene = ptScene, + .ptCullCamera = &atEnvironmentCamera[uFace], + .atDrawables = ptScene->sbtDeferredDrawables + }; + + plJobDesc tDeferredJobDesc = { + .task = pl__refr_cull_job, + .pData = &tDeferredCullData + }; + + plAtomicCounter* ptDeferredCounter = NULL; + gptJob->dispatch_batch(uOpaqueDrawableCount, 0, tDeferredJobDesc, &ptDeferredCounter); + gptJob->wait_for_counter(ptDeferredCounter); + pl_sb_reset(ptProbe->sbtVisibleOpaqueDrawables[uFace]); + for(uint32_t uDrawableIndex = 0; uDrawableIndex < uOpaqueDrawableCount; uDrawableIndex++) + { + const plDrawable tDrawable = ptScene->sbtDeferredDrawables[uDrawableIndex]; + if(!tDrawable.bCulled) + pl_sb_push(ptProbe->sbtVisibleOpaqueDrawables[uFace], tDrawable); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~update bind groups~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + const uint32_t uVisibleOpaqueDrawCount = pl_sb_size(ptProbe->sbtVisibleOpaqueDrawables[uFace]); + *gptData->pdDrawCalls += (double)uVisibleOpaqueDrawCount; + gptGfx->reset_draw_stream(ptStream, uVisibleOpaqueDrawCount); + for(uint32_t i = 0; i < uVisibleOpaqueDrawCount; i++) + { + const plDrawable tDrawable = ptProbe->sbtVisibleOpaqueDrawables[uFace][i]; + plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); + plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); + + plDynamicBinding tDynamicBinding = pl__allocate_dynamic_data(ptDevice); + + DynamicData* ptDynamicData = (DynamicData*)tDynamicBinding.pcData; + ptDynamicData->iDataOffset = tDrawable.uDataOffset; + ptDynamicData->iVertexOffset = tDrawable.uIndexCount == 0 ? 0 : tDrawable.uVertexOffset; + ptDynamicData->tModel = ptTransform->tWorld; + ptDynamicData->iMaterialOffset = tDrawable.uMaterialIndex; + ptDynamicData->uGlobalIndex = uFace; + + pl_add_to_draw_stream(ptStream, (plDrawStreamData) + { + .tShader = tDrawable.tEnvShader, + .auDynamicBuffers = { + tDynamicBinding.uBufferHandle + }, + .atVertexBuffers = { + ptScene->tVertexBuffer, + }, + .tIndexBuffer = tDrawable.uIndexCount == 0 ? (plBufferHandle){0} : ptScene->tIndexBuffer, + .uIndexOffset = tDrawable.uIndexOffset, + .uTriangleCount = tDrawable.uIndexCount == 0 ? tDrawable.uVertexCount / 3 : tDrawable.uIndexCount / 3, + .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, + .atBindGroups = { + ptScene->tGlobalBindGroup, + tGBufferFillBG1 + }, + .auDynamicBufferOffsets = { + tDynamicBinding.uByteOffset + }, + .uInstanceOffset = 0, + .uInstanceCount = 1 + }); + } + + gptGfx->draw_stream(ptProbeEncoder, 1, &atAreas[uFace]); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~subpass 1 - lighting~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + gptGfx->next_subpass(ptProbeEncoder, NULL); + + for(uint32_t uFace = 0; uFace < 6; uFace++) + { + + // create lighting dynamic bind group + + typedef struct _plLightingDynamicData + { + uint32_t uLambertianEnvSampler; + uint32_t uGGXEnvSampler; + uint32_t uGGXLUT; + uint32_t uGlobalIndex; + } plLightingDynamicData; + + plDynamicBinding tLightingDynamicData = pl__allocate_dynamic_data(ptDevice); + plLightingDynamicData* ptLightingDynamicData = (plLightingDynamicData*)tLightingDynamicData.pcData; + ptLightingDynamicData->uGGXEnvSampler = ptScene->sbtProbeData[0].uGGXEnvSampler; + ptLightingDynamicData->uGGXLUT = ptScene->sbtProbeData[0].uGGXLUT; + ptLightingDynamicData->uLambertianEnvSampler = ptScene->sbtProbeData[0].uLambertianEnvSampler; + ptLightingDynamicData->uGlobalIndex = uFace; + + + gptGfx->reset_draw_stream(ptStream, 1); + *gptData->pdDrawCalls += 1.0; + pl_add_to_draw_stream(ptStream, (plDrawStreamData) + { + .tShader = ptScene->tEnvLightingShader, + .auDynamicBuffers = { + tLightingDynamicData.uBufferHandle + }, + .atVertexBuffers = { + gptData->tFullQuadVertexBuffer + }, + .tIndexBuffer = gptData->tFullQuadIndexBuffer, + .uIndexOffset = 0, + .uTriangleCount = 2, + .atBindGroups = { + ptScene->tGlobalBindGroup, + ptProbe->tLightingBindGroup, + tSceneBG + }, + .auDynamicBufferOffsets = { + tLightingDynamicData.uByteOffset + }, + .uInstanceOffset = 0, + .uInstanceCount = 1 + }); + gptGfx->draw_stream(ptProbeEncoder, 1, &atAreas[uFace]); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~subpass 2 - forward~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + gptGfx->next_subpass(ptProbeEncoder, NULL); + + for(uint32_t uFace = 0; uFace < 6; uFace++) + { + + plCullData tForwardCullData = { + .ptScene = ptScene, + .ptCullCamera = &atEnvironmentCamera[uFace], + .atDrawables = ptScene->sbtForwardDrawables + }; + + plJobDesc tForwardJobDesc = { + .task = pl__refr_cull_job, + .pData = &tForwardCullData + }; + plAtomicCounter* ptForwardCounter = NULL; + gptJob->dispatch_batch(uTransparentDrawableCount, 0, tForwardJobDesc, &ptForwardCounter); + gptJob->wait_for_counter(ptForwardCounter); + pl_sb_reset(ptProbe->sbtVisibleTransparentDrawables[uFace]); + for(uint32_t uDrawableIndex = 0; uDrawableIndex < uTransparentDrawableCount; uDrawableIndex++) + { + const plDrawable tDrawable = ptScene->sbtForwardDrawables[uDrawableIndex]; + if(!tDrawable.bCulled) + pl_sb_push(ptProbe->sbtVisibleTransparentDrawables[uFace], tDrawable); + } + + if(ptScene->tSkyboxTexture.uIndex != 0) + { + + plDynamicBinding tSkyboxDynamicData = pl__allocate_dynamic_data(ptDevice); + plSkyboxDynamicData* ptSkyboxDynamicData = (plSkyboxDynamicData*)tSkyboxDynamicData.pcData; + ptSkyboxDynamicData->tModel = pl_mat4_translate_vec3(ptProbeComp->tPosition); + ptSkyboxDynamicData->uGlobalIndex = uFace; + + gptGfx->reset_draw_stream(ptStream, 1); + *gptData->pdDrawCalls += 1.0; + pl_add_to_draw_stream(ptStream, (plDrawStreamData) + { + .tShader = gptData->tSkyboxShader, + .auDynamicBuffers = { + tSkyboxDynamicData.uBufferHandle + }, + .atVertexBuffers = { + ptScene->tVertexBuffer, + }, + .tIndexBuffer = ptScene->tIndexBuffer, + .uIndexOffset = ptScene->tSkyboxDrawable.uIndexOffset, + .uTriangleCount = ptScene->tSkyboxDrawable.uIndexCount / 3, + .atBindGroups = { + tSkyboxBG1, + ptScene->tSkyboxBindGroup + }, + .auDynamicBufferOffsets = { + tSkyboxDynamicData.uByteOffset + }, + .uInstanceOffset = 0, + .uInstanceCount = 1 + }); + gptGfx->draw_stream(ptProbeEncoder, 1, &atAreas[uFace]); + } + + // transparent & complex material objects + + const uint32_t uVisibleTransparentDrawCount = pl_sb_size(ptProbe->sbtVisibleTransparentDrawables[uFace]); + gptGfx->reset_draw_stream(ptStream, uVisibleTransparentDrawCount); + *gptData->pdDrawCalls += (double)uVisibleTransparentDrawCount; + for(uint32_t i = 0; i < uVisibleTransparentDrawCount; i++) + { + const plDrawable tDrawable = ptProbe->sbtVisibleTransparentDrawables[uFace][i]; + plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tDrawable.tEntity); + plTransformComponent* ptTransform = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptObject->tTransform); + + plDynamicBinding tDynamicBinding = pl__allocate_dynamic_data(ptDevice); + + DynamicData* ptDynamicData = (DynamicData*)tDynamicBinding.pcData; + ptDynamicData->iDataOffset = tDrawable.uDataOffset; + ptDynamicData->iVertexOffset = tDrawable.uIndexCount == 0 ? 0 : tDrawable.uVertexOffset; + ptDynamicData->tModel = ptTransform->tWorld; + ptDynamicData->iMaterialOffset = tDrawable.uMaterialIndex; + ptDynamicData->uGlobalIndex = uFace; + + pl_add_to_draw_stream(ptStream, (plDrawStreamData) + { + .tShader = tDrawable.tEnvShader, + .auDynamicBuffers = { + tDynamicBinding.uBufferHandle + }, + .atVertexBuffers = { + ptScene->tVertexBuffer, + }, + .tIndexBuffer = tDrawable.uIndexCount == 0 ? (plBufferHandle){0} : ptScene->tIndexBuffer, + .uIndexOffset = tDrawable.uIndexOffset, + .uTriangleCount = tDrawable.uIndexCount == 0 ? tDrawable.uVertexCount / 3 : tDrawable.uIndexCount / 3, + .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, + .atBindGroups = { + ptScene->tGlobalBindGroup, + tSceneBG + }, + .auDynamicBufferOffsets = { + tDynamicBinding.uByteOffset + }, + .uInstanceOffset = 0, + .uInstanceCount = 1 + }); + } + gptGfx->draw_stream(ptProbeEncoder, 1, &atAreas[uFace]); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~submission~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + gptGfx->end_render_pass(ptProbeEncoder); + gptGfx->end_command_recording(ptCmdBuffer); + + const plSubmitInfo tProbeSubmitInfo = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptCmdBuffer, &tProbeSubmitInfo); + gptGfx->return_command_buffer(ptCmdBuffer); + ulValue = pl_create_environment_map_from_texture(uSceneHandle, ptProbe, ulValue); + } + + return ulValue; +} + +static uint64_t +pl_create_environment_map_from_texture(uint32_t uSceneHandle, plEnvironmentProbeData* ptProbe, uint64_t ulValue) +{ + pl_begin_cpu_sample(gptProfile, 0, __FUNCTION__); + // const int iSamples = 1024; + const int iSamples = 128; + plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; + plDevice* ptDevice = gptData->ptDevice; + plCommandPool* ptCmdPool = gptData->atCmdPools[gptGfx->get_current_frame_index()]; + plTimelineSemaphore* tSemHandle = gptData->aptSemaphores[gptGfx->get_current_frame_index()]; + + plTexture* ptCubeTexture = gptGfx->get_texture(ptDevice, ptProbe->tRawOutputCubeTexture); + plTexture* ptTexture = gptGfx->get_texture(ptDevice, ptProbe->tRawOutputTexture); + const int iResolution = (int)(ptCubeTexture->tDesc.tDimensions.x); + const size_t uFaceSize = ((size_t)iResolution * (size_t)iResolution) * 4 * sizeof(float); + + // copy to cube + { + + plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); + const plBeginCommandInfo tBeginInfo1 = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; + gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo1); + plBlitEncoder* ptBlitEncoder = gptGfx->begin_blit_pass(ptCommandBuffer); + gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE); + + plImageCopy atImageCopy[6] = {0}; + + const plVec2 atRenderOffset[6] = { + { 0.0f, 0.0f}, // +x + { 1.0f, 0.0f}, // -x + { 0.0f, 1.0f}, // +y + { 1.0f, 1.0f}, // -y + { 0.0f, 2.0f}, // +z + { 1.0f, 2.0f}, // -z + }; + + for(uint32_t i = 0; i < 6; i++) + { + // source + atImageCopy[i].iSourceOffsetX = iResolution * (int)atRenderOffset[i].x; + atImageCopy[i].iSourceOffsetY = iResolution * (int)atRenderOffset[i].y; + atImageCopy[i].iSourceOffsetZ = 0; + atImageCopy[i].uSourceExtentX = (uint32_t)iResolution; + atImageCopy[i].uSourceExtentY = (uint32_t)iResolution; + atImageCopy[i].uSourceExtentZ = 1; + atImageCopy[i].uSourceMipLevel = 0; + atImageCopy[i].uSourceBaseArrayLayer = 0; + atImageCopy[i].uSourceLayerCount = 1; + atImageCopy[i].tSourceImageUsage = PL_TEXTURE_USAGE_SAMPLED; + + // destination + atImageCopy[i].iDestinationOffsetX = 0; + atImageCopy[i].iDestinationOffsetY = 0; + atImageCopy[i].iDestinationOffsetZ = 0; + atImageCopy[i].uDestinationMipLevel = 0; + atImageCopy[i].uDestinationBaseArrayLayer = i; + atImageCopy[i].uDestinationLayerCount = 1; + atImageCopy[i].tDestinationImageUsage = PL_TEXTURE_USAGE_SAMPLED; + } + gptGfx->copy_texture(ptBlitEncoder, ptProbe->tRawOutputTexture, ptProbe->tRawOutputCubeTexture, 6, atImageCopy); + gptGfx->generate_mipmaps(ptBlitEncoder, ptProbe->tRawOutputCubeTexture); + gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ); + gptGfx->end_blit_pass(ptBlitEncoder); + gptGfx->end_command_recording(ptCommandBuffer); + const plSubmitInfo tSubmitInfo = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo); + gptGfx->return_command_buffer(ptCommandBuffer); + } + + plBindGroupLayout tBindgroupLayout = { + .atTextureBindings = { + {.uSlot = 1, .tStages = PL_STAGE_COMPUTE, .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED} + }, + .atBufferBindings = { + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 2, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 3, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 4, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 5, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 6, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 7, .tStages = PL_STAGE_COMPUTE}, + { .tType = PL_BUFFER_BINDING_TYPE_STORAGE, .uSlot = 8, .tStages = PL_STAGE_COMPUTE}, + }, + .atSamplerBindings = { {.uSlot = 0, .tStages = PL_STAGE_COMPUTE}} + }; + + typedef struct _FilterShaderSpecData{ + int iResolution; + float fRoughness; + int iSampleCount; + int iWidth; + float fLodBias; + int iDistribution; + int iIsGeneratingLut; + int iCurrentMipLevel; + } FilterShaderSpecData; + + // create lut + + { + + const plBindGroupDesc tFilterBindGroupDesc = { + .ptPool = gptData->aptTempGroupPools[gptGfx->get_current_frame_index()], + .ptLayout = &tBindgroupLayout, + .pcDebugName = "lut bind group" + }; + plBindGroupHandle tLutBindGroup = gptGfx->create_bind_group(ptDevice, &tFilterBindGroupDesc); + const plBindGroupUpdateBufferData atBGBufferData[] = { + { .uSlot = 2, .tBuffer = ptScene->atFilterWorkingBuffers[0], .szBufferRange = uFaceSize}, + { .uSlot = 3, .tBuffer = ptScene->atFilterWorkingBuffers[1], .szBufferRange = uFaceSize}, + { .uSlot = 4, .tBuffer = ptScene->atFilterWorkingBuffers[2], .szBufferRange = uFaceSize}, + { .uSlot = 5, .tBuffer = ptScene->atFilterWorkingBuffers[3], .szBufferRange = uFaceSize}, + { .uSlot = 6, .tBuffer = ptScene->atFilterWorkingBuffers[4], .szBufferRange = uFaceSize}, + { .uSlot = 7, .tBuffer = ptScene->atFilterWorkingBuffers[5], .szBufferRange = uFaceSize}, + { .uSlot = 8, .tBuffer = ptScene->atFilterWorkingBuffers[6], .szBufferRange = uFaceSize}, + }; + + const plBindGroupUpdateSamplerData tSamplerData = { + .tSampler = gptData->tSkyboxSampler, + .uSlot = 0 + }; + const plBindGroupUpdateTextureData tTextureData = { + .tTexture = ptProbe->tRawOutputCubeTexture, + .uSlot = 1, + .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED + }; + const plBindGroupUpdateData tBGData = { + .uBufferCount = 7, + .atBufferBindings = atBGBufferData, + .uSamplerCount = 1, + .atSamplerBindings = &tSamplerData, + .uTextureCount = 1, + .atTextureBindings = &tTextureData + }; + gptGfx->update_bind_group(ptDevice, tLutBindGroup, &tBGData); + gptGfx->queue_bind_group_for_deletion(ptDevice, tLutBindGroup); + + const plDispatch tDispach = { + .uGroupCountX = (uint32_t)iResolution / 16, + .uGroupCountY = (uint32_t)iResolution / 16, + .uGroupCountZ = 2, + .uThreadPerGroupX = 16, + .uThreadPerGroupY = 16, + .uThreadPerGroupZ = 3 + }; + + plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); + const plBeginCommandInfo tBeginInfo0 = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; + gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo0); + + const plPassBufferResource atPassBuffers[] = { + { .tHandle = ptScene->atFilterWorkingBuffers[0], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, + { .tHandle = ptScene->atFilterWorkingBuffers[1], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, + { .tHandle = ptScene->atFilterWorkingBuffers[2], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, + { .tHandle = ptScene->atFilterWorkingBuffers[3], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, + { .tHandle = ptScene->atFilterWorkingBuffers[4], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, + { .tHandle = ptScene->atFilterWorkingBuffers[5], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, + { .tHandle = ptScene->atFilterWorkingBuffers[6], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, + }; + + const plPassResources tPassResources = { + .uBufferCount = 7, + .atBuffers = atPassBuffers + }; + + plDynamicBinding tDynamicBinding = pl__allocate_dynamic_data(ptDevice); + FilterShaderSpecData* ptDynamicData = (FilterShaderSpecData*)tDynamicBinding.pcData; + ptDynamicData->iResolution = iResolution; + ptDynamicData->fRoughness = 0.0f; + ptDynamicData->iSampleCount = iSamples; + ptDynamicData->iWidth = iResolution; + ptDynamicData->fLodBias = 0.0f; + ptDynamicData->iDistribution = 1; + ptDynamicData->iIsGeneratingLut = 1; + ptDynamicData->iCurrentMipLevel = 0; + + plDynamicBinding tIrradianceDynamicBinding = pl__allocate_dynamic_data(ptDevice); + FilterShaderSpecData* ptIrrDynamicData = (FilterShaderSpecData*)tIrradianceDynamicBinding.pcData; + ptIrrDynamicData->iResolution = iResolution; + ptIrrDynamicData->fRoughness = 0.0f; + ptIrrDynamicData->iSampleCount = iSamples; + ptIrrDynamicData->iWidth = iResolution; + ptIrrDynamicData->fLodBias = 0.0f; + ptIrrDynamicData->iDistribution = 0; + ptIrrDynamicData->iIsGeneratingLut = 0; + ptIrrDynamicData->iCurrentMipLevel = 0; + + plComputeEncoder* ptComputeEncoder = gptGfx->begin_compute_pass(ptCommandBuffer, &tPassResources); + gptGfx->pipeline_barrier_compute(ptComputeEncoder, PL_STAGE_VERTEX | PL_STAGE_COMPUTE, PL_ACCESS_SHADER_READ, PL_STAGE_COMPUTE, PL_ACCESS_SHADER_WRITE); + gptGfx->bind_compute_bind_groups(ptComputeEncoder, gptData->tEnvFilterShader, 0, 1, &tLutBindGroup, 1, &tDynamicBinding); + gptGfx->bind_compute_shader(ptComputeEncoder, gptData->tEnvFilterShader); + gptGfx->dispatch(ptComputeEncoder, 1, &tDispach); + + gptGfx->bind_compute_bind_groups(ptComputeEncoder, gptData->tEnvFilterShader, 0, 1, &tLutBindGroup, 1, &tIrradianceDynamicBinding); + gptGfx->bind_compute_shader(ptComputeEncoder, gptData->tEnvFilterShader); + gptGfx->dispatch(ptComputeEncoder, 1, &tDispach); + gptGfx->pipeline_barrier_compute(ptComputeEncoder, PL_STAGE_COMPUTE, PL_ACCESS_SHADER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE, PL_ACCESS_SHADER_READ); + gptGfx->end_compute_pass(ptComputeEncoder); + gptGfx->end_command_recording(ptCommandBuffer); + + const plSubmitInfo tSubmitInfo0 = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo0); + gptGfx->return_command_buffer(ptCommandBuffer); + + ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); + const plBeginCommandInfo tBeginInfo1 = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; + gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo1); + plBlitEncoder* ptBlitEncoder = gptGfx->begin_blit_pass(ptCommandBuffer); + gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE); + + const plBufferImageCopy tBufferImageCopy0 = { + .uImageWidth = iResolution, + .uImageHeight = iResolution, + .uImageDepth = 1, + .uLayerCount = 1, + .szBufferOffset = 0, + .uBaseArrayLayer = 0, + }; + gptGfx->copy_buffer_to_texture(ptBlitEncoder, ptScene->atFilterWorkingBuffers[6], ptProbe->tGGXLUTTexture, 1, &tBufferImageCopy0); + + for(uint32_t i = 0; i < 6; i++) + { + const plBufferImageCopy tBufferImageCopy = { + .uImageWidth = iResolution, + .uImageHeight = iResolution, + .uImageDepth = 1, + .uLayerCount = 1, + .szBufferOffset = 0, + .uBaseArrayLayer = i, + }; + gptGfx->copy_buffer_to_texture(ptBlitEncoder, ptScene->atFilterWorkingBuffers[i], ptProbe->tLambertianEnvTexture, 1, &tBufferImageCopy); + } + gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ); + gptGfx->end_blit_pass(ptBlitEncoder); + gptGfx->end_command_recording(ptCommandBuffer); + const plSubmitInfo tSubmitInfo = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo); + gptGfx->return_command_buffer(ptCommandBuffer); + } + + { + + const plBindGroupUpdateSamplerData tSamplerData = { + .tSampler = gptData->tSkyboxSampler, + .uSlot = 0 + }; + const plBindGroupUpdateTextureData tTextureData = { + .tTexture = ptProbe->tRawOutputCubeTexture, + .uSlot = 1, + .tType = PL_TEXTURE_BINDING_TYPE_SAMPLED + }; + + const size_t uMaxFaceSize = (size_t)iResolution * (size_t)iResolution * 4 * sizeof(float); + + + const plBindGroupDesc tFilterComputeBindGroupDesc = { + .ptPool = gptData->aptTempGroupPools[gptGfx->get_current_frame_index()], + .ptLayout = &tBindgroupLayout, + .pcDebugName = "lut bindgroup" + }; + plBindGroupHandle tLutBindGroup = gptGfx->create_bind_group(ptDevice, &tFilterComputeBindGroupDesc); + + const plBindGroupUpdateBufferData atBGBufferData[] = { + { .uSlot = 2, .tBuffer = ptScene->atFilterWorkingBuffers[0], .szBufferRange = uMaxFaceSize}, + { .uSlot = 3, .tBuffer = ptScene->atFilterWorkingBuffers[1], .szBufferRange = uMaxFaceSize}, + { .uSlot = 4, .tBuffer = ptScene->atFilterWorkingBuffers[2], .szBufferRange = uMaxFaceSize}, + { .uSlot = 5, .tBuffer = ptScene->atFilterWorkingBuffers[3], .szBufferRange = uMaxFaceSize}, + { .uSlot = 6, .tBuffer = ptScene->atFilterWorkingBuffers[4], .szBufferRange = uMaxFaceSize}, + { .uSlot = 7, .tBuffer = ptScene->atFilterWorkingBuffers[5], .szBufferRange = uMaxFaceSize}, + { .uSlot = 8, .tBuffer = ptScene->atFilterWorkingBuffers[6], .szBufferRange = uMaxFaceSize} + }; + + const plBindGroupUpdateData tBGData = { + .uBufferCount = 7, + .atBufferBindings = atBGBufferData, + .uSamplerCount = 1, + .atSamplerBindings = &tSamplerData, + .uTextureCount = 1, + .atTextureBindings = &tTextureData + }; + gptGfx->update_bind_group(ptDevice, tLutBindGroup, &tBGData); + gptGfx->queue_bind_group_for_deletion(ptDevice, tLutBindGroup); + + const plPassBufferResource atInnerPassBuffers[] = { + { .tHandle = ptScene->atFilterWorkingBuffers[0], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, + { .tHandle = ptScene->atFilterWorkingBuffers[1], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, + { .tHandle = ptScene->atFilterWorkingBuffers[2], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, + { .tHandle = ptScene->atFilterWorkingBuffers[3], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, + { .tHandle = ptScene->atFilterWorkingBuffers[4], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, + { .tHandle = ptScene->atFilterWorkingBuffers[5], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, + { .tHandle = ptScene->atFilterWorkingBuffers[6], .tStages = PL_STAGE_COMPUTE, .tUsage = PL_PASS_RESOURCE_USAGE_WRITE }, + }; + + const plPassResources tInnerPassResources = { + .uBufferCount = 7, + .atBuffers = atInnerPassBuffers + }; + + plTexture* ptEnvTexture = gptGfx->get_texture(ptDevice, ptProbe->tGGXEnvTexture); + for(int i = ptEnvTexture->tDesc.uMips - 1; i != -1; i--) + { + int currentWidth = iResolution >> i; + + if(currentWidth < 16) + continue; + + // const size_t uCurrentFaceSize = (size_t)currentWidth * (size_t)currentWidth * 4 * sizeof(float); + + const plDispatch tDispach = { + .uGroupCountX = (uint32_t)currentWidth / 16, + .uGroupCountY = (uint32_t)currentWidth / 16, + .uGroupCountZ = 2, + .uThreadPerGroupX = 16, + .uThreadPerGroupY = 16, + .uThreadPerGroupZ = 3 + }; + + plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); + const plBeginCommandInfo tBeginInfo = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; + gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo); + + plDynamicBinding tDynamicBinding = pl__allocate_dynamic_data(ptDevice); + FilterShaderSpecData* ptDynamicData = (FilterShaderSpecData*)tDynamicBinding.pcData; + ptDynamicData->iResolution = iResolution; + ptDynamicData->fRoughness = (float)i / (float)(ptEnvTexture->tDesc.uMips - 1); + ptDynamicData->iSampleCount = i == 0 ? 1 : iSamples; + ptDynamicData->iWidth = currentWidth; + ptDynamicData->fLodBias = 0.0f; + ptDynamicData->iDistribution = 1; + ptDynamicData->iIsGeneratingLut = 0; + ptDynamicData->iCurrentMipLevel = i; + + plComputeEncoder* ptComputeEncoder = gptGfx->begin_compute_pass(ptCommandBuffer, &tInnerPassResources); + gptGfx->pipeline_barrier_compute(ptComputeEncoder, PL_STAGE_VERTEX | PL_STAGE_COMPUTE, PL_ACCESS_SHADER_READ, PL_STAGE_COMPUTE, PL_ACCESS_SHADER_WRITE); + gptGfx->bind_compute_bind_groups(ptComputeEncoder, gptData->tEnvFilterShader, 0, 1, &tLutBindGroup, 1, &tDynamicBinding); + gptGfx->bind_compute_shader(ptComputeEncoder, gptData->tEnvFilterShader); + gptGfx->dispatch(ptComputeEncoder, 1, &tDispach); + gptGfx->pipeline_barrier_compute(ptComputeEncoder, PL_STAGE_COMPUTE, PL_ACCESS_SHADER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE, PL_ACCESS_SHADER_READ); + gptGfx->end_compute_pass(ptComputeEncoder); + gptGfx->end_command_recording(ptCommandBuffer); + const plSubmitInfo tSubmitInfo = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo); + gptGfx->return_command_buffer(ptCommandBuffer); + + ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); + const plBeginCommandInfo tBeginInfo2 = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; + gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo2); + plBlitEncoder* ptBlitEncoder = gptGfx->begin_blit_pass(ptCommandBuffer); + gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE); + + for(uint32_t j = 0; j < 6; j++) + { + const plBufferImageCopy tBufferImageCopy = { + .uImageWidth = currentWidth, + .uImageHeight = currentWidth, + .uImageDepth = 1, + .uLayerCount = 1, + .szBufferOffset = 0, + .uBaseArrayLayer = j, + .uMipLevel = i + }; + gptGfx->copy_buffer_to_texture(ptBlitEncoder, ptScene->atFilterWorkingBuffers[j], ptProbe->tGGXEnvTexture, 1, &tBufferImageCopy); + } + gptGfx->pipeline_barrier_blit(ptBlitEncoder, PL_STAGE_TRANSFER, PL_ACCESS_TRANSFER_WRITE, PL_STAGE_VERTEX | PL_STAGE_COMPUTE | PL_STAGE_TRANSFER, PL_ACCESS_SHADER_READ | PL_ACCESS_TRANSFER_READ); + gptGfx->end_blit_pass(ptBlitEncoder); + gptGfx->end_command_recording(ptCommandBuffer); + const plSubmitInfo tSubmitInfo0 = { + .uSignalSemaphoreCount = 1, + .atSignalSempahores = {tSemHandle}, + .auSignalSemaphoreValues = {++ulValue} + }; + gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo0); + // gptGfx->wait_on_command_buffer(ptCommandBuffer); + gptGfx->return_command_buffer(ptCommandBuffer); + + } + } + + pl_end_cpu_sample(gptProfile, 0); + return ulValue; +} + +static void +pl__refr_process_drawables(uint32_t uSceneHandle, bool bReload) +{ + plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; + plDevice* ptDevice = gptData->ptDevice; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~CPU Buffers~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + int iSceneWideRenderingFlags = 0; + if(gptData->bPunctualLighting) + iSceneWideRenderingFlags |= PL_RENDERING_FLAG_USE_PUNCTUAL; + if(gptData->bImageBasedLighting) + iSceneWideRenderingFlags |= PL_RENDERING_FLAG_USE_IBL; + + // fill CPU buffers & drawable list + + pl_sb_reset(ptScene->sbtDeferredDrawables); + pl_sb_reset(ptScene->sbtForwardDrawables); + pl_sb_reset(ptScene->sbuShadowDeferredDrawables); + pl_sb_reset(ptScene->sbuShadowForwardDrawables); + + plDrawable* sbtNewDrawables[] = { + ptScene->sbtNewDeferredDrawables, + ptScene->sbtNewForwardDrawables, + }; + + plDrawable* sbtDrawables[] = { + ptScene->sbtDeferredDrawables, + ptScene->sbtForwardDrawables, + }; + + uint32_t* sbuShadowDrawables[] = { + ptScene->sbuShadowDeferredDrawables, + ptScene->sbuShadowForwardDrawables, + }; + + plShaderHandle atTemplateShaders[] = { + gptData->tDeferredShader, + gptData->tForwardShader + }; + + plShaderHandle atTemplateShadowShaders[] = { + gptData->tShadowShader, + gptData->tAlphaShadowShader + }; + + plGraphicsState atTemplateVariants[] = { + { + .ulDepthWriteEnabled = 1, + .ulDepthMode = PL_COMPARE_MODE_GREATER, + .ulCullMode = PL_CULL_MODE_CULL_BACK, + .ulStencilMode = PL_COMPARE_MODE_ALWAYS, + .ulStencilRef = 0xff, + .ulStencilMask = 0xff, + .ulStencilOpFail = PL_STENCIL_OP_KEEP, + .ulStencilOpDepthFail = PL_STENCIL_OP_KEEP, + .ulStencilOpPass = PL_STENCIL_OP_KEEP + }, + { + .ulDepthWriteEnabled = 1, + .ulDepthMode = PL_COMPARE_MODE_GREATER_OR_EQUAL, + .ulCullMode = PL_CULL_MODE_NONE, + .ulStencilMode = PL_COMPARE_MODE_ALWAYS, + .ulStencilRef = 0xff, + .ulStencilMask = 0xff, + .ulStencilOpFail = PL_STENCIL_OP_KEEP, + .ulStencilOpDepthFail = PL_STENCIL_OP_KEEP, + .ulStencilOpPass = PL_STENCIL_OP_KEEP + } + }; + + plHashMap* atHashmaps[] = { + ptScene->ptDeferredHashmap, + ptScene->ptForwardHashmap + }; + + for(uint32_t uDrawableBatchIndex = 0; uDrawableBatchIndex < 2; uDrawableBatchIndex++) + { + plHashMap* ptHashmap = atHashmaps[uDrawableBatchIndex]; + const uint32_t uDrawableCount = pl_sb_size(sbtNewDrawables[uDrawableBatchIndex]); + if(!bReload) + { + pl_hm_resize(ptHashmap, uDrawableCount); + } + for(uint32_t i = 0; i < uDrawableCount; i++) + { + + (sbtNewDrawables[uDrawableBatchIndex])[i].uSkinIndex = UINT32_MAX; + plEntity tEntity = (sbtNewDrawables[uDrawableBatchIndex])[i].tEntity; + + if(!bReload) + { + pl_hm_insert(ptHashmap, tEntity.ulData, i); + } + + // get actual components + plObjectComponent* ptObject = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_OBJECT, tEntity); + plMeshComponent* ptMesh = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MESH, ptObject->tMesh); + plMaterialComponent* ptMaterial = gptECS->get_component(&ptScene->tComponentLibrary, PL_COMPONENT_TYPE_MATERIAL, ptMesh->tMaterial); + + uint32_t uMaterialIndex = UINT32_MAX; + + if(pl_hm_has_key(ptScene->ptMaterialHashmap, ptMesh->tMaterial.ulData)) + { + uMaterialIndex = (uint32_t)pl_hm_lookup(ptScene->ptMaterialHashmap, ptMesh->tMaterial.ulData); + } + else + { + + uint64_t ulValue = pl_hm_get_free_index(ptScene->ptMaterialHashmap); + if(ulValue == UINT64_MAX) + { + ulValue = pl_sb_size(ptScene->sbtMaterialBuffer); + pl_sb_add(ptScene->sbtMaterialBuffer); + } + + uMaterialIndex = (uint32_t)ulValue; + + plTextureHandle tBaseColorTex = pl__create_texture_helper(ptMaterial, PL_TEXTURE_SLOT_BASE_COLOR_MAP, true, 0); + plTextureHandle tNormalTex = pl__create_texture_helper(ptMaterial, PL_TEXTURE_SLOT_NORMAL_MAP, false, 0); + plTextureHandle tEmissiveTex = pl__create_texture_helper(ptMaterial, PL_TEXTURE_SLOT_EMISSIVE_MAP, true, 0); + plTextureHandle tMetallicRoughnessTex = pl__create_texture_helper(ptMaterial, PL_TEXTURE_SLOT_METAL_ROUGHNESS_MAP, false, 0); + plTextureHandle tOcclusionTex = pl__create_texture_helper(ptMaterial, PL_TEXTURE_SLOT_OCCLUSION_MAP, false, 1); + + int iBaseColorTexIdx = (int)pl__get_bindless_texture_index(uSceneHandle, tBaseColorTex); + int iNormalTexIdx = (int)pl__get_bindless_texture_index(uSceneHandle, tNormalTex); + int iEmissiveTexIdx = (int)pl__get_bindless_texture_index(uSceneHandle, tEmissiveTex); + int iMetallicRoughnessTexIdx = (int)pl__get_bindless_texture_index(uSceneHandle, tMetallicRoughnessTex); + int iOcclusionTexIdx = (int)pl__get_bindless_texture_index(uSceneHandle, tOcclusionTex); + + plGPUMaterial tMaterial = { + .fMetallicFactor = ptMaterial->fMetalness, + .fRoughnessFactor = ptMaterial->fRoughness, + .tBaseColorFactor = ptMaterial->tBaseColor, + .tEmissiveFactor = ptMaterial->tEmissiveColor.rgb, + .fAlphaCutoff = ptMaterial->fAlphaCutoff, + .fOcclusionStrength = 1.0f, + .fEmissiveStrength = 1.0f, + .iBaseColorUVSet = (int)ptMaterial->atTextureMaps[PL_TEXTURE_SLOT_BASE_COLOR_MAP].uUVSet, + .iNormalUVSet = (int)ptMaterial->atTextureMaps[PL_TEXTURE_SLOT_NORMAL_MAP].uUVSet, + .iEmissiveUVSet = (int)ptMaterial->atTextureMaps[PL_TEXTURE_SLOT_EMISSIVE_MAP].uUVSet, + .iOcclusionUVSet = (int)ptMaterial->atTextureMaps[PL_TEXTURE_SLOT_OCCLUSION_MAP].uUVSet, + .iMetallicRoughnessUVSet = (int)ptMaterial->atTextureMaps[PL_TEXTURE_SLOT_METAL_ROUGHNESS_MAP].uUVSet, + .iBaseColorTexIdx = iBaseColorTexIdx, + .iNormalTexIdx = iNormalTexIdx, + .iEmissiveTexIdx = iEmissiveTexIdx, + .iMetallicRoughnessTexIdx = iMetallicRoughnessTexIdx, + .iOcclusionTexIdx = iOcclusionTexIdx + }; + ptScene->sbtMaterialBuffer[uMaterialIndex] = tMaterial; + pl_hm_insert(ptScene->ptMaterialHashmap, ptMesh->tMaterial.ulData, ulValue); + } + + (sbtNewDrawables[uDrawableBatchIndex])[i].uMaterialIndex = uMaterialIndex; + + // add data to global buffers + if(!bReload) + { + pl__add_drawable_data_to_global_buffer(ptScene, i, (sbtNewDrawables[uDrawableBatchIndex])); + pl__add_drawable_skin_data_to_global_buffer(ptScene, i, (sbtNewDrawables[uDrawableBatchIndex])); + } + + int iDataStride = 0; + int iFlagCopy0 = (int)ptMesh->ulVertexStreamMask; + while(iFlagCopy0) + { + iDataStride += iFlagCopy0 & 1; + iFlagCopy0 >>= 1; + } + + int iTextureMappingFlags = 0; + for(uint32_t j = 0; j < PL_TEXTURE_SLOT_COUNT; j++) + { + if((ptMaterial->atTextureMaps[j].acName[0] != 0)) + iTextureMappingFlags |= 1 << j; + } + + int iObjectRenderingFlags = iSceneWideRenderingFlags; + + if(ptMaterial->tFlags & PL_MATERIAL_FLAG_CAST_RECEIVE_SHADOW) + { + iObjectRenderingFlags |= PL_RENDERING_FLAG_SHADOWS; + } + if(ptMaterial->tFlags & PL_MATERIAL_FLAG_CAST_SHADOW) + { + pl_sb_push(sbuShadowDrawables[uDrawableBatchIndex], i); + } + + // choose shader variant + int aiConstantData0[] = { + (int)ptMesh->ulVertexStreamMask, + iDataStride, + iTextureMappingFlags, + PL_INFO_MATERIAL_METALLICROUGHNESS, + iObjectRenderingFlags, + pl_sb_capacity(ptScene->sbtDLightData), + pl_sb_capacity(ptScene->sbtPLightData), + pl_sb_capacity(ptScene->sbtSLightData) + }; + + plGraphicsState tVariantTemp = atTemplateVariants[uDrawableBatchIndex]; + + if(ptMaterial->tFlags & PL_MATERIAL_FLAG_DOUBLE_SIDED) + tVariantTemp.ulCullMode = PL_CULL_MODE_NONE; + + const plShaderVariant tVariant = { + .pTempConstantData = aiConstantData0, + .tGraphicsState = tVariantTemp + }; + + (sbtNewDrawables[uDrawableBatchIndex])[i].tShader = pl__get_shader_variant(uSceneHandle, atTemplateShaders[uDrawableBatchIndex], &tVariant); + aiConstantData0[4] = gptData->bPunctualLighting ? PL_RENDERING_FLAG_USE_PUNCTUAL : 0; + (sbtNewDrawables[uDrawableBatchIndex])[i].tEnvShader = pl__get_shader_variant(uSceneHandle, atTemplateShaders[uDrawableBatchIndex], &tVariant); + + if(uDrawableBatchIndex > 0) + { + const plShaderVariant tShadowVariant = { + .pTempConstantData = aiConstantData0, + .tGraphicsState = { + .ulDepthWriteEnabled = 1, + .ulDepthMode = PL_COMPARE_MODE_GREATER_OR_EQUAL, + .ulCullMode = PL_CULL_MODE_NONE, + .ulWireframe = 0, + .ulStencilMode = PL_COMPARE_MODE_ALWAYS, + .ulStencilRef = 0xff, + .ulStencilMask = 0xff, + .ulStencilOpFail = PL_STENCIL_OP_KEEP, + .ulStencilOpDepthFail = PL_STENCIL_OP_KEEP, + .ulStencilOpPass = PL_STENCIL_OP_KEEP + } + }; + (sbtNewDrawables[uDrawableBatchIndex])[i].tShadowShader = pl__get_shader_variant(uSceneHandle, atTemplateShadowShaders[uDrawableBatchIndex], &tShadowVariant); + } + + pl_sb_push(sbtDrawables[uDrawableBatchIndex], (sbtNewDrawables[uDrawableBatchIndex])[i]); + } + atHashmaps[uDrawableBatchIndex] = ptHashmap; + } + ptScene->sbtDeferredDrawables = sbtDrawables[0]; + ptScene->sbtForwardDrawables = sbtDrawables[1]; + ptScene->sbuShadowDeferredDrawables = sbuShadowDrawables[0]; + ptScene->sbuShadowForwardDrawables = sbuShadowDrawables[1]; + ptScene->ptDeferredHashmap = atHashmaps[0]; + ptScene->ptForwardHashmap = atHashmaps[1]; +} \ No newline at end of file diff --git a/extensions/pl_renderer_internal.h b/extensions/pl_renderer_internal.h index 9ee5d22..9a8ec1c 100644 --- a/extensions/pl_renderer_internal.h +++ b/extensions/pl_renderer_internal.h @@ -28,7 +28,6 @@ Index of this file: #include // FLT_MAX #include "pl.h" #include "pl_renderer_ext.h" -#include "pl_ds.h" #include "pl_string.h" #include "pl_memory.h" #define PL_MATH_INCLUDE_FUNCTIONS @@ -98,6 +97,8 @@ Index of this file: static struct _plIO* gptIO = 0; #endif +#include "pl_ds.h" + //----------------------------------------------------------------------------- // [SECTION] internal structs //----------------------------------------------------------------------------- @@ -135,6 +136,7 @@ typedef struct _plDrawable uint32_t uIndexCount; uint32_t uMaterialIndex; plShaderHandle tShader; + plShaderHandle tEnvShader; plShaderHandle tShadowShader; uint32_t uSkinIndex; bool bCulled; @@ -143,10 +145,9 @@ typedef struct _plDrawable typedef struct _plGPUMaterial { // Metallic Roughness - int iMipCount; float fMetallicFactor; float fRoughnessFactor; - int _unused0[1]; + int _unused0[2]; plVec4 tBaseColorFactor; // Emissive Strength @@ -203,15 +204,11 @@ typedef struct _plGPULightShadowData typedef struct _BindGroup_0 { plVec4 tViewportSize; + plVec4 tViewportInfo; plVec4 tCameraPos; plMat4 tCameraView; plMat4 tCameraProjection; plMat4 tCameraViewProjection; - - uint32_t uLambertianEnvSampler; - uint32_t uGGXEnvSampler; - uint32_t uGGXLUT; - uint32_t _uUnUsed; } BindGroup_0; typedef struct _DynamicData @@ -221,8 +218,66 @@ typedef struct _DynamicData int iMaterialOffset; int iPadding[1]; plMat4 tModel; + + uint32_t uLambertianEnvSampler; + uint32_t uGGXEnvSampler; + uint32_t uGGXLUT; + uint32_t uGlobalIndex; } DynamicData; +typedef struct _plSkyboxDynamicData +{ + uint32_t uGlobalIndex; + uint32_t _auUnused[3]; + plMat4 tModel; +} plSkyboxDynamicData; + +typedef struct _plDirectionLightShadowData +{ + plBufferHandle atDShadowCameraBuffers[PL_MAX_FRAMES_IN_FLIGHT]; + plBufferHandle atDLightShadowDataBuffer[PL_MAX_FRAMES_IN_FLIGHT]; + plGPULightShadowData* sbtDLightShadowData; + uint32_t uOffset; + uint32_t uOffsetIndex; +} plDirectionLightShadowData; + +typedef struct _plEnvironmentProbeData +{ + plEntity tEntity; + plVec2 tTargetSize; + + plRenderPassHandle tRenderPass; + + // g-buffer textures + plTextureHandle tAlbedoTexture; + plTextureHandle tNormalTexture; + plTextureHandle tAOMetalRoughnessTexture; + plTextureHandle tRawOutputTexture; + plTextureHandle tRawOutputCubeTexture; + plTextureHandle tDepthTexture; + + // lighting + plBindGroupHandle tLightingBindGroup; + + // GPU buffers + plBufferHandle atGlobalBuffers[PL_MAX_FRAMES_IN_FLIGHT]; + + // submitted drawables + plDrawable* sbtVisibleOpaqueDrawables[6]; + plDrawable* sbtVisibleTransparentDrawables[6]; + + // shadows + plDirectionLightShadowData tDirectionLightShadowData; + + // textures + plTextureHandle tGGXLUTTexture; + uint32_t uGGXLUT; + plTextureHandle tLambertianEnvTexture; + uint32_t uLambertianEnvSampler; + plTextureHandle tGGXEnvTexture; + uint32_t uGGXEnvSampler; +} plEnvironmentProbeData; + typedef struct _plRefView { // renderpasses @@ -233,27 +288,27 @@ typedef struct _plRefView plVec2 tTargetSize; // g-buffer textures - plTextureHandle tAlbedoTexture[PL_MAX_FRAMES_IN_FLIGHT]; - plTextureHandle tNormalTexture[PL_MAX_FRAMES_IN_FLIGHT]; - plTextureHandle tAOMetalRoughnessTexture[PL_MAX_FRAMES_IN_FLIGHT]; - plTextureHandle tRawOutputTexture[PL_MAX_FRAMES_IN_FLIGHT]; - plTextureHandle tDepthTexture[PL_MAX_FRAMES_IN_FLIGHT]; + plTextureHandle tAlbedoTexture; + plTextureHandle tNormalTexture; + plTextureHandle tAOMetalRoughnessTexture; + plTextureHandle tRawOutputTexture; + plTextureHandle tDepthTexture; // picking plTextureHandle tPickTexture; plTextureHandle tPickDepthTexture; // outlining - plTextureHandle atUVMaskTexture0[PL_MAX_FRAMES_IN_FLIGHT]; - plTextureHandle atUVMaskTexture1[PL_MAX_FRAMES_IN_FLIGHT]; + plTextureHandle atUVMaskTexture0; + plTextureHandle atUVMaskTexture1; plTextureHandle tLastUVMask; // output texture - plTextureHandle tFinalTexture[PL_MAX_FRAMES_IN_FLIGHT]; - plBindGroupHandle tFinalTextureHandle[PL_MAX_FRAMES_IN_FLIGHT]; + plTextureHandle tFinalTexture; + plBindGroupHandle tFinalTextureHandle; // lighting - plBindGroupHandle tLightingBindGroup[PL_MAX_FRAMES_IN_FLIGHT]; + plBindGroupHandle tLightingBindGroup; // GPU buffers plBufferHandle atGlobalBuffers[PL_MAX_FRAMES_IN_FLIGHT]; @@ -268,28 +323,19 @@ typedef struct _plRefView plDrawList3D* pt3DSelectionDrawList; // shadows - plBufferHandle atDShadowCameraBuffers[PL_MAX_FRAMES_IN_FLIGHT]; - plBufferHandle atDLightShadowDataBuffer[PL_MAX_FRAMES_IN_FLIGHT]; - plGPULightShadowData* sbtDLightShadowData; + plDirectionLightShadowData tDirectionLightShadowData; } plRefView; typedef struct _plRefScene { plShaderHandle tLightingShader; + plShaderHandle tEnvLightingShader; plShaderHandle tTonemapShader; // skybox resources (optional) - int iEnvironmentMips; plDrawable tSkyboxDrawable; plTextureHandle tSkyboxTexture; plBindGroupHandle tSkyboxBindGroup; - plTextureHandle tGGXLUTTexture; - uint32_t uGGXLUT; - plTextureHandle tLambertianEnvTexture; - uint32_t uLambertianEnvSampler; - plTextureHandle tGGXEnvTexture; - uint32_t uGGXEnvSampler; - // shared bind groups plBindGroupHandle tSkinBindGroup0; @@ -324,17 +370,26 @@ typedef struct _plRefScene plRenderPassHandle tFirstShadowRenderPass; plRenderPassHandle tShadowRenderPass; uint32_t uShadowAtlasResolution; - plTextureHandle tShadowTexture[PL_MAX_FRAMES_IN_FLIGHT]; - uint32_t atShadowTextureBindlessIndices[PL_MAX_FRAMES_IN_FLIGHT]; + plTextureHandle tShadowTexture; + uint32_t atShadowTextureBindlessIndices; // ECS component library plComponentLibrary tComponentLibrary; // drawables (per scene, will be culled by views) - plDrawable* sbtDeferredDrawables; - plDrawable* sbtForwardDrawables; + + plDrawable* sbtNewDeferredDrawables; // unprocessed + plDrawable* sbtNewForwardDrawables; // unprocessed + + plDrawable* sbtDeferredDrawables; // regular rendering + plDrawable* sbtForwardDrawables; // regular rendering + + uint32_t* sbuShadowDeferredDrawables; // shadow rendering (index into regular drawables) + uint32_t* sbuShadowForwardDrawables; // shadow rendering (index into regular drawables) + plDrawable* sbtOutlineDrawables; plShaderHandle* sbtOutlineDrawablesOldShaders; + plShaderHandle* sbtOutlineDrawablesOldEnvShaders; // entity to drawable hashmaps plHashMap* ptDeferredHashmap; @@ -360,6 +415,9 @@ typedef struct _plRefScene plBufferHandle atSLightShadowDataBuffer[PL_MAX_FRAMES_IN_FLIGHT]; plGPULightShadowData* sbtSLightShadowData; + // environment probes + plEnvironmentProbeData* sbtProbeData; + plBufferHandle atFilterWorkingBuffers[7]; } plRefScene; typedef struct _plRefRendererData @@ -395,12 +453,13 @@ typedef struct _plRefRendererData plRenderPassLayoutHandle tPickRenderPassLayout; // shader templates (variants are made from these) - plShaderHandle tShadowShader; - plShaderHandle tAlphaShadowShader; - plShaderHandle tDeferredShader; - plShaderHandle tForwardShader; - plShaderHandle tSkyboxShader; - plShaderHandle tPickShader; + plShaderHandle tShadowShader; + plShaderHandle tAlphaShadowShader; + plShaderHandle tDeferredShader; + plShaderHandle tForwardShader; + plShaderHandle tSkyboxShader; + plShaderHandle tPickShader; + plComputeShaderHandle tEnvFilterShader; // outline shaders plShaderHandle tUVShader; @@ -421,6 +480,7 @@ typedef struct _plRefRendererData // default textures & samplers & bindgroups plSamplerHandle tDefaultSampler; + plSamplerHandle tSkyboxSampler; plSamplerHandle tShadowSampler; plSamplerHandle tEnvSampler; plTextureHandle tDummyTexture; @@ -466,6 +526,7 @@ typedef struct _plRefRendererData bool bShowSelectedBoundingBox; bool bMultiViewportShadows; bool bImageBasedLighting; + bool bPunctualLighting; float fShadowConstantDepthBias; float fShadowSlopeDepthBias; uint32_t uOutlineWidth; @@ -509,7 +570,8 @@ enum _plMaterialInfoFlags enum _plRenderingFlags { PL_RENDERING_FLAG_USE_PUNCTUAL = 1 << 0, - PL_RENDERING_FLAG_USE_IBL = 1 << 1 + PL_RENDERING_FLAG_USE_IBL = 1 << 1, + PL_RENDERING_FLAG_SHADOWS = 1 << 2 }; //----------------------------------------------------------------------------- @@ -543,7 +605,7 @@ static bool pl__sat_visibility_test(plCameraComponent*, const plAABB*); static void pl_refr_update_skin_textures(plCommandBuffer*, uint32_t); static void pl_refr_perform_skinning(plCommandBuffer*, uint32_t); static bool pl_refr_pack_shadow_atlas(uint32_t uSceneHandle, const uint32_t* auViewHandles, uint32_t uViewCount); -static void pl_refr_generate_cascaded_shadow_map(plRenderEncoder*, plCommandBuffer*, uint32_t, uint32_t, uint32_t, plEntity tCamera); +static void pl_refr_generate_cascaded_shadow_map(plRenderEncoder*, plCommandBuffer*, uint32_t, uint32_t, uint32_t, int, plDirectionLightShadowData*, plCameraComponent*); static void pl_refr_generate_shadow_maps(plRenderEncoder*, plCommandBuffer*, uint32_t); static void pl_refr_post_process_scene(plCommandBuffer*, uint32_t, uint32_t, const plMat4*); @@ -559,6 +621,12 @@ static size_t pl__get_data_type_size2(plDataType tType); static plBlendState pl__get_blend_state(plBlendMode tBlendMode); static uint32_t pl__get_bindless_texture_index(uint32_t uSceneHandle, plTextureHandle); static uint32_t pl__get_bindless_cube_texture_index(uint32_t uSceneHandle, plTextureHandle); +static void pl__refr_process_drawables(uint32_t uSceneHandle, bool bReload); + +// environment probes +static void pl__create_probe_data(uint32_t uSceneHandle, plEntity tProbeHandle); +static uint64_t pl__update_environment_probes(uint32_t uSceneHandle, uint64_t ulValue); +static uint64_t pl_create_environment_map_from_texture(uint32_t uSceneHandle, plEnvironmentProbeData* ptProbe, uint64_t ulValue); #endif // PL_RENDERER_INTERNAL_EXT_H \ No newline at end of file diff --git a/extensions/pl_resource_ext.c b/extensions/pl_resource_ext.c index 3c529a3..ba34fe7 100644 --- a/extensions/pl_resource_ext.c +++ b/extensions/pl_resource_ext.c @@ -5,7 +5,6 @@ #include #include "pl.h" #include "pl_resource_ext.h" -#include "pl_ds.h" #include "pl_log_ext.h" #ifdef PL_UNITY_BUILD @@ -23,6 +22,8 @@ #endif #endif +#include "pl_ds.h" + //----------------------------------------------------------------------------- // [SECTION] structs //----------------------------------------------------------------------------- diff --git a/extensions/pl_shader_ext.c b/extensions/pl_shader_ext.c index afa88cf..09542fb 100644 --- a/extensions/pl_shader_ext.c +++ b/extensions/pl_shader_ext.c @@ -15,7 +15,6 @@ Index of this file: //----------------------------------------------------------------------------- #include "pl.h" -#include "pl_ds.h" // libs #include "pl_string.h" @@ -34,9 +33,17 @@ Index of this file: #define PL_REALLOC(x, y) gptMemory->tracked_realloc((x), (y), __FILE__, __LINE__) #define PL_FREE(x) gptMemory->tracked_realloc((x), 0, __FILE__, __LINE__) + #ifndef PL_DS_ALLOC + #define PL_DS_ALLOC(x) gptMemory->tracked_realloc(NULL, (x), __FILE__, __LINE__) + #define PL_DS_ALLOC_INDIRECT(x, FILE, LINE) gptMemory->tracked_realloc(NULL, (x), FILE, LINE) + #define PL_DS_FREE(x) gptMemory->tracked_realloc((x), 0, __FILE__, __LINE__) + #endif + static const plFileI* gptFile = NULL; #endif +#include "pl_ds.h" + // external #ifndef PL_OFFLINE_SHADERS_ONLY #include "shaderc/shaderc.h" diff --git a/extensions/pl_stats_ext.c b/extensions/pl_stats_ext.c index 1031614..842c31d 100644 --- a/extensions/pl_stats_ext.c +++ b/extensions/pl_stats_ext.c @@ -39,7 +39,6 @@ Index of this file: #include #include "pl.h" #include "pl_stats_ext.h" -#include "pl_ds.h" #ifdef PL_UNITY_BUILD #include "pl_unity_ext.inc" @@ -56,6 +55,8 @@ Index of this file: #endif #endif +#include "pl_ds.h" + //----------------------------------------------------------------------------- // [SECTION] internal structs //----------------------------------------------------------------------------- diff --git a/extensions/pl_string_intern_ext.c b/extensions/pl_string_intern_ext.c index 57f37d9..7ea8f1d 100644 --- a/extensions/pl_string_intern_ext.c +++ b/extensions/pl_string_intern_ext.c @@ -19,7 +19,6 @@ Index of this file: #include #include "pl.h" #include "pl_string_intern_ext.h" -#include "pl_ds.h" #ifdef PL_UNITY_BUILD #include "pl_unity_ext.inc" @@ -36,6 +35,8 @@ Index of this file: #endif #endif +#include "pl_ds.h" + //----------------------------------------------------------------------------- // [SECTION] internal structs //----------------------------------------------------------------------------- diff --git a/extensions/pl_ui_internal.h b/extensions/pl_ui_internal.h index 7251e0e..be60add 100644 --- a/extensions/pl_ui_internal.h +++ b/extensions/pl_ui_internal.h @@ -50,7 +50,6 @@ Index of this file: #define PL_MATH_INCLUDE_FUNCTIONS #include "pl_math.h" -#include "pl_ds.h" #ifdef PL_UNITY_BUILD #include "pl_unity_ext.inc" @@ -72,6 +71,8 @@ Index of this file: static plIO* gptIO = NULL; #endif +#include "pl_ds.h" + //----------------------------------------------------------------------------- // [SECTION] helper macros //----------------------------------------------------------------------------- diff --git a/sandbox/app.c b/sandbox/app.c index ddf5fd4..4d1067d 100644 --- a/sandbox/app.c +++ b/sandbox/app.c @@ -197,16 +197,17 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plEditorData* ptEditorData) plLightComponent* ptLight = NULL; ptEditorData->tSunlight = gptEcs->create_directional_light(ptMainComponentLibrary, "direction light", (plVec3){-0.375f, -1.0f, -0.085f}, &ptLight); ptLight->uCascadeCount = 4; + ptLight->fIntensity = 1.0f; ptLight->uShadowResolution = 1024; - ptLight->afCascadeSplits[0] = 2.0f; - ptLight->afCascadeSplits[1] = 8.0f; - ptLight->afCascadeSplits[2] = 15.0f; - ptLight->afCascadeSplits[3] = 35.0f; + ptLight->afCascadeSplits[0] = 5.0f; + ptLight->afCascadeSplits[1] = 10.0f; + ptLight->afCascadeSplits[2] = 20.0f; + ptLight->afCascadeSplits[3] = 48.0f; ptLight->tFlags |= PL_LIGHT_FLAG_CAST_SHADOW | PL_LIGHT_FLAG_VISUALIZER; ptEditorData->tPointLight = gptEcs->create_point_light(ptMainComponentLibrary, "point light", (plVec3){0.0f, 2.0f, 2.0f}, &ptLight); ptLight->uShadowResolution = 1024; - ptLight->tFlags |= PL_LIGHT_FLAG_CAST_SHADOW | PL_LIGHT_FLAG_VISUALIZER; + ptLight->tFlags |= PL_LIGHT_FLAG_CAST_SHADOW; plTransformComponent* ptPLightTransform = gptEcs->add_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptEditorData->tPointLight); ptPLightTransform->tTranslation = (plVec3){0.0f, 1.497f, 2.0f}; @@ -219,8 +220,13 @@ pl_app_load(plApiRegistryI* ptApiRegistry, plEditorData* ptEditorData) plTransformComponent* ptSLightTransform = gptEcs->add_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptEditorData->tSpotLight); ptSLightTransform->tTranslation = (plVec3){0.0f, 4.0f, 0.0f}; - // load models + plEnvironmentProbeComponent* ptProbe = NULL; + gptEcs->create_environment_probe(ptMainComponentLibrary, "Main Probe", (plVec3){0.0f, 2.0f, 2.0f}, &ptProbe); + ptProbe->fRange = 30.0f; + ptProbe->uResolution = 128; + ptProbe->tFlags = PL_ENVIRONMENT_PROBE_FLAGS_REALTIME; + // load models // plTransformComponent* ptTargetTransform = NULL; // ptEditorData->tTrackPoint = gptEcs->create_transform(ptMainComponentLibrary, "track 0", &ptTargetTransform); @@ -327,14 +333,6 @@ pl_app_update(plEditorData* ptEditorData) plCameraComponent* ptCullCamera = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_CAMERA, ptEditorData->tCullCamera); gptCamera->update(ptCullCamera); - plTransformComponent* ptLightTransform = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptEditorData->tPointLight); - plLightComponent* ptPointLight = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_LIGHT, ptEditorData->tPointLight); - ptPointLight->tPosition = ptLightTransform->tTranslation; - - plTransformComponent* ptSLightTransform = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_TRANSFORM, ptEditorData->tSpotLight); - plLightComponent* ptSpotLight = gptEcs->get_component(ptMainComponentLibrary, PL_COMPONENT_TYPE_LIGHT, ptEditorData->tSpotLight); - ptSpotLight->tPosition = ptSLightTransform->tTranslation; - if(ptEditorData->bSceneLoaded) { // run ecs system @@ -450,7 +448,7 @@ pl_app_update(plEditorData* ptEditorData) if(!ptEditorData->bSceneLoaded) { - static uint32_t uComboSelect = 1; + static uint32_t uComboSelect = 2; static const char* apcEnvMaps[] = { "none", "helipad", @@ -485,7 +483,8 @@ pl_app_update(plEditorData* ptEditorData) false, false, false, - true, + false, + false, true, false, }; @@ -497,6 +496,7 @@ pl_app_update(plEditorData* ptEditorData) "NormalTangentMirrorTest", "Humanoid", "Floor", + "Environment", "Test", }; @@ -507,11 +507,12 @@ pl_app_update(plEditorData* ptEditorData) "../data/glTF-Sample-Assets-main/Models/NormalTangentMirrorTest/glTF/NormalTangentMirrorTest.gltf", "../data/pilotlight-assets-master/models/gltf/humanoid/model.gltf", "../data/pilotlight-assets-master/models/gltf/humanoid/floor.gltf", + "../data/glTF-Sample-Assets-main/Models/EnvironmentTest/glTF/EnvironmentTest.gltf", "../data/testing/testing.gltf", }; gptUi->separator_text("Test Models"); - for(uint32_t i = 0; i < 7; i++) + for(uint32_t i = 0; i < 8; i++) gptUi->selectable(apcModels[i], &abModels[i], 0); @@ -524,7 +525,7 @@ pl_app_update(plEditorData* ptEditorData) char* sbcData = NULL; pl_sb_sprintf(sbcData, "../data/pilotlight-assets-master/environments/%s.hdr", apcEnvMaps[uComboSelect]); gptRenderer->load_skybox_from_panorama(ptEditorData->uSceneHandle0, sbcData, 1024); - gptRenderer->create_environment_map_from_skybox(ptEditorData->uSceneHandle0); + // gptRenderer->create_environment_map_from_skybox(ptEditorData->uSceneHandle0); pl_sb_free(sbcData); } diff --git a/sandbox/pl_ecs_tools.c b/sandbox/pl_ecs_tools.c index cdccb5b..e01db42 100644 --- a/sandbox/pl_ecs_tools.c +++ b/sandbox/pl_ecs_tools.c @@ -97,6 +97,7 @@ pl_show_ecs_window(plEntity* ptSelectedEntity, plComponentLibrary* ptLibrary, bo plAnimationComponent* ptAnimationComp = gptEcs->get_component(ptLibrary, PL_COMPONENT_TYPE_ANIMATION, *ptSelectedEntity); plInverseKinematicsComponent* ptIKComp = gptEcs->get_component(ptLibrary, PL_COMPONENT_TYPE_INVERSE_KINEMATICS, *ptSelectedEntity); plLightComponent* ptLightComp = gptEcs->get_component(ptLibrary, PL_COMPONENT_TYPE_LIGHT, *ptSelectedEntity); + plEnvironmentProbeComponent* ptProbeComp = gptEcs->get_component(ptLibrary, PL_COMPONENT_TYPE_ENVIRONMENT_PROBE, *ptSelectedEntity); gptUi->text("Entity: %u, %u", ptSelectedEntity->uIndex, ptSelectedEntity->uGeneration); @@ -106,6 +107,26 @@ pl_show_ecs_window(plEntity* ptSelectedEntity, plComponentLibrary* ptLibrary, bo gptUi->end_collapsing_header(); } + if(ptProbeComp && gptUi->begin_collapsing_header("Environment Probe", 0)) + { + gptUi->input_float3("Position", ptProbeComp->tPosition.d, NULL, 0); + + bool bRealTime = ptProbeComp->tFlags & PL_ENVIRONMENT_PROBE_FLAGS_REALTIME; + if(gptUi->checkbox("Real Time", &bRealTime)) + { + if(bRealTime) + ptProbeComp->tFlags |= PL_ENVIRONMENT_PROBE_FLAGS_REALTIME; + else + ptProbeComp->tFlags &= ~PL_ENVIRONMENT_PROBE_FLAGS_REALTIME; + } + if(gptUi->button("Update")) + { + ptProbeComp->tFlags |= PL_ENVIRONMENT_PROBE_FLAGS_DIRTY; + } + gptUi->input_float("Range:", &ptProbeComp->fRange, NULL, 0); + gptUi->end_collapsing_header(); + } + if(ptTransformComp && gptUi->begin_collapsing_header("Transform", 0)) { gptUi->text("Scale: (%+0.3f, %+0.3f, %+0.3f)", ptTransformComp->tScale.x, ptTransformComp->tScale.y, ptTransformComp->tScale.z); diff --git a/shaders/defines.glsl b/shaders/defines.glsl index ea60671..c2425f8 100644 --- a/shaders/defines.glsl +++ b/shaders/defines.glsl @@ -33,6 +33,7 @@ const int PL_MATERIAL_METALLICROUGHNESS = 1 << 0; // iRenderingFlags const int PL_RENDERING_FLAG_USE_PUNCTUAL = 1 << 0; const int PL_RENDERING_FLAG_USE_IBL = 1 << 1; +const int PL_RENDERING_FLAG_SHADOWS = 1 << 2; // lights const int PL_LIGHT_TYPE_DIRECTIONAL = 0; diff --git a/shaders/filter_environment.comp b/shaders/filter_environment.comp index 5289828..49f4c7d 100644 --- a/shaders/filter_environment.comp +++ b/shaders/filter_environment.comp @@ -16,14 +16,25 @@ const int cLambertian = 0; const int cGGX = 1; const int cCharlie = 2; -layout(constant_id = 0) const int giResolution = 0; -layout(constant_id = 1) const float gfRoughness = 0; -layout(constant_id = 2) const int gISampleCount = 0; -layout(constant_id = 3) const int giWidth = 0; -layout(constant_id = 4) const float gfLodBias = 0; -layout(constant_id = 5) const int giDistribution = 0; // enum -layout(constant_id = 6) const int giIsGeneratingLut = 0; -layout(constant_id = 7) const int giCurrentMipLevel = 0; +//----------------------------------------------------------------------------- +// [SECTION] dynamic bind group +//----------------------------------------------------------------------------- + +layout(set = 3, binding = 0) uniform PL_DYNAMIC_DATA +{ + int iResolution; + float fRoughness; + int iSampleCount; + int iWidth; + float fLodBias; + int iDistribution; + int iIsGeneratingLut; + int iCurrentMipLevel; +} tDynamicData; + +//----------------------------------------------------------------------------- +// [SECTION] helpers +//----------------------------------------------------------------------------- #define PL_PI 3.1415926535897932384626433832795 const float PL_GAMMA = 2.2; @@ -40,14 +51,19 @@ pl_uv_to_xyz(int iFace, vec2 tUv) { if (iFace == 0) // right return vec3(1.0, -tUv.y, -tUv.x); + else if (iFace == 1) // left return vec3(-1.0, -tUv.y, tUv.x); + else if (iFace == 2) // top return vec3(tUv.x, 1.0, tUv.y); + else if (iFace == 3) // bottom return vec3(tUv.x, -1.0, -tUv.y); + else if (iFace == 4) // front return vec3(tUv.x, -tUv.y, 1.0); + else //if(iFace == 5) return vec3(-tUv.x, -tUv.y, -1.0); } @@ -225,23 +241,23 @@ pl_get_importance_sample(int iSampleIndex, vec3 tN, float fRoughness) // pl_get_importance_sample returns an importance sample direction with pdf in the .w component // generate a quasi monte carlo point in the unit square [0.1)^2 - vec2 tXi = pl_hammersley_2d(iSampleIndex, gISampleCount); + vec2 tXi = pl_hammersley_2d(iSampleIndex, tDynamicData.iSampleCount); MicrofacetDistributionSample tImportanceSample; // generate the points on the hemisphere with a fitting mapping for // the distribution (e.g. lambertian uses a cosine importance) - if(giDistribution == cLambertian) + if(tDynamicData.iDistribution == cLambertian) { tImportanceSample = pl_lambertian(tXi, fRoughness); } - else if(giDistribution == cGGX) + else if(tDynamicData.iDistribution == cGGX) { // Trowbridge-Reitz / GGX microfacet model (Walter et al) // https://www.cs.cornell.edu/~srm/publications/EGSR07-btdf.html tImportanceSample = pl_ggx(tXi, fRoughness); } - else if(giDistribution == cCharlie) + else if(tDynamicData.iDistribution == cCharlie) { tImportanceSample = pl_charlie(tXi, fRoughness); } @@ -284,7 +300,7 @@ pl_compute_lod(float fPdf) // We achieved good results by using the original formulation from Krivanek & Colbert adapted to cubemaps // https://cgg.mff.cuni.cz/~jaroslav/papers/2007-sketch-fis/Final_sap_0073.pdf - const float fLod = 0.5 * log2( 6.0 * float(giWidth) * float(giWidth) / (float(gISampleCount) * fPdf)); + const float fLod = 0.5 * log2( 6.0 * float(tDynamicData.iWidth) * float(tDynamicData.iWidth) / (float(tDynamicData.iSampleCount) * fPdf)); return fLod; } @@ -294,9 +310,9 @@ pl_filter_color(vec3 tN) vec3 tColor = vec3(0.0); float fWeight = 0.0; - for(int i = 0; i < gISampleCount; ++i) + for(int i = 0; i < tDynamicData.iSampleCount; ++i) { - const vec4 tImportanceSample = pl_get_importance_sample(i, tN, gfRoughness); + const vec4 tImportanceSample = pl_get_importance_sample(i, tN, tDynamicData.fRoughness); const vec3 tH = vec3(tImportanceSample.xyz); const float fPdf = tImportanceSample.w; @@ -305,12 +321,13 @@ pl_filter_color(vec3 tN) float fLod = pl_compute_lod(fPdf); // apply the bias to the lod - fLod += gfLodBias; + fLod += tDynamicData.fLodBias; - if(giDistribution == cLambertian) + if(tDynamicData.iDistribution == cLambertian) { // sample lambertian at a lower giResolution to avoid fireflies - const vec3 tLambertian = pl_linear_to_srgb(textureLod(samplerCube(uCubeMap, tDefaultSampler), tH, fLod).rgb); + // const vec3 tLambertian = pl_linear_to_srgb(textureLod(samplerCube(uCubeMap, tDefaultSampler), tH, fLod).rgb); + const vec3 tLambertian = textureLod(samplerCube(uCubeMap, tDefaultSampler), tH, fLod).rgb; //// the below operations cancel each other out // lambertian *= NdotH; // lamberts law @@ -319,7 +336,7 @@ pl_filter_color(vec3 tN) tColor += tLambertian; } - else if(giDistribution == cGGX || giDistribution == cCharlie) + else if(tDynamicData.iDistribution == cGGX || tDynamicData.iDistribution == cCharlie) { // Note: reflect takes incident vector. const vec3 tV = tN; @@ -328,12 +345,13 @@ pl_filter_color(vec3 tN) if (fNdotL > 0.0) { - if(gfRoughness == 0.0) + if(tDynamicData.fRoughness == 0.0) { // without this the roughness=0 lod is too high - fLod = gfLodBias; + fLod = tDynamicData.fLodBias; } vec3 sampleColor = textureLod(samplerCube(uCubeMap, tDefaultSampler), tL, fLod).rgb; + // sampleColor = pl_linear_to_srgb(sampleColor); tColor += sampleColor * fNdotL; fWeight += fNdotL; } @@ -346,7 +364,7 @@ pl_filter_color(vec3 tN) } else { - tColor /= float(gISampleCount); + tColor /= float(tDynamicData.iSampleCount); } return tColor.rgb; @@ -391,7 +409,7 @@ pl_lut(float fNdotV, float fRoughness) float fB = 0.0; float fC = 0.0; - for(int i = 0; i < gISampleCount; ++i) + for(int i = 0; i < tDynamicData.iSampleCount; ++i) { // Importance sampling, depending on the distribution. vec4 tImportanceSample = pl_get_importance_sample(i, tN, fRoughness); @@ -404,7 +422,7 @@ pl_lut(float fNdotV, float fRoughness) float fVdotH = pl_saturate(dot(tV, tH)); if (fNdotL > 0.0) { - if (giDistribution == cGGX) + if (tDynamicData.iDistribution == cGGX) { // LUT for GGX distribution. @@ -418,7 +436,7 @@ pl_lut(float fNdotV, float fRoughness) fC += 0.0; } - if (giDistribution == cCharlie) + if (tDynamicData.iDistribution == cCharlie) { // LUT for Charlie distribution. float fSheenDistribution = pl_d_charlie(fRoughness, fNdotH); @@ -434,7 +452,7 @@ pl_lut(float fNdotV, float fRoughness) // The PDF is simply pdf(v, h) -> NDF * . // To parametrize the PDF over l, use the Jacobian transform, yielding to: pdf(v, l) -> NDF * / 4 // Since the BRDF divide through the PDF to be normalized, the 4 can be pulled out of the integral. - return vec3(4.0 * fA, 4.0 * fB, 4.0 * 2.0 * PL_PI * fC) / float(gISampleCount); + return vec3(4.0 * fA, 4.0 * fB, 4.0 * 2.0 * PL_PI * fC) / float(tDynamicData.iSampleCount); } layout (local_size_x = 16, local_size_y = 16, local_size_z = 3) in; @@ -446,32 +464,34 @@ main() const float fYCoord = gl_WorkGroupID.y * 16 + gl_LocalInvocationID.y; vec3 tColor = vec3(0.0, 1.0, 0.0); - if(giIsGeneratingLut == 0) + if(tDynamicData.iIsGeneratingLut == 0) { const int iFace = int(gl_WorkGroupID.z * 3 + gl_LocalInvocationID.z); - const float fXinc = 1.0 / giResolution; - const float fYinc = 1.0 / giResolution; + const float fXinc = 1.0 / tDynamicData.iResolution; + const float fYinc = 1.0 / tDynamicData.iResolution; const vec2 tInUV = vec2(fXCoord * fXinc, fYCoord * fYinc); - const int iCurrentPixel = int(fXCoord + fYCoord * giWidth); + const int iCurrentPixel = int(fXCoord + fYCoord * tDynamicData.iWidth); - vec2 tNewUV = tInUV * (1 << giCurrentMipLevel); + vec2 tNewUV = tInUV * (1 << tDynamicData.iCurrentMipLevel); tNewUV = tNewUV * 2.0 - 1.0; + // tNewUV = clamp(tNewUV, -0.999999, 0.999999); const vec3 tScan = pl_uv_to_xyz(iFace, tNewUV); vec3 tDirection = normalize(tScan); tDirection.z = -tDirection.z; - + // tDirection.x = -tDirection.x; + tColor = pl_filter_color(tDirection); pl_write_face(iCurrentPixel, iFace, tColor); } else { - const float fLutxinc = 1.0 / float(giResolution); - const float fLutyinc = 1.0 / float(giResolution); - const vec2 tLutUV = vec2(fXCoord * fLutxinc, fYCoord * fLutyinc); - const int iCurrentLUTPixel = int(fXCoord + fYCoord * float(giResolution)); + const float fLutxinc = 1.0 / float(tDynamicData.iResolution); + const float fLutyinc = 1.0 / float(tDynamicData.iResolution); + vec2 tLutUV = vec2(fXCoord * fLutxinc, fYCoord * fLutyinc); + const int iCurrentLUTPixel = int(fXCoord + fYCoord * float(tDynamicData.iResolution)); tColor = pl_lut(tLutUV.x, tLutUV.y); tLUTOut.atPixelData[iCurrentLUTPixel] = vec4(tColor, 1.0); diff --git a/shaders/lighting.frag b/shaders/lighting.frag index 6adde47..627a3ad 100644 --- a/shaders/lighting.frag +++ b/shaders/lighting.frag @@ -47,17 +47,19 @@ layout(input_attachment_index = 0, set = 1, binding = 3) uniform subpassInput t // [SECTION] bind group 2 //----------------------------------------------------------------------------- -layout(set = 2, binding = 0) uniform _plGlobalInfo +struct tGlobalData { vec4 tViewportSize; + vec4 tViewportInfo; vec4 tCameraPos; mat4 tCameraView; mat4 tCameraProjection; mat4 tCameraViewProjection; - uint uLambertianEnvSampler; - uint uGGXEnvSampler; - uint uGGXLUT; - uint _uUnUsed; +}; + +layout(set = 2, binding = 0) readonly buffer _plGlobalInfo +{ + tGlobalData data[]; } tGlobalInfo; layout(set = 2, binding = 1) uniform _plDLightInfo @@ -98,8 +100,10 @@ layout(set = 2, binding = 7) uniform sampler tShadowSampler; layout(set = 3, binding = 0) uniform PL_DYNAMIC_DATA { - int iDataOffset; - int iVertexOffset; + uint uLambertianEnvSampler; + uint uGGXEnvSampler; + uint uGGXLUT; + uint uGlobalIndex; } tObjectInfo; //----------------------------------------------------------------------------- @@ -183,17 +187,18 @@ vec3 BRDF_specularGGX(vec3 f0, vec3 f90, float alphaRoughness, float specularWei vec3 getDiffuseLight(vec3 n) { - // n.z = -n.z; uncomment if not reverse z + // n.z = -n.z; // uncomment if not reverse z // return texture(samplerCube(u_LambertianEnvSampler, tEnvSampler), n).rgb; - return texture(samplerCube(atCubeTextures[nonuniformEXT(tGlobalInfo.uLambertianEnvSampler)], tEnvSampler), n).rgb; + return texture(samplerCube(atCubeTextures[nonuniformEXT(tObjectInfo.uLambertianEnvSampler)], tEnvSampler), n).rgb; } vec4 getSpecularSample(vec3 reflection, float lod) { // reflection.z = -reflection.z; // uncomment if not reverse z + // reflection.x = -reflection.x; // uncomment if not reverse z // return textureLod(samplerCube(u_GGXEnvSampler, tEnvSampler), reflection, lod); - return textureLod(samplerCube(atCubeTextures[nonuniformEXT(tGlobalInfo.uGGXEnvSampler)], tEnvSampler), reflection, lod); + return textureLod(samplerCube(atCubeTextures[nonuniformEXT(tObjectInfo.uGGXEnvSampler)], tEnvSampler), reflection, lod); } vec3 getIBLRadianceGGX(vec3 n, vec3 v, float roughness, vec3 F0, float specularWeight, int u_MipCount) @@ -206,7 +211,7 @@ vec3 getIBLRadianceGGX(vec3 n, vec3 v, float roughness, vec3 F0, float specularW float NdotV = clampedDot(n, v); vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0)); // vec2 f_ab = texture(sampler2D(u_GGXLUT, tEnvSampler), brdfSamplePoint).rg; - vec2 f_ab = texture(sampler2D(at2DTextures[nonuniformEXT(tGlobalInfo.uGGXLUT)], tEnvSampler), brdfSamplePoint).rg; + vec2 f_ab = texture(sampler2D(at2DTextures[nonuniformEXT(tObjectInfo.uGGXLUT)], tEnvSampler), brdfSamplePoint).rg; vec3 specularLight = specularSample.rgb; @@ -225,7 +230,7 @@ vec3 getIBLRadianceLambertian(vec3 n, vec3 v, float roughness, vec3 diffuseColor float NdotV = clampedDot(n, v); vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0)); // vec2 f_ab = texture(sampler2D(u_GGXLUT, tEnvSampler), brdfSamplePoint).rg; - vec2 f_ab = texture(sampler2D(at2DTextures[nonuniformEXT(tGlobalInfo.uGGXLUT)], tEnvSampler), brdfSamplePoint).rg; + vec2 f_ab = texture(sampler2D(at2DTextures[nonuniformEXT(tObjectInfo.uGGXLUT)], tEnvSampler), brdfSamplePoint).rg; // see https://bruop.github.io/ibl/#single_scattering_results at Single Scattering Results // Roughness dependent fresnel, from Fdez-Aguera @@ -394,11 +399,16 @@ void main() vec4 tBaseColor = subpassLoad(tAlbedoSampler); float depth = subpassLoad(tDepthSampler).r; - vec3 ndcSpace = vec3(gl_FragCoord.x / tGlobalInfo.tViewportSize.x, gl_FragCoord.y / tGlobalInfo.tViewportSize.y, depth); + vec3 ndcSpace = vec3((gl_FragCoord.x - tGlobalInfo.data[tObjectInfo.uGlobalIndex].tViewportInfo.x) / tGlobalInfo.data[tObjectInfo.uGlobalIndex].tViewportSize.x, (gl_FragCoord.y - tGlobalInfo.data[tObjectInfo.uGlobalIndex].tViewportInfo.y) / tGlobalInfo.data[tObjectInfo.uGlobalIndex].tViewportSize.y, depth); + + vec3 clipSpace = ndcSpace; clipSpace.xy = clipSpace.xy * 2.0 - 1.0; - vec4 homoLocation = inverse(tGlobalInfo.tCameraProjection) * vec4(clipSpace, 1.0); - + // clipSpace.x *= tGlobalInfo.tViewportSize.z; + // clipSpace.y *= tGlobalInfo.tViewportSize.w; + // clipSpace.x += tGlobalInfo.tViewportInfo.x; + // clipSpace.y += tGlobalInfo.tViewportInfo.y; + vec4 homoLocation = inverse(tGlobalInfo.data[tObjectInfo.uGlobalIndex].tCameraProjection) * vec4(clipSpace, 1.0); // vec4 tWorldPosition0 = subpassLoad(tPositionSampler); vec4 tViewPosition = homoLocation; @@ -407,12 +417,11 @@ void main() tViewPosition.y = tViewPosition.y; tViewPosition.z = tViewPosition.z; tViewPosition.w = 1.0; - vec4 tWorldPosition = inverse(tGlobalInfo.tCameraView) * tViewPosition; + vec4 tWorldPosition = inverse(tGlobalInfo.data[tObjectInfo.uGlobalIndex].tCameraView) * tViewPosition; vec3 n = Decode(subpassLoad(tNormalTexture).xy); const vec3 f90 = vec3(1.0); - // LIGHTING vec3 f_specular = vec3(0.0); vec3 f_diffuse = vec3(0.0); @@ -423,8 +432,9 @@ void main() const float fPerceptualRoughness = AORoughnessMetalnessData.b; float specularWeight = 1.0; - vec3 v = normalize(tGlobalInfo.tCameraPos.xyz - tWorldPosition.xyz); - int iMips = int(AORoughnessMetalnessData.a); + vec3 v = normalize(tGlobalInfo.data[tObjectInfo.uGlobalIndex].tCameraPos.xyz - tWorldPosition.xyz); + // int iMips = int(AORoughnessMetalnessData.a); + int iMips = textureQueryLevels(samplerCube(atCubeTextures[nonuniformEXT(tObjectInfo.uGGXEnvSampler)], tEnvSampler)); // Calculate lighting contribution from image based lighting source (IBL) if(bool(iRenderingFlags & PL_RENDERING_FLAG_USE_IBL)) diff --git a/shaders/lighting.vert b/shaders/lighting.vert index c1dd196..48db0bc 100644 --- a/shaders/lighting.vert +++ b/shaders/lighting.vert @@ -2,83 +2,7 @@ #extension GL_ARB_separate_shader_objects : enable #extension GL_EXT_nonuniform_qualifier : enable -struct tMaterial -{ - // Metallic Roughness - int u_MipCount; - float u_MetallicFactor; - float u_RoughnessFactor; - //-------------------------- ( 16 bytes ) - - vec4 u_BaseColorFactor; - //-------------------------- ( 16 bytes ) - - // // Specular Glossiness - // vec3 u_SpecularFactor; - // vec4 u_DiffuseFactor; - // float u_GlossinessFactor; - - // // Sheen - // float u_SheenRoughnessFactor; - // vec3 u_SheenColorFactor; - - // Clearcoat - float u_ClearcoatFactor; - float u_ClearcoatRoughnessFactor; - vec2 _unused1; - //-------------------------- ( 16 bytes ) - - // Specular - vec3 u_KHR_materials_specular_specularColorFactor; - float u_KHR_materials_specular_specularFactor; - //-------------------------- ( 16 bytes ) - - // // Transmission - // float u_TransmissionFactor; - - // // Volume - // float u_ThicknessFactor; - // vec3 u_AttenuationColor; - // float u_AttenuationDistance; - - // Iridescence - float u_IridescenceFactor; - float u_IridescenceIor; - float u_IridescenceThicknessMinimum; - float u_IridescenceThicknessMaximum; - //-------------------------- ( 16 bytes ) - - // Emissive Strength - vec3 u_EmissiveFactor; - float u_EmissiveStrength; - //-------------------------- ( 16 bytes ) - - - // // IOR - float u_Ior; - - // // Anisotropy - // vec3 u_Anisotropy; - - // Alpha mode - float u_AlphaCutoff; - float u_OcclusionStrength; - float u_Unuses; - //-------------------------- ( 16 bytes ) - - int BaseColorUVSet; - int NormalUVSet; - int EmissiveUVSet; - int OcclusionUVSet; - int MetallicRoughnessUVSet; - int ClearcoatUVSet; - int ClearcoatRoughnessUVSet; - int ClearcoatNormalUVSet; - int SpecularUVSet; - int SpecularColorUVSet; - int IridescenceUVSet; - int IridescenceThicknessUVSet; -}; +#include "material.glsl" layout(std140, set = 0, binding = 0) readonly buffer _tVertexBuffer { @@ -102,8 +26,10 @@ layout(set = 0, binding = 4100) uniform textureCube atCubeTextures[4096]; layout(set = 3, binding = 0) uniform PL_DYNAMIC_DATA { - int iDataOffset; - int iVertexOffset; + uint uLambertianEnvSampler; + uint uGGXEnvSampler; + uint uGGXLUT; + uint _uUnUsed; } tObjectInfo; // input diff --git a/shaders/material.glsl b/shaders/material.glsl index dc53436..456abe8 100644 --- a/shaders/material.glsl +++ b/shaders/material.glsl @@ -2,7 +2,6 @@ struct tMaterial { // Metallic Roughness - int u_MipCount; float u_MetallicFactor; float u_RoughnessFactor; //-------------------------- ( 16 bytes ) diff --git a/shaders/outline.frag b/shaders/outline.frag index 39b2485..503239a 100644 --- a/shaders/outline.frag +++ b/shaders/outline.frag @@ -15,14 +15,11 @@ layout(constant_id = 1) const int iDataStride = 0; layout(set = 0, binding = 0) uniform _plGlobalInfo { vec4 tViewportSize; + vec4 tViewportInfo; vec4 tCameraPos; mat4 tCameraView; mat4 tCameraProjection; mat4 tCameraViewProjection; - uint uLambertianEnvSampler; - uint uGGXEnvSampler; - uint uGGXLUT; - uint _uUnUsed; } tGlobalInfo; layout(std140, set = 0, binding = 1) readonly buffer _tVertexBuffer diff --git a/shaders/outline.vert b/shaders/outline.vert index 9f02c40..130ee60 100644 --- a/shaders/outline.vert +++ b/shaders/outline.vert @@ -23,14 +23,11 @@ const int PL_MESH_FORMAT_FLAG_HAS_NORMAL = 1 << 1; layout(set = 0, binding = 0) uniform _plGlobalInfo { vec4 tViewportSize; + vec4 tViewportInfo; vec4 tCameraPos; mat4 tCameraView; mat4 tCameraProjection; mat4 tCameraViewProjection; - uint uLambertianEnvSampler; - uint uGGXEnvSampler; - uint uGGXLUT; - uint _uUnUsed; } tGlobalInfo; layout(std140, set = 0, binding = 1) readonly buffer _tVertexBuffer diff --git a/shaders/picking.vert b/shaders/picking.vert index 5137e4e..efcbb0a 100644 --- a/shaders/picking.vert +++ b/shaders/picking.vert @@ -8,14 +8,11 @@ layout(set = 0, binding = 0) uniform _plGlobalInfo { vec4 tViewportSize; + vec4 tViewportInfo; vec4 tCameraPos; mat4 tCameraView; mat4 tCameraProjection; mat4 tCameraViewProjection; - uint uLambertianEnvSampler; - uint uGGXEnvSampler; - uint uGGXLUT; - uint _uUnUsed; } tGlobalInfo; //----------------------------------------------------------------------------- diff --git a/shaders/primitive.frag b/shaders/primitive.frag index ca64a40..09a9e1b 100644 --- a/shaders/primitive.frag +++ b/shaders/primitive.frag @@ -38,18 +38,19 @@ layout(set = 0, binding = 4100) uniform textureCube atCubeTextures[4096]; // [SECTION] bind group 1 //----------------------------------------------------------------------------- -layout(set = 1, binding = 0) uniform _plGlobalInfo +struct tGlobalData { vec4 tViewportSize; + vec4 tViewportInfo; vec4 tCameraPos; mat4 tCameraView; mat4 tCameraProjection; mat4 tCameraViewProjection; +}; - uint uLambertianEnvSampler; - uint uGGXEnvSampler; - uint uGGXLUT; - uint _uUnUsed; +layout(set = 1, binding = 0) readonly buffer _plGlobalInfo +{ + tGlobalData data[]; } tGlobalInfo; //----------------------------------------------------------------------------- @@ -62,6 +63,11 @@ layout(set = 3, binding = 0) uniform PL_DYNAMIC_DATA int iVertexOffset; int iMaterialIndex; mat4 tModel; + + uint uLambertianEnvSampler; + uint uGGXEnvSampler; + uint uGGXLUT; + uint uGlobalIndex; } tObjectInfo; //----------------------------------------------------------------------------- @@ -274,6 +280,6 @@ void main() // fill g-buffer outAlbedo = tBaseColor; outNormal = Encode(tNormalInfo.n); - outAOMetalnessRoughness = vec4(ao, materialInfo.metallic, materialInfo.perceptualRoughness, material.u_MipCount); + outAOMetalnessRoughness = vec4(ao, materialInfo.metallic, materialInfo.perceptualRoughness, 1.0); } diff --git a/shaders/primitive.vert b/shaders/primitive.vert index f56137d..bf9e6e8 100644 --- a/shaders/primitive.vert +++ b/shaders/primitive.vert @@ -35,20 +35,22 @@ layout(set = 0, binding = 4) uniform texture2D at2DTextures[4096]; layout(set = 0, binding = 4100) uniform textureCube atCubeTextures[4096]; //----------------------------------------------------------------------------- -// [SECTION] bind group 2 +// [SECTION] bind group 1 //----------------------------------------------------------------------------- -layout(set = 1, binding = 0) uniform _plGlobalInfo +struct tGlobalData { vec4 tViewportSize; + vec4 tViewportInfo; vec4 tCameraPos; mat4 tCameraView; mat4 tCameraProjection; mat4 tCameraViewProjection; - uint uLambertianEnvSampler; - uint uGGXEnvSampler; - uint uGGXLUT; - uint _uUnUsed; +}; + +layout(set = 1, binding = 0) readonly buffer _plGlobalInfo +{ + tGlobalData data[]; } tGlobalInfo; //----------------------------------------------------------------------------- @@ -61,6 +63,11 @@ layout(set = 3, binding = 0) uniform PL_DYNAMIC_DATA int iVertexOffset; int iMaterialIndex; mat4 tModel; + + uint uLambertianEnvSampler; + uint uGGXEnvSampler; + uint uGGXLUT; + uint uGlobalIndex; } tObjectInfo; //----------------------------------------------------------------------------- @@ -147,7 +154,7 @@ void main() vec4 pos = tObjectInfo.tModel * inPosition; tShaderIn.tWorldPosition = pos.xyz / pos.w; - gl_Position = tGlobalInfo.tCameraViewProjection * pos; + gl_Position = tGlobalInfo.data[tObjectInfo.uGlobalIndex].tCameraViewProjection * pos; tShaderIn.tUV[0] = inTexCoord0; tShaderIn.tUV[1] = inTexCoord1; tShaderIn.tUV[2] = inTexCoord2; diff --git a/shaders/skybox.frag b/shaders/skybox.frag index 0c46c36..f31ef28 100644 --- a/shaders/skybox.frag +++ b/shaders/skybox.frag @@ -5,17 +5,19 @@ // [SECTION] bind group 0 //----------------------------------------------------------------------------- -layout(set = 0, binding = 0) uniform _plGlobalInfo +struct tGlobalData { vec4 tViewportSize; + vec4 tViewportInfo; vec4 tCameraPos; mat4 tCameraView; mat4 tCameraProjection; mat4 tCameraViewProjection; - uint uLambertianEnvSampler; - uint uGGXEnvSampler; - uint uGGXLUT; - uint _uUnUsed; +}; + +layout(set = 0, binding = 0) readonly buffer _plGlobalInfo +{ + tGlobalData data[]; } tGlobalInfo; layout(set = 0, binding = 1) uniform sampler tDefaultSampler; @@ -30,7 +32,10 @@ layout(set = 1, binding = 0) uniform textureCube samplerCubeMap; // [SECTION] dynamic bind group //----------------------------------------------------------------------------- -layout(set = 3, binding = 0) uniform PL_DYNAMIC_DATA { mat4 tModel;} tObjectInfo; +layout(set = 3, binding = 0) uniform PL_DYNAMIC_DATA { + uint uGlobalIndex; + mat4 tModel; +} tObjectInfo; //----------------------------------------------------------------------------- // [SECTION] input @@ -46,15 +51,6 @@ layout(location = 0) in struct plShaderOut { layout(location = 0) out vec4 outColor; -//----------------------------------------------------------------------------- -// [SECTION] helpers -//----------------------------------------------------------------------------- - -const float GAMMA = 2.2; -const float INV_GAMMA = 1.0 / GAMMA; - - - //----------------------------------------------------------------------------- // [SECTION] entry //----------------------------------------------------------------------------- diff --git a/shaders/skybox.vert b/shaders/skybox.vert index 25f8aa0..3dbbf96 100644 --- a/shaders/skybox.vert +++ b/shaders/skybox.vert @@ -5,17 +5,19 @@ // [SECTION] bind group 0 //----------------------------------------------------------------------------- -layout(set = 0, binding = 0) uniform _plGlobalInfo +struct tGlobalData { vec4 tViewportSize; + vec4 tViewportInfo; vec4 tCameraPos; mat4 tCameraView; mat4 tCameraProjection; mat4 tCameraViewProjection; - uint uLambertianEnvSampler; - uint uGGXEnvSampler; - uint uGGXLUT; - uint _uUnUsed; +}; + +layout(set = 0, binding = 0) readonly buffer _plGlobalInfo +{ + tGlobalData data[]; } tGlobalInfo; layout(set = 0, binding = 1) uniform sampler tDefaultSampler; @@ -30,7 +32,10 @@ layout(set = 1, binding = 0) uniform textureCube samplerCubeMap; // [SECTION] dynamic bind group //----------------------------------------------------------------------------- -layout(set = 3, binding = 0) uniform PL_DYNAMIC_DATA { mat4 tModel;} tObjectInfo; +layout(set = 3, binding = 0) uniform PL_DYNAMIC_DATA { + uint uGlobalIndex; + mat4 tModel; +} tObjectInfo; //----------------------------------------------------------------------------- // [SECTION] input @@ -53,7 +58,7 @@ layout(location = 0) out struct plShaderOut { void main() { - gl_Position = tGlobalInfo.tCameraProjection * tGlobalInfo.tCameraView * tObjectInfo.tModel * vec4(inPos, 1.0); + gl_Position = tGlobalInfo.data[tObjectInfo.uGlobalIndex].tCameraProjection * tGlobalInfo.data[tObjectInfo.uGlobalIndex].tCameraView * tObjectInfo.tModel * vec4(inPos, 1.0); gl_Position.z = 0.0; // gl_Position.w = gl_Position.z; uncomment if not reverse z tShaderOut.tWorldPosition = inPos; diff --git a/shaders/transparent.frag b/shaders/transparent.frag index e4d3760..4cfacd9 100644 --- a/shaders/transparent.frag +++ b/shaders/transparent.frag @@ -43,17 +43,19 @@ layout(set = 0, binding = 4100) uniform textureCube atCubeTextures[4096]; // [SECTION] bind group 1 //----------------------------------------------------------------------------- -layout(set = 1, binding = 0) uniform _plGlobalInfo +struct tGlobalData { vec4 tViewportSize; + vec4 tViewportInfo; vec4 tCameraPos; mat4 tCameraView; mat4 tCameraProjection; mat4 tCameraViewProjection; - uint uLambertianEnvSampler; - uint uGGXEnvSampler; - uint uGGXLUT; - uint _uUnUsed; +}; + +layout(set = 1, binding = 0) readonly buffer _plGlobalInfo +{ + tGlobalData data[]; } tGlobalInfo; layout(set = 1, binding = 1) uniform _plDLightInfo @@ -99,6 +101,11 @@ layout(set = 3, binding = 0) uniform PL_DYNAMIC_DATA int iMaterialIndex; int iPadding; mat4 tModel; + + uint uLambertianEnvSampler; + uint uGGXEnvSampler; + uint uGGXLUT; + uint uGlobalIndex; } tObjectInfo; //----------------------------------------------------------------------------- @@ -333,7 +340,7 @@ vec3 BRDF_specularGGX(vec3 f0, vec3 f90, float alphaRoughness, float specularWei vec3 getDiffuseLight(vec3 n) { // n.z = -n.z; uncomment if not reverse z - return texture(samplerCube(atCubeTextures[nonuniformEXT(tGlobalInfo.uLambertianEnvSampler)], tEnvSampler), n).rgb; + return texture(samplerCube(atCubeTextures[nonuniformEXT(tObjectInfo.uLambertianEnvSampler)], tEnvSampler), n).rgb; } @@ -341,7 +348,7 @@ vec4 getSpecularSample(vec3 reflection, float lod) { // reflection.z = -reflection.z; uncomment if not reverse z // return textureLod(u_GGXEnvSampler, u_EnvRotation * reflection, lod) * u_EnvIntensity; - return textureLod(samplerCube(atCubeTextures[nonuniformEXT(tGlobalInfo.uGGXEnvSampler)], tEnvSampler), reflection, lod); + return textureLod(samplerCube(atCubeTextures[nonuniformEXT(tObjectInfo.uGGXEnvSampler)], tEnvSampler), reflection, lod); } vec3 getIBLRadianceGGX(vec3 n, vec3 v, float roughness, vec3 F0, float specularWeight, int u_MipCount) @@ -351,7 +358,7 @@ vec3 getIBLRadianceGGX(vec3 n, vec3 v, float roughness, vec3 F0, float specularW vec3 reflection = normalize(reflect(-v, n)); vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0)); - vec2 f_ab = texture(sampler2D(at2DTextures[nonuniformEXT(tGlobalInfo.uGGXLUT)], tEnvSampler), brdfSamplePoint).rg; + vec2 f_ab = texture(sampler2D(at2DTextures[nonuniformEXT(tObjectInfo.uGGXLUT)], tEnvSampler), brdfSamplePoint).rg; vec4 specularSample = getSpecularSample(reflection, lod); vec3 specularLight = specularSample.rgb; @@ -371,7 +378,7 @@ vec3 getIBLRadianceLambertian(vec3 n, vec3 v, float roughness, vec3 diffuseColor { float NdotV = clampedDot(n, v); vec2 brdfSamplePoint = clamp(vec2(NdotV, roughness), vec2(0.0, 0.0), vec2(1.0, 1.0)); - vec2 f_ab = texture(sampler2D(at2DTextures[nonuniformEXT(tGlobalInfo.uGGXLUT)], tEnvSampler), brdfSamplePoint).rg; + vec2 f_ab = texture(sampler2D(at2DTextures[nonuniformEXT(tObjectInfo.uGGXLUT)], tEnvSampler), brdfSamplePoint).rg; vec3 irradiance = getDiffuseLight(n); @@ -563,7 +570,7 @@ void main() // outPosition = vec4(tShaderIn.tPosition, materialInfo.specularWeight); // outAOMetalnessRoughness = vec4(ao, materialInfo.metallic, materialInfo.perceptualRoughness, 1.0); - vec3 v = normalize(tGlobalInfo.tCameraPos.xyz - tShaderIn.tPosition.xyz); + vec3 v = normalize(tGlobalInfo.data[tObjectInfo.uGlobalIndex].tCameraPos.xyz - tShaderIn.tPosition.xyz); // LIGHTING vec3 f_specular = vec3(0.0); @@ -572,7 +579,8 @@ void main() // Calculate lighting contribution from image based lighting source (IBL) if(bool(iRenderingFlags & PL_RENDERING_FLAG_USE_IBL)) { - f_specular += getIBLRadianceGGX(n, v, materialInfo.perceptualRoughness, materialInfo.f0, specularWeight, material.u_MipCount); + int iMips = textureQueryLevels(samplerCube(atCubeTextures[nonuniformEXT(tObjectInfo.uGGXEnvSampler)], tEnvSampler)); + f_specular += getIBLRadianceGGX(n, v, materialInfo.perceptualRoughness, materialInfo.f0, specularWeight, iMips); f_diffuse += getIBLRadianceLambertian(n, v, materialInfo.perceptualRoughness, materialInfo.c_diff, materialInfo.f0, specularWeight); } @@ -583,6 +591,7 @@ void main() f_specular = vec3(0.0); uint cascadeIndex = 0; + const bool bShadows = bool(iRenderingFlags & PL_RENDERING_FLAG_SHADOWS); if(bool(iRenderingFlags & PL_RENDERING_FLAG_USE_PUNCTUAL)) { for(int i = 0; i < iDirectionLightCount; i++) @@ -592,13 +601,13 @@ void main() vec3 pointToLight = -tLightData.tDirection; float shadow = 1.0; - if(tLightData.iCastShadow > 0) + if(bShadows && tLightData.iCastShadow > 0) { plLightShadowData tShadowData = tDShadowData.atData[tLightData.iShadowIndex]; // Get cascade index for the current fragment's view position - vec4 inViewPos = tGlobalInfo.tCameraView * vec4(tShaderIn.tPosition.xyz, 1.0); + vec4 inViewPos = tGlobalInfo.data[tObjectInfo.uGlobalIndex].tCameraView * vec4(tShaderIn.tPosition.xyz, 1.0); for(uint j = 0; j < tLightData.iCascadeCount - 1; ++j) { if(inViewPos.z > tShadowData.cascadeSplits[j]) @@ -646,7 +655,7 @@ void main() float shadow = 1.0; - if(tLightData.iCastShadow > 0) + if(bShadows && tLightData.iCastShadow > 0) { plLightShadowData tShadowData = tSShadowData.atData[tLightData.iShadowIndex]; @@ -693,7 +702,7 @@ void main() vec3 pointToLight = tLightData.tPosition - tShaderIn.tPosition.xyz; float shadow = 1.0; - if(tLightData.iCastShadow > 0) + if(bShadows && tLightData.iCastShadow > 0) { plLightShadowData tShadowData = tPShadowData.atData[tLightData.iShadowIndex]; diff --git a/shaders/transparent.vert b/shaders/transparent.vert index 6579576..2acb146 100644 --- a/shaders/transparent.vert +++ b/shaders/transparent.vert @@ -42,17 +42,19 @@ layout(set = 0, binding = 4100) uniform textureCube atCubeTextures[4096]; // [SECTION] bind group 1 //----------------------------------------------------------------------------- -layout(set = 1, binding = 0) uniform _plGlobalInfo +struct tGlobalData { vec4 tViewportSize; + vec4 tViewportInfo; vec4 tCameraPos; mat4 tCameraView; mat4 tCameraProjection; mat4 tCameraViewProjection; - uint uLambertianEnvSampler; - uint uGGXEnvSampler; - uint uGGXLUT; - uint _uUnUsed; +}; + +layout(set = 1, binding = 0) readonly buffer _plGlobalInfo +{ + tGlobalData data[]; } tGlobalInfo; //----------------------------------------------------------------------------- @@ -66,6 +68,11 @@ layout(set = 3, binding = 0) uniform PL_DYNAMIC_DATA int iMaterialIndex; int iPadding; mat4 tModel; + + uint uLambertianEnvSampler; + uint uGGXEnvSampler; + uint uGGXLUT; + uint uGlobalIndex; } tObjectInfo; //----------------------------------------------------------------------------- @@ -151,7 +158,7 @@ void main() vec4 pos = tObjectInfo.tModel * inPosition; tShaderIn.tPosition = pos.xyz / pos.w; - gl_Position = tGlobalInfo.tCameraViewProjection * pos; + gl_Position = tGlobalInfo.data[tObjectInfo.uGlobalIndex].tCameraViewProjection * pos; tShaderIn.tUV[0] = inTexCoord0; tShaderIn.tUV[1] = inTexCoord1; tShaderIn.tUV[2] = inTexCoord2;