diff --git a/extensions/pl_renderer_internal.c b/extensions/pl_renderer_internal.c index daa178f..8a4db03 100644 --- a/extensions/pl_renderer_internal.c +++ b/extensions/pl_renderer_internal.c @@ -814,24 +814,24 @@ 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 + ((int)(i) << 16) + .iId = (int)uLightIndex + ((int)(uView) << 16) }; pl_sb_push(ptScene->sbtShadowRects, tPackRect); } - for(uint32_t i = 0; i < uProbeCount; i++) + for(uint32_t uProbe = 0; uProbe < uProbeCount; uProbe++) { - for(uint32_t j = 0; j < 6; j++) + for(uint32_t uView = 0; uView < 6; uView++) { - plPackRect tPackRect = { + const plPackRect tPackRect = { .iWidth = (int)(ptLight->uShadowResolution), .iHeight = (int)ptLight->uShadowResolution, - .iId = (int)uLightIndex + ((int)j << 16) + ((int)(i) << 19) + (-1 << 31) + .iId = (int)uLightIndex + ((int)uView << 16) + ((int)(uProbe) << 19) + (-1 << 31) }; pl_sb_push(ptScene->sbtShadowRects, tPackRect); } @@ -840,7 +840,7 @@ pl_refr_pack_shadow_atlas(uint32_t uSceneHandle, const uint32_t* auViewHandles, 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 @@ -850,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 @@ -859,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++) { @@ -1497,11 +1498,14 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer pl_begin_cpu_sample(gptProfile, 0, __FUNCTION__); // for convience - plDevice* ptDevice = gptData->ptDevice; - plDrawStream* ptStream = &gptData->tDrawStream; - plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; + plDevice* ptDevice = gptData->ptDevice; + plDrawStream* ptStream = &gptData->tDrawStream; + plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; const uint32_t uFrameIdx = gptGfx->get_current_frame_index(); + 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; @@ -1516,16 +1520,14 @@ 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 - const uint32_t uInitialOffset = ptDShadowData->uOffset; - - 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 plPackRect* ptRect = &ptScene->sbtShadowRects[uRectIndex]; + // decode rect info int iLight = ptRect->iId & ~(~0 << 16); int iView = (ptRect->iId >> 16) & ~(~0 << 3); int iProbe = (ptRect->iId >> 19) & ~(~0 << 12); @@ -1533,6 +1535,7 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer 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; @@ -1541,28 +1544,29 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer const uint32_t uDataOffset = pl_sb_size(ptDShadowData->sbtDLightShadowData); pl_sb_add(ptDShadowData->sbtDLightShadowData); + // copy GPU light shadow data plGPULightShadowData* ptShadowData = &ptDShadowData->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; + 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; 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); 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, + 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 = afCascadeSplits[uCascade]; @@ -1580,15 +1584,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}); @@ -1600,10 +1603,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++) @@ -1629,16 +1632,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); @@ -1648,6 +1650,9 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer fLastSplitDist = fSplitDist; } + // 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; @@ -1667,7 +1672,7 @@ 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[] = { @@ -1683,9 +1688,9 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer .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); @@ -1699,10 +1704,11 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer plMat4 tModel; } plShadowDynamicData; - for(uint32_t uLightIndex = 0; uLightIndex < uLightCount; uLightIndex++) + for(uint32_t uRectIndex = 0; uRectIndex < uAtlasRectCount; uRectIndex++) { - const plPackRect* ptRect = &ptScene->sbtShadowRects[uLightIndex]; + const plPackRect* ptRect = &ptScene->sbtShadowRects[uRectIndex]; + // decode rect info int iLight = ptRect->iId & ~(~0 << 16); int iView = (ptRect->iId >> 16) & ~(~0 << 3); int iProbe = (ptRect->iId >> 19) & ~(~0 << 12); @@ -1710,6 +1716,7 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer 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; @@ -1722,8 +1729,6 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer if(gptData->bMultiViewportShadows) { - - gptGfx->reset_draw_stream(ptStream, uVisibleOpaqueDrawCount + uVisibleTransparentDrawCount); gptGfx->set_depth_bias(ptEncoder, gptData->fShadowConstantDepthBias, 0.0f, gptData->fShadowSlopeDepthBias); *gptData->pdDrawCalls += (double)uVisibleOpaqueDrawCount; @@ -1757,7 +1762,7 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, .atBindGroups = { ptScene->tGlobalBindGroup, - tGlobalBG + tShadowBG1 }, .auDynamicBufferOffsets = { tDynamicBinding.uByteOffset @@ -1798,7 +1803,7 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, .atBindGroups = { ptScene->tGlobalBindGroup, - tGlobalBG + tShadowBG1 }, .auDynamicBufferOffsets = { tDynamicBinding.uByteOffset @@ -1910,7 +1915,7 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, .atBindGroups = { ptScene->tGlobalBindGroup, - tGlobalBG + tShadowBG1 }, .auDynamicBufferOffsets = { tDynamicBinding.uByteOffset @@ -1951,7 +1956,7 @@ pl_refr_generate_cascaded_shadow_map(plRenderEncoder* ptEncoder, plCommandBuffer .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, .atBindGroups = { ptScene->tGlobalBindGroup, - tGlobalBG + tShadowBG1 }, .auDynamicBufferOffsets = { tDynamicBinding.uByteOffset @@ -3277,26 +3282,120 @@ pl__create_probe_data(uint32_t uSceneHandle, plEntity tProbeHandle) static uint64_t pl__update_environment_probes(uint32_t uSceneHandle, uint64_t ulValue) { + + // TODO: utilize multiviewport rendering when available + + // for convience plDevice* ptDevice = gptData->ptDevice; - plCommandPool* ptCmdPool = gptData->atCmdPools[gptGfx->get_current_frame_index()]; - const uint32_t uFrameIdx = gptGfx->get_current_frame_index(); plDrawStream* ptStream = &gptData->tDrawStream; plRefScene* ptScene = &gptData->sbtScenes[uSceneHandle]; - const plLightComponent* sbtLights = ptScene->tComponentLibrary.tLightComponentManager.pComponents; + + const uint32_t uFrameIdx = gptGfx->get_current_frame_index(); + plCommandPool* ptCmdPool = gptData->atCmdPools[uFrameIdx]; plTimelineSemaphore* tSemHandle = gptData->aptSemaphores[uFrameIdx]; - const uint32_t uFrameIndex = gptGfx->get_current_frame_index(); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~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 } + }; + + // 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 tSceneBG = { + .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 tSceneBGDesc = { + .ptPool = gptData->aptTempGroupPools[uFrameIdx], + .ptLayout = &tSceneBG, + .pcDebugName = "light bind group 2" + }; + + plBindGroupLayout tSkyboxBG1Layout = { + .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 tSkyboxBG1Desc = { + .ptPool = gptData->aptTempGroupPools[uFrameIdx], + .ptLayout = &tSkyboxBG1Layout, + .pcDebugName = "skybox view specific bindgroup" + }; + + 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_UNIFORM, + .uSlot = 0, + .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, + } + } + }; + + const plBindGroupDesc tGBufferFillBG1Desc = { + .ptPool = gptData->aptTempGroupPools[uFrameIdx], + .ptLayout = &tGBufferFillBG1Layout, + .pcDebugName = "view specific bindgroup" + }; - for(uint32_t uProbeIndex = 0; uProbeIndex < pl_sb_size(ptScene->sbtProbeData); uProbeIndex++) + 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); + + // reset probe data pl_sb_reset(ptProbe->tDirectionLightShadowData.sbtDLightShadowData); ptProbe->tDirectionLightShadowData.uOffset = 0; ptProbe->tDirectionLightShadowData.uOffsetIndex = 0; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~culling~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // TODO: actually perform culling + const uint32_t uOpaqueDrawableCount = pl_sb_size(ptScene->sbtDeferredDrawables); const uint32_t uTransparentDrawableCount = pl_sb_size(ptScene->sbtForwardDrawables); @@ -3311,90 +3410,36 @@ pl__update_environment_probes(uint32_t uSceneHandle, uint64_t ulValue) memcpy(ptProbe->sbtVisibleTransparentDrawables, ptScene->sbtForwardDrawables, sizeof(plDrawable) * uTransparentDrawableCount); } - 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 atRenderOffset[6] = { - { 0.0f, 0.0f}, - {(float)ptProbeComp->uResolution, 0.0f}, - { 0.0f, (float)ptProbeComp->uResolution}, - {(float)ptProbeComp->uResolution, (float)ptProbeComp->uResolution}, - { 0.0f, 2.0f * (float)ptProbeComp->uResolution}, - {(float)ptProbeComp->uResolution, 2.0f * (float)ptProbeComp->uResolution}, - }; - - 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" - }; + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~probe face pre-calc~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 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 atLightBindGroup2[6] = {0}; - plBindGroupHandle atSkyboxViewBindGroup[6] = {0}; + // temporary data for probes + plBindGroupHandle atSceneBG[6] = {0}; plDrawArea atAreas[6] = {0}; + const uint32_t uAlignment = (uint32_t)pl_align_up(sizeof(BindGroup_0), gptData->tDeviceInfo.tLimits.uMinUniformBufferOffsetAlignment); for(uint32_t uFace = 0; uFace < 6; uFace++) { atAreas[uFace] = (plDrawArea) { - .ptDrawStream = ptStream, - .atScissors = - { - { - .uWidth = (uint32_t)ptProbeComp->uResolution, - .uHeight = (uint32_t)ptProbeComp->uResolution, - .iOffsetX = (int)atRenderOffset[uFace].x, - .iOffsetY = (int)atRenderOffset[uFace].y, - } - }, - .atViewports = - { - { - .fX = atRenderOffset[uFace].x, - .fY = atRenderOffset[uFace].y, - .fWidth = (float)ptProbeComp->uResolution, - .fHeight = (float)ptProbeComp->uResolution, - .fMaxDepth = 1.0f - } - } + .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 + } + } }; plCameraComponent tEnvironmentCamera = { @@ -3408,138 +3453,94 @@ pl__update_environment_probes(uint32_t uSceneHandle, uint64_t ulValue) gptCamera->set_pitch_yaw(&tEnvironmentCamera, atPitchYaw[uFace].x, atPitchYaw[uFace].y); gptCamera->update(&tEnvironmentCamera); + //~~~~~~~~~~~~~~~~~~~~~~~~~~~cascaded shadow maps~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - { - const plBeginCommandInfo tBeginInfo = { - .uWaitSemaphoreCount = 1, - .atWaitSempahores = {tSemHandle}, - .auWaitSemaphoreValues = {ulValue}, - }; + // TODO: these can be parallel - plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo); + const plBeginCommandInfo tBeginCSMInfo = { + .uWaitSemaphoreCount = 1, + .atWaitSempahores = {tSemHandle}, + .auWaitSemaphoreValues = {ulValue}, + }; - + plCommandBuffer* ptCSMCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); + gptGfx->begin_command_recording(ptCSMCommandBuffer, &tBeginCSMInfo); - plRenderEncoder* ptEncoder = gptGfx->begin_render_pass(ptCommandBuffer, ptScene->tShadowRenderPass, NULL); + plRenderEncoder* ptCSMEncoder = gptGfx->begin_render_pass(ptCSMCommandBuffer, ptScene->tShadowRenderPass, NULL); - pl_refr_generate_cascaded_shadow_map(ptEncoder, ptCommandBuffer, uSceneHandle, uFace, uProbeIndex, -1, &ptProbe->tDirectionLightShadowData, &tEnvironmentCamera); + pl_refr_generate_cascaded_shadow_map(ptCSMEncoder, ptCSMCommandBuffer, uSceneHandle, uFace, uProbeIndex, -1, &ptProbe->tDirectionLightShadowData, &tEnvironmentCamera); - gptGfx->end_render_pass(ptEncoder); - gptGfx->end_command_recording(ptCommandBuffer); + gptGfx->end_render_pass(ptCSMEncoder); + gptGfx->end_command_recording(ptCSMCommandBuffer); - const plSubmitInfo tSubmitInfo = { - .uSignalSemaphoreCount = 1, - .atSignalSempahores = {tSemHandle}, - .auSignalSemaphoreValues = {++ulValue} - }; - gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo); - gptGfx->return_command_buffer(ptCommandBuffer); - } + 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 tBindGroupBuffer = { + 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, atRenderOffset[uFace].y}, + .tViewportInfo = {atRenderOffset[uFace].x * (float)ptProbeComp->uResolution, atRenderOffset[uFace].y * (float)ptProbeComp->uResolution}, .tCameraPos = tEnvironmentCamera.tPos, .tCameraProjection = tEnvironmentCamera.tProjMat, .tCameraView = tEnvironmentCamera.tViewMat, .tCameraViewProjection = pl_mul_mat4(&tEnvironmentCamera.tProjMat, &tEnvironmentCamera.tViewMat) }; - uint32_t uSingleAlignment = (uint32_t)pl_align_up(sizeof(BindGroup_0), gptData->tDeviceInfo.tLimits.uMinUniformBufferOffsetAlignment); - uint32_t uAlignment = uSingleAlignment * uFace; - memcpy(&gptGfx->get_buffer(ptDevice, ptProbe->atGlobalBuffers[uFrameIdx])->tMemoryAllocation.pHostMapped[uAlignment], &tBindGroupBuffer, sizeof(BindGroup_0)); - - atLightBindGroup2[uFace] = gptGfx->create_bind_group(ptDevice, &tLightBGDesc); - atSkyboxViewBindGroup[uFace] = gptGfx->create_bind_group(ptDevice, &tSkyboxViewBindGroupDesc); + // copy global buffer data for probe rendering + const uint32_t uProbeGlobalBufferOffset = uAlignment * 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)); - const plBeginCommandInfo tBeginInfo = { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~probe rendering~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + const plBeginCommandInfo tProbeBeginInfo = { .uWaitSemaphoreCount = 1, .atWaitSempahores = {tSemHandle}, .auWaitSemaphoreValues = {ulValue}, }; - plCommandBuffer* ptCommandBuffer = gptGfx->request_command_buffer(ptCmdPool); - gptGfx->begin_command_recording(ptCommandBuffer, &tBeginInfo); + plCommandBuffer* ptCmdBuffer = gptGfx->request_command_buffer(ptCmdPool); + gptGfx->begin_command_recording(ptCmdBuffer, &tProbeBeginInfo); //~~~~~~~~~~~~~~~~~~~~~~~~~~subpass 0 - g buffer fill~~~~~~~~~~~~~~~~~~~~~~~~~~ - plRenderEncoder* ptEncoder = gptGfx->begin_render_pass(ptCommandBuffer, ptProbe->tRenderPass, NULL); - gptGfx->set_depth_bias(ptEncoder, 0.0f, 0.0f, 0.0f); + plRenderEncoder* ptProbeEncoder = gptGfx->begin_render_pass(ptCmdBuffer, ptProbe->tRenderPass, NULL); + gptGfx->set_depth_bias(ptProbeEncoder, 0.0f, 0.0f, 0.0f); - for(uint32_t uFaceIndex = 0; uFaceIndex < 6; uFaceIndex++) + for(uint32_t uFace = 0; uFace < 6; uFace++) { - uint32_t uSingleAlignment = (uint32_t)pl_align_up(sizeof(BindGroup_0), gptData->tDeviceInfo.tLimits.uMinUniformBufferOffsetAlignment); - uint32_t uAlignment = uSingleAlignment * uFaceIndex; + const uint32_t uProbeGlobalBufferOffset = uAlignment * uFace; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~update bind groups~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - plBindGroupLayout tViewBindGroupLayout = { - .atBufferBindings = { - { - .tType = PL_BUFFER_BINDING_TYPE_UNIFORM, - .uSlot = 0, - .tStages = PL_STAGE_VERTEX | PL_STAGE_PIXEL, - } - } + // create g-buffer fill bind group 1 + const plBindGroupUpdateBufferData tGBufferFillBG1BufferData = { + .tBuffer = ptProbe->atGlobalBuffers[uFrameIdx], + .uSlot = 0, + .szBufferRange = sizeof(BindGroup_0), + .szOffset = uProbeGlobalBufferOffset }; - const plBindGroupDesc tViewBindGroupDesc = { - .ptPool = gptData->aptTempGroupPools[uFrameIndex], - .ptLayout = &tViewBindGroupLayout, - .pcDebugName = "view specific bindgroup" + const plBindGroupUpdateData tGBufferFillBG1Data = { + .uBufferCount = 1, + .atBufferBindings = &tGBufferFillBG1BufferData }; - plBindGroupHandle tViewBindGroup = gptGfx->create_bind_group(ptDevice, &tViewBindGroupDesc); - plBindGroupUpdateSamplerData tSamplerData[] = { - { - .tSampler = gptData->tSkyboxSampler, - .uSlot = 1 - } - }; - - const plBindGroupUpdateBufferData atNewBufferData[] = - { - { - .tBuffer = ptProbe->atGlobalBuffers[uFrameIdx], - .uSlot = 0, - .szBufferRange = sizeof(BindGroup_0), - .szOffset = uAlignment - } - }; - - const plBindGroupUpdateBufferData atBufferData[] = - { - { - .tBuffer = ptProbe->atGlobalBuffers[uFrameIdx], - .uSlot = 0, - .szBufferRange = sizeof(BindGroup_0), - .szOffset = uAlignment - } - }; - - plBindGroupUpdateData tSkyboxViewBindGroupData = { - .uBufferCount = 1, - .atBufferBindings = atBufferData, - .uSamplerCount = 1, - .atSamplerBindings = tSamplerData, - }; - plBindGroupUpdateData tViewBindGroupData = { - .uBufferCount = 1, - .atBufferBindings = atNewBufferData - }; - - gptGfx->update_bind_group(gptData->ptDevice, atSkyboxViewBindGroup[uFaceIndex], &tSkyboxViewBindGroupData); - gptGfx->update_bind_group(gptData->ptDevice, tViewBindGroup, &tViewBindGroupData); - gptGfx->queue_bind_group_for_deletion(ptDevice, atSkyboxViewBindGroup[uFaceIndex]); - gptGfx->queue_bind_group_for_deletion(ptDevice, tViewBindGroup); + plBindGroupHandle tGBufferFillBG1 = gptGfx->create_bind_group(ptDevice, &tGBufferFillBG1Desc); + gptGfx->update_bind_group(gptData->ptDevice, tGBufferFillBG1, &tGBufferFillBG1Data); + gptGfx->queue_bind_group_for_deletion(ptDevice, tGBufferFillBG1); - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~render scene~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - const uint32_t uVisibleOpaqueDrawCount = pl_sb_size(ptProbe->sbtVisibleOpaqueDrawables); *gptData->pdDrawCalls += (double)uVisibleOpaqueDrawCount; gptGfx->reset_draw_stream(ptStream, uVisibleOpaqueDrawCount); @@ -3572,61 +3573,59 @@ pl__update_environment_probes(uint32_t uSceneHandle, uint64_t ulValue) .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, .atBindGroups = { ptScene->tGlobalBindGroup, - tViewBindGroup + tGBufferFillBG1 }, .auDynamicBufferOffsets = { tDynamicBinding.uByteOffset }, .uInstanceOffset = 0, - .uInstanceCount = 1 + .uInstanceCount = 1 }); } - gptGfx->draw_stream(ptEncoder, 1, &atAreas[uFaceIndex]); - + gptGfx->draw_stream(ptProbeEncoder, 1, &atAreas[uFace]); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~subpass 1 - lighting~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - gptGfx->next_subpass(ptEncoder, NULL); - for(uint32_t uFaceIndex = 0; uFaceIndex < 6; uFaceIndex++) + gptGfx->next_subpass(ptProbeEncoder, NULL); + + for(uint32_t uFace = 0; uFace < 6; uFace++) { - uint32_t uSingleAlignment = (uint32_t)pl_align_up(sizeof(BindGroup_0), gptData->tDeviceInfo.tLimits.uMinUniformBufferOffsetAlignment); - uint32_t uAlignment = uSingleAlignment * uFaceIndex; + const uint32_t uProbeGlobalBufferOffset = uAlignment * uFace; - const plBindGroupUpdateBufferData atLightBufferData[] = + // create scene bind group (camera, lights, shadows) + const plBindGroupUpdateBufferData tSceneBGBufferData[7] = { - { .uSlot = 0, .tBuffer = ptProbe->atGlobalBuffers[uFrameIdx], .szBufferRange = sizeof(BindGroup_0), .szOffset = uAlignment }, - { .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)}, + { .uSlot = 0, .tBuffer = ptProbe->atGlobalBuffers[uFrameIdx], .szOffset = uProbeGlobalBufferOffset, .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 = 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)}, }; - plBindGroupUpdateSamplerData tShadowSamplerData[] = { - { - .tSampler = gptData->tShadowSampler, - .uSlot = 7 - } + const plBindGroupUpdateData tSceneBGData = { + .uBufferCount = 7, + .atBufferBindings = tSceneBGBufferData, + .uSamplerCount = 1, + .atSamplerBindings = &tShadowSamplerData }; + atSceneBG[uFace] = gptGfx->create_bind_group(ptDevice, &tSceneBGDesc); + gptGfx->update_bind_group(gptData->ptDevice, atSceneBG[uFace], &tSceneBGData); + gptGfx->queue_bind_group_for_deletion(ptDevice, atSceneBG[uFace]); - plBindGroupUpdateData tBGData2 = { - .uBufferCount = 7, - .atBufferBindings = atLightBufferData, - .uSamplerCount = 1, - .atSamplerBindings = tShadowSamplerData - }; - gptGfx->update_bind_group(gptData->ptDevice, atLightBindGroup2[uFaceIndex], &tBGData2); - gptGfx->queue_bind_group_for_deletion(ptDevice, atLightBindGroup2[uFaceIndex]); + // create lighting dynamic bind group - typedef struct _plLightingDynamicData{ + typedef struct _plLightingDynamicData + { uint32_t uLambertianEnvSampler; uint32_t uGGXEnvSampler; uint32_t uGGXLUT; int unused[1]; } plLightingDynamicData; + plDynamicBinding tLightingDynamicData = pl__allocate_dynamic_data(ptDevice); plLightingDynamicData* ptLightingDynamicData = (plLightingDynamicData*)tLightingDynamicData.pcData; ptLightingDynamicData->uGGXEnvSampler = ptScene->sbtProbeData[0].uGGXEnvSampler; @@ -3651,7 +3650,7 @@ pl__update_environment_probes(uint32_t uSceneHandle, uint64_t ulValue) .atBindGroups = { ptScene->tGlobalBindGroup, ptProbe->tLightingBindGroup[uFrameIdx], - atLightBindGroup2[uFaceIndex] + atSceneBG[uFace] }, .auDynamicBufferOffsets = { tLightingDynamicData.uByteOffset @@ -3659,21 +3658,39 @@ pl__update_environment_probes(uint32_t uSceneHandle, uint64_t ulValue) .uInstanceOffset = 0, .uInstanceCount = 1 }); - gptGfx->draw_stream(ptEncoder, 1, &atAreas[uFaceIndex]); - + gptGfx->draw_stream(ptProbeEncoder, 1, &atAreas[uFace]); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~subpass 2 - forward~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - gptGfx->next_subpass(ptEncoder, NULL); - for(uint32_t uFaceIndex = 0; uFaceIndex < 6; uFaceIndex++) - { - uint32_t uSingleAlignment = (uint32_t)pl_align_up(sizeof(BindGroup_0), gptData->tDeviceInfo.tLimits.uMinUniformBufferOffsetAlignment); - uint32_t uAlignment = uSingleAlignment * uFaceIndex; + gptGfx->next_subpass(ptProbeEncoder, NULL); + for(uint32_t uFace = 0; uFace < 6; uFace++) + { if(ptScene->tSkyboxTexture.uIndex != 0) { + const uint32_t uProbeGlobalBufferOffset = uAlignment * uFace; + + // create skybox bind group 1 + const plBindGroupUpdateBufferData tSkyboxBG1BufferData = { + .tBuffer = ptProbe->atGlobalBuffers[uFrameIdx], + .uSlot = 0, + .szBufferRange = sizeof(BindGroup_0), + .szOffset = uProbeGlobalBufferOffset + }; + + 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); + plDynamicBinding tSkyboxDynamicData = pl__allocate_dynamic_data(ptDevice); plMat4* ptSkyboxDynamicData = (plMat4*)tSkyboxDynamicData.pcData; *ptSkyboxDynamicData = pl_mat4_translate_vec3(ptProbeComp->tPosition); @@ -3693,7 +3710,7 @@ pl__update_environment_probes(uint32_t uSceneHandle, uint64_t ulValue) .uIndexOffset = ptScene->tSkyboxDrawable.uIndexOffset, .uTriangleCount = ptScene->tSkyboxDrawable.uIndexCount / 3, .atBindGroups = { - atSkyboxViewBindGroup[uFaceIndex], + tSkyboxBG1, ptScene->tSkyboxAtlasBindGroup }, .auDynamicBufferOffsets = { @@ -3702,11 +3719,11 @@ pl__update_environment_probes(uint32_t uSceneHandle, uint64_t ulValue) .uInstanceOffset = 0, .uInstanceCount = 1 }); - gptGfx->draw_stream(ptEncoder, 1, &atAreas[uFaceIndex]); + gptGfx->draw_stream(ptProbeEncoder, 1, &atAreas[uFace]); } - // transparent & complex material objects + const uint32_t uVisibleTransparentDrawCount = pl_sb_size(ptProbe->sbtVisibleTransparentDrawables); gptGfx->reset_draw_stream(ptStream, uVisibleTransparentDrawCount); *gptData->pdDrawCalls += (double)uVisibleTransparentDrawCount; @@ -3739,7 +3756,7 @@ pl__update_environment_probes(uint32_t uSceneHandle, uint64_t ulValue) .uVertexOffset = tDrawable.uIndexCount == 0 ? tDrawable.uVertexOffset : 0, .atBindGroups = { ptScene->tGlobalBindGroup, - atLightBindGroup2[uFaceIndex] + atSceneBG[uFace] }, .auDynamicBufferOffsets = { tDynamicBinding.uByteOffset @@ -3748,22 +3765,21 @@ pl__update_environment_probes(uint32_t uSceneHandle, uint64_t ulValue) .uInstanceCount = 1 }); } - gptGfx->draw_stream(ptEncoder, 1, &atAreas[uFaceIndex]); + gptGfx->draw_stream(ptProbeEncoder, 1, &atAreas[uFace]); } - gptGfx->end_render_pass(ptEncoder); - - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~entity selection~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~submission~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - gptGfx->end_command_recording(ptCommandBuffer); + gptGfx->end_render_pass(ptProbeEncoder); + gptGfx->end_command_recording(ptCmdBuffer); - const plSubmitInfo tSubmitInfo = { + const plSubmitInfo tProbeSubmitInfo = { .uSignalSemaphoreCount = 1, .atSignalSempahores = {tSemHandle}, .auSignalSemaphoreValues = {++ulValue} }; - gptGfx->submit_command_buffer(ptCommandBuffer, &tSubmitInfo); - // gptGfx->wait_on_command_buffer(ptCommandBuffer); - gptGfx->return_command_buffer(ptCommandBuffer); + gptGfx->submit_command_buffer(ptCmdBuffer, &tProbeSubmitInfo); + gptGfx->return_command_buffer(ptCmdBuffer); ulValue = pl_create_environment_map_from_texture(uSceneHandle, ptProbe, ulValue); }