From f3687dbf4e408aaa7041525599f84e93b354acae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Sun, 5 Sep 2021 18:59:03 +0200 Subject: [PATCH] DX11 removal, Surfel GI version 0.57.0: - DX11 removed, DX12 is default now on Windows - graphics interfaces improved: - Bindless descriptor support is now assumed - GPU Buffers with USAGE_UPLOAD and USAGE_READBACK will be persistently mapped after creation - Removed Map/Unmap - added BindDynamicConstantBuffer helper function - improved AllocateGPU helper function - GPU Queries resolving can be done directly into GPUBuffer - UpdateBuffer now doesn't synchronize internally, this allows batching updates - removed support for bindless constant buffers (uniform buffers) - BindConstantBuffer will accept offset - RESOURCE_STATES refactor, they can be combined now in the barriers - many other refactors - gbuffer normals removed, implemented visibility buffer - bindless decals, bindless lightmaps, bindless hair particles, bindless software path tracing - hair particles path tracing support - path tracing eye adaption supported - Surfel GI (experimental) --- .github/workflows/build-nightly.yml | 2 +- .github/workflows/build-pr.yml | 2 +- .github/workflows/build.yml | 2 +- .../WickedEngine-Documentation.md | 34 +- Content/models/hairparticle_torus.wiscene | Bin 55663 -> 1221074 bytes Content/models/playground.wiscene | Bin 117691 -> 359725 bytes Editor/Editor.cpp | 11 +- Editor/Editor_SOURCE.vcxitems | 5 - Editor/Editor_SOURCE.vcxitems.filters | 1 - Editor/PaintToolWindow.cpp | 21 +- Editor/PostprocessWindow.cpp | 4 +- Editor/RendererWindow.cpp | 35 +- Editor/RendererWindow.h | 3 + Editor/Translator.cpp | 31 +- README.md | 2 +- Template_UWP/Template_UWP.vcxproj | 5 - Template_UWP/Template_UWP.vcxproj.filters | 1 - Template_Windows/Template_Windows.vcxproj | 15 +- .../Template_Windows.vcxproj.filters | 1 - Tests/Tests.vcxproj | 15 +- Tests/Tests.vcxproj.filters | 1 - WickedEngine/CMakeLists.txt | 1 - WickedEngine/MainComponent.cpp | 112 +- WickedEngine/OfflineShaderCompiler.vcxproj | 5 - WickedEngine/RenderPath2D.cpp | 14 +- WickedEngine/RenderPath3D.cpp | 317 +- WickedEngine/RenderPath3D.h | 28 +- WickedEngine/RenderPath3D_PathTracing.cpp | 32 +- WickedEngine/WickedEngine_SOURCE.vcxitems | 3 - .../WickedEngine_SOURCE.vcxitems.filters | 15 +- WickedEngine/WickedEngine_Windows.vcxproj | 6 +- WickedEngine/d3dcompiler_47.dll | Bin 4524496 -> 0 bytes WickedEngine/offlineshadercompiler.cpp | 27 +- WickedEngine/shaders/CMakeLists.txt | 19 +- WickedEngine/shaders/ConstantBufferMapping.h | 11 - WickedEngine/shaders/ResourceMapping.h | 75 +- WickedEngine/shaders/ShaderInterop.h | 8 +- WickedEngine/shaders/ShaderInterop_BVH.h | 52 +- .../shaders/ShaderInterop_EmittedParticle.h | 10 +- WickedEngine/shaders/ShaderInterop_Font.h | 15 +- .../shaders/ShaderInterop_HairParticle.h | 14 +- WickedEngine/shaders/ShaderInterop_Image.h | 24 +- WickedEngine/shaders/ShaderInterop_Paint.h | 27 - WickedEngine/shaders/ShaderInterop_Renderer.h | 484 +- WickedEngine/shaders/ShaderInterop_Skinning.h | 10 - WickedEngine/shaders/ShaderInterop_SurfelGI.h | 189 + WickedEngine/shaders/ShaderInterop_Utility.h | 41 - WickedEngine/shaders/Shaders_SOURCE.vcxitems | 126 +- .../shaders/Shaders_SOURCE.vcxitems.filters | 65 +- .../shaders/blur_gaussian_float4CS.hlsl | 2 +- WickedEngine/shaders/brdf.hlsli | 225 +- WickedEngine/shaders/bvh_primitivesCS.hlsl | 197 +- .../shaders/copytexture2D_float4CS.hlsl | 10 +- .../copytexture2D_float4_borderexpandCS.hlsl | 52 +- WickedEngine/shaders/cubeMapPS.hlsl | 2 +- WickedEngine/shaders/cubeShadowVS.hlsl | 2 +- .../shaders/cubeShadowVS_alphatest.hlsl | 2 +- .../shaders/cubeShadowVS_transparent.hlsl | 2 +- WickedEngine/shaders/cubeVS.hlsl | 6 - WickedEngine/shaders/cullingShaderHF.hlsli | 2 +- WickedEngine/shaders/depthOfFieldHF.hlsli | 4 +- WickedEngine/shaders/depthoffield_mainCS.hlsl | 2 +- .../shaders/depthoffield_prepassCS.hlsl | 4 +- .../shaders/depthoffield_upsampleCS.hlsl | 2 +- WickedEngine/shaders/emittedparticleHF.hlsli | 7 + WickedEngine/shaders/emittedparticleMS.hlsl | 10 +- .../shaders/emittedparticlePS_soft.hlsl | 35 +- WickedEngine/shaders/emittedparticleVS.hlsl | 12 +- .../shaders/emittedparticle_emitCS.hlsl | 5 +- .../shaders/emittedparticle_simulateCS.hlsl | 18 +- WickedEngine/shaders/envMapPS.hlsl | 1 + WickedEngine/shaders/envMapVS.hlsl | 1 + WickedEngine/shaders/filterEnvMapCS.hlsl | 20 +- WickedEngine/shaders/fontPS.hlsl | 9 +- WickedEngine/shaders/fontVS.hlsl | 6 +- .../shaders/forceFieldPlaneVisualizerVS.hlsl | 2 +- .../shaders/forceFieldPointVisualizerVS.hlsl | 2 +- .../shaders/forceFieldVisualizerPS.hlsl | 4 +- .../shaders/generateMIPChain2DCS_float4.hlsl | 10 +- .../shaders/generateMIPChain3DCS_float4.hlsl | 8 +- .../generateMIPChainCubeArrayCS_float4.hlsl | 10 +- .../generateMIPChainCubeCS_float4.hlsl | 8 +- WickedEngine/shaders/globals.hlsli | 142 +- WickedEngine/shaders/hairparticleHF.hlsli | 22 +- WickedEngine/shaders/hairparticlePS.hlsl | 30 +- .../shaders/hairparticlePS_prepass.hlsl | 30 +- .../shaders/hairparticlePS_simple.hlsl | 6 +- WickedEngine/shaders/hairparticleVS.hlsl | 107 +- .../shaders/hairparticle_finishUpdateCS.hlsl | 4 +- .../shaders/hairparticle_simulateCS.hlsl | 126 +- WickedEngine/shaders/hbaoCS.hlsl | 4 +- WickedEngine/shaders/imageHF.hlsli | 19 +- WickedEngine/shaders/imagePS.hlsl | 32 +- .../shaders/imagePS_backgroundblur.hlsl | 10 - .../imagePS_backgroundblur_masked.hlsl | 12 - WickedEngine/shaders/imagePS_masked.hlsl | 11 - .../shaders/imagePS_separatenormalmap.hlsl | 13 - .../imagePS_separatenormalmap_bicubic.hlsl | 13 - WickedEngine/shaders/imageVS.hlsl | 10 +- WickedEngine/shaders/impostorHF.hlsli | 6 +- WickedEngine/shaders/impostorPS.hlsl | 19 +- WickedEngine/shaders/impostorPS_prepass.hlsl | 18 +- WickedEngine/shaders/impostorPS_simple.hlsl | 6 +- WickedEngine/shaders/impostorVS.hlsl | 53 +- WickedEngine/shaders/lensFlareVS.hlsl | 16 +- WickedEngine/shaders/lightCullingCS.hlsl | 14 +- WickedEngine/shaders/lightingHF.hlsli | 84 +- WickedEngine/shaders/lineardepthCS.hlsl | 89 - WickedEngine/shaders/luminancePass2CS.hlsl | 2 +- WickedEngine/shaders/motionblurCS.hlsl | 10 +- ...tionblur_tileMaxVelocity_horizontalCS.hlsl | 2 +- WickedEngine/shaders/normalsfromdepthCS.hlsl | 2 +- WickedEngine/shaders/objectDS_prepass.hlsl | 2 +- .../shaders/objectDS_prepass_alphatest.hlsl | 2 +- WickedEngine/shaders/objectDS_simple.hlsl | 2 +- WickedEngine/shaders/objectGS_voxelizer.hlsl | 4 +- WickedEngine/shaders/objectHF.hlsli | 572 +-- .../shaders/objectHF_tessellation.hlsli | 18 +- WickedEngine/shaders/objectHS_prepass.hlsl | 2 +- .../shaders/objectHS_prepass_alphatest.hlsl | 2 +- WickedEngine/shaders/objectHS_simple.hlsl | 2 +- WickedEngine/shaders/objectPS_hologram.hlsl | 10 +- .../shaders/objectPS_paintradius.hlsl | 4 +- WickedEngine/shaders/objectPS_prepass.hlsl | 2 +- .../shaders/objectPS_prepass_alphatest.hlsl | 2 +- WickedEngine/shaders/objectPS_simple.hlsl | 2 +- WickedEngine/shaders/objectPS_voxelizer.hlsl | 22 +- WickedEngine/shaders/objectVS_prepass.hlsl | 2 +- .../shaders/objectVS_prepass_alphatest.hlsl | 2 +- ...jectVS_prepass_alphatest_tessellation.hlsl | 2 +- .../objectVS_prepass_tessellation.hlsl | 2 +- WickedEngine/shaders/objectVS_simple.hlsl | 2 +- .../shaders/objectVS_simple_tessellation.hlsl | 2 +- WickedEngine/shaders/oceanSimulatorCS.hlsl | 2 +- WickedEngine/shaders/oceanSurfacePS.hlsl | 12 +- WickedEngine/shaders/oceanSurfaceVS.hlsl | 12 +- WickedEngine/shaders/paint_textureCS.hlsl | 16 +- WickedEngine/shaders/raytraceCS.hlsl | 71 +- WickedEngine/shaders/raytracingHF.hlsli | 331 +- WickedEngine/shaders/renderlightmapPS.hlsl | 60 +- WickedEngine/shaders/rtaoCS.hlsl | 52 +- .../shaders/rtao_denoise_filterCS.hlsl | 2 +- .../rtao_denoise_tileclassificationCS.hlsl | 10 +- WickedEngine/shaders/rtreflectionLIB.hlsl | 115 +- .../shaders/rtshadow_denoise_filterCS.hlsl | 2 +- .../shaders/rtshadow_denoise_temporalCS.hlsl | 2 +- ...rtshadow_denoise_tileclassificationCS.hlsl | 10 +- WickedEngine/shaders/screenPS.hlsl | 11 +- WickedEngine/shaders/screenspaceshadowCS.hlsl | 151 +- .../shaders/shadingRateClassificationCS.hlsl | 4 +- WickedEngine/shaders/shadowPS_alphatest.hlsl | 2 +- .../shaders/shadowPS_transparent.hlsl | 2 +- WickedEngine/shaders/shadowPS_water.hlsl | 2 +- WickedEngine/shaders/shadowVS.hlsl | 2 +- WickedEngine/shaders/shadowVS_alphatest.hlsl | 2 +- .../shaders/shadowVS_transparent.hlsl | 2 +- WickedEngine/shaders/skinningCS.hlsl | 53 +- WickedEngine/shaders/skinningCS_LDS.hlsl | 3 - WickedEngine/shaders/skyAtmosphere.hlsli | 2 +- ...mosphere_multiScatteredLuminanceLutCS.hlsl | 2 +- .../skyAtmosphere_skyLuminanceLutCS.hlsl | 2 +- .../shaders/skyAtmosphere_skyViewLutCS.hlsl | 4 +- .../skyAtmosphere_transmittanceLutCS.hlsl | 2 +- WickedEngine/shaders/skyHF.hlsli | 26 +- WickedEngine/shaders/skyPS_dynamic.hlsl | 4 +- WickedEngine/shaders/skyPS_static.hlsl | 8 +- WickedEngine/shaders/skyPS_velocity.hlsl | 13 - WickedEngine/shaders/sphereVS.hlsl | 2 +- WickedEngine/shaders/ssaoCS.hlsl | 8 +- WickedEngine/shaders/ssr_raytraceCS.hlsl | 61 +- WickedEngine/shaders/ssr_resolveCS.hlsl | 26 +- WickedEngine/shaders/ssr_temporalCS.hlsl | 25 +- WickedEngine/shaders/stochasticSSRHF.hlsli | 1 + WickedEngine/shaders/sunPS.hlsl | 4 +- WickedEngine/shaders/surfel_binningCS.hlsl | 36 + WickedEngine/shaders/surfel_coverageCS.hlsl | 253 ++ .../shaders/surfel_gridoffsetsCS.hlsl | 15 + WickedEngine/shaders/surfel_gridresetCS.hlsl | 10 + .../shaders/surfel_indirectprepareCS.hlsl | 15 + WickedEngine/shaders/surfel_raytraceCS.hlsl | 322 ++ .../shaders/surfel_raytraceCS_rtapi.hlsl | 2 + WickedEngine/shaders/surfel_shadeCS.hlsl | 180 + WickedEngine/shaders/surfel_updateCS.hlsl | 52 + WickedEngine/shaders/temporalaaCS.hlsl | 8 +- WickedEngine/shaders/tileFrustumsCS.hlsl | 4 +- WickedEngine/shaders/tonemapCS.hlsl | 44 - .../shaders/upsample_bilateral_float4CS.hlsl | 2 +- WickedEngine/shaders/vPointLightVS.hlsl | 2 +- WickedEngine/shaders/vSpotLightVS.hlsl | 2 +- .../shaders/visibility_resolveCS.hlsl | 97 + .../shaders/visibility_resolveCS_MSAA.hlsl | 2 + .../shaders/volumetricCloud_renderCS.hlsl | 134 +- .../shaders/volumetricCloud_reprojectCS.hlsl | 20 +- .../shaders/volumetricCloud_temporalCS.hlsl | 18 +- .../volumetricLight_DirectionalPS.hlsl | 12 +- .../shaders/volumetricLight_PointPS.hlsl | 6 +- .../shaders/volumetricLight_SpotPS.hlsl | 6 +- WickedEngine/shaders/voxelConeTracingHF.hlsli | 24 +- WickedEngine/shaders/voxelGS.hlsl | 6 +- .../voxelRadianceSecondaryBounceCS.hlsl | 8 +- .../shaders/voxelSceneCopyClearCS.hlsl | 4 +- WickedEngine/shaders/voxelVS.hlsl | 6 +- WickedEngine/wiEmittedParticle.cpp | 131 +- WickedEngine/wiEmittedParticle.h | 4 +- WickedEngine/wiEnums.h | 66 +- WickedEngine/wiFFTGenerator.cpp | 22 +- WickedEngine/wiFont.cpp | 45 +- WickedEngine/wiGPUBVH.cpp | 363 +- WickedEngine/wiGPUBVH.h | 12 +- WickedEngine/wiGPUSortLib.cpp | 36 +- WickedEngine/wiGraphics.h | 228 +- WickedEngine/wiGraphicsDevice.h | 144 +- WickedEngine/wiGraphicsDevice_DX11.cpp | 3362 -------------- WickedEngine/wiGraphicsDevice_DX11.h | 159 - WickedEngine/wiGraphicsDevice_DX12.cpp | 895 ++-- WickedEngine/wiGraphicsDevice_DX12.h | 70 +- .../wiGraphicsDevice_SharedInternals.h | 10 - WickedEngine/wiGraphicsDevice_Vulkan.cpp | 1038 ++--- WickedEngine/wiGraphicsDevice_Vulkan.h | 64 +- WickedEngine/wiHairParticle.cpp | 313 +- WickedEngine/wiHairParticle.h | 14 +- WickedEngine/wiHelper.cpp | 36 +- WickedEngine/wiImage.cpp | 140 +- WickedEngine/wiOcean.cpp | 65 +- WickedEngine/wiPhysicsEngine_Bullet.cpp | 9 - WickedEngine/wiPlatform.h | 1 + WickedEngine/wiProfiler.cpp | 43 +- WickedEngine/wiRenderer.cpp | 3984 +++++++---------- WickedEngine/wiRenderer.h | 52 +- WickedEngine/wiResourceManager.cpp | 11 +- WickedEngine/wiScene.cpp | 677 ++- WickedEngine/wiScene.h | 85 +- WickedEngine/wiShaderCompiler.cpp | 6 +- WickedEngine/wiTextureHelper.cpp | 5 - WickedEngine/wiVersion.cpp | 4 +- WickedEngine/wiWidget.cpp | 32 +- appveyor.yml | 2 +- credits.txt | 1 + 238 files changed, 7025 insertions(+), 11690 deletions(-) delete mode 100644 WickedEngine/d3dcompiler_47.dll delete mode 100644 WickedEngine/shaders/ShaderInterop_Paint.h delete mode 100644 WickedEngine/shaders/ShaderInterop_Skinning.h create mode 100644 WickedEngine/shaders/ShaderInterop_SurfelGI.h delete mode 100644 WickedEngine/shaders/ShaderInterop_Utility.h delete mode 100644 WickedEngine/shaders/imagePS_backgroundblur.hlsl delete mode 100644 WickedEngine/shaders/imagePS_backgroundblur_masked.hlsl delete mode 100644 WickedEngine/shaders/imagePS_masked.hlsl delete mode 100644 WickedEngine/shaders/imagePS_separatenormalmap.hlsl delete mode 100644 WickedEngine/shaders/imagePS_separatenormalmap_bicubic.hlsl delete mode 100644 WickedEngine/shaders/lineardepthCS.hlsl delete mode 100644 WickedEngine/shaders/skinningCS_LDS.hlsl delete mode 100644 WickedEngine/shaders/skyPS_velocity.hlsl create mode 100644 WickedEngine/shaders/surfel_binningCS.hlsl create mode 100644 WickedEngine/shaders/surfel_coverageCS.hlsl create mode 100644 WickedEngine/shaders/surfel_gridoffsetsCS.hlsl create mode 100644 WickedEngine/shaders/surfel_gridresetCS.hlsl create mode 100644 WickedEngine/shaders/surfel_indirectprepareCS.hlsl create mode 100644 WickedEngine/shaders/surfel_raytraceCS.hlsl create mode 100644 WickedEngine/shaders/surfel_raytraceCS_rtapi.hlsl create mode 100644 WickedEngine/shaders/surfel_shadeCS.hlsl create mode 100644 WickedEngine/shaders/surfel_updateCS.hlsl create mode 100644 WickedEngine/shaders/visibility_resolveCS.hlsl create mode 100644 WickedEngine/shaders/visibility_resolveCS_MSAA.hlsl delete mode 100644 WickedEngine/wiGraphicsDevice_DX11.cpp delete mode 100644 WickedEngine/wiGraphicsDevice_DX11.h delete mode 100644 WickedEngine/wiGraphicsDevice_SharedInternals.h diff --git a/.github/workflows/build-nightly.yml b/.github/workflows/build-nightly.yml index c4ddcd18c..01661b827 100644 --- a/.github/workflows/build-nightly.yml +++ b/.github/workflows/build-nightly.yml @@ -18,7 +18,7 @@ jobs: run: | "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/MSBuild/Current/Bin/MSBuild.exe" WickedEngine.sln /t:OfflineShaderCompiler /m /p:Configuration=Release /p:Platform=x64 cd "WickedEngine" - "../BUILD/x64/Release/OfflineShaderCompiler/OfflineShaderCompiler.exe" hlsl5 hlsl6 spirv shaderdump + "../BUILD/x64/Release/OfflineShaderCompiler/OfflineShaderCompiler.exe" hlsl6 spirv shaderdump cd .. "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/MSBuild/Current/Bin/MSBuild.exe" WickedEngine.sln /t:rebuild /m /p:Configuration=Release /p:Platform=x64 diff --git a/.github/workflows/build-pr.yml b/.github/workflows/build-pr.yml index 16321ecf0..351dca698 100644 --- a/.github/workflows/build-pr.yml +++ b/.github/workflows/build-pr.yml @@ -17,7 +17,7 @@ jobs: run: | "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/MSBuild/Current/Bin/MSBuild.exe" WickedEngine.sln /t:OfflineShaderCompiler /m /p:Configuration=Release /p:Platform=x64 cd "WickedEngine" - "../BUILD/x64/Release/OfflineShaderCompiler/OfflineShaderCompiler.exe" hlsl5 hlsl6 spirv shaderdump + "../BUILD/x64/Release/OfflineShaderCompiler/OfflineShaderCompiler.exe" hlsl6 spirv shaderdump cd .. "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/MSBuild/Current/Bin/MSBuild.exe" WickedEngine.sln /t:rebuild /m /p:Configuration=Release /p:Platform=x64 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index daa6516a4..9cb4b69ed 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -18,7 +18,7 @@ jobs: run: | "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/MSBuild/Current/Bin/MSBuild.exe" WickedEngine.sln /t:OfflineShaderCompiler /m /p:Configuration=Release /p:Platform=x64 cd "WickedEngine" - "../BUILD/x64/Release/OfflineShaderCompiler/OfflineShaderCompiler.exe" hlsl5 hlsl6 spirv shaderdump + "../BUILD/x64/Release/OfflineShaderCompiler/OfflineShaderCompiler.exe" hlsl6 spirv shaderdump cd .. "C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/MSBuild/Current/Bin/MSBuild.exe" WickedEngine.sln /t:rebuild /m /p:Configuration=Release /p:Platform=x64 diff --git a/Content/Documentation/WickedEngine-Documentation.md b/Content/Documentation/WickedEngine-Documentation.md index 6298799bc..8b1d8dabc 100644 --- a/Content/Documentation/WickedEngine-Documentation.md +++ b/Content/Documentation/WickedEngine-Documentation.md @@ -480,7 +480,7 @@ device->SubmitCommandLists(); // execute all of the above The `WaitCommandList()` function is a GPU wait operation, so it will not block CPU execution. Furthermore, it is not required to use this between two `CommandList`s that are on the same queue, because the synchronization between those is implicit. -Important: The `IMAGE_LAYOUT_SHADER_RESOURCE` and `BUFFER_STATE_SHADER_RESOURCE` states cannot be used on the compute queue. The device could convert these to `IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE` and `BUFFER_STATE_SHADER_RESOURCE_COMPUTE` respectively while issuing `Barrier()` commands. However, the starting resource state must be correctly specified, because those cannot be converted. Consider always choosing a `_SHADER_RESOURCE_COMPUTE` starting resource state if the resource is goig to be used in a compute queue, and transition them to regular `SHADER_RESOURCE` only before the resource is going to be used in a pixel shader. The graphics queue with compute commands doesn't have this limitation however. +Important: The `RESOURCE_STATE_SHADER_RESOURCE` state cannot be used on the compute queue. The device could convert these to `RESOURCE_STATE_SHADER_RESOURCE_COMPUTE` while issuing `Barrier()` commands. However, the starting resource state must be correctly specified, because those cannot be converted. Consider always choosing a `_SHADER_RESOURCE_COMPUTE` starting resource state if the resource is goig to be used in a compute queue, and transition them to regular `SHADER_RESOURCE` only before the resource is going to be used in a pixel shader. The graphics queue with compute commands doesn't have this limitation however. ##### Presenting to the screen To present to the screen (an operating system window), first create a SwapChain with the `CreateSwapChain()` function that will be associated with a window. The SwapChain acts as a special kind of [RenderPass](#render-passes), so there is a `BeginRenderPass()` function with an overload that accepts a SwapChain parameter instead of a RenderPass. Simply use this `BeginRenderPass()` and `EndRenderPass()` to draw to the SwapChain. The final presentation will happen when calling `SubmitCommandLists()`. @@ -505,14 +505,14 @@ After this, the user can bind the texture resource from the CPU side: ```cpp Texture myTexture; // after texture was created, etc: -device->BindResource(PS, myTexture, my_texture_bind_slot, cmd); +device->BindResource(myTexture, my_texture_bind_slot, cmd); ``` Other than this, resources like `Texture` can have different subresources, so an extra parameter can be specified to the `BindResources()` function called `subresource`: ```cpp Texture myTexture; // after texture was created, etc: -device->BindResource(PS, myTexture, my_texture_bind_slot, cmd, 42); +device->BindResource(myTexture, my_texture_bind_slot, cmd, 42); ``` By default, the `subresource` parameter is `-1`, which means that the entire resource will be bound. For more information about subresources, see the [Subresources](#subresources) section. @@ -536,7 +536,7 @@ Remarks: ##### Bindless resources -Some graphics API supports bindless resource management, this can greatly improve performance and removes resource binding constraints to allow great flexibility. This can be queried by `GraphicsDevice::CheckCapability()` and providing the `GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS` flag. If the device supports this feature, the function will return true. +Wicked Engine supports bindless resource management, this can greatly improve performance and removes resource binding constraints to allow great flexibility. Related functions to this feature: - `GetDescriptorIndex()` : returns an `int` that identifies the resource in bindless space. The queried resource can be a `Sampler` or a `GPUResource`. If the resource is not usable (for example if it was not created), then the function returns `-1`. **In this case, the shaders must not use the resource, but instead rely on dynamic branching to avoid it, because this would be undefined behaviour and could result in a GPU hang**. Otherwise, the index can be used by shaders to index into a descriptor heap. @@ -565,7 +565,7 @@ struct PushConstants int textureindex; }; PushConstants push; -push.materialIndex = device->GetDescriptorIndex(materialCB, CBV); +push.materialIndex = device->GetDescriptorIndex(materialCB, SRV); push.textureindex = device->GetDescriptorIndex(texture, SRV); device->PushConstants(&push, sizeof(push), cmd); ``` @@ -620,13 +620,13 @@ Defines how the texture contents are initialized at the start of the render pass - Store operation:
Defines how the texture contents are handled after the render pass ends. `STOREOP_STORE` means that the contents will be preserved. `STOREOP_DONTCARE` means that the contents won't be necessarily preserved, they are only temporarily valid within the duration of the render pass, which can save some memory bandwidth on some platforms (specifically tile based rendering architectures, like mobile GPUs). - Layout transition:
-Define the `intial_layout`, `subpass_layout` (only for `RENDERTARGET` or `DEPTH_STENCIL`) and `final_layout` members to have an implicit transition performed as part of the render pass, that works like an [IMAGE_BARRIER](#gpu-barriers), but can be more optimal. The `initial_layout` states the starting state of the resource. The resource will be transitioned from `initial_layout` to `subpass_layout` within the render pass. The `subpass_layout` states how the resource is accessed within the render pass. For `RENDERTARGET`, this must be `IMAGE_LAYOUT_RENDERTARGET`, for `DEPTH_STENCIL` type, it must be either `IMAGE_LAYOUT_DEPTHSTENCIL` or `IMAGE_LAYOUT_DEPTHSTENCIL_READONLY`. For `RESOLVE` type, the subpass_layout have no meaning, it is implicitly defined. At the end of the render pass, the resources will be transitioned from `subpass_layout` to `final_layout`. +Define the `intial_layout`, `subpass_layout` (only for `RENDERTARGET` or `DEPTH_STENCIL`) and `final_layout` members to have an implicit transition performed as part of the render pass, that works like an [IMAGE_BARRIER](#gpu-barriers), but can be more optimal. The `initial_layout` states the starting state of the resource. The resource will be transitioned from `initial_layout` to `subpass_layout` within the render pass. The `subpass_layout` states how the resource is accessed within the render pass. For `RENDERTARGET`, this must be `RESOURCE_STATE_RENDERTARGET`, for `DEPTH_STENCIL` type, it must be either `RESOURCE_STATE_DEPTHSTENCIL` or `RESOURCE_STATE_DEPTHSTENCIL_READONLY`. For `RESOLVE` type, the subpass_layout have no meaning, it is implicitly defined. At the end of the render pass, the resources will be transitioned from `subpass_layout` to `final_layout`. Notes: - When `RenderPassBegin()` is called, `RenderPassEnd()` must be called after on the same command list before the command list gets [submitted](#work-submission). - It is not allowed to call `CopyResource()`, `CopyTexture2D()`, etc. inside a render pass. - It is not allowed to call `Dispatch()` and `DispatchIndirect()` inside a render pass. -- It is not allowed to call `UpdateBuffer()` inside the render pass unless the buffer is `USAGE_DYNAMIC` and is a `BIND_CONSTANT_BUFFER`. +- It is not allowed to call `UpdateBuffer()` inside the render pass. ##### GPU Barriers `GPUBarrier`s can be used to state dependencies between GPU workloads. There are different kinds of barriers: @@ -634,7 +634,7 @@ Notes: - MEMORY_BARRIER
Memory barriers are used to wait for UAV writes to finish, or in other words to wait for shaders to finish that are writing to a BIND_UNORDERED_ACCESS resource. The `GPUBarrier::memory.resource` member is a pointer to the GPUResource to wait on. If it is nullptr, than the barrier means "wait for every UAV write that is in flight to finish". - IMAGE_BARRIER
-Image barriers are stating resource state transition for [textures](#textures). The most common use case for example is to transition from `IMAGE_LAYOUT_RENDERTARGET` to `IMAGE_LAYOUT_SHADER_RESOURCE`, which means that the [RenderPass](#render-passes) that writes to the texture as render target must finish before the barrier, and the texture can be used as a read only shader resource after the barrier. There are other cases that can be indicated using the `GPUBarrier::image.layout_before` and `GPUBarrier::image.layout_after` states. The `GPUBarrier::image.resource` is a pointer to the resource which will have its state changed. If the texture's `layout` (as part of the TextureDesc) is not `IMAGE_LAYOUT_SHADER_RESOURCE`, the layout must be transitioned to `IMAGE_LAYOUT_SHADER_RESOURCE` before binding as shader resource. The image layout can also be transitioned using a [RenderPass](#render-passes), which should be preferred to `GPUBarrier`s. +Image barriers are stating resource state transition for [textures](#textures). The most common use case for example is to transition from `RESOURCE_STATE_RENDERTARGET` to `RESOURCE_STATE_SHADER_RESOURCE`, which means that the [RenderPass](#render-passes) that writes to the texture as render target must finish before the barrier, and the texture can be used as a read only shader resource after the barrier. There are other cases that can be indicated using the `GPUBarrier::image.layout_before` and `GPUBarrier::image.layout_after` states. The `GPUBarrier::image.resource` is a pointer to the resource which will have its state changed. If the texture's `layout` (as part of the TextureDesc) is not `RESOURCE_STATE_SHADER_RESOURCE`, the layout must be transitioned to `RESOURCE_STATE_SHADER_RESOURCE` before binding as shader resource. The image layout can also be transitioned using a [RenderPass](#render-passes), which should be preferred to `GPUBarrier`s. - BUFFER_BARRIER
Similar to `IMAGE_BARRIER`, but for [GPU Buffer](#gpu-buffers) state transitions. @@ -663,11 +663,10 @@ Related topics: [Creating Resources](#creating-resources), [Destroying Resources Related topics: [Creating Resources](#creating-resources), [Destroying Resources](#destroying-resources), [Binding resources](#resource-binding), [Subresources](#subresources), [Updating GPU Buffers](#updating-gpu-buffers) ##### Updating GPU buffers -A common scenario is updating buffers, when the developer wants to make data visible from the CPU to the GPU. The simplest way is to use the `GraphicsDevice::UpdateBuffer()` function. To use this successfully, the buffer must have been created with a `Usage` that is either `USAGE_DEFAULT` or `USAGE_DYNAMIC`. The `USAGE_IMMUTABLE` buffers cannot be updated after having been created. If the `USAGE_DEFAULT` is in effect, the buffer updating can be heavier on the CPU, and introduce additional [GPUBarriers](#gpu-barriers), but they can have superior GPU read performance, or can be writable by the GPU. On the other hand, `USAGE_DYNAMIC` type buffers will be lighter weight on the CPU side, but they could have worse GPU performance. If `USAGE_DYNAMIC` was specified, the buffer must also have been created with `CPUAccessFlags` member of the `GPUBufferDesc` that contains the value `CPU_ACCESS_WRITE` in order to be successfully updated. - -`GraphicsDevice::UpdateBuffer()` function can either take the dataSize parameter, or if it is left as default, the `GPUBufferDesc::ByteWidth` (that was specified at buffer creation time) number of bytes will be read from the `data` parameter and uploaded to the buffer. - -An other case is to dynamically allocate a temporary buffer using the `GraphicsDevice::AllocateGPU()` function. The developer has to specify the amount of space that needs to be allocated, and the function will return a `GPUAllocation` struct that has a `buffer` member that can be used for [resource binding](#resource-binding), a `data` pointer member that the application can write into, and an offset value, that indicates an offset that the new data will start from in the temporary buffer. Buffers that were allocated like this can be only used as index buffers, vertex buffers, instance buffers, or raw buffers. Attempting to use these as constant buffers, structured buffers, or typed buffers is not supported. +A `GPUBuffer`'s `Usage` parameter specifies how the buffer memory is accessed. +- `USAGE_DEFAULT`: The buffer memory is visible to the GPU but not the CPU. This means that it will observe maximum GPU performance, but special care needs to be taken to write the buffer contents. The GPU could write the memory from a shader or copy operation for example. You can also use the `UpdateBuffer()` function to update such a buffer from CPU (which uses a GPU copy). +- `USAGE_UPLOAD`: The buffer can be written by the CPU and read by the GPU. Once such a `GPUBuffer` was created, it's memory is persistently mapped for CPU access, and can be accessed through the `GPUResource::mapped_data` pointer. It's perfect to update a `USAGE_DEFAULT` buffer from this by first filling the `USAGE_UPLOAD` buffer from the CPU, then let the GPU copy its contents to the `USAGE_DEFAULT` buffer with a shader or copy operation. +- `USAGE_READBACK`: The buffer can be written by the GPU and the contents read by the CPU. The buffer memory is persistently mapped after creation, and accessible through the `GPUResource::mapped_data` pointer. ##### GPU Queries The `GPUQueryHeap` can be used to retrieve information from GPU to CPU. There are different query types: @@ -687,7 +686,7 @@ Binding a ray tracing pipeline state is required to dispatch ray tracing shaders Variable Rate Shading can be used to decrease shading quality while retaining depth testing accuracy. The shading rate can be set up in different ways: - `BindShadingRate()`: Set the shading rate for the following draw calls. The first parameter is the shading rate, which is by default `SHADING_RATE_1X1` (the best quality). The increasing enum values are standing for decreasing shading rates. -- Shading rate image: Set the shading rate for the screen via a tiled texture. The texture must be set as a RenderPassAttachment of `SHADING_RATE_SOURCE` type. The texture must be using the `FORMAT_R8_UINT` format. In each pixel, the texture contains the shading rate value for a tile of pixels (8x8, 16x16 or 32x32). The tile size can be queried via `GetVariableRateShadingTileSize()`. The shading rate values that the texture contains are not the raw values from `SHADING_RATE` enum, but they must be converted to values that are native to the graphics API used using the `WriteShadingRateValue()` function. The shading rate texture must be written with a compute shader and transitioned to `IMAGE_LAYOUT_SHADING_RATE_SOURCE` with a [GPUBarrier](#gpu-barriers) before setting it with `BindShadingRateImage()`. It is valid to set a `nullptr` instead of the texture, indicating that the shading rate is not specified by a texture. +- Shading rate image: Set the shading rate for the screen via a tiled texture. The texture must be set as a RenderPassAttachment of `SHADING_RATE_SOURCE` type. The texture must be using the `FORMAT_R8_UINT` format. In each pixel, the texture contains the shading rate value for a tile of pixels (8x8, 16x16 or 32x32). The tile size can be queried via `GetVariableRateShadingTileSize()`. The shading rate values that the texture contains are not the raw values from `SHADING_RATE` enum, but they must be converted to values that are native to the graphics API used using the `WriteShadingRateValue()` function. The shading rate texture must be written with a compute shader and transitioned to `RESOURCE_STATE_SHADING_RATE_SOURCE` with a [GPUBarrier](#gpu-barriers) before setting it with `BindShadingRateImage()`. It is valid to set a `nullptr` instead of the texture, indicating that the shading rate is not specified by a texture. - Or setting the shading rate from a vertex or geometry shader with the `SV_ShadingRate` system value semantic. The final shading rate will be determined from the above methods using the maximum shading rate (least detailed) which is applicable to the screen tile. In the future it might be considered to expose the operator to define this. @@ -696,8 +695,7 @@ To read more about variable rate shading, refer to the [DirectX specifications.] #### GraphicsDevice_DX11 -[[Header]](../../WickedEngine/wiGraphicsDevice_DX11.h) [[Cpp]](../../WickedEngine/wiGraphicsDevice_DX11.cpp) -DirectX11 implementation for rendering interface +The DirectX11 interface has been removed after version 0.56 #### GraphicsDevice_DX12 [[Header]](../../WickedEngine/wiGraphicsDevice_DX12.h) [[Cpp]](../../WickedEngine/wiGraphicsDevice_DX12.cpp) @@ -844,7 +842,7 @@ enum CBTYPE }; GPUBuffer buffers[CBTYPE_COUNT]; // this example array contains 3 elements //... -device->BindConstantBuffer(PS, &buffers[CBTYPE_MESH], 0, cmd); // makes it easy to reference an element +device->BindConstantBuffer(&buffers[CBTYPE_MESH], 0, cmd); // makes it easy to reference an element ``` This is widely used to make code straight forward and easy to add new objects, without needing to create additional declarations, except for the enum values. @@ -1544,8 +1542,6 @@ Shader Interop is used for declaring shared structures or values between C++ Eng [ShaderInterop_Raytracing.h](../WickedEngine/ShaderInterop_Raytracing.h)
[ShaderInterop_Renderer.h](../WickedEngine/ShaderInterop_Renderer.h)
[ShaderInterop_Skinning.h](../WickedEngine/ShaderInterop_Skinning.h)
-[ShaderInterop_Utility.h](../WickedEngine/ShaderInterop_Utility.h)
-[ShaderInterop_Vulkan.h](../WickedEngine/ShaderInterop_Vulkan.h)
The ShaderInterop also contains the resource macros to help share code between C++ and HLSL, and portability between shader compilers. Read more about macros in the [Shaders section](#shaders) ### Shader Compiler diff --git a/Content/models/hairparticle_torus.wiscene b/Content/models/hairparticle_torus.wiscene index 2f55f67afbe934afa57bbe3dceb09996df0787fd..2ede667ed02accc1a57d088a866d6b4f886178cc 100644 GIT binary patch literal 1221074 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

sHB$D= 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

?h9lGXKYCuf|0OzKO*HSJj}B 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�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ℑjOX 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Ð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 z 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

?8^rO*lJa> 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%0D{h?_T}hw+>G4gz->;ne)8J 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%0D_?A(nE6~_k8vY^`8>oF2~_3T zaF@kTGE^-_>OnaZOl3POua9py^$O+0yaY;{_PSM7aA6(`5XJU2P_%01*AkoGxrVev zeg85o@fxrT7Q`;DM*SD}GqI0TUD$O=>eQA`yG#DQ$%XKzWY*77KsQ{>wPDec(GU*A_aQ4n*l}qcWvm;9Z(EJs>DkB$&Bn=9AC3qv>$!8noOu(N$=y z1kU^S$MSK&0F_Po(_F<)PwHS7q&tw!jW3&WHr+-CMI2U@2vv_-E7C=a@)9C5os~W- zeo~Odx!zCJrKBiRgK{AJvJx!D9qFJ;Cv^=YauZZr_2z;AvCYHD24qzIdrKX7rNpO~ zI8l+A*HzTMxH@z}=qCZyAV1{$%Bfe!x2x;HVBH9WYCLm0PLY|G0MKl-^xM9Q#V?-u zjH^bww{3|Aw2U6bZK!?yCExnF>)VH+MC!L&IxN;-R+tQ5rUuog59EwZr{@)UhnvYR zA{zX8vkNv^tub@x0lzb{GMQ@$0n{B%)024X4hL=DZ0V5Q%S3y?CzuUjZq<)mXoIgVQ)<=)X%Zvqkd1!*@o z2@BR=y788w<6l3USb-z05{i3EHiN(`;j5!9mYKm_z>>&aFj)Do*iM2-Sz z2=yB%p=CGA^j*Tv(T}-6HL|BXmFKV~gpRMKkUx*CGC6eCV1P$;`o1@kc7O|Kv=s0t zg^3qA5HRDtrz@U7eSh<8x@$xZfeax2282hx@uFXAHf&8iDD>5PRMu~QoFE2AUj_!3 zoh5)Wo4Cn0!6bC&)$&CjK3p^+188|m26>9g;J{iX-ccq8JSA)d`y>JL$`4O@)(1dE zQ$U=V#S^^N(P?WL9Keg!K0ipL8=#1y!2zLzMTrYYVh{)2EFw;W84P`!$)X1v8)n&EYBDqn1vWzv}zY3_fxXSLW^SxHTr2n?MHkZXc37z<-dFN!egK zMLD(9_nK=h0wYWZp@FiOiN$3a9cwAd1}%Ys68&UYY=xFHFROvtE05+Zyr>z940DBq z_29UGY|M<*`7b!SQIA0LrnDEvX*lW|+bq=1R=V;%DY* zrh>pgE?G~0`Ip_Q8`(azZ}`^NrT@tzqJ*8_AIf?pgOsRXlm@&xro4Kt(i%yj-@0;; z2LYrbFFi-S)h`nNsbCV8KT+VnnEmuC`zSF3JUwOLPjaJyd_uB5f0_425erv1Fc!{S zSy%hOQBw&a(}nO>K7`P=rz$LcNu&JLnw80XjvhU+(H39B9J@yVd>Bzqg0K!@SOKH&!^7^5rz%M=LOLo!#;qFu9^CUN<<70< zH<_CsZ$$TeiHG8m82QQ!Uz+8X=}HFt5%_u%_n+@|yl}2?ujGxaA8RXHTb_6r`y9C0 z+3+gRzAM8!;QY|c;_~j~kt#om-gI~#8Et&dsJ&I8w>_`^@znBCc+>9UJH;Z_%9D7y zuBxAS(EXIR{4QGje=_*OxnG|CIdgNTk;9$+R3q&8l2h;b!dg` z<QbuJsyK;Cx@#hky#Pqk*^y5Ci$9AY|UF*hK( z*NQdbNRYU3K=GmkDm^X>UBJ_AS@QkX8Z4KjnU2QA1Gli*vM&m>Y%cgT4*GT%TBc_c z(Scb-96c6Thx7JEZ{L>(eyuuPId^AlSr$1@+z$6ZQHg@+t0z#S{q-xhIIa1weD+8q z>Q~a6zXm@b?kUJK3BJ%s;(@EHOUp(x9H}3%leuzRkkVI#{^Lqv9(u@!Z`aV>#Un%q zSd;~*w9d0dC{M}A2K967VCc1ul>}zhkukm~~Bxy$bA%y>}sD=?x z)vIvA`tb5a!Yhmt-!i=i#35Sv*;G7|#fX;!Wf!%Nq2{-k+GqJKvK(zFIGy}RT8TMA zsyZba!!<*A>oe>NLGbOMKO^wrVP>mQ<6gS_YtPMGO$uEYoBes|_n%Qp0`ug&8&Je)-n@wExWQ`-Uk+_KXY+*cHDe`l+lhI{4D4wYwxOM| zz{&0-?cHmPkh*gZ-{&F}^tU5Hx$5)Lq{XTMpj}Yc+RMhO5(K`cTMG2qdO=5|uBDAZk*II?lX# z^IhlT@)vtv{--2m&xaQRdwE(Kl#?|e>Ve!_;pTrr)FB8sP%yMgv#%CM-w}Q?bZVjq zhtvY%bS?HhRq`R>k*CmIg%3V%dveVHi@eC8?FO#iS2(7X0k;WC%Jl*aLg=j&n#uTv zkapY)h?X*ZjTJ-0JB~a*@#H5Ff=B3!W`MK`BAKWN#}P^NE=Dj#W7fj#$Dc@mjltI} zUX=y<^t5FcBDdneO!f!2(_oHNVh0<>@od zn&8LLokc&J#&GS}QYm=y0}6|oUH^^=;Zi*!Ju9#xlgG3n(16`6o@c4>IbS)-P7rS| zxE}Xk1CIQg^mqAe4i{qYS3ivXnL1jcw}6l@enX!0y8~-b z#tdV0c;)G~0eo|#;y|kEhSIZ$3i_9zGnrcE1WUH8v7@N3m6+gLJ~R`M14Ph!G+!yn zh~ntTl2t(#xcUQQ_6$`BF$1lbq0Bmx1|r}>$K&p~u#w*Uij9csGg@*=45it?p zEMYQYJHjZMQn$&3E1VHk)s^vS%~QZQmK`4iwH5CJ>VSGi31aC)cA}^O6AZ7na6lR* zb$8>n?r;O~=&wMDEPVSL)1h5mPO_`2ryh~J^^}qOMO?+to;?nD8i*a#=r31ng!UqF zBmfwgZ^Y$|sh{|-dYX|%368^Tt3^eD}gUE4yr!p4596-l_$qTuTS z(Mu#onBflMsNTMhuhC2?D2*gY$K-i$uHJdYJByTR$|qJHV2_CYZ+j0VqZR|R!g{)^ zd|#ifWn-?~e_#C9ttDDkaD$OxZNU0}kE=;7pSc!Kr3K)OI`-S?97km%yF-~P#oZu$ z+UF$_ru@Cqmkw=sn0@;oqE}N!3@`&pj&S>bY(qmX<{n|h%JYg{zR^NC&p2s=Nnz_; z*5%m;_w(N!#v-}5Yl_~@GNr|3S;Ocqoix{4zh>@CAl3BE zcJeu6{QJ)kLIQ&tupqU4CuI=bo_Gn91~gL!IX{*Vr~Wei2N5DOPln)(KR)%La2uZbT^|Sfi;9O! z@K-y8DrC@%Jdzz2+|vHoj*7oVD#9me>~2kfFn*wr__oaJS)2)<9eXsyZN&j@%}2-} zI9vZlyO_OaAr-+Lw}|J|H;|BD@fKijiefd09{8HO&ZmbFUUZvEf)|69)9*|4a0<6ODp@EOCl zSB%fmSj>#y_KVD$`wLvkex{15b02wM=6^eB^t&_-qF{+NNXq!gM(=}!=IdpQ%ii+= z`(ID`@NR&tj`NlFn?PidiBl?Tm2y-rL#3 zDa<3HKlv=9bPl+8ijnvA{Ruq947C)z3r{<;7P_t;-P^*N+J(H^V_|kNS;})K@Q^S( zlQR}TKpWaeau7tXTa1Xqd4OMo-X89%f>ih;xPA`JpiK9k20Cyt18XXM83)rP^v)rZ z7DbS1Jg$BQCfmzOQ3R^j3St<;A&lW#ju{~5T(0aj+D!r)C>MFnkG|TWVn482Ny?*) zO;x_S@bdr75J$>H=e`SY=8(>kZX+e5K&0gzSODjQqCD!b*cylq&NH~ZUJo#%K-_#J zQlh&}jef22wNOOBqxJgJAEW_oa` z{4GO?Pbr$Btf485jTtQdfb!3elxp|z)R!R^)mX*;)ALT)0})ExkXsp6a@OtA#llP~ za=F}=UvCPwj8sKiK0JGBWGatc6vs`(Q8zEs?oj?>C;661UDqeua#=KcE>NtsKQVhE z1u`w7YOtz;jhb9NCCJ{`Pkr!27A}m^J2(?;ch%}8fpoBTu94SV_xf=_g`emlK{#}C zJ=z|=XC2G+nhkNc5}eDbO?3_mR}dy#np_+?kgA-%g<5ls3=x5H`g?pd!FP7W z?B*WH<-*l5bQnXlzMD@~e0#R2pLJpndD>!v41vfLC&gzyiimvou{w<^017W}X(Sj) zSBxUi570j1s6RIPBFiWSc$fu)@lgLtk%-97UU5KxF6TuUR~FSruo4*EaQ4SatHXck zND#T7RxnQu7N2@?ZhqDx(H=@RW*!cIY81Aw-I{DlmIhnoW1v@ebq1()CwAdT{d^E{sBW}&&7A$d|IdU@&z{r;*tn( zv^+uGa{B1tbr?Uc-6v2@)=&@33~uO=UCE+t6QkN8=uSz)N?@IwdJI#e13HV8$kba_ z>`*1{>h*bl22!&RbNEenug`S^l*2$Djy|+PYFoA=ov~^WN8Noh6xItn zoO1dY{_P2xUNi-N8mg6{E(u3HlYa}-j$PMJ$j)_xA8|_omRN+Tt>rM} z-o571HjJ-cij$;2Mb{cN|6;`zAUEMsrayRI{*!)+Z7;Kd{X~FuNPszA$c6JLY`)JA zYi*(EZ+U}zq)PQ5qukZ86Lpy3o_D}` zq*q`nJD-!&Ks1C#jo_BgPuYV;CHog}i?p6jW#5tdq6@V(73NCU@rTy_{E>A8=`wN( ztsbTg?tY4YII3{&eRT&9&JKzO{c-g)TlzgpdA+Q9e&rUNEkAlOW$~EoCjeeod9(qC z-l(;Ve@p=qJI#bzBq};F+X+!`)>OCyf*JznYo84gB|mpRY~-0e^&;BwaV)igFDaX z-CJZSZuoHLMQyJSA`9e|aMaE(xbbo3*IXk7b1Skuk{z!$mndJ=w^d>$roMJPpX!mb zNSm%)e~z!4q0fia4NbgePU~&&Hn7|lwf1_cVMNP^KsANHiCIcptR)<#V*T`G2lE;f z5UCqEsDXS4Q8RAyih^XvE&Hg;JmD1sN-;Um8qSZK|8*87 zYN}zoTTh9hg%6pxQdDbQto{6GQqhWC0;cXM(-y@~o$wPX>4Qz{E=WdEtOgQ7mSLK* z*lylOAR|kCSaKVp4bVGIDl{=+wOore^Z=J4i6b-E6hp0&CXMKNg|q{RTJ!WULmVu9 zv0u6CVRn3I{9!r{RH8$pVDGmBZjn@*gVioqQ<4efCKW((*cQF^O;u{Y!<6=X1Dxl09^ z&51X!nVGDxw%jK9Qvm&21sics-eQ2z&t;R7y_?d+(9iT`wKC#N*n;(^{G#IpiA)O| z-M^=);k)6tGq;-g%KAV?aKtbNe-SlU-rtSnf(7tANL+~mZ*;woG-vP6uDXcz0~rLW zyKSE2yqS;yYS<3i=z(_@U3hd&?cG_y<5p*sLoFh|28Lg&x12_Ak*_+F_w>kBnNnMP6BXuIiiNF2|FGCmY+x zBA5|g0{n$jo%e2If}(&WrKiMuUn4ccA`t-T_2iF%F~v6tpr7_f=-Ph1t9-%}3YKp| zUm|)9sr7~nc^b4MhVn=fE;^Vc|IA}&hDP2)0fC^xHUd5ql2B2h{G&1fQ9Sj7Tuj_5 zMBTsQee+cQ5D}l6p!}aV4o##y|KXG>0^?Emf83E#SFP#ejh$>9I;W6#)-T}M;ZV+o zVJVEbffaj#qJQXN5o^vW0?}Qc3TEvW3($#zlhNWGsj3$LG}E0?GE|eB<%z8jXBj&D znq_F#FVZ5P`nVT2^_w`=P_8`Y3*nMh977SSKhloO8cIxDthfc-#u{`*^t5s0j#F@# zn971H0<;Q7Tl8+g4W5Pb{WKkbN>z2yU8oWU#3Ary5rI9KXOwvXus&ZhEC2gM^7AxBtJ=|^2XqMyvZ zyzuQ_{}CK{E4Lo%57@x%x%H^WgT~xHQ3hpZU>qQNm#q=`2%R7OT>q@745CcBunYoR zf~Dpyl9C?Q#MTZHR3`*jp{-M3aC`W4JOE9(9Y>Vo6%777~r?5uMM$4I+S@QcQ z+!c4uQvQ7GUU0e6R}%p#p*YI{B2%n!dAs@A2T;yuI%B=i2R$BGTaMOm%->>q1@-xz zj-VdPbteZuCZ9i|ZJxL1X?p4A1!Go3>ZKqr*uRce$)KP>_#cf(Ym&m50OFZ&xJ3g6 zcb#Yx0I{P4$C7c>&aqQ@rpU8+VrAN1adcV67;ihJikCu`Tbj#>&7beYV>=(E;;F%c zWFh5ss8HZkdZ?N(A8=7y*F421-;1l#SqtW2&q}-FZvfV17Q+ zd)@G8la<})OT&N~eC9*+5O|qY=^v{Ag1xOU@$Fn_=YA-uGeOSc)Z3Y1?F$u;%-eL` zGokkHOhj_8+mdz9uNx!f1?IA4>JAX>n}xdH+4foWJ^dIddP#j(h8N~Kg>2?dCH{xe z><6%7F+Q!)S{yZPXs3+K0k(7$r4#8RxkkFpJEIN5@Qg%j7l=>8ncM<$neQEvoBv() zHJwR}hTm(a1l&Vc!!dvekZVemWoap0VVVDt}ja>&|h5P}d^jkZS12e?*(jQt@@AA`{rC6nO zIGbOh17?IMWr;{4k-TetW~r6;VM5&>(@fAJROuEx3=a;QG<8~IU*b)SQbSZQ+CLDC z2*kmPy`H@FfKXLeh02ldNZ}=A%Lj}Bomxc}Y-^dB5*%^~XoWGsL`d)T~ zFnk#=qW@$FHKXr_CSlCE3CCy!`B_iimM|%EDfZfMFH6!l* zk8l*TrV(<>u;m6Q(ktNvkVGIIh96gkPZw0rHUD6blC&pIMdUo1jA!;a!0fA;SR!l$ z5H$kpdAtm539wG!OjjbhItL)SJxH#8l*Ub*W#v>S0Szz-yW+k&0+Re1ixd`=bw=(5ms=x}38KyMrf`j)rm)@clf`hZMSB#PSmWNmEX9s?quOFR#@7 zkaIi5L94^ywaDwE4SSs0jTu9{slbNwgae~Y@nogKeo^x zaAUb(8Z~qE{uy(o(LvkY^a77Bn>sfcKFG#ZKcphu+J(f?zAY^`IjOar=eW|KfpbY~ zhbPYIuEet~Tl6Tr?FY=kJn1v%BS__m(1Z5Cz57ky<0#6N6I8Z9W@agK z+7*L+WAtP-K>G%iCM*u3Dl-Ls8Y!P1Th8+iS%c_GWIPhg<4%K6Lkr^EigG%S6X=tW zdDoBJRq-$GHdEU8XadS4BaK@N!qT&XtTrxXs4{q&w3wH7L^R@E9cF<;>7+?K@02(wJ z9oZDJYJ#~LXxbFJ%ZyGt4Yuijk%+dmw5&!MUZfBsWVo?xOu2%AB?ho(mwP}j^(bu5 z101TRL5e$Q%nGR|+hSq;zAYm$)euG&*@WgWNAw83^D) z)9alOK0OjpMjTbRwl6Yor8xEHW=rLj?+!=OV~rovV@D=_ZN5cmhvAza0H3QCZR(t% z54D^2DUN+xrMe|%EC&yBg)-&n>5P&Sk#;7+)Iebn9~>p3sIY6a*q^ck^6z>9GXyZ} z7R+gajw2rUZEh*yvf&ze7k^J%SJO&xPii>n2R1*&2LUx>jsAI~GKmWUkPR^sl5eiL zemqnZZ3~A%m1udo&?t^!t2*oB9Vu(8rzvMM4BLo=7CivsC$CqiV7Ixqe~gryvHRA~ zI-S@K&n~E77o_H7#5N+t@K`$$_9%`!K{-928Z0gfBs6h=Qc*17`#~O^!#a5O67BSU zi>nK;7cqd5E2nlO-lC)fcQU5;J1;cQ5#WKiWVaI(M6DuC0KqE>cb~S2duY*e~;uMguD^4~AO~H|5K1gh!WY-yckt z+IYNLoW6eLC^oO7#tdYe?k{N72hsM&Y45Ul)#30?DN=`G?X*iAcBpu-l+Whl^r#*yM$7tlen*0e3#K#c*?MZe1ksIR&f{OEdh?v0CQ^s8c4gwWjqLNU|EiDr z^=P}Z7f<#*q&Hs&7q8@54`js#8fI7kIZO7(v(`&v3UI{Fe+phh^}Z7D$Ew5p5QhY7 z1iCAMdEIi4UWVsiBpSYL9@S)JUnDPnaF;?W1GtWiF@(;vWu0Q1LIXt2k1QD~^yEE| zdw=f2WZ_2~{gN>Vp#-S4P;!XTNF@@e8agD5TJY!!NAb5j1om*JBQko+CyKh)pZQqw za~N<2KXe~r2GL-B;%?;q#QI$>Q3@5V<@g97QT*s`UqbvXCcqUO9JLMCzlh1e+#APx z+JMP}X)=aetASGA7x1V=(9J5*D@@QNwTJsf7xe zOeZ4LkiJNY0>txe)rJ{(2h#g$FfweN2&VWK-@CELh118FKHSqnVNWeiOwfF1u{5p- z#SGzBxj((0J$_yayX}AK4=SZttCyd(-3jEut9#+x$nl1H)02A`T+J)B;7eP?)^6l3 z7hp$9^>EaWT+G;H&a1jFJ1Qb8iVL409EY5ai#@VY%cuJFc8qu= z<2s?AuX{N}99NtmJmcB2Sqo3~dtVA+@F7*+jFW{p*ZDpOAD4_m&XL5Ht8pVacp*sd zaei5ytX?ao6#od1g!%EP;y)$eH6n<`1Y`l35YENn*YY0DDm+JIYgy)5aVjL*RK)!s zP4697bN~O3KhHUxrgjuf85LTj(mDrGMuiAz*(D8>&^WKm1`3yq)Jdg`riL_}gA&r# z)=;$Tl*T#LIp_6#ocHJV`|rALw~NbhdOn|z$9*yiSD;uJxKP~e z4YWAJT?9*>wl-1%VlwmhM##DC9zO`)9T#o(;4#~H#z}|3({F13hVma-rd=v+Xc*{j z=N>)TAm-D%b>l9=n#q>e7CToMSWMxc+kI#v|#tX+#ncABtnDY z(_i%lEmmK%%p@?CFp3YITs{E#LQgQzC%j|zrb zN5Fi2DbUZD6DB|VlV%*L9ONS*G#MmgH?OKdR1rm-xblSrxyBVH#!&l6wuOhqBl-Gi zapddj?4v{UL>@ac+3n||atjnmC`UQOn{Ws&`~_HN4c?uZ#nb9(VviLN2db8~50?N` zXaRrV?ZD(u3w5Wn;QLyT?(I(35sE+>i*Zx*(#lO3i8>SF2%shc=Q|nbsEqozkk)vs zTp5NEp=0@wG!g+*|9^k^l^&ZGens3_yo(UA4Xr?)!$b|kyQ&mZ#5aiIna))1;98dP z^<^MiD6Aw0U%`K}j}t?Lt7n3UAtVk<0C`w6+)e%= z%lVrUp-5%kuh7k594y=3)9M;rOHHKl(v#71f@hAf8(7)3g0tmc&de@sc+>U}db8RU z)n0NlT*rZlDLQ|wtb*^by!;|4J!ttri!8<)tZ6E|n3!mPZI9)XwNvp8^|+E0Q4WfBJ09=yx)oSDXmMlfI#c9yUiD{w zx2Ma6DDV4#Yu5OQ)3V=QwxU=$q%i(&v(D|7LOr7-^rx4i$UiHhLh6^&Mu@aBRkUt7 zb4&KnPtA#lL`O$a__XOx)I`la`C=gjuzgMheYhVa);hhVYjvyw0s2CT=ol~WKxFeN zsIA))a6_#RYS|E#9{NU>8RANpt&bSlZi1|HtuKlrQ5WL6tGY=rwkM!M`$*HEWKrh9 zMKKc79-j>#z6cXRdnkZvru+qYU;B9W=C2DQ7RiHbYEnE$YbOG<^ODb#2{x?Qkyk<$ zKR7@?CrO3_DNZw&?i8%we`y$yel$QGiu43FgXR3JzT)lKutnv(qpm*@I-78Z$^)GiV*{dsC-nuy}KQu1{9_S+a%2m_Jc{7`D!CCq9nt4^>P|~Eh4CDV5n@| z6)JoV3Ds55o)Vd!A)g8U@lA-c!p>W7_JS59VR-yuT;h_pu@uL%X2YCVd!5ik81G{H z?tN%t+4*h)S&k24dCOkex8V6Khnva3p<~yA@F)I0!SNSGy%q@3$0`+i>FtV6bM6B& z=W!6d)!arJ!Z3^u&AaQG9>9Zl1-LXW1hTVL=;ea>!r=$R2!6D2srRo_5v9>uulYp5K(NN zIWlka$2Hh>s^lz+4dF^{?W z_YePhH#!M0g-%6EW+-S8G%BOye|aWY>>yB+9yDI(FsHeR>xGvsZ!2 zyWE}lz?!yx#hb&a-M_|Thz1K?4_~&B<1fPU+Erv^)Sp&;LvjgmbrjCZAccg}9t{mYPt7XhFMqs>U1FiV1eO6^2ZN?D!=d!jW` z{0c@dL`F4&oDgTbI^taO{&FDi%>}~5hHZ&>c8{S6&r5=;fX+IrxQOcW5WTtZyo`ha0N6@P0y{fZh$rP;+Bi zTnv*N7M6<5DMNe2Rog^P-SsH2)d9f)@A=azg8`VFw- z7om^ve3SzQYT&Xku)9no6n@&?1cbp~yTaS8Tt^ahvhhXwh@5#~=V(iwi1ER^_^A4+ zwcC$~U@4^(q;dCO<;2|e4m`VgQgI9~(ll$sEm;g1{CXRHL^B-f>w02V@y(%*;=dAP zbz!XhyL+S5^pOiw5QjQnI}4_xxE>Xe!L8FHX6Kt*73p+sd`5`sOWQulOz#Z}0`2O^d-hDsSY2P=)dtlWP8nz*Y@1~ALfJ8~$Hk|oD zj%%}ue_jn z+^gb$pnerLVMNeZuuVr9c=Spquf>CcNUsY4cZ~OD25-0}1OnmfBr%{4!M;6m8X9KIe(e#P6wX=uPu{LqRvJtlgAw`0(s0dms zFKAG$r~g47sUO(d!a0}}XrMjr7WM^*6NW7V?7kM3I#=E07HvSx8XCP&`fm6OhY`H& zvB2crr4A{j&b2MIjwCaLc(qOjdp>&Gcy}Oz%y-dKBB*Q0#6H*!p8-~In=60vDn$}X zZ(8!VjGCBm7jtD~qL-nIMMH~4?DsTrN8*l%!m`+)K2M7$&;6Q>eNEOxIZ_2j^E5o4S zmb)Q?3P=V_3)cY#=*ZApFGb)N922cTe$Gx+zAk%$@ALaab)l0t=o}wtp(vr*>>lgi>;#xCN$51{hcCwP}7EPW9Yy9osV zD&x6M7{crZf-^|W4+mEnsAp{)M%Ktf2Spj99$Lw%kS+-qVh?5QJQ>yVSqKz?>T@=W zR`6N>c|5*ipw2s8o|7SrYTIfe+`9YqxGRuGI}!C(SUggjq+Jk0N%Cl6m8RN3Kpv$* zTr33YX6#6DWED+$mKF(fdXB?ecX$Mi!Y(YI50{3lDb&By1#(0*u`WJ%ixqr9)E8Om?6ZAZ2}s(dHg`~s-@ zqHH8!@D{{Qu%UM|lRSuBQcO@pJCDsGB;Hg!K_ z$rGpnXpcec(ESaTZBNsKcXMhR{K)XuE=kCGashPLED=bLUsOkX`^q1wgs|SKKpl-^ z)tR@21mscNB`v}zNMT8-J7X0Y7K~D1D&$B^ zFC;$}fjSFND%^&OjmPUYKl_kIK?Zgs$I1YVS~p#~dm@)&^ae^rgRI zZ|BNm7$0HLv?Df+4f3^MVdyT)n&mm)qG*aJ?-%yMH!xF!OoaZ*{2xCo8W4TJJfs4&qz*raP=}sLdOg zSDVb$k1;V^b|54vB|4D9Z0KejHurYnE>J$d8zs60MKkqp< zE8kz*V*8s|-QJuJB|)F=LPn<) zj2l1{Y&SWsh?S_r2AV6{^G+Ou+Qk<`#=1dn*i!VZ#f}k4+Xqs&m+r6_0Ea-d7U;kc zg8wn~(3oC1rMV~6uVwd2a0*Ub6zxe?nN)8??L-V{I#rCdOZy!tPgbSsEk>L{%H}J( z;ANIViPB0)VWEJ8|NvrrY5AK8F9EgGaY`eIB~P5t@+gd+YOQd zwnXe0bq9p}cqTR@>nyt=XM|J3X0osPp* zy)WhLG$oVkU^I%GjsM`g@5fIE|9a)~pdELdbWpIzbR!lPWI1}%jg@4S@s04Pw5*?rY~vO4RwaX4rnmTV&e;B-3; zd35H@oXx!IYzJwcWn!PG*xL_B3 zu<%oB$23Dt6+Vu!On>h9*@_MGxVzdJRe+^m&u~K$jJ~hpjZYX|B?ld{&GsXXoXaD~T1XiHtZ6iG$mrFjpH3(+J`CWO{alUSFlJW0VzYzv-IT-qWDRjqQEXtBU zy(&KF_0wuor|PufO(`>D^W1Kob2PfzhGJ>-_$BGFGtw>NLyH(zO?xeM$#2GlUEl9S zYvn$=us6i_P~ptX^Vv|H*>^*8XLgmq^RIYio<~A=hctgkN}H&1KcvOq)8xLREra|y z%a)+KF`<`B@99LAES5x6|Gc22L1C=oX}yyJiNpW*i;RKbI|sz55vEZ@&0g@R$t3+I z#=f)(c;SVjwnm-h#9diE>0aW!l}#T!)(p-Nr)>u9ATO$10-ULBY+I0yfHmarob1*H z2GN-?UVD5vd_JL3>WsPnHGRX~Gu)e`B$+j8zBn6524~^kWlA56MNnSAgEGz~2i8-q z^N{ejDf!B`Tt0#M?({H46j3MXS*yt&TmEj4MMWe`ndS^I-UJtC!O~Pg@c_b}N^iRr z4;Tbr6eqC`WC&AJWIS>+C504{Egl@9Nl-r% zGz|GAo6zGrShFt*p+1E&_fm&Xvo$W^fdr3X3EXS33r*S>OGQIn>XMCe9s@pa8a3Sz6QAlOZ!}Itw{#^Yc zZ|WB9(9(Z7)@zd=-1E)$&mOtC_>1LUi^2i95Bwrmqb&DtQ)zP*1z9>#GrI=nxE$`l zBE>m4$$l2#qk39SJ1grsMp#@VB>Vo*eZ3xN@cCt4Ju9aStB#fq7&dfPSwJ!FBp=3%XM08E3 zO}&~wcm#4j)VBOQLateKgSY}EnI_%gD^}?Uc}k(k^8)k2Cu^F_?2laprl;=lr&$9a zu__~>2BFdSR+VSaVCWCYJ*9pi-u6hnfb7M#^D~cQX`=kOn8C1_ww=c8qH!QX=XvX* zrLa5gU6AnTcK}=;$)H`(biFpM3RweF=Rky^K33D5$SPduhlr*Pst3misKb%|Z4j3m zHnuoYRrq1Ok#g=$cB+nrs($572Ks`G2?`C${6Xe$j93pc8f#{dzU-7a=NIn;{|NdO?@I))P> zgZB|+a15R2gQww3sXSN&N+AXJqkO!zHSobf85*fI#1^vz|z z{fd8k$`8%Xn`(x3Pv?!k|Bzkl;OAjxePB|6Q%)Fx?Mc>foT&6F{)qMRKr|>N(}-lw zTb)cTTSP23LgIj|6%FS)-z0Xv-I@C~Y*1uvU}Lv5@?W406DIsBVMeD^>Je9LZVqgEEYe z%yEk(>7!O~vRyP0SO%!A3x%hq&F}s&(E#;)92{(Ku|tr@B#&aZV1Cta4w-LP=Cv%m zK-i!(+TFw-n8P97zy@b+*MO{1Q6~Sj@@+7bi6-%$cy!-}ArvsJ8&J0*g6fDcb5L)R zuxz{Us_5VdWi7Z*uH#{L%AY{^&G|9*u+pf2{jnLI=6^id@SqV&8tN%XDahVA>Np2V z2@Sqj;VyIJpEvtNo6{H}xDq!nuUr3{1w%CDFNXkp8(5+uYvk7kS{<8)-;&99FRzWG z#IgAz=vQ9W)6P;`%`0bDEi`bx|1~{sbt^bsh69(=oKP8FHHx1c!(F)WamBc_P5YA7 z>T8XzV$-=FF(Pr|aXoBeMRhD0_xGo^{M}m1i%G#-LFGB|_!Esi5@ay!@T=tHXz$RX#BzgF2)U0@XT9>$V4u2I^a#a(Hpp7s8?kuF%82Uv_EVM!A?y#ZP z%{!Xm?TLSI61wz(RdA({4T?=X^Mi4?!qKi7XDQKRk6`Q|23AF1jsiYwp<-v@@3t$2 zy%`25NkdC*p@f9xAJF)ucF+D6ifcP>{UXjWHs&vH6A*DH z$B0$b@W@c|$lc{DBOoE9N5lU&Yb0(HIyDj|yNAgJoSWn^^k8FE_i3vsfB4@%-3RPb z4!d(_;rQH6^E+P=9scL$-<0?B6RP{#f!uQwL)xg)Kfz!S{=xlpE@VaeYu>>xf zXJ<6|HPz6xlUVDJMafRVl4`y|sS^NXUlxzZH}7)K9+E~%E*`GiR*=z02ZdycFp;Jq zgljic5P!APvnSC&m?AB)H0?2Vb z=g4KL=)+xow2HpVM=hJ5@9}6KfXn&l#&%R=;Z(2&?+aW%{&PV6dCUr?3Npi%egnbV zi26NXK-+K14(&C<KnX$sLL`;7t6*R1`A>nf^)p}#|DRrI+(ztig zrd~J)dbv1SR|4`VJL;F95Z7bU?CqlhQ8-`)I;hAGAPenta83Bjj$Zv$!62djIjcq? z!WMDn^+U*#g%P*%)wwbTN^}T99Tz9y|2} z&?J=4U)#(1Yi4DYeY|p87{pb58Z6d5KFxrYB@PFC)L>peoI$<^Ge!glF2=o7fx-&Y zU+k#b&8tur?@09eOZy}NMv&Uecka>3fjgb%od)?qcSn=@Sjfr82Qs@CZd#|OiL5+^ zAydL#4d=!AC4En~oIxpF7PH!Kq+;W0_N_xEntt+MdEbFRL~!7-8M!&p zV8mQ~13a_(g?<2JdQ`U+2MX7nJCOh;fQe^%0!ZU($LQ44m>XSJKdM?A5S2Es+gx)+ z5@CC`wH}{p`R}hN?YbE&@{%8sEZW^$u=i(t&ZDH6tKk;l?l~h`9{2=cqqMkUY>$4q z)fW1_phO$AXBZXPN@8%kkcA6|?-YiQqa-Db4!g zO)b*cf>&N{@G8kDf#m$+gk`= z&V$!NF6!;6`>U$|s08_ojfSP)&upqVQJrUIX!!ur|I+lVT)#D2c05dICT}7NOmZhg zZ~R@^4_fNbWLG*ZjctbN&R@4E5M+_0qaVF1pI_^0pSNs$nAsBan|HX`b4KePgWb8j zEtjpAS5JG*Q@@l~+Nu7r!qN+6h?S_s31P1izp+44dBOd zeMlD){4o5(ZEh~XbdbLYx*Cpmz1v89HddVv5g&dVBWc?L(C%0RFA22dpd|XQ4d)pS ziJpWs4AVoU2u^$0n~zewX7Co<07R~00Yl$*H;{k=Edd7!VXH+zpS_YRrh)Zd-gXKi zP}25t*IIp^zdbmmCd&Uwz}~Fv#~rl|mVk)|o3SE7o0C&L z1GjND<~2S_XAhTN=P*t`xVuZ$ycK#hXgvwvZ<&2zMD=v*KF`B5oeSM#I>jbpd%p&k z*KG$}o~bTxygreL`B(oN2n+RgX}o`V=xtgAYeqt}-0CvSRbl$ImfMn~1$Jx#ad;}P@Wz|t@Oa0%evUR^2df3G)!{L`Dg z(KS0Bf|Mwc{5t_^g?EV&G#6Av@Khg^!gA*mQUcw5P!cAb06z5G}`c#Op> zM=!l^B4cH=Y`s&EGL;%#^HbT9uW04`t(ju-^WXE?vNwSNpHf7V*mLP7!=#eowyTW~ z&;I)i&B3=QDf0kb1TUwo<3}tkHOrBm9y;H@chGN0-t6#5`Q|qayISdjaZ+v*-5M(Z zvf8dI`QU<?>ko|88$x#-#1#w!bW!8O^#= ztkcz1W>;?u*-9Qn$1QqfG*0wz7ALIyy1SIDh%~b!7<;C*7oi`faf-x0t8Y4C$Aen% znB3c=JA^t{hu=Yj@*Pij^rBrIkhr18j09xb_Xqs<%XfiP;?=~vSQ(%5NP+GXvlxQzZ*Xct zcrcyUkpTsHp@Twu=^S@g&WhO%&`m{kt&QS>s^QY;9RB&>8TSUOa2}nA36ebApFAU> zZYx<7;<#|n*BG)_0L2g3Gza!D%&@&h2B#JT2l`G7;{ele@jLB>ZbEf{KYG$BEdHKP z;NK8o^5UW3v&!c10;44R=f&Ax+N%i%2@rwdEdkt$VfR#;&Geb>X>g%$fR@1(GJ7P> z$N%*lIS@a7x$NTRdt>*%{=zSA+@QrYe|VPd9VlN=gw7wNK6*h?Y5uPrXJC6)JX@%qzzz7B=nJxbbLj}n%@p@V0Da>xIE0vdIVaebqbxnGVcw6R#flbGZ#{(I{xKPB%VG|@23RbgW z0{SWLk9zD$YI!hfP3WOK82etjLOZ||KBKh!mlVq3)y$kI4%<=ZIPf}AH?%a3?FR`A zd8-q8Hb-(6pI+D}{2gRgYI^}9ys)KX`oHnaz;WmAv{beUfDKCt0@p_Z@{E^69@FZZ z0b6j$Uh#|I(d$mX#!-L8GT+JW@#+Lp7i%FZDp>|04@*vTpk=SOsQldK{1u$|a@ulk zXp{uTKHG{fKKVZ~>&uY2=0Dkm(yp{^J;F*LrkH$ZrPg>O_iWg*)>bL}Qbb!-Vd?&A z`7-+@kJ=gw8keFhJQ` zm>s{H*7>4aeUne~x zllOpvQ$-J5cK|_O?0HdU^#ve5BJP!pv`Y^^v2IuNyYFcXt#-B!Bx9obF)hmQy~S z7tiS|(1buBaS%4eX<|1>8VI8_PCb=?ojqjxWLw8tMWt%SG3yuX4ettpX~c1K)d8P+ zm+#<0E?SnzfE|ViL0DtndS@L`4;g`oSC)Y3dm~J)UcFB(RH_#rX*^TbHv=fZWohpt ziFLGPqcEs6wHJ!=mE^c(a(r3@C;jnKD5Ax8C>&wodmlzWit%;lW|PtFwO8*TqdE9Hq&My3JbSEuu?8Q;{R-UunRYu&A_NVZPPnrJd{}70D*ASItYauajO+4 z@0^gA@R_DSAFmpq?8$~^z)$xy=y+riC#8iRzwk(agJ)2b1v*8eCUNcNwHE|dJPkH| z?qp696g0#JXwdF}?3}=4F~6v{_y{A*wlkeJps~{Z7U!v~o9uav2wwek-Ckm3!vO_X zqe^Npq|AvZ?XC|3Bi5#e=4i>zQN1h4iJ4(pRpm4nIuJ|09Afm!xea*-b}dZ`Mn2?D zzJm!iIZw;ML7XcsgMO^N4q#lTpE<-B(10!6cpCn=95#ZN-lieUU zV57A%c;lfo*7re5ue!)*0UF7e`S_K8PHf@rNkbX70^zz|V;}AFg~hH0PhF8)kAul* z+c8&_Q$r^!eR3>al+nVbME`m@p*z1ObEc+hYTbm6jA!gWh-5oI< zGjpe})3XSv^06b75o-t(vO%(XDbZTEQ8M zlOXG}8FpGp5$0`YmdQ*T0l8!=^C^GQ08&svxnz$Yc+4@nmlmQ*P$8@7`*$|42ygf*=B5O}AfeitS zV@4tfqxmWTY?P(yK2~;e?+YDrPY1*)^BWbg+Rn~JXmm33AzlM|i#$@&KLOGpHfgW? z@!}lbiu<*MfqA3WJG862f*u;LLNsSqN2KqD~Pz9h>pOmaGB?t}fZ3h$l&V>gbAD$f1d_1_)7JWvus z#4TUvY6(o45p8NZ{KQ_9mO`a=J%(cV_IRcVL3c3;dBp=JX7I23!Pu2mig>=b5IRfS zq_5zaN!&%CIu!Ct`F#?X-!LC;3&J*TOGlc`VpN$%9W+AGAxd~kYuE1v&1GG)p3G+5 z=R-*_*5xk|k~26K!_oIqd^sZsZM($@0(p=DO#}20(!f%ZVC}KcJMs?jq{id+;pC`I zAe-*3dgfr7w6U4tvo%-% z3@UXx)LOdMI$0k124;++gHt;Qb#sTdxOZ&rNT71NQ+z7DRhCT;KzC`XjK>?BLo4{^ z1WZY9w(9DC1ZUChi0O$3l)*eYK6klRPH zYxMN?bJCgWOXiF2lCT;5p%X7jLB@*MgM#fb_@>G?Z5e$Vy^p@#tW{DG)7bAIqPc=w za`WWpRTHfHp6VaOv<=p=rm}T5@z?pa4AA%DLuQ7C#gv00{}zQxflG{A# z+WBQFMonGY8L&Vks&k&dgG9A}`(jV&=?m^AnCX2987lX`&ETC9{pb0>2xIKy_8)TH zt>cyw{r&q6oAXFOcFahjolp$}@RHA70@^u@N}~jv-|ovV6YW}E(-Z1{e-l+HkNq$e zv{G0F#SV0@Yd*U8$lVuWNoB1^WelRE_%D*iH81m6T!Z9fB1|LY8EaZdH zKgX>{1~%O*h?oLV24NfL6Hh{clbCTWe!3j69<%)#{5G35EoZ?&6q`LQg6?!L6F4fx zheJ=>zjz_cJSYzu0wh!la*n^E)0$StKf#o3CF-9L&0ahHZ45+XzxWP($}G;Rt?d9* z(BU5U9#Z)M&d|pD5feF7^wbF@0!ikZ~&=l^+V( zSIPc19vO8u*EfmPeJEvdB8(t+Us?P(SO028{dX0lMR*-6V^=*GIfXNh9_23(&{vx4W_b|z&jqBn``tE9x@-b+rkOJC)zh-Ml%uDsttpk+M{pf(P;}wO z1Sc8%-AJkRIHeFDGo$U|;uZZ#O151kU9!|$D`8XQ6ihM5C{XNxZ#^>zom2)4^?0(JLkdxHCxB}== zQS`M#2vD@4Cz@o0HHf2sNmb`7J&lKOP2ClTMt9?1J>rV+} z)XLwkYyKMV6e=sXSOE!>=c0ySqA!ub^Nh%7UC5Towvtek^n-x$)D2@|PaA=7U^ANm zR?>^TB||1FdS8*TwM-WhDFDTqVVnU=C7#wkv`1KSo&-YS<`{$lJOPp*x7A$B?}#ZR z7Gh25u4)j4xnej4hj2ROr}pawFlC2k?HKE=#D%u=(&aogz47ekWx9MPOV@A4i^q5& zs(zCqC~2(AIzcH-{q+%X=2@|+r8eGeF0M*WmJ8l(_qDF%+h3s504<+i+F40p9^XC( zQ$=NO42PciIGYsO))r--wfG32sZa<$L}Qz8eLDspp11RnuiKgznf#2a*}nEKXB{SC zoaSx&<*RGjw0AUplZ?D8_|aqo1?$3R|I#g zjK;@#QPb;%BuICl+HQib7#GSrF}NYNv)&wGIVWV$4l2elc8?%y)Z>c@BW(?;Ir1<_ z#t?+f)<#8bQG5o5Br%U<-*PQhre6SJ+RfO>k-B4L(ieNsbO0>&^fGoaX_vqFM_`wS zd^R+=IyWf8_Xlu2S2Gu(UqEdbHhJCVoa>9>u!&d%$R{8v_7Uzbj6jKk{0NWD&`#jf z;e(*(9}Y9#fsPNe0}jF5VVzkfYsEb^0Zjov!6RXay=d0p0|S_ucRzc?U~WbF^C@G1&@oXN~9K zg`IYfQE#737OJ`+hd=eDy{Z*MLaj49%XCzk>xSiW4OM#vMI!KIDxB8hn#48dP-}t7 zlYtg$$@s$`-p*eF4e#`Bq+4?=g*HbsIlrzgNO;S>?2dVyz7^Srx31DCg!l;croxn6 zs7B0ft0F3#S#Bqb+vEe2-y1ei;R^zi@1wyfYddr&88(foMTBXy=3E6#4(0rwdzzf+ zQ?ds@dU&+Gy1q=oU;+1f!h%7kcl~mY-0{gcVZ{7e5F`N$xg-n|3bTO2M;>nw6O?9Y zBBjFs@UBP9^KRy+4&un;>9`?K{X7Ol2e`_xAgh|Z&X&OZo@d!+k>D;fEQ=l=*~1FY z!^XlTFrRmCg^)^P7*!DwJq-3{pM&>=6}@#ykS@tfS-<)1XNs@gQh{El2sVSkov^s);5>4w9M9i$))BpA_Xf?}N``?!NIpt+4zHWPZ zq3LYJgQl|u-K^vU~fb-E0tJU?i&~jB_+#vp1`6~FGy;7GQ4|9VHxpg+?lo6ph@f-v zA@@HHJgUx9zMYd{nEkkWn%fucevo@`+XD#?R*e3J@R*z}0l$e*r zEqb$2MNUVNNBg}}DQ0S!FiLA!?`>ql^&Vc`59+}I_%pYx)bvfvZpj)SS1ma}++d1~ ztsa=e*_JOXB%(Ei@f`g#aM@5p!{2;yl0M%E++H2QBMIIkA4pWvTE2vU%09;<0908) zZBqa=9E1N@3kk}^{Q;`LAlDNSh2XNNo>D-!klIf&m0QB2U4s3BbDF|?iI~4uJB#eK zD`A+6i!j+U=71!CvvV93{o`jr+EV02x3$k%hQDsmZWD)Zfnwk)XKHgFqA=59{KL8g&B$mPJe-S6Trm@ z(qFzSC)oD3!94D_G~6XM-s60npQ~GSRw^4W`d&?aYhQ-1Ksf`dqqreXX~$RfR`oh> z+d2^pd2=7tug#g=1g(-a5RO!ZDx2YRtU&p|(vinDe^$(T@gQ7R)Zko@8wUdIor}Bj zGdi~8ZE5C8bD(0PjMf^{S##>U4K$qtGHpzK3Bo->v30*@j|CNO{nXej#V?IDU!iN~+H6J@(^|V+>0obDjw>PInx-w3bxM!YR=vs%EBa8EJ zbJVJOguDcKG&x#AD%3xxaD++L{>&W4Z=PO&bqR!Px3vHB`~+fyr0vMdSPJzIUa@rV zZE7cj^jdVv>nW>3Xz2}snEHqcdJ1Fxg=QUqDC}||15e{p&4MZN_(|V#^AA6L#0({Q zXf&=medX;&2X-r~+>lz&97K;b@7M)7@m@O0=oU@_!Ry72!vZW4KjX(7>Xdaw^aoQ^fmamysfec#A%RD{gs@| zW&%5rxOcV?QL~q7BkE&-D?|iH2~~h$qYn%TK)hEEzx%xi)}vIB{}T5=LKTx{dpqvj1wb?-`o{dQCDvaH!SMa?e2pnkly028=oq{ zG)mA|V%3}?e;6UT(I5b4oThZiJxNk731?*me8+=6hOL&|Yi?t|U*CnTc_(8Y&CIjD z%`)^2v!g+_=`~Zy>UtA>3NmcZb8ESTvdi&~$ZAM?L1n?d{mZ$-$K7O&^(}CvJ~2={ z>A0b1yWe~vvic7O3()RB8aEsjj(N?g(G0)4By?u??81u*aq^>aLgp2@pcHHy;9LJj6`~f%H5!B86?2rG}16%B=!Sf;#c204T*e7}Y+Os%!g$My-<1 z(uMD3-2={-%sMb40xGSpF&r;+PL@PKA6SqRv~usI_`lW>`3&Y25kdWdvbC?FH1WNgP_?N$O^X1p}a&B>g>F+cD zL3CYtGek1r+dlSnm#wPBwX*sB@0+?tBo-(mdFzN+?XTyx>W7EQQe@uM6PSkIMLD52 zzOsZ+!8g+@7Aj$`s&B@AxWVuzR z@JFT}j_v+Cw|2Uuldpb*wn&}#u9voL1|JFdL9qJ8mqxZWaK12Frl%a=&}DR?418k?0v(*628IR&I=CHZVVkJFA)~ z)71+vrJYE{>VelzR zXxLDP*t`l0*aq=!S&2md-BW5|T7D;ggx2^*(wv3QGep3&6OjoQP5#@C$@Mo9F9^VZ z;k-b3JOgflAWI_3CghCn?raxoSOqUYtLu4ZM=^&WlsZOK1>XN@O;2oj?j~f^U0&1- z1|yEv?rD*|wWX7C**eJJqx)N5h$!?-s_xq`bJ(J=i+3e4OIaY?j~4^-XJMfE*N0G;n_VEpH@MH}4+$zf zfdAgg3KT}Z0|SB40)K+>5*?%fHdxFNO?LZBYMT)ek0m7)va=OrAgEbVBU~6(Ur1Z|iJLjs=ks-Ruu{RI2}qc$|^q>xnU#{2+P;+yvIce3AHeyw#PVQP4l znxm~}Ud@V(l;{s6tj!F>FsDMVyo@tPQY~*I&7SY=q<;#%U_V2^02Xmv~{U%GhM(9p7>7nF9&BN0BAc$2A zT3CLL$4u1vJxOOB-@DHHX?o7(-*c5pCTpJxpow6L(iw7>)8Oimns2|zJt=8LC~n8k z%O*(ioRH?aG;}G|3r)`t2%GO99qNaQ@0jkV?D8D^%z+lc_Kt}Xmg%8nA>>ijADj;Z z8Jy(^gtCN@hQ+O2qC6@CHi)%Mm_LJdo{jkhwG$`lLaF6<055KOMPR;6Ct<-46d-Gk zx$z1MW(hnLP6iK$Q=E^JkY{MCJ}?>}V4{LXk%|^XMz)K3EZF%Yh>E|jI(Y$lj1 z2iTI6Q;x{s_wU|wiz1tTw<`h=J_CAKkR6YoEepC+7-}{j!*l;cYY*A3x!9B-Q*+Sa zrAt`F<6(EmdVr_YeijEzl>LZ=sYc!Wsvo^x)W5Nz^a5e;?QxR^0<5^}7!EOGjH!Cs zdE93j_aBE10(To5I0xawOk*<232m|5FiIIwnv=Y)A#fqaTRox(qqCRYo)1LueH0<{ zK%&!b2$i_SF)ybdn;|@P7SePJ1dqq(=BG$&m9K2ERc*?s^FYham@jX8ue2+idqUwW zeBNfoRzxW6^tAc$1PtQG%D3Z7XHEwndc#EMsS5IQswPu^AA=Z#B~X?M6v1rS6U7Vt ziM7o!QV<%G15Mw@sx=Th*nGzQ${S|jja{%W6m3xtDNW3zo&cIEx8$V^_E| zu09h?l+>;%`v;=UnZM7Q&HPU&Bc^wR0@@vks2@j`J!hFZb#DahikK=;L~8J5yO*4V z=qQRf>M2Vbf-fC9?!V24MTCJ(=w~o#k+Z$F0AGmjy=`wC`!^xGpT`SgIFAzz&iT#q zkG8!{FV1T+Ya^k!#8<=CPW9gyYt1tyyx_^>^p$UP*0O6~xKm#p4FoSGb0JNA?AvPp zf1L>u{3VF_Z8oX7afeVmMJ8zxBy8+3zZ5HfroP{AN@8nXlf$Fw`Ic?6M{6sVAnF^6 z_9mxdsOY@jHpABtLDp@?^QNDzZ0LuLYm+%rc2ibuO0PLV;v^KK2s!Vcq6j3KM)YOZSQL70~F(_c6nc)3up+Dk)^VCaWuWnsyAJzcXD6^qEU`0&?R+ z8n3FtM;vLlFRcLesf8YR=W&n*c{JLF-aG&me5GvK8Qeq!D=dqK-0DpbhJ7krNK^{* z*7~zzz+L4?TlHjYREXN~g`g3JehR0XD#*Z?bW`Q>UOOSyj4*^jI%yd~H&jkFy zROVp%K|Ve1Hb17xf{6z7%JDnV#lfpioQ>bv!?t?KyHf4=xiIqq)g^Oebh}vGOs#E^ ztwOI*Yf@#rQMQh1&#^=)0LmH(7aeck{V43}%`SEG`zfTc3ezK`3f0Loiu#Sr$f;fg z7k2yR@Gmp#_4>>XFF9G&*itc|e%uHuL6)q;_i}9z)A(pPy%(g>F0xM6Ij~!=l-bOP z-+RJs>O*0?rl7myaEuvYq3iV@q+yDn+K3iKCL+(d(!UjF3R3{Rqy9glzC0Yt_Wk>s z8M~|zg-8o3(yDATm7)|%A$w^dds&K@Q7WaP4N(ZC&6X|eOd^$pWTzQa#=e_j%-rue z&-Zs6?_bX!o)UB4*L9wsRsH-dT)?BvkpB>rq%T=$0i_;Ju6U&Aos#bMU>nX}P#?K= z9212%_FWrzgsf{4s($-cIo7G53453L*Ez$}cJzHlHlfwzrKmA<73~DksrWli*MU_! z!(!pVv|`8(*q(%$ZAGrj`N&nk-K{8hIO}}S9?s`S(DlM0;ZSNIETw7r$!o?YN|`&u^bcoE2Wpi!28e897#)%Ip0*Ja=||5NVL+rIZ2=w*KN z>u;KcfDdeEnCV4PrgPZBT0CW5Oc+^5w*kuF+>dB`x_*pe)3P5^Ahy)F>pEEgl-~xR z7FMoo{vVrpUje6lp3C)My&ovNpn#5Dh|yU;!*=nvQMjhCzGF(`ZEK$|PwS<;f&XZz z?J!e)w+x6x1g5S9Ja}F~XLGlUvh8;aJ}>RyX!!4GIuMZd(nEr>E+XflNL5NAUXEiP z?>3p)fc?~fD3}cm1BgO7m|4O5I;|JlW4UE`Hip2Mkh*!+v_w=3Y~zO6D2_e--h1Xq zT2E-lfLu!3mQCM%6IowtCHD~!1AqnBT8HCHJ>&@0ts~kvC&N>N_ePPC^!_tCNa467 z?p5Wz?PUPzT!E&$hQloqpWZ=I6I{zPkR^2!Me!o=lmsE^>nVNFVqreXLRL_cl4meP zRsknToe&<`{Rp8y)q4KAtx3#pD*0rEc+4P&S)9`b4ug@fGj`*6ZV=e{e&B%p4(PYs z3C*!$2%ygEvm(fh?uQuDz8p=!c#v0W1TM@9bj}ncy8sL@{0q-M;wcqlq2t)$PT!*Qs-0=xx9wga#(LOQ zMlc&LX2Mc!FzO6j-U_or&Tv(F{q7!~oEWld)rWnQ{yetpK?x{T6Dv zhz^CPBBbEr>-1i4!*rH5Ljr*O1psIDT^pg@+9;ZVCXV5RQM#N+P<1KcDibm?9c*(p zqsEWW1FUgIO&|GXPj!CKX$Ca%(U_pmbTA?*(K^H!h+6iQKkwauPP7&>m(eV5zML_w z0wRh1M%wlutZ$V^t_=o2yk;yZxCnRG+4E(aGITyY>?tMYoE>%gv)a_&b0CwFy9k9rY78}9L}6^IQUl&gSPWh20gMVRO=I&? zhz!dOZx%fR*-*A?e=twk>>x@+LN=5;4*jN+yRO@akixM_Rw;yLwu-usX+1l%GJax{ z{i61jf(P2PsJx}8*m<;>32vfwbnBy7` z2u#MbkjGX-6rC;e^XX@m^wzc;%ffg!&l>1R*6$dKjGtRz?J=|p0PG&w54)QF*-xQ& ze>ehmtQ`xQO=DprTW7dY?=RogOk#blIS$z}j2^y**;PAEH!)3#eWY~o#acBFwBYM? z8EoBLS$HHMPU>W9=j+n@tZkG7rlrM~R=^CAyU$XRlP|(Yh#~2EIlw^%h5oohwu&&a z(b!J2UNig#4-jtr`Q|og+U~OZWS%VFcl5z$PZo=nY3>ECH5>SEE`R?| zKx<2290fU)H$SrR9~?mnG6m8E6nnAfD=t+j{NimBzWp09bSPUOX!!fWesPJS)dijRfa`TnS7@o@uw zhzbNVG}Y2OfIYe!%zUP^H1{#kHN)_B_YrR!`ERbWFmQWS^) z;g}77vO=T@H<6IsY!mBEi2~%q8{csj+6@Fz>O|jj){O*qurQ?!_yy*Qhu$p}GJ^Mm zD}T1F_v2oi9bp*kLJTU17+|2vgFv4lBWJ+ge*6U`wsVoJbgEX2f>B}_9|pQ_WPjm@ z;CC(Q&vzcJhIkMpmjUMp(dJ~8OD{^@=!E=Xro9?y#CatJ%rjfH8=u(d8!_ zhSgC*4kxl>!3lPKr~WNHtIu@Nzo-!0W>uhtuX8h!^o~9wJ6Xy*qm(@UV}}#7h@Up) z7rN?S36}h(;e|Ux9j1h6g6rtC6A;VCknVBTjL2C?FvKE%4BLq40-x4t%u9@DMY$ok za^i45;_LJp{g5MEDPOvVmm=h)rjGn3Etfzk2K%wZ1y0?+%!oqlRY7EnO%#9qQ;jxBeeW2tDeLPqN@B(n~Z0)4voVdA# zhG|az$SPnjKtABpTu-`bR@`KID`@=8^eq3VSXMKf_%Cc~vOymD?ZUTZ+!x9{ruVmW z;z>nEG_DU+%dlCro=LQoNZllO;C@Wt3%7u0SNby^;2v%ay z38Afi9o-#Yvq}^t(3ha(ql!okq5h!Oe3&b+HF%1WFw6$H4?&K<#U?n>h4r`Ln2==I zX;1ogBiaau`025H36h^Cqfd2G zpXIKK?55!Suc{#%AciyoeKuDQp0n>~K)ZIplm`M`6A@Zv7bt7TLz(!#yP|9%87f+hieY-Aw51Bk=83OHcoqahruM?mIk! zbb=`zQ`OAHtfOhwQ~~NuDlui>8~hG(wYD^6^p7->xibFa?4+ehp39C+@QcG@oAZ<_+2ZFiSLh3#NXq^WU-u2$YEtR zwNE;*!0%IC%el3JAi|8{Wg>=gO_b5>u*a~e+F01_FRWUB;|Ml3rFbh;m1|oaKzUFL zrp!}+_d?RnBdXU-N;kP0D-P6Qb1(PkS5A8u@9%opgvrN9aW38}#|C#R2bDe#x6&Kl z@Cu&;pc5#imD`+u;{1dV;gmkjMid*p?Y$|$!CXH_G2jJ>cGwEG^$Czp{AtA=N;pG+|Tf~mI9 zNs+q=5+f1q#O@?u3`mO(j{vJP-86SPK*V(hG(+Ag5{dtWR?z=Kyq9~RUI=8o9ZzwZVhpI5qV-**Tnp7;$aiGlLu zPJ$sQyw<@I9Y;W6=dMY^vw2(1*ltYGJqQx29CXe<8Pke0>HuBs@UBroTjST>AW!GY~};VjPT?(9>r1Z8J3)6z+{X# zAibX;sN?b71Tm(*p6jZt3_k?AS={nKOOFd+^4>LST`i=N24nJ&S2~-Y_Vz^fE|^ zIR??&;gus7E=hW?@4rfL7jbveq`^V6H|w2Zg<9|cewigZUXmn7?9?z*%S zeN^fq`4;PC>?=%xJAz_hu^zTdN0;bHfR^5XI(WH4ApR(W-cEHm0+uBV1Hkb11mSx-5@C6v_2 zPcsQ#SBkonaSrkxhmpDPrTm}nOPSko(pedTf3hiOg(=12hAl$qQgL!X_?^#NTFv=% zgz7~$UaUKnt3g|k=SC6} z|E7#g9zs{y*NR$EDVfT^e$krS&Cc$7)9&WJ2F=aW$qQi=FWx zyZ{9nIkKoZtkWWL@BeaZH`@>EIT8f7F+p>Dz_jpLf%g0zegO<=L0=%;0HI^9oqkC3 z-G`K9hi4HCxVCJ|i8&|r|93=u8O;>)>Uggx!Xb>?ynmL{0;1pFzJIOdm5eOg2#EQw z1EHWRZ&GvO6jOo^_F;D0lP(t|9&Wo8+LBL=)4rUhk+eKyk)96;z}?i<#oSObS!{7t z-*`_PqTCJh=H>E2UtsbOY1w(vNjr?EHD#KD8I_*gx%jE>JFsA>ZN$soXDWE2IvIDi zSowWXL6gPg2TdQE%#8ClQ(>Z@rm{J=sW#i>30Ih=d*8LIs(U{7DIF9dtw2!28zcAV zU^7ybIBOD|3PXKt22NSb17WUB)}M?=q)_{@t1DKuOCq(OBcXCARRF)Zx0<;5ua%J! zH9z^lqADI)nMI%H{rTy<9(_2V$H=^>BTIn7>ZXkpL2{7-K;{bj@8lWB)k6(hKM9?-tS^27-YS86^ zaJvCgmeR4iE6{BLbR|<1b=%Ju>vWSXtA0;|qub>ilhnrJFW4hf)kW+Cw1eGg}e&qCiB2Q=LZ*%4x1FEAbd z*=CvF#>Rz)ec^K0<|`*OIOIeuhOI|=1mWD++9{U$NHghAF##24zkUps)eTo>QamQv z(`^>7u9(p=-};vMJse%AS((C~cQ07#qk#=`dzHq8r!c z4e86|rCZhF7RW?xS|%)mFrlm{-Hd~q%X!b~pKB?~P#8_yaXZ23-8lmnpKQ@w*4^9k ze+AJ<=(VPie^nGo$l4WmQa!x!qD0KJ{AB0(wxceew{O4u;kzpN(2;dh1~?>ifqj@? z`uZ3vaq)*GE)X0Jnbx#CRf)U>QAyN(ufWl8arc<)&UYMD=nTgPIsYLKehs3&!FunO zThqqcN;JMZ2>u&>1PvSl@4||*v9e_Eumh|!mM|UIezCt*e-zP-TyRkRXO;(7$DNFZ zhps9jh~yQjk6X>7ihwi7bdjLOz9%6}>s7X}GShW}422mcucQ{N3NJ(!OEQN#9>Cl$ ziZnj%@!osX_xt8l3^qd27h-A~LE`05==T=R3KW~`^hy^^IL4P;fFDbYaBn>bHz20B z@rp3gPZ{U~+LGmwOg)<_iN<=@xhHj;GXX*4%>Qhh;EI!A&LULD1tHp-xvxykiU0V? z4N6d5HX|H(QrltdWGk=ut&P>`Ve{i}$1MG+!YQv#D+NA?8onGuem7^+i%}%)pH1Xq z&3(R~@4tEG$DFjRRoK~x?bsa zA_XIqGMB4hO=n794fe5w1j@s5$XBDa<38<1x~Z3rH}&D$=Ywi)?}v7afKL{)0g?SG zo z4-Q%+jM@(V;)6O{|ALM23{tb_8YP^Yez=ShH4b4MGUQ0=F7*2?gs{P45wY`JStjUD z`Na**_gW;t>D5?6HGq>tT4zBRvh4Kj5NbaMj=`;n;}C#MCi&YYy=e{mmH^V-5}mtl z9GumK{2W@qU?>1)MbZTq#(Qj@WI(2X)QPiIVVC$WP#SbwW_A*BIl~f8JW>4XVm?h(XGA;t=*B=(+Zr99KchQr=MCGfx{i z_@yO>`JUWfcGmF)SSTKo7xr<_3ZuJm`)F*q^f}R5B0*_AJ+yF`{T_8Zo zyjzAWm%i-aUae<)Eu{?J&)oTuRl5A_jB1|cgrYQQJ&G|>LFV~HP%9XAJMHQ zvex#OsoJjgOI_(o@}6~}R(pskZMF&wCTH*az4mSEyW{1BeuX?cN*K{!5$}IkJNkoR zHl`)KN3{!vxa8Vx5h8GPne+&3NPHEltS|WV=S+sP<<0aP&`o=Uf1gXY*X{^6WtrwY zym8+E1yvp`{9y%!XPNN%zfB(cy2Hq&ZpV6lOrh7Mm&r|9SFc741MWY(AL%-=F6IX` z?7xXFbjAZ>XuMs2&9Mq6HRSqIT@d}5**fHVdA5`;fYfLw?oGr%0=h7wz<()>LJB2l z5JK<#bQNYq!k>z0A=huAk8#(Qp@~B=9Ww)(nu_iqMgmt`)1xtwMT?^6I5gx9bow72 zUFu7trID6u6VWILY4~`ly zi=9%0UFws?(F_Ga44#eqw+x)ia~MKb~s0Jg&cMV z-bO|0d#DS#n#-yOO!r`sV3h;dQ;A3FZ490Bc7*s>IJFApYB;1l)SqWB4d_d{lAEmE zT)Go__gB{#vdx;kj)1v=D*i>XjuMJ_ghr^jyb050{5 z>T#aJkn4*EY*|?GY(vnKhiY^4Z4wo;^BUx__R#nfw%54(a>!GRZz0^Jj&=udmohZ* zX4RuJ)BDR<`3*md3Ppyu)o+R`{LZPV;R3fQfM|}0SovK*DZM0sKof*1p)Vzlk|7KL zCorB%9+x0T$HD3zKb%@snmEb7?wByLlnix`AW$Cg<%r3{OL>ww;3{N=X>L(usq^R# z{dfvf3&L^L#tcf3j_Q-W`2E9qy}z9c@J}mqq);rLw2A~8nP%WStsIaH;J{5}b*QI8 zL3lKVU_#wPmBKZB#knF??Hrb+8s;%;%Ty6!6N9`=`$dCgq}uJynPr1#tj z!Magu^HjizE4C2rHB8IZ?9m%ch zC+c;SxW(VFQWx;ALJK(xDU$QX>s7`=0t_&B=l91Kc7ygvP#JySE3&fHC}pf8ZYZ&0 zaS}#9o)+&WmyV--KNUdzjw9WxlyBJpR1!<%DFOk4NVVZO7^~}^=t)DWEFB<nJbut@k|aA_Sl?!tgUy&`WdjiTpAYL(|B80@&&CmF@1+E^u%sGu54!zYbDbyYM=+y+#T=<>>yFc<8;9$CgCsn@a zcl6>DF1~@^*@uB$eJV|s5ybs$nW@(VH9Tdl@-O|(mr^hYcBpS1@;?NF@TC;8PMnn= zgk~hm$?^rlS~#^kB@l=F79i-~^I`Uv47~e$XwGzWnMICW3sWKNvXe z#vp1bGisFwswA7h`#G?=3w}Z3*fNxwaN*T&gP@e^-rvRuE=kC9hy(pDBpxrl&eA3z zorTp93cL!QeWjQudQKcCQzXsT9yPWX%Oby)SGRHK8j_ucWQOfH@b)MTC zIKmM5uy^23QWcX}*M64rutdLD$FPIjeoCzPz*FrOiES~U^<_^h_F8IF_Ult3sl;_E z=)ReiS|cJIS?bzTVz@Td=`h9Uj-i`rn_)1rQk+;d)gI_gWtk0)MTH>RT>NxU#0NM+l2YQW{!m*>hs82ULx?1j6Y@S;dlQ(ybz;Nr z49JNEAn7tewQL|B7aF#h_(R~dVk{H{B=XhKp# zPYkh`mA|LwaVSY=4zi<#O^{zs>)-AFRhujcAdDsIS`8hx3e(hi^|(ueh#Qc6XU`iQ7wHOu8?JYSKG4Nh|}#p{?4Tp#^(z{iAfFTmZdo8 zQ$>_q(vxO7WCzFaq@C*P{1J#2|Dl}@zIRGjrzzvrvJVB6 zh?Dkso!yGqn{K-#y^c5}0P z`Fpkua>X(wTo2)((8w3ZzMCefhElD0L|l3AeAWV#Bt}6n3!m8LgAEki;((W1^)77p zQrP`GsDRZ~vE;=^9pu;qjJn$s9tvj#!D|mAg9p2PAov=-}YBVp17D*iWhoVjq1NlqFKMb~>Ux{{$ zQXhTi$fKr7@}tnCq>>qJ(Si+kyUh+=eKU9?^qkoE^a;}RU4>I=UPg;I}8jW!hY8r3w)!L68o>@J$8j17*V(QR#=+)xo z4kmSgXW4#YSS8ynLH*Gk9@*QbSbnyeXZfuf|I9_i(uz7BcgsTGFCG3f=%T5$! zv2AUFw5jl8!-4B1?Si;7^P5-HMSBKWN4D*#F?DKP=g3e(?AO(>diyb*5XooObjFP% zETFrP<9SgFwQKiYnz;G6+yXw;9;Mz`*!C70LZIk<>k1?yi6V{mJuY@?toXYDDx0QG z-8W9f9yDPV$hCj^au$r@yCu;6k^`au=t<8;T?7ToG5~GjJS(=qZSRs3oxTtS8nyz5 z;w7khKn5vBHL^fk+Y2Pat^c2qZ@sM%(ICyWQNN3HGhDS+rTJwx4z6-R2GjBa(!DyK zJ#KVw{Ns+M;3wIv!c&nU{?roqhO14D*!#t&JPZ%PKn&a%2ZvYb9x2c{1@%V+xHc`0eJTz( z#~Q4b#?elzd~cQ<*g-bOxi|N#`Zt8ux8QEwC4bJdK@@Wu__x-)O=&t@yY#VFQZ*Lj zIotNw`={WGcMU`ZXALIQk#`P7)Ec(IFAPYmxKYmtH_t>lWN%g&2Vd zJe|n(xk(Hp)oJDF+gz370Ov>o7NdfXVbh;u&j#O2mq?!t zg&{uf@!iExgkCKnp0Ex{G8HDl#lO_5GQ9Lyv! z+*X@2SAKAvzv0b(_1nB{Q1orh#Wv`-f);pzT((FyAukaP$;ZmrrVP#_v)!m!723EZ zQNrh1NkL`2X3?O3GZQPQmy3L!@4LxQW#xPevqkkYe;EAc{@U}*dUoel5fXFP z9@U566MP71VgZI<|KD^bt?!K|0Z?l@Se|i?ho_P6=GHgBJG>kR01@ zWTV;0PX+Fu_39l=Jb{HR_mDXhZ}wD^rUDLsYwJ^0b#x*QHh9y;M+qK_3QWh)TUt%U4F2*UvRDiQ~_QBTCS^ z1Dg)%K2Mc@fwBqWHm8A=t*40vx$+-C5676RjD1NxprkQ7@rYiYNULqJ-$ zbHhKPeclR$C-wmNBu9HVDX~-xqVtp5JCGObZF)jRoKM6ULLD znWxWRuO92*DP-Q?o2hi`x}_w1cBw+>)P`1^ zyDW&?%~p}*ygXDWYa|$Ecy!}Vwrj6+42K)p~BFhgy30k7uT(`JHjk+frJY*xTE*a|1Q)R9`4Ao5dP{i<_7UBESE z1^~>ib8D^YajEp))x1iVeNbq}k?vFNtv545lp~kHpaU8F2vmT>Pju3&d>hol{zm+(=$8jx?EL~LkL^-` z(Np`CIK)w@<~gzsZ|ztTkP$tkv9z6ClM- zCN$OUyH1*}q9D90>5wp-z`eEQ$1Rt5{u0ntRKxXq<15y|R`#&^YtVTDbJF6X;EcS` z8f}K!D4y=2z2wrNw%PvDY{2V2#|H}Mrd?81Kof%+az_{gHFs{dn}t91t&?UY8ZTP3 zAlho;S78GSt{rP<;#4A^0hL0HI#vVj8!`YEV9Jr2s9R9#uw~I~O|sWOO`<5~lw-3( z5|U^KYVcW3sk~;pjg7!Yj-4ny{C59q19xhV@WB)l3Z?ovG=&fsJEfb+Vvsgd%s8}?S0rE2_rJbPJkjq5kg<`}IW0)^nu zU4|&Bj~mwtqG)QM1c=;^5BN2=Dp94_p9`LW&2D_r^vyhzYMk@~2R1&i<{;e5b%^0k zgjvV%>PkeTF}|Gx^P6*$4!^3~cV9XEH86#MT?PoC1+xDVHTL1f4c$0eNQw~5Gi;6j zj*6o-Zlx2C>NknM8@U;{3L&d*siD&O>)CO@WBjQmz*C%WL0aM|gkFtVekUIP8b{2E z9v6PsHh>i0UW;F2_3G7XT2_W9P>Q!_A5+KNoIu7^r4Q4(!1#rZ7A_5}P)GrD^FMU3Bi8O!*t z=&Uc+{GEP=x9ObMk!>&Fj|P<=-+sT?QSa{u^m6#+%FtP-;i*#;&w`D&4NRWBz7AlQ&@*aF+6FIm~&vfK5^a zn*6vBlF;M2T3K3dE#z_sB0E-+>|`;s@E3gB@5XC3YxV9GC#liac-Mk*ARWs9MT~34 z!zNlgej@RJEJZdEc3ar-Cm^@s`!wG=ueQ>jpUHAr8HY|@N3-Po3YkAEy)LRDI7Bma zQ1w z`LMqEYF1$5IABRy7-w7CLybRvaYGnUai;|rUu`iIe%VA)x_p5e9WF&e^sVrX`;4@!YgSFqhF)I!v ztg0yn*|zCe6!|SL$1UKcvjNAC+ja5Y!DBg@3*@%#ZFk3qMo(ig4HD?i+gaz=Zm+-c zdvhR&Glfg6mH;@@W64b%(ax!^Ql^@CmAbZXG4JtX6oe&jz+&uj`ooSS zb1a9cN(vsTt(9MPe8TCPcez}}luwcGW%sluONda|@zT2!?mtv+#x0W{ME?XDD{%V= zPjs3NgDE;kltN3ty$h_9>n5(a9HvMFh^Fe$rh7VUNF>cAQ49fOxENI9h~umYNd#+5 zXXHN!YA7YZD3?(;0?35pvNo>bC*e(AX!Yfl*S48f(^r=k@BTuBqL|nJ1}mkcLHKNe z6MbjpDu!;@KZkof)OqiS)aF%|#S|N)`yFy3C6q>mktV-*=xlZ7~_u_db zf6uH|R|^+Kso#t_PsgK2;^ia?8pGd&Ld^gvDzpOewboG=Nx1R9VCR7$oTQA(sR|M^ z1Lc{SGP&6~4UjJZ#*BuCGfrj-2`}k`ASHs_sG)NX0CB3L#=s^BO)7q~V`s4$Yq)=I z=ywvmdb~L(U7B$kUHk1;Su|{~;ugT^oIJbTAe);8^H6q#U}l-Ot6$4yZf$8>C4fYX z?Ps7Wx(_yvJHLX0;WWEiAB|k6dRyBh1kj=81-ZEmd>-oy_HQZKXYe}RzmYFo{m1jZA5A;t7esfj}-j#pK4XbEV`Nu`aLy9aE zMrukadJsteT5=P_hU+i?-uSho0hjtP%ECAUx(?RjP>A6h1Z6X{hGv|PJTK+-X{83K zmg{OaVd0PMmzwX+iI%JJRtB2-E`EoTH)ru;-k&|e#}o=dmr-2Pp!Do_b7gep&3$$` z9^rR_rpYCJ`M0Iyh2UNOfac2SXKH>+8{T0I_nmoME^|-hpwnVVTl@zkP1X`{{iAY! zA2Sk8Z@Dw(rMN>IhS0G%0L_U_l8yh>bA!BmA`IlrLa=@y#@-sxF})l*Wpp9mr&F(m zd{BmT!4uku=7F6wCcBJ*ot8dsei|ZrB`G+{L)lk?DB<}i6Vam4PeC{h1={2t409E7(=u)KnvSIaj^u4SUztO!JnnO z@9IE043#mnGvN+ZBD<6Dl=}D@APPBV#Bbt zFhzJgbY7(5rF6;4F{nYn`h_4Z7es&V7(`+I!A$waVreX@v&3|myleV-NW%w}!jXT1 z>mCRnTa0nf!)^|NFta!xiuSC9NiyVjifQh$9G-GhgWF5E1WxoAF8HcbMS}5>%#yQL z{$iu)m`Ku8;jW)QORvn($|P;HwVKo_(z+w*`6)aREX zS&oe&sL(en)$sfEY1ypiBmRdfKJHO+!Mb2bsC1%`MO$&FJ8dABdU(C5mvg`*+w+Ia_E ziV-jdnEiiYb0zjgD_0F75-Z7E^B@3D;BlUW(b{AOXSwuw9nk8ga%Ieb;u;PFGTlB0 zh^9Pen2u)d*&tG`jp2X^6V2JN zWMD(b(}#uKyawMsmPaT9;Dy0Gx3DvvpJ5}xA?AX-gK!blbo!X9H12Sov4ezrLznti zYWsg(1X0*$PdP9L_Ro}kcJHFABAQ*8=}#!IRpZssc9TINL_D68qGJU8cOl?D)<@FU zAR#GyE!1@G(HMV!#)EX@t3>}ANRjIce+&D=;pfG~UgXL(*FP|TzNdr-k_ha$n8SU-J_{T)U`LaV@ zo#{PSqWg^O|6vzCTgrnJG>DRcv&++qykD)aHwEXy{X6gXBhsZ6Br$a8$_8nBohtZf z9tcgOzbfE9Mr*rqHq}nocws` z(q1Z{nMxW#x@XUAMVfDMjen4c6Iy~Czo@7li3NVb8o{){^38g}HrYc!x=rR z2$|5<7(vv-YY1;XimZnB@k8na#zR}$E0MVg15krba^#kDk3iLHetwVp7!ur(!PIj+XXXs8xM=zpF|e(lk`F@t*Gm>_GJH5z7|;JwJ#Mvnh|D z_ZE_$K$2|B6HbWbY;WDp$M={4Np zg@Qm*us^HNFxW&1gQ^ebOt9WP0o;1ix_5DaCNOPFuP8#R}(Eo_4(vTlpE zm!DCSqyRtndS`0S(lvF9A;0CG#bws@O*OyLetys5z8cmSK%OuG)>&Jv$2xqp6#v0~b|mMFc`~yp%o99))O0jP~e0Z0vuD;$NRtF7B~i;_o+fzs?m0@vXXFq+8SCF-ov>hJs?neJ=fkV8rECMB%q`j z6|EbP>7a}ry+9_2F$X#aiiHZ&hv7a*0KF#AaHJ9boBCT!SL}kiPw;+B1#bfTz6_4` zs;3^>J}eZl5mPxlBvdDCjQHjoC`^e=xCLbu0iRAn9S)Ot9=cK@f07?&!l&A9+07f@ zwUAPleu~ee<_^1IdVH?7h<9vJ579;+6A2ry^!kk2+NZFD5knw#0Wu=XRKK%Srm&oc zxwTr1bgm>)7hr@@x0J}k4e&&r2X_y+k3i$Z{~JMK$W8eTy90ibdSGCQKKj5_orGw( zb}Uo%ov%`UR$NbIIbadbJr8Pdh%&1vT~Indf=G~F*NTII#(m6mc)y% zS1`l9dW@%ZiEs90VV#xvfsW~-aYilAv_n@kHa<2=rC$S^AP6O=VvHJ}-E9mmXbf#< zQh8uU{4AfdN_v_A$e9rgX3ouKxW=npXY4F zBT_eAzM4CsUEww&y083{X6omc?)K{DcpS0_V&vl z3gozSN{7g~r7O_{HVM5_I@U?(!$}g74#8qTK!U?3G*C}Qs0QN4x238u@LUUF zBzK|g7(^}6at^R(+wi%9@Cuh5hQo&Ryg~#Wj7G~OVSUu$4GPf0KVq&|9l?}~3@?aC zJE5Hi-EmBQX)fO*P5Qtd2PIW$FC2n6&8C0I^}TWJoPjd>C}<@FYy!OBez-<0(AQyB zX)^U)LDuK zyym&WBDA;-p`xN3QeIHqWG>sY8KjHOUoL^1nzn7$7JTC!uaB= z5FR9JaPM}Le`xDzzhi|5-!iBAZehH~*t1T1iW|gLCO0uQ<@--zv zslzWv;(4H!pK=O);oCH zP5>7fTFBZ=gZjoC9L9#A`4w3Du z4zps-E!(_jQY>(COHN~_T+-#$<8&YTC#auC9BTFU@sfjh z<5mejFc+ilyc2ZW9F4%>?4n_1@8PxjHt~aO$2XW~{j^gne!?QFiz1YyPoUgdkdm3Z zv-ofaNoF@+k|2hAz!^ub-Mh0i4)?+si{OO{kV-JCr{LjH%H2V+PjTOg#3qSWNSDc% zJ-~8L@(Ui0jQ(5Ur4r-VZkr#d|IueXpOv7FJ{aMQc zNrM5rlGRI)8FB`L@i&zSlcU0n9C@%hx!&>VUdz+i0pa~HWGi-TTFPDd3wnys#bF7g zyBde00sYPZlG*}CN*AJ?u5iJlazKYE<{mhv3If$+8XLJn)v-< zd`%N`Ph0M!L!HUq z@7H=(~S1 z(Lb@q@<2h9s>^tj|4WehV@LDKiIUbTO4rxD@zOn+?bGMAyEsAn(jLiCD*Gr>)~ckm znb?1;9J>OAQz_1wGnCKU4Rr=epY3;C>84g!_b*sPfdvYuamz}w9B(CfmbgL&a=Xx% z6g?az%_^0j32$oLSVX{=zx95dJDSaD;C5E-81l7 zip1q_aZ7o0V<4Piur!QJ8C&HK^Fy3bE67Z0U#U<&1PY^|`7MZ|O)jdQ4Hzwh2OpU6 zIKDYsu>)QM@o!*b_!!?WP?kuI#V< zJ$U|Q=-YLOw1IT=vVyxqr~gZ=YFOwIKq|mHw4v=H{L8}bm0R#vYrd-A)Sbj<93<+J zvlBfb1;BH6F!*4oJgF(n0d6u${w!NcpolIggB1j+qg>5MV$=V5ES>5OxI$=yg8VMT zeE)DXqWDH!c7JbGa*^t>FPS20qul@UozeydE>K_yhA87o1y-4<@T^@ASQHa72#@bC zp3tZLdwMCw&8k zL1XU=YcvlIp>8ka8f;W{E{t0SNhWI_;1KOv z(RG*Zu3K{zVA>m{1f;|oUCZCk(x1tS189*AK1nrgWY!%AW!D(JEUy*NdLpQzFDL#GL(kwpD`B#!}fKr@Q4F=n6tdMLpy4PjxjYpdWQ+t@i-Ok%2g-0+Uw8mZL zoneal^FN$tK4P%*Xh9GM0~QYRCE-Ag8%rHY0U zTsAO=4a-!AxHv1-P{qkoPsQlX;ozRd0Z9r>iC>;&_2nb{(%O4;Ikd5frE009 zUOJ?Y)R!QJH4qPW>6#36BR!GSq#+PLwEl6NIVo5?M-iz?(^X54Q)(E{0>NUPHR04r zn#!iO_fE2Lp?T>FuW=rsw7qc3gaVcQ9p~rB5+`U$ySEK};LjAs#B7%6^=M86p0alw z+Jv8Cum|T=8~3@ijT}X}Nh_x**H|~*4J179D3m_3MTCJ|RRa~FWkQhQ$isZ7c7>r< z0M@@!N`7l!R(p7{4L%bs(6UL>Hl(~evti|11#dh@8LU{+m<+1E8UZ%EKLKL7&K$AU z-IUdRKp~fE@z+p(*UdM|ZgCX*;V)~V$7{x=8Du_d3J5~li18#@Ib4&uBA3K!f!e($ z-##PJqD%<6QpgK*eL|r8!qIkv2!^}-Qc_NTGiWcl1b9@yQUx<3gUjQc9^P`#Lx2*oszZLntL{ zNp_RNk(8x`h>^;^W*M2~{$9@K@%#OEN++88zOVawU)SsPeB~}^qIfi@%GO8zIve;I zY<3Ifij;C7!7yV!pyo3$mg^LwEO*~v`$hfE ztq-JFKlbZ{17qExGga|Z9RWujv;BAluI)0oUE6JeeoYkZx}PMc@*PW;f3kMad<`R^ z{@L^&_yGHl1xaa^9u$P|iH!;)eHp>vds-$SLI&nA5frj3WG}!r@e?W`BFnpFP#h8< z?ilPbjI-=(5s=k}7%oV+xqYF{dTIDt_o>kP1jcAX$QlUNA|S%@yl_Guz77(xjlV@^ zrX-dfQ}0~TLW?2lE+CJ9V4oz8((%;uiMAH%+kP{Jkg_NN>Ftq6VSy1xrn+3d^!-}q z4=>}JXX-09B(Fi#+Ldklbf^nONo&zJJ!d==koTi?-}s>$Fc)S(4FZ@9C-oZ-4;2il zQagYZ3|C!vXxBJqK3r3?J4!+wteXm4EpRS*)g%t2O%pLYPDK}-Nod@p1^VT{4G4l` z0?)X?J-7Id4lw!M1|DwQej_ihdnMls+>EM!7kJWFn?+Or78XDYhuCzXI|V8k39^f2v~~f8M(g$8i(grwF}>a>IsZt z2%}-eRg5w3m(-+M_c^zmQoJpAJw4^g17CA4fyC>&LP-KampqN6oQnsEwI#3 zYs}-cT-!$r{N7MLcm&t+5ztsm=PUnW@_u2`h2Wyp^HsJj0W~*88edK#vTMO`sFy7F^{ig-@Lr7r&lAD`Y0kf)vc_6VStO#rYpA{W)`El7{-XzM8kUXoSQKV@P8E zb{_Rdmw=JIs@)|>*IV{oIpAH0&q?TbjTP&ef!p(w2GR(#Zs~k^d1`n^!JHUU3_F-% z&&rctadmkW@(oG9854u!)n1vxwOvhbH54FqvK1(Y(bB9@G$79GJkZ3vekbt7~M zx0qc!@3PUe;(M|WnQ^Q>Od$N z2*E*$2T?U1qM`!8Z_3NxuDd!86z5 zag8INwhXIppe2MeMso^qV16&!Cj!Tpewc2VUBRW4j&%&r){OmnyfpdcT;zd>rjc3P z1QIE1NI|8R1U*+6bf5oykq?NEX`W?5f@39HHrFQK`GCt@{b!loq>1>xUFywkxnaw? z0D2x}Lx~8TmGGp-K2xuBIjOR^d{z+ugm{)F16$*8rc+ozR}2-&(pvSO5$d zi0??$J;SoK{|VDj&<{j|Fq@REOYzE93h?6g5rm7JvabE>;JAn;57hBy(l__j-o{h$ z=o>aLkwKY(+YJz03H84L3bb9B3jD|cCQGcIiWs`tLz#0RM3YBpHEL7ena@!=85A8q zIkOQzar%LRS(e8fek#t)8$WVtIb_#vG4wV8k{sjow20Wt|1b^$9r1YZJitv3Ou*T2 z9FN6Q*zme9d}Gt?tQ67tmsA_;rGmjVUa0Ln`W531 zrC#=V2z?p%`s|B*dZTl8p$sW%2D2A22j$dyhdQ(&1VXuTTB%kEq1!*@fcjvLXOB=) zUKa4)E`q&ZKgPP-MR%q}T8%MxIi#8rNXi;PhUT8r@)D3(j>OY9qNL|SjN3aSV&rgWL^E;ur znOK?)#9v{wZqe3GDZNG-^SkHL(zH%9X^ehVqP}VunyYB$%)Na2NAc8D=iKq$A4b1# zeba%heuMA~^Dfc0Sorp{Y?t)r-mk~w!VqI`y&WvB4!^qGohr5o>@IoWVr|tq>p~2G zU*(3Dq$;#l0ZRciTJG>3U-eKfIWNd$>IvI{gd{m)H;L)t4PykzWJrz_LezHE4`(DS zdjQfWK4-rn0019xJmukg4f?SVP0R@KSl$&x4MBgJDr#F2u^KrBmo!AW@ROF%lV-A8C3z#*IX?Hi4(tYK`LD zi!ZzYt$LlPeX549*tNnE|Gu&JALffc@J!DsA#Gyd8t#locl20j**%i~y%YNu78>@CPZMJ)VI z@gt?nC=Xm}77}uXlA@y}dPD#TnkFZeuVWlbxsyc*^H0=tlEf*#5Y(~4j>!k%4VFM9 zsMWCEYl#?c>LD9P&5sV?FDp9Rc~N1PE|feUoI>a#b1x@U4qYFH^-g}>r<=Eos>V{^ zk0D1M1KOo%L<}2 zO81yc3(t&&b>NuVApauxBw{J5^G`%EB2u0^(_>MLkjClWmW_XKW-Fck`C{PaYF09;n35zWP)GnKZX+RM&cPIE;Ao*CLnEwGoIH$rvlgI ztK^fa&%fJnF|~>3cn9kv&+U&6+ZZVia+gg~%dlvC>{Q1`9{nGvH{+W(*qy~~{;|Nl zot!>S;DWrO!@lU)w)_+zPpDBv`Tp{5Whv>#9pMGeOkKgn@#r!LHhPxCDBAa(Vvehg z;X@G%muVN9*&#HZ=sxJwo|c^R8E^Ujzh4&_>8%)w8=!q~#+a33}f%A?5ES zi+1bM{_7J4gs0mPl_6l7QAf|zPOrn4PM3cqP+ia{>8B`GJ&6uIXC_&Ozq&a=&#p8; znO_CzTH-+_QSa^sFTP%T@uB7{8+)qmtoDfI`**f+h~d-p!i)OM%O2lEy5H4AWD<~d znayu7NRdIPv=2smx7G-$LC}la#s0huXQ~gZlc*JpymFhKdEwcwJQz4Oya+C$0z*9U zf6~T%8T2nl^Jd*QIA=EqM#!TV@tX+H{3EpP(VwflS7PgU7fJhX(6V6CMv{lQVgjq3 z(C=;pqz;t(SyZm{dQy~PD9_QPg=-X?Hlm+w$f{95{awe)f9|&_861Hl2j&HVM*W01 zPmI_>XRJlokInw@+JQ@(E`kW#(-)a1&&vYZ=K%WqOm~3q*J{$Ts8-^4Y>@eHP&&1o zp$q;u&!$Hk5L4YT*4gS^WK9)*Y>6N(u^sl7rpi23q#pVxMuhh=Wz+Ym>GX^L9T?UR zT-B8Hm~D!Z`g1(ajfAuuUilCCyWg?YbiVtI7e3|h;f0X?(dJM-gTwU)k>`{yD`M4*s|EK>^QXREj~X!RV+HI*YUSj7LR_V8-~NKTP(Lt;^3BU*G%IJoQ&6>J|SQ zX!1(*vFkJ&mICU3$)n^Q>%wA^J?K_Zc7IPVCT%}|k#LTldDbM!9eb7di~L&^+<}9{a>$Vr5lw zZ_!Jh_kXTQ)c@N~Qf~LKln3f>auPFGV#!(^%55v@&S$C>nQmr$k=(O3ZDgd%`>?Mt zgY|A|CHOy3tRf6tgAcf1W7&su`Dv?>_T!eoBc+SF%cL*I1bZ@r1CO#i!jvHm`=|8> z-CYPC|1Md>m6*Q~AWelC)eQR9V@we;BXGSBDC}sf&1SKK;Ql^zuiN-voTEd+UarGp z;m+8B@_$g|k3s^m>TOlsp}o)IUn_8~y8c+UGC=MIYtKpZ zHl@s4iy%e#S4pnp9j+w>UrA2=M0dRkh6p7@T?xA+aU3Ekxv->c3>~EhO?5jxod_&j zU{h+$d-P>EXTV3ay&K=e>ulyxsAyU(UeoOPa1x+l5Ws*e`ekbY9|nGrr8EOVPUkU7 z*^&y_y8pnM#6H!2F{u(d9EHuleKpJ^j|_j~hfJ$%#{nC)QKzX4B{lR}$Y29!hsT_f zdjBRQfa1Z(jR;9bDMK1W3EFjLR)Sm{Y@+|mFaA~F-l-tE5=}Wzs#%q}=H54A_-3Ax%J=WZ29sZCabA?W{9_Q3!wc zGYK%Pn6YwQzAnM+G4Y5#3B{Pk;{GiixhF8dty3JONqmw;t_FyfN0KNMMeEPPVckYn z8!4-tjY^d`V;!s|JTI}5j4394`n{2cm1=-`J_4d^Qh};6bZ{oE^WS-BLjDVwI8hVH zbiaYnZ=4`3NGBsJzpx!nWYBa;W0{mjun~lNPtG?&gopN?DFgeS^Y@?Xp$=m}&ws{4 zPhznA=B(}>#4eN5Mo6ewJd9ccKgs~Tv}ARG?+^nj-2k&MGe`*{Z3!Gl0_HA`R{X1` z`0!y9I3-GWF&jG0RG4_+uUjmo(?0eLJ{cpT0Ni$LINdEvYH+{8b-*qRiJ~R8Qi}?M zWAWl^^BcdHU-$!x4&)%DMT~`4qt6@BOY#IM|4Wa{DX>38W;_5Vp0;{HVuW&9+TL2O zrH;+u=k6X@+~cn@^|CgyIuWeXl5h%qH+MtH71-|aJL%-U(f13ZCa-u`+@Ls$9~=L) z28{I3<=NSggZ-!%`N`1yTzxf2O1<5$7PzE@M~QWhcTSHN$)=$Ptu2^tJ?qTyJH zG@rRE7sI>`nEkTYfQ__ELh71;*{JN0`@)2E3v2z+O;0kk9xfzeF%g3Y+s?r2>x5WG zM3g7bIBGY{E`6@?)yrNCFQW zc?x<9uu{SR8n5|lhKz;__|s(xS2OXt+uV=K;$io%BlqLBk|D_~W4XzC%cEt&$PPLT zJ#A$ioKc3xxvXk1;Sc{r+Fj{*N=vLNUN`U=hLkP#tnjN`YhAHxv5@m-vv5Q3kvlZ% zc&_ina8BG5%xZeItO$jxFnC$yo^W@aYWOiW&!l^u0!+t)IpztRyd{N;CmYX9As`nA zQS^_RLMrwxB1*-9BD;K>Is08eJIm(N!UF0*-w?MnwQ)RGp)nLcq9~BzH_DxY)5jbS zh7?L%m^3aAR$&ytJbhCyLmi3*f*hllAgUO}^<7_i{kzHx^$MlaLV8UTh6+AS{eF*U zmJHUW$>sg{-h3zcJ0%y6J)s@HuAeMxKH9$jy0)(4x=6ZOGQG|?Dz+^G`l+-iEQ^0S zr7gUUlCJy|ZYsxreFOQ#XXBq=sRIck_#!Swd1h)Wn=nO4gJr$tvaR8Qvq!9^>uWKu zy&^&P2e96+0-IOFl3?aA+)F5NefIU;wh2PuzLS%|3GwqEdkKk^pP#T3G^H|Pm|sp< z_q-O&I>1napz}w5eQM&dVdvm8>EtDO-sl8 zyR($=0O$4{o5LS8-AXjSaIL#uofuoMH{s)=c6r~ zJEOr*GUVya^Wn#zY4-1VC1Z2w+@oRCHRoOh*zrL-MYy5HfBf=oGVnK5PeM;Z>K z06sp%CtfrOzoz$z?53Bw&d%@s6S|I9a|hH193ZGnq5ieqvYEpyT6?G|1!10&IFuP` zZ5JD)3c653_+sJcpM%S;TO@GPY9i*l-q(y4uqc3-Stym`YQ4glE4qF-Zd%Rt23Kcd z#-Zs3PepEv8HLOBm8E{?Q~!qa2-~?9oi_Qrm3Q#fzhK}Yro|b8UW3RG>}j;XN7!03 zc+2_)tv$o4;}?mgi*N2D{uL>On{CLzsXP(Qog?`_un0k$2q0qIl<}clP+Rzg|8pU1 z@$|0DTU*{pqbu3S(FHT%uniHqLg=)tQ$FcnwPGD#rz$UD00WvfERd){ieZ^ICvLtw z*De5(cJ)7F-h=!^*1oRWU&#F-E9K=Z!%;=GTGK>Gnt6G1w)nBTs?eQWkN*$DW1ZIC z{!n6h;pO9)p?Cz|7rsb&Nd!^%F`5%NT1F0Zf|>wAWJZU`mvb?xV6~g?h8G_sLi{}> z3`sU-c(^EXNSi=#9rzKIre)-!XIK1TVei6`yc7S^J8x{45%k-<>KVKb-X9e3Ar)H@ zl-HsDG8ySZ(?>UH)106e&tsnh*6LGOyZR3zuSCy`Mmy8G^IhVX0?UcJrdHL z`5801vz6SQPQnN%LTf6s^T1(nidJ`>Z|yH#cys_FS2)EYZs`*?Gc$LF#=h=^K}7*m zk$?^m>gfOMN|%czQ9GqVt2!mn`a)N}<&>&mg$#=My~V&GWX4AZ_hr~$yIm>a4$H2H zXOwBp^*g+?O|G;>k5ye45+L)ERk_AMfZeZpWJKLat^a`?i&jO)Kh<-R`G zC}kAl+Sexr_OZ7IgfUS)&`{ex9SJ_VmO9RzTO>O^Q9Lh0MH0w0(vMcfmN9i`Vj{)*?_=U(L6bgMljou5-m>~&&4 z^7_|dl7BSpOl4w$$uRx6pXTq+Fw$O;wL~{y(?1cXZ;r#^1H6YbX9ck?D0IYh5_#@_;#~tuT&w` z!SBK;SwmSQZLp$e1O31|5gQ23+(_LzzXpyLg(pe;QJb-LRJX>T;9&T-;5m&IrAwQP z?xs7=?sthQR2PliM*ZGP*!gg(xulv8Jv(}qdNdG=>HB09U2DKMeygz2fN##F#ZZ*A za(xha0QOKl^TyZw6p|vhXg#1{g=ltpZ#5S!P-V?<6`}X&ZbArz$ zY$T%+9Q^KKOfP>D|2eoCAZV7eWS<2)wlftX@`Tcdx50^09AW-Ln6cASJVe2LAm~7*E zykG)J4(61%B_XV`zZeoO(Wh0|Ce%;a3)*Q($ulAhD}L}p6!N3#n$3_5pvRAz(mnu8 z2`$!~Piu|%$Md2ZVuS_|5zDG|?@6$Ai^4N7w@VZpLl!9g0f?%n<)Ch{iRk@V)S8^c z!HWfH+0vMvlbAeBp-)5&Eyqbz@+%MEUQ(~Uugaxxnao>uQ|g?!isC%+N|0_^z-9zF zZiE>VHS5BsohRp%zE6F@Kk^E=jCx8*K*#(jE)~$hn@G{{H=S*I6oQA=wLz#1t}F4W zG&qWjmsp4QJl?~@?aUIov_ud?WAlrSr51TG9EqZDLOvRZc1%Wan&Ji%1zAYG?6+7v z!L}Ga0YvB@%I@)Nv7K~RuvY_@!JhSnzEKDI;f-@brZv&V2cT?E3KaT*kt?p=cMC`# zoZoe*~EA?m^nKs;xp^6QL&J`qZP97<7tGzw4TPRFRe0UOxm6KN#?_rGixSZpI z2}4*!`J|e3#Q8*&zMmr{3O=8QhaCHAc4P9WE+CR2{SbhR$`=9f*D$gwePZt$%&5CL zlsWuz$yxyQ4O5~ZrefQBN9m8p$N zj?JHoPu78~-t>1n5pAkM=CZ&K|J?f|DCw2t=O}j3qdNi?7ae1ICf>HTmGDS=tM~`~ zrEHsK-K|sLHXF91XZqlgoj}XMHc23Laco9zt?`_doVc~vukQEc=v52;!C_z_Vb0jmrkqdp=mqOXe>!$if|lF(1d zh;@WAvS#BDAAt>4OrN_GIGUIkiZkr8bZiX$n<RKnTey8)(#sifyYeW$=EEgu1_|fL#s;b2_K!tdB zEMzV!nRKwb)E4lD;$F?WK0M!Y*C2m9z;5Rf?x9fN@ddvK(Klj?Z>KCcaI)0hv=3s` zWx>Sc_LJA(1A#Q)YIq4KM={rJCBbv_tU8KB9dQC4%Nt~955e2o)7M(4x+TLCn#PE$y zkrgOzkX#v@@Fol@*nk--3jMJnT`zqXX*=CTg;%v)0>-|UXBePI1i?oq?pKg1T^mI! z?R1b2mF2u~pOrqJI8406yV6MgHzD*?F2XthO?y&M|Mh5<>wJi@BtVF`O_>yfB|psv zEY30fBvfEWC$we^IqBNSJR2<73rmGN+aoo~3wn8%HuNk)+nRj7!nU!*(5+?XZ@O1F zDB)oEkdhzz@u=hnP%Js~YM#KWe?719fts2z5xY13qFhN6lD^MxS>WR*N#GOR0woaJ zkm;G;k%Ukn;qw7R13&F4elViKZ;%;L7Gq!M{@I0SM{7i}gmzHFkRTHqE+4!m6r1=t zK!QtD{RGF9_LZJPi0byiIRAuO&%NdoO)UYZUs(PMdfb$QlTaa7mG@%|bhzq@?}l-~ zJ`3g@+8n(yq5zCX^woO907QRQLmXoGEj(HFNT-3BqbpPDM_=cI^PDq3GhA!kWUKBB zjg}A36R;~u4t`PNzJx^(b>y&HK8ZFH-U|&9T#E0eKIcQ}w*)g>4S4c#GcTnv_38MY$Xtr^}E^@VnOl!{$xJI5Xa19tVHb zM3~{fG^}Pj=z?Kld_Z>uuV}Uxx#ztF{?+xfXgh9O8!nikSdNKj&@$IjHL9#GS?LJ&e>NUQUCe*q|t(l;j?R1@IGv z%o`*+MlRJPdB!b+o^>oL6@A6NoS935f7%~_GtlFiS&RiSKHyw~E=-BQxDfyT4EyC| z92C*Bp;KY6Zz_aki=lCP#Z3}+goyO+ii8}?i-jpKvfQ3Bdz% zR=2`d-p!a_)Ur*Svwo+}c?u)_jq(^*-dJq}V!ab#8oG8&zV-KjMLRMZ* zT$zmI?yKDghEBPeBy2}~8)xN#myDI1(ZSOifHzQzB$0Mi3;*=pc%~!Aucd7JN~Gfn z^80yj)1XxNIGp{~BP0kh3*hh18L^GSTL8}g17usfb$=eRQxZhVjzdm)Z1(3d0c4)r zIo0)?=}$FbmGX^C8CChNPlp<9$+top1uZAR#L`J`vB=?tF^lv8u_@qB}VE z#nMMo9;7}XHl-d13FI~RWh;{^qPd*`3R?<{{jx8P-6x_CFHZejdeAQh+&0j_##_rb z&2iP<;I0a{KrF_SV8=!<9w+fA>9aXQu&tyQHD8mQlExnlFNDMHp&?b224`NZ&Ws>{ z5k&>o8OCZ5o6ZvV)79Z~N4eVRgA&pLa}MWSm1uDnDo-4zn)~MIr5iO5>2{MwjboQ! z6!OK!DtDOxuezhZ%+Lrj;)X@1-L2h=VSyn^2wnXsS+3V>2ZABW1nIdLRf4)@noGd! zH_Vg9U6rrB^#2sBWM4P-a{f=}6kt>TT>B*$x*QaB7WGST`#>B*j((bZVhlbomxE+R ze&^^QSS+_6M8(&{Y6?PiF)9IpPU$k#))xHoJbbV|$neN#cEHiM)MeH`)`=YH)i?7Z za#kZ-E>oWfuN($c;@FG7d0&+zx}c>CL9tWdX@bZVY*-7#8-GErH3^CTNsfn>#N^R- zelnWbVGZh)00@G4eaIbxV1mk1HEy0_tdxhLfkNaJ{XWY#I-QJ!%8gp`j>$xyhEr8B zC5>|R+Y>K_XO}J6_$X*m47NCj?EIfOLC#W`(SBlSLf9N1(S!#+$(l1pj{_f1L`BWy z!L!KmBQnlL=$bV4-|OD|dVwhFA1Jm~V<<@0d5lRMn*3lfzl-4)WsrHRS85l?k+x2a z)r^#V)AUM2&zkG)L8m)Askj1fW((7u-~JXmmhGm`n}%UMJ+UlzsQL9{Myfdoeovsc}Is zTQ|8uy+gxgVe_hQ;#n=>sT9pn#XU_q=)*% zGw{@J^iM+Kcroec8yI~qW{WGw(+AF0X~sv0joqG>AW$pX=$FwsUv7&uo;jT+i>u;k z_hH9r#G*g#6VY8EGid?HqN==w24;$DnHbGv3Qud|DRtv!%TcnO1a#~smuZ1-nmZkg zUs<$KW)zIc@$AiUZ`YI_+=a8vY+9A~d>719MSUtmnDnz79dqj5F4f%hDWJ^?qBc1OA^)+V+i zKKTLq$jId1n~^MaT=e?T<-nmGNEq36DA0PWcJ#Xa0_~60{J9v@Uwv=ZTYgk%?Nq@g z39icGWMopJfYN`6uUl<*tiKMyHPV*}xBOgJtUYOGm=U@qq9qfd z-t0$9IxMfdzcTUi{I!<0L2r;LSA~RLkEcvd@bGbNV4?i!@;;%BJ_lC!+rGH><*e>T zhwf`f^R}}_7Y;w@={;A%+Wv9!soHMIL_TVew`e7+FVsR#GMc;_h@de#LMNmJE(m8R<`-$;k57w@4*N2Ujnzj7{xqyvPF48s;@rXZhW8neu!l> z#a;uZY2`&3=lss%2p=5;9;Fw}GcFykHLGO5&7BfPKE8!h4(G=pFIP^Eh>87nwfea{HDDXlnmB?}FCj++7lu&?}(mqg)ui0==6W ziaFUpUb?mD;l6AHHsb9KcMO|UWJh*Cp?q0PxL+x8jFgi%)c#(DNuIVwjQV9R z({gYnb*y9^!hDv6I*WrT7ktrA_$|S;-@W1T$}Za1>$+OnBXORh;oStDc6=SBMW|Bv zN)5TeGaWd#c!M}2c_ih>9Cgl{{;F(=l8@CdiOO+V)%cG;`QrGQhkt%gPmZxhd;<@1 zw2E=M&SqZcNqlHc;y8XBtW_{rZ!O|dl(=cG*40~cp!sytUSc-+bGVJy2Iv>KWPxet zx33|AcM>HEHN4Bkg`t?w72!#$bR~%?ab-V3*Si|xMen3-%Cy8jta1fJlfLPdHl<0f#Ev)>*l?NseM5HtG$0 zrKLc+kL`x^NoAEWh$dYQYj91;X3$DotX6MV=R-rGH_t2`OU|TcY2JXIaf+yIVt;nS z^u1mAkeK^g0L2D%vk9U;Vy(Lv0NzP^KIT_a{I;@lv@zNFvNb1$Eulfcj2q%RE9}3+ zse)DpLK%L3#3o=Xu^L({Dw1sDo66YV(;c#g$vc=YeCV%d`w-7nGZt z;qJ0P?3h@ZxugAZ-CFy(m|cHtHSPs&1=-Gv#t)fyPF|_gJ8v9N>9#j{gt)L1%Uo3X zbOl&ZCbIp7EB#%b$$*TDcpVZ;2<9X1<7Bj5Ob)7p`5!+Wjk5MfL3DZyQbFmp_&zDt z<(3=7C*0b5qT`4Cc~KG)vF_-H@%W7zum}9c*>lBt@(KvveSTL9a!>ZBsT60{cXqp9o zBlf)_L{u1+b3rIOJ$(TgDix})!c85)qeY;q^Lz!7KUU4G#2nmeacBXI4kR|+ZXOq%z_m6D^TUV%#p482t$+Xeumv<4 z;rC6jrSKD*aTq%M10k~%s?hf&61EPr8Fi|c`F;nWYVrkf6{EOG!;8Niq5W{?o}Z(H zUVX>%LxbTDK$84cpI?=id-^t03E)Xe+@Z2u+jKq?M>*KwDT{n2R%$DoeQ>lmPMwm2 z1`Yl^4I99knnm||a!V{(rZ2X#DPRSzqkQ>!WYaVAnwj}x%l=hoQDx7!bv~UR_r0`t zzr6;LC7!QF>SrYc!NyNmqL00)W`^%6?t>~3`(|b$KAHKw(8;Ps@g(b1Ed8v2@*$8e5U4)dEm?4 zOqq%NmGU4-uZtJ)i$rq6ebB%*xmss~FBa-L)nYC*T$qe@zE8bY8iTM21(Y%@#%I*z znB+nMTiv2a2?SvBO?~{QT)d#CHA-=AKeQE2S&&hp20_{uB@>ZI35ko=g2HL z2SD{`C8e#yiod4pdwVVO^>%*cu?d?Gh7NmIJ^Y;Z)#6-_58RQZ{b|PxOxL+Q7P;w% z-4z}Fn^sfO#?SC|pHk!Rf9}s!KrLQnM_AdY-_Ye}!YdxnOUr*mtlYhx6kbtT&%Bd* zGA81~AE{lui#N{+%cBbK5wSh=a<78ETjN1Br45vv zs%?SWaeC&ZvHjQbmP^wOiWJeie@?g!&T1}&r~2QUZrP(Nfm^RYxpL{I$L-cI>^J-Q z<~=xP9=b=CT5|zKN4rQtD6Maix#<~HBb zq9;F$dPyi=7;XKeu$)tQYW4^?-s>pXsZrhnN`FM6Spy+PAqFw77&jORpmRL{hHG{r z{QKY6I&M4`K*RA^;TRMPIBX0{BjtASfyaw1A_klwL;Hye8|H&-WE-pX27iN4Gzl%7 zm`h6}g7yyYH8|FyV&^6R&BJjH={y^2mXNJFt_QPA=JQ1{0(3`uebE;t*#W~3-xB&W zL7eFJK2TG~U{6mpaPi|27BhIL<=~I>=Pdf(=uF&f0Z@)&6Zmo6=vDlPo}n(yInH_5 zhMT?qNtVRtSh{3}dK~wI5S(rwd)-Z8_{$IRw$-m>3{y7kIX+2of%9LMmF?!;#G0um z3iEM-m+B1cl~LvbBJdeENsPsYVQ4I@?@eQ;$80q0=ve;7-ASJr1}mfU5#Oq&UIGmg zH?dj~(tvonF+<+`g1=4eC3E~DAqWx}0^xeS4K9~$^debuLIdG;oF_QA<*JPpe7Sk; zh&>4VAei%{1`!C}WCo#d8*Cjw?7%SEvU|*oXmAnLjZL_!BnCaO*)&c$_LeJyl&|e> z+#9ZmCoR`klZcv0i(RYQ_d%rN_x_VLiM@744T=g%uzg5953ki{ZrP!=F1jxoo8QbE zokX-*XPJcg&K$r)Q%$xnLtF_+90pa$R?Gd2D0=Ce1GX3a>%J|cww~d@t)Qhhf89vN z7JO$E4bT=FN&*bYdmziDSd5rf8(H}jRsuB@Lh8Qi#Pcq3})DMo3yfEgP{IGvhWM_;%#g8Uz?PuZXutxmaJ0 z+Gf|zBrF2`199x|n#}em9QedK_f$;fFbt zC4UON+`Z?DD7K>@8!^tGK9meuqLrIw=m}vJ7ub9FeWZE2P8}DGqIkn~Fg}o%(Yvtl zFyxwH#soXBg$O=Rk&f`>%ar-WB8%*#J#bShr=>1hzogCrGQ$N;1wKfh-HxJrpXEJ& zXBvBOqW2hDj;M;u)n10C5rV83MdZIZpGVYUjAfi&^$-z%kMwR#999fLVv!>KNlN$a zDHc5A0Vv`V(957t@Nh>jPbg;RS08yeqBCQ|S)oJ8>|kLRcs&Hn8;A<$2q{BShAkHVe7 z>HC`gW2fhoBHh+=jNq#xZ*aO|G0D}v?0+j)maVg`eOwN8I1;$;~er{1hSPWeub)lr@3L~{v_A49r&ygw@ubnde;HV^)*W>}L=D7#N%A&pw&$ha zJA5;HC!=1aF~oYF{keUe&n-UnfizJtI0n2XqVgo63O?ywe6^u}uZzKYE$Y5EIiFu! zFzfj`-@1!lS_^sr#H;xS4@nY7<9Dt%EF^)%nl`Ji$-Zzn_fGoqi&h0GZ=lWYIJ*Pl zV++nIq{0sW<{~qAbCpuxCDq;lk@E#2z-xW!nvv!nDS%uH);Fz(+2V_Nqk{D7E`tc< z436U(^QNq-SE`75g)0Zy*OjL*0ur*7nv;CCUxGKdroZfUo-^xcC*O+VaF7=*clmjs zncUrSg0{Qmqc3bS^-iTU8+^UBxl?^JM*M6hus)?g>3Ebh@|uVd>A!U3W&fS{FA_9^)Fx-n4I*vV zY0iydi{s94lcKHyiqpBkQ2+5lwk~&s|Dx0G-e{krVGo_mD#FhhwJ4bvhJO#KR|3+M zSf%ID(r-$4HD;+lrM??V5Ro-L*;KQacVY#o(JmDVnV9w&#tn7xGeB?{v#j3~cQ$77 zA!!xxNuUAuPi-p9w7`I2`igqTTm4!X>?DxHk)P-tVl2iCwg-OZhnax#&olh7uYr7a zpPw%0K%&}5Wkga^wh*e*VdMNsc-k`w;H9VzAhO7w)OqSctKqqt|aJ_(GNe@zX#wU z*W@K2YFKsj+p^gmk4RVRDi(Fgm}$@oR4a|5>1xY7xJk75v^ul}R|AL{kIx-G@^-Ws zlXT?1DP2wnsSC?;%rfz!MWAug{xCCr|Ai4HuVI+(37}}|Jbf)U?J!rY-DvSIq%6t4 z_;Z17X1v6V-G zU-FsJ9U$2H{8wx8$lnS@NhxoNkp@}1@M=3sR$Y+Lyvo^@N}B z5*;HF=j4!M$WDKhTW)LP;P!T(rd`H7z-w%)%%I{L@HvKK@@RXYpkDefa`AYe05bmd z4sVfJNv6(#fDxg~fLTk9wAk>w7c|W7X>S#beaBH(GKBF=wO(Y-9;kPRm(@-PQ4&yK zuLTsP1Ou+xGkg@3Nkr;*%gusE;hQ<`A)}7KgO(UP9&#Glil`ZjJC9H>SI}QyK>4Y} zNEr!z&*z4PJ{3SjIKKAP8)kgVS@NQ%ezsr>rQU5Amz}a7M8jXID9V@ZLWI{I81z+m zKE|s)dpXi?L;vg*$inspc{4%pStwXl6zYJ+GSw(ThG?83ckv=60772e3=cKFDK4z# z7a48&G(U>4otPid2UHMrr=C}7yHM6%ec(#a|2<0vo0~8EL^JT%)KSQ0e|_A9AXWw;dcYvDH4S=6E@8Y=%;?I=cl9TX(%y`;6j?_% zJU`sE5HgYBA6?)b-~UIX6CSB#0o%gKSCX7aSq+i9>=SOQjLo}ZX8C&fqL|h8zsW*N zs$=H;P=_7YFs_x?b%{%z1~BHgXQSqdvM355m36&HFp!}99**#XL`U7JZ>{w4JS1dl zOe}sTm!5!w3#Ja%w$x++pV7x<^R5UCE&B<86Wa#qPwUo;b3NXc1lVh-Y;~W%UVXP@ z#l(Z^YywKXNz;IZN%$19 z<$S8_`VI@LtE%1i0(ERAt7R5$VS$?|H;ycImTX*n-PieKwmfn$_~m>_UTWHqyIa9F zaS$rak*W@qu0R-iP^{}OpbWbWV=*~u-O+Gl^mHd&ht#dwZW$ZKMX9@~!uNERYB-$h zCs*6YnT(116qT9vcQ@^5+Qn39+bfH5IzOw>VoYsTAkpe<_MKcyDernSp?_b-!zB4!`-ZP z!5Ndsi+C+Yu5V0kRTT?=K-jO^DZsSI%fWr7L)k|FgVk1~?a*`I2gXREn1p13$0h_1 z#Kh(0SyV%%W=ms$4yaQ=gY5245nKPA8#+c^{*$X4avG-v(TDb-(+|1`g&Td*IFELn zfSsOOy2>*^L3`OrZL>C?e4U3=K6cK(`Tbt}49R7Wl0PKEG^Wk`7T@esy=Y=|^wtx! zqH}CT=MaDZ7FpbHgjOMxPE#I8I}|03u6|iiK`B02McxrA%xe{Gd*#q#Vb3`av#}r4 zc5k{3C1UB~PxASZvf?*5$A13<7wD)M5n`y2_lTo6{v4K1@$LhUowgpPoO`A6qu@L8 z6hJfYj8zxx{XvXE%hyZ^E_lk%t(~YWRT4#g|HNA@MV6+<)8VX0K&zz|Se_M%V?=S# z^AN_v4DtvVslV02Wr6&8E~e}F{|dy{P|q^stF)fldEq*I#%)yrJ2x7Sd*d|te>A;$ zJXG!fKYpE=!Pv)A6f#+&O{5~*ObV5X(qhRHN+nB0c5{>>gwnns?L}xo)~QI{Er?LI zu@u>5pD}a3uX%rdzklvWJ?e3bIp?}wujiWb{5kr6nXqHyPJv|hcFOnyq$~+6 z1+5WdBE8G>n`0;1P82Qeu@)@LN?RA;My&Nyy)7+)NtI6f3@OX<%#@W&VOw1jZ;I?U0;>4KoPt(u_MVTyfMW%v>Fq#tApa{h zj5bJ(6BzPayT2lQgmDTvZoaN0&XO%SE{t`bFaLq{v@}5G#zwwWdqFmvsd1!|t?P1Hcwdf^|^JNK`)8p`4sMXGfnCPvDR7gq7aJMWuJX-@j7c}; z+A2n_A7Y-?Tp?u~7I1GJ4iAWE=r<#T|AIN;%Yw|`MdWwG$o9oWcU1)cTs)Y{R!d!v zO06<6Jll#Be*Wr(fQB@+!i6HFvW+0m;KB4@3!jIH!j;$JTA~z`P;mZQ+uKnhn8(-$ zC+ZYb6K-A!p`NLvm{X9L&c@n$4VpKu6d|F!J=IWc*Y-)~EE&%+diFP31bKW~Fi8CH z?w(Xc*`rnhf&R|r#)M}jV-(aWLqs4->O46ByrZGr{XDhOTT*;*1#a%HuvjsS?^?8n&DPf>3U@BX#245 z^dU<0)RT1Y|1Lr$R~8h_)Qz9z^LsOLv?O=zgMa%wLvBoM%IYD0a-^~D(1=}W-IZg- zjaRbY?B9M!b>x!+>XIPXNN_9=+5t1li|5|PR`>3(nR)cfKT0_wK>FyL=;@X-m(Emd z)^sbJ{Kbh>OXW<9NX*%l9=@?kR=xW3eh$y<9zV8*_mRO8Y?#|#<*vIBak@7|sdPNQ zNn5cM`t9|djeh(=A2(?nI0ENS;21d69Onte?VCLgwC zxVdCh_Ej_iF&KDn2aENLOgk?y#*re)TV0j%es90wu|{7C@`&BEg^Hqg!`~tqqnXCo zLkN#D7DabwQq+)@kdw%B?D+i8Fh>n-f;9JkYS%CvzMMlW3GbE#g?S+{e#c%4sv!IJ zQ_w5F1!(4OvN+=GymPXquQiSNa`zc<$k8%CionC}d_kaaJFSPP9|scGvQ-k9P%`Ji zwi`fH_koy(W`fLsqhMm}y|aW2I_8!;rW4MXE^BbY*jY>%(x5^$DtJJsrT9k}^#hy% zxMIBXCcUtsc-E#>r0KFKbuN7MrRM7rCq2*rtv~)GiV+V#A4EsvOZpAz91TV+7Moii;yHeGUFuu1+j~j! zztT;E63o!L)v4dGdTnbenJn)CKM8oTi?Gdd>_0;uF#bT&wpgYL`&~A{doeB_dQ)$2 zc4>2k73amtp2Q|Ct!JNxZ#Arj^pxX?Ob`Ic=kfMd#r~B!uX2=fS(xl|=ae|T%Wux& z$u0!kwz;RWC#ym%eqZ2BFY6?fcbb^aJ7)5EX5Q!f7Q)EF3=zs--7; zMo%{?4LN{_A$+T)6q=tgqz8?EWF}D|iV9kvI{V~1t=gwGHvn?4bk^;MiX_NW@%8)q zWAUelAy3Z_^PGjo3eV`(9$=hlI;Ul;_v4bZQSqf-OHhjlnu|X~laB+4F-drJbtH<* zA5$TrqgX6&zT0D1DlS`5(W$onWvxr3ARyr2jKMuf>X^z1lhR?n7vZ!(8^lw9PT47y z_1pu>CC?h+M!fOsT>0(#>PC0)am&1l0Z{72^z3FPw@jsSh;}E z5-!g}w0)oNPIJ-;Tn=a$7b=xlCOvp3$jjKpqsncc4s#V&hTZ{jLMvn(^^p1Nqt9W? zqA$dk_tkTsUS6mHrYc>I^=Edx#+oqSvGjxzJKbG7s-+{R`SECi?UT*7qO;qLHW=mH z3#vCsy5)C%2c!cceld2KXCE1IQ&hk6V`@`GjWj=FJ5ctXpG9RPTpQ%3sg2}CsF+v8}$EoxDw8t5c3 zX05e+r=7l?IZ76(KIbb>g#yUt&4a6!j1aT0<+<{FDvORRGpe(Fw~A3I7Wd{>iKfU+ z#z)o6hA=t9C^or}Dy2qd#yp7!XC>U|qM5k=e;9I8rtug9kB+n>W`WtD3`Z!rt!4X? z>CUB+=$(29yKA5JpqB2RLn}%9jFEk==f@O6W#*lL2UesI z-#1F)W^)654EJfOSnw*t)O9hZ0_6O>rWYQs9C%+%ri!}HvDySJ^QsvTCDPy{el6}T zYwq~=>GFM7W|~-~Rwmq(2N|ub3MGzVL_WI~%OuFqxh}a0O7t$8Z^5R{i-f_k476Yz2VnNI~*U}YObv_T-mi6sLIGsi1cQL#_KHwAe( zuxTH2V4jh(M_4PyUbkQN4phN-*oz`ZcTwpCggm4Ud-zk}E&P-I^zZRy0;hHfNYR3K zafj_#;uY_Icb_^DUWmDj?WlI|XYueCL9VYj%A0g`C7byC0yCwIJ$`%Y55f;#d-mz6 zQE`12D_jlcJw|&jlu(3NIA^5Q34Fpj!ZSc;bOBbN51pd%oDH34!;OZmoxlK*t-gl( zyRp!@1TD;pe(dCKCc<{+spa&?*($aFoLKKEh6B4ObO{gft@~wvLJKwjIwt<`@22$7 zJe{ze4BEulNK*%cHg#Y4*Q$w2iEWK7thZ0Lu1B@9lqx>G+Qwq*Vt4=+5iR~f+A6tw z($0cr9!kns79l|9zsM+in0(KsWO5O(taHy7BUZE3XS4sVo=xG`m_>g%WuZ=nzm3K+ zvzAJG@N8W7ih2B)_w?1khbyG;xbJIV(desLrm}d)*{lbc{y!M>N!WZ6P9r7B0{1{1 znOeS4P-36DcqVE>{bFbdVpBXo^z8qPFbu%@TwzWRxQNdElF~1UF;8a_Op(Lh%=Yq zfaZ7^Pfp&2sFu@}Szxq7@qr;@DGD$l!fpi_-JtYilXnI zY(5*He5aXk9gU;0G3HWA^EI$~O|#OC)b3}`95=dG1FSoYz0fxvpN}7{(zh;T8n3bW>rYyQf?(t$% z`r`E-yE}!|H17_=v}&PAPzDyv8tJFzX!gk<#k`%Ywx*eXVe!O@KAGC( z`4t>*fbl=IV!uMpZ^{gzj?RyPPy||@IIm)pxrkeA^NPMk^BtmS zbsSSUF34^ToCZ1*#KHjKaiHj@uxfxVg(%0jZissj8m63GE$XjH$n!+e8gp*`Ffp;< zO^RlblG#IenJqvh`KmE3`O{93TKI|gbv*G3XHKUGbF4$lgk#?0j{6b+BLfP~gS{!S;V4;XEg6$ZTeV2wG9EUQgmH=e*gKuYrT! zqCM@2B&VpLjq3)Q8x*=z$4E)DD`P6!>r_L~VyHv<{8x;WR97Vzf>FmgS@Q45^6qXZreMaHzT z{G&>D2EA%>y06>3va6VM8Z5rccoZ^WRnC7PhT|Ht| z$bEidv=VP+Y=zCWF85_OzXKZV^4BHmb$j8AWm&-R6X%Ww&En%fzMAj#N9^&N8loGO z@Ofk@2x6*Kjsc~}frZGRd-r-Y3Ly)diqv5r0)>Lt^bg{9icf>!(nZ#36>u|_#V5~q zMek-_6x<7@Yew2_iBEE_>3bAA8eP_LEpF;Uy|l$WLTIt3g`mu3CSZeFfQr;T=!AJfRnaWwjOKrd&WJnx zcC`dH{|CzJ1yjO*M&B**c!F{9@Dzw0k1X*3ctNVnS_)l11;ABds9y9=K}EGv`WD`l zrvF!r-Z>(dD9D>fA5a5$u_@Ss#*DL{i6|PK_5gL!SZ&s!&XGFE{<${~Mi^jU{J7;e zcFm>K5pIKod_g{}1*3W2e7>vo@xf)W!jY(I77)Aqm{Y{1Izk~K+OtA8Xz0Nd>-=1< zPZrD%Q;uV=m7cnD8*P7dMB6p30C-X0&xgPifV|iBEtG~N%jBAu;T`h)XZbwMxf_tP zKSzyX;txo)@T7Q~%RIBcs9efGmJV7JJ$%qWlV4C4TS6w~O0o+?sS~PhO6)|ba|pf7 z9a$GF77GY#A8;95Q(+979=!cZ2y#%x&(F%AkP)SZz&UwXF5cAR=Nnk)%N=XJlh1jB zbHatzW|D|-k|j@>Tf~A z^28x${nTU(j=9q@i;?5R(YDhOegP^l)zt~-K1RPwW>_qV}Ree=2Gt7$-24i6de1NSht z!od(5-RA`~3Rnut_!+e#t1Vf1X>f$)uo52j%qp3nH6zel&HM#>0_X9vkJ{TH^{Bj_zn&uzyMPmwljCY`~bKz4A)f3KO@StTg^Hm9o9cLyZces8z&1 z4`#;ml5{}RNFEFQLv%D1C&pd`h80QeRM(RfVa;4;urhl8d{8%3cOu?5XX>NWN0@gT zO8AcYOlv+GlHiN=ob5e=VrKs7J|*iLoPn?XYA|?;|*f6CvN*ny1+Z1k#?yjddfPGN{0Zs0M!FxJ^I0PW-DaUt0VL?!lmk8YFa3 zP3V)9MSX8RSAz0mlkdeD9atyrGa%{>LPBZ*-!*mT;%2G^HGRZs z&>al&S9RX#CF=i-4tP1Y5Q&wnW?sh-(UBr-rk{HWqfN?EP%A1o@>p(q|HhZT>!>1( zJ~)*={C%|-Vo*{9-J)4T87+j<@Ee#2AfW4`0V#9qAW`D8?*}nID?<);gwFATNY{l> z$Sp;!$7p}u6xgoV7lmw{>(fK;50=XgfW}T`^9gFYGp~Ovk~PRzQUomZPPE*|7|(9=#)5`z!#m zuPiB~R{HO_5{^(l-+Jv&r|(Nro0Wi)u_B49>}+CrmtN?oSz}fD^^qzSLe*r@U93_q-3mvH|L0e5DwcJd*=p_-U4AwDEA%`pZonMxGv_ot0a9*Z%Y!_?L#PKi z7RN4Vjfg#@f|wveYlKsR`B+v_7^>D2Cp;x?aQ81p)afH2a4R`!eqN9WDKj9Xzqll9 zL({5o%@BCR4r7~5PxLQYvHo6n@3)xjP!Bm2s-^G`KQm_HU%#cIcG_@co~UK;*Zv5n z=m#!cZpGGcmIr6TD%W3qFJz+Jy5Cr)KH}g+2gcSd+c!W>#qheH(d8qyasPu3Z(S_F z2Dh#ousdB4y@E^q{Dn(ke+_Vd0338b3);}_R zrfnsIR!9q>#9RJ*zKU>;AcbJffg>=r@bmBAW8aWO2b7gKC$VADSCLziMbUal+*rw* z%Cnyfai*j)2dne}RHfgpV61#Su$pV91OtzIYThb&{_!F*&R2KJyv2PDo5V3&j9u!r zk@xU#5na%Rjc&9SIdXPy7fcAFIOXgkfKNKe%Crs0qWa}PqA393^uuIjXpsWeGlnfI zWK=Ty83TcFqh*?Na>)%rAUv}pxm9eKa)l5tR5TCxC<;t0#S6A!Y=^eJh=%knPwO2s z>O+}Jrva-IltqZ)5U6J9AAeklppL9YqgU3!M<93~kHM}@9sPaa_bd^+5%wg0e!C>( zeu4#Jsk~JdBMAVjE;zAL|Gn>n%Gk0=b)k|mL+`+6-9n1zdqHl8Sh8$y$g_T;2U?;* zeLJ%+RM-sJ(YQ92U$KHvAG1^3O%Ndo#aZ?faT^98qPgN*e1!{fA%DU|_k$zC1Y|F50_azn8`rK$Dc`R6q9Ebg|s2fV6K?96V4>klOM8#27Yz+GS z8dLlO{JS(sb_`xH6dMR<2f(hBOB(n`7mYDHIi|Dd)dFg%#_?IvHj&Yi#mbg-ZoPF!UBwPeQ$UNXGm#!PG6br* zXd=#JhspdPtGpT@5S%fRDA^Uzug!FeAT=aFU zj_)qfdaA~O;yx^Ncld9sGM!yiUDd+~_uW(M_1v@lMtC}jM#62@bbuFOamCK?=whl= z{qc=+-6ZB5#DZ5zp;8(GMe;*ly9f$--*rEFP2$ySBB!G(qI(e9J?S1@ese{1j;H2d ztCqB;itaQ1V89xBB>$(VY!c!KP@wJwr|RXOPQPsX^ev@0?cg;ST+EXpMTOMbrm1uEJsNy@bR6I+Y9OR^t?th!%pRqj zkc)N;*@BSz_$ImgafpkXqsnd*>7r)0$fSVkz*6V*?9Z$fk6~GcWZPKW4PbHMU z5DwciPX!qU{|!jkyfF zrsYCS^ELbn#y(T;aINy1i7KDiwT2ro#iG1^ZV*5ywGis!gM{`FvEzSM2-$DBYcI_8 zB05}eGq6Cs4?hNG8$sM;y0H&!P5@dYq$MqDO^90)+8mzN6mjjq@_v@e2BNiJk);1R zQwDuDG(sfcH@II!QXjys1qV`I%_fV_+c>_U<4L)}eKBg#<&(6C_p!q7Uf3!r>Tdn9 zRWS^iQKbBF7qo7Gr|X!P=JTKbqT66EftUHq%VbDt!D`pFYt+W3Z(1a@v}R{oWmdAl z4$(I7+I#5WS9d!bqHzDS1t@d7M?VdCa_~{Dc`e>LZLySefpC_s=%Qd-(qH1Dim#*q7~^pAz-v)Z^9ay2<( z+NJ@DiBsCSLE65n*3g-{!@Y|J8Z#~?XT00ME_XR|>FYi*9nE!(+?@B?d4gRg75uMn zx92K|3Fi*;gsb2W%qJuF;gs2zHZw4?e=+Q;@lu*rGe+_26I4-86$)tFM%8FAlSWGD z2y%QV7nv?OjOgDgLN@%-07a1u)+(ak>G)E2KoQY8qc;sgyu;lG*yhJ1MBRmo!fa|a z2R~;Mi?XXRW*ze-cdC(>?*3B>9a4h_kBM3qprD}l7c#bzc>*9a0_FfWsql#P^lO`d55DL58KCiZLsZ|Qc(OJh=xwHq=E-Q zEh5Xf!*RpFQ4QMk}qsLOZY%D)e6Bhe2HI%|Upvnm(ro;3>A-S_ zt?r_CtuXlnjILvxeNsB@Jt(g>AktIRHW_0HRxAVnJw5R+I$B z{<%nnbL;NFk*CieJhAEjl-<3@+(!aE#`NE%Z){pvy}9XN8aY!$nDro|YpF~|o>NO* z3%PEmSjLY#qBq&1%$n5$uO{k$Z#DU+4$)MCUO*$&?sc}1rhDe&3{B9mALWnDObSJbXgwn(gyp;!!#+8S#|2$~;9{Cm6zv)y3Z5 z{OtNEVf@NNMR;mQdwcXybPvRSb=64B@n0-o8FbHYrgb~(u%Cv-p@Ron#w}h3;vuit&-GLCB9s0_C^rrYNgUkoA{!s>kS)d({!JWzf!03)kx$jYi~e&)(O#Buh@Pm7N?*aDe8`FhiHNh+WhUQ1t>ho^ zsF4CazDdKt#ausOLFdet=ZIv+YIJ}I%DRON`7Df>TKCX(+sRaDw@36md(gl8Ll#`? zlm@C@C4$#Ze~mcs>j{~2tNZD8goh(4!H9Z+k-*<3ju129bO_QtgAR<|1`Pb;H6Sh! zdf3^=7z;k%t%2;X@=`v^_I4kJ!Nn{H1qvftz*2X$UQi>6G{WVG$Po9s{QNG~O2oX# zClZTgFi6~UZ#r_34;!@hJ>pIa(fg>3zu@mQ$g|j}>eR}@R>FQRqLWd{7*F}jg;k)5 z-n3|nB|cbwaln_g{+JbiM9SU8Hr-{9-I@Ry+-KiI2M^qoMB@%i06uZuW)M<8E=F8k zPvaPnGQu`RSQO`ar2kGD=6UT$D>S9qjlSxQW7jW}-G@EU-IR}FG`b)L$%xWGWUL70 zh<63W0sn#aXF*CCqTj1I>u<8Oa*%-7_8pIey%LI!ynU|FKPeMaJRAX8ELV+= z0?+R#$IiB8!u-as*3PrBoae$@canM;P@*c?=uEyC5TKxN;>&1M*w{lAMy+x- z^Y+4RjZ)S|Iengs1_n!n{B}j0-A-)jCe}J4kR?cqA_h-_escpdcPEc+I{Dv(c7EW=2m}X zG~FWORelhcNDSHy6SgKh7NgPdgT|wQWj<(KCY@7$nMicLf_si(i$5V<~>A?7!7qb!mB&;5uyUi?21bUHAqf7%5puvg{i`Mc8GKxA#_TVW+XdeUz9 zB^@oU7l@!ANwO_nE0<4_izmz8E)kqm!mUD9A7G^v4Ah;fLb&?m`{Gb@*kbU>&lr1X zQ)FwxyMo_Q-Xjl&)@{fxX)D zmUanfnnnfDwO1Zu`&GXi*?IaU_#du@hEq>`uOw4L5vzWzk1`>ap>sQ60}pGR?JYG# zfvmtUEF5^FhF+aP`I(xQh}}?+qV)`7W{9^viWH9ytA@gpSe}gJx|WM0y!xM$Lwe;K|Cm|86U6%dJNjSaGtcu+Br^y$FscSD=^R8eedAxgs7s&FUB{8;M;@(x6| z#lRh@ZvuP3Ss!h>A=DX`QV|G2>4@{_=Zyu8bodgUfStG#>1%V9S1ms z=yOpfhdOFK$LuzEE*gcc%=rF>2yUA7Eq^aeCfOUMg1d5!13%-RY zJWOAJ4`rD+&R`TycdCB^f2VY#aC2HS8yC+!e=! zC||CMYRca}25`UZ9pcU-@_{`~b^O!A2H7)rhR=(BU&8+zMq0ZeJ zB8K3jb{9oONu}k7y5z|6@>2({M)TKazX9VD zYi%&9ZK{~|UVB5cv#j6qr6e1}{ZHr2q_=QC<#%dGVr;FmuJq#Cybikr#H@QP(7IEb z)Yy$+%q_3YVU)efVio1=n>Iq3jL%n!aifl{7}KG&&aWrv!&o|u6Ek*H+UN_xOe+S< z_(sc_pCdsNyz%<(f)?*Oapaim=ZxVZIu2BLGF(x%B;=h&f}czglnWhO7BXiZxfHZE zolSB5!aH2CY9lxa**3E`=3n5(?bPDlIER=9+r}Z}q#pcTi#+)~J|ahu$+|zJ%xY88 zH;j2vNR8x^@j%3mf1YR)3kfm*(U~jy;+0XTDU)+HMWE1;+SdoSeRc>MtsM;SsF&AX zb*#as`3gkd>S%dLB4#rN&)_RmdPfl@M>#?M0(zLlTx4!Zi92;zww&T%u3rdg0LXdM_0C&*O@I=?79NE9Xn#3642IzYJUWL$pC&g{9+ zP;EvZ%bmX2YWnn2|N`9tS5wPv`2rmsVx(&amSl+)n=!V+n8qv_s`K7ti zv**LF3f8IMA>tfgy|bo|K?gzNpA0dmBDJRve_fEt9E>mlHlLa+j#R0>6l2P$Gp0A} z^v$fR{cO2p1QX~SkJG`TA1hhqW+xGyb6f;1z>%@2loY^hh|=6sHtD@fR1{vNz>T%^ z(K2dgFtwJiuohVwr-o3AuEQ3wWW(ktuunZ9XI{+?gX?Bs3r77#8IHNuU$o=2#tq5av~1JCzf zdVQ_`)6v`NzkEcxCa(lR&sM7QC5fK%@^OxY(w*lmvm5*4!JW}-*RXy8q|J#MKo3mH zuIn>R1+j0DA585@t+sTY#kMVCR9MLYmvN41f(kr{Lb)29Iobjdj-a`k2@))C^F6-2E4_Y|DL%5v}Im>}0to(s#-=+ERTf{NU#| z-~1auPu%~%KFeJuhZB;C6}!Uq`kbR+?(Nf}L3s&@E{JlE6BA}K^(i6ri|fbo@jxDG zZ#Fv#H@%nIrA==Br!esON?cEyJVQntlFD<&*Y>n4ijXgk942)RT@^T(n{-0%^=FvB zuRm7!_3voV@m;L}5K8a;^?@EA+bbcA{I{=469{yIZWm4-| zt|HXvad%3kst-0}v}nPOdujZ^*OSFzii7n5w^lT6IhH00^`3&yZNRS{HJ}7uRDXog zIbN`1WE=q}Vep+I^p4T?;`iLA51*a(LJU1dOPNtvG0iweqSF$iS*qWB-gQ`}#Hr41 z{}%vi2#fyymYGvODmf=&%PI}qkn(T9g(Q&?>eAmvjxWKAB;l=xucO2c{Te6I)3pZh zO8mtdBysD_%(Nn&8{CiVBf~D^jGlzXV!z*;w}|)`vK^JNj^ zi^?4e$R5xE9-|sulyvS55RjH%gCsc`vB(&XQI+R1YlUdRUP$2p`oiuR!xxLEH%$MO zK=+@Z9E|Q4@gT^BJKaMv8 z&h|xJMXUB}#rAnJ5~15*Mc7vBa+JA_tNu__I1vuoHQ7~LtFo~WF?x@#{9!9hd$)2~ z6~=i@{*xhr*xGbv$_47Gu$2&kt*iL4VHf4x^^NdZPrP=|<(1|LcVy3(>nZ;M@c#0p zQK5v{u2d4Oqh!=wD4JS+ys{#t2o< z{TVS3n37c23ws8oHs2dpKzW^qR<5u8fB|W@I0g4n1e+$WKh=AzD*OeAz!Wz=Ql@vY zya7r027I$3UQ)Lj4Cf_I+Y34d^;*GAQENLhkm5P^rdZ&(3wi9}r|g}4ziZ20*TZIZ zR21ap%jcHmsbAs8{XH#@C`8!FzDbNWUr)=aIcDEqR1uq zfM3)z)1N_Qmw@oOY>cP^vmJBcwNS-QtBXF{qTA@EdW^;{Sn8NTMo?1wa;?xAU0)-C z;;(^xDY#tf?uaLB#`(W9bU}QuWabt~jsa#E1GNfh(!?Xg*Y%@RQRbfM-liYC^hW9R zmil(&)J(4y8UjE%z8+{DdcBk5M{N_@l$9{QN%6di7}BE*nfDov{(_!jfgv~LI)IKk z!dEzu%C=~b58e9CyMep7cs2kI1}TFMQDLGN#FCB9$Ab{nW;U^s0UhJz<#0>^72%Rb z<{SdaBM(qclW*HW2>;Jq2}8+#R5WJ_H~=p7OaqOISU0K<7feur0vhs@MP{N@)coh< z4Q+MAUL%Giln7Cj{)wJiZrAQZMV^o~)dKHB6&qvjRJ00*MGxk2`uQu zOoXN|7Aa1)inw~aA^2gKhkUQX58{0tq!zP$k3ASEpAT6qVD{%fnsI+L#j;?0i?j12 zh?kvLdY0c))Kt8oz-F=^A3fm?ijVQvO5f{P>XSM+>g;1RPo?Dhzw+w*Gxf*Rv{G4CQ`MeYmGxo8j2xY$A;Pl{bah~D z4rE=lYU9Sba=tkv#&%?1P`X_iQAtWZr7L7q=60$!m8p{i03unqr;~t4o>xSb($y{X zVnT~qR(Hh2wXet{CAsZ`?`!W7F_Tlk8oP-8fdGPKf12E$=-djfDc(7qErTAD^Cr)g z-}9aHmgb0|)b*lpQy?8?tI^4X!`tA4eWoFxN}Ro0yDAvn9>t;odi;QecY`9~h; zLAX?3%?_nymQh`A(|fF3*_s9Or>A87_$PNvDWlBSqHpG2O&U_|!8SQ7o^ z@AOSFURZod&8S4`+zN}3|KSQCgp5_3TaY>uY|r?9TpAy}9xQ)n(5Izu?JbR8j{;TB zLUSis*AaBbYw!#EXh0#rFCOHc(pGsT?MiOk4^!o7f2`dAuZD}TV+nG8_lTeN^;htIA7|(a{)$ge=SnAR|OuZa;vA4H@4zhKLq0FgoEEZjrM z=AiTtUa=m#R|Ac`6ctJ$V=&kzu6hNmQu87hCLrRIP?CSEs)E>5annsJa?ftm5=Ele z=@DZJ$xKuq5-a;v7vrkgp_VJ#eswAmCI;q)zn` zG7Vax4Fg0-+KrpB>o+jannCJrA`_xE&zDqP6-_OW^u94qd`%o&jsb-nOouP zOG3}UsPw>R;L{(Yk{n+q=%2|3MbIK_k8V8&;bh=t2tk;YC*hx{&ek=y2$5Qr_oih8 zAhbAph&ILta%#^`IC$2YV5rjq&a0(3sTb|xhPi{&L7H=U<64E`-9&Gh;lB)1q=7gx zKyW6SPP*Km_M9cc16IK}8h$u|?2-Q5kg4*w9w)b{7f=v2^dAqSvd_HXy8Y>Hf3w?e zU2ETqI#%&rCyZH^{8JFTBJ%&+A9SU~(5=bt9Wr$f2QJj{vJO+ZcTZW?tamEZz@amO ztMD>q?S5Fuf%iF)ZCUi^4_?N1kzk6W(RRUoC1aHNSbZM< zxMm)>;2#fHe2?XO@Ge?R9rqOGikNo%ZB&Phm$2XIyTs52--w*reL480v?Og2o5c!aw54I7e6qvuS;Y3n=bM z_!EdI#qf>D4x?i1$f1-Oo#J*9JuVzCmJ5`c3DYM6ce;SEJf0#{Lyh^=_#lr>4>~CynTW>m zUA4Qq&GhL}J+;d6#AsO$_WSXpQ7HrAm3-zi#tDJXqAi_N`%R~bT&*7Bu<CV5o zI;Af}KlMElkGksOO~ZeK-msP|x@34u6+;+HQv|fz=J+>X)qP-=ZXcqq36N86L;zO4 z^Y2_LhMoXL%-$-lPzh@o4D{2XTvyw@uGw46w&LYCk_7>wW&RLconw8G4N@6yMxn&z z&?=0LKBUSL{cs8X*jWVrYT*r{cp!0p^t zj*ptE{~A-&Snl?6{%Mz7Be3+Y(GNoO)N7@CZTGrA)%r|A`uk1;-=yB+a&>p0*95y)IpqAI0gyA7Y-33 z#fPrBJ%^!U0t~d4xpL5}DI2(7D4VQXM!zA08r^c1_&$Gi3S!DnpwXw%x^7Q?3s;w7 z{E(Vo5lZ&u<%~cB#eo18bkp-QeyI1Crd{#={`Qa=rFKsg^iF?JfRu7 zr>nsg+_~@uyy2TpcHdNR<%7R4vw|3Q**!DTXz)ho=U8+I!MMAkS-n4kf<{&Na-suW zUQNr6shjV6#{cJ+H9DV_Q?TK2u8EPcQ`B8$h*V6Im|JgC;%DlCY0i~LwB&SLZ(>evSDg2>wEbYHaiT(0e4 zAqgp>NPEkySIA>NtSVnHH~_w(_%&^zMr3@22>d^rKsap=Z!`#KX1Bm{(W zBVZwT!7Yybo?b5=rZj!G*=K^01i62L@I^AHtC5u?AnLlWl;>{UUji~1oCa)JmtY4V zvJ)9{{$ePdCky>c#D)B!A*gXy=M$bw1W^+e9|h{k0>UhhxQ6hT@w^@HK&B-GS!Y&v zsZ#;DRGxdSw2W9;MF68ZT(cNKL_O>$K7rD5A|Hz&* z>~iEASLUSnD^bJ?lR3{Z?LvJ)C0W1K&b7Jg7LA-lY(C{4KbnxURzS4|>t~+56*Wul zGbBqvDWUe%5s}c{HCCUQ@HR2bGlx7;-tdW(;ed!0+GmEPKwvd-2qI)tj4H02l5UpJ zuMJr^UmAF=7bn*yzRrCFQn&-<-{vvp^By}OoSO0Y ziZE7mL(q#h{8C|13?(;|z?kdDrTmkJr*X>#B$JdM?Rmj?Y~ z|;qm~iP(%Y%LX=dCMzGJI_^MSYYKmH6Tl(vle{qyao zt><~t*LWN8v65xQ$NLJdM`_KQhJOY^9z;bwFv@0@PNQ%9o1DEZ@*OS zRM*o43I0&U9nLg!uzH-zD)3r1M##$YO=eeuTai5#viuK;E!eJxtcwFNdt{%{vL6|f zASZPrOabr)0YF{^k&@PaVt{ctw$6i05E)#O)m1}VGK~7@&0>pzGB0?s0NSNDW5|r2 zk2i-P&PwEDeU_K(jO67v7$D_}66OCv++P~F2Ha>%L~BHc0Th_CLF{aJ)0i`c;om~4 zkFO*_ew#GXwH&h>HKw3$twWFuu-~j&d+- zpwhpTl9wVpFt0!AV$=gLG9wngsE}8UI4<&c4G^bU5yRo;e|tQL3ff8y#Qep&VuI- zgT$Zjb;sd5?E-JN{xmo}mI7MPx`6W>S$E43!^mU7z45#8vTyNKUi~RKrpzUR?%(l| zl_fs~lcoNI`n_I#L|@EVil_z@X&mX}d`9g5fe&T!-1(~vpSl=zGWLyE%8N_d!l9~L zu;th;6_3A8M=AH0B2)jpm!$X6(l%boF*`sfS==;9z z>$FO2$4k{v77o(GLLNvbS1HP%@5&8pkeoG$lg4<#j4g?q`b9vHn3246r3etYoS)?k zqzp^7Yq4G1+#$HG%g&!Eyp$aQ4_}iD8Fwmfa(g-wx;|5fglyfnR{?dD?dKtm=(+8x z%YL2vg+Y*cl23!H0S)3q1CFXa23zK!U1vpB)K-kWp^dQJrpeu+hA8kQ|9qbG{w@Hq zr0a5FSuJ=oH{T(@4{jqPDj9`$cuj`YnHaueEH#qUZr_KYc4f~e-^EC>`s@PIh7KF9TwRJdWClln{stbc z75tV-uO%^_>z6tN-?d{n+xjAJgkKMnTE6SrPp?y@x$5)zhrdcg5`}~n%-Si-&;7MK z)%a;^8X12Fxqe#0xac8_t>Jq6K0K}gQT*JX8wv*me-r#vK+lHmqfj@c4U;hR%OEaq zq)EML1HW&Wf2AOiz_W~V(8J2liOC0cHct&^nA^1YopzkMSzhr)#J=F`{j#<{B&NOL zJM~;K*y}NLpG+T)L5j0p=72q_gOw6PFdhAgx)Yb1crC881q6bz#M^U-eJup|`}X%% zQ8U+fM!A28H2yWBDcE*IOra{52U5p18WM8H4wy0_paJqK^i3dng4TUiw3b8yUBYsz z<7H9ycqDZ0RMOZ3DAL_%9K5PABz$B`p4kf~>DYtz@k8b#kaDTN8k&Ett-XZJHUZn= zkXRQYhPFc#1Pz(JUY+y4c9{sC2{wF?tJk*$(!Gl?igrA104rAU;0otqR=(WXU~lBE!p zkab9@qe8Mo)@09;eVMs`uX%sIkKccF&PklP@9TQKp6h@n5|G^(3L3VPf=pioy1)}4 zzJ^Q*+I$Q`^>Dn80${QPkYmLsMnw>m=K0GIF-tnqe6kF!UCBuY-l)q=@}ntuvRL|{ zXb1d5H%OU^{{RTWYK&FIg5MY9mgD>SwPpZ)08COE=OE@89PhjPgG=Kj%PV)VXM5?`l-MlKa;VdxhjEyH^raRlXTK|m&sYa$t8EZwK} zN=bkCNqN6M=+&4FzuG~Flej)~tcEE_=xj2cEK?v}^*%p*j+B2xF#;5l(}-Bbu;Z5( zE7WI`%S=Mk1#;ziN8L4o9st6jk*sS)E0C_B$XP`66`*qmiOHS709s^7C9gZw_e#A% z1v4)uZhX=U2JtqpZTDVEFEKkmE3(_}|<QUdl!;o!0X?f^QzxNFt zh*i=F2$4r%Xor|$&twAhRNC|*X4f$OekSS3@bZXFwXep543ADM{3T%b;X&dqd|b!T zUB1zM*)xE4{Bk*Gvp%;jZ1fiuW@*88qNxM~Ize-gsv2PUurTM0DJspuHyC?$WlZpDl^tj-;_@OWe|sGup^^feKgxIK zKTjF1bmd}rAT zb{8j{l?(1hAzCyil!#=OPRG1^GEsf~f@aKDEji9sM4w!#bIJv0l( zI+VnExk&(mpUD7KnZyyhKvdMUY8xutiV)A>Q3os-yY@e*d}el^>ey5raIGphQyPW2 z?acX#;3gDB(z-D4K-|;e6W{1C0g4a-&H{$=68J`!6GT4n1QFn+RzQh&2RzZZXYgUc z{IdRSwX3rbTEi6vCrEJC5&-11SS6z9LLgv?P>Rk&<>%Ri*G%OPb&sZC9zk0&|2~K z$;`2A{Cnh{xqhPk$(azatDI0ua{K=0=ryeA)mKf#=U%Q=Pj^Af)Nl4R1=FK~LxXMV-i?omQVY)rZ)_?~2)7 z73v1a_~XwnHQYreS0*=-qrt_e>& zy_ahQ4@P+pqI)9qUfM!qms5XRB^@g7*MVI=9a(D@J5wF#*_kSH?rCD!-vvc^lxt{*t^s)(H^%zA>~RqQ*&%}u z^Z3~=!Oa_1>p)Xgy}vbZ8iU82g|gpA-6mnAb>!sY4<-rmt6*x8M`u@F^H*%kzg`7= zS8z*n!MQO0fJCqf>o5DqCWmqCe@x1vI#*3o2dlb35g07R9znw8_;IV(ed~?OR6$6P z_+=X;;2DhW;ZW%;4hTZJkb3kLt?rZaG{`i)? zgRP*F+1yZ@n$U6|`qmxrO5u?UODFkL<|C$+t@B>0QKy>tn2fd1k8|kj_t#TzFCpfB zhTvU!AWdoYKX$w|;A0~!ZPU$@oSZfB?iVYSdSPQ~LIMQ#CcTr+i9eDas(*S&9k$+a z$A7`o)hH+vgQb)&0krT4KLd@sFv-*5c29|hg zp+d+Z*|?(OL(YI_!r1P^_T~hFW0D*ncb{ON#8S7mxXi54n1qI~8!iAk?8%=QEJaD2 z6^Ogv2Ihh86I|Dr&hV7F!Yh=bJ~|2K4mvyp(K5t|>|hC;iNV0W62bLfwLQ(`|}egw-%gzhP*k=<|i6B<9wSK;C)?0DvI|e8%b}V7}oR%IHjk)chMfjih1( z>RKhJR>ep_ibro<)JJb15=mkuwL(@9gr`# z`upPQ-cH#M1LalvDR>-zvP0tO@X%0A1$zAKDC*X`%r7~esKh?yDVVkUieX!NT8Mz?QU_<82u%NO@zZJ&9So8@T)?0kMVoAN_@mz@Xz|O5%ury5mJULdV>FRP{Rs zb?VCx%|fD47C&^cDAo#)f<_DFl{OnI!zR^1qkRR>N~19I(vX$ z>=A((dzNVG8?aJ;F9w0jr+>)sx*1%0Hga8V%pCH%i*26cVP;pazdhkU#4uR9Hb zSHt`H)5oSW@+24AZ9%1gz?zD-T%Uysu8;lLH+laSHDTuGDSebbQuZJ+5aXR zohrGCZkdciHUWBD#!2G!?ejk12^Jsd2L7@7Nkf-^bX@iRsffnUI%MU=M9^P}nsN<9 z*}}xD5THUINLLuJJfkq0|BY~cJOXZVhQGba!>7p(4r>2)?4zoSr-+D%tOi{AY{lo% z-4dXBSe#E;vt*?sGO}nCliaV>F#hT&ht>E1`kAtEqcLTivP=^Hy!`{WbG17#KMHhj zROtgY(tRT1D(zE5!qr_Objx*9eN?o)Bk*v~_O`&4Sk&8wb%+j-DV2SxX4&EWCx|!t z1qqnh+9ktl`n_m+MQp`ro0rR!dv|U}RmR5wODHBi*J>*l|*_T%LhdF{9EyT>Zzs6;H@%uk<uCXFW;&P}chkE}}?Q&JyEN@ZSQ-KKt!cQaTH@ku04@ zV^_Ejpi%2sqMLJ@l;mQWI~*p}xWvwq$Ed!qj00Z`x0;BVZ;&hokm~Z@kyPb)cgjVc~dM=CsqD zWkOz{;8=&X1Y0Z3EWbje^rPfM2}oS3Zo&RW!JEZI-Ja?0-))g_ZK-0Gh+Q^IK!cI6 zSQc7!msO4J)jhEnbtUW+Vy}uTO`k3w*ezyL!{$dVGd}#tOJi&uI@!jSMX{4(c7V4I zOgud@1d`0eX}hiZu*D&tg>BWtajI5!g5O?I(Vnm0s-p-oB zwQ7C-&r4=N%Q=UbH9HXI;Ot*w|B6H>q5jlUUUqvM`X2|ZcB9Gap`8QUu5Oqc*@oz* z^T%CLmrh9dwy_)1VNjV}H&HE-?b@h-tcEthjRmOPM+;UrfE7veM-_@gWLnzi-rv}q zWX~Wj5Z2k+OA9Qxjis9I$N)0Hfx9k^qYvq=$r(xgQ#&$0Wv?jUnVrr)*IIPi_}9+A zJJG3QgW>1i9foWEDL`oIf`JcWn{$pQj354qAMkzM6XeUFU`J*^?JX<=%i}>FfBCJCm-4(Y)jlICR+m=4`wqxsOeUD|7#Pod?}Uj)xo{z7 zXUO5}hnFD`LbkcTQ#o&5>cX_MVsUv+Z8i>3=;t#X0=l+-zO(ln+OE$W>Fh1GJW00M zS|*Kt^zY6dw9Oy6WGl=j`*#tUUUKBRAFEL1S2`PLQ+Vl>F7|g*=@b-T_gLTu!2vQr zn5r956czbNFf9ml+KDhZ3gRWjjzZ%b!NvvG5J2ql>2nfnC8W8@6$c1p{+?~f*|X&< zfv*=IY=f_<$;VdaN8~LqA=5j+n;dwF!aR>dVs2ICn{`ZhczTiweG98Dfq1Kan@ar| zNaM>SVaz1}LXH>NA!g>zEL`9sfCW^rfhfR2#2hwqq42shPW<+afiA=u*DVX;nDNp9 zG-e60c3kL8fb%ePpqju0&pE9ftSu!&!lv?q+myYv9H%yI@KagsaQUh>e(2}KwvqP0dbcv>759xs zWqZL^l&dX;KXSg-P6Mq1F=z!*QQ{_(B4Xoofj};a4#^RRwi8l(^AAulyd@l8>i1wm z>Z;~M`KDkyaWIV#fR-H(jAq7tt<$z3>BjvzOM>B0a@k=LbN1o}HNIq3fa{UG1rnAK-Gj8NyR;lr*-&+76zfawGM8N)z9nMOIc$k(Q+y(t*QqLDNl#>HrSrXW) zqsu+yy2bX(K>p6Jr@u~x1Ls!Aa*F+{J1Y!4m^Zl!p(g-49Y+)|jorIn6o?o+AV6;R z`p=2>BKi5OkvnN32OEL`8~-@m4#HH(mPPyMm;TJJDmroj3jX>az2NaFZ_haRI`y5P z0?knBds7lZF7_4!CEJ%pBN&j304@OS2DXuc)`~zXnzR9=teUJsx*IsjnuSk>VIip< z;_Rb9O<)3*e+bEbp8>A9QMiZw(`88Z%~og|DQQhG z$ejJ;I$g{j{Ybm;e@Xa9O^2h2+siqnF0btv+QXe^f$Y9>C}I4b)BL->ejx(7GHYzX zh`YOgp+Shi{v!3(NypTAb+1In9b3Rwr=@1n^P(Nf|J*OmPVEe9xMvK`kgigIx<{(T zU%W%wuncrwva1}2Djtb3eK(Q~SbB2GXVOzex1f+5u#|k(xgJtLLeC4Wvj06JsBRT(aE(sDl&Z~{h_=xmz-l{@af zpRDPFy5#4+nM6rP-IGQ8D9KW2{5=7}OBfYei2z{C85tn(jgSFD<)I|<5E{a^S*qRw zJKG7e$2Y+!dertZRhdrCKm2k%U@hV52pTsB#IRb%tv2x~)9UA76?mcffC^T`w_fUuVa)a0M|u|ar6s~i%DxY zaQjnm(kouwUrJIVUXZp|LgUn30B6^7r)qZ|WYt{cM?uzOw;*i{P4!8GZR@bYWB1^$FU;F0wM87=rjH!wI?sY z3o2Y}(e2Db)gZa^Tomfj%diK1 zknEr887s|&7*D!7)qGzsWc7U(kcf)hCW&vO@B4BuV_XRXV!`6Umpkk?I-!!6EL1?P zyifYVy+#!4_wFtcOBg$R=d1exlb3Oja=%w+pyS#~=p4vNIn*TwQ8ybmZo1Eeaepca z-dl_#nWc+nR=EJ2H~L}VEgprKKmX|ff_0N+pu25;c>7*QhFCGB-YaMHRm||@e&_Xk z=<-|E8xVsp(~up2rnt7ZPFvTJ|Cgr?i3bpgJZtv|RM29cN2E!ZN)fK&MuHSohsHlH zum2ezngw1(^f?{OB~K5{c8-9fyWN#$d1b<6=N*;XZpq_Lt%sfhP^U}Gl0z{nccHm; zb0mT7!NSgUz9dEIF3o#A=JGT8y54gR~Y$bHWE=O$3nXCfFJGV)l0)oD3g-@)Ho~iw%&J zcT|F%n!W&vFutz8dZ?8ENxizr?{HhKApks0{F)>*+_{HWuv>Et5xo&3`dfN1;2|2L z8z=yxDkHWp0BcmdWO*e3FE(fL;`Kz8%{QIwJ=(uxEjSDOx)~5*-9ej7TnheBaf$2? zy?t?xlM zn%-Pag87b%(94VRaQZJ;Wz`ei8F=xldfzODgE0K&*m zYPG`+5xZFeCV{8K?oly90SskK;|c;6GydlKUx;Dy_MNcmqJoEbQEd#OIviHZY&Vl& zR^i8^^bm6tN?Lz;l_m~s)jaC`90DtBYIz|bJMmr1TF$OR0gt_f;6YBoo7T~#p63zr z0xTA2({2WpfzOnSWaRc0v;E{^4i5_{$>7@`AE;Y+ch*k!{EkQ2HYlv_E z{Bc+mF%_^s{R`^xIC2iDM3^%fs;D z^rbESmdyj6kuJf@hlJ=$+r;){`#F%2PMO`CKr^X{hc{@@uD}F%UZrj^@mceO)Za!| zDhD2}u?$0>EU?%9@(9REM4>yNFruy%&j{Rci-r6jZ;qNz$63}G+2 z56@!y`YQkpiOJkAnE71|YB124F1n}hVE?}?-8dZ#B;=c4JMeOgVg|;fkeYtOoMKJ> z_AHIK3}-La`+JTcoW?DfSi(K0?&sI?)6b80P$5=;`!t<@6yR{G12fo&?P{^f5 zu&-=(d{w(SWCXE6L+1eGJ(Xjyb1q((S>u-YoG2Shz!njz8jUGh&~b(vD*`49iO2!@ z+Kl82k)ZAf76?AGTmXMsj~|}FUoXLAv$jJ`ien1sEkt*l0N5wZ!Yyi#;MbP$ zz-j-=dKOH_Wa=V-uH_lSL#YYR=lXrE9E-=g{fn;3G=!k_=Pl zyEqzeg;zOfs^dxtWRh6sJ~lU7^nR1{br#5N;I^ZgRgBQNS?^aQRE*yZw*6-Q=Uafb zR6Pw5&;N>C>5J6vd`huE>xfMBkKI2$_h<6}g_Z_)y1hT4O;(zU z-1)slXft$m5L!aswDEN2fgOMIm1^3)sMM`Q@*F>pOXDQNS|$OrVr;K^n#gPc+J7Jq z{)Zb^1pwG!p77#-4IDWuh*&T`ayhzvsN!?I0E&H4q)^Nvqmnc1{9J*qcL%??2c^WF z4}rj~uDKRdy$V=ZoNfZaxaaPJ$4?hW{Z)rP-)?@Vk0*|SGoeuJt;6VIXtY0&*Efg8R#sV@9Vkg4- zf)%t3;<<`2vYTDYS^PZ+-y%XAzRgmQBDl`vZl_deE56x#mSZ+9b7RS3q-3o?s@C}!qyf!N6k0(vV%#j6+r zFN(*0?im0roxuC@-w%HVLU_{oQ@$paN`^P(l{v(cr4Di4k$$`k1E{>Ra65ur|^Oyyw!+;B!4p!UrZiL>V_^| ztPPI`Y;Q{nUSQ2B2j%9i4~IOe5xi*;A-Si>3SbYPy|%U&GlzCS`r=ef0cDM-IComox zUS1%oMn*ttY%jm;6WW~lxlc|MME-T#cB`|J}V@ zwEUSFOsa-#0yB;{F3*f@{^5EBVYUQQF$A)jecBV{mgO1&8ZEflVDL61OF~^mjT0c? zs+-Oq`Y+aG_GZ4jD(G3TTl)0}7D7%a+*W({1ClU^pEPodCn9J-G_fghvrqq4dTcM> z!x$}kvZv|z^VPy9&LM12a>DcGR-UN@qU4|QQt|R81C3RC%sJZ#5Gw!0D3u`>$*C83Jdv}p+?lls}-Jrm#Z#vN_B7~e!R>bpv7f&k} z>|n$e?QhC&=ink?T@mrp*zfZCq$9ZoMpv^dXX*oAoqgrr;Io}RFj(E`5-(G5>rImF zV$=;jbtE$jqcuOTU)%vkQr>LhLdYYcJ&ensQOlGaih(U$9e7mg@_A)Q!WpktUkX-~ z11|Iucg2LWVtvvLZlD@Om`@~^Wz)Q--HHzFEhZel{i$|m7)U| z5Gs>N-UkjP%djS}5Z{LL(1)9c&>k?6=*cbtKMhFdnj*m*0-QAI61bjO;tQ@uQeep< zYZ5r?h3KkseFR|omR|&iY!p1jkmNq$;50+K!Nup_v}CvfjwT*z+#OFkEdjHDfnya~ z3xB@*48k05oE*bJvD(7jyA(K$iy$vY+?|BDTR-3{Zdq0Fh#vcIRpnOCxk-dje9y#v zAu0TL!-Yj~n$I)jIsL72>A$f#=PCQ1)+RiwUl|7#t8V*Qx_^IFTkwCO z88P71RQ~?jW=RToiKNA@9R4CSNN|Rj1jg=FLL;M=u+PL&-{Y@Pu&bZSzV&AkK5%ncvsBu zi(%&?Ab>_4``sEc9QaiX1mzP7$l&Fj@y}b13rO0xy6@~l$q_1*A$Ki5!S~{^5#&^v zG({m0@BvULgWe)@nqP=TksCRjWCevqr*-RVrQg-KYa`tkBA<$XJpoYV`uvF zW4OekiWtVq?f>0da6*8Jy4vB3PVHu|(hWtwsMf-Wf*ODpHc5(ElKP@N09l+;TNq}> z*UqNM^|%?*gco4+MWyv^cRK7GHsS- zA&4E^2lrYD>?5l+;Y7JRcb*RfWlo*xX6dL)C83}XkUKpH5*|Zz1y1v}r~WSdkeO~g zLA$CiTDEpOenX~6l=?G+u^(E9VTu~h2u~v+nfI$uSdu>r&f(=zY;onQh+%iY!Yezqhh+k73xdhdm}~-8rZiK~__1p5$iRN*N!RiwpQwBb4}#ygtnB!}(;uSPfb-@K zm=qK1SqJzk@1iRGEriPIJVB@3@b(eF0%D0ZLN|<43MZd+cmq4m`6W7!t8JySzv{n4 ze8!9svDj$Vck=5$y>rC_&f&C+?jDH3zWK4})e3oL@1kCgcvr1NC4pR4An-U(RgQBc zm-iS3z|1WbZr8FVRvHC9CSYrTGuk&BY@xDx`R=6^=#xC!P)mWNfm9wqSYjoLRq&${ zYxHWHub`h0GsP0SGU_W<(wrTrd!=gRgj=AQJW6r|78<%1&V4870d73UDKayhs;T%a z!M6ze_=ElvAK+8tj^Pq^M=!?%gBI8Pt>Zi|HNpSR@0>~ai1_%K@Q zsfCMP6ztF}t9-+g)c;O!)~y;B#tmLO7&@q&IN_xhU77F9in$%U=yv}@*qy<(!I^GA zg=HxZ*|k)wBbeI0qqPE&er8J=y7g{uTzMeAR*=_9&V{>M*oFEfkg!fqwf#%Veek}j z1@Emk?^ee&`#V3tT@MP^PJcDC(vOseN9b(bG$oA;{Cxg7&|IhfIqI`%>G;&p># zTFj^e7p^~#ydjLbWr|ScW|TF%jr<9NPl(DDBTz3!ZZYYF;Q(}Ljyf`P2>>@8KpsgZ zU&UV^#*~|3V{RgpMo1aP1>%RIoK zIA@O|9{TfbuXCv+UR82%=@=ru_QI-{rw$S#y=W6G7k?7Uy&)JRH98mo9+_gkf2SW> zKx4@BKjr=_hzvCljw2Wsm!t~eX`cH8*G6RmL9O;msiHFXeI6mqpCy)N(xL>nVLsrn zGtU6~rQ%Yv&)WWA^tO*YJoEf-H=+a{sb$|;le`xuc?;?9lCe)Qev~0f?=Igrdn0<8 zz}-B4phA*2G!E5x3B=X`PBdEZc2v)sSX4v6i1CYwSvGVKW=)>94AnhbEaUDxyARTG zem(Kn4`A7Upa&*mr3+uAh4X6VAzNn5`L zw2%YGL-2PfV9k7&g-QSqHz{j|Iw+Ioil3vssfKTFLQ|>25yXx=*4P{Q?G}`X-j*o3 z3JUkPa0Yvt*PNWPZ*F>&x#RZUv4g_L1g=7C6TWHTdLboEDo1&4<2?Yf6D0_rT>}+hL2@u9UWR&*Em88}m9;7-c4h%Z z|06gc;eJGG#xusx*bP<#H4;3olYrbIy`#&Jke2wf*}KOdbZp*=%&eD91M>OIJL~=IH-F>SK|IJ*&&!5{kKYI7z zT!a`(v)^?}D+RX?+}>l~y!r$8_|m4@dGkMbx>x(IgZ+^2Q0~qyPWqC`xwGipcsrsm zEmVr#*T4BVPB@&F1rA1-sN zpzGcb0#g+Gkh5MJ#TJpZfr$ApPt@Uqt)}(bI*@%?K)oXj+wZJFmW!7iYxgg}2#|F< z_Ob1!;X(Nc9pAObe?Y8a;{c-`q07?`i|;7Y?#w2=6%_%ki?yCu&_|H!fe&SB_~q2< zMX$%R7NCZY*GC;$HpA?VTa{6A;36y*`^Inigw|+~Q5VpVYWkU;%zknY#5&XqAtZ2S z*W6YpgaE>rdY@Q1;9oyO-p0{48n{42zh@i0D-UM@N}qI%`;7P{O_>eZ zdi`dS7WWs@kwL0dtpe)J?-KCaB{P|IM-=+ad99;y)%es^E~J}-Xkp-Kci7K`4hK)| zUc`LWr_I;CelOH>@}P-ct9O8&p#9#+qjY=PgnuGyA3eRT=8_vvo^mbOU7Umf3lQk8rLFDke?Hu?BpI&&j(3iOTO8*ZL02AhZ z1m<}VcCEyk2>@6K(|w61>Y&jAiFxEIHWRM@@yXdx^WIXBUHo2&Rv>zr@~X+)nP3pf zyjO7mY@h&vh#&P3G2r|hz-RV9SoH}rKUHo!M2W!1&_ay_*C~8+bKFXG#E({s=@U?p z#$jn~VLfx$(J81?PIZ3*0sX5{>D9Xgah>IR5oXPIa z&|)rxyo|zmI0cVmNU9%%es%cW?8&O0&i-S()57{qJ!mYY(OubLxi{XCf<1+^Fv%Ls z!b3Otgaa_LiO>HMyxm6du?<2W$|-R5lndj(_+od~9x*$FGcIs^yJP;+CcwP5fqK?1edusv%4}CA;>`QSN zh4*v4g7uPwmb`{u5|q67G>c-Q*#}7f+zz0wD}>TMRGH{KDnbu>2H#c+{4B={mHQr= z&5@)XVSg~{TrROg2tjw{*Wr&Y4@p?ils!+x_lQIkyrs#PeB^1>5cw<(3SE&WGx@>& zD3&kEid*aCWdJk8fh4Sv* z?TDR!tkG$)O`0$wj>NwAjP6wV$+1*fRxswPO4;nzxRHH%vAAvbvPfFznU>P@Q4K+O zVOCv$5_1ZYk4_QbLfVE#w|fds(;-2y0w@L2S(95_w4b3aY&6(+1EzWGf{*I(%c0^r zEguwn!5%&ZJ92&b==8PJV30-%&>>&Tm>&`}c&n=a4a{uyZ==rysAoV}6b_G0CEQMi z{3t8M&0&S^T0TUvp0M&}rM)6KS&Ire`(ST8%brY#LoBs2>G;|SQxkKN01r4zt}dj!emc z`VTg{4%@GXfdtDg&uEP_g3b^rjd8OSFfh9gMhJJE-SUu?_ChK*G0V@6AtX8VznYM_ zM`zG@ub$o7;{pqp;XI~EBKCI+$zwpAy1~>DxiDCL0OcMSbDhkt;Maojgz(xXN6Me4 z3~x(us|j43OtH{n+x;&H^w}P1g*%p&NyWfw=O>&{6(a|zwtZ#PH$LW_5S5BD=-y&K zNkqD3vDy9t6NN9G74(S~kwt_)g)z%Mc{hHfEIleaN8(3$d_l)1e8Wz2l*q`_>X|zB zN2ch}C9cHMiNBqSt_qHwbTp|LFfth#k~BKsl79JiJ54m?2E@sAj*T|ZygS6G`wRE= zBwT=`){L79%Sk5kMVLqf^xM-Hc2HyWkv!Qvoccza5b>a-0U?R`yHz{W5%w2c@+9o! zhKQ-sJQX)SU8}J8TL-FeCV`m=B7?}qr^_+214hImrFW{+ehl~WlD=Urfu?bUdLiQv zbl23sUNE2hQ}7w$ndN1V`k?XbiAH@P)Z@v%+;c(w3m94+5!wD-p#4tb{C5BuLlHrK z>U)CHO2nR*h-L-4MZqD^8AmrILo=~HDrCoiI<)(>JTl>(#h5fgY?IQss`ygpr}sFW zA6V8x@EUF(gJ=wZCMI1rX7VC2K1VLS_B-e}7uZ0oNP?G)7uQcb7lInNin{WdF=uS5E&mux}?bcg?z97q^R`R z6)JyU!6}d?m==mXsWrH@e4&A3!;k*mB>c<=LD}-qJKFU?RdY^7pq|A2Av?DK4#a0c z&~0LvvLPF_#<9I0kTOtfJLHV^8}QM|=$t4Ld~5-Iq4O_Cmvw@pqey@ZP*cyHdi?Eu zZ3ZoL}$W1g$tlYG5=-~YPYw4x!dgE9q%I> z7GB0%!(@L?x6!xASP3$7&E-Hl6Y2SFTkD=4BS8XEl5^Oyzuy%!rm7UEBQs8{Ui0Or z;wm5m`+l;*^Z!!BS`m;SU$!N4pnb-AEa@rBpkPcUP0a5vc80>VdOf<*a-e8)^yqu< z>;p`I2ECAMI!{hPv4JsilyCsKWP?{;W;Ar7DA7M=lh^h769yDFH2A_t1_gbD8lr*U z|86Zl&8-jO$TGoc`GuAGf;PPS^~`QSFJ3Uhj1=md1;2hyXT;98!o1U94pA828t)u( zAE+|owS-(-a9iOL#+@*)JJpbs%a*FP_=!bh}kCwyGuMSfPE9>Mp07G(SVhY7K zaF3lWt&LEIY?wH$dvh$9zW|JAfFMQiwMvs7(CR(f&k-0RCR@jcm(lq(4AxcCISMLWr$HqUtzO%gTxiacH)9KZEoL7nWV>G< z-JpF0T_Grl&1r+M?+U>awEfVuJXgIU_QsU*0s$HEPDtBs0piwcpJRE2s z4r`uhfp*1qPaHsofSIp^&~Ru(kiD3oHetnOw0*lhC)9lEvlzT+gNbg6I!=PY-^pk3 zd~@O%?(>67$~|%B<41*RVCqXN{8A86&Z2ca$y1$;mb_Aot=5UevJ zn(53yI2LM6U$Do7QQ_nd(^3K^#!Fn)9k1Cuo75Bm4d-L1>zR>MW#{EZX_Fu+Gj#hvWiSw#=> z|3%M2;CG)^?O=cJlZ?(c@m{O0LR=;?Y&Nj#vQYn(axSJS*h)LV85Z0d0}&7$7h=iG zTJp5FY@5H*7U;@2fG|EWbd#ffP7>E8=9m1ucfPD6;mh}!hOkYBMa=&QklD5BdEm6N zpDF}=aVGyh9e3gU&EJvHPwl#wciLV)(rf1o~N<}xz+=XwrFveY4#p>WRq62VDp z(0u)7i6He~)LW)hy0mXLu{%N&Zj^~bQTLQ8IyF`k1?lXqt6iY6L5=1JSSI9{&Dz)@ zU-(rCKYQz%XFQV_Lf6PF`4$)mtu|)bDqd1sD&?a?{R!A5&TnrN%HOE_bGs07L&{X< z7|g*i|4Ph*6l*Qfybyx-G`%sDyxJB@U2itFfdU(oCz|xo>S=j|k;O&v!<1Fa#&f-o``yrDAyhb^A&HljWTE6}R;4iFt(7f!^>8sgA$(S0hC4<< zy!W0}KfpSR`yx%|B2Kwx3?;9a$;@o}uB8|_;Cg7Xu^*#*xy5t+^2|CZ{=PF?`nk$W zp%?b3Ja9`0#~BSXmnAr}76Yyw@`#Pn@(nymU@-MyHxMucjhkHmku8J_iSd@(Qx|Qd zpo+9G*2;|2ur4P1hC}}K>ip~bL!$iRo$a%&3U)nVwkRNHSj3*aX=ae&^W({3t}t7{9IiU}`dMZyq+MM}`_= zK==!H1GzD|`h+9_5zgq{OnS`?fI z@t_zAhd{$7BTabJmV>PL`V2_J){KA_h#Ue4$1;PPvvNtHm(QTOJ8Hq%)rh@*FzYAt z&7Go;N+3icqU#536vzsjZg$`PWe8d`gWCl3i=;6yX+=inX4_D%(ugw<6V*NqS3I{G z!N!}MN-;EwZj!n3bAI~r?kADcN8$-+e$iE9mLdd!#Y45bdg4MX2l}VYb}TYr&zerb zXwQi@yJfwTen3+~a#AWoGJW4;?0R3$yC0|9`L5-w!oa{*=RDY9b&&u+-*Ei3g6}^6 zzi|6M)eyssTz+QI@zyJU)BBaLH3f#ZT?yS=4()I8egdTDcX4!mcFeVS$!+)N%fvf)kUuDy@A0Qj>|Eh~w9zNbgThA&|ghYIU zu+Dy{TO6xT@`V8D3ap|Sva~4JEhi1KxdL*hn1ga2ZT%9U5o|SlCh^3u7$Hj`*~A`L zjEex~@w&yRtVkW1MflqyO-~%91DQfCiJ|SfUic|S7@s}{C9p4>W<>?#X|?C`h^zVF zR9^d(gx0r`(5PH|J`y1?(`Q&a6^;>*xV)^uvSA3)ZJoUw1vBOWq+>_>UNCVZ5uhp& z*b%U~S=bL0<)wl&0Iv8e7Yr8V)XQYBCm$7@mI9nbYt5?Wtwo@%Xy^xEtgHBUCPyCa z<*7%K$8gU_5PnzZ0d94O6G7G|ep@9CjTZZw*z)X>W(EsZ21@(oiRfkxlYnWszQ*q} zv5q}U8ub^~1cyTouXbP#X^_+DgvUT3u}VF(hso^TH@pyKh93h68jcMs1NDl<%PSgt zJL(&IGld{$?Y`MT3d{T8bduIW%rqV%7($yasPm56Q1yWk$9lOn%zwzmS64mc3GbAMxvk{WT~ zFbmx2(#G&!ncD%y%qDcbM8sQ3(E%6cnp3IRxe+l<*<}ANtdSD?Nxb<+!w-mKUAr3RSp&}db$i78d zM7drn}JtRtoAnn zvNrpw)}dpAS~;gjJWZ-sQP7z8&kX$kLc=e|gZCj={4{b9oNbbvkM9`y#$(ric-w@W z=p6jOw7<<`Jq zX3jqOZ8C(!z-?+C__cn^i^b??GRWhe&d^}lJn!IuhdMd6(}y#+EL#KM%Hg%W69Kkl zDq@=A56x7jPP|;5slFK^wZU)lD5&sOgOv(?vdA2MfJE1sU7QsIPLG0Ls6M>(43e+U z!dpF6nlsZYhJ9@=5-|s$w0GL`JB;O*;8yDx+U@geWH)pRST0X0t{!N88B_F#_3Lt% z*>bsM{!YG@lv-x zHZF#2hA7`Jw{snxBqpp@!V6!*=KwL;e^lW{-p*wphn5%85D5e@{3M=qbpKlkc<(M; zTJ+&Qy`A>|5%uQrQ1$;G_vg$EGsv2#EHhH1jZ(-qQwb%}CS{GfD%r}KZH`hD(VkX9 zX|=Ra)=7$zkV1AUMD}GEGjs0ue1G@-xc}=>*Hw&jKA-pUdOcsL^-(WMol6BuP^XC` zctBqK;)C=lbp{rf1v7eGgw;NK`Ua0x@Z?kAgM`l`LU2YL`HzCW0eF0R0PTG<0@Lg7 zN}R2P&t2IL`&W>8lio$f(B`_eJU0MFQ<07)OmY|DuZT_4Yj|`h9}IcSWrG4bP%r@I z59k~#q6Og{%Y<2J0K-VyN+F|?sg3L2?$vnbw;j3T-RE=OyeebKS~_Qlc(lznBR#4P+23bYMGLIbM-L4)uZH4^&?I(Db7;o=Tl# zdifnTcSK>rbuLbG5_?E0&AqD&N!GNJr%5Gld8(uIV5+;@scv>jYdwh8;{sGh8(+*v zj3%>fO*VZm?+vP{%B|3jFd;GUY0+UYJ8pzV7O~$*fKZ5hUX=uggHfM(LPZ>au7N}* z(YmA)xxXLSbVV%l+YVRBWO!&+yM}#qA#J)mxmOkaA9JfxJTQ1^-nW&k-0}bRoGO7D zu3-m@>&x@IFdWS{m+Z0w6kI|g=&K?fU_X(<@YrE@XPKh|bUr)TaN4tzzyf@N2_c)U8ml+Uk#RGCj*IpdtabxEcC9~^*bZW+Om6vAc|O!K zR6Nmd0SdJ^rB1`caTzgN#Hx9RR;>Crvrm%a8G>;Ro4^32UY0@12OG!E)w*5T@yByZ z`u->{1jlOB%fthXM@4BtXye*H*04+do6)+var3RWAQ|H1q0>hzj02GS-xOJN@lh-b zLyvmw?AWJ~7)<&9dvK2T>P4x5)lXe5F2Z|n&l|Av{&OvSzcF}#cq#nx4YoeWtnAmf zRo?VsdQzHCT&Rg``P=+~W3SsDRV)0xDdm3elsYkLKs!G7pTZ;pGUvC!$0JO_B4o`k z_st$K4~`2K+f`m_mS_Qvh?YgsfXY~UzGf+!Ryj{>IPRD8EZraJX`e<_x(|<{_2^=g ztPin@r_#Vyg*GBZ+!uGD%Lx5~qb@$g0J3phCkO-R(EKw~YhlELqd0Riy0w2HLab=( zP30PW=bh03H8fV_Qq(2^ZUlQ!?!U?&--uI0+1WtkO9^@2-YawNp}_1vZV1?9wdKM) zZhi;!7EH2fY>TJ`6!!&xNi|tI;wS^zBmeHNyWeyw`lHm_x3s97vnrDwC>3lPadL?9 z5rjFdpldo4BRLK*|8MF$JhBu4m+1$E30T%RHzw7BBt@=q3t`9X@sJL7mU{-+MPXU7 zkc94qvp@+H)QqKqryoQ>EFn?m`FL7en$-=Rg2w_X%ZS$@iw;6+pkH@K012hr}3Zn;LFlH|Wn>JBzU z^1sbIgFQFLV@g3sgzkenuwwvz(WI+5s{s&~4(La%o5Jtn5s}vy;T)@1zZBh_%9%%z z5iP<@Qvm}%DWk|#&%vM6c_f~%TjhbmgfA2+<}T$zWj$4*qx7@ zK-QhRrhQcg|7LCF{3nwCOsV{(1vRhASso%8^Uh2$wG+4ar|x6IpyH>LBGr6U{C?GW zwIR|0yJ9pHun7Qo*Mbgw#(kdBFb+IQuYb!OeQCTsP`VPs6V>*6G(J~Colp(lu{p#4 zcB0Vzus*Gd*kJDo+?n`aWfZfwr>4 zF1}O_BFk#>4Ba`utS5|-b^1xQQ7R3^tv*lONHcK^Zi!ZL|DkgF%A}w4R)hBMDY}To zZupN|gR{H@HGq3^B{S|0@p6t~us%hM#lO~~m`8=k^6x{J?4#*NY4NpUa-hf&0aoXb zRMoy2x~|?_R{jBy{2OUFQ51*<~fN5p6O=pDLDJ}TOr{+{k zK?vXo2}k&_UG`L)?x=h(5i7@V9vV>JXJ4&`j;pY!sHe!$X(0T>mLJB*USt@{k`*m? z^M65RUEY5lcMR~1U?>k2Ma124q1rqQKfHv$k;-|ma7H2Uq$Fs!ZdnqOyxfr*%@f*+ zVje|MUdV%b3MfA!?iM3U6jK!btZ}AwZd=$rU$Sh6YJD5`dG6y8KLuj{;rl1gHE2PO z#y%>1wyS9)6#|53eOiN9Fm1H0a83KNQ>pnUv0yTU=HAU*D(pp!Jc0~j%=-c+w0to4 z`4Z_s+EM>-FZRfeEFs=@?0G zjA%-GWx%3|B`+Gmknf=3ai9P!opYq+Nb%s6w_-WGm-J{yL)Jx~;VLs}P9Zs=H5C#{ zR#b?AWZb1myjIM#Mq<7@)6GgR#qa6uNQ$`*iVLF)Wb>0iy-M+h*I*H@fhyIIf=)nS z>Dg)4)!e~tD>w0XEoa0~-cW#O=USG_H3}m2$z6O1X~TBQbn=E3VVfw$qM%C84#x3M zNAzChN_(r6+U_*+;%zPx5cY*RUznzTiAJ9j)!;Is3q@(jcf>vSc5QZ=YIRHDAEIb)Ma?x=k8!UaCx*r1q8zW!+iR zWQ*hzk*@>L#aUTXcS3nmUB@0`Ff%+Qk-L2(JTZ0a{2HD;{o#T}7RW-5NXL_h%!J04 zLbxke{771UhSziFnYNUx1ZZ`HM_x*$=GvuaGqpj>{#u6;>cF;ekm|fh#$RPK5xyH= z9lp4A3kH3BkNm`|Ns-m$T+ueRf(+0BYyK}afOD%c{Ic2tQJ(>wcFoHD<$<>+kHseL z>q?4HoHAv%!zVftnkU)fS|e|n*&;8Fwg=J>2&Lgc-~5jR*MLX+Kfz-WctXy1)Xs{S zjpy&~RL(y3Og9lm6)6hy=Rcd)K7aDvix!9(+kihkedU7Tl7EvGUU}>oq3+Aa!U&)5 z%w(8gCo%hZCMN9z!sY$QyRsiWE4g)kQ~90O0kYbd|dVf_FKXM###bDARo3GWBqFVIaJRit_1w^t%u?bS0_pl$LRh8bk^S|7|EbDIRKvpo^rOndj*q;gCgM|TcOCniH#*`g0II}J#+$G7 z3a2ZiJ6ZT7R37jH^Ik9;Zi`gKzLPpnmfb>O%- z7m{+(01uqwcn3q}Y={-CxxRl^{^s|`TjRwF$nI4tufY>@7(`S~c*VW^yO*=vdy5Kg_&(L}J zkM1P{DzApiKW@OVqIb`&HQ&H+I(488pO13x?O^9unV{4@dJCLOZ$cSWWtSr6@|Hl3 z0()CL2diI0WexvTC#%*^+>|3|6LL^?gkI-n^ok0K+eK$m6Lm$pq3AfbYsN6fO9%WC zB%a!KvtN+W(Y$qylVBu5n2K5aP$=k0U4lJt|1Dg4dgG%3JOwO%3v23=!Kl=+d!oLnhSDh@r{h$pD3arcP zrQHV~ywXHEl#)mwi;97Ssv?NA%i`i9JVPY$E{%$l8T*w@XL$?HFxxlWaj?I$#8sVM z{~~AbCo|!c0K}J}u1rndK-R&dQerI{-`d3V_Ri+GwMug!l4>f-hxqmtn25e0DZX`{ z*E?@!N^B8v1zeHQnxqgx*KvWh;)bp}Jon9&3mywMwnf55yzcs{0db0?ZkjH!MP^B*Os8j8dinvXOP zZJdx-m%%_@xfwvt%|AP^PC(hNSp^?fo)6-zIX9+?iq?VH@-MUvC53sYbEg-f4Hu0* zsJ_*Z2jXzEJG{+&#Sz!W`3w{~_i4z8@@6iS(3=(@|2nz|axaAREKCdP~1zP72F50jVNaEWrJ%T>Qijcza z1_)t@SRMAsRP?z&2R*mOVh+qVpbhboxawL!vWACC=}wlmjcb*~z3Xt`2R&Z!|0=K= zoU@h;Eao>lKhaXjvcA|~a-)t2a#)db&%1O_?pM-g*>Hv1=Z;O1!{Yft+VV}{c2=vMHf8kv2tKxW|O_>3A-y*}MRxQ3kAnDjWl6XBj8 z%vU4Fkhj|VYB(*@JM{v+{b0p?QJjWr{p33|8^Z{(-wIq~!QfiFQKWVEKxZmE041wM z+0}1?U~DD_KMYCQM}+IeZi6MIyOZS%eCr+@&|21l5!HPAMDis47_&y6gbL6c^2Aa0 zHyJH2SlFA_v;wf~m=}a3b58e8p6p|EBKHJyrVRer*x*W1-%Q}My+?>iL$6O8T$Dvq z4%4OLmqBZuvQZcYi=&mIv6#)UcUm-P`A8D5pedEMZvO2FDe2F~Y6Q^6sLX0Z_(Q4)jtl)7`1q zZVNG#49zL}^IdlSnS)Jrv8|Q+1KBCGd@%dMkyx-=u{u-yiI>dQ(O4yJIe&zDXJ1c)1q6oOWtwlTi%p zlkqnC-=ZHgPv&n@1Bcl&8CDN+T%=)jCiGvQE7g6%L1KN|cQ`jr#oQ@`ugAC4>e-q9 ztrnnh5&{-oB%|7VgSj5*0bk;_j(u}b$;?Keo74I;1HUF${@{*wm#mdutVC#_k@2Mo!N|R+ zT<;X$Zt>S>WQ!Q{XF#zExj(Qy9=;)vpMkwUU6L(ZGu|77kXwW?Y+KOu%dQJ`?5{WF zP^+w?B#f;>Q$bhV%?tr}7aD)r%?^-}9=v^S7pwbrm>5ugVU94Z4P^w3Q1LahrCG|b zu_46W3Af!80P7JEZ)2uboFmTZAU&F%`Q50)8z;{v2{mET;3#78v@k7+$lr9}Z2#0g z;N8LxboJ5l;Xf-YCFKrzbXb^c3YUN#s4m!*~nL4&Z8_}TI7ICs`~`-Hr1TfB!-`g zxW0(-YRU;2O$^6p{LL;IQ@;5;+-g74>bm%%&-=-QF?g#ai7VWPRRJ)V zEVYLXwrUZRb9bKg)1=ImVO0mQJ$`eo6Ys*8zE-LjpwyY z2vga(&}Y*|yX6SbEQ#Tg!qqTt1QO~W#1bj)A>KaDi<$(3oN?vAmrmt7g`eUoi+IKJ4ry`WujZ(lq^HheSDZ9rSE0?dThU{D=P4{mm|6QPyeU zm%f|%LxnMQy6z}sr@ChM$6k3Nd=5Pj^k3V4C^I2=L>1{n3%r^cfYmCEc)=0K^xBL# zqBlz2<ND74T4_kxioxl4$;iOd0$w zT4gh*bWvA9dajv|c=2o4Q%+yX*!(%~8I7R>A7kIVDp`+G`e1a-z0$s>k6kSvb9o!n zU$CDJ&c6?SQWK_)wF z{^fa`Ph2hsdl8;z(Uz4^wj1=<9ASDelMnx9#|jfd`kW6zV3A>d+Y|m~2o^L(z_p}7 zVp>Q+2W4>E#t#7V5LF!!LzU;?5x-~&!<_lI=c%qx73@X69;1F8hounb z#p=TTw`3S}+H1nJ%ygH}XM*a$=#ii4s$|o!hzTO;X=%0{SFb}1gGmBaS^1{s3m}- zl+cx%JrILBGZnrt@9eNGG0{;L$Y8?Xg>#=0bylDr`3*;ESsihJ7nwFq@1|E8$WT8U z7aKmmLL>Gz2QT%Rt*j@yUhV!u90}7JS<+rD&p0kS-@W~Y3B?^Y3O%p4*W5f!dMK*{ zElL7E{60rdj5Tbya!%Z9x<<;%Ouf#zHn(??<9f?ZN`xXzzCo7N3YjF1)U|q`q%1BZ zCsXAZ-7eq5FCfb)vmmsg##nheVd$5PyGjUp6VA!2zE?$wy8a9BId$w<5CD0=gy)c3 zzXF3`U-o#?Fz+p;70cPi4aQHORDfP)Mtk5>*|Ww%>PFBS-p*>AE4Z$;T=)CSM_NyH z9j@3GbSx>oQ^!803^Xl;JNxo+Ib{FcxAy}4H~=Y^OKl(CPK|+*-YT%hx`5+@;nSl& zXJx%K`oJ)LKQY;F9nWqp$T}mZhF*=N46O$l)vOF%z^o1sN2!$<=ZLTX=(Sn5jqmyG zy&PGP|L`MZqi6jpj}vA1oU4cEvVpkrgG0R#+QnIfIDHYYr5BA#lNVL~-6==L7g&Kba-8H{Jb1dK*NomShEn$5`JQA^Hx>-$j!e4tDi|P$39c7e3ZvFjIA2R$ znBq2*za(J}LjS8g`JQ>)t$Mow6*m_@8v_rZ!3FcG0v_5*s^%w zHT^Xn(d~d$%bP3_+N=uJuKMb5InxkMMhFhj%>8v5ctJ_xOKxZVjTJ)|e~1zWs+Pr^ z)j@}f1vBqr5(~(9yRgdTjqI^Mr_&rIj_q2Tfp{NHTg*!+!fVCxyDG zRRhfvitfv%5*P{Xk>Cfm5O+z)<4QMsH$U^;3+#iniIoBLP*gbX=`Quv{F<8lWySgr&np-4vU@({s(WPwNqm%rr1P@}n>E(}$} z-rK7jvZy>j$U333P<|_rPz@owxs+;;`(Q}bii!?Mqn#wjue6@I@lP5=xh7lHl+P3U zFjl0SiavPCIsMR9>w$tsSOHzUF?1oMXtnd+bKwG_)HA3mp(=Ie!+s1j_gNzhWTj zQbiFOK-Nj;l`tg`t#RHDfN(PH58q6@sf_NtdfLvdR<7qZeija|B;rh^87~R$Qz5;H zpnH3YL>k0$Wj-XX+`Gz(Ja{u^hVM024AsWPPD5?H+U`jS|M}>J>ug_w3JYZ`;%%Pw z{SExN-!aA#VCG&q`T8yM2F{?@lZ5 zT<3B$@Yj;x*W5v_^Do{)NqxD>;(_uhJ-mU?K1WcZOoSi&iYUbwCSt)Q(J6yJ9D)e| zk~C6fb%I$e8PXo9cy_??;WV{Nve2TwA#+X#$;|b3Iwy5(Zr>E!_Wk5)#M*W;nkCf} zB)diGohs@p`F4l20F4;n;KqSbLKAU#>+dfOo{&r>gT$^!?f+D#<^Pz{b$$-=F4}1; zqUCTtXh2f(u?NUKwtVSbQk>ba*Il7!{-Hrq3x=mFR8yIKC6UNKHf;`i_4)q-2eA3c zeKiosj0Fzo4m&JaKYCmrv;i>QK2P#3vApzAy>0K_D}sV-8Ib&{7&i>pUd~g^B|!szE2Y8P8!lu9ivKaZENaCAFNNro+D)N_^#h!86=Qf zkK7~cMvp2_wT88CpQ_2fQ1)*oS}N7sgc2!(ZHJ>ss{y(s$48C(g3QmL$M$yVs|&IR z*Qph{bOb>hVQsHY4c8)g-0>j?4K_Y+=xc!&Q3BSXnQRVtz z{xVs6ntxUG{vi@;#o0lmJ@m9?>B3dWH*3KGmFKr-mMF(&Y&3gH*4uK>OByi%;bw1oWB(@M zSDc;%RH;ba3FE9gDkR9T4rgU&cC1nn=)y#D+7sbVHDPfPv>#MTqS@;sjP+(ZC9HpyDv~J3-Z4oLg<$2~DTm_NvcqROAPKvUT_dmp9=P5p$Tc4RHIar&N#S=y-kWJ~ zE&1+;jSBo}m+-KLW zW6T?+af>$LF~!;OB1VLMzu#XhEUE|k4dJXO#ry!6tqAW4rgKdZ8CjT@-Md7L&QU$Y zz0b5PdXbGg1+yU-%X~Y{@I$0}`%olv+FfAIaFRe-f- ztUL*!@#2WH6B-TFeQo%jJQ1`P{&6+Lxqq!Uc5xLM>Gl3O0adA0j6P4+9^o3Kn@xKSBHoZ2Y#-Kr4-UOZVr#Yl1)VQgag-*Y~KrQG01q zYE~c%PXe%VQo9h6${;KEO=lI{A>q}-yKfuQ*1E`r{Q64OoQYlXJHFwyWO>nR?E4vU z>cg zKoA~SU&zNN<-rsz?_eiq=jS|^MTG|4);WdE-B~qSZy*YGQU+nTn zV(zQZhqNzZoh@?WV6s>XGer}$bbj(s@4&YsM(F&ndJ-!2)YIECN}tyudHwZ;O9}#W zwb!q&Z)@7SMeE;>*ArfQUnnS7-R8ajVkrnIN;&I9;T{5VhoCXk& z2n`bQKD`USia|nOzXQ5>DXP3>uVscB`ixjh$KK08n!Ee@Q|+Qa7z9P#uLMELLQGMr zh#j^c$)Qx0J1|QY$+?!E0NIj!Jj^XT=RX7iaTQo-5WeF$6|t8c|Fj&$6O zXV03yE}92%04u=L%}#=eOQ#y*M;5z1W4wFn>w>A~AwEIPOXXd}oIgnBGWe ze}e|DhV<+Xlmo*20xz~IZaaXhRY9Tx)RRkrI|cN2!>e#pvD8hou$%r2aRB^JFAM1Y zqcvAUPstxYN5qEJ*RiD}*bh5Wo+a;W6Zp7LX_4g-M+kr{?OyPeTwcl*XeWy}T59$= zon0sQ%K)9~1nf!as2+1C7jI zy?rb4g*y(`iTz(ZiHZdvk%>?#FU^J};n#tt|I+z+cH$D>1iOqb7Lpf_9i2S<7rP}Y zEYd%hN(JkV87`YkP`0D%XVQ81Ifr9XPUZ`hpNAYzdSo@>RE&J$r&CfZJYPl1NQe{w zZz^v;^O5&KF!HjNr)fkhLuN?M2JUT}K>E26Xc$?}k&kaZYY04~C9GeFE(Ay00;cXd z2*-olA8q{-qFty6zgNxO8Pjn?t%1Gf!`LHbe-L0k4O*E-L+-P~7JN85)Ta;Kcx?*z zifK|j8@@527Gmt^(?PM04?RQeD~9nQ(3JtP^YTC82luBuzdRru!a}jhIA;NxSgew@ zMa7ywcljy<#DR#`jqbNXT40sl79Eiws(PUFU`21IV3s1NSp5 z>c4pcyhMsBLqn?DtiWgUT{aHmOlTIA0DqIxcYF}0`L#e^930l~+np6_=|H}$*Ox*^&&t2#6OdNm1`2+y_h zWC2dB)y=#hse_zoVJo*HpZUeSyhvWc@0{f^_yy66?*GvW|2& zHDoJ)g7yVwP-Ve*k(TBxJZ&IrLfkDQdS%m1X^KD`l@DkqT}(xtAzFKQQH%{yr53UI zDDWNh9U83V&|)tBJ8zXRmv9mi54~Iwd}=@nKYpy^$aYviL6d4k837H*A?QkgX`{W7 zDl);Jnoe5$D3{PzSap1_B%(RP@GR$~EqoP@@8DLEgHiyWmvE8&2jp3C8}KBUGeq3X z1S1L~5RD{@*0zxRl!sO*%zg=`?8JOcX5WJ<+2pR2U^b1Nr!okYrw!u$7;g`=~`$`!%b-xy` zlUvrFV{hbUA^aCTfNlCHr74Mgob6m+JiKR#@WHwjswhJT(?B_c^FZT2yt`V=pT*Tt z{5F*rO${o20R^ZL3O)j&J!b?s1=uBA7y=>KJlo};KF<+7Hpua$Yj5<_F;M#`UBmEE zg+^$0_9wkx47Tg$Uw7g$lx9vvH9Xa&9&V_Jg=jvoXrrL1qNWCNw?kh?|4-+y`_J3z}K|3Dx+TzJ&o)JWKN% zbx3rEd~+81&UP)^@1_(t<5Q4x^mVQQLdDuojdhlN8Vi8g7>4^wjz>gUU;HyZ5To{h zE&v?NkARg%yKIzF=!-^ABw2tNZN^??NL!CswIEr*a;&v`w>I;(6lGtZ-sfNNO&)bp zlj>$Q>FXHqRS!7vHoU!G(fH&O+}tXVHJsF=Mnx9!y?yyUN;IAxpl%A~RdV|>SK;eH z1_$uNf|dr24Qy|U@?Qp%&^V(Nn-==-qqwE z;g#^JekorFw8N!Cubz={kO+NJRNlSqDr*BrW7+?P9EuUo%RVqRHnhi*G-gi!o%|2U zZNdR#XL}0JaxcXcRxOYHo&NT?6bn?IBt0bpzJtU}6L`<;x?Wrw*a;9(1Tw7&@ZoCl z$yC;SUqTiFuGGdCH^|2)D8Wd-j%dO*Yl8X2e-n%^TE-h5?27y(y0UGGF4=Fhc}Yk8R>=Q zGzdJF{CqU)0myZt^!a4t<9W5fQp-oD!q=#@H3;CaltnD!M`;qoBp}xDt;db`J1BWq zu~fB-TEzK;{O{DG*Z)3bw~V1f32@JKa?5~%tp7MJ3Hl-DhdeZwPmXxG$$t6Ehl z8CNSvItqGrm*-k49sk?hJYBWt%AelJHkaqx$EKr90udu^0soG67nHF)IF(qtcddiZ z&HOUlTNdoKmusd1WuZyQj*U$5shV02$lP5BPY0Ah!>GCkV(ICr4A~f&j*w0PRP)}! zwsp^c&F^!Z(-^cR1hm*;a9V}Q()2b|_~s?nUj}Wd`WqPXPwJtO10gT$n9iFAsz|H< zmrEo7B09J@Qqzbpo<J^I$y4F?+GT`=; z3Og}TjrqTBu^iI*o!{*o@^`98Tsw`7H-RcT^#w6?Tj#iQ#E`lV3^xkTvlCu+##Zk{ z6P}7Bw8-32#P^;3oc=*5$gBSUMjIk$U(dnWS_OZ>ga2r9=V#WIG6!h>D+WjDWW1*? zGOhHYtyokzve)7`VW*gSh*gx8x}3wDbNx?rUy=_YTn|cAX*u_Xs%r;-0>I~OnGez8 z8R(s-SLZlAEL;x_jlTMzaV zu&#A?SP2D%5*VtNLo2>>hft@A@pc(hvZiPO+Gf1-AF9My!R@cesOxIy{MQt8vo8d3 zpzDQdGu|{yjNS&PS<^kkxu83D{Af^g9b~_Ve`Md((hm}+o2;hw`)j__^?6Cv^mlf=IdZs8$q{|3??r~lH30=Ph&m&<3dhD?4de!;D0B~00d_F z)AV@svgjOfl*g|t_z7?wND37vy_k#(wkVd0u$+BvoqB2^`bW>Ikncq9=Pe}CXJJAl z2wj!eyS{rZ{Ew{c@=w1bb(ZEhL@Ri}Ve>WrCa`uqMvtBlLdOO@0qzlv(1|kTt;l2W zYrNR4T_P0)y_k1m-M-9J$5b*td3_n{Ij#h#VGnA1eeoON>Ec81+nQp3Nx{Poa!rFK z%?9lsHw}2K9*%xQr=e7b`5q~0(c&1ytZ@^5|4O`oA#TNH8Ppb@QE?w3P=$XzBHE@( z1ASr1;l&Pa*-LH*G5tgg6-Kq^-=AAwz<-qkcWdoiC1Vt}B<#41e5XJ{uRX&`OYJ75O`!R8eq$lV1gD)wl)Xow@-LnEnl)R}y5U`vDZ=5p@hmw(H& z)Bt?joCmOB9g!ReXaspGx1L4ajjSh~0;PL_sGZROc*~gQjh{2ydm)$zQcusUg5Z}< zgr64%$f+E@odSER47AO>wX&D(VcXo`ml4GW7WQonpDA!ZoYKGLp(;?uwPDrRzPElO z@PS}CG3FF`>B-c!od8CsL_&6Ztr+}$Wl@E4TY1s@PX4(En8j1{_b^lKg7Iix(micq z?og=HX3#wYMg=w1IHN&GCs>4VhHd@=8ah&3Vk(3{I;I1k`axIm^ov6$%hRELf{4_^ zhI-kzjoT7z&C-U)c89$9cgk09O$$>~D0oH`{H=UOO!Za;R$XZJmc+ueQA~P1d9k$n z!XUKxH_X%j`-V7<5`|(17UGoK@xxkm^fQIXk)4ULnxx&oCx&(OwtzopF5KeQeL!2k za!=}wt_|xg=*Lm|d3aE{xznK0$be}=&Qt&&ey96`6l%|Igx*jEfRiT3n1YT=;uwm| z*0+0z+#e>gFOl(K%Kc$D9vDL96uS@1E~r#cQ>T1I+`&|dGQU9Z!Sq#}L7PzLt_En+ z&S#g}SASs7!EPazK~g1T^DM*TLwksKb_>%9tqDyKk0sS&BZIl~V30UiV+E1VckQ5` z{GfWpL|QaDtqOX!ahBQZyHx0jMn3GAeAo(6MWqrDtO2z5V<5-63s(>?X>yd1AlAW=ALbjV*+- znU{&ArtGcBncGnh-JVfC`+&^omLFFb-FEVy4*FYibfl>h?OGYa;JlEd<;boRnUPEW zEl{b>)=tuWyf2JXGcQ*k*U_AoLBLjyoB7_8LP9M!24D2D_~FW^e0@u9k_jaLvZ8CL zNUto3W(7mg)+LsQj=Bt(Y`;mApV>6nR?skcBGml$c<1W501;vOic z20DY~X|^F*?;MP3F%*Pk{t8>2s8A3Mh?fKA;8?T1Zz!1>5b|PlzowY`=*_Sf<4TW9 zzz$p5>~|*5?Sz&X6&6;m7lSvx{13w3?;<0#ztqeG!x?f!)eJyA)-RgX@CJ-UY5(uDcyUXxTIw z3$rsQ1Vy6W9_<}4WDy=6F#ONzIUOpCg$9@Ie~NI4sZR{*LCN>yuc}6F|MF*Vj@tu- zJ49t@=eWru$MLYF3y}7J?+mko)pl(dgb5sMa4oiK2~j5IQ{TyU9XOW-0Rl-;uU45t zfdK??uk)8d54tB~ioaIc{l}R(&WheQ&JTYV(>uE#EigJlMNP3vY$6;)jG9YFh{MBn z>4VGa`P==;+Mx4BRLQ^@rx3+DfmF_5ku=tx z60cpcRzsp%b0IAnY5cdEvL)f>K6-1GS4iWF7T>}f$9`UO$$IwrP-ejS7NTQ(=x|DJ z(c$5Mnt6+QWNVtkONR@&>$%%P2zJdYTT5%fUGtu@j$)xe7!F43--PCvgdhX}-mGUJz&^)zfumA=AbkPq3{dz$R7|#JeLq}= z;o;@-#E!ngrkeaZIXH8cji!i{JphL~7M@;m`<20$Z~_#z=h)A3xutW4+3G@iG4bmR zQPr?$s?B3DYA33c7LO*45UplEgq0t-uZ6|o#Ojz*75h2ErTM~u(IkvwEq(C~@iKnc zPoNefyg~P#SL(L#F`@;Z#+nV2nC)zn>v}0EIGD**H5<&tQpfslRQwA+&gw9%8?IPF zN!4TYUL?7Xux2e_XeHOxGs9lInUZsT)R7{0De79!IR(89Zizsbe*BHOk?A8%yNVdk zA=-4DA6fmJ$5iNIB_LK@$44SfL9%uw{=7!Br%jIgo#a2vgb9a{odufJ8Zy)xHeb|U zNJ*a7t%0YdG{y!jB#~b=yf_F?py4#sSMQ49nhK#c8H)Ia2h-a7(J(X3w=Va$fEyhB zSc*kO-Y4@{b~UY1XPck7l)Va)vQQ}T7_@gyX+)-7iLEm33hpo`g=`+PXmDE<;$->B zZkd*u7cN({4y6v2$jZ(ny*%W;mJ+FkSe16FXwJOYwa_#S`VFj0J2RTkgMLD+^Ps|5 zpj00TWiLjo3$g0R-cou3;dk4R`=7^M9!DvN#|OdSmoJCh41njo&%otYWwZFu))sY$ zVV3RPgWT_c9!j`6jq3cnC17dsm})@OT+<^IRFkB{9W|X)i|FK7kB-!5PzLhTD9Et? zB(&ms$?3x`$}n%bOvc?Z5FcWaI3EosPe0Ht`!7&dZ9D7->=tsirlCaHkmtjo`Ntp~G94`vHASlgapRh{$KE&7o4zcS4E>7X z-fe%|7bV&rgIQ<~eR3&&D`-nZ2v}9`bBHTtY^H;}36dg1hQfqcg9_cP$Aujcun1*e39D zM0lIl=Xn*Vw0kQLbj&~Lxk*B#IL*Y~STB*}6n!7q310?BRf1;BoQ$}a6C$a}~5 zP%V@Cyv&r!ItEWe$p~-eL_A!Z>X_V05|Sk$ADH?z;D0WG8*8ZD z5F-14?=eE?w*Pq1tM59^-rL0#xj4Mah_+cbWiZq-NU}dGJb%D|WaL7{WiFAnU<;q^ z&?DD5uJ5G(x?>4%c|BJ))nP#3cID%9``%5@r9%ayLbpX-#Jm`StfPRs{5%x|w6Wha z!~dL&5i8YH%dPZ@MC$4yt}2--$4f9#bRS^g>!rAj@UzG|Dv#Ef3L3B7i<~-#7y?}I zctfRTcd-GUq<tv6S&*TKfi!!;N|Y(5{asx`rFXKtIA2c1B1Ede<2}%iYAAU4)G6gRLJe zLTmG#25tlQb-ZPXFu(Xpf9M_{0Bamg4jwHZxZ4o@3r_5i?W_LVVzRD_% zCuT7eV1xWUC6I6JxQCMz@>+zVFcf8>1U3&n#Wzo#ZrldfEKlB<|Ey$1=8_fn{(_Kk z8pAvkS=5DrFks?!o}_TrDG-fW_jZ42YRDV^q`7Z;8ze!a6?N1@qXEx7KFUah?1V=z z$LqxL@t#i~+ISu$WOVpUN%?X&uz&*Rkd&%~#W?JtczQ(YK-RUBH-sFUqKF(4_D(O1jgp3HX$ zZD3j%XqlXEEFI(PyPc1kGD&kYJXWy7lMwd>{t6`8u?~2H%HZW92JHT5UQiQezzGzbDR-&i92Bm64*S9{3vN4tWwR5JE%c@2sa7?FA?? z$U*G?^C-~^mP-v z^!IDU-G+%1|A@JI?@t*83?T+Vm`B>3^i>jeP|<`Uu^hlkM5$94s53$dsx*-_L+mC} z@=pGCyWM#sIo@dw6eEOwh!z=LZ6~^PzjzDS(NU)?6l)5V>`IY~-foL_l98CX?+<~^C3bv+b77IowjTf#Tsm=M zYLa)uHOi#H`0M!k+q#;lXfvY@OO7R4oYym57IDPP&i3A;VdYGv7Me#Wp^5x8H*+=- zKWj8LP>@65g@xD}DhkBlQdRJfM=OldW|?hQzFrHxsU7`-<>4bdFeVIoHfW0D<;;e^ zq>G4iwsFb74x6ryswIo)YzB)GfeH@xa;y_?PO4H#k*zDKV_7SO5Q{zLcWu$*1ljnRH^a}^PVL3Ztm zSkBl%c$G|4kkJ){zSb@S-P!g~TvPwXyeE z47^kpkx<>7Y(^Vzdd-TXi3RyI{P~ummy_d7J@NovQ6Bx>SvZ}~!&(YO6d(Ope-^&( z1q*=9qw0sfTV9cNP+pSZl}9WRAk;pkwJD zX!r~dXFihUmdRl(8)m{%G)%Ks##koMWLluw`jjL1U*09{qzn>@kT@h&^7GqzX?gV2 z7!(K`&#)*PS8I9niUf)4CU?Cs)3Gl(P@uueW<>L^98Q0}i5EQzl2?4*)NH%h2l?vU z>!rB^)L{Gi$zR7>4we`g4%DS=z#qQO_nFhqf1$!^D_Hz>b+P54l{nZrYZvFuVy9A| zSBe<;IK{jourDK)hZ1e$HRevwb9W3J~x&irdREHn%AOH>fM7{g5KC@*<7 z#;+RTXB*ZqTP|(vW`ApLv=ruRgI<0ir|kXRrRY4?zkY8U8p+e(kAqUf5Yj{4sF3Hz zkYp}}k>Y_qIoueM+dEO}yEsurmRBx_lQ4vrS;(%t`%V^W(s8)S2i~jZ(k%Bb-@r#95b$>R`&5!yRFZz5+Ui&zo6( z2F|440?($-;7#s<~dN^{~ORMA{xX2C&x4YeV^dy zGmzNYnXlK{iOdyTBKr5A(hLeli_E*WIx)0y;gtNy9%KBj_6BoZ4CDU$HE4&YDoz_) z@&o=sgk^M|s>=M@>p=-We;u9E1nv+TD-aKv!%$!}0BaQ`+}=|8vUq#;Ve`g$YK-Wl z-u7No5~tT%x-uTMmk|)WxEe}jxcx_H*j(-df4FD%V+k6+_q~r&6EWlB;7y%uhP`^Vvo!Z_Q{ammf3b@1cLWzTt(dMso!>MMdU;>e?~95chi zQ?cxIIz=#HA~JkTM=c9_a}`fDo@?$~rJ8Jo7-w(Tr*B($h8t-s0q4RNdCjDqHXBps zNz!@{LrL}vhK{MXrm&PYzJ*~K*xW$~H`X1UuvypKa+LD~cL!_C_#Ip-gZ>-VsWRYq z%5m`zeC3$Pb*qsdh2qe+(X;jGdZGHaMNPp$a?@gHdUU=z_)8SW!}%W$j0ZM8zhD`j z1W~bM^IpA)UEO0x43T?>2}!kK{q2r{MEEyZ$*Rctx#3+8JjDFRb{({u)cO0MRIl5K zjidk@GsMUsvecjf`hQ5e@_4B8|Nou?ql0mT3L}IL*OruPrc!EEx@#jWTPo#9j$HHU z*pM{Zwp0q~(BbTIn@OUL8Y1KxN4XjIjJZC)m+$YNeLVKD*9L zfpsC1l{4%H-ul_6dxenxAimY)A-3~T78?^iS6T-a?J*!?RtF#T2m=<)q>|7k*_TO{ zu!&x4{MXQwOJKY2&6$wzgs{B!dL?S!i$32u^}%Yz-y!SM+)~SaZ0B=CUkNH(6~QHh zaXZ>|#S@ndj6^}G(-f&_Zh+H(4@=L*einv3Bc6g!>S@;Ly8(rL&-YUjpTQ>4qk`Pr zh}hC|U*@5bTlxr6x@=CJL~2At+KPTs=d2(ytb&28T(ZTph@bl|n$#&Q0mB^Z5X}~OJ*lSlkA!$)eHWKtZDoWpDWMsDzOJrW( zSyDY*pf0)g@fnICQNrJ42AME~^dSO~!Yq--G8GiTpYY%*#!+>~Fo z;c-NR(wtfB_Qm8Z&rTs|Cvu(j?_9hP&}CErByCxRR;M zP(rKcX6ha5P;QS-(du&~Se#SB`NU%WbC_32JVnlbBN%%cXHLV& zKVgp;>Fvb|3+5qTBaw}rc8$TRffuthQ2i>F037ZRx_CNL{(wHyRuHRBTXoKYwDj!vr(@db9mm&^Eb(oBOfNo5M?9 zgPieO!P7OmXLes;t^)}|8+cV5DC(aOW7#-!EAzvh)21EKDN84fMAP2B?#vz5e_0Om zV1@hY;5yV0_*iYmAD3+E$K|C4hQl;2enh&)jk&e8DQ~-nJPKRFnWyM92)SjgguM%> zb*DxKr|b&5whq5?f$Y}Z#G8=;5a552?V*mk%@jZ`xnLeK9ijoSsDqn~8jt3Yvc%O{=kn5SKz6id&3-5aIIteXo-L#HpYOTnk^i0h*e1RzZi9SVvbrY*a?;)t4xv z0s${IgUvndbDFkzJrVQ1%qC$>!#o!uy$@uD|1!*Emf0Ii3Gg;e=E51I+3v7*Ml67F zRv*Qh{0HPLAe+OPrLbP?t|##E9i_dRgM|yfiRmr`&cqB;161Pe>T~#_u8805;f3=G z`i+U4{A+&*@$#S3Rk38@0u>bcw(Mz7p81zS4VhmUKHF|Np2J(FiHG3?(vzKcRx~4o zPi=SHxL?2weIQ7Us_pjJRflT$*@~W>X_v{dVT=nO z2x%zj+K;?zR_fxO$Vr)6aGK>c-ypk1+%iY&?o<=FWP0kV`R#=4qX#``dLf{vSDWFR z5{nzRH@m7Z&Wy`mYcOgrpe6Nga)>H=!g1mlG%ki5xnLkQIBspPqvgAM;t(<%{2^M> z$W7b=-Rr5fFpN<|+NwY2ph8-$L%aM+r1yU7drpDh`?`P4s06tBj5Xs8r*ywZy&z$? zGN#y*x4OIv-(!ZdrUxNVj{J5pYTo5~GD~p#LhBSBnnccqpwZP95Kh1wl#@IrVj0W7 zRjJ{y8l)R2=?j-4ECOc@6+sJ{A7dfnB(rCxPUH=_ZvN<}h*QwI2a8uW-uGM7%Dx4) z0qC&~q-(U1Vw-+WGlys2J&D#r!l!Gi>$ZQK=rdZxda!No`}C#3Cr%xAytn)QKNhnT zG-_@?6^uG7Rkf$$5#uL`dKN+jyKpsm7y@frpo!IPDpiTN0o{4Q-_Xsxk`h5ijtd&L zzQ7rlD!lF^Ai!87u@j)|gaKSy-BF3Io5bJ)0jH0js} zBeRt#E$f$dsX(7SWw0w%Ng6bTwnL?sR;IZAgmQ}v^p za&qQAc7^pq;+(-M&Sq(ve$(w+f;*vOC8Tb^W*DS~0JKPqy-kX-!jKy)Vs^ zyuK?av`Ge&`Qju!{`s279aXcD^<|3q&Xcrpk6saeJ6q87irpY_^4FKVnvzULQU#I( z3a&N7x8MlQFF19&#@;PlIt|V2$$jv^*x@-~lFys5%HIxMUriz=lM4cMwO-^&fn~%7wZU|MXILKQz&dH zC*Cj`k^$F4l|V4k<3oP|>b8@sj&`{SXpsJ2>lC7k*IcaYYCoBMk$16q4*<2@C0({^0HLZ>-faw@q_EXL`R6 zJqAU$DWjSNfL}&OH6A;6Ep2^QSQif7KR(VMocw=kqHh+zE5Nr4gx;`$dtb$)W>O4g z;}SJRL>9Ik&EmU`%(u^uXNKdG_MB%i@A*n8Oo43j=)4Y`op=Wqn@M&yC#9!G31r@n zNy4%%gggCC&oVY#SD6XJRir8UoH8Byor;nO!Q%Km1SN&TeJTX^wYBp}M0pcY)e)9i zTBqKo)Y>S}ee6@mSWe^D*BhI5o{D2a;H_Ad__&;T^5_9_E*a%TpxeDuvdkUb?L+f( zpA@4GW~$TAh^xp;XU}LmA(ohS%=5leCY-EqP*UsGlc{_f$D_<1(0@Ei&eE6RE3@B20T+(+NuKaSw1CCLFdpKcA4ZS1$L} zQO{VkUg*^KN8QMm9OXaeB+tz^Ma+^fo*Ris?CV&{8zRh~+14Lk%^(MsHI6C-RX5!y zy{w==6?e}=k}hEfK)<=pOaA03f3-%O!pG2ph~&2klLa13A2K@7#Q~`&mwiKgJ4qEa zKN8P?bV}N1r+^0TgA8v^f8AbtLlG?kz>`z(ym>uzPx+oDZ7q#w*dN@>BwdS(KFRBn!++UdEYd(l-l{8=Ovf7L$X7i&X zo)M8?Kw)Z~bnI&)xMdJ_N~TR(bg;~B|7r2)?mWqUe?U5qX(ARX2w&7xAG4jNadm+W zcxmrNulBgrX}`{`Rh|mHX0Qe;MX_@ywb7k{uuItrACrT^-mH>Kn^D+Tsl1ea+?~`3 z){8&dm*hugwK{@89U6MN9L@DBv{)aP?&HOlqV~W$EIqbisN$yOv@tS<+hCICX;jU)-tV~ywdKQ1w zN2^b`CcFFjVCWNqp0>*5u_eF+790Mxjg+<&S$C-aOlPDy5e_e5fDcjv8wnNt*}sXc zgc=lOHu2pSL@ar^y66dNAfU@f$*6+}Hj(52HNofr5D^P-pA_H^PK@_KIRXoNfAe|r zNZ!jNBNkl+c{KFwp@8H!6Y!E)Y8nJ(xL1scHo|@lHOt`6s}Ae6>Prlt4_nV|4)R=56D{FW(t%N)<}=TAf9z^oEs$%+XlmA!Ze;?{_B z_)2xQsxpP-65LD{!q{`0@SKK{?+O$Z7=HD-OBs4qcen%< zZ4?&IC=OAaXF`OPqFXoq03`WS7jp^-mz9ub$H&qfV@c|^3$4~hdHg+OCA9ZnhN{55 zllzVQ`&{Ur+dfS~?r#0RG`xR1CFiM5aFkR9Pde|0(ZZ(P)hyi%yWDP2wU5m4HeL~% z6>(w{8(@yc79fC43{XdgJZJW!hGOko^CuTC0Pc@Q!+Z*wU*J_op$B0-+i5bw9?pG| zHrioAWVn`3`Zo1>lMb6At=$rDNG0bLr>!@!botECglx;n_zWwj-_7P44BHFzQS)BN zd(R)#l|PZ|l=Fyye(Zad;QzRr8HRruf)ij^n@Yek;$gDDeLWVx`&Sv#^LKTUAMDR` zuzDWm=Bj`iSXv+fytd-E4dw_F&z>Hf^y#MA0?D>J2f+D0e@MD8lK_(SF65|vh8fCb zKECrv{MiVNCCbW*DA@O7WX?XG178z)rf)T4whP0yn&7+Q&XO@mj#0%~+O*piqsnL< zzOlMwRtfp>vT1J8ezR|dDv$-lxWIYB&A*z!zpl<=XPSRoqlok-bRZ>`giOr(SAd#1TMXP2jM;pTE+X6tIW2{Lh@p z7e^318Ks>Zb%J$8z!Kk&88dF8b#W)XcXZ?I#u@sy2G+oawyH_aoz#O@qbH|)X?gTp zORW&WI_w$=eLjH|iXP77GG9)ayB^YzzP!v-l`cZHGlvebf1B8hI4uZi+(JNs1EO+$ z9@0DeW9ISP|0AWyO<24E5}no&u#L+Y>M`)q@ZGnd1}$JZFc)X^r=^7U2#8Hc*D(h7 zM~njG@Lq$(?vB>ZjVkt6?=O=m;y$)=1^Sj&6!huLZcyjkB4HGQ#2yZMT|z*yOhW;A zxVD@mgsp=MfI`*V63Mi5=S3qr40qisB4R5g9^Gs+ z3I1xeguWFuT*h(NGh9}8s_9Iy;=vMJtDN1^(H_1}e4vBg%`3$jTe(s}EiP>DvR%=I zH`xddJreLfmMMz%4tr<*Iqcjbc>5UTb~FZNztd=8<@VXEOS)ca#BjTGem~>)<%t~g zjaXd7gAW?(J-cMT8msbN*z1)uH>%>XvQu`z>WB}hN_lCF&Te%=;s=6b8Q&K2Hltn0 z*n&NyLsCoCZQCYeBb}8^G>~?4NT4N8R_y;m^%sj-34Q? zbV5C^=bvBn8kfr~+coPqEv>u0oBJ`^FIM!SWi&G980s8Tz6#G+m_kQ-vQJZ9@U3F>0*YOky zeOneAmbARGu@j$F+-JLY_nhB9Y2RZ5S(Z-mO6QV>%#DGI0W1l%L(ass<$)TwaXZs_zxRB9X0_8)? zm?+obO^*}uloaU9ewc)0W4)KIG2gR3QpdISpdJXy3cX4MrQ@%UsJ`egDOfnHvc+{^ zsOcTb++O3oGw5xP>QDQgCnxx}2ZM&iVWJHoT)KF4)>y)xlC>7-Mr8Lwm)Q%pAj!Uh zmgC?>SBz>uK_LB3<#_KnRz^m{Yi7o}rdX_8<|b*A^Hk{Hvf@7cfOOx~$SMP7ff+<5 zlg4(T=$?ghSwuIg7mBnM!}lVuB_JJD35qQ>LfEo?>fN0Py;PIdoxRWxRSUDvi*MHY z6VbVO!oLtoHE~7VQh^3cJ(PjaK#wFM^&@@j#x*Q3RPjphjK2RFOr96%9SE1?e6t7b zuTJ&-3{Hg;-qUaa+hZYoPm#P2co1T!FgkoYsZa&M8R|rx*-�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 X;P;?o_5ZQ-<>657|NHOfnHk2CwPOj{DlK+x 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%0DMm4%D&Q@HpKy8cN|D!o{=#k*$-$-v;C>%|a8e0W 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 delta 610 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

  • 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

    M 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 i6GetDepthStencil(), RenderPassAttachment::LOADOP_LOAD, RenderPassAttachment::STOREOP_STORE, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL_READONLY ) ); hr = device->CreateRenderPass(&desc, &renderpass_selectionOutline[0]); @@ -771,8 +771,8 @@ void EditorComponent::Load() { wiScene::GetCamera() = *cam; // camera aspect should be always for the current screen - wiScene::GetCamera().width = renderPath->GetInternalResolution().x; - wiScene::GetCamera().height = renderPath->GetInternalResolution().y; + wiScene::GetCamera().width = (float)renderPath->GetInternalResolution().x; + wiScene::GetCamera().height = (float)renderPath->GetInternalResolution().y; } } } @@ -1947,7 +1947,6 @@ void EditorComponent::Render() const // Objects outline: { - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); device->RenderPassBegin(&renderpass_selectionOutline[1], cmd); // Draw solid blocks of selected objects diff --git a/Editor/Editor_SOURCE.vcxitems b/Editor/Editor_SOURCE.vcxitems index 341406eaa..cf9f74db1 100644 --- a/Editor/Editor_SOURCE.vcxitems +++ b/Editor/Editor_SOURCE.vcxitems @@ -153,11 +153,6 @@ - - true - true - Document - true true diff --git a/Editor/Editor_SOURCE.vcxitems.filters b/Editor/Editor_SOURCE.vcxitems.filters index bc4de9f67..00dc20113 100644 --- a/Editor/Editor_SOURCE.vcxitems.filters +++ b/Editor/Editor_SOURCE.vcxitems.filters @@ -167,7 +167,6 @@ - diff --git a/Editor/PaintToolWindow.cpp b/Editor/PaintToolWindow.cpp index c4f110631..f2cfbe094 100644 --- a/Editor/PaintToolWindow.cpp +++ b/Editor/PaintToolWindow.cpp @@ -1,7 +1,7 @@ #include "stdafx.h" #include "Editor.h" #include "PaintToolWindow.h" -#include "shaders/ShaderInterop_Paint.h" +#include "shaders/ShaderInterop_Renderer.h" #include #include @@ -305,22 +305,11 @@ void PaintToolWindow::Update(float dt) // Need to requery this because RecordHistory might swap textures on material: editTexture = GetEditTextureSlot(*material, &uvset); - static GPUBuffer cbuf; - if (!cbuf.IsValid()) - { - GPUBufferDesc desc; - desc.BindFlags = BIND_CONSTANT_BUFFER; - desc.Usage = USAGE_DYNAMIC; - desc.CPUAccessFlags = CPU_ACCESS_WRITE; - desc.ByteWidth = sizeof(PaintTextureCB); - device->CreateBuffer(&desc, nullptr, &cbuf); - } - device->BindComputeShader(wiRenderer::GetShader(CSTYPE_PAINT_TEXTURE), cmd); wiRenderer::BindCommonResources(cmd); - device->BindResource(CS, wiTextureHelper::getWhite(), TEXSLOT_ONDEMAND0, cmd); - device->BindUAV(CS, &editTexture, 0, cmd); + device->BindResource(wiTextureHelper::getWhite(), TEXSLOT_ONDEMAND0, cmd); + device->BindUAV(&editTexture, 0, cmd); PaintTextureCB cb; cb.xPaintBrushCenter = center; @@ -328,8 +317,7 @@ void PaintToolWindow::Update(float dt) cb.xPaintBrushAmount = amount; cb.xPaintBrushFalloff = falloff; cb.xPaintBrushColor = color.rgba; - device->UpdateBuffer(&cbuf, &cb, cmd); - device->BindConstantBuffer(CS, &cbuf, CB_GETBINDSLOT(PaintTextureCB), cmd); + device->PushConstants(&cb, sizeof(cb), cmd); const uint diameter = cb.xPaintBrushRadius * 2; const uint dispatch_dim = (diameter + PAINT_TEXTURE_BLOCKSIZE - 1) / PAINT_TEXTURE_BLOCKSIZE; @@ -340,7 +328,6 @@ void PaintToolWindow::Update(float dt) }; device->Barrier(barriers, arraysize(barriers), cmd); - device->UnbindUAVs(0, 1, cmd); wiRenderer::GenerateMipChain(editTexture, wiRenderer::MIPGENFILTER::MIPGENFILTER_LINEAR, cmd); } diff --git a/Editor/PostprocessWindow.cpp b/Editor/PostprocessWindow.cpp index bb1e728fc..9abc14ef6 100644 --- a/Editor/PostprocessWindow.cpp +++ b/Editor/PostprocessWindow.cpp @@ -59,7 +59,7 @@ void PostprocessWindow::Create(EditorComponent* editor) aoComboBox.AddItem("SSAO"); aoComboBox.AddItem("HBAO"); aoComboBox.AddItem("MSAO"); - if (wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { aoComboBox.AddItem("RTAO"); } @@ -142,7 +142,7 @@ void PostprocessWindow::Create(EditorComponent* editor) editor->renderPath->setRaytracedReflectionsEnabled(args.bValue); }); AddWidget(&raytracedReflectionsCheckBox); - raytracedReflectionsCheckBox.SetEnabled(wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) && wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_GEOMETRYINDEX)); + raytracedReflectionsCheckBox.SetEnabled(wiRenderer::GetDevice()->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)); screenSpaceShadowsCheckBox.Create("SS Shadows: "); screenSpaceShadowsCheckBox.SetTooltip("Enable screen space contact shadows. This can add small shadows details to shadow maps in screen space."); diff --git a/Editor/RendererWindow.cpp b/Editor/RendererWindow.cpp index 69f8f7efc..0044729c4 100644 --- a/Editor/RendererWindow.cpp +++ b/Editor/RendererWindow.cpp @@ -64,6 +64,26 @@ void RendererWindow::Create(EditorComponent* editor) }); AddWidget(&gammaSlider); + surfelGICheckBox.Create("Surfel GI: "); + surfelGICheckBox.SetTooltip("Surfel GI is a raytraced diffuse GI using raytracing and surface cache."); + surfelGICheckBox.SetPos(XMFLOAT2(x, y += step)); + surfelGICheckBox.SetSize(XMFLOAT2(itemheight, itemheight)); + surfelGICheckBox.OnClick([](wiEventArgs args) { + wiRenderer::SetSurfelGIEnabled(args.bValue); + }); + surfelGICheckBox.SetCheck(wiRenderer::GetSurfelGIEnabled()); + AddWidget(&surfelGICheckBox); + + surfelGIDebugCheckBox.Create("DEBUG: "); + surfelGIDebugCheckBox.SetTooltip("Toggle Surfel GI visualization."); + surfelGIDebugCheckBox.SetPos(XMFLOAT2(x + 122, y)); + surfelGIDebugCheckBox.SetSize(XMFLOAT2(itemheight, itemheight)); + surfelGIDebugCheckBox.OnClick([](wiEventArgs args) { + wiRenderer::SetSurfelGIDebugEnabled(args.bValue); + }); + surfelGIDebugCheckBox.SetCheck(wiRenderer::GetSurfelGIDebugEnabled()); + AddWidget(&surfelGIDebugCheckBox); + voxelRadianceCheckBox.Create("Voxel GI: "); voxelRadianceCheckBox.SetTooltip("Toggle voxel Global Illumination computation."); voxelRadianceCheckBox.SetPos(XMFLOAT2(x, y += step)); @@ -231,7 +251,7 @@ void RendererWindow::Create(EditorComponent* editor) shadowTypeComboBox.SetSize(XMFLOAT2(100, itemheight)); shadowTypeComboBox.SetPos(XMFLOAT2(x, y += step)); shadowTypeComboBox.AddItem("Shadowmaps"); - if (wiRenderer::GetDevice()->CheckCapability(wiGraphics::GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (wiRenderer::GetDevice()->CheckCapability(wiGraphics::GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { shadowTypeComboBox.AddItem("Ray traced"); } @@ -631,7 +651,7 @@ void RendererWindow::Create(EditorComponent* editor) - disableAlbedoMapsCheckBox.Create("Disable Albedo maps: "); + disableAlbedoMapsCheckBox.Create("Disable albedo maps: "); disableAlbedoMapsCheckBox.SetTooltip("Disables albedo maps on objects for easier lighting debugging"); disableAlbedoMapsCheckBox.SetPos(XMFLOAT2(x, y += step)); disableAlbedoMapsCheckBox.SetSize(XMFLOAT2(itemheight, itemheight)); @@ -642,6 +662,17 @@ void RendererWindow::Create(EditorComponent* editor) AddWidget(&disableAlbedoMapsCheckBox); + forceDiffuseLightingCheckBox.Create("Force diffuse lighting: "); + forceDiffuseLightingCheckBox.SetTooltip("Sets every surface fully diffuse, with zero specularity"); + forceDiffuseLightingCheckBox.SetPos(XMFLOAT2(x, y += step)); + forceDiffuseLightingCheckBox.SetSize(XMFLOAT2(itemheight, itemheight)); + forceDiffuseLightingCheckBox.OnClick([](wiEventArgs args) { + wiRenderer::SetForceDiffuseLighting(args.bValue); + }); + forceDiffuseLightingCheckBox.SetCheck(wiRenderer::IsForceDiffuseLighting()); + AddWidget(&forceDiffuseLightingCheckBox); + + Translate(XMFLOAT3(100, 50, 0)); SetVisible(false); diff --git a/Editor/RendererWindow.h b/Editor/RendererWindow.h index fff3ac1eb..8548b94a2 100644 --- a/Editor/RendererWindow.h +++ b/Editor/RendererWindow.h @@ -27,6 +27,8 @@ public: wiCheckBox occlusionCullingCheckBox; wiSlider resolutionScaleSlider; wiSlider gammaSlider; + wiCheckBox surfelGICheckBox; + wiCheckBox surfelGIDebugCheckBox; wiCheckBox voxelRadianceCheckBox; wiCheckBox voxelRadianceDebugCheckBox; wiCheckBox voxelRadianceSecondaryBounceCheckBox; @@ -74,6 +76,7 @@ public: wiCheckBox freezeCullingCameraCheckBox; wiCheckBox disableAlbedoMapsCheckBox; + wiCheckBox forceDiffuseLightingCheckBox; uint32_t GetPickType() const; }; diff --git a/Editor/Translator.cpp b/Editor/Translator.cpp index 3295086e5..663b06edb 100644 --- a/Editor/Translator.cpp +++ b/Editor/Translator.cpp @@ -73,7 +73,6 @@ void Translator::Create() bd.Usage = USAGE_DEFAULT; bd.ByteWidth = sizeof(verts); bd.BindFlags = BIND_VERTEX_BUFFER; - bd.CPUAccessFlags = 0; SubresourceData InitData; InitData.pSysMem = verts; @@ -100,7 +99,6 @@ void Translator::Create() bd.Usage = USAGE_DEFAULT; bd.ByteWidth = sizeof(verts); bd.BindFlags = BIND_VERTEX_BUFFER; - bd.CPUAccessFlags = 0; SubresourceData InitData; InitData.pSysMem = verts; @@ -156,7 +154,6 @@ void Translator::Create() bd.Usage = USAGE_DEFAULT; bd.ByteWidth = sizeof(verts); bd.BindFlags = BIND_VERTEX_BUFFER; - bd.CPUAccessFlags = 0; SubresourceData InitData; InitData.pSysMem = verts; @@ -467,25 +464,19 @@ void Translator::Draw(const CameraComponent& camera, CommandList cmd) const // xy XMStoreFloat4x4(&sb.g_xTransform, matX); sb.g_xColor = state == TRANSLATOR_XY ? XMFLOAT4(1, 1, 1, 1) : XMFLOAT4(0.4f, 0.4f, 0, 0.4f); - device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &sb, cmd); - device->BindConstantBuffer(VS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CBSLOT_RENDERER_MISC, cmd); device->Draw(vertexCount_Plane, 0, cmd); // xz XMStoreFloat4x4(&sb.g_xTransform, matZ); sb.g_xColor = state == TRANSLATOR_XZ ? XMFLOAT4(1, 1, 1, 1) : XMFLOAT4(0.4f, 0.4f, 0, 0.4f); - device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &sb, cmd); - device->BindConstantBuffer(VS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CBSLOT_RENDERER_MISC, cmd); device->Draw(vertexCount_Plane, 0, cmd); // yz XMStoreFloat4x4(&sb.g_xTransform, matY); sb.g_xColor = state == TRANSLATOR_YZ ? XMFLOAT4(1, 1, 1, 1) : XMFLOAT4(0.4f, 0.4f, 0, 0.4f); - device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &sb, cmd); - device->BindConstantBuffer(VS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CBSLOT_RENDERER_MISC, cmd); device->Draw(vertexCount_Plane, 0, cmd); // Lines: @@ -503,25 +494,19 @@ void Translator::Draw(const CameraComponent& camera, CommandList cmd) const // x XMStoreFloat4x4(&sb.g_xTransform, matX); sb.g_xColor = state == TRANSLATOR_X ? XMFLOAT4(1, 1, 1, 1) : XMFLOAT4(1, 0, 0, 1); - device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &sb, cmd); - device->BindConstantBuffer(VS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CBSLOT_RENDERER_MISC, cmd); device->Draw(vertexCount_Axis, 0, cmd); // y XMStoreFloat4x4(&sb.g_xTransform, matY); sb.g_xColor = state == TRANSLATOR_Y ? XMFLOAT4(1, 1, 1, 1) : XMFLOAT4(0, 1, 0, 1); - device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &sb, cmd); - device->BindConstantBuffer(VS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CBSLOT_RENDERER_MISC, cmd); device->Draw(vertexCount_Axis, 0, cmd); // z XMStoreFloat4x4(&sb.g_xTransform, matZ); sb.g_xColor = state == TRANSLATOR_Z ? XMFLOAT4(1, 1, 1, 1) : XMFLOAT4(0, 0, 1, 1); - device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &sb, cmd); - device->BindConstantBuffer(VS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CBSLOT_RENDERER_MISC, cmd); device->Draw(vertexCount_Axis, 0, cmd); // Origin: @@ -536,9 +521,7 @@ void Translator::Draw(const CameraComponent& camera, CommandList cmd) const device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, nullptr, cmd); XMStoreFloat4x4(&sb.g_xTransform, mat); sb.g_xColor = state == TRANSLATOR_XYZ ? XMFLOAT4(1, 1, 1, 1) : XMFLOAT4(0.25f, 0.25f, 0.25f, 1); - device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &sb, cmd); - device->BindConstantBuffer(VS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CBSLOT_RENDERER_MISC, cmd); device->Draw(vertexCount_Origin, 0, cmd); } diff --git a/README.md b/README.md index 28f495007..1b3917363 100644 --- a/README.md +++ b/README.md @@ -203,7 +203,7 @@ The preferred workflow is to import models into the Editor, and save them as ### Graphics API: -The default renderer is `DirectX 11` on Windows and `Vulkan` on Linux. There is also an optional `DirectX 12` renderer for Windows. +The default renderer is `DirectX 12` on Windows and `Vulkan` on Linux. The `DirectX 11` renderer is no longer available starting from version 0.57.0, but it can be found on the dx11-backup branch. You can specify command line arguments (without any prefix) to switch between render devices or other settings. Currently the list of options: diff --git a/Template_UWP/Template_UWP.vcxproj b/Template_UWP/Template_UWP.vcxproj index ac729d56f..c41a87a29 100644 --- a/Template_UWP/Template_UWP.vcxproj +++ b/Template_UWP/Template_UWP.vcxproj @@ -159,11 +159,6 @@ - - true - Document - true - true Document diff --git a/Template_UWP/Template_UWP.vcxproj.filters b/Template_UWP/Template_UWP.vcxproj.filters index 904359c08..724c704f0 100644 --- a/Template_UWP/Template_UWP.vcxproj.filters +++ b/Template_UWP/Template_UWP.vcxproj.filters @@ -44,7 +44,6 @@ - diff --git a/Template_Windows/Template_Windows.vcxproj b/Template_Windows/Template_Windows.vcxproj index 2fd04a674..9daa99cad 100644 --- a/Template_Windows/Template_Windows.vcxproj +++ b/Template_Windows/Template_Windows.vcxproj @@ -75,9 +75,8 @@ $(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) - xcopy "$(SolutionDir)WickedEngine\dxcompiler.dll" "$(OutDir)" /c /y -xcopy "$(SolutionDir)WickedEngine\dxil.dll" "$(OutDir)" /c /y -xcopy "$(SolutionDir)WickedEngine\d3dcompiler_47.dll" "$(OutDir)" /c /y + + @@ -97,9 +96,8 @@ xcopy "$(SolutionDir)WickedEngine\d3dcompiler_47.dll" "$(OutDir)" /c /y$(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) - xcopy "$(SolutionDir)WickedEngine\dxcompiler.dll" "$(OutDir)" /c /y -xcopy "$(SolutionDir)WickedEngine\dxil.dll" "$(OutDir)" /c /y -xcopy "$(SolutionDir)WickedEngine\d3dcompiler_47.dll" "$(OutDir)" /c /y + + @@ -131,11 +129,6 @@ xcopy "$(SolutionDir)WickedEngine\d3dcompiler_47.dll" "$(OutDir)" /c /y - - true - Document - true - true Document diff --git a/Template_Windows/Template_Windows.vcxproj.filters b/Template_Windows/Template_Windows.vcxproj.filters index e5bb75190..87ab8dae9 100644 --- a/Template_Windows/Template_Windows.vcxproj.filters +++ b/Template_Windows/Template_Windows.vcxproj.filters @@ -49,7 +49,6 @@ - \ No newline at end of file diff --git a/Tests/Tests.vcxproj b/Tests/Tests.vcxproj index 3955b2d27..c34ba14c0 100644 --- a/Tests/Tests.vcxproj +++ b/Tests/Tests.vcxproj @@ -78,9 +78,8 @@ $(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) - xcopy "$(SolutionDir)WickedEngine\dxcompiler.dll" "$(OutDir)" /c /y -xcopy "$(SolutionDir)WickedEngine\dxil.dll" "$(OutDir)" /c /y -xcopy "$(SolutionDir)WickedEngine\d3dcompiler_47.dll" "$(OutDir)" /c /y + + @@ -101,9 +100,8 @@ xcopy "$(SolutionDir)WickedEngine\d3dcompiler_47.dll" "$(OutDir)" /c /y$(SolutionDir)BUILD\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) - xcopy "$(SolutionDir)WickedEngine\dxcompiler.dll" "$(OutDir)" /c /y -xcopy "$(SolutionDir)WickedEngine\dxil.dll" "$(OutDir)" /c /y -xcopy "$(SolutionDir)WickedEngine\d3dcompiler_47.dll" "$(OutDir)" /c /y + + @@ -135,11 +133,6 @@ xcopy "$(SolutionDir)WickedEngine\d3dcompiler_47.dll" "$(OutDir)" /c /y - - true - Document - true - true Document diff --git a/Tests/Tests.vcxproj.filters b/Tests/Tests.vcxproj.filters index 99ffd102b..2f38cb886 100644 --- a/Tests/Tests.vcxproj.filters +++ b/Tests/Tests.vcxproj.filters @@ -68,7 +68,6 @@ - diff --git a/WickedEngine/CMakeLists.txt b/WickedEngine/CMakeLists.txt index 8676756d3..e5c295e89 100644 --- a/WickedEngine/CMakeLists.txt +++ b/WickedEngine/CMakeLists.txt @@ -61,7 +61,6 @@ add_library(${TARGET_NAME} STATIC wiGPUBVH.cpp wiGPUSortLib.cpp wiGraphicsDevice.cpp - wiGraphicsDevice_DX11.cpp wiGraphicsDevice_DX12.cpp wiGraphicsDevice_Vulkan.cpp wiGUI.cpp diff --git a/WickedEngine/MainComponent.cpp b/WickedEngine/MainComponent.cpp index 0e5c9422e..258e6053f 100644 --- a/WickedEngine/MainComponent.cpp +++ b/WickedEngine/MainComponent.cpp @@ -16,7 +16,6 @@ #include "wiImage.h" #include "wiEvent.h" -#include "wiGraphicsDevice_DX11.h" #include "wiGraphicsDevice_DX12.h" #include "wiGraphicsDevice_Vulkan.h" @@ -107,64 +106,61 @@ void MainComponent::Run() wiLua::RunFile("startup.lua"); } + if (!is_window_active) + { + // If the application is not active, disable Update loops: + deltaTimeAccumulator = 0; + return; + } + wiProfiler::BeginFrame(); deltaTime = float(std::max(0.0, timer.elapsed() / 1000.0)); timer.record(); - if (is_window_active) + // Wake up the events that need to be executed on the main thread, in thread safe manner: + wiEvent::FireEvent(SYSTEM_EVENT_THREAD_SAFE_POINT, 0); + + const float dt = framerate_lock ? (1.0f / targetFrameRate) : deltaTime; + + fadeManager.Update(dt); + + if (GetActivePath() != nullptr) { - // If the application is active, run Update loops: + GetActivePath()->init(canvas); + GetActivePath()->PreUpdate(); + } - // Wake up the events that need to be executed on the main thread, in thread safe manner: - wiEvent::FireEvent(SYSTEM_EVENT_THREAD_SAFE_POINT, 0); - - const float dt = framerate_lock ? (1.0f / targetFrameRate) : deltaTime; - - fadeManager.Update(dt); - - if (GetActivePath() != nullptr) + // Fixed time update: + auto range = wiProfiler::BeginRangeCPU("Fixed Update"); + { + if (frameskip) { - GetActivePath()->init(canvas); - GetActivePath()->PreUpdate(); - } - - // Fixed time update: - auto range = wiProfiler::BeginRangeCPU("Fixed Update"); - { - if (frameskip) + deltaTimeAccumulator += dt; + if (deltaTimeAccumulator > 10) { - deltaTimeAccumulator += dt; - if (deltaTimeAccumulator > 10) - { - // application probably lost control, fixed update would take too long - deltaTimeAccumulator = 0; - } - - const float targetFrameRateInv = 1.0f / targetFrameRate; - while (deltaTimeAccumulator >= targetFrameRateInv) - { - FixedUpdate(); - deltaTimeAccumulator -= targetFrameRateInv; - } + // application probably lost control, fixed update would take too long + deltaTimeAccumulator = 0; } - else + + const float targetFrameRateInv = 1.0f / targetFrameRate; + while (deltaTimeAccumulator >= targetFrameRateInv) { FixedUpdate(); + deltaTimeAccumulator -= targetFrameRateInv; } } - wiProfiler::EndRange(range); // Fixed Update - - // Variable-timed update: - Update(dt); - - Render(); - } - else - { - // If the application is not active, disable Update loops: - deltaTimeAccumulator = 0; + else + { + FixedUpdate(); + } } + wiProfiler::EndRange(range); // Fixed Update + + // Variable-timed update: + Update(dt); + + Render(); wiInput::Update(window); @@ -267,12 +263,6 @@ void MainComponent::Compose(CommandList cmd) ss << "[UWP]"; #endif -#ifdef WICKEDENGINE_BUILD_DX11 - if (dynamic_cast(device)) - { - ss << "[DX11]"; - } -#endif #ifdef WICKEDENGINE_BUILD_DX12 if (dynamic_cast(device)) { @@ -356,16 +346,9 @@ void MainComponent::SetWindow(wiPlatform::window_type window, bool fullscreen) bool debugdevice = wiStartupArguments::HasArgument("debugdevice"); bool gpuvalidation = wiStartupArguments::HasArgument("gpuvalidation"); - bool use_dx11 = wiStartupArguments::HasArgument("dx11"); bool use_dx12 = wiStartupArguments::HasArgument("dx12"); bool use_vulkan = wiStartupArguments::HasArgument("vulkan"); -#ifndef WICKEDENGINE_BUILD_DX11 - if (use_dx11) { - wiHelper::messageBox("The engine was built without DX11 support!", "Error"); - use_dx11 = false; - } -#endif #ifndef WICKEDENGINE_BUILD_DX12 if (use_dx12) { wiHelper::messageBox("The engine was built without DX12 support!", "Error"); @@ -379,11 +362,9 @@ void MainComponent::SetWindow(wiPlatform::window_type window, bool fullscreen) } #endif - if (!use_dx11 && !use_dx12 && !use_vulkan) + if (!use_dx12 && !use_vulkan) { -#if defined(WICKEDENGINE_BUILD_DX11) - use_dx11 = true; -#elif defined(WICKEDENGINE_BUILD_DX12) +#if defined(WICKEDENGINE_BUILD_DX12) use_dx12 = true; #elif defined(WICKEDENGINE_BUILD_VULKAN) use_vulkan = true; @@ -392,7 +373,7 @@ void MainComponent::SetWindow(wiPlatform::window_type window, bool fullscreen) assert(false); #endif } - assert(use_dx11 || use_dx12 || use_vulkan); + assert(use_dx12 || use_vulkan); if (use_vulkan) { @@ -406,13 +387,6 @@ void MainComponent::SetWindow(wiPlatform::window_type window, bool fullscreen) #ifdef WICKEDENGINE_BUILD_DX12 wiRenderer::SetShaderPath(wiRenderer::GetShaderPath() + "hlsl6/"); wiRenderer::SetDevice(std::make_shared(debugdevice, gpuvalidation)); -#endif - } - else if (use_dx11) - { -#ifdef WICKEDENGINE_BUILD_DX11 - wiRenderer::SetShaderPath(wiRenderer::GetShaderPath() + "hlsl5/"); - wiRenderer::SetDevice(std::make_shared(debugdevice)); #endif } } diff --git a/WickedEngine/OfflineShaderCompiler.vcxproj b/WickedEngine/OfflineShaderCompiler.vcxproj index bb5ff4e93..95dfe384b 100644 --- a/WickedEngine/OfflineShaderCompiler.vcxproj +++ b/WickedEngine/OfflineShaderCompiler.vcxproj @@ -97,11 +97,6 @@ - - true - Document - true - true true diff --git a/WickedEngine/RenderPath2D.cpp b/WickedEngine/RenderPath2D.cpp index 3ec663d23..0e6043197 100644 --- a/WickedEngine/RenderPath2D.cpp +++ b/WickedEngine/RenderPath2D.cpp @@ -18,7 +18,7 @@ void RenderPath2D::ResizeBuffers() if(dsv != nullptr && (resolutionScale != 1.0f || dsv->GetDesc().SampleCount > 1)) { TextureDesc desc = GetDepthStencil()->GetDesc(); - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE; desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE; desc.Format = FORMAT_R8G8B8A8_UNORM; device->CreateTexture(&desc, nullptr, &rtStenciled); @@ -55,9 +55,9 @@ void RenderPath2D::ResizeBuffers() dsv, RenderPassAttachment::LOADOP_LOAD, RenderPassAttachment::STOREOP_STORE, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL_READONLY ) ); @@ -81,9 +81,9 @@ void RenderPath2D::ResizeBuffers() dsv, RenderPassAttachment::LOADOP_LOAD, RenderPassAttachment::STOREOP_STORE, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL_READONLY ) ); } diff --git a/WickedEngine/RenderPath3D.cpp b/WickedEngine/RenderPath3D.cpp index decb83b3e..cef7968a2 100644 --- a/WickedEngine/RenderPath3D.cpp +++ b/WickedEngine/RenderPath3D.cpp @@ -20,51 +20,63 @@ void RenderPath3D::ResizeBuffers() { TextureDesc desc; - desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE; - if (getMSAASampleCount() == 1) - { - desc.BindFlags |= BIND_UNORDERED_ACCESS; - } + desc.Format = FORMAT_R11G11B10_FLOAT; + desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; desc.Width = internalResolution.x; desc.Height = internalResolution.y; - desc.SampleCount = getMSAASampleCount(); + desc.SampleCount = 1; - desc.Format = FORMAT_R11G11B10_FLOAT; - device->CreateTexture(&desc, nullptr, &rtGbuffer[GBUFFER_COLOR]); - device->SetName(&rtGbuffer[GBUFFER_COLOR], "rtGbuffer[GBUFFER_COLOR]"); + device->CreateTexture(&desc, nullptr, &rtMain); + device->SetName(&rtMain, "rtMain"); - desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE; - desc.Format = FORMAT_R8G8B8A8_UNORM; - device->CreateTexture(&desc, nullptr, &rtGbuffer[GBUFFER_NORMAL_ROUGHNESS]); - device->SetName(&rtGbuffer[GBUFFER_NORMAL_ROUGHNESS], "rtGbuffer[GBUFFER_NORMAL_ROUGHNESS]"); + if (getMSAASampleCount() > 1) + { + desc.SampleCount = getMSAASampleCount(); + desc.BindFlags = BIND_RENDER_TARGET; + device->CreateTexture(&desc, nullptr, &rtMain_render); + device->SetName(&rtMain_render, "rtMain_render"); + } + else + { + rtMain_render = rtMain; + } + } + { + TextureDesc desc; + desc.Width = internalResolution.x; + desc.Height = internalResolution.y; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; + desc.SampleCount = 1; + + desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; + desc.Format = FORMAT_R32G32_UINT; + device->CreateTexture(&desc, nullptr, &rtGbuffer[GBUFFER_PRIMITIVEID]); + device->SetName(&rtGbuffer[GBUFFER_PRIMITIVEID], "rtGbuffer[GBUFFER_PRIMITIVEID]"); + + desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; desc.Format = FORMAT_R16G16_FLOAT; device->CreateTexture(&desc, nullptr, &rtGbuffer[GBUFFER_VELOCITY]); device->SetName(&rtGbuffer[GBUFFER_VELOCITY], "rtGbuffer[GBUFFER_VELOCITY]"); if (getMSAASampleCount() > 1) { - desc.SampleCount = 1; - desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - - desc.Format = FORMAT_R11G11B10_FLOAT; - device->CreateTexture(&desc, nullptr, &rtGbuffer_resolved[GBUFFER_COLOR]); - device->SetName(&rtGbuffer_resolved[GBUFFER_COLOR], "rtGbuffer_resolved[GBUFFER_COLOR]"); - - desc.Format = FORMAT_R8G8B8A8_UNORM; - device->CreateTexture(&desc, nullptr, &rtGbuffer_resolved[GBUFFER_NORMAL_ROUGHNESS]); - device->SetName(&rtGbuffer_resolved[GBUFFER_NORMAL_ROUGHNESS], "rtGbuffer_resolved[GBUFFER_NORMAL_ROUGHNESS]"); - - desc.Format = FORMAT_R16G16_FLOAT; - device->CreateTexture(&desc, nullptr, &rtGbuffer_resolved[GBUFFER_VELOCITY]); - device->SetName(&rtGbuffer_resolved[GBUFFER_VELOCITY], "rtGbuffer_resolved[GBUFFER_VELOCITY]"); + desc = rtGbuffer[GBUFFER_PRIMITIVEID].desc; + desc.SampleCount = getMSAASampleCount(); + desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE; + device->CreateTexture(&desc, nullptr, &rtPrimitiveID_render); + device->SetName(&rtPrimitiveID_render, "rtPrimitiveID_render"); + } + else + { + rtPrimitiveID_render = rtGbuffer[GBUFFER_PRIMITIVEID]; } } { TextureDesc desc; desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE; - desc.Format = FORMAT_R16G16B16A16_FLOAT; + desc.Format = FORMAT_R16G16_FLOAT; desc.Width = internalResolution.x; desc.Height = internalResolution.y; desc.SampleCount = getMSAASampleCount(); @@ -91,7 +103,7 @@ void RenderPath3D::ResizeBuffers() { TextureDesc desc; desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE; - desc.Format = FORMAT_R8G8_SNORM; + desc.Format = FORMAT_R16G16_FLOAT; desc.Width = internalResolution.x; desc.Height = internalResolution.y; device->CreateTexture(&desc, nullptr, &rtWaterRipple); @@ -138,7 +150,7 @@ void RenderPath3D::ResizeBuffers() desc.Format = FORMAT_R32G32B32A32_UINT; desc.Width = internalResolution.x / 2; desc.Height = internalResolution.y / 2; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; device->CreateTexture(&desc, nullptr, &rtShadow); device->SetName(&rtShadow, "rtShadow"); } @@ -218,7 +230,7 @@ void RenderPath3D::ResizeBuffers() uint32_t tileSize = device->GetVariableRateShadingTileSize(); TextureDesc desc; - desc.layout = IMAGE_LAYOUT_UNORDERED_ACCESS; + desc.layout = RESOURCE_STATE_UNORDERED_ACCESS; desc.BindFlags = BIND_UNORDERED_ACCESS | BIND_SHADING_RATE; desc.Format = FORMAT_R8_UINT; desc.Width = (internalResolution.x + tileSize - 1) / tileSize; @@ -235,17 +247,17 @@ void RenderPath3D::ResizeBuffers() desc.Height = internalResolution.y; desc.SampleCount = getMSAASampleCount(); - desc.layout = IMAGE_LAYOUT_DEPTHSTENCIL_READONLY; + desc.layout = RESOURCE_STATE_DEPTHSTENCIL_READONLY; desc.Format = FORMAT_R32G8X24_TYPELESS; desc.BindFlags = BIND_DEPTH_STENCIL | BIND_SHADER_RESOURCE; device->CreateTexture(&desc, nullptr, &depthBuffer_Main); device->SetName(&depthBuffer_Main, "depthBuffer_Main"); - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; desc.Format = FORMAT_R32_FLOAT; desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; desc.SampleCount = 1; - desc.MipLevels = 3; + desc.MipLevels = 5; device->CreateTexture(&desc, nullptr, &depthBuffer_Copy); device->SetName(&depthBuffer_Copy, "depthBuffer_Copy"); device->CreateTexture(&desc, nullptr, &depthBuffer_Copy1); @@ -270,7 +282,7 @@ void RenderPath3D::ResizeBuffers() desc.Format = FORMAT_R32_TYPELESS; desc.Width = internalResolution.x / 4; desc.Height = internalResolution.y / 4; - desc.layout = IMAGE_LAYOUT_DEPTHSTENCIL_READONLY; + desc.layout = RESOURCE_STATE_DEPTHSTENCIL_READONLY; device->CreateTexture(&desc, nullptr, &depthBuffer_Reflection); device->SetName(&depthBuffer_Reflection, "depthBuffer_Reflection"); } @@ -280,8 +292,8 @@ void RenderPath3D::ResizeBuffers() desc.Format = FORMAT_R32_FLOAT; desc.Width = internalResolution.x; desc.Height = internalResolution.y; - desc.MipLevels = 6; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE; + desc.MipLevels = 5; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; device->CreateTexture(&desc, nullptr, &rtLinearDepth); device->SetName(&rtLinearDepth, "rtLinearDepth"); @@ -303,60 +315,63 @@ void RenderPath3D::ResizeBuffers() &depthBuffer_Main, RenderPassAttachment::LOADOP_CLEAR, RenderPassAttachment::STOREOP_STORE, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL, - IMAGE_LAYOUT_SHADER_RESOURCE + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL, + RESOURCE_STATE_SHADER_RESOURCE + ) + ); + desc.attachments.push_back( + RenderPassAttachment::RenderTarget( + &rtPrimitiveID_render, + RenderPassAttachment::LOADOP_DONTCARE, + RenderPassAttachment::STOREOP_STORE, + RESOURCE_STATE_SHADER_RESOURCE_COMPUTE, + RESOURCE_STATE_RENDERTARGET, + RESOURCE_STATE_SHADER_RESOURCE_COMPUTE ) ); - desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtGbuffer[GBUFFER_VELOCITY], RenderPassAttachment::LOADOP_DONTCARE)); - if (getMSAASampleCount() > 1) - { - desc.attachments.push_back(RenderPassAttachment::Resolve(GetGbuffer_Read(GBUFFER_VELOCITY))); - } device->CreateRenderPass(&desc, &renderpass_depthprepass); desc.attachments.clear(); - desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtGbuffer[GBUFFER_COLOR], RenderPassAttachment::LOADOP_DONTCARE)); - desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtGbuffer[GBUFFER_NORMAL_ROUGHNESS], RenderPassAttachment::LOADOP_DONTCARE)); + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtMain_render, RenderPassAttachment::LOADOP_DONTCARE)); desc.attachments.push_back( RenderPassAttachment::DepthStencil( &depthBuffer_Main, RenderPassAttachment::LOADOP_LOAD, RenderPassAttachment::STOREOP_STORE, - IMAGE_LAYOUT_SHADER_RESOURCE, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + RESOURCE_STATE_SHADER_RESOURCE, + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL_READONLY ) ); if (getMSAASampleCount() > 1) { - desc.attachments.push_back(RenderPassAttachment::Resolve(GetGbuffer_Read(GBUFFER_COLOR))); - desc.attachments.push_back(RenderPassAttachment::Resolve(GetGbuffer_Read(GBUFFER_NORMAL_ROUGHNESS))); + desc.attachments.push_back(RenderPassAttachment::Resolve(&rtMain)); } if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2)) { - desc.attachments.push_back(RenderPassAttachment::ShadingRateSource(&rtShadingRate, IMAGE_LAYOUT_UNORDERED_ACCESS, IMAGE_LAYOUT_UNORDERED_ACCESS)); + desc.attachments.push_back(RenderPassAttachment::ShadingRateSource(&rtShadingRate, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_UNORDERED_ACCESS)); } device->CreateRenderPass(&desc, &renderpass_main); } { RenderPassDesc desc; - desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtGbuffer[GBUFFER_COLOR], RenderPassAttachment::LOADOP_LOAD)); + desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtMain_render, RenderPassAttachment::LOADOP_LOAD)); desc.attachments.push_back( RenderPassAttachment::DepthStencil( &depthBuffer_Main, RenderPassAttachment::LOADOP_LOAD, RenderPassAttachment::STOREOP_STORE, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL, + RESOURCE_STATE_DEPTHSTENCIL_READONLY ) ); if (getMSAASampleCount() > 1) { - desc.attachments.push_back(RenderPassAttachment::Resolve(&rtGbuffer_resolved[GBUFFER_COLOR])); + desc.attachments.push_back(RenderPassAttachment::Resolve(&rtMain)); } device->CreateRenderPass(&desc, &renderpass_transparent); } @@ -367,9 +382,9 @@ void RenderPath3D::ResizeBuffers() &depthBuffer_Reflection, RenderPassAttachment::LOADOP_CLEAR, RenderPassAttachment::STOREOP_STORE, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL, - IMAGE_LAYOUT_SHADER_RESOURCE + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL, + RESOURCE_STATE_SHADER_RESOURCE ) ); @@ -382,9 +397,9 @@ void RenderPath3D::ResizeBuffers() &rtReflection, RenderPassAttachment::LOADOP_DONTCARE, RenderPassAttachment::STOREOP_STORE, - IMAGE_LAYOUT_SHADER_RESOURCE, - IMAGE_LAYOUT_RENDERTARGET, - IMAGE_LAYOUT_SHADER_RESOURCE + RESOURCE_STATE_SHADER_RESOURCE, + RESOURCE_STATE_RENDERTARGET, + RESOURCE_STATE_SHADER_RESOURCE ) ); desc.attachments.push_back( @@ -392,9 +407,9 @@ void RenderPath3D::ResizeBuffers() &depthBuffer_Reflection, RenderPassAttachment::LOADOP_LOAD, RenderPassAttachment::STOREOP_DONTCARE, - IMAGE_LAYOUT_SHADER_RESOURCE, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + RESOURCE_STATE_SHADER_RESOURCE, + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL_READONLY ) ); @@ -413,9 +428,9 @@ void RenderPath3D::ResizeBuffers() &depthBuffer_Main, RenderPassAttachment::LOADOP_LOAD, RenderPassAttachment::STOREOP_STORE, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL_READONLY ) ); desc.attachments.push_back(RenderPassAttachment::RenderTarget(&rtSun[0], RenderPassAttachment::LOADOP_CLEAR)); @@ -441,9 +456,9 @@ void RenderPath3D::ResizeBuffers() &depthBuffer_Main, RenderPassAttachment::LOADOP_LOAD, RenderPassAttachment::STOREOP_STORE, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL_READONLY, + RESOURCE_STATE_DEPTHSTENCIL_READONLY ) ); @@ -473,8 +488,6 @@ void RenderPath3D::ResizeBuffers() desc.SampleCount = 1; desc.Usage = USAGE_DEFAULT; desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; device->CreateTexture(&desc, nullptr, &debugUAV); device->SetName(&debugUAV, "debugUAV"); @@ -488,8 +501,9 @@ void RenderPath3D::ResizeBuffers() wiRenderer::CreateVolumetricCloudResources(volumetriccloudResources, internalResolution); wiRenderer::CreateVolumetricCloudResources(volumetriccloudResources_reflection, XMUINT2(depthBuffer_Reflection.desc.Width, depthBuffer_Reflection.desc.Height)); wiRenderer::CreateBloomResources(bloomResources, internalResolution); + wiRenderer::CreateSurfelGIResources(surfelGIResources, internalResolution); - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { wiRenderer::CreateRTShadowResources(rtshadowResources, internalResolution); } @@ -510,7 +524,7 @@ void RenderPath3D::PreUpdate() void RenderPath3D::Update(float dt) { - if (rtGbuffer[GBUFFER_COLOR].desc.SampleCount != msaaSampleCount) + if (rtMain_render.desc.SampleCount != msaaSampleCount) { ResizeBuffers(); } @@ -519,14 +533,15 @@ void RenderPath3D::Update(float dt) if (getSceneUpdateEnabled()) { - scene->Update(dt * wiRenderer::GetGameSpeed()); - - if (wiRenderer::GetRaytracedShadowsEnabled() || + if (wiRenderer::GetSurfelGIEnabled() || + wiRenderer::GetRaytracedShadowsEnabled() || getAO() == AO_RTAO || getRaytracedReflectionEnabled()) { scene->SetAccelerationStructureUpdateRequested(true); } + + scene->Update(dt * wiRenderer::GetGameSpeed()); } // Frustum culling for main camera: @@ -607,6 +622,21 @@ void RenderPath3D::Render() const wiRenderer::UpdateRaytracingAccelerationStructures(*scene, cmd); + if (wiRenderer::GetSurfelGIEnabled()) + { + wiRenderer::UpdateCameraCB( + *camera, + camera_previous, + camera_reflection, + cmd + ); + wiRenderer::SurfelGI( + surfelGIResources, + *scene, + cmd + ); + } + }); } @@ -634,6 +664,8 @@ void RenderPath3D::Render() const cmd ); + wiRenderer::OcclusionCulling_Reset(visibility_main, cmd); // must be outside renderpass! + device->RenderPassBegin(&renderpass_depthprepass, cmd); device->EventBegin("Opaque Z-prepass", cmd); @@ -644,7 +676,6 @@ void RenderPath3D::Render() const vp.Height = (float)depthBuffer_Main.GetDesc().Height; device->BindViewports(1, &vp, cmd); wiRenderer::DrawScene(visibility_main, RENDERPASS_PREPASS, cmd, drawscene_flags); - wiRenderer::DrawSkyVelocity(cmd); wiProfiler::EndRange(range); device->EventEnd(cmd); @@ -656,6 +687,8 @@ void RenderPath3D::Render() const device->RenderPassEnd(cmd); + wiRenderer::OcclusionCulling_Resolve(visibility_main, cmd); // must be outside renderpass! + }); // Main camera compute effects: @@ -675,24 +708,33 @@ void RenderPath3D::Render() const cmd ); - // Create the top mip of depth pyramid from main depth buffer: - if (getMSAASampleCount() > 1) - { - wiRenderer::ResolveMSAADepthBuffer(depthBuffer_Copy, depthBuffer_Main, cmd); - } - else - { - wiRenderer::CopyTexture2D(depthBuffer_Copy, 0, 0, 0, depthBuffer_Main, 0, cmd); - } + wiRenderer::VisibilityResolve( + depthBuffer_Main, + rtPrimitiveID_render, + rtGbuffer, + depthBuffer_Copy, + rtLinearDepth, + cmd + ); - wiRenderer::Postprocess_DepthPyramid(depthBuffer_Copy, rtLinearDepth, cmd); + if (wiRenderer::GetSurfelGIEnabled()) + { + wiRenderer::SurfelGI_Coverage( + surfelGIResources, + *scene, + depthBuffer_Copy, + rtGbuffer, + debugUAV, + cmd + ); + } RenderAO(cmd); if (wiRenderer::GetVariableRateShadingClassification() && device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2)) { wiRenderer::ComputeShadingRateClassification( - GetGbuffer_Read(), + rtGbuffer, rtLinearDepth, rtShadingRate, debugUAV, @@ -729,6 +771,7 @@ void RenderPath3D::Render() const depthBuffer_Copy, rtLinearDepth, tiledLightResources.entityTiles_Opaque, + rtGbuffer, rtShadow, cmd, getScreenSpaceShadowRange(), @@ -745,7 +788,7 @@ void RenderPath3D::Render() const rtLinearDepth, depthBuffer_Copy1, tiledLightResources.entityTiles_Opaque, - GetGbuffer_Read(), + rtGbuffer, rtShadow, cmd ); @@ -766,8 +809,13 @@ void RenderPath3D::Render() const cmd = device->BeginCommandList(); wiJobSystem::Execute(ctx, [cmd, this](wiJobArgs args) { wiRenderer::BindCommonResources(cmd); - wiRenderer::RefreshDecalAtlas(*scene, cmd); - wiRenderer::RefreshLightmapAtlas(*scene, cmd); + wiRenderer::UpdateCameraCB( + *camera, + camera_previous, + camera_reflection, + cmd + ); + wiRenderer::RefreshLightmaps(*scene, cmd); wiRenderer::RefreshEnvProbes(visibility_main, cmd); wiRenderer::RefreshImpostors(*scene, cmd); }); @@ -852,15 +900,14 @@ void RenderPath3D::Render() const vp.Height = (float)depthBuffer_Reflection.GetDesc().Height; device->BindViewports(1, &vp, cmd); - device->UnbindResources(TEXSLOT_DEPTH, 1, cmd); device->RenderPassBegin(&renderpass_reflection, cmd); - device->BindResource(PS, &tiledLightResources_planarReflection.entityTiles_Opaque, TEXSLOT_RENDERPATH_ENTITYTILES, cmd); - device->BindResource(PS, wiTextureHelper::getTransparent(), TEXSLOT_RENDERPATH_REFLECTION, cmd); - device->BindResource(PS, wiTextureHelper::getWhite(), TEXSLOT_RENDERPATH_AO, cmd); - device->BindResource(PS, wiTextureHelper::getTransparent(), TEXSLOT_RENDERPATH_SSR, cmd); - device->BindResource(PS, wiTextureHelper::getUINT4(), TEXSLOT_RENDERPATH_RTSHADOW, cmd); + device->BindResource(&tiledLightResources_planarReflection.entityTiles_Opaque, TEXSLOT_RENDERPATH_ENTITYTILES, cmd); + device->BindResource(wiTextureHelper::getTransparent(), TEXSLOT_RENDERPATH_REFLECTION, cmd); + device->BindResource(wiTextureHelper::getWhite(), TEXSLOT_RENDERPATH_AO, cmd); + device->BindResource(wiTextureHelper::getTransparent(), TEXSLOT_RENDERPATH_SSR, cmd); + device->BindResource(wiTextureHelper::getUINT4(), TEXSLOT_RENDERPATH_RTSHADOW, cmd); wiRenderer::DrawScene(visibility_reflection, RENDERPASS_MAIN, cmd, drawscene_flags_reflections); wiRenderer::DrawSky(*scene, cmd); @@ -905,7 +952,7 @@ void RenderPath3D::Render() const *scene, depthBuffer_Copy, depthBuffer_Copy1, - GetGbuffer_Read(), + rtGbuffer, rtSSR, cmd ); @@ -922,19 +969,20 @@ void RenderPath3D::Render() const if (wiRenderer::GetRaytracedShadowsEnabled() || wiRenderer::GetScreenSpaceShadowsEnabled()) { - GPUBarrier barrier = GPUBarrier::Image(&rtShadow, rtShadow.desc.layout, IMAGE_LAYOUT_SHADER_RESOURCE); + GPUBarrier barrier = GPUBarrier::Image(&rtShadow, rtShadow.desc.layout, RESOURCE_STATE_SHADER_RESOURCE); device->Barrier(&barrier, 1, cmd); - device->BindResource(PS, &rtShadow, TEXSLOT_RENDERPATH_RTSHADOW, cmd); + device->BindResource(&rtShadow, TEXSLOT_RENDERPATH_RTSHADOW, cmd); } else { - device->BindResource(PS, wiTextureHelper::getUINT4(), TEXSLOT_RENDERPATH_RTSHADOW, cmd); + device->BindResource(wiTextureHelper::getUINT4(), TEXSLOT_RENDERPATH_RTSHADOW, cmd); } - device->BindResource(PS, &tiledLightResources.entityTiles_Opaque, TEXSLOT_RENDERPATH_ENTITYTILES, cmd); - device->BindResource(PS, getReflectionsEnabled() ? &rtReflection : wiTextureHelper::getTransparent(), TEXSLOT_RENDERPATH_REFLECTION, cmd); - device->BindResource(PS, getAOEnabled() ? &rtAO : wiTextureHelper::getWhite(), TEXSLOT_RENDERPATH_AO, cmd); - device->BindResource(PS, getSSREnabled() || getRaytracedReflectionEnabled() ? &rtSSR : wiTextureHelper::getTransparent(), TEXSLOT_RENDERPATH_SSR, cmd); + device->BindResource(&tiledLightResources.entityTiles_Opaque, TEXSLOT_RENDERPATH_ENTITYTILES, cmd); + device->BindResource(getReflectionsEnabled() ? &rtReflection : wiTextureHelper::getTransparent(), TEXSLOT_RENDERPATH_REFLECTION, cmd); + device->BindResource(getAOEnabled() ? &rtAO : wiTextureHelper::getWhite(), TEXSLOT_RENDERPATH_AO, cmd); + device->BindResource(getSSREnabled() || getRaytracedReflectionEnabled() ? &rtSSR : wiTextureHelper::getTransparent(), TEXSLOT_RENDERPATH_SSR, cmd); + device->BindResource(&surfelGIResources.result, TEXSLOT_RENDERPATH_SURFELGI, cmd); wiRenderer::DrawScene(visibility_main, RENDERPASS_MAIN, cmd, drawscene_flags); wiRenderer::DrawSky(*scene, cmd); @@ -949,7 +997,7 @@ void RenderPath3D::Render() const wiRenderer::Postprocess_Upsample_Bilateral( volumetriccloudResources.texture_temporal[device->GetFrameCount() % 2], rtLinearDepth, - *GetGbuffer_Read(GBUFFER_COLOR), // only desc is taken if pixel shader upsampling is used + rtMain_render, // only desc is taken if pixel shader upsampling is used cmd, true // pixel shader upsampling ); @@ -960,7 +1008,7 @@ void RenderPath3D::Render() const if (wiRenderer::GetRaytracedShadowsEnabled() || wiRenderer::GetScreenSpaceShadowsEnabled()) { - GPUBarrier barrier = GPUBarrier::Image(&rtShadow, IMAGE_LAYOUT_SHADER_RESOURCE, rtShadow.desc.layout); + GPUBarrier barrier = GPUBarrier::Image(&rtShadow, RESOURCE_STATE_SHADER_RESOURCE, rtShadow.desc.layout); device->Barrier(&barrier, 1, cmd); } @@ -990,6 +1038,7 @@ void RenderPath3D::Render() const RenderTransparents(cmd); RenderPostprocessChain(cmd); + }); RenderPath2D::Render(); @@ -1010,7 +1059,11 @@ void RenderPath3D::Compose(CommandList cmd) const wiImage::Draw(GetLastPostprocessRT(), fx, cmd); device->EventEnd(cmd); - if (wiRenderer::GetDebugLightCulling() || wiRenderer::GetVariableRateShadingClassificationDebug()) + if ( + wiRenderer::GetDebugLightCulling() || + wiRenderer::GetVariableRateShadingClassificationDebug() || + wiRenderer::GetSurfelGIDebugEnabled() + ) { fx.enableFullScreen(); fx.blendFlag = BLENDMODE_PREMULTIPLIED; @@ -1024,13 +1077,12 @@ void RenderPath3D::RenderFrameSetUp(CommandList cmd) const { GraphicsDevice* device = wiRenderer::GetDevice(); - device->BindResource(CS, &depthBuffer_Copy1, TEXSLOT_DEPTH, cmd); + device->BindResource(&depthBuffer_Copy1, TEXSLOT_DEPTH, cmd); wiRenderer::UpdateRenderData(visibility_main, frameCB, cmd); } void RenderPath3D::RenderAO(CommandList cmd) const { - wiRenderer::GetDevice()->UnbindResources(TEXSLOT_RENDERPATH_AO, 1, cmd); if (getAOEnabled()) { @@ -1075,7 +1127,7 @@ void RenderPath3D::RenderAO(CommandList cmd) const depthBuffer_Copy, rtLinearDepth, depthBuffer_Copy1, - GetGbuffer_Read(), + rtGbuffer, rtAO, cmd, getAORange(), @@ -1095,7 +1147,7 @@ void RenderPath3D::RenderSSR(CommandList cmd) const depthBuffer_Copy, rtLinearDepth, depthBuffer_Copy1, - GetGbuffer_Read(), + rtGbuffer, rtSSR, cmd ); @@ -1116,7 +1168,6 @@ void RenderPath3D::RenderLightShafts(CommandList cmd) const GraphicsDevice* device = wiRenderer::GetDevice(); device->EventBegin("Light Shafts", cmd); - device->UnbindResources(TEXSLOT_ONDEMAND0, TEXSLOT_ONDEMAND_COUNT, cmd); // Render sun stencil cutout: { @@ -1205,7 +1256,7 @@ void RenderPath3D::RenderSceneMIPChain(CommandList cmd) const fx.sampleFlag = SAMPLEMODE_CLAMP; fx.quality = QUALITY_LINEAR; fx.blendFlag = BLENDMODE_OPAQUE; - wiImage::Draw(GetGbuffer_Read(GBUFFER_COLOR), fx, cmd); + wiImage::Draw(&rtMain, fx, cmd); device->RenderPassEnd(cmd); @@ -1235,8 +1286,6 @@ void RenderPath3D::RenderTransparents(CommandList cmd) const device->RenderPassEnd(cmd); } - device->UnbindResources(TEXSLOT_GBUFFER0, 1, cmd); - device->UnbindResources(TEXSLOT_ONDEMAND0, TEXSLOT_ONDEMAND_COUNT, cmd); device->RenderPassBegin(&renderpass_transparent, cmd); @@ -1250,11 +1299,11 @@ void RenderPath3D::RenderTransparents(CommandList cmd) const auto range = wiProfiler::BeginRangeGPU("Transparent Scene", cmd); device->EventBegin("Transparent Scene", cmd); - device->BindResource(PS, &tiledLightResources.entityTiles_Transparent, TEXSLOT_RENDERPATH_ENTITYTILES, cmd); - device->BindResource(PS, &rtLinearDepth, TEXSLOT_LINEARDEPTH, cmd); - device->BindResource(PS, getReflectionsEnabled() ? &rtReflection : wiTextureHelper::getTransparent(), TEXSLOT_RENDERPATH_REFLECTION, cmd); - device->BindResource(PS, &rtSceneCopy, TEXSLOT_RENDERPATH_REFRACTION, cmd); - device->BindResource(PS, &rtWaterRipple, TEXSLOT_RENDERPATH_WATERRIPPLES, cmd); + device->BindResource(&tiledLightResources.entityTiles_Transparent, TEXSLOT_RENDERPATH_ENTITYTILES, cmd); + device->BindResource(&rtLinearDepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(getReflectionsEnabled() ? &rtReflection : wiTextureHelper::getTransparent(), TEXSLOT_RENDERPATH_REFLECTION, cmd); + device->BindResource(&rtSceneCopy, TEXSLOT_RENDERPATH_REFRACTION, cmd); + device->BindResource(&rtWaterRipple, TEXSLOT_RENDERPATH_WATERRIPPLES, cmd); uint32_t drawscene_flags = 0; drawscene_flags |= wiRenderer::DRAWSCENE_TRANSPARENT; @@ -1323,7 +1372,7 @@ void RenderPath3D::RenderPostprocessChain(CommandList cmd) const GraphicsDevice* device = wiRenderer::GetDevice(); const Texture* rt_first = nullptr; // not ping-ponged with read / write - const Texture* rt_read = GetGbuffer_Read(GBUFFER_COLOR); + const Texture* rt_read = &rtMain; const Texture* rt_write = &rtPostprocess_HDR; // 1.) HDR post process chain @@ -1338,7 +1387,7 @@ void RenderPath3D::RenderPostprocessChain(CommandList cmd) const *rt_read, rtTemporalAA[history], rtLinearDepth, depthBuffer_Copy1, - GetGbuffer_Read(), + rtGbuffer, rtTemporalAA[output], cmd ); @@ -1358,7 +1407,6 @@ void RenderPath3D::RenderPostprocessChain(CommandList cmd) const rt_first = nullptr; std::swap(rt_read, rt_write); - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); } if (getMotionBlurEnabled() && getMotionBlurStrength() > 0) @@ -1367,7 +1415,7 @@ void RenderPath3D::RenderPostprocessChain(CommandList cmd) const motionblurResources, rt_first == nullptr ? *rt_read : *rt_first, rtLinearDepth, - GetGbuffer_Read(), + rtGbuffer, *rt_write, cmd, getMotionBlurStrength() @@ -1375,7 +1423,6 @@ void RenderPath3D::RenderPostprocessChain(CommandList cmd) const rt_first = nullptr; std::swap(rt_read, rt_write); - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); } if (getBloomEnabled()) @@ -1390,7 +1437,6 @@ void RenderPath3D::RenderPostprocessChain(CommandList cmd) const rt_first = nullptr; std::swap(rt_read, rt_write); - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); } } @@ -1406,14 +1452,13 @@ void RenderPath3D::RenderPostprocessChain(CommandList cmd) const getDitherEnabled(), getColorGradingEnabled() ? (scene->weather.colorGradingMap == nullptr ? nullptr : &scene->weather.colorGradingMap->texture) : nullptr, getMSAASampleCount() > 1 ? &rtParticleDistortion_Resolved : &rtParticleDistortion, - getEyeAdaptionEnabled() ? wiRenderer::ComputeLuminance(luminanceResources, *GetGbuffer_Read(GBUFFER_COLOR), cmd, getEyeAdaptionRate()) : nullptr, + getEyeAdaptionEnabled() ? wiRenderer::ComputeLuminance(luminanceResources, rtMain, cmd, getEyeAdaptionRate()) : nullptr, getEyeAdaptionKey() ); rt_first = nullptr; rt_read = rt_write; rt_write = &rtPostprocess_LDR[1]; - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); } // 3.) LDR post process chain @@ -1423,7 +1468,6 @@ void RenderPath3D::RenderPostprocessChain(CommandList cmd) const wiRenderer::Postprocess_Sharpen(*rt_read, *rt_write, cmd, getSharpenFilterAmount()); std::swap(rt_read, rt_write); - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); } if (getFXAAEnabled()) @@ -1431,7 +1475,6 @@ void RenderPath3D::RenderPostprocessChain(CommandList cmd) const wiRenderer::Postprocess_FXAA(*rt_read, *rt_write, cmd); std::swap(rt_read, rt_write); - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); } if (getChromaticAberrationEnabled()) @@ -1439,7 +1482,6 @@ void RenderPath3D::RenderPostprocessChain(CommandList cmd) const wiRenderer::Postprocess_Chromatic_Aberration(*rt_read, *rt_write, cmd, getChromaticAberrationAmount()); std::swap(rt_read, rt_write); - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); } // GUI Background blurring: @@ -1457,7 +1499,6 @@ void RenderPath3D::RenderPostprocessChain(CommandList cmd) const { wiRenderer::Postprocess_FSR(*rt_read, rtFSR[1], rtFSR[0], cmd, getFSRSharpness()); - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); } } } @@ -1481,7 +1522,7 @@ void RenderPath3D::setAO(AO value) TextureDesc desc; desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; desc.Format = FORMAT_R8_UNORM; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; switch (ao) { diff --git a/WickedEngine/RenderPath3D.h b/WickedEngine/RenderPath3D.h index 2d5902fc7..f774a0663 100644 --- a/WickedEngine/RenderPath3D.h +++ b/WickedEngine/RenderPath3D.h @@ -64,8 +64,10 @@ private: uint32_t msaaSampleCount = 1; public: + wiGraphics::Texture rtMain; + wiGraphics::Texture rtMain_render; // can be MSAA wiGraphics::Texture rtGbuffer[GBUFFER_COUNT]; - wiGraphics::Texture rtGbuffer_resolved[GBUFFER_COUNT]; + wiGraphics::Texture rtPrimitiveID_render; // can be MSAA wiGraphics::Texture rtReflection; // contains the scene rendered for planar reflections wiGraphics::Texture rtSSR; // standard screen-space reflection results wiGraphics::Texture rtSceneCopy; // contains the rendered scene that can be fed into transparent pass for distortion effect @@ -121,29 +123,7 @@ public: wiRenderer::VolumetricCloudResources volumetriccloudResources; wiRenderer::VolumetricCloudResources volumetriccloudResources_reflection; wiRenderer::BloomResources bloomResources; - - const constexpr wiGraphics::Texture* GetGbuffer_Read() const - { - if (getMSAASampleCount() > 1) - { - return rtGbuffer_resolved; - } - else - { - return rtGbuffer; - } - } - const constexpr wiGraphics::Texture* GetGbuffer_Read(GBUFFER i) const - { - if (getMSAASampleCount() > 1) - { - return &rtGbuffer_resolved[i]; - } - else - { - return &rtGbuffer[i]; - } - } + wiRenderer::SurfelGIResources surfelGIResources; // Post-processes are ping-ponged, this function helps to obtain the last postprocess render target that was written const wiGraphics::Texture* GetLastPostprocessRT() const diff --git a/WickedEngine/RenderPath3D_PathTracing.cpp b/WickedEngine/RenderPath3D_PathTracing.cpp index 788c481a3..260555534 100644 --- a/WickedEngine/RenderPath3D_PathTracing.cpp +++ b/WickedEngine/RenderPath3D_PathTracing.cpp @@ -55,7 +55,7 @@ void RenderPath3D_PathTracing::ResizeBuffers() #ifdef OPEN_IMAGE_DENOISE desc.BindFlags = BIND_UNORDERED_ACCESS; - desc.layout = IMAGE_LAYOUT_UNORDERED_ACCESS; + desc.layout = RESOURCE_STATE_UNORDERED_ACCESS; device->CreateTexture(&desc, nullptr, &denoiserAlbedo); device->SetName(&denoiserAlbedo, "denoiserAlbedo"); device->CreateTexture(&desc, nullptr, &denoiserNormal); @@ -93,6 +93,8 @@ void RenderPath3D_PathTracing::ResizeBuffers() device->CreateRenderPass(&desc, &renderpass_debugbvh); } + wiRenderer::CreateLuminanceResources(luminanceResources, internalResolution); + // also reset accumulation buffer state: sam = -1; } @@ -306,25 +308,6 @@ void RenderPath3D_PathTracing::Render() const wiProfiler::EndRange(range); // Traced Scene } - wiRenderer::Postprocess_Tonemap( - denoiserResult.IsValid() ? denoiserResult : traceResult, - rtPostprocess_LDR[0], - cmd, - getExposure(), - getDitherEnabled(), - getColorGradingEnabled() ? (scene->weather.colorGradingMap == nullptr ? nullptr : &scene->weather.colorGradingMap->texture) : nullptr - ); - - // GUI Background blurring: - { - auto range = wiProfiler::BeginRangeGPU("GUI Background Blur", cmd); - device->EventBegin("GUI Background Blur", cmd); - wiRenderer::Postprocess_Downsample4x(rtPostprocess_LDR[0], rtGUIBlurredBackground[0], cmd); - wiRenderer::Postprocess_Downsample4x(rtGUIBlurredBackground[0], rtGUIBlurredBackground[2], cmd); - wiRenderer::Postprocess_Blur_Gaussian(rtGUIBlurredBackground[2], rtGUIBlurredBackground[1], rtGUIBlurredBackground[2], cmd, -1, -1, true); - device->EventEnd(cmd); - wiProfiler::EndRange(range); - } }); } @@ -342,13 +325,18 @@ void RenderPath3D_PathTracing::Render() const ); wiRenderer::BindCommonResources(cmd); + Texture srcTex = denoiserResult.IsValid() && !wiJobSystem::IsBusy(denoiserContext) ? denoiserResult : traceResult; + wiRenderer::Postprocess_Tonemap( - denoiserResult.IsValid() && !wiJobSystem::IsBusy(denoiserContext) ? denoiserResult : traceResult, + srcTex, rtPostprocess_LDR[0], cmd, getExposure(), getDitherEnabled(), - getColorGradingEnabled() ? (scene->weather.colorGradingMap == nullptr ? nullptr : &scene->weather.colorGradingMap->texture) : nullptr + getColorGradingEnabled() ? (scene->weather.colorGradingMap == nullptr ? nullptr : &scene->weather.colorGradingMap->texture) : nullptr, + nullptr, + getEyeAdaptionEnabled() ? wiRenderer::ComputeLuminance(luminanceResources, srcTex, cmd, getEyeAdaptionRate()) : nullptr, + getEyeAdaptionKey() ); // GUI Background blurring: diff --git a/WickedEngine/WickedEngine_SOURCE.vcxitems b/WickedEngine/WickedEngine_SOURCE.vcxitems index b00f37774..16322f20e 100644 --- a/WickedEngine/WickedEngine_SOURCE.vcxitems +++ b/WickedEngine/WickedEngine_SOURCE.vcxitems @@ -262,7 +262,6 @@ - @@ -319,7 +318,6 @@ - @@ -658,7 +656,6 @@ - diff --git a/WickedEngine/WickedEngine_SOURCE.vcxitems.filters b/WickedEngine/WickedEngine_SOURCE.vcxitems.filters index 585df0619..35bc2a001 100644 --- a/WickedEngine/WickedEngine_SOURCE.vcxitems.filters +++ b/WickedEngine/WickedEngine_SOURCE.vcxitems.filters @@ -894,9 +894,6 @@ ENGINE\Graphics\API - - ENGINE\Graphics\API - ENGINE\Graphics @@ -912,9 +909,6 @@ ENGINE\Graphics\API - - ENGINE\Graphics\API - UTILITY @@ -960,9 +954,6 @@ ENGINE\High level interface - - ENGINE\High level interface - ENGINE\High level interface @@ -1086,6 +1077,9 @@ ENGINE\System + + ENGINE\High level interface + @@ -1706,9 +1700,6 @@ ENGINE\Graphics\API - - ENGINE\Graphics\API - ENGINE\Graphics diff --git a/WickedEngine/WickedEngine_Windows.vcxproj b/WickedEngine/WickedEngine_Windows.vcxproj index 2e54b27ba..3c82cb514 100644 --- a/WickedEngine/WickedEngine_Windows.vcxproj +++ b/WickedEngine/WickedEngine_Windows.vcxproj @@ -87,7 +87,8 @@ %(AdditionalLibraryDirectories) - IF NOT EXIST "$(ProjectDir)shaders\" mkdir "$(ProjectDir)shaders\" + + @@ -121,7 +122,8 @@ true - IF NOT EXIST "$(ProjectDir)shaders\" mkdir "$(ProjectDir)shaders\" + + diff --git a/WickedEngine/d3dcompiler_47.dll b/WickedEngine/d3dcompiler_47.dll deleted file mode 100644 index 66976312175645bd913723841af999bd893b3cd8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4524496 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

    ;+g)5<6l5?! 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�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

    kM+m!6*+7{jsv*bLFLF{AU*D+6dcrg~q*|R(k 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 onto the simulation to avoid blowing up - float xParticleEmissive; + float xEmitter_padding2; float3 xParticleGravity; float xParticleDrag; diff --git a/WickedEngine/shaders/ShaderInterop_Font.h b/WickedEngine/shaders/ShaderInterop_Font.h index ab9e3477e..5f6c94a49 100644 --- a/WickedEngine/shaders/ShaderInterop_Font.h +++ b/WickedEngine/shaders/ShaderInterop_Font.h @@ -1,17 +1,16 @@ #ifndef WI_SHADERINTEROP_FONT_H #define WI_SHADERINTEROP_FONT_H - #include "ShaderInterop.h" -CBUFFER(FontCB, CBSLOT_FONT) +struct PushConstantsFont { - float4x4 g_xFont_Transform; - float4 g_xFont_Color; - uint g_xFont_BufferOffset; - int g_xFont_TextureIndex; - float g_xFont_padding0; - float g_xFont_padding1; + float4x4 transform; + uint color; + int buffer_index; + uint buffer_offset; + int texture_index; }; +PUSHCONSTANT(push, PushConstantsFont); #endif // WI_SHADERINTEROP_FONT_H diff --git a/WickedEngine/shaders/ShaderInterop_HairParticle.h b/WickedEngine/shaders/ShaderInterop_HairParticle.h index 1f644e566..c0400913d 100644 --- a/WickedEngine/shaders/ShaderInterop_HairParticle.h +++ b/WickedEngine/shaders/ShaderInterop_HairParticle.h @@ -5,24 +5,19 @@ #define THREADCOUNT_SIMULATEHAIR 256 -struct Patch +struct PatchSimulationData { float3 position; uint tangent_random; float3 normal; // need high precision for the simulation! uint binormal_length; -}; - -struct PatchSimulationData -{ float3 velocity; uint padding; }; CBUFFER(HairParticleCB, CBSLOT_OTHER_HAIRPARTICLE) { - float4x4 xWorld; - float4 xColor; + float4x4 xHairWorld; uint xHairRegenerate; float xLength; @@ -46,6 +41,11 @@ CBUFFER(HairParticleCB, CBSLOT_OTHER_HAIRPARTICLE) float2 xHairTexMul; float xHairAspect; uint xHairLayerMask; + + uint xHairInstanceIndex; + uint padding0; + uint padding1; + uint padding2; }; #endif // WI_SHADERINTEROP_HAIRPARTICLE_H diff --git a/WickedEngine/shaders/ShaderInterop_Image.h b/WickedEngine/shaders/ShaderInterop_Image.h index 49502dce7..7c5057b83 100644 --- a/WickedEngine/shaders/ShaderInterop_Image.h +++ b/WickedEngine/shaders/ShaderInterop_Image.h @@ -2,21 +2,23 @@ #define WI_SHADERINTEROP_IMAGE_H #include "ShaderInterop.h" -CBUFFER(ImageCB, CBSLOT_IMAGE) -{ - float4 xCorners[4]; - float4 xTexMulAdd; - float4 xTexMulAdd2; - float4 xColor; -}; +static const uint IMAGE_FLAG_EXTRACT_NORMALMAP = 1 << 0; struct PushConstantsImage { - int texture_base_index; - int texture_mask_index; - int texture_background_index; - int sampler_index; + float4 corners[4]; + float4 texMulAdd; + float4 texMulAdd2; + + uint2 packed_color; // packed half4 + uint flags; + int sampler_index; + + int texture_base_index; + int texture_mask_index; + int texture_background_index; }; +PUSHCONSTANT(push, PushConstantsImage); #endif // WI_SHADERINTEROP_IMAGE_H diff --git a/WickedEngine/shaders/ShaderInterop_Paint.h b/WickedEngine/shaders/ShaderInterop_Paint.h deleted file mode 100644 index 83e5d4761..000000000 --- a/WickedEngine/shaders/ShaderInterop_Paint.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef WI_SHADERINTEROP_PAINT_H -#define WI_SHADERINTEROP_PAINT_H -#include "ShaderInterop.h" - -static const uint PAINT_TEXTURE_BLOCKSIZE = 8; - -CBUFFER(PaintTextureCB, CBSLOT_RENDERER_UTILITY) -{ - uint2 xPaintBrushCenter; - uint xPaintBrushRadius; - float xPaintBrushAmount; - - float xPaintBrushFalloff; - uint xPaintBrushColor; - uint2 padding0; -}; - -CBUFFER(PaintRadiusCB, CBSLOT_RENDERER_UTILITY) -{ - uint2 xPaintRadResolution; - uint2 xPaintRadCenter; - uint xPaintRadUVSET; - float xPaintRadRadius; - uint2 pad; -}; - -#endif // WI_SHADERINTEROP_PAINT_H diff --git a/WickedEngine/shaders/ShaderInterop_Renderer.h b/WickedEngine/shaders/ShaderInterop_Renderer.h index c4e892227..d8d1108b9 100644 --- a/WickedEngine/shaders/ShaderInterop_Renderer.h +++ b/WickedEngine/shaders/ShaderInterop_Renderer.h @@ -2,6 +2,18 @@ #define WI_SHADERINTEROP_RENDERER_H #include "ShaderInterop.h" +struct ShaderScene +{ + int instancebuffer; + int meshbuffer; + int materialbuffer; + int TLAS; + + int envmaparray; + int globalenvmap; + int padding1; + int padding2; +}; static const uint SHADERMATERIAL_OPTION_BIT_USE_VERTEXCOLORS = 1 << 0; static const uint SHADERMATERIAL_OPTION_BIT_SPECULARGLOSSINESS_WORKFLOW = 1 << 1; @@ -10,6 +22,8 @@ static const uint SHADERMATERIAL_OPTION_BIT_OCCLUSION_SECONDARY = 1 << 3; static const uint SHADERMATERIAL_OPTION_BIT_USE_WIND = 1 << 4; static const uint SHADERMATERIAL_OPTION_BIT_RECEIVE_SHADOW = 1 << 5; static const uint SHADERMATERIAL_OPTION_BIT_CAST_SHADOW = 1 << 6; +static const uint SHADERMATERIAL_OPTION_BIT_DOUBLE_SIDED = 1 << 7; +static const uint SHADERMATERIAL_OPTION_BIT_TRANSPARENT = 1 << 8; struct ShaderMaterial { @@ -96,6 +110,8 @@ struct ShaderMaterial inline bool IsCastingShadow() { return options & SHADERMATERIAL_OPTION_BIT_CAST_SHADOW; } }; +static const uint SHADERMESH_FLAG_DOUBLE_SIDED = 1 << 0; + struct ShaderMesh { int ib; @@ -109,25 +125,193 @@ struct ShaderMesh int vb_pre; int subsetbuffer; - int blendmaterial1; - int blendmaterial2; - int blendmaterial3; + uint blendmaterial1; + uint blendmaterial2; + uint blendmaterial3; + + float3 aabb_min; + uint flags; + float3 aabb_max; + float tessellation_factor; + + void init() + { + ib = -1; + vb_pos_nor_wind = -1; + vb_tan = -1; + vb_col = -1; + + vb_uv0 = -1; + vb_uv1 = -1; + vb_atl = -1; + vb_pre = -1; + + subsetbuffer = -1; + blendmaterial1 = 0; + blendmaterial2 = 0; + blendmaterial3 = 0; + + aabb_min = float3(0, 0, 0); + aabb_max = float3(0, 0, 0); + + flags = 0; + } }; struct ShaderMeshSubset { uint indexOffset; - uint indexCount; - int mesh; - int material; + uint materialIndex; + + void init() + { + indexOffset = 0; + materialIndex = 0; + } +}; + +struct ShaderTransform +{ + float4 mat0; + float4 mat1; + float4 mat2; + + void init() + { + mat0 = float4(1, 0, 0, 0); + mat1 = float4(0, 1, 0, 0); + mat2 = float4(0, 0, 1, 0); + } + void Create(float4x4 mat) + { + mat0 = float4(mat._11, mat._21, mat._31, mat._41); + mat1 = float4(mat._12, mat._22, mat._32, mat._42); + mat2 = float4(mat._13, mat._23, mat._33, mat._43); + } + float4x4 GetMatrix() +#ifdef __cplusplus + const +#endif // __cplusplus + { + return float4x4( + mat0.x, mat0.y, mat0.z, mat0.w, + mat1.x, mat1.y, mat1.z, mat1.w, + mat2.x, mat2.y, mat2.z, mat2.w, + 0, 0, 0, 1 + ); + } +}; + +struct ShaderMeshInstance +{ + uint uid; + uint flags; + uint meshIndex; + uint color; + uint emissive; + int lightmap; + int padding0; + int padding1; + ShaderTransform transform; + ShaderTransform transformInverseTranspose; // This correctly handles non uniform scaling for normals + ShaderTransform transformPrev; + + void init() + { + uid = 0; + flags = 0; + meshIndex = ~0; + color = ~0u; + emissive = ~0u; + lightmap = -1; + transform.init(); + transformInverseTranspose.init(); + transformPrev.init(); + } + +}; +struct ShaderMeshInstancePointer +{ + uint instanceID; + uint userdata; + + void init() + { + instanceID = ~0; + userdata = 0; + } + void Create(uint _instanceID, uint frustum_index, float dither) + { + instanceID = _instanceID; + userdata = 0; + userdata |= frustum_index & 0xF; + userdata |= (uint(dither * 255.0f) & 0xFF) << 4u; + } + uint GetFrustumIndex() + { + return userdata & 0xF; + } + float GetDither() + { + return ((userdata >> 4u) & 0xFF) / 255.0f; + } }; struct ObjectPushConstants { - int mesh; - int material; + uint meshIndex_subsetIndex; // 24-bit mesh, 8-bit subset + uint materialIndex; int instances; uint instance_offset; + + void init( + uint _meshIndex, + uint _subsetIndex, + uint _materialIndex, + int _instances, + uint _instance_offset + ) + { + meshIndex_subsetIndex = 0; + meshIndex_subsetIndex |= _meshIndex & 0xFFFFFF; + meshIndex_subsetIndex |= (_subsetIndex & 0xFF) << 24u; + materialIndex = _materialIndex; + instances = _instances; + instance_offset = _instance_offset; + } + uint GetMeshIndex() + { + return meshIndex_subsetIndex & 0xFFFFFF; + } + uint GetSubsetIndex() + { + return (meshIndex_subsetIndex >> 24u) & 0xFF; + } + uint GetMaterialIndex() + { + return materialIndex; + } +}; + +struct PrimitiveID +{ + uint primitiveIndex; + uint instanceIndex; + uint subsetIndex; + + uint2 pack() + { + // 32 bit primitiveID + // 24 bit instanceID + // 8 bit subsetID + return uint2(primitiveIndex, (instanceIndex & 0xFFFFFF) | ((subsetIndex & 0xFF) << 24u)); + } + void unpack(uint2 value) + { + primitiveIndex = value.x; + instanceIndex = value.y & 0xFFFFFF; + subsetIndex = (value.y >> 24u) & 0xFF; + } }; // Warning: the size of this structure directly affects shader performance. @@ -525,7 +709,7 @@ struct VolumetricCloudParameters }; -// These option bits can be read from g_xFrame_Options constant buffer value: +// These option bits can be read from Options constant buffer value: static const uint OPTION_BIT_TEMPORALAA_ENABLED = 1 << 0; static const uint OPTION_BIT_TRANSPARENTSHADOWS_ENABLED = 1 << 1; static const uint OPTION_BIT_VOXELGI_ENABLED = 1 << 2; @@ -535,126 +719,130 @@ static const uint OPTION_BIT_SIMPLE_SKY = 1 << 5; static const uint OPTION_BIT_REALISTIC_SKY = 1 << 6; static const uint OPTION_BIT_HEIGHT_FOG = 1 << 7; static const uint OPTION_BIT_RAYTRACED_SHADOWS = 1 << 8; -static const uint OPTION_BIT_DISABLE_ALBEDO_MAPS = 1 << 9; -static const uint OPTION_BIT_SHADOW_MASK = 1 << 10; +static const uint OPTION_BIT_SHADOW_MASK = 1 << 9; +static const uint OPTION_BIT_SURFELGI_ENABLED = 1 << 10; +static const uint OPTION_BIT_DISABLE_ALBEDO_MAPS = 1 << 11; +static const uint OPTION_BIT_FORCE_DIFFUSE_LIGHTING = 1 << 12; // ---------- Common Constant buffers: ----------------- -CBUFFER(FrameCB, CBSLOT_RENDERER_FRAME) +struct FrameCB { - float2 g_xFrame_CanvasSize; - float2 g_xFrame_CanvasSize_rcp; + float2 CanvasSize; + float2 CanvasSize_rcp; - float2 g_xFrame_InternalResolution; - float2 g_xFrame_InternalResolution_rcp; + float2 InternalResolution; + float2 InternalResolution_rcp; - float3 g_xFrame_SunColor; - float g_xFrame_Gamma; + float3 SunColor; + float Gamma; - float3 g_xFrame_SunDirection; - uint g_xFrame_ShadowCascadeCount; + float3 SunDirection; + uint ShadowCascadeCount; - float3 g_xFrame_Horizon; - uint g_xFrame_ConstantOne; // Just a constant 1 value as uint (can be used to force disable loop unrolling) + float3 Horizon; + uint ConstantOne; // Just a constant 1 value as uint (can be used to force disable loop unrolling) - float3 g_xFrame_Zenith; - float g_xFrame_CloudScale; + float3 Zenith; + float CloudScale; - float3 g_xFrame_Ambient; - float g_xFrame_Cloudiness; + float3 Ambient; + float Cloudiness; - float4 g_xFrame_Fog; // Fog Start,End,Height Start,Height End + float4 Fog; // Fog Start,End,Height Start,Height End - float g_xFrame_padding0; - float g_xFrame_FogHeightSky; - float g_xFrame_SkyExposure; - float g_xFrame_VoxelRadianceMaxDistance; // maximum raymarch distance for voxel GI in world-space + float padding0; + float FogHeightSky; + float SkyExposure; + float VoxelRadianceMaxDistance; // maximum raymarch distance for voxel GI in world-space - float g_xFrame_VoxelRadianceDataSize; // voxel half-extent in world space units - float g_xFrame_VoxelRadianceDataSize_rcp; // 1.0 / voxel-half extent - uint g_xFrame_VoxelRadianceDataRes; // voxel grid resolution - float g_xFrame_VoxelRadianceDataRes_rcp; // 1.0 / voxel grid resolution + float VoxelRadianceDataSize; // voxel half-extent in world space units + float VoxelRadianceDataSize_rcp; // 1.0 / voxel-half extent + uint VoxelRadianceDataRes; // voxel grid resolution + float VoxelRadianceDataRes_rcp; // 1.0 / voxel grid resolution - uint g_xFrame_VoxelRadianceDataMIPs; // voxel grid mipmap count - uint g_xFrame_VoxelRadianceNumCones; // number of diffuse cones to trace - float g_xFrame_VoxelRadianceNumCones_rcp; // 1.0 / number of diffuse cones to trace - float g_xFrame_VoxelRadianceRayStepSize; // raymarch step size in voxel space units + uint VoxelRadianceDataMIPs; // voxel grid mipmap count + uint VoxelRadianceNumCones; // number of diffuse cones to trace + float VoxelRadianceNumCones_rcp; // 1.0 / number of diffuse cones to trace + float VoxelRadianceRayStepSize; // raymarch step size in voxel space units - float3 g_xFrame_VoxelRadianceDataCenter; // center of the voxel grid in world space units - uint g_xFrame_Options; // wiRenderer bool options packed into bitmask + float3 VoxelRadianceDataCenter; // center of the voxel grid in world space units + uint Options; // wiRenderer bool options packed into bitmask - uint3 g_xFrame_EntityCullingTileCount; - int g_xFrame_GlobalEnvProbeIndex; + uint3 EntityCullingTileCount; + int GlobalEnvProbeIndex; - uint g_xFrame_EnvProbeMipCount; - float g_xFrame_EnvProbeMipCount_rcp; - float g_xFrame_Time; - float g_xFrame_TimePrev; + uint EnvProbeMipCount; + float EnvProbeMipCount_rcp; + float Time; + float TimePrev; - float g_xFrame_SunEnergy; - float g_xFrame_WindSpeed; - float g_xFrame_DeltaTime; - uint g_xFrame_FrameCount; + float SunEnergy; + float WindSpeed; + float DeltaTime; + uint FrameCount; - uint g_xFrame_LightArrayOffset; // indexing into entity array - uint g_xFrame_LightArrayCount; // indexing into entity array - uint g_xFrame_DecalArrayOffset; // indexing into entity array - uint g_xFrame_DecalArrayCount; // indexing into entity array + uint LightArrayOffset; // indexing into entity array + uint LightArrayCount; // indexing into entity array + uint DecalArrayOffset; // indexing into entity array + uint DecalArrayCount; // indexing into entity array - uint g_xFrame_ForceFieldArrayOffset; // indexing into entity array - uint g_xFrame_ForceFieldArrayCount; // indexing into entity array - uint g_xFrame_EnvProbeArrayOffset; // indexing into entity array - uint g_xFrame_EnvProbeArrayCount; // indexing into entity array + uint ForceFieldArrayOffset; // indexing into entity array + uint ForceFieldArrayCount; // indexing into entity array + uint EnvProbeArrayOffset; // indexing into entity array + uint EnvProbeArrayCount; // indexing into entity array - float3 g_xFrame_WindDirection; - float g_xFrame_WindWaveSize; + float3 WindDirection; + float WindWaveSize; - float3 g_xFrame_WorldBoundsMin; // world enclosing AABB min - float g_xFrame_CloudSpeed; + float3 WorldBoundsMin; // world enclosing AABB min + float CloudSpeed; - float3 g_xFrame_WorldBoundsMax; // world enclosing AABB max - float g_xFrame_WindRandomness; + float3 WorldBoundsMax; // world enclosing AABB max + float WindRandomness; - float3 g_xFrame_WorldBoundsExtents; // world enclosing AABB abs(max - min) - float g_xFrame_StaticSkyGamma; // possible values (0: no static sky; 1: hdr static sky; other: actual gamma when ldr) + float3 WorldBoundsExtents; // world enclosing AABB abs(max - min) + float StaticSkyGamma; // possible values (0: no static sky; 1: hdr static sky; other: actual gamma when ldr) - float3 g_xFrame_WorldBoundsExtents_rcp; // world enclosing AABB 1.0f / abs(max - min) - uint g_xFrame_TemporalAASampleRotation; + float3 WorldBoundsExtents_rcp; // world enclosing AABB 1.0f / abs(max - min) + uint TemporalAASampleRotation; - float g_xFrame_ShadowKernel2D; - float g_xFrame_ShadowKernelCube; - int g_xFrame_ObjectShaderSamplerIndex; - float g_xFrame_BlueNoisePhase; + float ShadowKernel2D; + float ShadowKernelCube; + int ObjectShaderSamplerIndex; + float BlueNoisePhase; - AtmosphereParameters g_xFrame_Atmosphere; - VolumetricCloudParameters g_xFrame_VolumetricClouds; + AtmosphereParameters Atmosphere; + VolumetricCloudParameters VolumetricClouds; + + ShaderScene scene; }; -CBUFFER(CameraCB, CBSLOT_RENDERER_CAMERA) +struct CameraCB { - float4x4 g_xCamera_VP; // View*Projection + float4x4 VP; // View*Projection - float4 g_xCamera_ClipPlane; + float4 ClipPlane; - float3 g_xCamera_CamPos; - float g_xCamera_DistanceFromOrigin; + float3 CamPos; + float DistanceFromOrigin; - float3 g_xCamera_At; - float g_xCamera_ZNearP; + float3 At; + float ZNearP; - float3 g_xCamera_Up; - float g_xCamera_ZFarP; + float3 Up; + float ZFarP; - float g_xCamera_ZNearP_rcp; - float g_xCamera_ZFarP_rcp; - float g_xCamera_ZRange; - float g_xCamera_ZRange_rcp; + float ZNearP_rcp; + float ZFarP_rcp; + float ZRange; + float ZRange_rcp; - float4x4 g_xCamera_View; - float4x4 g_xCamera_Proj; - float4x4 g_xCamera_InvV; // Inverse View - float4x4 g_xCamera_InvP; // Inverse Projection - float4x4 g_xCamera_InvVP; // Inverse View-Projection + float4x4 View; + float4x4 Proj; + float4x4 InvV; // Inverse View + float4x4 InvP; // Inverse Projection + float4x4 InvVP; // Inverse View-Projection // Frustum planes: // 0 : near @@ -663,45 +851,30 @@ CBUFFER(CameraCB, CBSLOT_RENDERER_CAMERA) // 3 : right // 4 : top // 5 : bottom - float4 g_xCamera_FrustumPlanes[6]; + float4 FrustumPlanes[6]; - float2 g_xFrame_TemporalAAJitter; - float2 g_xFrame_TemporalAAJitterPrev; + float2 TemporalAAJitter; + float2 TemporalAAJitterPrev; - float4x4 g_xCamera_PrevV; - float4x4 g_xCamera_PrevP; - float4x4 g_xCamera_PrevVP; // PrevView*PrevProjection - float4x4 g_xCamera_PrevInvVP; // Inverse(PrevView*PrevProjection) - float4x4 g_xCamera_ReflVP; // ReflectionView*ReflectionProjection - float4x4 g_xCamera_Reprojection; // view_projection_inverse_matrix * previous_view_projection_matrix + float4x4 PrevV; + float4x4 PrevP; + float4x4 PrevVP; // PrevView*PrevProjection + float4x4 PrevInvVP; // Inverse(PrevView*PrevProjection) + float4x4 ReflVP; // ReflectionView*ReflectionProjection + float4x4 Reprojection; // view_projection_inverse_matrix * previous_view_projection_matrix - float2 g_xCamera_ApertureShape; - float g_xCamera_ApertureSize; - float g_xCamera_FocalLength; + float2 ApertureShape; + float ApertureSize; + float FocalLength; }; +CONSTANTBUFFER(g_xFrame, FrameCB, CBSLOT_RENDERER_FRAME); +CONSTANTBUFFER(g_xCamera, CameraCB, CBSLOT_RENDERER_CAMERA); // ------- On demand Constant buffers: ---------- -CBUFFER(MaterialCB, CBSLOT_RENDERER_MATERIAL) -{ - ShaderMaterial g_xMaterial; -}; -CBUFFER(MaterialCB_Blend1, CBSLOT_RENDERER_MATERIAL_BLEND1) -{ - ShaderMaterial g_xMaterial_blend1; -}; -CBUFFER(MaterialCB_Blend2, CBSLOT_RENDERER_MATERIAL_BLEND2) -{ - ShaderMaterial g_xMaterial_blend2; -}; -CBUFFER(MaterialCB_Blend3, CBSLOT_RENDERER_MATERIAL_BLEND3) -{ - ShaderMaterial g_xMaterial_blend3; -}; - CBUFFER(MiscCB, CBSLOT_RENDERER_MISC) { float4x4 g_xTransform; @@ -715,15 +888,6 @@ CBUFFER(ForwardEntityMaskCB, CBSLOT_RENDERER_FORWARD_LIGHTMASK) uint xForwardEnvProbeMask; // supports indexing 32 environment probes }; -CBUFFER(DecalCB, CBSLOT_RENDERER_DECAL) -{ - float4x4 xDecalVP; - float3 eye; - int hasTexNor; - float3 front; - float opacity; -}; - CBUFFER(VolumeLightCB, CBSLOT_RENDERER_VOLUMELIGHT) { float4x4 lightWorld; @@ -731,7 +895,7 @@ CBUFFER(VolumeLightCB, CBSLOT_RENDERER_VOLUMELIGHT) float4 lightEnerdis; }; -CBUFFER(LensFlareCB, CBSLOT_RENDERER_LENSFLARE) +struct LensFlarePush { float3 xLensFlarePos; float xLensFlareOffset; @@ -749,9 +913,61 @@ CBUFFER(CubemapRenderCB, CBSLOT_RENDERER_CUBEMAPRENDER) CubemapRenderCam xCubemapRenderCams[6]; }; -CBUFFER(TessellationCB, CBSLOT_RENDERER_TESSELLATION) +// MIP Generator params: +#define GENERATEMIPCHAIN_1D_BLOCK_SIZE 64 +#define GENERATEMIPCHAIN_2D_BLOCK_SIZE 8 +#define GENERATEMIPCHAIN_3D_BLOCK_SIZE 4 + +struct GenerateMIPChainCB { - float4 xTessellationFactors; + uint3 outputResolution; + uint arrayIndex; + float3 outputResolution_rcp; + uint mipgen_options; +}; +static const uint MIPGEN_OPTION_BIT_PRESERVE_COVERAGE = 1 << 0; + +struct FilterEnvmapCB +{ + uint2 filterResolution; + float2 filterResolution_rcp; + uint filterArrayIndex; + float filterRoughness; + uint filterRayCount; + uint padding_filterCB; +}; + +// CopyTexture2D params: +struct CopyTextureCB +{ + int2 xCopyDest; + int2 xCopySrcSize; + int2 padding0; + int xCopySrcMIP; + int xCopyBorderExpandStyle; +}; + + +static const uint PAINT_TEXTURE_BLOCKSIZE = 8; + +struct PaintTextureCB +{ + uint2 xPaintBrushCenter; + uint xPaintBrushRadius; + float xPaintBrushAmount; + + float xPaintBrushFalloff; + uint xPaintBrushColor; + uint2 padding0; +}; + +CBUFFER(PaintRadiusCB, CBSLOT_RENDERER_MISC) +{ + uint2 xPaintRadResolution; + uint2 xPaintRadCenter; + uint xPaintRadUVSET; + float xPaintRadRadius; + uint2 pad; }; diff --git a/WickedEngine/shaders/ShaderInterop_Skinning.h b/WickedEngine/shaders/ShaderInterop_Skinning.h deleted file mode 100644 index 84c069b46..000000000 --- a/WickedEngine/shaders/ShaderInterop_Skinning.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef WI_SHADERINTEROP_SKINNING_H -#define WI_SHADERINTEROP_SKINNING_H -#include "ShaderInterop.h" - - -// Skinning compute params: -#define SKINNING_COMPUTE_THREADCOUNT 128 - - -#endif // WI_SHADERINTEROP_SKINNING_H diff --git a/WickedEngine/shaders/ShaderInterop_SurfelGI.h b/WickedEngine/shaders/ShaderInterop_SurfelGI.h new file mode 100644 index 000000000..b5772ab29 --- /dev/null +++ b/WickedEngine/shaders/ShaderInterop_SurfelGI.h @@ -0,0 +1,189 @@ +#ifndef WI_SHADERINTEROP_SURFEL_GI_H +#define WI_SHADERINTEROP_SURFEL_GI_H +#include "ShaderInterop.h" +#include "ShaderInterop_Renderer.h" + +struct Surfel +{ + float3 position; + uint normal; + float3 color; + float radius; +}; +struct SurfelData +{ + uint2 primitiveID; + uint bary; + uint uid; + + float3 mean; + uint life; + + float3 shortMean; + float vbbr; + + float3 variance; + float inconsistency; + + float3 hitpos; + uint hitnormal; + + float3 hitenergy; + float padding0; + + float3 traceresult; + float padding1; +}; +static const uint SURFEL_CAPACITY = 250000; +static const uint SQRT_SURFEL_CAPACITY = (uint)ceil(sqrt((float)SURFEL_CAPACITY)); +static const uint SURFEL_MOMENT_TEXELS = 4 + 2; +static const uint SURFEL_MOMENT_ATLAS_TEXELS = SQRT_SURFEL_CAPACITY * SURFEL_MOMENT_TEXELS; +static const uint3 SURFEL_GRID_DIMENSIONS = uint3(128, 64, 128); +static const uint SURFEL_TABLE_SIZE = SURFEL_GRID_DIMENSIONS.x * SURFEL_GRID_DIMENSIONS.y * SURFEL_GRID_DIMENSIONS.z; +static const float SURFEL_MAX_RADIUS = 1; +struct SurfelGridCell +{ + uint count; + uint offset; +}; +static const uint SURFEL_STATS_OFFSET_COUNT = 0; +static const uint SURFEL_STATS_OFFSET_CELLALLOCATOR = 4; +static const uint SURFEL_STATS_OFFSET_INDIRECT = 8; +static const uint SURFEL_INDIRECT_NUMTHREADS = 32; +static const float SURFEL_TARGET_COVERAGE = 0.5; // how many surfels should affect a pixel fully, higher values will increase quality and cost +static const uint SURFEL_CELL_LIMIT = ~0; // limit the amount of allocated surfels in a cell +#define SURFEL_COVERAGE_HALFRES // runs the coverage shader in half resolution for improved performance +#define SURFEL_GRID_CULLING // if defined, surfels will not be added to grid cells that they do not intersect +#define SURFEL_USE_HASHING // if defined, hashing will be used to retrieve surfels, hashing is good because it supports infinite world trivially, but slower due to hash collisions + +#ifndef __cplusplus +inline int3 surfel_cell(float3 position) +{ +#ifdef SURFEL_USE_HASHING + return floor(position / SURFEL_MAX_RADIUS); +#else + return floor((position - floor(g_xCamera.CamPos)) / SURFEL_MAX_RADIUS) + SURFEL_GRID_DIMENSIONS / 2; +#endif // SURFEL_USE_HASHING +} +float3 surfel_griduv(float3 position) +{ +#ifdef SURFEL_USE_HASHING + return 0; // hashed grid can't be sampled for colors, it doesn't make sense +#else + return (((position - floor(g_xCamera.CamPos)) / SURFEL_MAX_RADIUS) + SURFEL_GRID_DIMENSIONS / 2) / SURFEL_GRID_DIMENSIONS; +#endif // SURFEL_USE_HASHING +} +inline uint surfel_cellindex(int3 cell) +{ +#ifdef SURFEL_USE_HASHING + const uint p1 = 73856093; // some large primes + const uint p2 = 19349663; + const uint p3 = 83492791; + int n = p1 * cell.x ^ p2 * cell.y ^ p3 * cell.z; + n %= SURFEL_TABLE_SIZE; + return n; +#else + return flatten3D(cell, SURFEL_GRID_DIMENSIONS); +#endif // SURFEL_USE_HASHING +} +inline bool surfel_cellvalid(int3 cell) +{ +#ifdef SURFEL_USE_HASHING + return true; +#else + if (cell.x < 0 || cell.x >= SURFEL_GRID_DIMENSIONS.x) + return false; + if (cell.y < 0 || cell.y >= SURFEL_GRID_DIMENSIONS.y) + return false; + if (cell.z < 0 || cell.z >= SURFEL_GRID_DIMENSIONS.z) + return false; + return true; +#endif // SURFEL_USE_HASHING +} +inline bool surfel_cellintersects(Surfel surfel, int3 cell) +{ + if (!surfel_cellvalid(cell)) + return false; + +#ifdef SURFEL_GRID_CULLING +#ifdef SURFEL_USE_HASHING + float3 gridmin = cell * SURFEL_MAX_RADIUS; + float3 gridmax = (cell + 1) * SURFEL_MAX_RADIUS; +#else + float3 gridmin = cell - SURFEL_GRID_DIMENSIONS / 2 * SURFEL_MAX_RADIUS + floor(g_xCamera.CamPos); + float3 gridmax = (cell + 1) - SURFEL_GRID_DIMENSIONS / 2 * SURFEL_MAX_RADIUS + floor(g_xCamera.CamPos); +#endif // SURFEL_USE_HASHING + + float3 closestPointInAabb = min(max(surfel.position, gridmin), gridmax); + float dist = distance(closestPointInAabb, surfel.position); + if (dist < surfel.radius) + return true; + return false; +#else + return true; +#endif // SURFEL_GRID_CULLING +} +// 27 neighbor offsets in a 3D grid, including center cell: +static const int3 surfel_neighbor_offsets[27] = { + int3(-1, -1, -1), + int3(-1, -1, 0), + int3(-1, -1, 1), + int3(-1, 0, -1), + int3(-1, 0, 0), + int3(-1, 0, 1), + int3(-1, 1, -1), + int3(-1, 1, 0), + int3(-1, 1, 1), + int3(0, -1, -1), + int3(0, -1, 0), + int3(0, -1, 1), + int3(0, 0, -1), + int3(0, 0, 0), + int3(0, 0, 1), + int3(0, 1, -1), + int3(0, 1, 0), + int3(0, 1, 1), + int3(1, -1, -1), + int3(1, -1, 0), + int3(1, -1, 1), + int3(1, 0, -1), + int3(1, 0, 0), + int3(1, 0, 1), + int3(1, 1, -1), + int3(1, 1, 0), + int3(1, 1, 1), +}; + +inline float2 encode(in float3 N) +{ + return float2(atan2(N.y, N.x) / PI, N.z) * 0.5 + 0.5; +} +float2 surfel_moment_pixel(uint surfel_index, float3 normal, float3 direction) +{ + uint2 moments_pixel = unflatten2D(surfel_index, SQRT_SURFEL_CAPACITY) * SURFEL_MOMENT_TEXELS; + float3 hemi = mul(direction, transpose(GetTangentSpace(normal))); + hemi.z = abs(hemi.z); + hemi = normalize(hemi); + float2 moments_uv = encode_hemioct(hemi) * 0.5 + 0.5; + //float2 moments_uv = hemi.xy * 0.5 + 0.5; + return moments_pixel + 1 + moments_uv * (SURFEL_MOMENT_TEXELS - 2); +} +float2 surfel_moment_uv(uint surfel_index, float3 normal, float3 direction) +{ + return surfel_moment_pixel(surfel_index, normal, direction) / SURFEL_MOMENT_ATLAS_TEXELS; +} +float surfel_moment_weight(float2 moments, float dist) +{ + float mean = moments.x; + float mean2 = moments.y; + if (dist > mean) + { + // Chebishev weight + float variance = abs(sqr(mean) - mean2); + return variance / (variance + sqr(dist - mean)); + } + return 1; +} +#endif // __cplusplus + +#endif // WI_SHADERINTEROP_SURFEL_GI_H diff --git a/WickedEngine/shaders/ShaderInterop_Utility.h b/WickedEngine/shaders/ShaderInterop_Utility.h deleted file mode 100644 index 2b86bc521..000000000 --- a/WickedEngine/shaders/ShaderInterop_Utility.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef WI_SHADERINTEROP_UTILITY_H -#define WI_SHADERINTEROP_UTILITY_H -#include "ShaderInterop.h" - -// MIP Generator params: -#define GENERATEMIPCHAIN_1D_BLOCK_SIZE 64 -#define GENERATEMIPCHAIN_2D_BLOCK_SIZE 8 -#define GENERATEMIPCHAIN_3D_BLOCK_SIZE 4 - -CBUFFER(GenerateMIPChainCB, CBSLOT_RENDERER_UTILITY) -{ - uint3 outputResolution; - uint arrayIndex; - float3 outputResolution_rcp; - uint mipgen_options; -}; -static const uint MIPGEN_OPTION_BIT_PRESERVE_COVERAGE = 1 << 0; - -CBUFFER(FilterEnvmapCB, CBSLOT_RENDERER_UTILITY) -{ - uint2 filterResolution; - float2 filterResolution_rcp; - uint filterArrayIndex; - float filterRoughness; - uint filterRayCount; - uint padding_filterCB; -}; - - - -// CopyTexture2D params: -CBUFFER(CopyTextureCB, CBSLOT_RENDERER_UTILITY) -{ - int2 xCopyDest; - int2 xCopySrcSize; - int2 padding0; - int xCopySrcMIP; - int xCopyBorderExpandStyle; -}; - -#endif // WI_SHADERINTEROP_UTILITY_H diff --git a/WickedEngine/shaders/Shaders_SOURCE.vcxitems b/WickedEngine/shaders/Shaders_SOURCE.vcxitems index 65d1836da..49350c6c1 100644 --- a/WickedEngine/shaders/Shaders_SOURCE.vcxitems +++ b/WickedEngine/shaders/Shaders_SOURCE.vcxitems @@ -977,15 +977,41 @@ Compute Compute - - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel + + Compute + 4.0 + + + Compute + 4.0 + + + Compute + 4.0 + + + Compute + 4.0 + + + Compute + 4.0 + + + Compute + 4.0 + + + Compute + 4.0 + + + Compute + 4.0 + + + Compute + 4.0 Compute @@ -1028,6 +1054,14 @@ Compute Compute + + Compute + 4.0 + + + Compute + 4.0 + Vertex @@ -1684,56 +1718,6 @@ Pixel Pixel - - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - - - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - - - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - - - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - - - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - Pixel - Vertex Vertex @@ -1876,16 +1860,6 @@ Pixel Pixel - - Compute - Compute - Compute - Compute - Compute - Compute - Compute - Compute - Compute Compute @@ -2536,16 +2510,6 @@ Compute Compute - - Compute - Compute - Compute - Compute - Compute - Compute - Compute - Compute - Pixel Pixel @@ -2880,11 +2844,9 @@ - - - + \ No newline at end of file diff --git a/WickedEngine/shaders/Shaders_SOURCE.vcxitems.filters b/WickedEngine/shaders/Shaders_SOURCE.vcxitems.filters index 694147d47..48b7188d4 100644 --- a/WickedEngine/shaders/Shaders_SOURCE.vcxitems.filters +++ b/WickedEngine/shaders/Shaders_SOURCE.vcxitems.filters @@ -236,9 +236,6 @@ CS - - CS - CS @@ -302,9 +299,6 @@ CS - - CS - CS @@ -500,21 +494,6 @@ PS - - PS - - - PS - - - PS - - - PS - - - PS - PS @@ -896,9 +875,6 @@ PS - - PS - VS @@ -995,6 +971,39 @@ CS + + CS + + + CS + + + CS + + + CS + + + CS + + + CS + + + CS + + + CS + + + CS + + + CS + + + CS + @@ -1033,9 +1042,6 @@ interop - - interop - interop @@ -1045,10 +1051,7 @@ interop - - interop - - + interop diff --git a/WickedEngine/shaders/blur_gaussian_float4CS.hlsl b/WickedEngine/shaders/blur_gaussian_float4CS.hlsl index 407d50da8..8a820ecff 100644 --- a/WickedEngine/shaders/blur_gaussian_float4CS.hlsl +++ b/WickedEngine/shaders/blur_gaussian_float4CS.hlsl @@ -165,7 +165,7 @@ void main(uint3 Gid : SV_GroupID, uint groupIndex : SV_GroupIndex) const BLUR_FORMAT color2 = color_cache[sam]; #ifdef BILATERAL const float depth = depth_cache[sam]; - const float weight = saturate(abs(depth - center_depth) * g_xCamera_ZFarP * depth_threshold); + const float weight = saturate(abs(depth - center_depth) * g_xCamera.ZFarP * depth_threshold); color += lerp(color2, center_color, weight) * gaussianWeightsNormalized[i]; #else color += color2 * gaussianWeightsNormalized[i]; diff --git a/WickedEngine/shaders/brdf.hlsli b/WickedEngine/shaders/brdf.hlsli index 9f0c69052..dbd024997 100644 --- a/WickedEngine/shaders/brdf.hlsli +++ b/WickedEngine/shaders/brdf.hlsli @@ -202,10 +202,22 @@ struct Surface { init(); - opacity = baseColor.a; + if (material.options & SHADERMATERIAL_OPTION_BIT_TRANSPARENT || material.alphaTest > 0) + { + opacity = baseColor.a; + } + else + { + opacity = 1; + } roughness = material.roughness; f0 = material.specularColor.rgb * specularMap.rgb * specularMap.a * material.specularColor.a; + if (g_xFrame.Options & OPTION_BIT_FORCE_DIFFUSE_LIGHTING) + { + f0 = material.metalness = material.reflectance = 0; + } + [branch] if (material.IsUsingSpecularGlossinessWorkflow()) { @@ -267,6 +279,217 @@ struct Surface } inline bool IsReceiveShadow() { return receiveshadow; } + + + ShaderMeshInstance inst; + ShaderMesh mesh; + ShaderMeshSubset subset; + ShaderMaterial material; + float2 bary; + float3 pre; + + bool load(in PrimitiveID prim, in float2 barycentrics, in uint uid = 0) + { + inst = load_instance(prim.instanceIndex); + if (uid != 0 && inst.uid != uid) + return false; + + mesh = load_mesh(inst.meshIndex); + if (mesh.vb_pos_nor_wind < 0) + return false; + + subset = load_subset(mesh, prim.subsetIndex); + material = load_material(subset.materialIndex); + bary = barycentrics; + + uint startIndex = prim.primitiveIndex * 3 + subset.indexOffset; + uint i0 = bindless_ib[NonUniformResourceIndex(mesh.ib)][startIndex + 0]; + uint i1 = bindless_ib[NonUniformResourceIndex(mesh.ib)][startIndex + 1]; + uint i2 = bindless_ib[NonUniformResourceIndex(mesh.ib)][startIndex + 2]; + + uint4 data0 = bindless_buffers[NonUniformResourceIndex(mesh.vb_pos_nor_wind)].Load4(i0 * 16); + uint4 data1 = bindless_buffers[NonUniformResourceIndex(mesh.vb_pos_nor_wind)].Load4(i1 * 16); + uint4 data2 = bindless_buffers[NonUniformResourceIndex(mesh.vb_pos_nor_wind)].Load4(i2 * 16); + float3 p0 = asfloat(data0.xyz); + float3 p1 = asfloat(data1.xyz); + float3 p2 = asfloat(data2.xyz); + float3 n0 = unpack_unitvector(data0.w); + float3 n1 = unpack_unitvector(data1.w); + float3 n2 = unpack_unitvector(data2.w); + + float u = barycentrics.x; + float v = barycentrics.y; + float w = 1 - u - v; + + P = p0 * w + p1 * u + p2 * v; + P = mul(inst.transform.GetMatrix(), float4(P, 1)).xyz; + V = normalize(g_xCamera.CamPos - P); + + float4 uv0 = 0, uv1 = 0, uv2 = 0; + [branch] + if (mesh.vb_uv0 >= 0) + { + uv0.xy = unpack_half2(bindless_buffers[NonUniformResourceIndex(mesh.vb_uv0)].Load(i0 * 4)); + uv1.xy = unpack_half2(bindless_buffers[NonUniformResourceIndex(mesh.vb_uv0)].Load(i1 * 4)); + uv2.xy = unpack_half2(bindless_buffers[NonUniformResourceIndex(mesh.vb_uv0)].Load(i2 * 4)); + } + [branch] + if (mesh.vb_uv1 >= 0) + { + uv0.zw = unpack_half2(bindless_buffers[NonUniformResourceIndex(mesh.vb_uv1)].Load(i0 * 4)); + uv1.zw = unpack_half2(bindless_buffers[NonUniformResourceIndex(mesh.vb_uv1)].Load(i1 * 4)); + uv2.zw = unpack_half2(bindless_buffers[NonUniformResourceIndex(mesh.vb_uv1)].Load(i2 * 4)); + } + float4 uvsets = uv0 * w + uv1 * u + uv2 * v; + uvsets.xy = uvsets.xy * material.texMulAdd.xy + material.texMulAdd.zw; + + float4 baseColor = material.baseColor; + [branch] + if (material.texture_basecolormap_index >= 0) + { + const float2 UV_baseColorMap = material.uvset_baseColorMap == 0 ? uvsets.xy : uvsets.zw; + float4 baseColorMap = bindless_textures[NonUniformResourceIndex(material.texture_basecolormap_index)].SampleLevel(sampler_linear_wrap, UV_baseColorMap, 0); + if ((g_xFrame.Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) + { + baseColorMap.rgb *= DEGAMMA(baseColorMap.rgb); + baseColor *= baseColorMap; + } + else + { + baseColor.a *= baseColorMap.a; + } + } + + [branch] + if (mesh.vb_col >= 0 && material.IsUsingVertexColors()) + { + float4 c0, c1, c2; + const uint stride_COL = 4; + c0 = unpack_rgba(bindless_buffers[NonUniformResourceIndex(mesh.vb_col)].Load(i0 * stride_COL)); + c1 = unpack_rgba(bindless_buffers[NonUniformResourceIndex(mesh.vb_col)].Load(i1 * stride_COL)); + c2 = unpack_rgba(bindless_buffers[NonUniformResourceIndex(mesh.vb_col)].Load(i2 * stride_COL)); + float4 vertexColor = c0 * w + c1 * u + c2 * v; + baseColor *= vertexColor; + } + + float4 surfaceMap = 1; + [branch] + if (material.texture_surfacemap_index >= 0) + { + const float2 UV_surfaceMap = material.uvset_surfaceMap == 0 ? uvsets.xy : uvsets.zw; + surfaceMap = bindless_textures[NonUniformResourceIndex(material.texture_surfacemap_index)].SampleLevel(sampler_linear_wrap, UV_surfaceMap, 0); + } + + float4 specularMap = 1; + [branch] + if (material.texture_specularmap_index >= 0) + { + const float2 UV_specularMap = material.uvset_specularMap == 0 ? uvsets.xy : uvsets.zw; + specularMap = bindless_textures[NonUniformResourceIndex(material.texture_specularmap_index)].SampleLevel(sampler_linear_wrap, UV_specularMap, 0); + specularMap.rgb = DEGAMMA(specularMap.rgb); + } + + create(material, baseColor, surfaceMap, specularMap); + + emissiveColor = material.emissiveColor; + [branch] + if (material.texture_emissivemap_index >= 0) + { + const float2 UV_emissiveMap = material.uvset_emissiveMap == 0 ? uvsets.xy : uvsets.zw; + float4 emissiveMap = bindless_textures[NonUniformResourceIndex(material.texture_emissivemap_index)].SampleLevel(sampler_linear_wrap, UV_emissiveMap, 0); + emissiveMap.rgb = DEGAMMA(emissiveMap.rgb); + emissiveColor *= emissiveMap; + } + + transmission = material.transmission; + if (material.texture_transmissionmap_index >= 0) + { + const float2 UV_transmissionMap = material.uvset_transmissionMap == 0 ? uvsets.xy : uvsets.zw; + float transmissionMap = bindless_textures[NonUniformResourceIndex(material.texture_transmissionmap_index)].SampleLevel(sampler_linear_wrap, UV_transmissionMap, 0).r; + transmission *= transmissionMap; + } + + [branch] + if (material.IsOcclusionEnabled_Secondary() && material.texture_occlusionmap_index >= 0) + { + const float2 UV_occlusionMap = material.uvset_occlusionMap == 0 ? uvsets.xy : uvsets.zw; + occlusion *= bindless_textures[NonUniformResourceIndex(material.texture_occlusionmap_index)].SampleLevel(sampler_linear_wrap, UV_occlusionMap, 0).r; + } + + N = n0 * w + n1 * u + n2 * v; + N = mul((float3x3)inst.transformInverseTranspose.GetMatrix(), N); + N = normalize(N); + facenormal = N; + + [branch] + if (mesh.vb_tan >= 0 && material.texture_normalmap_index >= 0 && material.normalMapStrength > 0) + { + float4 t0, t1, t2; + const uint stride_TAN = 4; + t0 = unpack_utangent(bindless_buffers[NonUniformResourceIndex(mesh.vb_tan)].Load(i0 * stride_TAN)); + t1 = unpack_utangent(bindless_buffers[NonUniformResourceIndex(mesh.vb_tan)].Load(i1 * stride_TAN)); + t2 = unpack_utangent(bindless_buffers[NonUniformResourceIndex(mesh.vb_tan)].Load(i2 * stride_TAN)); + float4 T = t0 * w + t1 * u + t2 * v; + T = T * 2 - 1; + T.xyz = mul((float3x3)inst.transformInverseTranspose.GetMatrix(), T.xyz); + T.xyz = normalize(T.xyz); + float3 B = normalize(cross(T.xyz, N) * T.w); + float3x3 TBN = float3x3(T.xyz, B, N); + + const float2 UV_normalMap = material.uvset_normalMap == 0 ? uvsets.xy : uvsets.zw; + float3 normalMap = bindless_textures[NonUniformResourceIndex(material.texture_normalmap_index)].SampleLevel(sampler_linear_wrap, UV_normalMap, 0).rgb; + normalMap.b = normalMap.b == 0 ? 1 : normalMap.b; // fix for missing blue channel + normalMap = normalMap * 2 - 1; + N = normalize(lerp(N, mul(normalMap, TBN), material.normalMapStrength)); + } + + [branch] + if (mesh.vb_pre >= 0) + { + p0 = asfloat(bindless_buffers[mesh.vb_pre].Load3(i0 * 16)); + p1 = asfloat(bindless_buffers[mesh.vb_pre].Load3(i1 * 16)); + p2 = asfloat(bindless_buffers[mesh.vb_pre].Load3(i2 * 16)); + } + pre = p0 * w + p1 * u + p2 * v; + pre = mul(inst.transformPrev.GetMatrix(), float4(pre, 1)).xyz; + + update(); + + return true; + } + + bool load(in PrimitiveID prim, in float3 P, in uint uid = 0) + { + inst = load_instance(prim.instanceIndex); + if (uid != 0 && inst.uid != uid) + return false; + + mesh = load_mesh(inst.meshIndex); + if (mesh.vb_pos_nor_wind < 0) + return false; + + subset = load_subset(mesh, prim.subsetIndex); + material = load_material(subset.materialIndex); + + uint startIndex = prim.primitiveIndex * 3 + subset.indexOffset; + uint i0 = bindless_ib[NonUniformResourceIndex(mesh.ib)][startIndex + 0]; + uint i1 = bindless_ib[NonUniformResourceIndex(mesh.ib)][startIndex + 1]; + uint i2 = bindless_ib[NonUniformResourceIndex(mesh.ib)][startIndex + 2]; + + uint4 data0 = bindless_buffers[NonUniformResourceIndex(mesh.vb_pos_nor_wind)].Load4(i0 * 16); + uint4 data1 = bindless_buffers[NonUniformResourceIndex(mesh.vb_pos_nor_wind)].Load4(i1 * 16); + uint4 data2 = bindless_buffers[NonUniformResourceIndex(mesh.vb_pos_nor_wind)].Load4(i2 * 16); + float3 p0 = asfloat(data0.xyz); + float3 p1 = asfloat(data1.xyz); + float3 p2 = asfloat(data2.xyz); + float3 P0 = mul(inst.transform.GetMatrix(), float4(p0, 1)).xyz; + float3 P1 = mul(inst.transform.GetMatrix(), float4(p1, 1)).xyz; + float3 P2 = mul(inst.transform.GetMatrix(), float4(p2, 1)).xyz; + + float2 barycentrics = compute_barycentrics(P, P0, P1, P2); + + return load(prim, barycentrics, uid); + } }; struct SurfaceToLight diff --git a/WickedEngine/shaders/bvh_primitivesCS.hlsl b/WickedEngine/shaders/bvh_primitivesCS.hlsl index e7f103e48..09571aec1 100644 --- a/WickedEngine/shaders/bvh_primitivesCS.hlsl +++ b/WickedEngine/shaders/bvh_primitivesCS.hlsl @@ -2,150 +2,81 @@ #include "ShaderInterop_BVH.h" // This shader builds scene triangle data and performs BVH classification: -// - This shader is run per object. +// - This shader is run per object subset. // - Each thread processes a triangle // - Computes triangle bounding box, morton code and other properties and stores into global primitive buffer -STRUCTUREDBUFFER(materialBuffer, ShaderMaterial, TEXSLOT_ONDEMAND0); -TYPEDBUFFER(meshIndexBuffer, uint, TEXSLOT_ONDEMAND1); -RAWBUFFER(meshVertexBuffer_POS, TEXSLOT_ONDEMAND2); -RAWBUFFER(meshVertexBuffer_UV0, TEXSLOT_ONDEMAND3); -RAWBUFFER(meshVertexBuffer_UV1, TEXSLOT_ONDEMAND4); -RAWBUFFER(meshVertexBuffer_COL, TEXSLOT_ONDEMAND5); -TYPEDBUFFER(meshVertexBuffer_SUB, uint, TEXSLOT_ONDEMAND6); +PUSHCONSTANT(push, BVHPushConstants); RWSTRUCTUREDBUFFER(primitiveIDBuffer, uint, 0); RWSTRUCTUREDBUFFER(primitiveBuffer, BVHPrimitive, 1); -RWSTRUCTUREDBUFFER(primitiveDataBuffer, BVHPrimitiveData, 2); -RWSTRUCTUREDBUFFER(primitiveMortonBuffer, float, 3); // morton buffer is float because sorting is written for floats! - +RWSTRUCTUREDBUFFER(primitiveMortonBuffer, float, 2); // morton buffer is float because sorting is written for floats! [numthreads(BVH_BUILDER_GROUPSIZE, 1, 1)] void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) { - const uint tri = DTid.x; - const uint primitiveID = xBVHMeshTriangleOffset + tri; - const bool activeThread = tri < xBVHMeshTriangleCount; + if (DTid.x >= push.primitiveCount) + return; - if (activeThread) + PrimitiveID prim; + prim.primitiveIndex = DTid.x; + prim.instanceIndex = push.instanceIndex; + prim.subsetIndex = push.subsetIndex; + + ShaderMeshInstance inst = load_instance(prim.instanceIndex); + ShaderMesh mesh = load_mesh(inst.meshIndex); + ShaderMeshSubset subset = load_subset(mesh, prim.subsetIndex); + ShaderMaterial material = load_material(subset.materialIndex); + + uint startIndex = prim.primitiveIndex * 3 + subset.indexOffset; + uint i0 = bindless_ib[mesh.ib][startIndex + 0]; + uint i1 = bindless_ib[mesh.ib][startIndex + 1]; + uint i2 = bindless_ib[mesh.ib][startIndex + 2]; + + uint4 data0 = bindless_buffers[mesh.vb_pos_nor_wind].Load4(i0 * 16); + uint4 data1 = bindless_buffers[mesh.vb_pos_nor_wind].Load4(i1 * 16); + uint4 data2 = bindless_buffers[mesh.vb_pos_nor_wind].Load4(i2 * 16); + float3 p0 = asfloat(data0.xyz); + float3 p1 = asfloat(data1.xyz); + float3 p2 = asfloat(data2.xyz); + float3 P0 = mul(inst.transform.GetMatrix(), float4(p0, 1)).xyz; + float3 P1 = mul(inst.transform.GetMatrix(), float4(p1, 1)).xyz; + float3 P2 = mul(inst.transform.GetMatrix(), float4(p2, 1)).xyz; + + BVHPrimitive bvhprim; + bvhprim.packed_prim = prim.pack(); + bvhprim.flags = 0; + if (mesh.flags & SHADERMESH_FLAG_DOUBLE_SIDED) { - // load indices of triangle from index buffer - uint i0 = meshIndexBuffer[tri * 3 + 0]; - uint i1 = meshIndexBuffer[tri * 3 + 2]; - uint i2 = meshIndexBuffer[tri * 3 + 1]; - - // load vertices of triangle from vertex buffer: - float4 pos_nor0 = asfloat(meshVertexBuffer_POS.Load4(i0 * xBVHMeshVertexPOSStride)); - float4 pos_nor1 = asfloat(meshVertexBuffer_POS.Load4(i1 * xBVHMeshVertexPOSStride)); - float4 pos_nor2 = asfloat(meshVertexBuffer_POS.Load4(i2 * xBVHMeshVertexPOSStride)); - - uint nor_u = asuint(pos_nor0.w); - float3 nor0 = unpack_unitvector(nor_u); - uint subsetIndex = meshVertexBuffer_SUB[i0]; - - nor_u = asuint(pos_nor1.w); - float3 nor1 = unpack_unitvector(nor_u); - - nor_u = asuint(pos_nor2.w); - float3 nor2 = unpack_unitvector(nor_u); - - - // Compute triangle parameters: - float4x4 WORLD = xBVHWorld; - const uint materialIndex = xBVHMaterialOffset + subsetIndex; - ShaderMaterial material = materialBuffer[materialIndex]; - - float3 v0 = mul(WORLD, float4(pos_nor0.xyz, 1)).xyz; - float3 v1 = mul(WORLD, float4(pos_nor1.xyz, 1)).xyz; - float3 v2 = mul(WORLD, float4(pos_nor2.xyz, 1)).xyz; - nor0 = normalize(mul((float3x3)WORLD, nor0)); - nor1 = normalize(mul((float3x3)WORLD, nor1)); - nor2 = normalize(mul((float3x3)WORLD, nor2)); - float4 u0 = float4(unpack_half2(meshVertexBuffer_UV0.Load(i0 * 4)) * material.texMulAdd.xy + material.texMulAdd.zw, unpack_half2(meshVertexBuffer_UV1.Load(i0 * 4))); - float4 u1 = float4(unpack_half2(meshVertexBuffer_UV0.Load(i1 * 4)) * material.texMulAdd.xy + material.texMulAdd.zw, unpack_half2(meshVertexBuffer_UV1.Load(i1 * 4))); - float4 u2 = float4(unpack_half2(meshVertexBuffer_UV0.Load(i2 * 4)) * material.texMulAdd.xy + material.texMulAdd.zw, unpack_half2(meshVertexBuffer_UV1.Load(i2 * 4))); - - const float4 color = xBVHInstanceColor * material.baseColor; - float4 c0 = color; - float4 c1 = color; - float4 c2 = color; - - [branch] - if (material.IsUsingVertexColors()) - { - c0 *= unpack_rgba(meshVertexBuffer_COL.Load(i0 * 4)); - c1 *= unpack_rgba(meshVertexBuffer_COL.Load(i1 * 4)); - c2 *= unpack_rgba(meshVertexBuffer_COL.Load(i2 * 4)); - } - - // Compute tangent vectors: - float4 tangent; - float3 binormal; - { - const float3 facenormal = normalize(nor0 + nor1 + nor2); - - const float x1 = v1.x - v0.x; - const float x2 = v2.x - v0.x; - const float y1 = v1.y - v0.y; - const float y2 = v2.y - v0.y; - const float z1 = v1.z - v0.z; - const float z2 = v2.z - v0.z; - - const float s1 = u1.x - u0.x; - const float s2 = u2.x - u0.x; - const float t1 = u1.y - u0.y; - const float t2 = u2.y - u0.y; - - const float r = 1.0f / (s1 * t2 - s2 * t1); - const float3 sdir = float3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, - (t2 * z1 - t1 * z2) * r); - const float3 tdir = float3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, - (s1 * z2 - s2 * z1) * r); - - tangent.xyz = normalize(sdir - facenormal * dot(facenormal, sdir)); - tangent.w = (dot(cross(tangent.xyz, facenormal), tdir) < 0.0f) ? -1.0f : 1.0f; - - binormal = normalize(cross(tangent.xyz, facenormal) * tangent.w); - } - - // Pack primitive: - BVHPrimitive prim; - prim.x0 = v0.x; - prim.y0 = v0.y; - prim.z0 = v0.z; - prim.x1 = v1.x; - prim.y1 = v1.y; - prim.z1 = v1.z; - prim.x2 = v2.x; - prim.y2 = v2.y; - prim.z2 = v2.z; - prim.n0 = pack_unitvector(nor0); - prim.n1 = pack_unitvector(nor1); - prim.n2 = pack_unitvector(nor2); - - BVHPrimitiveData primdata; - primdata.u0 = pack_half4(u0); - primdata.u1 = pack_half4(u1); - primdata.u2 = pack_half4(u2); - primdata.c0 = pack_rgba(c0); - primdata.c1 = pack_rgba(c1); - primdata.c2 = pack_rgba(c2); - primdata.tangent = pack_unitvector(tangent.xyz); - primdata.binormal = pack_unitvector(binormal); - primdata.materialIndex = materialIndex; - - // Store primitive: - primitiveBuffer[primitiveID] = prim; - primitiveDataBuffer[primitiveID] = primdata; - - primitiveIDBuffer[primitiveID] = primitiveID; // will be sorted by morton so we need this! - - - // Compute triangle morton code: - float3 minAABB = min(v0, min(v1, v2)); - float3 maxAABB = max(v0, max(v1, v2)); - float3 centerAABB = (minAABB + maxAABB) * 0.5f; - const uint mortoncode = morton3D((centerAABB - g_xFrame_WorldBoundsMin) * g_xFrame_WorldBoundsExtents_rcp); - primitiveMortonBuffer[primitiveID] = (float)mortoncode; // convert to float before sorting + bvhprim.flags |= BVH_PRIMITIVE_FLAG_DOUBLE_SIDED; } + if (material.options & SHADERMATERIAL_OPTION_BIT_DOUBLE_SIDED) + { + bvhprim.flags |= BVH_PRIMITIVE_FLAG_DOUBLE_SIDED; + } + if (material.options & SHADERMATERIAL_OPTION_BIT_TRANSPARENT || material.alphaTest > 0) + { + bvhprim.flags |= BVH_PRIMITIVE_FLAG_TRANSPARENT; + } + bvhprim.x0 = P0.x; + bvhprim.y0 = P0.y; + bvhprim.z0 = P0.z; + bvhprim.x1 = P1.x; + bvhprim.y1 = P1.y; + bvhprim.z1 = P1.z; + bvhprim.x2 = P2.x; + bvhprim.y2 = P2.y; + bvhprim.z2 = P2.z; + + uint primitiveID = push.primitiveOffset + prim.primitiveIndex; + primitiveBuffer[primitiveID] = bvhprim; + primitiveIDBuffer[primitiveID] = primitiveID; // will be sorted by morton so we need this! + + // Compute triangle morton code: + float3 minAABB = min(P0, min(P1, P2)); + float3 maxAABB = max(P0, max(P1, P2)); + float3 centerAABB = (minAABB + maxAABB) * 0.5f; + const uint mortoncode = morton3D((centerAABB - g_xFrame.WorldBoundsMin) * g_xFrame.WorldBoundsExtents_rcp); + primitiveMortonBuffer[primitiveID] = (float)mortoncode; // convert to float before sorting + } diff --git a/WickedEngine/shaders/copytexture2D_float4CS.hlsl b/WickedEngine/shaders/copytexture2D_float4CS.hlsl index 282c01d0d..5f54aa08a 100644 --- a/WickedEngine/shaders/copytexture2D_float4CS.hlsl +++ b/WickedEngine/shaders/copytexture2D_float4CS.hlsl @@ -1,10 +1,12 @@ #include "globals.hlsli" -#include "ShaderInterop_Utility.h" +#include "ShaderInterop_Renderer.h" #ifndef COPY_OUTPUT_FORMAT #define COPY_OUTPUT_FORMAT float4 #endif // COPY_OUTPUT_FORMAT +PUSHCONSTANT(push, CopyTextureCB); + TEXTURE2D(input, float4, TEXSLOT_ONDEMAND0); RWTEXTURE2D(output, COPY_OUTPUT_FORMAT, 0); @@ -12,13 +14,13 @@ RWTEXTURE2D(output, COPY_OUTPUT_FORMAT, 0); [numthreads(8, 8, 1)] void main(int3 DTid : SV_DispatchThreadID) { - if (DTid.x >= xCopySrcSize.x || DTid.y >= xCopySrcSize.y) + if (DTid.x >= push.xCopySrcSize.x || DTid.y >= push.xCopySrcSize.y) { return; } const int2 readcoord = DTid.xy; - const int2 writecoord = DTid.xy + xCopyDest; + const int2 writecoord = DTid.xy + push.xCopyDest; - output[writecoord] = input.Load(int3(readcoord, xCopySrcMIP)); + output[writecoord] = input.Load(int3(readcoord, push.xCopySrcMIP)); } diff --git a/WickedEngine/shaders/copytexture2D_float4_borderexpandCS.hlsl b/WickedEngine/shaders/copytexture2D_float4_borderexpandCS.hlsl index 6650a3c54..850ee8663 100644 --- a/WickedEngine/shaders/copytexture2D_float4_borderexpandCS.hlsl +++ b/WickedEngine/shaders/copytexture2D_float4_borderexpandCS.hlsl @@ -1,10 +1,12 @@ #include "globals.hlsli" -#include "ShaderInterop_Utility.h" +#include "ShaderInterop_Renderer.h" #ifndef COPY_OUTPUT_FORMAT #define COPY_OUTPUT_FORMAT float4 #endif // COPY_OUTPUT_FORMAT +PUSHCONSTANT(push, CopyTextureCB); + TEXTURE2D(input, float4, TEXSLOT_ONDEMAND0); RWTEXTURE2D(output, COPY_OUTPUT_FORMAT, 0); @@ -12,79 +14,79 @@ RWTEXTURE2D(output, COPY_OUTPUT_FORMAT, 0); [numthreads(8, 8, 1)] void main(int3 DTid : SV_DispatchThreadID) { - if (DTid.x >= xCopySrcSize.x || DTid.y >= xCopySrcSize.y) + if (DTid.x >= push.xCopySrcSize.x || DTid.y >= push.xCopySrcSize.y) { return; } const int2 readcoord = DTid.xy; - const int2 writecoord = DTid.xy + xCopyDest; + const int2 writecoord = DTid.xy + push.xCopyDest; - output[writecoord] = input.Load(int3(readcoord, xCopySrcMIP)); + output[writecoord] = input.Load(int3(readcoord, push.xCopySrcMIP)); // border expansion: - const bool wrap = xCopyBorderExpandStyle == 1; + const bool wrap = push.xCopyBorderExpandStyle == 1; int2 readoffset; // left if (readcoord.x == 0) { - readoffset = wrap ? int2(xCopySrcSize.x - 1, 0) : 0; + readoffset = wrap ? int2(push.xCopySrcSize.x - 1, 0) : 0; - output[writecoord + int2(-1, 0)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP)); + output[writecoord + int2(-1, 0)] = input.Load(int3(readcoord + readoffset, push.xCopySrcMIP)); // top left if (readcoord.y == 0) { - readoffset = wrap ? int2(xCopySrcSize.x - 1, xCopySrcSize.x - 1) : 0; + readoffset = wrap ? int2(push.xCopySrcSize.x - 1, push.xCopySrcSize.x - 1) : 0; - output[writecoord + int2(-1, -1)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP)); + output[writecoord + int2(-1, -1)] = input.Load(int3(readcoord + readoffset, push.xCopySrcMIP)); } } // right - if (readcoord.x == xCopySrcSize.x - 1) + if (readcoord.x == push.xCopySrcSize.x - 1) { - readoffset = wrap ? int2(-xCopySrcSize.x + 1, 0) : 0; + readoffset = wrap ? int2(-push.xCopySrcSize.x + 1, 0) : 0; - output[writecoord + int2(1, 0)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP)); + output[writecoord + int2(1, 0)] = input.Load(int3(readcoord + readoffset, push.xCopySrcMIP)); // bottom right - if (readcoord.y == xCopySrcSize.y - 1) + if (readcoord.y == push.xCopySrcSize.y - 1) { - readoffset = wrap ? int2(-xCopySrcSize.x + 1, -xCopySrcSize.x + 1) : 0; + readoffset = wrap ? int2(-push.xCopySrcSize.x + 1, -push.xCopySrcSize.x + 1) : 0; - output[writecoord + int2(1, 1)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP)); + output[writecoord + int2(1, 1)] = input.Load(int3(readcoord + readoffset, push.xCopySrcMIP)); } } // top if (readcoord.y == 0) { - readoffset = wrap ? int2(0, xCopySrcSize.x - 1) : 0; + readoffset = wrap ? int2(0, push.xCopySrcSize.x - 1) : 0; - output[writecoord + int2(0, -1)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP)); + output[writecoord + int2(0, -1)] = input.Load(int3(readcoord + readoffset, push.xCopySrcMIP)); // top right - if (readcoord.x == xCopySrcSize.x - 1) + if (readcoord.x == push.xCopySrcSize.x - 1) { - readoffset = wrap ? int2(-xCopySrcSize.x + 1, xCopySrcSize.x - 1) : 0; + readoffset = wrap ? int2(-push.xCopySrcSize.x + 1, push.xCopySrcSize.x - 1) : 0; - output[writecoord + int2(1, -1)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP)); + output[writecoord + int2(1, -1)] = input.Load(int3(readcoord + readoffset, push.xCopySrcMIP)); } } // bottom - if (readcoord.y == xCopySrcSize.y - 1) + if (readcoord.y == push.xCopySrcSize.y - 1) { - readoffset = wrap ? int2(0, -xCopySrcSize.x + 1) : 0; + readoffset = wrap ? int2(0, -push.xCopySrcSize.x + 1) : 0; - output[writecoord + int2(0, 1)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP)); + output[writecoord + int2(0, 1)] = input.Load(int3(readcoord + readoffset, push.xCopySrcMIP)); // bottom left if (readcoord.x == 0) { - readoffset = wrap ? int2(xCopySrcSize.x - 1, -xCopySrcSize.x + 1) : 0; + readoffset = wrap ? int2(push.xCopySrcSize.x - 1, -push.xCopySrcSize.x + 1) : 0; - output[writecoord + int2(-1, 1)] = input.Load(int3(readcoord + readoffset, xCopySrcMIP)); + output[writecoord + int2(-1, 1)] = input.Load(int3(readcoord + readoffset, push.xCopySrcMIP)); } } } diff --git a/WickedEngine/shaders/cubeMapPS.hlsl b/WickedEngine/shaders/cubeMapPS.hlsl index 1494d41c4..84b13fa5d 100644 --- a/WickedEngine/shaders/cubeMapPS.hlsl +++ b/WickedEngine/shaders/cubeMapPS.hlsl @@ -13,6 +13,6 @@ float4 main(VSOut_Sphere input) : SV_TARGET { float3 P = input.pos3D; float3 N = normalize(input.nor); - float3 V = normalize(g_xCamera_CamPos - P); + float3 V = normalize(g_xCamera.CamPos - P); return float4(cubeMap.Sample(sampler_linear_clamp, -reflect(V, N)).rgb, 1); } \ No newline at end of file diff --git a/WickedEngine/shaders/cubeShadowVS.hlsl b/WickedEngine/shaders/cubeShadowVS.hlsl index 1041baf5f..93bb701d9 100644 --- a/WickedEngine/shaders/cubeShadowVS.hlsl +++ b/WickedEngine/shaders/cubeShadowVS.hlsl @@ -1,4 +1,4 @@ #define OBJECTSHADER_COMPILE_VS -#define OBJECTSHADER_LAYOUT_POS +#define OBJECTSHADER_LAYOUT_SHADOW #define OBJECTSHADER_USE_RENDERTARGETARRAYINDEX #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/cubeShadowVS_alphatest.hlsl b/WickedEngine/shaders/cubeShadowVS_alphatest.hlsl index df4fcd731..aea4bcb00 100644 --- a/WickedEngine/shaders/cubeShadowVS_alphatest.hlsl +++ b/WickedEngine/shaders/cubeShadowVS_alphatest.hlsl @@ -1,5 +1,5 @@ #define OBJECTSHADER_COMPILE_VS -#define OBJECTSHADER_LAYOUT_POS_TEX +#define OBJECTSHADER_LAYOUT_SHADOW_TEX #define OBJECTSHADER_USE_RENDERTARGETARRAYINDEX #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/cubeShadowVS_transparent.hlsl b/WickedEngine/shaders/cubeShadowVS_transparent.hlsl index 6f3a7fac9..d988de5f1 100644 --- a/WickedEngine/shaders/cubeShadowVS_transparent.hlsl +++ b/WickedEngine/shaders/cubeShadowVS_transparent.hlsl @@ -1,5 +1,5 @@ #define OBJECTSHADER_COMPILE_VS -#define OBJECTSHADER_LAYOUT_POS_TEX +#define OBJECTSHADER_LAYOUT_SHADOW_TEX #define OBJECTSHADER_USE_COLOR #define OBJECTSHADER_USE_RENDERTARGETARRAYINDEX #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/cubeVS.hlsl b/WickedEngine/shaders/cubeVS.hlsl index cc5c39e25..043f6b51e 100644 --- a/WickedEngine/shaders/cubeVS.hlsl +++ b/WickedEngine/shaders/cubeVS.hlsl @@ -1,13 +1,11 @@ #include "globals.hlsli" #include "cube.hlsli" -#ifdef BINDLESS struct CubePushConstants { float4x4 transform; }; PUSHCONSTANT(push, CubePushConstants); -#endif // BINDLESS float4 main(uint vID : SV_VERTEXID) : SV_Position { @@ -15,9 +13,5 @@ float4 main(uint vID : SV_VERTEXID) : SV_Position //return mul(g_xTransform, CUBE[vID]); // This is a 14 vertex count trianglestrip variant: -#ifdef BINDLESS return mul(push.transform, float4(CreateCube(vID) * 2 - 1,1)); -#else - return mul(g_xTransform, float4(CreateCube(vID) * 2 - 1,1)); -#endif // BINDLESS } diff --git a/WickedEngine/shaders/cullingShaderHF.hlsli b/WickedEngine/shaders/cullingShaderHF.hlsli index ea1b35c82..785339153 100644 --- a/WickedEngine/shaders/cullingShaderHF.hlsli +++ b/WickedEngine/shaders/cullingShaderHF.hlsli @@ -40,7 +40,7 @@ struct Frustum float4 ClipToView(float4 clip) { // View space position. - float4 view = mul(g_xCamera_InvP, clip); + float4 view = mul(g_xCamera.InvP, clip); // Perspective projection. view = view / view.w; diff --git a/WickedEngine/shaders/depthOfFieldHF.hlsli b/WickedEngine/shaders/depthOfFieldHF.hlsli index 24fd6bb56..c02fe5e0b 100644 --- a/WickedEngine/shaders/depthOfFieldHF.hlsli +++ b/WickedEngine/shaders/depthOfFieldHF.hlsli @@ -3,10 +3,10 @@ inline float get_coc(in float linear_depth) { - return min(dof_maxcoc, dof_cocscale * g_xCamera_ApertureSize * pow(abs(1 - g_xCamera_FocalLength / (linear_depth * g_xCamera_ZFarP)), 2.0f)); + return min(dof_maxcoc, dof_cocscale * g_xCamera.ApertureSize * pow(abs(1 - g_xCamera.FocalLength / (linear_depth * g_xCamera.ZFarP)), 2.0f)); } -#define DOF_DEPTH_SCALE_FOREGROUND (g_xCamera_ZFarP * 1.5) +#define DOF_DEPTH_SCALE_FOREGROUND (g_xCamera.ZFarP * 1.5) float2 DepthCmp2(float depth, float closestTileDepth) { float d = DOF_DEPTH_SCALE_FOREGROUND * (depth - closestTileDepth); diff --git a/WickedEngine/shaders/depthoffield_mainCS.hlsl b/WickedEngine/shaders/depthoffield_mainCS.hlsl index 611f01aec..b865c1406 100644 --- a/WickedEngine/shaders/depthoffield_mainCS.hlsl +++ b/WickedEngine/shaders/depthoffield_mainCS.hlsl @@ -46,7 +46,7 @@ void main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID) const uint ringCount = clamp(ceil(pow(maxcoc, 0.5f) * DOF_RING_COUNT), 1, DOF_RING_COUNT); const float spreadScale = ringCount / maxcoc; - const float2 ringScale = float(ringCount) / float(DOF_RING_COUNT) * maxcoc * g_xCamera_ApertureShape * xPPResolution_rcp; + const float2 ringScale = float(ringCount) / float(DOF_RING_COUNT) * maxcoc * g_xCamera.ApertureShape * xPPResolution_rcp; const float3 center_color = texture_prefilter[pixel]; const float3 center_presort = texture_presort[pixel]; diff --git a/WickedEngine/shaders/depthoffield_prepassCS.hlsl b/WickedEngine/shaders/depthoffield_prepassCS.hlsl index eb4ce921a..a10f0ec7d 100644 --- a/WickedEngine/shaders/depthoffield_prepassCS.hlsl +++ b/WickedEngine/shaders/depthoffield_prepassCS.hlsl @@ -47,14 +47,14 @@ void main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID) [branch] if (backgroundFactor < 1.0f) { - const float2 ringScale = 0.5f * coc * g_xCamera_ApertureShape * xPPResolution_rcp; + const float2 ringScale = 0.5f * coc * g_xCamera.ApertureShape * xPPResolution_rcp; [unroll] for (uint i = ringSampleCount[0]; i < ringSampleCount[1]; ++i) { const float2 uv2 = uv + ringScale * disc[i].xy; const float depth = texture_lineardepth.SampleLevel(sampler_point_clamp, uv2, 1); const float3 color = max(0, input.SampleLevel(sampler_linear_clamp, uv2, 0).rgb); - const float weight = saturate(abs(depth - center_depth) * g_xCamera_ZFarP * 2); + const float weight = saturate(abs(depth - center_depth) * g_xCamera.ZFarP * 2); prefilter += lerp(color, center_color, weight); } prefilter *= ringNormFactor[1]; diff --git a/WickedEngine/shaders/depthoffield_upsampleCS.hlsl b/WickedEngine/shaders/depthoffield_upsampleCS.hlsl index 782425461..233474d99 100644 --- a/WickedEngine/shaders/depthoffield_upsampleCS.hlsl +++ b/WickedEngine/shaders/depthoffield_upsampleCS.hlsl @@ -24,7 +24,7 @@ void main(uint3 DTid : SV_DispatchThreadID) const float coc = get_coc(center_depth); - float depthDelta = saturate(1.0 - g_xCamera_ZFarP * (center_depth - mindepth)); + float depthDelta = saturate(1.0 - g_xCamera.ZFarP * (center_depth - mindepth)); const float backgroundFactor = coc; const float foregroundFactor = lerp(maxcoc, coc, depthDelta); diff --git a/WickedEngine/shaders/emittedparticleHF.hlsli b/WickedEngine/shaders/emittedparticleHF.hlsli index 0bd0f5e4f..4e079f450 100644 --- a/WickedEngine/shaders/emittedparticleHF.hlsli +++ b/WickedEngine/shaders/emittedparticleHF.hlsli @@ -1,5 +1,12 @@ #ifndef WI_EMITTEDPARTICLE_HF #define WI_EMITTEDPARTICLE_HF +#include "globals.hlsli" +#include "ShaderInterop_EmittedParticle.h" + +ShaderMaterial EmitterGetMaterial() +{ + return load_material(xEmitterMaterialIndex); +} struct VertextoPixel { diff --git a/WickedEngine/shaders/emittedparticleMS.hlsl b/WickedEngine/shaders/emittedparticleMS.hlsl index 41b812d51..1a9646835 100644 --- a/WickedEngine/shaders/emittedparticleMS.hlsl +++ b/WickedEngine/shaders/emittedparticleMS.hlsl @@ -43,7 +43,7 @@ void main( // calculate render properties from life: float lifeLerp = 1 - particle.life / particle.maxLife; float size = lerp(particle.sizeBeginEnd.x, particle.sizeBeginEnd.y, lifeLerp); - float opacity = saturate(lerp(1, 0, lifeLerp) * xEmitterOpacity); + float opacity = saturate(lerp(1, 0, lifeLerp) * EmitterGetMaterial().baseColor.a); float rotation = lifeLerp * particle.rotationalVelocity; const float spriteframe = xEmitterFrameRate == 0 ? @@ -60,7 +60,7 @@ void main( sin(rotation), cos(rotation) ); - float3 velocity = mul((float3x3)g_xCamera_View, particle.velocity); + float3 velocity = mul((float3x3)g_xCamera.View, particle.velocity); // Transform the vertices and write them for (uint i = 0; i < BILLBOARD_VERTEXCOUNT; ++i) @@ -93,10 +93,10 @@ void main( // copy to output: Out.pos = float4(particle.position, 1); - Out.pos = mul(g_xCamera_View, Out.pos); + Out.pos = mul(g_xCamera.View, Out.pos); Out.pos.xyz += quadPos.xyz; - Out.P = mul(g_xCamera_InvV, float4(Out.pos.xyz, 1)).xyz; - Out.pos = mul(g_xCamera_Proj, Out.pos); + Out.P = mul(g_xCamera.InvV, float4(Out.pos.xyz, 1)).xyz; + Out.pos = mul(g_xCamera.Proj, Out.pos); Out.tex = float4(uv, uv2); Out.size = size; diff --git a/WickedEngine/shaders/emittedparticlePS_soft.hlsl b/WickedEngine/shaders/emittedparticlePS_soft.hlsl index a28aa3e1b..9b598762d 100644 --- a/WickedEngine/shaders/emittedparticlePS_soft.hlsl +++ b/WickedEngine/shaders/emittedparticlePS_soft.hlsl @@ -3,23 +3,29 @@ #include "ShaderInterop_EmittedParticle.h" #include "objectHF.hlsli" -TEXTURE2D(texture_color, float4, TEXSLOT_ONDEMAND0); - [earlydepthstencil] float4 main(VertextoPixel input) : SV_TARGET { - float4 color = texture_color.Sample(sampler_linear_clamp, input.tex.xy); + ShaderMaterial material = EmitterGetMaterial(); + + float4 color = 1; [branch] - if (xEmitterOptions & EMITTER_OPTION_BIT_FRAME_BLENDING_ENABLED) + if (material.texture_basecolormap_index >= 0) { - float4 color2 = texture_color.Sample(sampler_linear_clamp, input.tex.zw); - color = lerp(color, color2, input.frameBlend); + color = bindless_textures[material.texture_basecolormap_index].Sample(sampler_linear_clamp, input.tex.xy); + + [branch] + if (xEmitterOptions & EMITTER_OPTION_BIT_FRAME_BLENDING_ENABLED) + { + float4 color2 = bindless_textures[material.texture_basecolormap_index].Sample(sampler_linear_clamp, input.tex.zw); + color = lerp(color, color2, input.frameBlend); + } } float2 pixel = input.pos.xy; - float2 ScreenCoord = pixel * g_xFrame_InternalResolution_rcp; - float4 depthScene = texture_lineardepth.GatherRed(sampler_linear_clamp, ScreenCoord) * g_xCamera_ZFarP; + float2 ScreenCoord = pixel * g_xFrame.InternalResolution_rcp; + float4 depthScene = texture_lineardepth.GatherRed(sampler_linear_clamp, ScreenCoord) * g_xCamera.ZFarP; float depthFragment = input.pos.w; float fade = saturate(1.0 / input.size*(max(max(depthScene.x, depthScene.y), max(depthScene.z, depthScene.w)) - depthFragment)); @@ -31,7 +37,7 @@ float4 main(VertextoPixel input) : SV_TARGET float opacity = saturate(color.a * inputColor.a * fade); - color.rgb *= inputColor.rgb * (1 + xParticleEmissive); + color.rgb *= inputColor.rgb * (1 + material.emissiveColor.rgb * material.emissiveColor.a); color.a = opacity; #ifdef EMITTEDPARTICLE_DISTORTION @@ -49,20 +55,20 @@ float4 main(VertextoPixel input) : SV_TARGET N.x = -cos(PI * input.unrotated_uv.x); N.y = cos(PI * input.unrotated_uv.y); N.z = -sin(PI * length(input.unrotated_uv)); - N = mul((float3x3)g_xCamera_InvV, N); + N = mul((float3x3)g_xCamera.InvV, N); N = normalize(N); Lighting lighting; lighting.create(0, 0, GetAmbient(N), 0); Surface surface; - surface.create(g_xMaterial, color, 0); + surface.create(material, color, 0); surface.P = input.P; surface.N = N; surface.V = 0; surface.pixel = pixel; - surface.sss = g_xMaterial.subsurfaceScattering; - surface.sss_inv = g_xMaterial.subsurfaceScattering_inv; + surface.sss = material.subsurfaceScattering; + surface.sss_inv = material.subsurfaceScattering_inv; surface.update(); TiledLighting(surface, lighting); @@ -72,9 +78,10 @@ float4 main(VertextoPixel input) : SV_TARGET //color.rgb = float3(unrotated_uv, 0); //color.rgb = float3(input.tex, 0); + color = max(0, color); } #endif // EMITTEDPARTICLE_LIGHTING - return max(color, 0); + return color; } diff --git a/WickedEngine/shaders/emittedparticleVS.hlsl b/WickedEngine/shaders/emittedparticleVS.hlsl index bf67d001d..0e21cbb22 100644 --- a/WickedEngine/shaders/emittedparticleVS.hlsl +++ b/WickedEngine/shaders/emittedparticleVS.hlsl @@ -22,7 +22,7 @@ VertextoPixel main(uint vertexID : SV_VERTEXID, uint instanceID : SV_INSTANCEID) // calculate render properties from life: float lifeLerp = 1 - particle.life / particle.maxLife; float size = lerp(particle.sizeBeginEnd.x, particle.sizeBeginEnd.y, lifeLerp); - float opacity = saturate(lerp(1, 0, lifeLerp) * xEmitterOpacity); + float opacity = saturate(lerp(1, 0, lifeLerp) * EmitterGetMaterial().baseColor.a); float rotation = lifeLerp * particle.rotationalVelocity; // expand the point into a billboard in view space: @@ -57,16 +57,16 @@ VertextoPixel main(uint vertexID : SV_VERTEXID, uint instanceID : SV_INSTANCEID) quadPos *= size; // scale the billboard along view space motion vector: - float3 velocity = mul((float3x3)g_xCamera_View, particle.velocity); + float3 velocity = mul((float3x3)g_xCamera.View, particle.velocity); quadPos += dot(quadPos, velocity) * velocity * xParticleMotionBlurAmount; // copy to output: Out.pos = float4(particle.position, 1); - Out.pos = mul(g_xCamera_View, Out.pos); + Out.pos = mul(g_xCamera.View, Out.pos); Out.pos.xyz += quadPos.xyz; - Out.P = mul(g_xCamera_InvV, float4(Out.pos.xyz, 1)).xyz; - Out.pos = mul(g_xCamera_Proj, Out.pos); + Out.P = mul(g_xCamera.InvV, float4(Out.pos.xyz, 1)).xyz; + Out.pos = mul(g_xCamera.Proj, Out.pos); Out.tex = float4(uv, uv2); Out.size = size; @@ -75,4 +75,4 @@ VertextoPixel main(uint vertexID : SV_VERTEXID, uint instanceID : SV_INSTANCEID) Out.frameBlend = frameBlend; return Out; -} \ No newline at end of file +} diff --git a/WickedEngine/shaders/emittedparticle_emitCS.hlsl b/WickedEngine/shaders/emittedparticle_emitCS.hlsl index adb7b8bf2..66cfa4b0c 100644 --- a/WickedEngine/shaders/emittedparticle_emitCS.hlsl +++ b/WickedEngine/shaders/emittedparticle_emitCS.hlsl @@ -1,4 +1,5 @@ #include "globals.hlsli" +#include "emittedparticleHF.hlsli" #include "ShaderInterop_EmittedParticle.h" RWSTRUCTUREDBUFFER(particleBuffer, Particle, 0); @@ -22,7 +23,7 @@ void main(uint3 DTid : SV_DispatchThreadID) { // we can emit: - float2 uv = float2(g_xFrame_Time + xEmitterRandomness, (float)DTid.x / (float)THREADCOUNT_EMIT); + float2 uv = float2(g_xFrame.Time + xEmitterRandomness, (float)DTid.x / (float)THREADCOUNT_EMIT); float seed = 0.12345; #ifdef EMIT_FROM_MESH @@ -112,7 +113,7 @@ void main(uint3 DTid : SV_DispatchThreadID) color_modifier |= (uint)(255.0 * lerp(1, rand(seed, uv), xParticleRandomColorFactor)) << 0; color_modifier |= (uint)(255.0 * lerp(1, rand(seed, uv), xParticleRandomColorFactor)) << 8; color_modifier |= (uint)(255.0 * lerp(1, rand(seed, uv), xParticleRandomColorFactor)) << 16; - particle.color_mirror |= xParticleColor & color_modifier; + particle.color_mirror |= pack_rgba(float4(EmitterGetMaterial().baseColor.rgb, 1)) & color_modifier; // new particle index retrieved from dead list (pop): diff --git a/WickedEngine/shaders/emittedparticle_simulateCS.hlsl b/WickedEngine/shaders/emittedparticle_simulateCS.hlsl index e3a45bd33..dd840f32e 100644 --- a/WickedEngine/shaders/emittedparticle_simulateCS.hlsl +++ b/WickedEngine/shaders/emittedparticle_simulateCS.hlsl @@ -21,7 +21,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex) if (DTid.x < aliveCount) { // simulation can be either fixed or variable timestep: - const float dt = xEmitterFixedTimestep >= 0 ? xEmitterFixedTimestep : g_xFrame_DeltaTime; + const float dt = xEmitterFixedTimestep >= 0 ? xEmitterFixedTimestep : g_xFrame.DeltaTime; uint particleIndex = aliveBuffer_CURRENT[DTid.x]; Particle particle = particleBuffer[particleIndex]; @@ -29,9 +29,9 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex) if (particle.life > 0) { // simulate: - for (uint i = 0; i < g_xFrame_ForceFieldArrayCount; ++i) + for (uint i = 0; i < g_xFrame.ForceFieldArrayCount; ++i) { - ShaderEntity forceField = EntityArray[g_xFrame_ForceFieldArrayOffset + i]; + ShaderEntity forceField = EntityArray[g_xFrame.ForceFieldArrayOffset + i]; [branch] if (forceField.layerMask & xEmitterLayerMask) @@ -57,13 +57,13 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex) // NOTE: We are using the textures from previous frame, so reproject against those! (PrevVP) - float4 pos2D = mul(g_xCamera_PrevVP, float4(particle.position, 1)); + float4 pos2D = mul(g_xCamera.PrevVP, float4(particle.position, 1)); pos2D.xyz /= pos2D.w; if (pos2D.x > -1 && pos2D.x < 1 && pos2D.y > -1 && pos2D.y < 1) { float2 uv = pos2D.xy * float2(0.5f, -0.5f) + 0.5f; - uint2 pixel = uv * g_xFrame_InternalResolution; + uint2 pixel = uv * g_xFrame.InternalResolution; float depth0 = texture_depth[pixel]; float surfaceLinearDepth = getLinearDepth(depth0); @@ -79,9 +79,9 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex) float depth1 = texture_depth[pixel + uint2(1, 0)]; float depth2 = texture_depth[pixel + uint2(0, -1)]; - float3 p0 = reconstructPosition(uv, depth0, g_xCamera_PrevInvVP); - float3 p1 = reconstructPosition(uv + float2(1, 0) * g_xFrame_InternalResolution_rcp, depth1, g_xCamera_PrevInvVP); - float3 p2 = reconstructPosition(uv + float2(0, -1) * g_xFrame_InternalResolution_rcp, depth2, g_xCamera_PrevInvVP); + float3 p0 = reconstructPosition(uv, depth0, g_xCamera.PrevInvVP); + float3 p1 = reconstructPosition(uv + float2(1, 0) * g_xFrame.InternalResolution_rcp, depth1, g_xCamera.PrevInvVP); + float3 p2 = reconstructPosition(uv + float2(0, -1) * g_xFrame.InternalResolution_rcp, depth2, g_xCamera.PrevInvVP); float3 surfaceNormal = normalize(cross(p2 - p0, p1 - p0)); @@ -165,7 +165,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint Gid : SV_GroupIndex) #ifdef SORTING // store squared distance to main camera: - float3 eyeVector = particle.position - g_xCamera_CamPos; + float3 eyeVector = particle.position - g_xCamera.CamPos; float distSQ = dot(eyeVector, eyeVector); distanceBuffer[particleIndex] = -distSQ; // this can be negated to modify sorting order here instead of rewriting sorting shaders... #endif // SORTING diff --git a/WickedEngine/shaders/envMapPS.hlsl b/WickedEngine/shaders/envMapPS.hlsl index 6f884b590..db35d28ba 100644 --- a/WickedEngine/shaders/envMapPS.hlsl +++ b/WickedEngine/shaders/envMapPS.hlsl @@ -12,6 +12,7 @@ #define OBJECTSHADER_USE_TANGENT #define OBJECTSHADER_USE_POSITION3D #define OBJECTSHADER_USE_EMISSIVE +#define OBJECTSHADER_USE_INSTANCEID #define OBJECTSHADER_USE_RENDERTARGETARRAYINDEX #define ENVMAPRENDERING #define FORWARD diff --git a/WickedEngine/shaders/envMapVS.hlsl b/WickedEngine/shaders/envMapVS.hlsl index 8a0862434..5cb191a47 100644 --- a/WickedEngine/shaders/envMapVS.hlsl +++ b/WickedEngine/shaders/envMapVS.hlsl @@ -12,6 +12,7 @@ #define OBJECTSHADER_USE_TANGENT #define OBJECTSHADER_USE_POSITION3D #define OBJECTSHADER_USE_EMISSIVE +#define OBJECTSHADER_USE_INSTANCEID #define OBJECTSHADER_USE_RENDERTARGETARRAYINDEX #define ENVMAPRENDERING #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/filterEnvMapCS.hlsl b/WickedEngine/shaders/filterEnvMapCS.hlsl index 1127c7eab..7eff40439 100644 --- a/WickedEngine/shaders/filterEnvMapCS.hlsl +++ b/WickedEngine/shaders/filterEnvMapCS.hlsl @@ -1,5 +1,7 @@ #include "globals.hlsli" -#include "ShaderInterop_Utility.h" +#include "ShaderInterop_Renderer.h" + +PUSHCONSTANT(push, FilterEnvmapCB); TEXTURECUBEARRAY(input, float4, TEXSLOT_ONDEMAND0); RWTEXTURE2DARRAY(output, float4, 0); @@ -21,25 +23,25 @@ float3 ImportanceSampleGGX(float2 Xi, float Roughness, float3 N) [numthreads(GENERATEMIPCHAIN_2D_BLOCK_SIZE, GENERATEMIPCHAIN_2D_BLOCK_SIZE, 1)] void main(uint3 DTid : SV_DispatchThreadID) { - if (DTid.x < filterResolution.x && DTid.y < filterResolution.y) + if (DTid.x < push.filterResolution.x && DTid.y < push.filterResolution.y) { - float2 uv = (DTid.xy + 0.5f) * filterResolution_rcp.xy; + float2 uv = (DTid.xy + 0.5f) * push.filterResolution_rcp.xy; float3 N = UV_to_CubeMap(uv, DTid.z); float3x3 tangentSpace = GetTangentSpace(N); float4 col = 0; - for (uint i = 0; i < filterRayCount; ++i) + for (uint i = 0; i < push.filterRayCount; ++i) { - float2 hamm = hammersley2d(i, filterRayCount); - float3 hemisphere = ImportanceSampleGGX(hamm, filterRoughness, N); + float2 hamm = hammersley2d(i, push.filterRayCount); + float3 hemisphere = ImportanceSampleGGX(hamm, push.filterRoughness, N); float3 cone = mul(hemisphere, tangentSpace); - col += input.SampleLevel(sampler_linear_clamp, float4(cone, filterArrayIndex), 0); + col += input.SampleLevel(sampler_linear_clamp, float4(cone, push.filterArrayIndex), 0); } - col /= (float)filterRayCount; + col /= (float)push.filterRayCount; - output[uint3(DTid.xy, DTid.z + filterArrayIndex * 6)] = col; + output[uint3(DTid.xy, DTid.z + push.filterArrayIndex * 6)] = col; } } diff --git a/WickedEngine/shaders/fontPS.hlsl b/WickedEngine/shaders/fontPS.hlsl index 9665b0ae6..8108f75d0 100644 --- a/WickedEngine/shaders/fontPS.hlsl +++ b/WickedEngine/shaders/fontPS.hlsl @@ -1,13 +1,6 @@ #include "globals.hlsli" #include "ShaderInterop_Font.h" -#ifdef BINDLESS -Texture2D bindless_textures[] : register(space1); -#define texture_font bindless_textures[g_xFont_TextureIndex] -#else -TEXTURE2D(texture_font, float, TEXSLOT_FONTATLAS); -#endif // BINDLESS - SAMPLERSTATE(sampler_font, SSLOT_ONDEMAND1); struct VertextoPixel @@ -18,5 +11,5 @@ struct VertextoPixel float4 main(VertextoPixel PSIn) : SV_TARGET { - return texture_font.SampleLevel(sampler_font, PSIn.tex, 0).rrrr * g_xFont_Color; + return bindless_textures[push.texture_index].SampleLevel(sampler_font, PSIn.tex, 0).rrrr * unpack_rgba(push.color); } diff --git a/WickedEngine/shaders/fontVS.hlsl b/WickedEngine/shaders/fontVS.hlsl index ecc2eabe6..65ca56a1e 100644 --- a/WickedEngine/shaders/fontVS.hlsl +++ b/WickedEngine/shaders/fontVS.hlsl @@ -7,15 +7,13 @@ struct VertextoPixel float2 tex : TEXCOORD0; }; -RAWBUFFER(vertexBuffer, 0); - VertextoPixel main(uint vertexID : SV_VERTEXID, uint instanceID : SV_InstanceID) { VertextoPixel Out; uint vID = instanceID * 4 + vertexID; - uint3 raw = vertexBuffer.Load3(g_xFont_BufferOffset + vID * 12); - Out.pos = mul(g_xFont_Transform, float4(asfloat(raw.xy), 0, 1)); + uint3 raw = bindless_buffers[push.buffer_index].Load3(push.buffer_offset + vID * 12); + Out.pos = mul(push.transform, float4(asfloat(raw.xy), 0, 1)); Out.tex = unpack_half2(raw.z); return Out; diff --git a/WickedEngine/shaders/forceFieldPlaneVisualizerVS.hlsl b/WickedEngine/shaders/forceFieldPlaneVisualizerVS.hlsl index b9c77aa9e..20695213a 100644 --- a/WickedEngine/shaders/forceFieldPlaneVisualizerVS.hlsl +++ b/WickedEngine/shaders/forceFieldPlaneVisualizerVS.hlsl @@ -13,7 +13,7 @@ PSIn main(uint vID : SV_VERTEXID) Out.pos = float4(CreateCube(vID) * 2 - 1, 1); - uint forceFieldID = g_xFrame_ForceFieldArrayOffset + (uint)g_xColor.w; + uint forceFieldID = g_xFrame.ForceFieldArrayOffset + (uint)g_xColor.w; ShaderEntity forceField = EntityArray[forceFieldID]; Out.pos.xyz *= forceField.GetConeAngleCos(); // range... diff --git a/WickedEngine/shaders/forceFieldPointVisualizerVS.hlsl b/WickedEngine/shaders/forceFieldPointVisualizerVS.hlsl index 6914e581e..25d8f8e75 100644 --- a/WickedEngine/shaders/forceFieldPointVisualizerVS.hlsl +++ b/WickedEngine/shaders/forceFieldPointVisualizerVS.hlsl @@ -15,7 +15,7 @@ PSIn main(uint vID : SV_VERTEXID) Out.pos = UVSPHERE[vID]; - uint forceFieldID = g_xFrame_ForceFieldArrayOffset + (uint)g_xColor.w; + uint forceFieldID = g_xFrame.ForceFieldArrayOffset + (uint)g_xColor.w; ShaderEntity forceField = EntityArray[forceFieldID]; Out.pos.xyz *= forceField.GetConeAngleCos(); // range... diff --git a/WickedEngine/shaders/forceFieldVisualizerPS.hlsl b/WickedEngine/shaders/forceFieldVisualizerPS.hlsl index f343319ea..89ab0b8c6 100644 --- a/WickedEngine/shaders/forceFieldVisualizerPS.hlsl +++ b/WickedEngine/shaders/forceFieldVisualizerPS.hlsl @@ -9,7 +9,7 @@ struct PSIn float4 main(PSIn input) : SV_TARGET { - uint forceFieldID = g_xFrame_ForceFieldArrayOffset + (uint)g_xColor.w; + uint forceFieldID = g_xFrame.ForceFieldArrayOffset + (uint)g_xColor.w; ShaderEntity forceField = EntityArray[forceFieldID]; float4 color = forceField.GetEnergy() < 0 ? float4(0, 0, 1, 1) : float4(1, 0, 0, 1); @@ -30,7 +30,7 @@ float4 main(PSIn input) : SV_TARGET } float2 pTex = input.pos2D.xy / input.pos2D.w * float2(0.5f, -0.5f) + 0.5f; - float4 depthScene = texture_lineardepth.GatherRed(sampler_linear_clamp, pTex) * g_xCamera_ZFarP; + float4 depthScene = texture_lineardepth.GatherRed(sampler_linear_clamp, pTex) * g_xCamera.ZFarP; float depthFragment = input.pos2D.w; float fade = saturate(1.0 / forceField.GetConeAngleCos() * abs(forceField.GetEnergy()) * (max(max(depthScene.x, depthScene.y), max(depthScene.z, depthScene.w)) - depthFragment)); color.a *= fade; diff --git a/WickedEngine/shaders/generateMIPChain2DCS_float4.hlsl b/WickedEngine/shaders/generateMIPChain2DCS_float4.hlsl index 8ee94a17a..7d4e4ccfe 100644 --- a/WickedEngine/shaders/generateMIPChain2DCS_float4.hlsl +++ b/WickedEngine/shaders/generateMIPChain2DCS_float4.hlsl @@ -1,10 +1,12 @@ #include "globals.hlsli" -#include "ShaderInterop_Utility.h" +#include "ShaderInterop_Renderer.h" #ifndef MIP_OUTPUT_FORMAT #define MIP_OUTPUT_FORMAT float4 #endif +PUSHCONSTANT(push, GenerateMIPChainCB); + TEXTURE2D(input, float4, TEXSLOT_ONDEMAND0); RWTEXTURE2D(output, MIP_OUTPUT_FORMAT, 0); @@ -13,13 +15,13 @@ SAMPLERSTATE(customsampler, SSLOT_ONDEMAND0); [numthreads(GENERATEMIPCHAIN_2D_BLOCK_SIZE, GENERATEMIPCHAIN_2D_BLOCK_SIZE, 1)] void main(uint3 DTid : SV_DispatchThreadID) { - if (DTid.x < outputResolution.x && DTid.y < outputResolution.y) + if (DTid.x < push.outputResolution.x && DTid.y < push.outputResolution.y) { - float2 uv = ((float2)DTid.xy + 0.5f) * (float2)outputResolution_rcp.xy; + float2 uv = ((float2)DTid.xy + 0.5f) * (float2)push.outputResolution_rcp.xy; float4 color = input.SampleLevel(customsampler, uv, 0); [branch] - if (mipgen_options & MIPGEN_OPTION_BIT_PRESERVE_COVERAGE) + if (push.mipgen_options & MIPGEN_OPTION_BIT_PRESERVE_COVERAGE) { float4 alphas = input.GatherAlpha(customsampler, uv, 0); alphas = pow(saturate(alphas), 2.2f); diff --git a/WickedEngine/shaders/generateMIPChain3DCS_float4.hlsl b/WickedEngine/shaders/generateMIPChain3DCS_float4.hlsl index d95b064c9..029ab46a2 100644 --- a/WickedEngine/shaders/generateMIPChain3DCS_float4.hlsl +++ b/WickedEngine/shaders/generateMIPChain3DCS_float4.hlsl @@ -1,10 +1,12 @@ #include "globals.hlsli" -#include "ShaderInterop_Utility.h" +#include "ShaderInterop_Renderer.h" #ifndef MIP_OUTPUT_FORMAT #define MIP_OUTPUT_FORMAT float4 #endif +PUSHCONSTANT(push, GenerateMIPChainCB); + TEXTURE3D(input, float4, TEXSLOT_ONDEMAND0); RWTEXTURE3D(output, MIP_OUTPUT_FORMAT, 0); @@ -13,8 +15,8 @@ SAMPLERSTATE(customsampler, SSLOT_ONDEMAND0); [numthreads(GENERATEMIPCHAIN_3D_BLOCK_SIZE, GENERATEMIPCHAIN_3D_BLOCK_SIZE, GENERATEMIPCHAIN_3D_BLOCK_SIZE)] void main( uint3 DTid : SV_DispatchThreadID ) { - if (DTid.x < outputResolution.x && DTid.y < outputResolution.y && DTid.z < outputResolution.z) + if (DTid.x < push.outputResolution.x && DTid.y < push.outputResolution.y && DTid.z < push.outputResolution.z) { - output[DTid] = input.SampleLevel(customsampler, ((float3)DTid + 0.5f) * (float3)outputResolution_rcp, 0); + output[DTid] = input.SampleLevel(customsampler, ((float3)DTid + 0.5f) * (float3)push.outputResolution_rcp, 0); } } diff --git a/WickedEngine/shaders/generateMIPChainCubeArrayCS_float4.hlsl b/WickedEngine/shaders/generateMIPChainCubeArrayCS_float4.hlsl index 708889698..51f3f9082 100644 --- a/WickedEngine/shaders/generateMIPChainCubeArrayCS_float4.hlsl +++ b/WickedEngine/shaders/generateMIPChainCubeArrayCS_float4.hlsl @@ -1,10 +1,12 @@ #include "globals.hlsli" -#include "ShaderInterop_Utility.h" +#include "ShaderInterop_Renderer.h" #ifndef MIP_OUTPUT_FORMAT #define MIP_OUTPUT_FORMAT float4 #endif +PUSHCONSTANT(push, GenerateMIPChainCB); + TEXTURECUBEARRAY(input, float4, TEXSLOT_ONDEMAND0); RWTEXTURE2DARRAY(output, MIP_OUTPUT_FORMAT, 0); @@ -13,11 +15,11 @@ SAMPLERSTATE(customsampler, SSLOT_ONDEMAND0); [numthreads(GENERATEMIPCHAIN_2D_BLOCK_SIZE, GENERATEMIPCHAIN_2D_BLOCK_SIZE, 1)] void main(uint3 DTid : SV_DispatchThreadID) { - if (DTid.x < outputResolution.x && DTid.y < outputResolution.y) + if (DTid.x < push.outputResolution.x && DTid.y < push.outputResolution.y) { - float2 uv = ((float2)DTid.xy + 0.5f) * outputResolution_rcp.xy; + float2 uv = ((float2)DTid.xy + 0.5f) * push.outputResolution_rcp.xy; float3 N = UV_to_CubeMap(uv, DTid.z); - output[uint3(DTid.xy, DTid.z + arrayIndex * 6)] = input.SampleLevel(customsampler, float4(N, arrayIndex), 0); + output[uint3(DTid.xy, DTid.z + push.arrayIndex * 6)] = input.SampleLevel(customsampler, float4(N, push.arrayIndex), 0); } } diff --git a/WickedEngine/shaders/generateMIPChainCubeCS_float4.hlsl b/WickedEngine/shaders/generateMIPChainCubeCS_float4.hlsl index ccdb3a217..17584c46a 100644 --- a/WickedEngine/shaders/generateMIPChainCubeCS_float4.hlsl +++ b/WickedEngine/shaders/generateMIPChainCubeCS_float4.hlsl @@ -1,10 +1,12 @@ #include "globals.hlsli" -#include "ShaderInterop_Utility.h" +#include "ShaderInterop_Renderer.h" #ifndef MIP_OUTPUT_FORMAT #define MIP_OUTPUT_FORMAT float4 #endif +PUSHCONSTANT(push, GenerateMIPChainCB); + TEXTURECUBE(input, float4, TEXSLOT_ONDEMAND0); RWTEXTURE2DARRAY(output, MIP_OUTPUT_FORMAT, 0); @@ -13,9 +15,9 @@ SAMPLERSTATE(customsampler, SSLOT_ONDEMAND0); [numthreads(GENERATEMIPCHAIN_2D_BLOCK_SIZE, GENERATEMIPCHAIN_2D_BLOCK_SIZE, 1)] void main(uint3 DTid : SV_DispatchThreadID) { - if (DTid.x < outputResolution.x && DTid.y < outputResolution.y) + if (DTid.x < push.outputResolution.x && DTid.y < push.outputResolution.y) { - float2 uv = ((float2)DTid.xy + 0.5f) * outputResolution_rcp.xy; + float2 uv = ((float2)DTid.xy + 0.5f) * push.outputResolution_rcp.xy; float3 N = UV_to_CubeMap(uv, DTid.z); output[DTid.xyz] = input.SampleLevel(customsampler, N, 0); diff --git a/WickedEngine/shaders/globals.hlsli b/WickedEngine/shaders/globals.hlsli index 18e60ec55..9be56feda 100644 --- a/WickedEngine/shaders/globals.hlsli +++ b/WickedEngine/shaders/globals.hlsli @@ -3,15 +3,40 @@ #include "ShaderInterop.h" #include "ShaderInterop_Renderer.h" +Texture2D bindless_textures[] : register(space1); +ByteAddressBuffer bindless_buffers[] : register(space2); +SamplerState bindless_samplers[] : register(space3); +Buffer bindless_ib[] : register(space4); + +TextureCube bindless_cubemaps[] : register(space5); +TextureCubeArray bindless_cubearrays[] : register(space6); +Texture3D bindless_textures3D[] : register(space7); +RWTexture2D bindless_rwtextures[] : register(space8); + +ShaderMeshInstance load_instance(uint instanceIndex) +{ + return bindless_buffers[g_xFrame.scene.instancebuffer].Load(instanceIndex * sizeof(ShaderMeshInstance)); +} +ShaderMesh load_mesh(uint meshIndex) +{ + return bindless_buffers[g_xFrame.scene.meshbuffer].Load(meshIndex * sizeof(ShaderMesh)); +} +ShaderMeshSubset load_subset(ShaderMesh mesh, uint subsetIndex) +{ + return bindless_buffers[NonUniformResourceIndex(mesh.subsetbuffer)].Load(subsetIndex * sizeof(ShaderMeshSubset)); +} +ShaderMaterial load_material(uint materialIndex) +{ + return bindless_buffers[g_xFrame.scene.materialbuffer].Load(materialIndex * sizeof(ShaderMaterial)); +} + +#define texture_globalenvmap bindless_cubemaps[g_xFrame.scene.globalenvmap] +#define texture_envmaparray bindless_cubearrays[g_xFrame.scene.envmaparray] + TEXTURE2D(texture_depth, float, TEXSLOT_DEPTH); TEXTURE2D(texture_lineardepth, float, TEXSLOT_LINEARDEPTH); -TEXTURE2D(texture_gbuffer0, float3, TEXSLOT_GBUFFER0); -TEXTURE2D(texture_gbuffer1, float4, TEXSLOT_GBUFFER1); -TEXTURE2D(texture_gbuffer2, float2, TEXSLOT_GBUFFER2); -TEXTURECUBE(texture_globalenvmap, float4, TEXSLOT_GLOBALENVMAP); -TEXTURE2D(texture_globallightmap, float4, TEXSLOT_GLOBALLIGHTMAP); -TEXTURECUBEARRAY(texture_envmaparray, float4, TEXSLOT_ENVMAPARRAY); -TEXTURE2D(texture_decalatlas, float4, TEXSLOT_DECALATLAS); +TEXTURE2D(texture_gbuffer0, uint2, TEXSLOT_GBUFFER0); +TEXTURE2D(texture_gbuffer1, float2, TEXSLOT_GBUFFER1); TEXTURE2D(texture_skyviewlut, float4, TEXSLOT_SKYVIEWLUT); TEXTURE2D(texture_transmittancelut, float4, TEXSLOT_TRANSMITTANCELUT); TEXTURE2D(texture_multiscatteringlut, float4, TEXSLOT_MULTISCATTERINGLUT); @@ -20,7 +45,7 @@ TEXTURE2DARRAY(texture_shadowarray_2d, float, TEXSLOT_SHADOWARRAY_2D); TEXTURECUBEARRAY(texture_shadowarray_cube, float, TEXSLOT_SHADOWARRAY_CUBE); TEXTURE2DARRAY(texture_shadowarray_transparent_2d, float4, TEXSLOT_SHADOWARRAY_TRANSPARENT_2D); TEXTURECUBEARRAY(texture_shadowarray_transparent_cube, float4, TEXSLOT_SHADOWARRAY_TRANSPARENT_CUBE); -TEXTURE3D(texture_voxelradiance, float4, TEXSLOT_VOXELRADIANCE); +TEXTURE3D(texture_voxelgi, float4, TEXSLOT_VOXELGI); TEXTURE2D(texture_sheenlut, float, TEXSLOT_SHEENLUT); TEXTURE2D(texture_bluenoise, float4, TEXSLOT_BLUENOISE); TEXTURE2D(texture_random64x64, float4, TEXSLOT_RANDOM64X64); @@ -37,7 +62,6 @@ SAMPLERSTATE( sampler_aniso_clamp, SSLOT_ANISO_CLAMP ); SAMPLERSTATE( sampler_aniso_wrap, SSLOT_ANISO_WRAP ); SAMPLERSTATE( sampler_aniso_mirror, SSLOT_ANISO_MIRROR ); SAMPLERCOMPARISONSTATE( sampler_cmp_depth, SSLOT_CMP_DEPTH ); -SAMPLERSTATE( sampler_objectshader, SSLOT_OBJECTSHADER ); #define PI 3.14159265358979323846 #define SQRT2 1.41421356237309504880 @@ -52,20 +76,20 @@ inline bool is_saturated(float2 a) { return is_saturated(a.x) && is_saturated(a. inline bool is_saturated(float3 a) { return is_saturated(a.x) && is_saturated(a.y) && is_saturated(a.z); } inline bool is_saturated(float4 a) { return is_saturated(a.x) && is_saturated(a.y) && is_saturated(a.z) && is_saturated(a.w); } -#define DEGAMMA_SKY(x) pow(abs(x),g_xFrame_StaticSkyGamma) -#define DEGAMMA(x) pow(abs(x),g_xFrame_Gamma) -#define GAMMA(x) pow(abs(x),1.0/g_xFrame_Gamma) +#define DEGAMMA_SKY(x) pow(abs(x),g_xFrame.StaticSkyGamma) +#define DEGAMMA(x) pow(abs(x),g_xFrame.Gamma) +#define GAMMA(x) pow(abs(x),1.0/g_xFrame.Gamma) -inline float3 GetSunColor() { return g_xFrame_SunColor; } -inline float3 GetSunDirection() { return g_xFrame_SunDirection; } -inline float GetSunEnergy() { return g_xFrame_SunEnergy; } -inline float3 GetHorizonColor() { return g_xFrame_Horizon.rgb; } -inline float3 GetZenithColor() { return g_xFrame_Zenith.rgb; } -inline float3 GetAmbientColor() { return g_xFrame_Ambient.rgb; } -inline float2 GetInternalResolution() { return g_xFrame_InternalResolution; } -inline float GetTime() { return g_xFrame_Time; } -inline uint2 GetTemporalAASampleRotation() { return uint2((g_xFrame_TemporalAASampleRotation >> 0u) & 0x000000FF, (g_xFrame_TemporalAASampleRotation >> 8) & 0x000000FF); } -inline bool IsStaticSky() { return g_xFrame_StaticSkyGamma > 0.0; } +inline float3 GetSunColor() { return g_xFrame.SunColor; } +inline float3 GetSunDirection() { return g_xFrame.SunDirection; } +inline float GetSunEnergy() { return g_xFrame.SunEnergy; } +inline float3 GetHorizonColor() { return g_xFrame.Horizon.rgb; } +inline float3 GetZenithColor() { return g_xFrame.Zenith.rgb; } +inline float3 GetAmbientColor() { return g_xFrame.Ambient.rgb; } +inline float2 GetInternalResolution() { return g_xFrame.InternalResolution; } +inline float GetTime() { return g_xFrame.Time; } +inline uint2 GetTemporalAASampleRotation() { return uint2((g_xFrame.TemporalAASampleRotation >> 0u) & 0x000000FF, (g_xFrame.TemporalAASampleRotation >> 8) & 0x000000FF); } +inline bool IsStaticSky() { return g_xFrame.scene.globalenvmap >= 0; } // Exponential height fog based on: https://www.iquilezles.org/www/articles/fog/fog.htm // Non constant density function @@ -74,12 +98,12 @@ inline bool IsStaticSky() { return g_xFrame_StaticSkyGamma > 0.0; } // V : sample to point vector inline float GetFogAmount(float distance, float3 O, float3 V) { - float fogDensity = saturate((distance - g_xFrame_Fog.x) / (g_xFrame_Fog.y - g_xFrame_Fog.x)); + float fogDensity = saturate((distance - g_xFrame.Fog.x) / (g_xFrame.Fog.y - g_xFrame.Fog.x)); - if (g_xFrame_Options & OPTION_BIT_HEIGHT_FOG) + if (g_xFrame.Options & OPTION_BIT_HEIGHT_FOG) { - float fogHeightStart = g_xFrame_Fog.z; - float fogHeightEnd = g_xFrame_Fog.w; + float fogHeightStart = g_xFrame.Fog.z; + float fogHeightEnd = g_xFrame.Fog.w; float fogFalloffScale = 1.0 / max(0.01, fogHeightEnd - fogHeightStart); // solve for x, e^(-h * x) = 0.001 @@ -121,11 +145,11 @@ float3 inverseTonemap(float3 x) inline float4 blue_noise(uint2 pixel) { - return frac(texture_bluenoise[pixel % 128].rgba + g_xFrame_BlueNoisePhase); + return frac(texture_bluenoise[pixel % 128].rgba + g_xFrame.BlueNoisePhase); } inline float4 blue_noise(uint2 pixel, float depth) { - return frac(texture_bluenoise[pixel % 128].rgba + g_xFrame_BlueNoisePhase + depth); + return frac(texture_bluenoise[pixel % 128].rgba + g_xFrame.BlueNoisePhase + depth); } // Helpers: @@ -267,7 +291,7 @@ inline float getLinearDepth(in float z, in float near, in float far) } inline float getLinearDepth(in float z) { - return getLinearDepth(z, g_xCamera_ZNearP, g_xCamera_ZFarP); + return getLinearDepth(z, g_xCamera.ZNearP, g_xCamera.ZFarP); } inline float3x3 GetTangentSpace(in float3 normal) @@ -322,7 +346,7 @@ inline float3 reconstructPosition(in float2 uv, in float z, in float4x4 InvVP) } inline float3 reconstructPosition(in float2 uv, in float z) { - return reconstructPosition(uv, z, g_xCamera_InvVP); + return reconstructPosition(uv, z, g_xCamera.InvVP); } #if 0 @@ -578,6 +602,49 @@ inline uint morton3D(in float3 pos) } +// Octahedral encodings: +// Journal of Computer Graphics Techniques Vol. 3, No. 2, 2014 http://jcgt.org + +// Returns +/-1 +float2 signNotZero(float2 v) +{ + return float2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0); +} +// Assume normalized input. Output is on [-1, 1] for each component. +float2 encode_oct(in float3 v) +{ + // Project the sphere onto the octahedron, and then onto the xy plane + float2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + abs(v.z))); + // Reflect the folds of the lower hemisphere over the diagonals + return (v.z <= 0.0) ? ((1.0 - abs(p.yx)) * signNotZero(p)) : p; +} +float3 decode_oct(float2 e) +{ + float3 v = float3(e.xy, 1.0 - abs(e.x) - abs(e.y)); + if (v.z < 0) v.xy = (1.0 - abs(v.yx)) * signNotZero(v.xy); + return normalize(v); +} + +// Assume normalized input on +Z hemisphere. +// Output is on [-1, 1]. +float2 encode_hemioct(in float3 v) +{ + // Project the hemisphere onto the hemi-octahedron, + // and then into the xy plane + float2 p = v.xy * (1.0 / (abs(v.x) + abs(v.y) + v.z)); + // Rotate and scale the center diamond to the unit square + return float2(p.x + p.y, p.x - p.y); +} +float3 decode_hemioct(float2 e) +{ + // Rotate and scale the unit square back to the center diamond + float2 temp = float2(e.x + e.y, e.x - e.y) * 0.5; + float3 v = float3(temp, 1.0 - abs(temp.x) - abs(temp.y)); + return normalize(v); +} + + + static const float2x2 BayerMatrix2 = { @@ -715,6 +782,21 @@ float3 ClosestPointOnSegment(float3 a, float3 b, float3 c) return a + saturate(t) * ab; } +// Compute barycentric coordinates on triangle from a point p +float2 compute_barycentrics(float3 p, float3 a, float3 b, float3 c) +{ + float3 v0 = b - a, v1 = c - a, v2 = p - a; + float d00 = dot(v0, v0); + float d01 = dot(v0, v1); + float d11 = dot(v1, v1); + float d20 = dot(v2, v0); + float d21 = dot(v2, v1); + float denom_rcp = rcp(d00 * d11 - d01 * d01); + float u = (d11 * d20 - d01 * d21) * denom_rcp; + float v = (d00 * d21 - d01 * d20) * denom_rcp; + return float2(u, v); +} + static const float4 halton64[] = { float4(0.5000000000f, 0.3333333333f, 0.2000000000f, 0.1428571429f), float4(0.2500000000f, 0.6666666667f, 0.4000000000f, 0.2857142857f), diff --git a/WickedEngine/shaders/hairparticleHF.hlsli b/WickedEngine/shaders/hairparticleHF.hlsli index 9b199d282..b998434e0 100644 --- a/WickedEngine/shaders/hairparticleHF.hlsli +++ b/WickedEngine/shaders/hairparticleHF.hlsli @@ -1,15 +1,29 @@ #ifndef WI_HAIRPARTICLE_HF #define WI_HAIRPARTICLE_HF +#include "globals.hlsli" +#include "ShaderInterop_HairParticle.h" + +ShaderMeshInstance HairGetInstance() +{ + return load_instance(xHairInstanceIndex); +} +ShaderMesh HairGetMesh() +{ + return load_mesh(HairGetInstance().meshIndex); +} +ShaderMaterial HairGetMaterial() +{ + return load_material(load_subset(HairGetMesh(), 0).materialIndex); +} struct VertexToPixel { float4 pos : SV_POSITION; + float2 tex : TEXCOORD; + nointerpolation float fade : DITHERFADE; + uint primitiveID : PRIMITIVEID; float3 pos3D : POSITION3D; float3 nor : NORMAL; - float2 tex : TEXCOORD; - float fade : DITHERFADE; - float4 pos2DPrev : SCREENPOSITIONPREV; - float3 color : COLOR; }; #endif // WI_HAIRPARTICLE_HF diff --git a/WickedEngine/shaders/hairparticlePS.hlsl b/WickedEngine/shaders/hairparticlePS.hlsl index 16f0392c8..2f8b21fe1 100644 --- a/WickedEngine/shaders/hairparticlePS.hlsl +++ b/WickedEngine/shaders/hairparticlePS.hlsl @@ -5,25 +5,32 @@ #include "objectHF.hlsli" #include "hairparticleHF.hlsli" -TEXTURE2D(texture_color, float4, TEXSLOT_ONDEMAND0); - [earlydepthstencil] -GBuffer main(VertexToPixel input) +float4 main(VertexToPixel input) : SV_Target { - float4 color = texture_color.Sample(sampler_linear_wrap, input.tex); - color.rgb = DEGAMMA(color.rgb); - color.rgb *= input.color; + ShaderMaterial material = HairGetMaterial(); + + float4 color = 1; + + [branch] + if (material.texture_basecolormap_index >= 0 && (g_xFrame.Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) + { + color = bindless_textures[material.texture_basecolormap_index].Sample(sampler_linear_wrap, input.tex); + color.rgb = DEGAMMA(color.rgb); + } + color *= material.baseColor; + float opacity = 1; - float3 V = g_xCamera_CamPos - input.pos3D; + float3 V = g_xCamera.CamPos - input.pos3D; float dist = length(V); V /= dist; float emissive = 0; const uint2 pixel = input.pos.xy; - const float2 ScreenCoord = pixel * g_xFrame_InternalResolution_rcp; + const float2 ScreenCoord = pixel * g_xFrame.InternalResolution_rcp; Surface surface; - surface.create(g_xMaterial, color, 0); + surface.create(material, color, 0); surface.P = input.pos3D; surface.N = input.nor; surface.V = V; @@ -47,9 +54,10 @@ GBuffer main(VertexToPixel input) TiledLighting(surface, lighting); + ApplyLighting(surface, lighting, color); - ApplyFog(dist, g_xCamera_CamPos, V, color); + ApplyFog(dist, g_xCamera.CamPos, V, color); - return CreateGBuffer(color, surface); + return color; } diff --git a/WickedEngine/shaders/hairparticlePS_prepass.hlsl b/WickedEngine/shaders/hairparticlePS_prepass.hlsl index 8d2838f4d..c31f270bc 100644 --- a/WickedEngine/shaders/hairparticlePS_prepass.hlsl +++ b/WickedEngine/shaders/hairparticlePS_prepass.hlsl @@ -1,26 +1,34 @@ #include "globals.hlsli" +#include "objectHF.hlsli" #include "hairparticleHF.hlsli" +#include "ShaderInterop_HairParticle.h" -TEXTURE2D(texture_color, float4, TEXSLOT_ONDEMAND0); - -float2 main(VertexToPixel input) : SV_TARGET +uint2 main(VertexToPixel input) : SV_TARGET { + ShaderMaterial material = HairGetMaterial(); + const float lineardepth = input.pos.w; clip(dither(input.pos.xy + GetTemporalAASampleRotation()) - input.fade); - float4 color = texture_color.Sample(sampler_linear_clamp,input.tex); + float4 color = 1; - float alphatest = g_xMaterial.alphaTest; - if (g_xFrame_Options & OPTION_BIT_TEMPORALAA_ENABLED) + [branch] + if (material.texture_basecolormap_index >= 0) + { + color = bindless_textures[material.texture_basecolormap_index].Sample(sampler_linear_clamp, input.tex); + } + + float alphatest = material.alphaTest; + if (g_xFrame.Options & OPTION_BIT_TEMPORALAA_ENABLED) { alphatest = clamp(blue_noise(input.pos.xy, lineardepth).r, 0, 0.99); } clip(color.a - alphatest); - float2 ScreenCoord = input.pos.xy * g_xFrame_InternalResolution_rcp; - float2 pos2D = ScreenCoord * 2 - 1; - pos2D.y *= -1; - float2 velocity = ((input.pos2DPrev.xy / input.pos2DPrev.w - g_xFrame_TemporalAAJitterPrev) - (pos2D.xy - g_xFrame_TemporalAAJitter)) * float2(0.5f, -0.5f); - return velocity; + PrimitiveID prim; + prim.primitiveIndex = input.primitiveID; + prim.instanceIndex = xHairInstanceIndex; + prim.subsetIndex = 0; + return prim.pack(); } diff --git a/WickedEngine/shaders/hairparticlePS_simple.hlsl b/WickedEngine/shaders/hairparticlePS_simple.hlsl index a20d54300..85d2f4dd7 100644 --- a/WickedEngine/shaders/hairparticlePS_simple.hlsl +++ b/WickedEngine/shaders/hairparticlePS_simple.hlsl @@ -3,5 +3,7 @@ float4 main(VertexToPixel input) : SV_TARGET { - return float4(input.color, 1.0f); -} \ No newline at end of file + ShaderMaterial material = HairGetMaterial(); + + return material.baseColor; +} diff --git a/WickedEngine/shaders/hairparticleVS.hlsl b/WickedEngine/shaders/hairparticleVS.hlsl index bbe86317f..9c364f802 100644 --- a/WickedEngine/shaders/hairparticleVS.hlsl +++ b/WickedEngine/shaders/hairparticleVS.hlsl @@ -2,105 +2,30 @@ #include "hairparticleHF.hlsli" #include "ShaderInterop_HairParticle.h" -static const float3 HAIRPATCH[] = { - float3(-1, -1, 0), - float3(1, -1, 0), - float3(-1, 1, 0), - float3(1, 1, 0), -}; +TYPEDBUFFER(primitiveBuffer, uint, 0); -STRUCTUREDBUFFER(particleBuffer, Patch, 0); -STRUCTUREDBUFFER(culledIndexBuffer, uint, 1); - -VertexToPixel main(uint vertexID : SV_VERTEXID, uint instanceID : SV_INSTANCEID) +VertexToPixel main(uint vid : SV_VERTEXID) { + ShaderMesh mesh = HairGetMesh(); + VertexToPixel Out; + Out.primitiveID = vid / 3; - const uint particleID = culledIndexBuffer[instanceID]; - const uint segmentID = particleID % xHairSegmentCount; + uint vertexID = primitiveBuffer[vid]; + uint4 data = bindless_buffers[mesh.vb_pos_nor_wind].Load4(vertexID * 16); + float3 position = asfloat(data.xyz); + float3 normal = normalize(unpack_unitvector(data.w)); + float2 uv = unpack_half2(bindless_buffers[mesh.vb_uv0].Load(vertexID * 4)); - float3 rootposition = particleBuffer[particleID - segmentID].position; - Out.fade = saturate(distance(rootposition.xyz, g_xCamera_CamPos.xyz) / xHairViewDistance); + Out.fade = saturate(distance(position.xyz, g_xCamera.CamPos.xyz) / xHairViewDistance); Out.fade = saturate(Out.fade - 0.8f) * 5.0f; // fade will be on edge and inwards 20% - [branch] - if (Out.fade < 1.0 - 1.0f / 255.0f) - { - uint tangent_random = particleBuffer[particleID].tangent_random; - float3 normal = particleBuffer[particleID].normal; - uint binormal_length = particleBuffer[particleID].binormal_length; + Out.pos = float4(position, 1); + Out.pos3D = Out.pos.xyz; + Out.pos = mul(g_xCamera.VP, Out.pos); - float3 tangent; - tangent.x = (tangent_random >> 0) & 0x000000FF; - tangent.y = (tangent_random >> 8) & 0x000000FF; - tangent.z = (tangent_random >> 16) & 0x000000FF; - tangent = tangent / 255.0f * 2 - 1; - - uint rand = (tangent_random >> 24) & 0x000000FF; - - float3 binormal; - binormal.x = (binormal_length >> 0) & 0x000000FF; - binormal.y = (binormal_length >> 8) & 0x000000FF; - binormal.z = (binormal_length >> 16) & 0x000000FF; - binormal = binormal / 255.0f * 2 - 1; - - float len = (binormal_length >> 24) & 0x000000FF; - len /= 255.0f; - len *= xLength; - - // expand the particle into a billboard cross section, the patch: - float3 patchPos = HAIRPATCH[vertexID]; - float2 uv = vertexID < 6 ? patchPos.xy : patchPos.zy; - uv = uv * float2(0.5f, 0.5f) + 0.5f; - uv.y = lerp((float)segmentID / (float)xHairSegmentCount, ((float)segmentID + 1) / (float)xHairSegmentCount, uv.y); - uv.y = 1 - uv.y; - patchPos.y += 1; - - // Sprite sheet UV transform: - const uint currentFrame = (xHairFrameStart + rand) % xHairFrameCount; - uint2 offset = uint2(currentFrame % xHairFramesXY.x, currentFrame / xHairFramesXY.x); - uv.xy += offset; - uv.xy *= xHairTexMul; - - // scale the billboard by the texture aspect: - float2 frame = float2(xHairAspect, 1); - frame.xy *= len; - patchPos.xyz *= frame.xyx * 0.5f; - - // simplistic wind effect only affects the top, but leaves the base as is: - const float waveoffset = dot(rootposition, g_xFrame_WindDirection) * g_xFrame_WindWaveSize + rand / 255.0f * g_xFrame_WindRandomness; - const float3 wavedir = g_xFrame_WindDirection * (segmentID + patchPos.y); - const float3 wind = sin(g_xFrame_Time * g_xFrame_WindSpeed + waveoffset) * wavedir; - const float3 windPrev = sin(g_xFrame_TimePrev * g_xFrame_WindSpeed + waveoffset) * wavedir; - - // rotate the patch into the tangent space of the emitting triangle: - float3x3 TBN = float3x3(tangent, normal, binormal); // don't derive binormal, because we want the shear! - patchPos = mul(patchPos, TBN); - - // inset to the emitter a bit, to avoid disconnect: - float3 position = particleBuffer[particleID].position; - position.xyz -= normal * 0.1 * len; - - - // copy to output: - Out.pos = float4(position, 1); - Out.pos.xyz += patchPos; - float3 savedPos = Out.pos.xyz; - Out.pos.xyz += wind; - Out.pos3D = Out.pos.xyz; - Out.pos = mul(g_xCamera_VP, Out.pos); - - Out.nor = normalize(normal + wind); - Out.tex = uv; - - Out.pos2DPrev = mul(g_xCamera_PrevVP, float4(savedPos + windPrev, 1)); - - Out.color = xColor.rgb; - } - else - { - Out = (VertexToPixel)0; - } + Out.nor = normalize(normal); + Out.tex = uv; return Out; } diff --git a/WickedEngine/shaders/hairparticle_finishUpdateCS.hlsl b/WickedEngine/shaders/hairparticle_finishUpdateCS.hlsl index 7ccbabf1a..892d6b55f 100644 --- a/WickedEngine/shaders/hairparticle_finishUpdateCS.hlsl +++ b/WickedEngine/shaders/hairparticle_finishUpdateCS.hlsl @@ -13,6 +13,6 @@ void main( uint3 DTid : SV_DispatchThreadID ) // Reset counter for next frame: counterBuffer.Store(0, 0); - // Create draw argument buffer (VertexCountPerInstance, InstanceCount, StartVertexLocation, StartInstanceLocation): - counterBuffer.Store4(4, uint4(4, particleCount, 0, 0)); + // Create draw argument buffer (IndexCountPerInstance, InstanceCount, StartIndexLocation, BaseVertexLocation, StartInstanceLocation): + counterBuffer.Store4(4, uint4(particleCount * 6, 1, 0, 0)); } diff --git a/WickedEngine/shaders/hairparticle_simulateCS.hlsl b/WickedEngine/shaders/hairparticle_simulateCS.hlsl index bcdda002c..09d844526 100644 --- a/WickedEngine/shaders/hairparticle_simulateCS.hlsl +++ b/WickedEngine/shaders/hairparticle_simulateCS.hlsl @@ -1,10 +1,20 @@ #include "globals.hlsli" +#include "hairparticleHF.hlsli" #include "ShaderInterop_HairParticle.h" -RWSTRUCTUREDBUFFER(particleBuffer, Patch, 0); -RWSTRUCTUREDBUFFER(simulationBuffer, PatchSimulationData, 1); -RWSTRUCTUREDBUFFER(indexBuffer, uint, 2); -RWRAWBUFFER(counterBuffer, 3); +static const float3 HAIRPATCH[] = { + float3(-1, -1, 0), + float3(1, -1, 0), + float3(-1, 1, 0), + float3(1, 1, 0), +}; + +RWSTRUCTUREDBUFFER(simulationBuffer, PatchSimulationData, 0); +RWRAWBUFFER(vertexBuffer_POS, 1); +RWRAWBUFFER(vertexBuffer_TEX, 2); +RWTYPEDBUFFER(primitiveBuffer, uint, 3); +RWTYPEDBUFFER(culledIndexBuffer, uint, 4); +RWRAWBUFFER(counterBuffer, 5); TYPEDBUFFER(meshIndexBuffer, uint, TEXSLOT_ONDEMAND0); RAWBUFFER(meshVertexBuffer_POS, TEXSLOT_ONDEMAND1); @@ -73,8 +83,8 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIn const uint strandID = DTid.x * xHairSegmentCount; // Transform particle by the emitter object matrix: - float3 base = mul(xWorld, float4(position.xyz, 1)).xyz; - target = normalize(mul((float3x3)xWorld, target)); + float3 base = mul(xHairWorld, float4(position.xyz, 1)).xyz; + target = normalize(mul((float3x3)xHairWorld, target)); const float3 root = base; float3 normal = 0; @@ -83,17 +93,17 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIn { // Identifies the hair strand segment particle: const uint particleID = strandID + segmentID; - particleBuffer[particleID].tangent_random = tangent_random; - particleBuffer[particleID].binormal_length = binormal_length; + simulationBuffer[particleID].tangent_random = tangent_random; + simulationBuffer[particleID].binormal_length = binormal_length; if (xHairRegenerate) { - particleBuffer[particleID].position = base; - particleBuffer[particleID].normal = target; + simulationBuffer[particleID].position = base; + simulationBuffer[particleID].normal = target; simulationBuffer[particleID].velocity = 0; } - normal += particleBuffer[particleID].normal; + normal += simulationBuffer[particleID].normal; normal = normalize(normal); float len = (binormal_length >> 24) & 0x000000FF; @@ -104,9 +114,9 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIn // Accumulate forces: float3 force = 0; - for (uint i = 0; i < g_xFrame_ForceFieldArrayCount; ++i) + for (uint i = 0; i < g_xFrame.ForceFieldArrayCount; ++i) { - ShaderEntity forceField = EntityArray[g_xFrame_ForceFieldArrayOffset + i]; + ShaderEntity forceField = EntityArray[g_xFrame.ForceFieldArrayOffset + i]; [branch] if (forceField.layerMask & xHairLayerMask) @@ -132,50 +142,110 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint groupIn // Pull back to rest position: force += (target - normal) * xStiffness; - force *= g_xFrame_DeltaTime; + force *= g_xFrame.DeltaTime; // Simulation buffer load: float3 velocity = simulationBuffer[particleID].velocity; // Apply surface-movement-based velocity: - const float3 old_base = particleBuffer[particleID].position; - const float3 old_normal = particleBuffer[particleID].normal; + const float3 old_base = simulationBuffer[particleID].position; + const float3 old_normal = simulationBuffer[particleID].normal; const float3 old_tip = old_base + old_normal * len; const float3 surface_velocity = old_tip - tip; velocity += surface_velocity; // Apply forces: velocity += force; - normal += velocity * g_xFrame_DeltaTime; + normal += velocity * g_xFrame.DeltaTime; // Drag: velocity *= 0.98f; // Store particle: - particleBuffer[particleID].position = base; - particleBuffer[particleID].normal = normalize(normal); + simulationBuffer[particleID].position = base; + simulationBuffer[particleID].normal = normalize(normal); // Store simulation data: simulationBuffer[particleID].velocity = velocity; - // Offset next segment root to current tip: - base = tip; + // Write out render buffers: + // These must be persistent, not culled (raytracing, surfels...) + uint v0 = particleID * 4; + uint i0 = particleID * 6; + primitiveBuffer[i0 + 0] = v0 + 0; + primitiveBuffer[i0 + 1] = v0 + 1; + primitiveBuffer[i0 + 2] = v0 + 2; + primitiveBuffer[i0 + 3] = v0 + 2; + primitiveBuffer[i0 + 4] = v0 + 1; + primitiveBuffer[i0 + 5] = v0 + 3; + + uint rand = (tangent_random >> 24) & 0x000000FF; + float3x3 TBN = float3x3(tangent, normal, binormal); // don't derive binormal, because we want the shear! + float3 rootposition = base - normal * 0.1 * len; // inset to the emitter a bit, to avoid disconnect: + float2 frame = float2(xHairAspect, 1) * len * 0.5; + const uint currentFrame = (xHairFrameStart + rand) % xHairFrameCount; + uint2 offset = uint2(currentFrame % xHairFramesXY.x, currentFrame / xHairFramesXY.x); + + for (uint vertexID = 0; vertexID < 4; ++vertexID) + { + // expand the particle into a billboard cross section, the patch: + float3 patchPos = HAIRPATCH[vertexID]; + float2 uv = vertexID < 6 ? patchPos.xy : patchPos.zy; + uv = uv * float2(0.5f, 0.5f) + 0.5f; + uv.y = lerp((float)segmentID / (float)xHairSegmentCount, ((float)segmentID + 1) / (float)xHairSegmentCount, uv.y); + uv.y = 1 - uv.y; + patchPos.y += 1; + + // Sprite sheet UV transform: + uv.xy += offset; + uv.xy *= xHairTexMul; + + // scale the billboard by the texture aspect: + patchPos.xyz *= frame.xyx; + + // rotate the patch into the tangent space of the emitting triangle: + patchPos = mul(patchPos, TBN); + + // simplistic wind effect only affects the top, but leaves the base as is: + const float waveoffset = dot(rootposition, g_xFrame.WindDirection) * g_xFrame.WindWaveSize + rand / 255.0f * g_xFrame.WindRandomness; + const float3 wavedir = g_xFrame.WindDirection * (segmentID + patchPos.y); + const float3 wind = sin(g_xFrame.Time * g_xFrame.WindSpeed + waveoffset) * wavedir; + + float3 position = rootposition + patchPos + wind; + + uint4 data; + data.xyz = asuint(position); + data.w = pack_unitvector(normalize(normal + wind)); + vertexBuffer_POS.Store4((v0 + vertexID) * 16, data); + vertexBuffer_TEX.Store((v0 + vertexID) * 4, pack_half2(uv)); + } // Frustum culling: uint infrustum = 1; - infrustum &= distance(base, g_xCamera_CamPos.xyz) < xHairViewDistance; - infrustum &= dot(g_xCamera_FrustumPlanes[0], float4(base, 1)) > -len; - infrustum &= dot(g_xCamera_FrustumPlanes[2], float4(base, 1)) > -len; - infrustum &= dot(g_xCamera_FrustumPlanes[3], float4(base, 1)) > -len; - infrustum &= dot(g_xCamera_FrustumPlanes[4], float4(base, 1)) > -len; - infrustum &= dot(g_xCamera_FrustumPlanes[5], float4(base, 1)) > -len; + float3 center = (base + tip) * 0.5; + float radius = -len; + infrustum &= distance(base, g_xCamera.CamPos.xyz) < xHairViewDistance; + infrustum &= dot(g_xCamera.FrustumPlanes[0], float4(center, 1)) > radius; + infrustum &= dot(g_xCamera.FrustumPlanes[2], float4(center, 1)) > radius; + infrustum &= dot(g_xCamera.FrustumPlanes[3], float4(center, 1)) > radius; + infrustum &= dot(g_xCamera.FrustumPlanes[4], float4(center, 1)) > radius; + infrustum &= dot(g_xCamera.FrustumPlanes[5], float4(center, 1)) > radius; if (infrustum) { uint prevCount; counterBuffer.InterlockedAdd(0, 1, prevCount); - indexBuffer[prevCount] = particleID; + uint ii0 = prevCount * 6; + culledIndexBuffer[ii0 + 0] = i0 + 0; + culledIndexBuffer[ii0 + 1] = i0 + 1; + culledIndexBuffer[ii0 + 2] = i0 + 2; + culledIndexBuffer[ii0 + 3] = i0 + 3; + culledIndexBuffer[ii0 + 4] = i0 + 4; + culledIndexBuffer[ii0 + 5] = i0 + 5; } + + // Offset next segment root to current tip: + base = tip; } } diff --git a/WickedEngine/shaders/hbaoCS.hlsl b/WickedEngine/shaders/hbaoCS.hlsl index e040ad963..f1b36ad0f 100644 --- a/WickedEngine/shaders/hbaoCS.hlsl +++ b/WickedEngine/shaders/hbaoCS.hlsl @@ -89,7 +89,7 @@ void main(uint3 Gid : SV_GroupID, uint groupIndex : SV_GroupIndex) { const uint2 pixel = tile_start + hbao_direction * (i - TILE_BORDER); const float2 uv = (pixel + 0.5f) * xPPResolution_rcp; - const float z = texture_lineardepth.Load(uint3(tile_start + hbao_direction * (i - TILE_BORDER), 1)) * g_xCamera_ZFarP; + const float z = texture_lineardepth.Load(uint3(tile_start + hbao_direction * (i - TILE_BORDER), 1)) * g_xCamera.ZFarP; const float2 xy = (hbao_uv_to_view_A * uv + hbao_uv_to_view_B) * z; cache[i] = float2(horizontal ? xy.x : xy.y, z); } @@ -97,7 +97,7 @@ void main(uint3 Gid : SV_GroupID, uint groupIndex : SV_GroupIndex) const uint2 pixel = tile_start + groupIndex * hbao_direction; const int center = TILE_BORDER + groupIndex; - if (pixel.x >= xPPResolution.x || pixel.y >= xPPResolution.y || cache[center].y >= g_xCamera_ZFarP - 0.99) + if (pixel.x >= xPPResolution.x || pixel.y >= xPPResolution.y || cache[center].y >= g_xCamera.ZFarP - 0.99) { return; } diff --git a/WickedEngine/shaders/imageHF.hlsli b/WickedEngine/shaders/imageHF.hlsli index 59cda07af..07c72c771 100644 --- a/WickedEngine/shaders/imageHF.hlsli +++ b/WickedEngine/shaders/imageHF.hlsli @@ -3,21 +3,6 @@ #include "globals.hlsli" #include "ShaderInterop_Image.h" -#ifdef BINDLESS -PUSHCONSTANT(push, PushConstantsImage); -Texture2D bindless_textures[] : register(space1); -SamplerState bindless_samplers[] : register(space2); -#define texture_base bindless_textures[push.texture_base_index] -#define texture_mask bindless_textures[push.texture_mask_index] -#define texture_background bindless_textures[push.texture_background_index] -#define Sampler bindless_samplers[push.sampler_index] -#else -TEXTURE2D(texture_base, float4, TEXSLOT_IMAGE_BASE); -TEXTURE2D(texture_mask, float4, TEXSLOT_IMAGE_MASK); -TEXTURE2D(texture_background, float4, TEXSLOT_IMAGE_BACKGROUND); -SAMPLERSTATE(Sampler, SSLOT_ONDEMAND0); -#endif // BINDLESS - float Wedge2D(float2 v, float2 w) { return v.x * w.y - v.y * w.x; @@ -62,8 +47,8 @@ struct VertextoPixel else uv.x = (q.y - b2.y * uv.y) / denom.y; - float2 uv0 = uv * xTexMulAdd.xy + xTexMulAdd.zw; - float2 uv1 = uv * xTexMulAdd2.xy + xTexMulAdd2.zw; + float2 uv0 = uv * push.texMulAdd.xy + push.texMulAdd.zw; + float2 uv1 = uv * push.texMulAdd2.xy + push.texMulAdd2.zw; return float4(uv0, uv1); } }; diff --git a/WickedEngine/shaders/imagePS.hlsl b/WickedEngine/shaders/imagePS.hlsl index b09a18f59..fbe4b8770 100644 --- a/WickedEngine/shaders/imagePS.hlsl +++ b/WickedEngine/shaders/imagePS.hlsl @@ -2,8 +2,38 @@ float4 main(VertextoPixel input) : SV_TARGET { + SamplerState sam = bindless_samplers[push.sampler_index]; + float4 uvsets = input.compute_uvs(); - float4 color = texture_base.Sample(Sampler, uvsets.xy) * xColor; + + float4 color = unpack_half4(push.packed_color); + [branch] + if (push.texture_base_index >= 0) + { + float4 tex = bindless_textures[push.texture_base_index].Sample(sam, uvsets.xy); + + if (push.flags & IMAGE_FLAG_EXTRACT_NORMALMAP) + { + tex.rgb = tex.rgb * 2 - 1; + } + + color *= tex; + } + + float4 mask = 1; + [branch] + if (push.texture_mask_index >= 0) + { + mask = bindless_textures[push.texture_mask_index].Sample(sam, uvsets.zw); + } + color *= mask; + + [branch] + if (push.texture_background_index >= 0) + { + float3 background = bindless_textures[push.texture_background_index].Sample(sam, (input.uv_screen.xy * float2(0.5f, -0.5f) + 0.5f) / input.uv_screen.w).rgb; + color = float4(lerp(background, color.rgb, color.a), mask.a); + } return color; } diff --git a/WickedEngine/shaders/imagePS_backgroundblur.hlsl b/WickedEngine/shaders/imagePS_backgroundblur.hlsl deleted file mode 100644 index 7515cb885..000000000 --- a/WickedEngine/shaders/imagePS_backgroundblur.hlsl +++ /dev/null @@ -1,10 +0,0 @@ -#include "imageHF.hlsli" - -float4 main(VertextoPixel input) : SV_TARGET -{ - float4 uvsets = input.compute_uvs(); - float4 color = texture_base.Sample(Sampler, uvsets.xy) * xColor; - float3 background = texture_background.Sample(Sampler, (input.uv_screen.xy * float2(0.5f, -0.5f) + 0.5f) / input.uv_screen.w).rgb; - - return float4(lerp(background, color.rgb, color.a), 1); -} diff --git a/WickedEngine/shaders/imagePS_backgroundblur_masked.hlsl b/WickedEngine/shaders/imagePS_backgroundblur_masked.hlsl deleted file mode 100644 index f7855fa9b..000000000 --- a/WickedEngine/shaders/imagePS_backgroundblur_masked.hlsl +++ /dev/null @@ -1,12 +0,0 @@ -#include "imageHF.hlsli" - -float4 main(VertextoPixel input) : SV_TARGET -{ - float4 uvsets = input.compute_uvs(); - float4 color = texture_base.Sample(Sampler, uvsets.xy) * xColor; - float3 background = texture_background.Sample(Sampler, (input.uv_screen.xy * float2(0.5f, -0.5f) + 0.5f) / input.uv_screen.w).rgb; - float4 mask = texture_mask.Sample(Sampler, uvsets.zw); - color *= mask; - - return float4(lerp(background, color.rgb, color.a), mask.a); -} diff --git a/WickedEngine/shaders/imagePS_masked.hlsl b/WickedEngine/shaders/imagePS_masked.hlsl deleted file mode 100644 index b4bce5f13..000000000 --- a/WickedEngine/shaders/imagePS_masked.hlsl +++ /dev/null @@ -1,11 +0,0 @@ -#include "imageHF.hlsli" - -float4 main(VertextoPixel input) : SV_TARGET -{ - float4 uvsets = input.compute_uvs(); - float4 color = texture_base.Sample(Sampler, uvsets.xy) * xColor; - - color *= texture_mask.Sample(Sampler, uvsets.zw); - - return color; -} diff --git a/WickedEngine/shaders/imagePS_separatenormalmap.hlsl b/WickedEngine/shaders/imagePS_separatenormalmap.hlsl deleted file mode 100644 index db9ca2072..000000000 --- a/WickedEngine/shaders/imagePS_separatenormalmap.hlsl +++ /dev/null @@ -1,13 +0,0 @@ -#include "imageHF.hlsli" - -float4 main(VertextoPixel input) : SV_TARGET -{ - float4 uvsets = input.compute_uvs(); - float4 color = texture_base.Sample(Sampler, uvsets.xy); - - color = 2 * color - 1; - - color *= xColor; - - return color; -} diff --git a/WickedEngine/shaders/imagePS_separatenormalmap_bicubic.hlsl b/WickedEngine/shaders/imagePS_separatenormalmap_bicubic.hlsl deleted file mode 100644 index b2dc5b79f..000000000 --- a/WickedEngine/shaders/imagePS_separatenormalmap_bicubic.hlsl +++ /dev/null @@ -1,13 +0,0 @@ -#include "imageHF.hlsli" - -float4 main(VertextoPixel input) : SV_TARGET -{ - float4 uvsets = input.compute_uvs(); - float4 color = SampleTextureCatmullRom(texture_base, Sampler, uvsets.xy); - - color = 2 * color - 1; - - color *= xColor; - - return color; -} diff --git a/WickedEngine/shaders/imageVS.hlsl b/WickedEngine/shaders/imageVS.hlsl index 4501da5ac..47440ee4a 100644 --- a/WickedEngine/shaders/imageVS.hlsl +++ b/WickedEngine/shaders/imageVS.hlsl @@ -11,14 +11,14 @@ VertextoPixel main(uint vI : SV_VERTEXID) // / // 3--4 - Out.pos = xCorners[vI]; + Out.pos = push.corners[vI]; Out.uv_screen = Out.pos; // Set up inverse bilinear interpolation - Out.q = Out.pos.xy - xCorners[0].xy; - Out.b1 = xCorners[1].xy - xCorners[0].xy; - Out.b2 = xCorners[2].xy - xCorners[0].xy; - Out.b3 = xCorners[0].xy - xCorners[1].xy - xCorners[2].xy + xCorners[3].xy; + Out.q = Out.pos.xy - push.corners[0].xy; + Out.b1 = push.corners[1].xy - push.corners[0].xy; + Out.b2 = push.corners[2].xy - push.corners[0].xy; + Out.b3 = push.corners[0].xy - push.corners[1].xy - push.corners[2].xy + push.corners[3].xy; return Out; } diff --git a/WickedEngine/shaders/impostorHF.hlsli b/WickedEngine/shaders/impostorHF.hlsli index abf19fd63..52a3d4a92 100644 --- a/WickedEngine/shaders/impostorHF.hlsli +++ b/WickedEngine/shaders/impostorHF.hlsli @@ -4,11 +4,11 @@ struct VSOut { float4 pos : SV_POSITION; - float3 tex : TEXCOORD; + float2 uv : TEXCOORD; + uint slice : SLICE; nointerpolation float dither : DITHER; float3 pos3D : WORLDPOSITION; - uint instanceColor : INSTANCECOLOR; - float4 pos2DPrev : SCREENPOSITIONPREV; + uint instanceID : INSTANCEID; }; TEXTURE2DARRAY(impostorTex, float4, TEXSLOT_ONDEMAND0); diff --git a/WickedEngine/shaders/impostorPS.hlsl b/WickedEngine/shaders/impostorPS.hlsl index bb194fdf2..e37db430a 100644 --- a/WickedEngine/shaders/impostorPS.hlsl +++ b/WickedEngine/shaders/impostorPS.hlsl @@ -3,15 +3,17 @@ #include "objectHF.hlsli" [earlydepthstencil] -GBuffer main(VSOut input) +float4 main(VSOut input) : SV_Target { - float3 uv_col = input.tex; + float3 uv_col = float3(input.uv, input.slice); float3 uv_nor = uv_col; uv_nor.z += impostorCaptureAngles; float3 uv_sur = uv_nor; uv_sur.z += impostorCaptureAngles; - float4 color = impostorTex.Sample(sampler_linear_clamp, uv_col) * unpack_rgba(input.instanceColor); + ShaderMeshInstance instance = load_instance(input.instanceID); + + float4 color = impostorTex.Sample(sampler_linear_clamp, uv_col) * unpack_rgba(instance.color); float3 N = impostorTex.Sample(sampler_linear_clamp, uv_nor).rgb * 2 - 1; float4 surfaceparams = impostorTex.Sample(sampler_linear_clamp, uv_sur); @@ -20,7 +22,7 @@ GBuffer main(VSOut input) float metalness = surfaceparams.b; float reflectance = surfaceparams.a; - float3 V = g_xCamera_CamPos - input.pos3D; + float3 V = g_xCamera.CamPos - input.pos3D; float dist = length(V); V /= dist; @@ -38,16 +40,11 @@ GBuffer main(VSOut input) Lighting lighting; lighting.create(0, 0, GetAmbient(surface.N), 0); - float2 ScreenCoord = surface.pixel * g_xFrame_InternalResolution_rcp; - float2 pos2D = ScreenCoord * 2 - 1; - pos2D.y *= -1; - float2 velocity = ((input.pos2DPrev.xy / input.pos2DPrev.w - g_xFrame_TemporalAAJitterPrev) - (pos2D.xy - g_xFrame_TemporalAAJitter)) * float2(0.5f, -0.5f); - TiledLighting(surface, lighting); ApplyLighting(surface, lighting, color); - ApplyFog(dist, g_xCamera_CamPos, V, color); + ApplyFog(dist, g_xCamera.CamPos, V, color); - return CreateGBuffer(color, surface); + return color; } diff --git a/WickedEngine/shaders/impostorPS_prepass.hlsl b/WickedEngine/shaders/impostorPS_prepass.hlsl index 56f6e45df..a7c796ea3 100644 --- a/WickedEngine/shaders/impostorPS_prepass.hlsl +++ b/WickedEngine/shaders/impostorPS_prepass.hlsl @@ -1,19 +1,15 @@ #include "globals.hlsli" #include "impostorHF.hlsli" -float4 main(VSOut input) : SV_TARGET +uint2 main(VSOut input) : SV_Target { clip(dither(input.pos.xy + GetTemporalAASampleRotation()) - input.dither); - float3 uv_col = input.tex; + float3 uv_col = float3(input.uv, input.slice); clip(impostorTex.Sample(sampler_linear_clamp, uv_col).a - 0.5f); - const float2 pixel = input.pos.xy; - const float2 ScreenCoord = pixel * g_xFrame_InternalResolution_rcp; - - float2 pos2D = ScreenCoord * 2 - 1; - pos2D.y *= -1; - input.pos2DPrev.xy /= input.pos2DPrev.w; - const float2 velocity = ((input.pos2DPrev.xy - g_xFrame_TemporalAAJitterPrev) - (pos2D.xy - g_xFrame_TemporalAAJitter)) * float2(0.5, -0.5); - - return float4(velocity, 0, 0); + PrimitiveID prim; + prim.primitiveIndex = ~0u; + prim.instanceIndex = input.instanceID; + prim.subsetIndex = 0; + return prim.pack(); } diff --git a/WickedEngine/shaders/impostorPS_simple.hlsl b/WickedEngine/shaders/impostorPS_simple.hlsl index a7fd97970..8701fd5f5 100644 --- a/WickedEngine/shaders/impostorPS_simple.hlsl +++ b/WickedEngine/shaders/impostorPS_simple.hlsl @@ -5,10 +5,10 @@ float4 main(VSOut input) : SV_TARGET { clip(dither(input.pos.xy + GetTemporalAASampleRotation()) - input.dither); - float3 uv_col = input.tex; + float3 uv_col = float3(input.uv, input.slice); - float4 color = impostorTex.Sample(sampler_linear_clamp, uv_col) * unpack_rgba(input.instanceColor); - clip(color.a - 0.5f); + ShaderMeshInstance instance = load_instance(input.instanceID); + float4 color = unpack_rgba(instance.color); return color; } diff --git a/WickedEngine/shaders/impostorVS.hlsl b/WickedEngine/shaders/impostorVS.hlsl index ee8830f76..8138ba739 100644 --- a/WickedEngine/shaders/impostorVS.hlsl +++ b/WickedEngine/shaders/impostorVS.hlsl @@ -1,6 +1,12 @@ #include "globals.hlsli" #include "impostorHF.hlsli" +struct ImpostorPush +{ + uint instanceOffset; +}; +PUSHCONSTANT(push, ImpostorPush); + static const float3 BILLBOARD[] = { float3(-1, -1, 0), float3(1, -1, 0), @@ -10,36 +16,30 @@ static const float3 BILLBOARD[] = { float3(1, 1, 0), }; -RAWBUFFER(instanceBuffer, TEXSLOT_ONDEMAND21); +RAWBUFFER(impostorBuffer, TEXSLOT_ONDEMAND21); VSOut main(uint fakeIndex : SV_VERTEXID) { const uint vertexID = fakeIndex % 6; const uint instanceID = fakeIndex / 6; - uint byteOffset = (uint)g_xColor.x + instanceID * 64; - - float4 mat0 = asfloat(instanceBuffer.Load4(byteOffset + 0)); - float4 mat1 = asfloat(instanceBuffer.Load4(byteOffset + 16)); - float4 mat2 = asfloat(instanceBuffer.Load4(byteOffset + 32)); - uint4 userdata = instanceBuffer.Load4(byteOffset + 48); - - float4x4 WORLD = WORLD = float4x4( - mat0, - mat1, - mat2, - float4(0, 0, 0, 1) - ); + ShaderMeshInstancePointer poi = impostorBuffer.Load(push.instanceOffset + instanceID * 8); + ShaderMeshInstance instance = load_instance(poi.instanceID); + ShaderMesh mesh = load_mesh(instance.meshIndex); + float3 extents = mesh.aabb_max - mesh.aabb_min; + float radius = max(extents.x, max(extents.y, extents.z)) * 0.5; float3 pos = BILLBOARD[vertexID]; - float3 tex = float3(pos.xy * float2(0.5f, -0.5f) + 0.5f, userdata.y); + float2 uv = float2(pos.xy * float2(0.5f, -0.5f) + 0.5f); + uint slice = poi.GetFrustumIndex(); + pos *= radius; // We rotate the billboard to face camera, but unlike emitted particles, // they don't rotate according to camera rotation, but the camera position relative // to the impostor (at least for now) - float3 origin = mul(WORLD, float4(0, 0, 0, 1)).xyz; - float3 up = normalize(mul((float3x3)WORLD, float3(0, 1, 0))); - float3 face = mul((float3x3)WORLD, g_xCamera_CamPos - origin); + float3 origin = mul(instance.transform.GetMatrix(), float4(0, 0, 0, 1)).xyz; + float3 up = normalize(mul((float3x3)instance.transform.GetMatrix(), float3(0, 1, 0))); + float3 face = mul((float3x3)instance.transform.GetMatrix(), g_xCamera.CamPos - origin); face.y = 0; // only rotate around Y axis! face = normalize(face); float3 right = normalize(cross(face, up)); @@ -52,17 +52,16 @@ VSOut main(uint fakeIndex : SV_VERTEXID) angle = 2 - angle; } angle *= 0.5f; - tex.z += floor(angle * impostorCaptureAngles); - - float4 color_dither = unpack_rgba(userdata.x); + angle = saturate(angle - 0.0001); + slice += uint(angle * impostorCaptureAngles); VSOut Out; - Out.pos3D = mul(WORLD, float4(pos, 1)).xyz; - Out.pos = mul(g_xCamera_VP, float4(Out.pos3D, 1)); - Out.tex = tex; - Out.dither = 1 - color_dither.a; - Out.instanceColor = pack_rgba(float4(color_dither.rgb, 1)); - Out.pos2DPrev = mul(g_xCamera_PrevVP, float4(Out.pos3D, 1)); + Out.pos3D = mul(instance.transform.GetMatrix(), float4(pos, 1)).xyz; + Out.pos = mul(g_xCamera.VP, float4(Out.pos3D, 1)); + Out.uv = uv; + Out.slice = slice; + Out.dither = poi.GetDither(); + Out.instanceID = poi.instanceID; return Out; } diff --git a/WickedEngine/shaders/lensFlareVS.hlsl b/WickedEngine/shaders/lensFlareVS.hlsl index 12de86765..c2a76cd28 100644 --- a/WickedEngine/shaders/lensFlareVS.hlsl +++ b/WickedEngine/shaders/lensFlareVS.hlsl @@ -1,5 +1,7 @@ #include "globals.hlsli" +PUSHCONSTANT(push, LensFlarePush); + TEXTURE2D(texture_occlusion, float4, TEXSLOT_ONDEMAND0); static const float2 BILLBOARD[] = { @@ -22,8 +24,8 @@ VertexOut main(uint vertexID : SV_VertexID) Out.uv = BILLBOARD[vertexID] * 0.5f + 0.5f; // determine the flare opacity based on depth buffer occlusion and occlusion mask: - float referenceDepth = saturate(1 - xLensFlarePos.z); - const float2 step = 1.0 / (GetInternalResolution() * xLensFlarePos.z); + float referenceDepth = saturate(1 - push.xLensFlarePos.z); + const float2 step = 1.0 / (GetInternalResolution() * push.xLensFlarePos.z); const float2 range = 10.5 * step; float samples = 0; float visibility = 0; @@ -32,8 +34,8 @@ VertexOut main(uint vertexID : SV_VertexID) for (float x = -range.x; x <= range.x; x += step.x) { samples++; - float vis = texture_occlusion.SampleLevel(sampler_linear_clamp, xLensFlarePos.xy + float2(x, y), 0).r; - vis *= texture_depth.SampleLevel(sampler_point_clamp, xLensFlarePos.xy + float2(x, y), 0).r <= referenceDepth ? 1 : 0; + float vis = texture_occlusion.SampleLevel(sampler_linear_clamp, push.xLensFlarePos.xy + float2(x, y), 0).r; + vis *= texture_depth.SampleLevel(sampler_point_clamp, push.xLensFlarePos.xy + float2(x, y), 0).r <= referenceDepth ? 1 : 0; visibility += vis; } } @@ -41,11 +43,11 @@ VertexOut main(uint vertexID : SV_VertexID) Out.opacity = visibility; - float2 pos = (xLensFlarePos.xy - 0.5) * float2(2, -2); - float2 moddedpos = pos * xLensFlareOffset; + float2 pos = (push.xLensFlarePos.xy - 0.5) * float2(2, -2); + float2 moddedpos = pos * push.xLensFlareOffset; Out.opacity *= saturate(1 - length(pos - moddedpos)); - Out.pos = float4(moddedpos + BILLBOARD[vertexID] * xLensFlareSize * g_xFrame_CanvasSize_rcp, 0, 1); + Out.pos = float4(moddedpos + BILLBOARD[vertexID] * push.xLensFlareSize * g_xFrame.CanvasSize_rcp, 0, 1); return Out; } diff --git a/WickedEngine/shaders/lightCullingCS.hlsl b/WickedEngine/shaders/lightCullingCS.hlsl index b45b8563b..582f05523 100644 --- a/WickedEngine/shaders/lightCullingCS.hlsl +++ b/WickedEngine/shaders/lightCullingCS.hlsl @@ -2,7 +2,7 @@ #include "cullingShaderHF.hlsli" #include "lightingHF.hlsli" -#define entityCount (g_xFrame_LightArrayCount + g_xFrame_DecalArrayCount + g_xFrame_EnvProbeArrayCount) +#define entityCount (g_xFrame.LightArrayCount + g_xFrame.DecalArrayCount + g_xFrame.EnvProbeArrayCount) STRUCTUREDBUFFER(in_Frustums, Frustum, TEXSLOT_ONDEMAND0); @@ -94,7 +94,7 @@ void main(uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : uint i = 0; // Compute addresses and load frustum: - const uint flatTileIndex = flatten2D(Gid.xy, g_xFrame_EntityCullingTileCount.xy); + const uint flatTileIndex = flatten2D(Gid.xy, g_xFrame.EntityCullingTileCount.xy); const uint tileBucketsAddress = flatTileIndex * SHADER_ENTITY_TILE_BUCKET_COUNT; const uint bucketIndex = groupIndex; Frustum GroupFrustum = in_Frustums[flatTileIndex]; @@ -182,7 +182,7 @@ void main(uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : // We can perform coarse AABB intersection tests with this: GroupAABB_WS = GroupAABB; - AABBtransform(GroupAABB_WS, g_xCamera_InvV); + AABBtransform(GroupAABB_WS, g_xCamera.InvV); } // Convert depth values to view space. @@ -223,7 +223,7 @@ void main(uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : { case ENTITY_TYPE_POINTLIGHT: { - float3 positionVS = mul(g_xCamera_View, float4(entity.position, 1)).xyz; + float3 positionVS = mul(g_xCamera.View, float4(entity.position, 1)).xyz; Sphere sphere = { positionVS.xyz, entity.GetRange() }; if (SphereInsideFrustum(sphere, GroupFrustum, nearClipVS, maxDepthVS)) { @@ -243,8 +243,8 @@ void main(uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : break; case ENTITY_TYPE_SPOTLIGHT: { - float3 positionVS = mul(g_xCamera_View, float4(entity.position, 1)).xyz; - float3 directionVS = mul((float3x3)g_xCamera_View, entity.GetDirection()); + float3 positionVS = mul(g_xCamera.View, float4(entity.position, 1)).xyz; + float3 directionVS = mul((float3x3)g_xCamera.View, entity.GetDirection()); // Construct a tight fitting sphere around the spotlight cone: const float r = entity.GetRange() * 0.5f / (entity.GetConeAngleCos() * entity.GetConeAngleCos()); Sphere sphere = { positionVS - directionVS * r, r }; @@ -274,7 +274,7 @@ void main(uint3 Gid : SV_GroupID, uint3 DTid : SV_DispatchThreadID, uint3 GTid : case ENTITY_TYPE_DECAL: case ENTITY_TYPE_ENVMAP: { - float3 positionVS = mul(g_xCamera_View, float4(entity.position, 1)).xyz; + float3 positionVS = mul(g_xCamera.View, float4(entity.position, 1)).xyz; Sphere sphere = { positionVS.xyz, entity.GetRange() }; if (SphereInsideFrustum(sphere, GroupFrustum, nearClipVS, maxDepthVS)) { diff --git a/WickedEngine/shaders/lightingHF.hlsli b/WickedEngine/shaders/lightingHF.hlsli index ca9d08e65..cf1fa7e1b 100644 --- a/WickedEngine/shaders/lightingHF.hlsli +++ b/WickedEngine/shaders/lightingHF.hlsli @@ -50,22 +50,22 @@ inline float3 shadowCascade(in ShaderEntity light, in float3 shadowPos, in float float3 shadow = 0; #ifndef DISABLE_SOFT_SHADOWMAP // sample along a rectangle pattern around center: - shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(-1, -1) * g_xFrame_ShadowKernel2D, slice), realDistance); - shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(-1, 0) * g_xFrame_ShadowKernel2D, slice), realDistance); - shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(-1, 1) * g_xFrame_ShadowKernel2D, slice), realDistance); - shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(0, -1) * g_xFrame_ShadowKernel2D, slice), realDistance); + shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(-1, -1) * g_xFrame.ShadowKernel2D, slice), realDistance); + shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(-1, 0) * g_xFrame.ShadowKernel2D, slice), realDistance); + shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(-1, 1) * g_xFrame.ShadowKernel2D, slice), realDistance); + shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(0, -1) * g_xFrame.ShadowKernel2D, slice), realDistance); shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV, slice), realDistance); - shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(0, 1) * g_xFrame_ShadowKernel2D, slice), realDistance); - shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(1, -1) * g_xFrame_ShadowKernel2D, slice), realDistance); - shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(1, 0) * g_xFrame_ShadowKernel2D, slice), realDistance); - shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(1, 1) * g_xFrame_ShadowKernel2D, slice), realDistance); + shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(0, 1) * g_xFrame.ShadowKernel2D, slice), realDistance); + shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(1, -1) * g_xFrame.ShadowKernel2D, slice), realDistance); + shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(1, 0) * g_xFrame.ShadowKernel2D, slice), realDistance); + shadow.x += texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV + float2(1, 1) * g_xFrame.ShadowKernel2D, slice), realDistance); shadow = shadow.xxx / 9.0; #else shadow = texture_shadowarray_2d.SampleCmpLevelZero(sampler_cmp_depth, float3(shadowUV, slice), realDistance); #endif // DISABLE_SOFT_SHADOWMAP #ifndef DISABLE_TRANSPARENT_SHADOWMAP - if (g_xFrame_Options & OPTION_BIT_TRANSPARENTSHADOWS_ENABLED) + if (g_xFrame.Options & OPTION_BIT_TRANSPARENTSHADOWS_ENABLED) { float4 transparent_shadow = texture_shadowarray_transparent_2d.SampleLevel(sampler_linear_clamp, float3(shadowUV, slice), 0); #ifdef TRANSPARENT_SHADOWMAP_SECONDARY_DEPTH_CHECK @@ -89,22 +89,22 @@ inline float3 shadowCube(in ShaderEntity light, in float3 L, in float3 Lunnormal #ifndef DISABLE_SOFT_SHADOWMAP // sample along a cube pattern around center: L = -L; - shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(-1, -1, -1) * g_xFrame_ShadowKernelCube, slice), remappedDistance); - shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(1, -1, -1) * g_xFrame_ShadowKernelCube, slice), remappedDistance); - shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(-1, 1, -1) * g_xFrame_ShadowKernelCube, slice), remappedDistance); - shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(1, 1, -1) * g_xFrame_ShadowKernelCube, slice), remappedDistance); + shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(-1, -1, -1) * g_xFrame.ShadowKernelCube, slice), remappedDistance); + shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(1, -1, -1) * g_xFrame.ShadowKernelCube, slice), remappedDistance); + shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(-1, 1, -1) * g_xFrame.ShadowKernelCube, slice), remappedDistance); + shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(1, 1, -1) * g_xFrame.ShadowKernelCube, slice), remappedDistance); shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L, slice), remappedDistance).r; - shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(-1, -1, 1) * g_xFrame_ShadowKernelCube, slice), remappedDistance); - shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(1, -1, 1) * g_xFrame_ShadowKernelCube, slice), remappedDistance); - shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(-1, 1, 1) * g_xFrame_ShadowKernelCube, slice), remappedDistance); - shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(1, 1, 1) * g_xFrame_ShadowKernelCube, slice), remappedDistance); + shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(-1, -1, 1) * g_xFrame.ShadowKernelCube, slice), remappedDistance); + shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(1, -1, 1) * g_xFrame.ShadowKernelCube, slice), remappedDistance); + shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(-1, 1, 1) * g_xFrame.ShadowKernelCube, slice), remappedDistance); + shadow += texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(L + float3(1, 1, 1) * g_xFrame.ShadowKernelCube, slice), remappedDistance); shadow /= 9.0; #else shadow = texture_shadowarray_cube.SampleCmpLevelZero(sampler_cmp_depth, float4(-Lunnormalized, slice), remappedDistance).r; #endif // DISABLE_SOFT_SHADOWMAP #ifndef DISABLE_TRANSPARENT_SHADOWMAP - if (g_xFrame_Options & OPTION_BIT_TRANSPARENTSHADOWS_ENABLED) + if (g_xFrame.Options & OPTION_BIT_TRANSPARENTSHADOWS_ENABLED) { float4 transparent_shadow = texture_shadowarray_transparent_cube.SampleLevel(sampler_linear_clamp, float4(-Lunnormalized, slice), 0); #ifdef TRANSPARENT_SHADOWMAP_SECONDARY_DEPTH_CHECK @@ -137,12 +137,12 @@ inline void DirectionalLight(in ShaderEntity light, in Surface surface, inout Li { #ifdef SHADOW_MASK_ENABLED [branch] - if ((g_xFrame_Options & OPTION_BIT_RAYTRACED_SHADOWS) == 0) + if ((g_xFrame.Options & OPTION_BIT_RAYTRACED_SHADOWS) == 0) #endif // SHADOW_MASK_ENABLED { // Loop through cascades from closest (smallest) to furthest (largest) [loop] - for (uint cascade = 0; cascade < g_xFrame_ShadowCascadeCount; ++cascade) + for (uint cascade = 0; cascade < g_xFrame.ShadowCascadeCount; ++cascade) { // Project into shadow map space (no need to divide by .w because ortho projection!): float3 ShPos = mul(MatrixArray[light.GetMatrixIndex() + cascade], float4(surface.P, 1)).xyz; @@ -158,7 +158,7 @@ inline void DirectionalLight(in ShaderEntity light, in Surface surface, inout Li // If we are on cascade edge threshold and not the last cascade, then fallback to a larger cascade: [branch] - if (cascade_fade > 0 && cascade < g_xFrame_ShadowCascadeCount - 1) + if (cascade_fade > 0 && cascade < g_xFrame.ShadowCascadeCount - 1) { // Project into next shadow cascade (no need to divide by .w because ortho projection!): cascade += 1; @@ -182,9 +182,9 @@ inline void DirectionalLight(in ShaderEntity light, in Surface surface, inout Li if (any(shadow)) { float3 atmosphereTransmittance = 1; - if (g_xFrame_Options & OPTION_BIT_REALISTIC_SKY) + if (g_xFrame.Options & OPTION_BIT_REALISTIC_SKY) { - atmosphereTransmittance = GetAtmosphericLightTransmittance(g_xFrame_Atmosphere, surface.P, L, texture_transmittancelut); + atmosphereTransmittance = GetAtmosphericLightTransmittance(g_xFrame.Atmosphere, surface.P, L, texture_transmittancelut); } float3 lightColor = light.GetColor().rgb * light.GetEnergy() * shadow * atmosphereTransmittance; @@ -223,7 +223,7 @@ inline void PointLight(in ShaderEntity light, in Surface surface, inout Lighting { #ifdef SHADOW_MASK_ENABLED [branch] - if ((g_xFrame_Options & OPTION_BIT_RAYTRACED_SHADOWS) == 0) + if ((g_xFrame.Options & OPTION_BIT_RAYTRACED_SHADOWS) == 0) #endif // SHADOW_MASK_ENABLED { shadow *= shadowCube(light, L, Lunnormalized); @@ -279,7 +279,7 @@ inline void SpotLight(in ShaderEntity light, in Surface surface, inout Lighting { #ifdef SHADOW_MASK_ENABLED [branch] - if ((g_xFrame_Options & OPTION_BIT_RAYTRACED_SHADOWS) == 0) + if ((g_xFrame.Options & OPTION_BIT_RAYTRACED_SHADOWS) == 0) #endif // SHADOW_MASK_ENABLED { float4 ShPos = mul(MatrixArray[light.GetMatrixIndex() + 0], float4(surface.P, 1)); @@ -332,7 +332,7 @@ inline float3 GetAmbient(in float3 N) #else - ambient = texture_envmaparray.SampleLevel(sampler_linear_clamp, float4(N, g_xFrame_GlobalEnvProbeIndex), g_xFrame_EnvProbeMipCount).rgb; + ambient = texture_envmaparray.SampleLevel(sampler_linear_clamp, float4(N, g_xFrame.GlobalEnvProbeIndex), g_xFrame.EnvProbeMipCount).rgb; #endif // ENVMAPRENDERING @@ -365,19 +365,19 @@ inline float3 EnvironmentReflection_Global(in Surface surface) #else - float MIP = surface.roughness * g_xFrame_EnvProbeMipCount; - envColor = texture_envmaparray.SampleLevel(sampler_linear_clamp, float4(surface.R, g_xFrame_GlobalEnvProbeIndex), MIP).rgb * surface.F; + float MIP = surface.roughness * g_xFrame.EnvProbeMipCount; + envColor = texture_envmaparray.SampleLevel(sampler_linear_clamp, float4(surface.R, g_xFrame.GlobalEnvProbeIndex), MIP).rgb * surface.F; #ifdef BRDF_SHEEN envColor *= surface.sheen.albedoScaling; - MIP = surface.sheen.roughness * g_xFrame_EnvProbeMipCount; - envColor += texture_envmaparray.SampleLevel(sampler_linear_clamp, float4(surface.R, g_xFrame_GlobalEnvProbeIndex), MIP).rgb * surface.sheen.color * surface.sheen.DFG; + MIP = surface.sheen.roughness * g_xFrame.EnvProbeMipCount; + envColor += texture_envmaparray.SampleLevel(sampler_linear_clamp, float4(surface.R, g_xFrame.GlobalEnvProbeIndex), MIP).rgb * surface.sheen.color * surface.sheen.DFG; #endif // BRDF_SHEEN #ifdef BRDF_CLEARCOAT envColor *= 1 - surface.clearcoat.F; - MIP = surface.clearcoat.roughness * g_xFrame_EnvProbeMipCount; - envColor += texture_envmaparray.SampleLevel(sampler_linear_clamp, float4(surface.clearcoat.R, g_xFrame_GlobalEnvProbeIndex), MIP).rgb * surface.clearcoat.F; + MIP = surface.clearcoat.roughness * g_xFrame.EnvProbeMipCount; + envColor += texture_envmaparray.SampleLevel(sampler_linear_clamp, float4(surface.clearcoat.R, g_xFrame.GlobalEnvProbeIndex), MIP).rgb * surface.clearcoat.F; #endif // BRDF_CLEARCOAT #endif // ENVMAPRENDERING @@ -403,12 +403,12 @@ inline float4 EnvironmentReflection_Local(in Surface surface, in ShaderEntity pr float3 R_parallaxCorrected = IntersectPositionWS - probe.position; // Sample cubemap texture: - float MIP = surface.roughness * g_xFrame_EnvProbeMipCount; + float MIP = surface.roughness * g_xFrame.EnvProbeMipCount; float3 envColor = texture_envmaparray.SampleLevel(sampler_linear_clamp, float4(R_parallaxCorrected, probe.GetTextureIndex()), MIP).rgb * surface.F; #ifdef BRDF_SHEEN envColor *= surface.sheen.albedoScaling; - MIP = surface.sheen.roughness * g_xFrame_EnvProbeMipCount; + MIP = surface.sheen.roughness * g_xFrame.EnvProbeMipCount; envColor += texture_envmaparray.SampleLevel(sampler_linear_clamp, float4(R_parallaxCorrected, probe.GetTextureIndex()), MIP).rgb * surface.sheen.color * surface.sheen.DFG; #endif // BRDF_SHEEN @@ -422,7 +422,7 @@ inline float4 EnvironmentReflection_Local(in Surface surface, in ShaderEntity pr R_parallaxCorrected = IntersectPositionWS - probe.position; envColor *= 1 - surface.clearcoat.F; - MIP = surface.clearcoat.roughness * g_xFrame_EnvProbeMipCount; + MIP = surface.clearcoat.roughness * g_xFrame.EnvProbeMipCount; envColor += texture_envmaparray.SampleLevel(sampler_linear_clamp, float4(R_parallaxCorrected, probe.GetTextureIndex()), MIP).rgb * surface.clearcoat.F; #endif // BRDF_CLEARCOAT @@ -438,26 +438,26 @@ inline float4 EnvironmentReflection_Local(in Surface surface, in ShaderEntity pr inline void VoxelGI(in Surface surface, inout Lighting lighting) { - [branch] if (g_xFrame_VoxelRadianceDataRes != 0) + [branch] if (g_xFrame.VoxelRadianceDataRes != 0) { // determine blending factor (we will blend out voxel GI on grid edges): - float3 voxelSpacePos = surface.P - g_xFrame_VoxelRadianceDataCenter; - voxelSpacePos *= g_xFrame_VoxelRadianceDataSize_rcp; - voxelSpacePos *= g_xFrame_VoxelRadianceDataRes_rcp; + float3 voxelSpacePos = surface.P - g_xFrame.VoxelRadianceDataCenter; + voxelSpacePos *= g_xFrame.VoxelRadianceDataSize_rcp; + voxelSpacePos *= g_xFrame.VoxelRadianceDataRes_rcp; voxelSpacePos = saturate(abs(voxelSpacePos)); float blend = 1 - pow(max(voxelSpacePos.x, max(voxelSpacePos.y, voxelSpacePos.z)), 4); // diffuse: { - float4 trace = ConeTraceDiffuse(texture_voxelradiance, surface.P, surface.N); + float4 trace = ConeTraceDiffuse(texture_voxelgi, surface.P, surface.N); lighting.indirect.diffuse = lerp(lighting.indirect.diffuse, trace.rgb, trace.a * blend); } // specular: [branch] - if (g_xFrame_Options & OPTION_BIT_VOXELGI_REFLECTIONS_ENABLED) + if (g_xFrame.Options & OPTION_BIT_VOXELGI_REFLECTIONS_ENABLED) { - float4 trace = ConeTraceSpecular(texture_voxelradiance, surface.P, surface.N, surface.V, surface.roughness); + float4 trace = ConeTraceSpecular(texture_voxelgi, surface.P, surface.N, surface.V, surface.roughness); lighting.indirect.specular = lerp(lighting.indirect.specular, trace.rgb * surface.F, trace.a * blend); } } diff --git a/WickedEngine/shaders/lineardepthCS.hlsl b/WickedEngine/shaders/lineardepthCS.hlsl deleted file mode 100644 index c5269cfa5..000000000 --- a/WickedEngine/shaders/lineardepthCS.hlsl +++ /dev/null @@ -1,89 +0,0 @@ -#include "globals.hlsli" -#include "ShaderInterop_Renderer.h" -#include "ShaderInterop_Postprocess.h" - -RWTEXTURE2D(output_lineardepth_mip0, float, 0); -RWTEXTURE2D(output_lineardepth_mip1, float, 1); -RWTEXTURE2D(output_lineardepth_mip2, float, 2); -RWTEXTURE2D(output_lineardepth_mip3, float, 3); -RWTEXTURE2D(output_lineardepth_mip4, float, 4); -RWTEXTURE2D(output_lineardepth_mip5, float, 5); - -RWTEXTURE2D(output_depth_mip1, float, 6); -RWTEXTURE2D(output_depth_mip2, float, 7); - -groupshared float tile[POSTPROCESS_LINEARDEPTH_BLOCKSIZE][POSTPROCESS_LINEARDEPTH_BLOCKSIZE]; - -[numthreads(POSTPROCESS_LINEARDEPTH_BLOCKSIZE, POSTPROCESS_LINEARDEPTH_BLOCKSIZE, 1)] -void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID) -{ - // Native depth MAX chain: - // Native depth MAX = closest pixel - const float4 depths = float4( - texture_depth[clamp(DTid.xy * 2 + uint2(0, 0), 0, lineardepth_inputresolution - 1)], - texture_depth[clamp(DTid.xy * 2 + uint2(1, 0), 0, lineardepth_inputresolution - 1)], - texture_depth[clamp(DTid.xy * 2 + uint2(0, 1), 0, lineardepth_inputresolution - 1)], - texture_depth[clamp(DTid.xy * 2 + uint2(1, 1), 0, lineardepth_inputresolution - 1)] - ); - - float maxdepth = max(depths.x, max(depths.y, max(depths.z, depths.w))); - tile[GTid.x][GTid.y] = maxdepth; - output_depth_mip1[DTid.xy] = maxdepth; - GroupMemoryBarrierWithGroupSync(); - - if (GTid.x % 2 == 0 && GTid.y % 2 == 0) - { - maxdepth = max(tile[GTid.x][GTid.y], max(tile[GTid.x + 1][GTid.y], max(tile[GTid.x][GTid.y + 1], tile[GTid.x + 1][GTid.y + 1]))); - tile[GTid.x][GTid.y] = maxdepth; - output_depth_mip2[DTid.xy / 2] = maxdepth; - } - GroupMemoryBarrierWithGroupSync(); - - // Linear depth MAX chain: - // Linear depth MAX = farthest pixel - const float4 lineardepths = float4( - getLinearDepth(depths.x), - getLinearDepth(depths.y), - getLinearDepth(depths.z), - getLinearDepth(depths.w) - ) * g_xCamera_ZFarP_rcp; - output_lineardepth_mip0[DTid.xy * 2 + uint2(0, 0)] = lineardepths.x; - output_lineardepth_mip0[DTid.xy * 2 + uint2(1, 0)] = lineardepths.y; - output_lineardepth_mip0[DTid.xy * 2 + uint2(0, 1)] = lineardepths.z; - output_lineardepth_mip0[DTid.xy * 2 + uint2(1, 1)] = lineardepths.w; - - maxdepth = max(lineardepths.x, max(lineardepths.y, max(lineardepths.z, lineardepths.w))); - tile[GTid.x][GTid.y] = maxdepth; - output_lineardepth_mip1[DTid.xy] = maxdepth; - GroupMemoryBarrierWithGroupSync(); - - if (GTid.x % 2 == 0 && GTid.y % 2 == 0) - { - maxdepth = max(tile[GTid.x][GTid.y], max(tile[GTid.x + 1][GTid.y], max(tile[GTid.x][GTid.y + 1], tile[GTid.x + 1][GTid.y+ 1]))); - tile[GTid.x][GTid.y] = maxdepth; - output_lineardepth_mip2[DTid.xy / 2] = maxdepth; - } - GroupMemoryBarrierWithGroupSync(); - - if (GTid.x % 4 == 0 && GTid.y % 4 == 0) - { - maxdepth = max(tile[GTid.x][GTid.y], max(tile[GTid.x + 2][GTid.y], max(tile[GTid.x][GTid.y + 2], tile[GTid.x + 2][GTid.y + 2]))); - tile[GTid.x][GTid.y] = maxdepth; - output_lineardepth_mip3[DTid.xy / 4] = maxdepth; - } - GroupMemoryBarrierWithGroupSync(); - - if (GTid.x % 8 == 0 && GTid.y % 8 == 0) - { - maxdepth = max(tile[GTid.x][GTid.y], max(tile[GTid.x + 4][GTid.y], max(tile[GTid.x][GTid.y + 4], tile[GTid.x + 4][GTid.y + 4]))); - tile[GTid.x][GTid.y] = maxdepth; - output_lineardepth_mip4[DTid.xy / 8] = maxdepth; - } - GroupMemoryBarrierWithGroupSync(); - - if (GTid.x % 16 == 0 && GTid.y % 16 == 0) - { - maxdepth = max(tile[GTid.x][GTid.y], max(tile[GTid.x + 8][GTid.y], max(tile[GTid.x][GTid.y + 8], tile[GTid.x + 8][GTid.y + 8]))); - output_lineardepth_mip5[DTid.xy / 16] = maxdepth; - } -} diff --git a/WickedEngine/shaders/luminancePass2CS.hlsl b/WickedEngine/shaders/luminancePass2CS.hlsl index 89783ef2f..2b11eda83 100644 --- a/WickedEngine/shaders/luminancePass2CS.hlsl +++ b/WickedEngine/shaders/luminancePass2CS.hlsl @@ -39,7 +39,7 @@ void main( float lastlum = output[uint2(0, 0)]; // https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/LuminanceReduction.hlsl - float newlum = lastlum + (currentlum - lastlum) * (1 - exp(-g_xFrame_DeltaTime * luminance_adaptionrate)); + float newlum = lastlum + (currentlum - lastlum) * (1 - exp(-g_xFrame.DeltaTime * luminance_adaptionrate)); output[uint2(0, 0)] = newlum; } diff --git a/WickedEngine/shaders/motionblurCS.hlsl b/WickedEngine/shaders/motionblurCS.hlsl index 8a5857569..bf6953ac8 100644 --- a/WickedEngine/shaders/motionblurCS.hlsl +++ b/WickedEngine/shaders/motionblurCS.hlsl @@ -62,7 +62,7 @@ void main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID) const float neighborhood_velocity_magnitude = length(neighborhood_velocity); const float4 center_color = input[pixel]; - const float2 center_velocity = texture_gbuffer2[pixel].xy * motionblur_strength; + const float2 center_velocity = texture_gbuffer1[pixel].xy * motionblur_strength; const float center_velocity_magnitude = length(center_velocity); const float center_depth = texture_lineardepth[pixel]; @@ -85,12 +85,12 @@ void main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID) for (float i = -range; i <= range; i += 2.0f) { const float depth1 = texture_lineardepth.SampleLevel(sampler_point_clamp, uv2, 0); - const float2 velocity1 = texture_gbuffer2.SampleLevel(sampler_point_clamp, uv2, 0).xy; + const float2 velocity1 = texture_gbuffer1.SampleLevel(sampler_point_clamp, uv2, 0).xy; const float velocity_magnitude1 = length(velocity1); const float3 color1 = input.SampleLevel(sampler_point_clamp, uv2, 0).rgb; uv2 += sampling_direction; const float depth2 = texture_lineardepth.SampleLevel(sampler_point_clamp, uv2, 0); - const float2 velocity2 = texture_gbuffer2.SampleLevel(sampler_point_clamp, uv2, 0).xy; + const float2 velocity2 = texture_gbuffer1.SampleLevel(sampler_point_clamp, uv2, 0).xy; const float velocity_magnitude2 = length(velocity2); const float3 color2 = input.SampleLevel(sampler_point_clamp, uv2, 0).rgb; uv2 += sampling_direction; @@ -99,8 +99,8 @@ void main(uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID) sum += float4(color1, 1); sum += float4(color2, 1); #else - float weight1 = SampleWeight(center_depth, depth1, neighborhood_velocity_magnitude, center_velocity_magnitude, velocity_magnitude1, 1000, g_xCamera_ZFarP); - float weight2 = SampleWeight(center_depth, depth2, neighborhood_velocity_magnitude, center_velocity_magnitude, velocity_magnitude2, 1000, g_xCamera_ZFarP); + float weight1 = SampleWeight(center_depth, depth1, neighborhood_velocity_magnitude, center_velocity_magnitude, velocity_magnitude1, 1000, g_xCamera.ZFarP); + float weight2 = SampleWeight(center_depth, depth2, neighborhood_velocity_magnitude, center_velocity_magnitude, velocity_magnitude2, 1000, g_xCamera.ZFarP); bool2 mirror = bool2(depth1 > depth2, velocity_magnitude2 > velocity_magnitude1); weight1 = all(mirror) ? weight2 : weight1; diff --git a/WickedEngine/shaders/motionblur_tileMaxVelocity_horizontalCS.hlsl b/WickedEngine/shaders/motionblur_tileMaxVelocity_horizontalCS.hlsl index 152240b02..c657f8874 100644 --- a/WickedEngine/shaders/motionblur_tileMaxVelocity_horizontalCS.hlsl +++ b/WickedEngine/shaders/motionblur_tileMaxVelocity_horizontalCS.hlsl @@ -17,7 +17,7 @@ void main(uint3 DTid : SV_DispatchThreadID) for (uint i = 0; i < MOTIONBLUR_TILESIZE.x; ++i) { const uint2 pixel = uint2(tile_upperleft.x + i, tile_upperleft.y); - const float2 velocity = texture_gbuffer2[pixel].xy; + const float2 velocity = texture_gbuffer1[pixel].xy; const float magnitude = length(velocity); if (magnitude > max_magnitude) { diff --git a/WickedEngine/shaders/normalsfromdepthCS.hlsl b/WickedEngine/shaders/normalsfromdepthCS.hlsl index 0b08db920..b3256830c 100644 --- a/WickedEngine/shaders/normalsfromdepthCS.hlsl +++ b/WickedEngine/shaders/normalsfromdepthCS.hlsl @@ -46,7 +46,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : const float center_Z = tile_Z[cross_idx[0]]; [branch] - if (center_Z >= g_xCamera_ZFarP) + if (center_Z >= g_xCamera.ZFarP) return; const uint best_Z_horizontal = abs(tile_Z[cross_idx[1]] - center_Z) < abs(tile_Z[cross_idx[2]] - center_Z) ? 1 : 2; diff --git a/WickedEngine/shaders/objectDS_prepass.hlsl b/WickedEngine/shaders/objectDS_prepass.hlsl index 8c21ff2ee..71abad1f9 100644 --- a/WickedEngine/shaders/objectDS_prepass.hlsl +++ b/WickedEngine/shaders/objectDS_prepass.hlsl @@ -1,5 +1,5 @@ #define OBJECTSHADER_COMPILE_DS -#define OBJECTSHADER_LAYOUT_POS_PREVPOS_TEX +#define OBJECTSHADER_LAYOUT_PREPASS_TEX #define OBJECTSHADER_USE_NORMAL #include "objectHF_tessellation.hlsli" diff --git a/WickedEngine/shaders/objectDS_prepass_alphatest.hlsl b/WickedEngine/shaders/objectDS_prepass_alphatest.hlsl index 8c21ff2ee..71abad1f9 100644 --- a/WickedEngine/shaders/objectDS_prepass_alphatest.hlsl +++ b/WickedEngine/shaders/objectDS_prepass_alphatest.hlsl @@ -1,5 +1,5 @@ #define OBJECTSHADER_COMPILE_DS -#define OBJECTSHADER_LAYOUT_POS_PREVPOS_TEX +#define OBJECTSHADER_LAYOUT_PREPASS_TEX #define OBJECTSHADER_USE_NORMAL #include "objectHF_tessellation.hlsli" diff --git a/WickedEngine/shaders/objectDS_simple.hlsl b/WickedEngine/shaders/objectDS_simple.hlsl index 175854253..b6b534938 100644 --- a/WickedEngine/shaders/objectDS_simple.hlsl +++ b/WickedEngine/shaders/objectDS_simple.hlsl @@ -1,5 +1,5 @@ #define OBJECTSHADER_COMPILE_DS -#define OBJECTSHADER_LAYOUT_POS_TEX +#define OBJECTSHADER_LAYOUT_SHADOW_TEX #define OBJECTSHADER_USE_COLOR #define OBJECTSHADER_USE_NORMAL #include "objectHF_tessellation.hlsli" diff --git a/WickedEngine/shaders/objectGS_voxelizer.hlsl b/WickedEngine/shaders/objectGS_voxelizer.hlsl index 4b4d2065a..5802787c1 100644 --- a/WickedEngine/shaders/objectGS_voxelizer.hlsl +++ b/WickedEngine/shaders/objectGS_voxelizer.hlsl @@ -32,7 +32,7 @@ void main( GSOutput output; // World space -> Voxel grid space: - output.pos.xyz = (input[i].pos.xyz - g_xFrame_VoxelRadianceDataCenter) * g_xFrame_VoxelRadianceDataSize_rcp; + output.pos.xyz = (input[i].pos.xyz - g_xFrame.VoxelRadianceDataCenter) * g_xFrame.VoxelRadianceDataSize_rcp; // Project onto dominant axis: [flatten] @@ -46,7 +46,7 @@ void main( } // Voxel grid space -> Clip space - output.pos.xy *= g_xFrame_VoxelRadianceDataRes_rcp; + output.pos.xy *= g_xFrame.VoxelRadianceDataRes_rcp; output.pos.zw = 1; // Append the rest of the parameters as is: diff --git a/WickedEngine/shaders/objectHF.hlsli b/WickedEngine/shaders/objectHF.hlsli index f2c64c249..5fc87abcd 100644 --- a/WickedEngine/shaders/objectHF.hlsli +++ b/WickedEngine/shaders/objectHF.hlsli @@ -20,38 +20,39 @@ #include "globals.hlsli" #include "brdf.hlsli" #include "lightingHF.hlsli" +#include "ShaderInterop_SurfelGI.h" // DEFINITIONS ////////////////// -#ifdef BINDLESS -Texture2D bindless_textures[] : register(t0, space1); -SamplerState bindless_samplers[] : register(t0, space2); -ByteAddressBuffer bindless_buffers[] : register(t0, space3); PUSHCONSTANT(push, ObjectPushConstants); +inline uint GetSubsetIndex() +{ + return push.GetSubsetIndex(); +} inline ShaderMesh GetMesh() { - return bindless_buffers[push.mesh].Load(0); + return load_mesh(push.GetMeshIndex()); } inline ShaderMaterial GetMaterial() { - return bindless_buffers[push.material].Load(0); + return load_material(push.GetMaterialIndex()); } inline ShaderMaterial GetMaterial1() { - return bindless_buffers[GetMesh().blendmaterial1].Load(0); + return load_material(GetMesh().blendmaterial1); } inline ShaderMaterial GetMaterial2() { - return bindless_buffers[GetMesh().blendmaterial2].Load(0); + return load_material(GetMesh().blendmaterial2); } inline ShaderMaterial GetMaterial3() { - return bindless_buffers[GetMesh().blendmaterial3].Load(0); + return load_material(GetMesh().blendmaterial3); } -#define sampler_objectshader bindless_samplers[g_xFrame_ObjectShaderSamplerIndex] +#define sampler_objectshader bindless_samplers[g_xFrame.ObjectShaderSamplerIndex] #define texture_basecolormap bindless_textures[GetMaterial().texture_basecolormap_index] #define texture_normalmap bindless_textures[GetMaterial().texture_normalmap_index] @@ -83,57 +84,6 @@ inline ShaderMaterial GetMaterial3() #define texture_blend3_emissivemap bindless_textures[GetMaterial3().texture_emissivemap_index] -#else - -inline ShaderMaterial GetMaterial() -{ - return g_xMaterial; -} -inline ShaderMaterial GetMaterial1() -{ - return g_xMaterial_blend1; -} -inline ShaderMaterial GetMaterial2() -{ - return g_xMaterial_blend2; -} -inline ShaderMaterial GetMaterial3() -{ - return g_xMaterial_blend3; -} - -// These are bound by wiRenderer (based on Material): -TEXTURE2D(texture_basecolormap, float4, TEXSLOT_RENDERER_BASECOLORMAP); // rgb: baseColor, a: opacity -TEXTURE2D(texture_normalmap, float3, TEXSLOT_RENDERER_NORMALMAP); // rgb: normal -TEXTURE2D(texture_surfacemap, float4, TEXSLOT_RENDERER_SURFACEMAP); // r: occlusion, g: roughness, b: metallic, a: reflectance -TEXTURE2D(texture_emissivemap, float4, TEXSLOT_RENDERER_EMISSIVEMAP); // rgba: emissive -TEXTURE2D(texture_displacementmap, float, TEXSLOT_RENDERER_DISPLACEMENTMAP); // r: heightmap -TEXTURE2D(texture_occlusionmap, float, TEXSLOT_RENDERER_OCCLUSIONMAP); // r: occlusion -TEXTURE2D(texture_transmissionmap, float, TEXSLOT_RENDERER_TRANSMISSIONMAP); // r: transmission factor -TEXTURE2D(texture_sheencolormap, float3, TEXSLOT_RENDERER_SHEENCOLORMAP); // rgb -TEXTURE2D(texture_sheenroughnessmap, float4, TEXSLOT_RENDERER_SHEENROUGHNESSMAP); // a -TEXTURE2D(texture_clearcoatmap, float, TEXSLOT_RENDERER_CLEARCOATMAP); // r -TEXTURE2D(texture_clearcoatroughnessmap, float2, TEXSLOT_RENDERER_CLEARCOATROUGHNESSMAP); // g -TEXTURE2D(texture_clearcoatnormalmap, float3, TEXSLOT_RENDERER_CLEARCOATNORMALMAP); // rgb -TEXTURE2D(texture_specularmap, float4, TEXSLOT_RENDERER_SPECULARMAP); // rgb color, a intensity - -TEXTURE2D(texture_blend1_basecolormap, float4, TEXSLOT_RENDERER_BLEND1_BASECOLORMAP); // rgb: baseColor, a: opacity -TEXTURE2D(texture_blend1_normalmap, float3, TEXSLOT_RENDERER_BLEND1_NORMALMAP); // rgb: normal -TEXTURE2D(texture_blend1_surfacemap, float4, TEXSLOT_RENDERER_BLEND1_SURFACEMAP); // r: occlusion, g: roughness, b: metallic, a: reflectance -TEXTURE2D(texture_blend1_emissivemap, float4, TEXSLOT_RENDERER_BLEND1_EMISSIVEMAP); // rgba: emissive - -TEXTURE2D(texture_blend2_basecolormap, float4, TEXSLOT_RENDERER_BLEND2_BASECOLORMAP); // rgb: baseColor, a: opacity -TEXTURE2D(texture_blend2_normalmap, float3, TEXSLOT_RENDERER_BLEND2_NORMALMAP); // rgb: normal -TEXTURE2D(texture_blend2_surfacemap, float4, TEXSLOT_RENDERER_BLEND2_SURFACEMAP); // r: occlusion, g: roughness, b: metallic, a: reflectance -TEXTURE2D(texture_blend2_emissivemap, float4, TEXSLOT_RENDERER_BLEND2_EMISSIVEMAP); // rgba: emissive - -TEXTURE2D(texture_blend3_basecolormap, float4, TEXSLOT_RENDERER_BLEND3_BASECOLORMAP); // rgb: baseColor, a: opacity -TEXTURE2D(texture_blend3_normalmap, float3, TEXSLOT_RENDERER_BLEND3_NORMALMAP); // rgb: normal -TEXTURE2D(texture_blend3_surfacemap, float4, TEXSLOT_RENDERER_BLEND3_SURFACEMAP); // r: occlusion, g: roughness, b: metallic, a: reflectance -TEXTURE2D(texture_blend3_emissivemap, float4, TEXSLOT_RENDERER_BLEND3_EMISSIVEMAP); // rgba: emissive - -#endif // BINDLESS - // These are bound by RenderPath (based on Render Path): STRUCTUREDBUFFER(EntityTiles, uint, TEXSLOT_RENDERPATH_ENTITYTILES); @@ -143,26 +93,18 @@ TEXTURE2D(texture_waterriples, float4, TEXSLOT_RENDERPATH_WATERRIPPLES); // rgb: TEXTURE2D(texture_ao, float, TEXSLOT_RENDERPATH_AO); // r: ambient occlusion TEXTURE2D(texture_ssr, float4, TEXSLOT_RENDERPATH_SSR); // rgb: screen space ray-traced reflections, a: reflection blend based on ray hit or miss TEXTURE2D(texture_rtshadow, uint4, TEXSLOT_RENDERPATH_RTSHADOW); // bitmask for max 16 shadows' visibility +TEXTURE2D(texture_surfelgi, float3, TEXSLOT_RENDERPATH_SURFELGI); // Use these to compile this file as shader prototype: //#define OBJECTSHADER_COMPILE_VS - compile vertex shader prototype //#define OBJECTSHADER_COMPILE_PS - compile pixel shader prototype -// Use these to define the expected input layout for the shader: -//#define OBJECTSHADER_LAYOUT_POS - input layout that has position and instance matrix -//#define OBJECTSHADER_LAYOUT_POS_TEX - input layout that has position and texture coords -//#define OBJECTSHADER_LAYOUT_POS_PREVPOS - input layout that has position and previous frame position -//#define OBJECTSHADER_LAYOUT_POS_PREVPOS_TEX - input layout that has position, previous frame position and texture coords -//#define OBJECTSHADER_LAYOUT_COMMON - input layout that has all the required inputs for common shaders - -// Use these to define the expected input layout for the shader, but in a fine grained manner: -// (These will not define additional capabilities) -//#define OBJECTSHADER_INPUT_POS - adds position to input layout -//#define OBJECTSHADER_INPUT_PRE - adds previous frame position to input layout -//#define OBJECTSHADER_INPUT_TEX - adds texture coordinates to input layout -//#define OBJECTSHADER_INPUT_ATL - adds atlas texture coords to input layout -//#define OBJECTSHADER_INPUT_COL - adds vertex colors to input layout -//#define OBJECTSHADER_INPUT_TAN - adds tangents to input layout +// Use these to define the expected layout for the shader: +//#define OBJECTSHADER_LAYOUT_SHADOW - layout for shadow pass +//#define OBJECTSHADER_LAYOUT_SHADOW_TEX - layout for shadow pass and alpha test or transparency +//#define OBJECTSHADER_LAYOUT_PREPASS - layout for prepass +//#define OBJECTSHADER_LAYOUT_PREPASS_TEX - layout for prepass and alpha test or dithering +//#define OBJECTSHADER_LAYOUT_COMMON - layout for common passes // Use these to enable features for the shader: // (Some of these are enabled automatically with OBJECTSHADER_LAYOUT defines) @@ -175,50 +117,37 @@ TEXTURE2D(texture_rtshadow, uint4, TEXSLOT_RENDERPATH_RTSHADOW); // bitmask fo //#define OBJECTSHADER_USE_NORMAL - shader will use normals //#define OBJECTSHADER_USE_TANGENT - shader will use tangents, normal mapping //#define OBJECTSHADER_USE_POSITION3D - shader will use world space positions -//#define OBJECTSHADER_USE_POSITIONPREV - shader will use previous frame positions //#define OBJECTSHADER_USE_EMISSIVE - shader will use emissive //#define OBJECTSHADER_USE_RENDERTARGETARRAYINDEX - shader will use dynamic render target slice selection //#define OBJECTSHADER_USE_NOCAMERA - shader will not use camera space transform +//#define OBJECTSHADER_USE_INSTANCEID - shader will use instance ID -#ifdef OBJECTSHADER_LAYOUT_POS // used by opaque shadows -#define OBJECTSHADER_INPUT_POS +#ifdef OBJECTSHADER_LAYOUT_SHADOW #define OBJECTSHADER_USE_WIND -#endif // OBJECTSHADER_LAYOUT_POS +#endif // OBJECTSHADER_LAYOUT_SHADOW -#ifdef OBJECTSHADER_LAYOUT_POS_TEX // used by shadows with alpha test or transparency -#define OBJECTSHADER_INPUT_POS -#define OBJECTSHADER_INPUT_TEX +#ifdef OBJECTSHADER_LAYOUT_SHADOW_TEX #define OBJECTSHADER_USE_WIND #define OBJECTSHADER_USE_UVSETS #define OBJECTSHADER_USE_COLOR -#endif // OBJECTSHADER_LAYOUT_POS_TEX +#endif // OBJECTSHADER_LAYOUT_SHADOW_TEX -#ifdef OBJECTSHADER_LAYOUT_POS_PREVPOS // used by depth prepass -#define OBJECTSHADER_INPUT_POS -#define OBJECTSHADER_INPUT_PRE +#ifdef OBJECTSHADER_LAYOUT_PREPASS #define OBJECTSHADER_USE_CLIPPLANE #define OBJECTSHADER_USE_WIND -#define OBJECTSHADER_USE_POSITIONPREV -#endif // OBJECTSHADER_LAYOUT_POS +#define OBJECTSHADER_USE_INSTANCEID +#endif // OBJECTSHADER_LAYOUT_SHADOW -#ifdef OBJECTSHADER_LAYOUT_POS_PREVPOS_TEX // used by depth prepass with alpha test or dithered transparency -#define OBJECTSHADER_INPUT_POS -#define OBJECTSHADER_INPUT_PRE -#define OBJECTSHADER_INPUT_TEX +#ifdef OBJECTSHADER_LAYOUT_PREPASS_TEX #define OBJECTSHADER_USE_CLIPPLANE #define OBJECTSHADER_USE_WIND -#define OBJECTSHADER_USE_POSITIONPREV #define OBJECTSHADER_USE_UVSETS #define OBJECTSHADER_USE_DITHERING -#endif // OBJECTSHADER_LAYOUT_POS_TEX +#define OBJECTSHADER_USE_INSTANCEID +#endif // OBJECTSHADER_LAYOUT_SHADOW_TEX -#ifdef OBJECTSHADER_LAYOUT_COMMON // used by common render passes -#define OBJECTSHADER_INPUT_POS -#define OBJECTSHADER_INPUT_TEX -#define OBJECTSHADER_INPUT_ATL -#define OBJECTSHADER_INPUT_COL -#define OBJECTSHADER_INPUT_TAN +#ifdef OBJECTSHADER_LAYOUT_COMMON #define OBJECTSHADER_USE_CLIPPLANE #define OBJECTSHADER_USE_WIND #define OBJECTSHADER_USE_UVSETS @@ -228,28 +157,11 @@ TEXTURE2D(texture_rtshadow, uint4, TEXSLOT_RENDERPATH_RTSHADOW); // bitmask fo #define OBJECTSHADER_USE_TANGENT #define OBJECTSHADER_USE_POSITION3D #define OBJECTSHADER_USE_EMISSIVE +#define OBJECTSHADER_USE_INSTANCEID #endif // OBJECTSHADER_LAYOUT_COMMON -#ifdef BINDLESS -static const uint instance_stride_matrix_userdata = 16 * 4; -static const uint instance_stride_atlas = 16; -static const uint instance_stride_prev = 16 * 3; - -#ifdef OBJECTSHADER_INPUT_PRE -static const uint instance_stride = instance_stride_matrix_userdata + instance_stride_prev; -#else -#ifdef OBJECTSHADER_INPUT_ATL -static const uint instance_stride = instance_stride_matrix_userdata + instance_stride_atlas; -#else -static const uint instance_stride = instance_stride_matrix_userdata; -#endif // OBJECTSHADER_INPUT_ATL -#endif // OBJECTSHADER_INPUT_PRE -#endif // BINDLESS - struct VertexInput { -#ifdef BINDLESS - // Data coming from bindless fetching: uint vertexID : SV_VertexID; uint instanceID : SV_InstanceID; @@ -272,7 +184,6 @@ struct VertexInput return ((normal_wind >> 24u) & 0xFF) / 255.0; } -#ifdef OBJECTSHADER_INPUT_TEX float2 GetUV0() { [branch] @@ -287,51 +198,17 @@ struct VertexInput return 0; return unpack_half2(bindless_buffers[GetMesh().vb_uv1].Load(vertexID * 4)); } -#endif // OBJECTSHADER_INPUT_TEX - float4x4 GetInstanceMatrix() + ShaderMeshInstancePointer GetInstancePointer() { - float4 mat0 = bindless_buffers[push.instances].Load(push.instance_offset + instanceID * instance_stride + 16 * 0); - float4 mat1 = bindless_buffers[push.instances].Load(push.instance_offset + instanceID * instance_stride + 16 * 1); - float4 mat2 = bindless_buffers[push.instances].Load(push.instance_offset + instanceID * instance_stride + 16 * 2); - return float4x4( - mat0, - mat1, - mat2, - float4(0, 0, 0, 1) - ); - } - uint4 GetInstanceUserdata() - { - return bindless_buffers[push.instances].Load(push.instance_offset + instanceID * instance_stride + 16 * 3); + if (push.instances >= 0) + return bindless_buffers[push.instances].Load(push.instance_offset + instanceID * 8); + + ShaderMeshInstancePointer poi; + poi.init(); + return poi; } -#ifdef OBJECTSHADER_INPUT_PRE - float4 GetPositionPrev() - { - int descriptor_index = GetMesh().vb_pre; - [branch] - if (descriptor_index < 0) - { - descriptor_index = GetMesh().vb_pos_nor_wind; - } - return float4(bindless_buffers[descriptor_index].Load(vertexID * 16), 1); - } - float4x4 GetInstanceMatrixPrev() - { - float4 matPrev0 = bindless_buffers[push.instances].Load(push.instance_offset + instanceID * instance_stride + 16 * 4); - float4 matPrev1 = bindless_buffers[push.instances].Load(push.instance_offset + instanceID * instance_stride + 16 * 5); - float4 matPrev2 = bindless_buffers[push.instances].Load(push.instance_offset + instanceID * instance_stride + 16 * 6); - return float4x4( - matPrev0, - matPrev1, - matPrev2, - float4(0, 0, 0, 1) - ); - } -#endif // OBJECTSHADER_INPUT_PRE - -#ifdef OBJECTSHADER_INPUT_ATL float2 GetAtlasUV() { [branch] @@ -339,13 +216,7 @@ struct VertexInput return 0; return unpack_half2(bindless_buffers[GetMesh().vb_atl].Load(vertexID * 4)); } - float4 GetInstanceAtlas() - { - return bindless_buffers[push.instances].Load(push.instance_offset + instanceID * instance_stride + 16 * 4); - } -#endif // OBJECTSHADER_INPUT_ATL -#ifdef OBJECTSHADER_INPUT_COL float4 GetVertexColor() { [branch] @@ -353,128 +224,24 @@ struct VertexInput return 1; return unpack_rgba(bindless_buffers[GetMesh().vb_col].Load(vertexID * 4)); } -#endif // OBJECTSHADER_INPUT_COL -#ifdef OBJECTSHADER_INPUT_TAN float4 GetTangent() { + [branch] + if (GetMesh().vb_tan < 0) + return 0; return unpack_utangent(bindless_buffers[GetMesh().vb_tan].Load(vertexID * 4)) * 2 - 1; } -#endif // OBJECTSHADER_INPUT_TAN - - - - -#else - // Data coming from input layout: - float4 pos : POSITION_NORMAL_WIND; - float4 GetPosition() + ShaderMeshInstance GetInstance() { - return float4(pos.xyz, 1); - } - float3 GetNormal() - { - const uint normal_wind = asuint(pos.w); - float3 normal; - normal.x = (float)((normal_wind >> 0u) & 0xFF) / 255.0 * 2 - 1; - normal.y = (float)((normal_wind >> 8u) & 0xFF) / 255.0 * 2 - 1; - normal.z = (float)((normal_wind >> 16u) & 0xFF) / 255.0 * 2 - 1; - return normal; - } - float GetWindWeight() - { - const uint normal_wind = asuint(pos.w); - return ((normal_wind >> 24u) & 0xFF) / 255.0; - } + if (push.instances >= 0) + return load_instance(GetInstancePointer().instanceID); -#ifdef OBJECTSHADER_INPUT_PRE - float4 pre : PREVPOS; - float4 GetPositionPrev() - { - return float4(pre.xyz, 1); + ShaderMeshInstance inst; + inst.init(); + return inst; } -#endif // OBJECTSHADER_INPUT_PRE - -#ifdef OBJECTSHADER_INPUT_TEX - float2 uv0 : UVSET0; - float2 uv1 : UVSET1; - float2 GetUV0() - { - return uv0; - } - float2 GetUV1() - { - return uv1; - } -#endif // OBJECTSHADER_INPUT_TEX - -#ifdef OBJECTSHADER_INPUT_ATL - float2 atl : ATLAS; - float2 GetAtlasUV() - { - return atl; - } -#endif // OBJECTSHADER_INPUT_ATL - -#ifdef OBJECTSHADER_INPUT_COL - float4 col : COLOR; - float4 GetVertexColor() - { - return col; - } -#endif // OBJECTSHADER_INPUT_COL - -#ifdef OBJECTSHADER_INPUT_TAN - float4 tan : TANGENT; - float4 GetTangent() - { - return tan * 2 - 1; - } -#endif // OBJECTSHADER_INPUT_TAN - - float4 mat0 : INSTANCEMATRIX0; - float4 mat1 : INSTANCEMATRIX1; - float4 mat2 : INSTANCEMATRIX2; - uint4 userdata : INSTANCEUSERDATA; - -#ifdef OBJECTSHADER_INPUT_PRE - float4 matPrev0 : INSTANCEMATRIXPREV0; - float4 matPrev1 : INSTANCEMATRIXPREV1; - float4 matPrev2 : INSTANCEMATRIXPREV2; - float4x4 GetInstanceMatrixPrev() - { - return float4x4( - matPrev0, - matPrev1, - matPrev2, - float4(0, 0, 0, 1) - ); - } -#endif // OBJECTSHADER_INPUT_PRE - -#ifdef OBJECTSHADER_INPUT_ATL - float4 atlasMulAdd : INSTANCEATLAS; - float4 GetInstanceAtlas() - { - return atlasMulAdd; - } -#endif // OBJECTSHADER_INPUT_ATL - - float4x4 GetInstanceMatrix() - { - return float4x4( - mat0, - mat1, - mat2, - float4(0, 0, 0, 1) - ); - } - uint4 GetInstanceUserdata() - { - return userdata; - } -#endif // BINDLESS }; @@ -486,65 +253,40 @@ struct VertexSurface float4 color; float3 normal; float4 tangent; - float4 positionPrev; uint emissiveColor; inline void create(in ShaderMaterial material, in VertexInput input) { - float4x4 WORLD = input.GetInstanceMatrix(); - uint4 userdata = input.GetInstanceUserdata(); position = input.GetPosition(); - color = material.baseColor * unpack_rgba(userdata.x); - emissiveColor = userdata.z; + color = material.baseColor * unpack_rgba(input.GetInstance().color); + color.a *= 1 - input.GetInstancePointer().GetDither(); + emissiveColor = input.GetInstance().emissive; -#ifdef OBJECTSHADER_INPUT_PRE - positionPrev = input.GetPositionPrev(); -#else - positionPrev = position; -#endif // OBJECTSHADER_INPUT_PRE - -#ifdef OBJECTSHADER_INPUT_COL if (material.IsUsingVertexColors()) { color *= input.GetVertexColor(); } -#endif // OBJECTSHADER_INPUT_COL - normal = normalize(mul((float3x3)WORLD, input.GetNormal())); + normal = normalize(mul((float3x3)input.GetInstance().transformInverseTranspose.GetMatrix(), input.GetNormal())); -#ifdef OBJECTSHADER_INPUT_TAN tangent = input.GetTangent(); - tangent.xyz = normalize(mul((float3x3)WORLD, tangent.xyz)); -#endif // OBJECTSHADER_INPUT_TAN + tangent.xyz = normalize(mul((float3x3)input.GetInstance().transformInverseTranspose.GetMatrix(), tangent.xyz)); -#ifdef OBJECTSHADER_INPUT_TEX uvsets = float4(input.GetUV0() * material.texMulAdd.xy + material.texMulAdd.zw, input.GetUV1()); -#endif // OBJECTSHADER_INPUT_TEX -#ifdef OBJECTSHADER_INPUT_ATL - float4 atlasMulAdd = input.GetInstanceAtlas(); - atlas = input.GetAtlasUV() * atlasMulAdd.xy + atlasMulAdd.zw; -#endif // OBJECTSHADER_INPUT_ATL + atlas = input.GetAtlasUV(); - position = mul(WORLD, position); + position = mul(input.GetInstance().transform.GetMatrix(), position); -#ifdef OBJECTSHADER_INPUT_PRE - positionPrev = mul(input.GetInstanceMatrixPrev(), positionPrev); -#else - positionPrev = position; -#endif // OBJECTSHADER_INPUT_PRE #ifdef OBJECTSHADER_USE_WIND if (material.IsUsingWind()) { const float windweight = input.GetWindWeight(); - const float waveoffset = dot(position.xyz, g_xFrame_WindDirection) * g_xFrame_WindWaveSize + (position.x + position.y + position.z) * g_xFrame_WindRandomness; - const float waveoffsetPrev = dot(positionPrev.xyz, g_xFrame_WindDirection) * g_xFrame_WindWaveSize + (positionPrev.x + positionPrev.y + positionPrev.z) * g_xFrame_WindRandomness; - const float3 wavedir = g_xFrame_WindDirection * windweight; - const float3 wind = sin(g_xFrame_Time * g_xFrame_WindSpeed + waveoffset) * wavedir; - const float3 windPrev = sin(g_xFrame_TimePrev * g_xFrame_WindSpeed + waveoffsetPrev) * wavedir; + const float waveoffset = dot(position.xyz, g_xFrame.WindDirection) * g_xFrame.WindWaveSize + (position.x + position.y + position.z) * g_xFrame.WindRandomness; + const float3 wavedir = g_xFrame.WindDirection * windweight; + const float3 wind = sin(g_xFrame.Time * g_xFrame.WindSpeed + waveoffset) * wavedir; position.xyz += wind; - positionPrev.xyz += windPrev; } #endif // OBJECTSHADER_USE_WIND } @@ -554,22 +296,26 @@ struct PixelInput { precise float4 pos : SV_POSITION; +#ifdef OBJECTSHADER_USE_INSTANCEID + uint instanceID : INSTANCEID; +#endif // OBJECTSHADER_USE_INSTANCEID + #ifdef OBJECTSHADER_USE_CLIPPLANE float clip : SV_ClipDistance0; #endif // OBJECTSHADER_USE_CLIPPLANE -#ifdef OBJECTSHADER_USE_POSITIONPREV - float4 pre : PREVIOUSPOSITION; -#endif // OBJECTSHADER_USE_POSITIONPREV +#ifdef OBJECTSHADER_USE_DITHERING + nointerpolation float dither : DITHER; +#endif // OBJECTSHADER_USE_DITHERING + +#ifdef OBJECTSHADER_USE_EMISSIVE + uint emissiveColor : EMISSIVECOLOR; +#endif // OBJECTSHADER_USE_EMISSIVE #ifdef OBJECTSHADER_USE_COLOR float4 color : COLOR; #endif // OBJECTSHADER_USE_COLOR -#ifdef OBJECTSHADER_USE_DITHERING - nointerpolation float dither : DITHER; -#endif // OBJECTSHADER_USE_DITHERING - #ifdef OBJECTSHADER_USE_UVSETS float4 uvsets : UVSETS; #endif // OBJECTSHADER_USE_UVSETS @@ -590,10 +336,6 @@ struct PixelInput float3 pos3D : WORLDPOSITION; #endif // OBJECTSHADER_USE_POSITION3D -#ifdef OBJECTSHADER_USE_EMISSIVE - uint emissiveColor : EMISSIVECOLOR; -#endif // OBJECTSHADER_USE_EMISSIVE - #ifdef OBJECTSHADER_USE_RENDERTARGETARRAYINDEX #ifdef VPRT_EMULATION uint RTIndex : RTINDEX; @@ -603,23 +345,6 @@ struct PixelInput #endif // OBJECTSHADER_USE_RENDERTARGETARRAYINDEX }; -struct GBuffer -{ - float4 g0 : SV_TARGET0; /*FORMAT_R11G11B10_FLOAT*/ - float4 g1 : SV_TARGET1; /*FORMAT_R8G8B8A8_FLOAT*/ -}; -inline GBuffer CreateGBuffer(in float4 color, in Surface surface) -{ - GBuffer gbuffer; - gbuffer.g0 = color; -#ifdef BRDF_CLEARCOAT - gbuffer.g1 = float4(surface.clearcoat.N * 0.5f + 0.5f, surface.clearcoat.roughness); -#else - gbuffer.g1 = float4(surface.N * 0.5f + 0.5f, surface.roughness); -#endif // BRDF_CLEARCOAT - return gbuffer; -} - // METHODS //////////// @@ -629,15 +354,16 @@ inline void ApplyEmissive(in Surface surface, inout Lighting lighting) lighting.direct.specular += surface.emissiveColor.rgb * surface.emissiveColor.a; } -inline void LightMapping(in float2 ATLAS, inout Lighting lighting) +inline void LightMapping(in int lightmap, in float2 ATLAS, inout Lighting lighting) { [branch] - if (any(ATLAS)) + if (lightmap >= 0 && any(ATLAS)) { + Texture2D texture_lightmap = bindless_textures[NonUniformResourceIndex(lightmap)]; #ifdef LIGHTMAP_QUALITY_BICUBIC - lighting.indirect.diffuse = SampleTextureCatmullRom(texture_globallightmap, sampler_linear_clamp, ATLAS).rgb; + lighting.indirect.diffuse = SampleTextureCatmullRom(texture_lightmap, sampler_linear_clamp, ATLAS).rgb; #else - lighting.indirect.diffuse = texture_globallightmap.SampleLevel(sampler_linear_clamp, ATLAS, 0).rgb; + lighting.indirect.diffuse = texture_lightmap.SampleLevel(sampler_linear_clamp, ATLAS, 0).rgb; #endif // LIGHTMAP_QUALITY_BICUBIC } } @@ -662,7 +388,7 @@ inline void NormalMapping(in float4 uvsets, inout float3 N, in float3x3 TBN, out inline float3 PlanarReflection(in Surface surface, in float2 bumpColor) { - float4 reflectionUV = mul(g_xCamera_ReflVP, float4(surface.P, 1)); + float4 reflectionUV = mul(g_xCamera.ReflVP, float4(surface.P, 1)); reflectionUV.xy /= reflectionUV.w; reflectionUV.xy = reflectionUV.xy * float2(0.5, -0.5) + 0.5; return texture_reflection.SampleLevel(sampler_linear_clamp, reflectionUV.xy + bumpColor*GetMaterial().normalMapStrength, 0).rgb; @@ -726,22 +452,28 @@ inline void ForwardLighting(inout Surface surface, inout Lighting lighting) [branch] if (decalAccumulation.a < 1) { - ShaderEntity decal = EntityArray[g_xFrame_DecalArrayOffset + entity_index]; + ShaderEntity decal = EntityArray[g_xFrame.DecalArrayOffset + entity_index]; if ((decal.layerMask & surface.layerMask) == 0) continue; float4x4 decalProjection = MatrixArray[decal.GetMatrixIndex()]; - float4 texMulAdd = decalProjection[3]; + int decalTexture = asint(decalProjection[3][0]); + int decalNormal = asint(decalProjection[3][1]); decalProjection[3] = float4(0, 0, 0, 1); const float3 clipSpacePos = mul(decalProjection, float4(surface.P, 1)).xyz; const float3 uvw = clipSpacePos.xyz * float3(0.5, -0.5, 0.5) + 0.5; [branch] if (is_saturated(uvw)) { - // mipmapping needs to be performed by hand: - const float2 decalDX = mul(P_dx, (float3x3)decalProjection).xy * texMulAdd.xy; - const float2 decalDY = mul(P_dy, (float3x3)decalProjection).xy * texMulAdd.xy; - float4 decalColor = texture_decalatlas.SampleGrad(sampler_linear_clamp, uvw.xy * texMulAdd.xy + texMulAdd.zw, decalDX, decalDY); + float4 decalColor = 1; + [branch] + if (decalTexture >= 0) + { + // mipmapping needs to be performed by hand: + const float2 decalDX = mul(P_dx, (float3x3)decalProjection).xy; + const float2 decalDY = mul(P_dy, (float3x3)decalProjection).xy; + decalColor = bindless_textures[NonUniformResourceIndex(decalTexture)].SampleGrad(sampler_objectshader, uvw.xy, decalDX, decalDY); + } // blend out if close to cube Z: float edgeBlend = 1 - pow(saturate(abs(clipSpacePos.z)), 8); decalColor.a *= edgeBlend; @@ -795,7 +527,7 @@ inline void ForwardLighting(inout Surface surface, inout Lighting lighting) [branch] if (envmapAccumulation.a < 1) { - ShaderEntity probe = EntityArray[g_xFrame_EnvProbeArrayOffset + entity_index]; + ShaderEntity probe = EntityArray[g_xFrame.EnvProbeArrayOffset + entity_index]; if ((probe.layerMask & surface.layerMask) == 0) continue; @@ -847,7 +579,7 @@ inline void ForwardLighting(inout Surface surface, inout Lighting lighting) { // Loop through light buckets for the draw call: const uint first_item = 0; - const uint last_item = first_item + g_xFrame_LightArrayCount - 1; + const uint last_item = first_item + g_xFrame.LightArrayCount - 1; const uint first_bucket = first_item / 32; const uint last_bucket = min(last_item / 32, 1); // only 2 buckets max (uint2) for forward pass! [loop] @@ -863,7 +595,7 @@ inline void ForwardLighting(inout Surface surface, inout Lighting lighting) const uint entity_index = bucket * 32 + bucket_bit_index; bucket_bits ^= 1u << bucket_bit_index; - ShaderEntity light = EntityArray[g_xFrame_LightArrayOffset + entity_index]; + ShaderEntity light = EntityArray[g_xFrame.LightArrayOffset + entity_index]; if ((light.layerMask & surface.layerMask) == 0) continue; @@ -899,12 +631,12 @@ inline void ForwardLighting(inout Surface surface, inout Lighting lighting) inline void TiledLighting(inout Surface surface, inout Lighting lighting) { const uint2 tileIndex = uint2(floor(surface.pixel / TILED_CULLING_BLOCKSIZE)); - const uint flatTileIndex = flatten2D(tileIndex, g_xFrame_EntityCullingTileCount.xy) * SHADER_ENTITY_TILE_BUCKET_COUNT; + const uint flatTileIndex = flatten2D(tileIndex, g_xFrame.EntityCullingTileCount.xy) * SHADER_ENTITY_TILE_BUCKET_COUNT; #ifndef DISABLE_DECALS [branch] - if (g_xFrame_DecalArrayCount > 0) + if (g_xFrame.DecalArrayCount > 0) { // decals are enabled, loop through them first: float4 decalAccumulation = 0; @@ -912,8 +644,8 @@ inline void TiledLighting(inout Surface surface, inout Lighting lighting) const float3 P_dy = ddy_coarse(surface.P); // Loop through decal buckets in the tile: - const uint first_item = g_xFrame_DecalArrayOffset; - const uint last_item = first_item + g_xFrame_DecalArrayCount - 1; + const uint first_item = g_xFrame.DecalArrayOffset; + const uint last_item = first_item + g_xFrame.DecalArrayCount - 1; const uint first_bucket = first_item / 32; const uint last_bucket = min(last_item / 32, max(0, SHADER_ENTITY_TILE_BUCKET_COUNT - 1)); [loop] @@ -940,7 +672,8 @@ inline void TiledLighting(inout Surface surface, inout Lighting lighting) continue; float4x4 decalProjection = MatrixArray[decal.GetMatrixIndex()]; - float4 texMulAdd = decalProjection[3]; + int decalTexture = asint(decalProjection[3][0]); + int decalNormal = asint(decalProjection[3][1]); decalProjection[3] = float4(0, 0, 0, 1); const float3 clipSpacePos = mul(decalProjection, float4(surface.P, 1)).xyz; const float3 uvw = clipSpacePos.xyz * float3(0.5, -0.5, 0.5) + 0.5; @@ -948,9 +681,14 @@ inline void TiledLighting(inout Surface surface, inout Lighting lighting) if (is_saturated(uvw)) { // mipmapping needs to be performed by hand: - const float2 decalDX = mul(P_dx, (float3x3)decalProjection).xy * texMulAdd.xy; - const float2 decalDY = mul(P_dy, (float3x3)decalProjection).xy * texMulAdd.xy; - float4 decalColor = texture_decalatlas.SampleGrad(sampler_linear_clamp, uvw.xy * texMulAdd.xy + texMulAdd.zw, decalDX, decalDY); + float4 decalColor = 1; + [branch] + if (decalTexture >= 0) + { + const float2 decalDX = mul(P_dx, (float3x3)decalProjection).xy; + const float2 decalDY = mul(P_dy, (float3x3)decalProjection).xy; + decalColor = bindless_textures[NonUniformResourceIndex(decalTexture)].SampleGrad(sampler_objectshader, uvw.xy, decalDX, decalDY); + } // blend out if close to cube Z: float edgeBlend = 1 - pow(saturate(abs(clipSpacePos.z)), 8); decalColor.a *= edgeBlend; @@ -991,11 +729,11 @@ inline void TiledLighting(inout Surface surface, inout Lighting lighting) #ifndef DISABLE_LOCALENVPMAPS [branch] - if (g_xFrame_EnvProbeArrayCount > 0) + if (g_xFrame.EnvProbeArrayCount > 0) { // Loop through envmap buckets in the tile: - const uint first_item = g_xFrame_EnvProbeArrayOffset; - const uint last_item = first_item + g_xFrame_EnvProbeArrayCount - 1; + const uint first_item = g_xFrame.EnvProbeArrayOffset; + const uint last_item = first_item + g_xFrame.EnvProbeArrayCount - 1; const uint first_bucket = first_item / 32; const uint last_bucket = min(last_item / 32, max(0, SHADER_ENTITY_TILE_BUCKET_COUNT - 1)); [loop] @@ -1067,20 +805,20 @@ inline void TiledLighting(inout Surface surface, inout Lighting lighting) #endif //DISABLE_VOXELGI [branch] - if (g_xFrame_LightArrayCount > 0) + if (g_xFrame.LightArrayCount > 0) { uint4 shadow_mask_packed = 0; #ifdef SHADOW_MASK_ENABLED [branch] - if (g_xFrame_Options & OPTION_BIT_SHADOW_MASK) + if (g_xFrame.Options & OPTION_BIT_SHADOW_MASK) { shadow_mask_packed = texture_rtshadow[surface.pixel / 2]; } #endif // SHADOW_MASK_ENABLED // Loop through light buckets in the tile: - const uint first_item = g_xFrame_LightArrayOffset; - const uint last_item = first_item + g_xFrame_LightArrayCount - 1; + const uint first_item = g_xFrame.LightArrayOffset; + const uint last_item = first_item + g_xFrame.LightArrayCount - 1; const uint first_bucket = first_item / 32; const uint last_bucket = min(last_item / 32, max(0, SHADER_ENTITY_TILE_BUCKET_COUNT - 1)); [loop] @@ -1115,9 +853,9 @@ inline void TiledLighting(inout Surface surface, inout Lighting lighting) float shadow_mask = 1; #ifdef SHADOW_MASK_ENABLED [branch] - if (g_xFrame_Options & OPTION_BIT_SHADOW_MASK && light.IsCastingShadow()) + if (g_xFrame.Options & OPTION_BIT_SHADOW_MASK && light.IsCastingShadow()) { - uint shadow_index = entity_index - g_xFrame_LightArrayOffset; + uint shadow_index = entity_index - g_xFrame.LightArrayOffset; if (shadow_index < 16) { uint mask_shift = (shadow_index % 4) * 8; @@ -1162,6 +900,15 @@ inline void TiledLighting(inout Surface surface, inout Lighting lighting) } } + +#ifndef TRANSPARENT + [branch] + if (g_xFrame.Options & OPTION_BIT_SURFELGI_ENABLED && surfel_cellvalid(surfel_cell(surface.P))) + { + lighting.indirect.diffuse = texture_surfelgi[surface.pixel]; + } +#endif // TRANSPARENT + } inline void ApplyLighting(in Surface surface, in Lighting lighting, inout float4 color) @@ -1174,7 +921,7 @@ inline void ApplyFog(in float distance, float3 P, float3 V, inout float4 color) { const float fogAmount = GetFogAmount(distance, P, V); - if (g_xFrame_Options & OPTION_BIT_REALISTIC_SKY) + if (g_xFrame.Options & OPTION_BIT_REALISTIC_SKY) { const float3 skyLuminance = texture_skyluminancelut.SampleLevel(sampler_point_clamp, float2(0.5, 0.5), 0).rgb; color.rgb = lerp(color.rgb, skyLuminance, fogAmount); @@ -1197,26 +944,23 @@ PixelInput main(VertexInput input) { PixelInput Out; +#ifdef OBJECTSHADER_USE_INSTANCEID + Out.instanceID = input.GetInstancePointer().instanceID; +#endif // OBJECTSHADER_USE_INSTANCEID + VertexSurface surface; surface.create(GetMaterial(), input); Out.pos = surface.position; #ifndef OBJECTSHADER_USE_NOCAMERA - Out.pos = mul(g_xCamera_VP, Out.pos); + Out.pos = mul(g_xCamera.VP, Out.pos); #endif // OBJECTSHADER_USE_NOCAMERA #ifdef OBJECTSHADER_USE_CLIPPLANE - Out.clip = dot(surface.position, g_xCamera_ClipPlane); + Out.clip = dot(surface.position, g_xCamera.ClipPlane); #endif // OBJECTSHADER_USE_CLIPPLANE -#ifdef OBJECTSHADER_USE_POSITIONPREV - Out.pre = surface.positionPrev; -#ifndef OBJECTSHADER_USE_NOCAMERA - Out.pre = mul(g_xCamera_PrevVP, Out.pre); -#endif // OBJECTSHADER_USE_NOCAMERA -#endif // OBJECTSHADER_USE_POSITIONPREV - #ifdef OBJECTSHADER_USE_POSITION3D Out.pos3D = surface.position.xyz; #endif // OBJECTSHADER_USE_POSITION3D @@ -1250,7 +994,7 @@ PixelInput main(VertexInput input) #endif // OBJECTSHADER_USE_EMISSIVE #ifdef OBJECTSHADER_USE_RENDERTARGETARRAYINDEX - const uint frustum_index = input.GetInstanceUserdata().y; + const uint frustum_index = input.GetInstancePointer().GetFrustumIndex(); Out.RTIndex = xCubemapRenderCams[frustum_index].properties.x; #ifndef OBJECTSHADER_USE_NOCAMERA Out.pos = mul(xCubemapRenderCams[frustum_index].VP, surface.position); @@ -1283,11 +1027,11 @@ PixelInput main(VertexInput input) // entry point: -#ifdef OUTPUT_GBUFFER -GBuffer main(PixelInput input, in bool is_frontface : SV_IsFrontFace) +#ifdef PREPASS +uint2 main(PixelInput input, in uint primitiveID : SV_PrimitiveID) : SV_TARGET #else float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET -#endif // OUTPUT_GBUFFER +#endif // PREPASS // Pixel shader base: @@ -1295,7 +1039,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET const float depth = input.pos.z; const float lineardepth = input.pos.w; const float2 pixel = input.pos.xy; - const float2 ScreenCoord = pixel * g_xFrame_InternalResolution_rcp; + const float2 ScreenCoord = pixel * g_xFrame.InternalResolution_rcp; float3 bumpColor = 0; #ifndef DISABLE_ALPHATEST @@ -1310,14 +1054,6 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET #endif // ENVMAPRENDERING -#ifdef OBJECTSHADER_USE_POSITIONPREV - float2 pos2D = ScreenCoord * 2 - 1; - pos2D.y *= -1; - input.pre.xy /= input.pre.w; - const float2 velocity = ((input.pre.xy - g_xFrame_TemporalAAJitterPrev) - (pos2D.xy - g_xFrame_TemporalAAJitter)) * float2(0.5, -0.5); -#endif // OBJECTSHADER_USE_POSITIONPREV - - Surface surface; surface.init(); @@ -1332,7 +1068,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET #ifdef OBJECTSHADER_USE_POSITION3D surface.P = input.pos3D; - surface.V = g_xCamera_CamPos - surface.P; + surface.V = g_xCamera.CamPos - surface.P; float dist = length(surface.V); surface.V /= dist; #endif // OBJECTSHADER_USE_POSITION3D @@ -1359,7 +1095,11 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET #ifdef OBJECTSHADER_USE_UVSETS [branch] - if (GetMaterial().uvset_baseColorMap >= 0 && (g_xFrame_Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) +#ifdef PREPASS + if (GetMaterial().uvset_baseColorMap >= 0) +#else + if (GetMaterial().uvset_baseColorMap >= 0 && (g_xFrame.Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) +#endif // PREPASS { const float2 UV_baseColorMap = GetMaterial().uvset_baseColorMap == 0 ? input.uvsets.xy : input.uvsets.zw; float4 baseColorMap = texture_basecolormap.Sample(sampler_objectshader, UV_baseColorMap); @@ -1379,7 +1119,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET float alphatest = GetMaterial().alphaTest; #ifndef TRANSPARENT #ifndef ENVMAPRENDERING - if (g_xFrame_Options & OPTION_BIT_TEMPORALAA_ENABLED) + if (g_xFrame.Options & OPTION_BIT_TEMPORALAA_ENABLED) { alphatest = clamp(blue_noise(pixel, lineardepth).r, 0, 0.99); } @@ -1462,7 +1202,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET #ifdef OBJECTSHADER_USE_UVSETS [branch] - if (GetMaterial().uvset_baseColorMap >= 0 && (g_xFrame_Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) + if (GetMaterial().uvset_baseColorMap >= 0 && (g_xFrame.Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) { float2 uv = GetMaterial().uvset_baseColorMap == 0 ? input.uvsets.xy : input.uvsets.zw; color2 = texture_basecolormap.Sample(sampler_objectshader, uv); @@ -1524,7 +1264,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET #ifdef OBJECTSHADER_USE_UVSETS [branch] - if (GetMaterial1().uvset_baseColorMap >= 0 && (g_xFrame_Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) + if (GetMaterial1().uvset_baseColorMap >= 0 && (g_xFrame.Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) { float2 uv = GetMaterial1().uvset_baseColorMap == 0 ? input.uvsets.xy : input.uvsets.zw; color2 = texture_blend1_basecolormap.Sample(sampler_objectshader, uv); @@ -1586,7 +1326,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET #ifdef OBJECTSHADER_USE_UVSETS [branch] - if (GetMaterial2().uvset_baseColorMap >= 0 && (g_xFrame_Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) + if (GetMaterial2().uvset_baseColorMap >= 0 && (g_xFrame.Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) { float2 uv = GetMaterial2().uvset_baseColorMap == 0 ? input.uvsets.xy : input.uvsets.zw; color2 = texture_blend2_basecolormap.Sample(sampler_objectshader, uv); @@ -1648,7 +1388,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET #ifdef OBJECTSHADER_USE_UVSETS [branch] - if (GetMaterial3().uvset_baseColorMap >= 0 && (g_xFrame_Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) + if (GetMaterial3().uvset_baseColorMap >= 0 && (g_xFrame.Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) { float2 uv = GetMaterial3().uvset_baseColorMap == 0 ? input.uvsets.xy : input.uvsets.zw; color2 = texture_blend3_basecolormap.Sample(sampler_objectshader, uv); @@ -1829,13 +1569,13 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET bumpColor0 = 2 * texture_normalmap.Sample(sampler_objectshader, UV_normalMap - GetMaterial().texMulAdd.ww).rg - 1; bumpColor1 = 2 * texture_normalmap.Sample(sampler_objectshader, UV_normalMap + GetMaterial().texMulAdd.zw).rg - 1; } - bumpColor2 = texture_waterriples.SampleLevel(sampler_objectshader, ScreenCoord, 0).rg; + bumpColor2 = texture_waterriples.SampleLevel(sampler_linear_clamp, ScreenCoord, 0).rg; bumpColor = float3(bumpColor0 + bumpColor1 + bumpColor2, 1) * GetMaterial().refraction; surface.N = normalize(lerp(surface.N, mul(normalize(bumpColor), TBN), GetMaterial().normalMapStrength)); bumpColor *= GetMaterial().normalMapStrength; //REFLECTION - float4 reflectionUV = mul(g_xCamera_ReflVP, float4(surface.P, 1)); + float4 reflectionUV = mul(g_xCamera.ReflVP, float4(surface.P, 1)); reflectionUV.xy /= reflectionUV.w; reflectionUV.xy = reflectionUV.xy * float2(0.5, -0.5) + 0.5; lighting.indirect.specular += texture_reflection.SampleLevel(sampler_linear_mirror, reflectionUV.xy + bumpColor.rg, 0).rgb * surface.F; @@ -1862,7 +1602,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET float2 size; float mipLevels; texture_refraction.GetDimensions(0, size.x, size.y, mipLevels); - const float2 normal2D = mul((float3x3)g_xCamera_View, surface.N.xyz).xy; + const float2 normal2D = mul((float3x3)g_xCamera.View, surface.N.xyz).xy; float2 perturbatedRefrTexCoords = ScreenCoord.xy + normal2D * GetMaterial().refraction; float4 refractiveColor = texture_refraction.SampleLevel(sampler_linear_clamp, perturbatedRefrTexCoords, surface.roughness * mipLevels); surface.refraction.rgb = surface.albedo * refractiveColor.rgb; @@ -1872,7 +1612,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET #ifdef OBJECTSHADER_USE_ATLAS - LightMapping(input.atl, lighting); + LightMapping(load_instance(input.instanceID).lightmap, input.atl, lighting); #endif // OBJECTSHADER_USE_ATLAS @@ -1908,13 +1648,13 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET #ifdef WATER // WATER REFRACTION - float sampled_lineardepth = texture_lineardepth.SampleLevel(sampler_point_clamp, ScreenCoord.xy + bumpColor.rg, 0) * g_xCamera_ZFarP; + float sampled_lineardepth = texture_lineardepth.SampleLevel(sampler_point_clamp, ScreenCoord.xy + bumpColor.rg, 0) * g_xCamera.ZFarP; float depth_difference = sampled_lineardepth - lineardepth; surface.refraction.rgb = texture_refraction.SampleLevel(sampler_linear_mirror, ScreenCoord.xy + bumpColor.rg * saturate(0.5 * depth_difference), 0).rgb; if (depth_difference < 0) { // Fix cutoff by taking unperturbed depth diff to fill the holes with fog: - sampled_lineardepth = texture_lineardepth.SampleLevel(sampler_point_clamp, ScreenCoord.xy, 0) * g_xCamera_ZFarP; + sampled_lineardepth = texture_lineardepth.SampleLevel(sampler_point_clamp, ScreenCoord.xy, 0) * g_xCamera.ZFarP; depth_difference = sampled_lineardepth - lineardepth; } // WATER FOG: @@ -1935,7 +1675,7 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET #ifdef OBJECTSHADER_USE_POSITION3D - ApplyFog(dist, g_xCamera_CamPos, surface.V, color); + ApplyFog(dist, g_xCamera.CamPos, surface.V, color); #endif // OBJECTSHADER_USE_POSITION3D @@ -1944,13 +1684,13 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_TARGET // end point: #ifdef PREPASS - return float4(velocity, 0, 0); /*FORMAT_R16G16_FLOAT*/ -#else -#ifdef OUTPUT_GBUFFER - return CreateGBuffer(color, surface); + PrimitiveID prim; + prim.primitiveIndex = primitiveID; + prim.instanceIndex = input.instanceID; + prim.subsetIndex = GetSubsetIndex(); + return prim.pack(); #else return color; -#endif // OUTPUT_GBUFFER #endif // PREPASS } diff --git a/WickedEngine/shaders/objectHF_tessellation.hlsli b/WickedEngine/shaders/objectHF_tessellation.hlsli index 7f2c3f04e..fe39c2217 100644 --- a/WickedEngine/shaders/objectHF_tessellation.hlsli +++ b/WickedEngine/shaders/objectHF_tessellation.hlsli @@ -25,12 +25,12 @@ ConstantOutput PatchConstantFunction(InputPatch patch) for (uint ie = 0; ie < 3; ++ie) { #if 0 - output.edges[ie] = xTessellationFactors.x; + output.edges[ie] = GetMesh().tessellation_factor; #else float3 edge = patch[(ie + 1) % 3].pos.xyz - patch[ie].pos.xyz; - float3 vec = (patch[(ie + 1) % 3].pos.xyz + patch[ie].pos.xyz) / 2 - g_xCamera_CamPos.xyz; + float3 vec = (patch[(ie + 1) % 3].pos.xyz + patch[ie].pos.xyz) / 2 - g_xCamera.CamPos.xyz; float len = sqrt(dot(edge, edge) / dot(vec, vec)); - output.edges[(ie + 1) % 3] = max(1, len * xTessellationFactors.x); + output.edges[(ie + 1) % 3] = max(1, len * GetMesh().tessellation_factor); #endif } @@ -43,9 +43,9 @@ ConstantOutput PatchConstantFunction(InputPatch patch) for (int ip = 0; ip < 4; ++ip) { culled[ip] = 1; - culled[ip] &= dot(g_xCamera_FrustumPlanes[ip + 2], patch[0].pos) < -rad; - culled[ip] &= dot(g_xCamera_FrustumPlanes[ip + 2], patch[1].pos) < -rad; - culled[ip] &= dot(g_xCamera_FrustumPlanes[ip + 2], patch[2].pos) < -rad; + culled[ip] &= dot(g_xCamera.FrustumPlanes[ip + 2], patch[0].pos) < -rad; + culled[ip] &= dot(g_xCamera.FrustumPlanes[ip + 2], patch[1].pos) < -rad; + culled[ip] &= dot(g_xCamera.FrustumPlanes[ip + 2], patch[2].pos) < -rad; } if (culled[0] || culled[1] || culled[2] || culled[3]) output.edges[0] = 0; #endif @@ -151,16 +151,16 @@ PixelInput main(ConstantOutput input, float3 uvw : SV_DomainLocation, const Outp #ifdef OBJECTSHADER_USE_CLIPPLANE - output.clip = dot(output.pos, g_xCamera_ClipPlane); + output.clip = dot(output.pos, g_xCamera.ClipPlane); #endif // OBJECTSHADER_USE_CLIPPLANE #ifndef OBJECTSHADER_USE_NOCAMERA - output.pos = mul(g_xCamera_VP, output.pos); + output.pos = mul(g_xCamera.VP, output.pos); #endif // OBJECTSHADER_USE_NOCAMERA #ifdef OBJECTSHADER_USE_POSITIONPREV #ifndef OBJECTSHADER_USE_NOCAMERA - output.pre = mul(g_xCamera_PrevVP, output.pre); + output.pre = mul(g_xCamera.PrevVP, output.pre); #endif // OBJECTSHADER_USE_NOCAMERA #endif // OBJECTSHADER_USE_POSITIONPREV diff --git a/WickedEngine/shaders/objectHS_prepass.hlsl b/WickedEngine/shaders/objectHS_prepass.hlsl index 6975d2859..326490299 100644 --- a/WickedEngine/shaders/objectHS_prepass.hlsl +++ b/WickedEngine/shaders/objectHS_prepass.hlsl @@ -1,4 +1,4 @@ #define OBJECTSHADER_COMPILE_HS -#define OBJECTSHADER_LAYOUT_POS_PREVPOS_TEX +#define OBJECTSHADER_LAYOUT_PREPASS_TEX #define OBJECTSHADER_USE_NORMAL #include "objectHF_tessellation.hlsli" diff --git a/WickedEngine/shaders/objectHS_prepass_alphatest.hlsl b/WickedEngine/shaders/objectHS_prepass_alphatest.hlsl index 6975d2859..326490299 100644 --- a/WickedEngine/shaders/objectHS_prepass_alphatest.hlsl +++ b/WickedEngine/shaders/objectHS_prepass_alphatest.hlsl @@ -1,4 +1,4 @@ #define OBJECTSHADER_COMPILE_HS -#define OBJECTSHADER_LAYOUT_POS_PREVPOS_TEX +#define OBJECTSHADER_LAYOUT_PREPASS_TEX #define OBJECTSHADER_USE_NORMAL #include "objectHF_tessellation.hlsli" diff --git a/WickedEngine/shaders/objectHS_simple.hlsl b/WickedEngine/shaders/objectHS_simple.hlsl index a0865ca53..873883df0 100644 --- a/WickedEngine/shaders/objectHS_simple.hlsl +++ b/WickedEngine/shaders/objectHS_simple.hlsl @@ -1,5 +1,5 @@ #define OBJECTSHADER_COMPILE_HS -#define OBJECTSHADER_LAYOUT_POS_TEX +#define OBJECTSHADER_LAYOUT_SHADOW_TEX #define OBJECTSHADER_USE_COLOR #define OBJECTSHADER_USE_NORMAL #include "objectHF_tessellation.hlsli" diff --git a/WickedEngine/shaders/objectPS_hologram.hlsl b/WickedEngine/shaders/objectPS_hologram.hlsl index 3525b9822..7f560ae5d 100644 --- a/WickedEngine/shaders/objectPS_hologram.hlsl +++ b/WickedEngine/shaders/objectPS_hologram.hlsl @@ -6,7 +6,7 @@ float4 main(PixelInput input) : SV_TARGET { float4 color; [branch] - if (GetMaterial().uvset_baseColorMap >= 0 && (g_xFrame_Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) + if (GetMaterial().uvset_baseColorMap >= 0 && (g_xFrame.Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) { const float2 UV_baseColorMap = GetMaterial().uvset_baseColorMap == 0 ? input.uvsets.xy : input.uvsets.zw; color = texture_basecolormap.Sample(sampler_objectshader, UV_baseColorMap); @@ -30,15 +30,15 @@ float4 main(PixelInput input) : SV_TARGET } color.rgb += emissiveColor.rgb * emissiveColor.a; - float time = g_xFrame_Time; - float2 uv = input.pos.xy * g_xFrame_InternalResolution_rcp; - uv.y *= g_xFrame_InternalResolution.y * g_xFrame_InternalResolution_rcp.x; + float time = g_xFrame.Time; + float2 uv = input.pos.xy * g_xFrame.InternalResolution_rcp; + uv.y *= g_xFrame.InternalResolution.y * g_xFrame.InternalResolution_rcp.x; // wave: color.a *= sin(input.pos3D.y * 30 + time * 10) * 0.5 + 0.5; // rim: - color *= lerp(0.3, 6, pow(1 - saturate(dot(normalize(input.nor), normalize(g_xCamera_CamPos - input.pos3D))), 2)); + color *= lerp(0.3, 6, pow(1 - saturate(dot(normalize(input.nor), normalize(g_xCamera.CamPos - input.pos3D))), 2)); // keep some base color color.a += 0.2; diff --git a/WickedEngine/shaders/objectPS_paintradius.hlsl b/WickedEngine/shaders/objectPS_paintradius.hlsl index fae57afa6..e76dad8bc 100644 --- a/WickedEngine/shaders/objectPS_paintradius.hlsl +++ b/WickedEngine/shaders/objectPS_paintradius.hlsl @@ -1,6 +1,6 @@ -#define OBJECTSHADER_LAYOUT_POS_TEX +#define OBJECTSHADER_LAYOUT_SHADOW_TEX #include "objectHF.hlsli" -#include "ShaderInterop_Paint.h" +#include "ShaderInterop_Renderer.h" [earlydepthstencil] float4 main(PixelInput PSIn) : SV_TARGET diff --git a/WickedEngine/shaders/objectPS_prepass.hlsl b/WickedEngine/shaders/objectPS_prepass.hlsl index c29057a68..43d8ac384 100644 --- a/WickedEngine/shaders/objectPS_prepass.hlsl +++ b/WickedEngine/shaders/objectPS_prepass.hlsl @@ -1,5 +1,5 @@ #define OBJECTSHADER_COMPILE_PS -#define OBJECTSHADER_LAYOUT_POS_PREVPOS +#define OBJECTSHADER_LAYOUT_PREPASS #define PREPASS #define DISABLE_ALPHATEST #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/objectPS_prepass_alphatest.hlsl b/WickedEngine/shaders/objectPS_prepass_alphatest.hlsl index 5ad92aec1..034bdd816 100644 --- a/WickedEngine/shaders/objectPS_prepass_alphatest.hlsl +++ b/WickedEngine/shaders/objectPS_prepass_alphatest.hlsl @@ -1,5 +1,5 @@ #define OBJECTSHADER_COMPILE_PS -#define OBJECTSHADER_LAYOUT_POS_PREVPOS_TEX +#define OBJECTSHADER_LAYOUT_PREPASS_TEX #define PREPASS #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/objectPS_simple.hlsl b/WickedEngine/shaders/objectPS_simple.hlsl index d44cb329d..ebcb51d9f 100644 --- a/WickedEngine/shaders/objectPS_simple.hlsl +++ b/WickedEngine/shaders/objectPS_simple.hlsl @@ -1,4 +1,4 @@ -#define OBJECTSHADER_LAYOUT_POS_TEX +#define OBJECTSHADER_LAYOUT_SHADOW_TEX #define OBJECTSHADER_USE_COLOR #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/objectPS_voxelizer.hlsl b/WickedEngine/shaders/objectPS_voxelizer.hlsl index 0f06e7a8a..8a985448d 100644 --- a/WickedEngine/shaders/objectPS_voxelizer.hlsl +++ b/WickedEngine/shaders/objectPS_voxelizer.hlsl @@ -21,7 +21,7 @@ void main(PSInput input) float3 N = normalize(input.N); float3 P = input.P; - float3 diff = (P - g_xFrame_VoxelRadianceDataCenter) * g_xFrame_VoxelRadianceDataRes_rcp * g_xFrame_VoxelRadianceDataSize_rcp; + float3 diff = (P - g_xFrame.VoxelRadianceDataCenter) * g_xFrame.VoxelRadianceDataRes_rcp * g_xFrame.VoxelRadianceDataSize_rcp; float3 uvw = diff * float3(0.5f, -0.5f, 0.5f) + 0.5f; [branch] @@ -29,7 +29,7 @@ void main(PSInput input) { float4 baseColor; [branch] - if (GetMaterial().uvset_baseColorMap >= 0 && (g_xFrame_Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) + if (GetMaterial().uvset_baseColorMap >= 0 && (g_xFrame.Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) { const float2 UV_baseColorMap = GetMaterial().uvset_baseColorMap == 0 ? input.uvsets.xy : input.uvsets.zw; baseColor = texture_basecolormap.Sample(sampler_linear_wrap, UV_baseColorMap); @@ -63,7 +63,7 @@ void main(PSInput input) if (blend_weights.x > 0) { [branch] - if (GetMaterial().uvset_baseColorMap >= 0 && (g_xFrame_Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) + if (GetMaterial().uvset_baseColorMap >= 0 && (g_xFrame.Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) { float2 uv = GetMaterial().uvset_baseColorMap == 0 ? input.uvsets.xy : input.uvsets.zw; sam = texture_basecolormap.Sample(sampler_objectshader, uv); @@ -89,7 +89,7 @@ void main(PSInput input) if (blend_weights.y > 0) { [branch] - if (GetMaterial1().uvset_baseColorMap >= 0 && (g_xFrame_Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) + if (GetMaterial1().uvset_baseColorMap >= 0 && (g_xFrame.Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) { float2 uv = GetMaterial1().uvset_baseColorMap == 0 ? input.uvsets.xy : input.uvsets.zw; sam = texture_blend1_basecolormap.Sample(sampler_objectshader, uv); @@ -115,7 +115,7 @@ void main(PSInput input) if (blend_weights.z > 0) { [branch] - if (GetMaterial2().uvset_baseColorMap >= 0 && (g_xFrame_Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) + if (GetMaterial2().uvset_baseColorMap >= 0 && (g_xFrame.Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) { float2 uv = GetMaterial2().uvset_baseColorMap == 0 ? input.uvsets.xy : input.uvsets.zw; sam = texture_blend2_basecolormap.Sample(sampler_objectshader, uv); @@ -141,7 +141,7 @@ void main(PSInput input) if (blend_weights.w > 0) { [branch] - if (GetMaterial3().uvset_baseColorMap >= 0 && (g_xFrame_Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) + if (GetMaterial3().uvset_baseColorMap >= 0 && (g_xFrame.Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) { float2 uv = GetMaterial3().uvset_baseColorMap == 0 ? input.uvsets.xy : input.uvsets.zw; sam = texture_blend3_basecolormap.Sample(sampler_objectshader, uv); @@ -175,7 +175,7 @@ void main(PSInput input) { // Loop through light buckets for the draw call: const uint first_item = 0; - const uint last_item = first_item + g_xFrame_LightArrayCount - 1; + const uint last_item = first_item + g_xFrame.LightArrayCount - 1; const uint first_bucket = first_item / 32; const uint last_bucket = min(last_item / 32, 1); // only 2 buckets max (uint2) for forward pass! [loop] @@ -191,7 +191,7 @@ void main(PSInput input) const uint entity_index = bucket * 32 + bucket_bit_index; bucket_bits ^= 1u << bucket_bit_index; - ShaderEntity light = EntityArray[g_xFrame_LightArrayOffset + entity_index]; + ShaderEntity light = EntityArray[g_xFrame.LightArrayOffset + entity_index]; if (light.GetFlags() & ENTITY_FLAG_LIGHT_STATIC) { @@ -213,7 +213,7 @@ void main(PSInput input) [branch] if (light.IsCastingShadow() >= 0) { - const uint cascade = g_xFrame_ShadowCascadeCount - 1; // biggest cascade (coarsest resolution) will be used to voxelize + const uint cascade = g_xFrame.ShadowCascadeCount - 1; // biggest cascade (coarsest resolution) will be used to voxelize float3 ShPos = mul(MatrixArray[light.GetMatrixIndex() + cascade], float4(P, 1)).xyz; // ortho matrix, no divide by .w float3 ShTex = ShPos.xyz * float3(0.5f, -0.5f, 0.5f) + 0.5f; @@ -320,8 +320,8 @@ void main(PSInput input) uint normal_encoded = pack_unitvector(N); // output: - uint3 writecoord = floor(uvw * g_xFrame_VoxelRadianceDataRes); - uint id = flatten3D(writecoord, g_xFrame_VoxelRadianceDataRes); + uint3 writecoord = floor(uvw * g_xFrame.VoxelRadianceDataRes); + uint id = flatten3D(writecoord, g_xFrame.VoxelRadianceDataRes); InterlockedMax(output[id].colorMask, color_encoded); InterlockedMax(output[id].normalMask, normal_encoded); } diff --git a/WickedEngine/shaders/objectVS_prepass.hlsl b/WickedEngine/shaders/objectVS_prepass.hlsl index 5aca3adb7..46363f750 100644 --- a/WickedEngine/shaders/objectVS_prepass.hlsl +++ b/WickedEngine/shaders/objectVS_prepass.hlsl @@ -1,3 +1,3 @@ #define OBJECTSHADER_COMPILE_VS -#define OBJECTSHADER_LAYOUT_POS_PREVPOS +#define OBJECTSHADER_LAYOUT_PREPASS #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/objectVS_prepass_alphatest.hlsl b/WickedEngine/shaders/objectVS_prepass_alphatest.hlsl index d11b3e690..eb28e2a95 100644 --- a/WickedEngine/shaders/objectVS_prepass_alphatest.hlsl +++ b/WickedEngine/shaders/objectVS_prepass_alphatest.hlsl @@ -1,3 +1,3 @@ #define OBJECTSHADER_COMPILE_VS -#define OBJECTSHADER_LAYOUT_POS_PREVPOS_TEX +#define OBJECTSHADER_LAYOUT_PREPASS_TEX #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/objectVS_prepass_alphatest_tessellation.hlsl b/WickedEngine/shaders/objectVS_prepass_alphatest_tessellation.hlsl index a0ca9bcf4..6af689c42 100644 --- a/WickedEngine/shaders/objectVS_prepass_alphatest_tessellation.hlsl +++ b/WickedEngine/shaders/objectVS_prepass_alphatest_tessellation.hlsl @@ -1,5 +1,5 @@ #define OBJECTSHADER_COMPILE_VS -#define OBJECTSHADER_LAYOUT_POS_PREVPOS_TEX +#define OBJECTSHADER_LAYOUT_PREPASS_TEX #define OBJECTSHADER_USE_NOCAMERA #define OBJECTSHADER_USE_NORMAL #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/objectVS_prepass_tessellation.hlsl b/WickedEngine/shaders/objectVS_prepass_tessellation.hlsl index 1c9cdb984..08bbd402f 100644 --- a/WickedEngine/shaders/objectVS_prepass_tessellation.hlsl +++ b/WickedEngine/shaders/objectVS_prepass_tessellation.hlsl @@ -1,5 +1,5 @@ #define OBJECTSHADER_COMPILE_VS -#define OBJECTSHADER_LAYOUT_POS_PREVPOS_TEX +#define OBJECTSHADER_LAYOUT_PREPASS_TEX #define OBJECTSHADER_USE_NOCAMERA #define OBJECTSHADER_USE_NORMAL #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/objectVS_simple.hlsl b/WickedEngine/shaders/objectVS_simple.hlsl index f6b448015..ba84a94e2 100644 --- a/WickedEngine/shaders/objectVS_simple.hlsl +++ b/WickedEngine/shaders/objectVS_simple.hlsl @@ -1,4 +1,4 @@ #define OBJECTSHADER_COMPILE_VS -#define OBJECTSHADER_LAYOUT_POS_TEX +#define OBJECTSHADER_LAYOUT_SHADOW_TEX #define OBJECTSHADER_USE_COLOR #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/objectVS_simple_tessellation.hlsl b/WickedEngine/shaders/objectVS_simple_tessellation.hlsl index 75c657964..6e58c0a4e 100644 --- a/WickedEngine/shaders/objectVS_simple_tessellation.hlsl +++ b/WickedEngine/shaders/objectVS_simple_tessellation.hlsl @@ -1,5 +1,5 @@ #define OBJECTSHADER_COMPILE_VS -#define OBJECTSHADER_LAYOUT_POS_TEX +#define OBJECTSHADER_LAYOUT_SHADOW_TEX #define OBJECTSHADER_USE_COLOR #define OBJECTSHADER_USE_NORMAL #define OBJECTSHADER_USE_NOCAMERA diff --git a/WickedEngine/shaders/oceanSimulatorCS.hlsl b/WickedEngine/shaders/oceanSimulatorCS.hlsl index 061d2a55a..a390ae5b7 100644 --- a/WickedEngine/shaders/oceanSimulatorCS.hlsl +++ b/WickedEngine/shaders/oceanSimulatorCS.hlsl @@ -17,7 +17,7 @@ void main(uint3 DTid : SV_DispatchThreadID) float2 h0_k = g_InputH0[in_index]; float2 h0_mk = g_InputH0[in_mindex]; float sin_v, cos_v; - sincos(g_InputOmega[in_index] * g_xFrame_Time * g_TimeScale, sin_v, cos_v); + sincos(g_InputOmega[in_index] * g_xFrame.Time * g_TimeScale, sin_v, cos_v); float2 ht; ht.x = (h0_k.x + h0_mk.x) * cos_v - (h0_k.y + h0_mk.y) * sin_v; diff --git a/WickedEngine/shaders/oceanSurfacePS.hlsl b/WickedEngine/shaders/oceanSurfacePS.hlsl index e15bb3f2a..c113747d3 100644 --- a/WickedEngine/shaders/oceanSurfacePS.hlsl +++ b/WickedEngine/shaders/oceanSurfacePS.hlsl @@ -11,7 +11,7 @@ TEXTURE2D(texture_gradientmap, float4, TEXSLOT_ONDEMAND1); float4 main(PSIn input) : SV_TARGET { float4 color = xOceanWaterColor; - float3 V = g_xCamera_CamPos - input.pos3D; + float3 V = g_xCamera.CamPos - input.pos3D; float dist = length(V); V /= dist; float emissive = 0; @@ -40,7 +40,7 @@ float4 main(PSIn input) : SV_TARGET TiledLighting(surface, lighting); float2 refUV = float2(1, -1)*input.ReflectionMapSamplingPos.xy / input.ReflectionMapSamplingPos.w * 0.5f + 0.5f; - float2 ScreenCoord = surface.pixel * g_xFrame_InternalResolution_rcp; + float2 ScreenCoord = surface.pixel * g_xFrame.InternalResolution_rcp; //REFLECTION float2 RefTex = float2(1, -1)*input.ReflectionMapSamplingPos.xy / input.ReflectionMapSamplingPos.w / 2.0f + 0.5f; @@ -49,24 +49,24 @@ float4 main(PSIn input) : SV_TARGET // WATER REFRACTION float lineardepth = input.pos.w; - float sampled_lineardepth = texture_lineardepth.SampleLevel(sampler_point_clamp, ScreenCoord.xy + surface.N.xz * 0.04f, 0) * g_xCamera_ZFarP; + float sampled_lineardepth = texture_lineardepth.SampleLevel(sampler_point_clamp, ScreenCoord.xy + surface.N.xz * 0.04f, 0) * g_xCamera.ZFarP; float depth_difference = sampled_lineardepth - lineardepth; surface.refraction.rgb = texture_refraction.SampleLevel(sampler_linear_mirror, ScreenCoord.xy + surface.N.xz * 0.04f * saturate(0.5 * depth_difference), 0).rgb; if (depth_difference < 0) { // Fix cutoff by taking unperturbed depth diff to fill the holes with fog: - sampled_lineardepth = texture_lineardepth.SampleLevel(sampler_point_clamp, ScreenCoord.xy, 0) * g_xCamera_ZFarP; + sampled_lineardepth = texture_lineardepth.SampleLevel(sampler_point_clamp, ScreenCoord.xy, 0) * g_xCamera.ZFarP; depth_difference = sampled_lineardepth - lineardepth; } // WATER FOG: surface.refraction.a = 1 - saturate(color.a * 0.1f * depth_difference); // Blend out at distance: - color.a = pow(saturate(1 - saturate(dist / g_xCamera_ZFarP)), 2); + color.a = pow(saturate(1 - saturate(dist / g_xCamera.ZFarP)), 2); ApplyLighting(surface, lighting, color); - ApplyFog(dist, g_xCamera_CamPos, V, color); + ApplyFog(dist, g_xCamera.CamPos, V, color); return color; } diff --git a/WickedEngine/shaders/oceanSurfaceVS.hlsl b/WickedEngine/shaders/oceanSurfaceVS.hlsl index 3a70b5624..e29002e08 100644 --- a/WickedEngine/shaders/oceanSurfaceVS.hlsl +++ b/WickedEngine/shaders/oceanSurfaceVS.hlsl @@ -12,7 +12,7 @@ static const float3 QUAD[] = { float3(0, 1, 0), }; -#define infinite g_xCamera_ZFarP +#define infinite g_xCamera.ZFarP float3 intersectPlaneClampInfinite(in float3 rayOrigin, in float3 rayDirection, in float3 planeNormal, float planeHeight) { float dist = (planeHeight - dot(planeNormal, rayOrigin)) / dot(planeNormal, rayDirection); @@ -42,8 +42,8 @@ PSIn main(uint fakeIndex : SV_VERTEXID) Out.pos.xy *= max(1, xOceanSurfaceDisplacementTolerance); // extrude screen space grid to tolerate displacement // Perform ray tracing of screen grid and plane surface to unproject to world space: - float3 o = g_xCamera_CamPos; - float4 r = mul(g_xCamera_InvVP, float4(Out.pos.xy, 0, 1)); + float3 o = g_xCamera.CamPos; + float4 r = mul(g_xCamera.InvVP, float4(Out.pos.xy, 0, 1)); r.xyz /= r.w; float3 d = normalize(o.xyz - r.xyz); @@ -52,14 +52,14 @@ PSIn main(uint fakeIndex : SV_VERTEXID) // Displace surface: float2 uv = worldPos.xz * xOceanPatchSizeRecip; float3 displacement = texture_displacementmap.SampleLevel(sampler_linear_wrap, uv + xOceanMapHalfTexel, 0).xzy; - displacement *= 1 - saturate(distance(g_xCamera_CamPos, worldPos) * 0.0025f); + displacement *= 1 - saturate(distance(g_xCamera.CamPos, worldPos) * 0.0025f); worldPos += displacement; // Reproject displaced surface and output: - Out.pos = mul(g_xCamera_VP, float4(worldPos, 1)); + Out.pos = mul(g_xCamera.VP, float4(worldPos, 1)); Out.pos3D = worldPos; Out.uv = uv; - Out.ReflectionMapSamplingPos = mul(g_xCamera_ReflVP, float4(worldPos, 1)); + Out.ReflectionMapSamplingPos = mul(g_xCamera.ReflVP, float4(worldPos, 1)); return Out; } diff --git a/WickedEngine/shaders/paint_textureCS.hlsl b/WickedEngine/shaders/paint_textureCS.hlsl index f9579d122..b0359fce8 100644 --- a/WickedEngine/shaders/paint_textureCS.hlsl +++ b/WickedEngine/shaders/paint_textureCS.hlsl @@ -1,5 +1,7 @@ #include "globals.hlsli" -#include "ShaderInterop_Paint.h" +#include "ShaderInterop_Renderer.h" + +PUSHCONSTANT(push, PaintTextureCB); TEXTURE2D(texture_brush, float4, TEXSLOT_ONDEMAND0); @@ -8,12 +10,12 @@ RWTEXTURE2D(output, unorm float4, 0); [numthreads(PAINT_TEXTURE_BLOCKSIZE, PAINT_TEXTURE_BLOCKSIZE, 1)] void main( uint3 DTid : SV_DispatchThreadID ) { - const uint2 pixel = xPaintBrushCenter + DTid.xy - xPaintBrushRadius.xx; - const float2 uv = (DTid.xy + 0.5f) / xPaintBrushRadius.xx; - const float4 color = texture_brush.SampleLevel(sampler_linear_clamp, uv, 0) * unpack_rgba(xPaintBrushColor); - const float dist = distance((float2)pixel, (float2)xPaintBrushCenter); - const float affection = xPaintBrushAmount * pow(1 - saturate(dist / (float)xPaintBrushRadius), xPaintBrushFalloff); - if (affection > 0 && dist < (float)xPaintBrushRadius) + const uint2 pixel = push.xPaintBrushCenter + DTid.xy - push.xPaintBrushRadius.xx; + const float2 uv = (DTid.xy + 0.5f) / push.xPaintBrushRadius.xx; + const float4 color = texture_brush.SampleLevel(sampler_linear_clamp, uv, 0) * unpack_rgba(push.xPaintBrushColor); + const float dist = distance((float2)pixel, (float2)push.xPaintBrushCenter); + const float affection = push.xPaintBrushAmount * pow(1 - saturate(dist / (float)push.xPaintBrushRadius), push.xPaintBrushFalloff); + if (affection > 0 && dist < (float)push.xPaintBrushRadius) { output[pixel] = lerp(output[pixel], color, affection); } diff --git a/WickedEngine/shaders/raytraceCS.hlsl b/WickedEngine/shaders/raytraceCS.hlsl index 1ffedf8d3..3d6b98fde 100644 --- a/WickedEngine/shaders/raytraceCS.hlsl +++ b/WickedEngine/shaders/raytraceCS.hlsl @@ -31,12 +31,12 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) RayDesc ray = CreateCameraRay(uv); // Depth of field setup: - float3 focal_point = ray.Origin + ray.Direction * g_xCamera_FocalLength; + float3 focal_point = ray.Origin + ray.Direction * g_xCamera.FocalLength; float3 coc = float3(hemispherepoint_cos(rand(seed, uv), rand(seed, uv)).xy, 0); - coc.xy *= g_xCamera_ApertureShape.xy; - coc = mul(coc, float3x3(cross(g_xCamera_Up, g_xCamera_At), g_xCamera_Up, g_xCamera_At)); - coc *= g_xCamera_FocalLength; - coc *= g_xCamera_ApertureSize; + coc.xy *= g_xCamera.ApertureShape.xy; + coc = mul(coc, float3x3(cross(g_xCamera.Up, g_xCamera.At), g_xCamera.Up, g_xCamera.At)); + coc *= g_xCamera.FocalLength; + coc *= g_xCamera.ApertureSize; coc *= 0.1f; ray.Origin = ray.Origin + coc; ray.Direction = focal_point - ray.Origin; // will be normalized before tracing! @@ -89,35 +89,23 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) } Surface surface; - ShaderMaterial material; #ifdef RTAPI // ray origin updated for next bounce: ray.Origin = q.WorldRayOrigin() + q.WorldRayDirection() * q.CommittedRayT(); - ShaderMesh mesh = bindless_buffers[NonUniformResourceIndex(q.CommittedInstanceID())].Load(0); - ShaderMeshSubset subset = bindless_subsets[NonUniformResourceIndex(mesh.subsetbuffer)][q.CommittedGeometryIndex()]; - material = bindless_buffers[NonUniformResourceIndex(subset.material)].Load(0); + PrimitiveID prim; + prim.primitiveIndex = q.CommittedPrimitiveIndex(); + prim.instanceIndex = q.CommittedInstanceID(); + prim.subsetIndex = q.CommittedGeometryIndex(); - EvaluateObjectSurface( - mesh, - subset, - material, - q.CommittedPrimitiveIndex(), - q.CommittedTriangleBarycentrics(), - q.CommittedObjectToWorld3x4(), - surface - ); + surface.load(prim, q.CommittedTriangleBarycentrics()); #else // ray origin updated for next bounce: ray.Origin = ray.Origin + ray.Direction * hit.distance; - EvaluateObjectSurface( - hit, - material, - surface - ); + surface.load(hit.primitiveID, hit.bary); #endif // RTAPI @@ -125,14 +113,18 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) surface.V = -ray.Direction; surface.update(); + result += max(0, energy * surface.emissiveColor.rgb * surface.emissiveColor.a); + + + // Light sampling: [loop] - for (uint iterator = 0; iterator < g_xFrame_LightArrayCount; iterator++) + for (uint iterator = 0; iterator < g_xFrame.LightArrayCount; iterator++) { - ShaderEntity light = EntityArray[g_xFrame_LightArrayOffset + iterator]; + ShaderEntity light = EntityArray[g_xFrame.LightArrayOffset + iterator]; Lighting lighting; lighting.create(0, 0, 0, 0); @@ -158,9 +150,9 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) lightColor = light.GetColor().rgb * light.GetEnergy(); float3 atmosphereTransmittance = 1; - if (g_xFrame_Options & OPTION_BIT_REALISTIC_SKY) + if (g_xFrame.Options & OPTION_BIT_REALISTIC_SKY) { - AtmosphereParameters Atmosphere = g_xFrame_Atmosphere; + AtmosphereParameters Atmosphere = g_xFrame.Atmosphere; atmosphereTransmittance = GetAtmosphericLightTransmittance(Atmosphere, surface.P, L, texture_transmittancelut); } lightColor *= atmosphereTransmittance; @@ -249,25 +241,13 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) ); while (q.Proceed()) { - ShaderMesh mesh = bindless_buffers[NonUniformResourceIndex(q.CandidateInstanceID())].Load(0); - ShaderMeshSubset subset = bindless_subsets[NonUniformResourceIndex(mesh.subsetbuffer)][q.CandidateGeometryIndex()]; - ShaderMaterial material = bindless_buffers[NonUniformResourceIndex(subset.material)].Load(0); - [branch] - if (!material.IsCastingShadow()) - { - continue; - } + PrimitiveID prim; + prim.primitiveIndex = q.CandidatePrimitiveIndex(); + prim.instanceIndex = q.CandidateInstanceID(); + prim.subsetIndex = q.CandidateGeometryIndex(); Surface surface; - EvaluateObjectSurface( - mesh, - subset, - material, - q.CandidatePrimitiveIndex(), - q.CandidateTriangleBarycentrics(), - q.CandidateObjectToWorld3x4(), - surface - ); + surface.load(prim, q.CandidateTriangleBarycentrics()); shadow *= lerp(1, surface.albedo * surface.transmission, surface.opacity); @@ -291,6 +271,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) } + if (bounce == 0) { primary_albedo = surface.albedo; @@ -317,7 +298,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex) if (roulette <= refractChance) { // Refraction - const float3 R = refract(ray.Direction, surface.N, 1 - material.refraction); + const float3 R = refract(ray.Direction, surface.N, 1 - surface.material.refraction); ray.Direction = lerp(R, SampleHemisphere_cos(R, seed, uv), surface.roughnessBRDF); energy *= surface.albedo; diff --git a/WickedEngine/shaders/raytracingHF.hlsli b/WickedEngine/shaders/raytracingHF.hlsli index d423eb93d..0efe6309a 100644 --- a/WickedEngine/shaders/raytracingHF.hlsli +++ b/WickedEngine/shaders/raytracingHF.hlsli @@ -17,11 +17,11 @@ struct RayDesc inline RayDesc CreateCameraRay(float2 clipspace) { - float4 unprojected = mul(g_xCamera_InvVP, float4(clipspace, 0, 1)); + float4 unprojected = mul(g_xCamera.InvVP, float4(clipspace, 0, 1)); unprojected.xyz /= unprojected.w; RayDesc ray; - ray.Origin = g_xCamera_CamPos; + ray.Origin = g_xCamera.CamPos; ray.Direction = normalize(unprojected.xyz - ray.Origin); ray.TMin = 0.001; ray.TMax = FLT_MAX; @@ -33,153 +33,6 @@ inline RayDesc CreateCameraRay(float2 clipspace) // Hardware acceleration raytracing path: RAYTRACINGACCELERATIONSTRUCTURE(scene_acceleration_structure, TEXSLOT_ACCELERATION_STRUCTURE); -Texture2D bindless_textures[] : register(t0, space1); -ByteAddressBuffer bindless_buffers[] : register(t0, space2); -StructuredBuffer bindless_subsets[] : register(t0, space3); -Buffer bindless_ib[] : register(t0, space4); - -void EvaluateObjectSurface( - in ShaderMesh mesh, - in ShaderMeshSubset subset, - in ShaderMaterial material, - in uint primitiveIndex, - in float2 barycentrics, - in float3x4 worldMatrix, - out Surface surface -) -{ - uint startIndex = primitiveIndex * 3 + subset.indexOffset; - uint i0 = bindless_ib[NonUniformResourceIndex(mesh.ib)][startIndex + 0]; - uint i1 = bindless_ib[NonUniformResourceIndex(mesh.ib)][startIndex + 1]; - uint i2 = bindless_ib[NonUniformResourceIndex(mesh.ib)][startIndex + 2]; - float4 uv0 = 0, uv1 = 0, uv2 = 0; - [branch] - if (mesh.vb_uv0 >= 0) - { - uv0.xy = unpack_half2(bindless_buffers[NonUniformResourceIndex(mesh.vb_uv0)].Load(i0 * 4)); - uv1.xy = unpack_half2(bindless_buffers[NonUniformResourceIndex(mesh.vb_uv0)].Load(i1 * 4)); - uv2.xy = unpack_half2(bindless_buffers[NonUniformResourceIndex(mesh.vb_uv0)].Load(i2 * 4)); - } - [branch] - if (mesh.vb_uv1 >= 0) - { - uv0.zw = unpack_half2(bindless_buffers[NonUniformResourceIndex(mesh.vb_uv1)].Load(i0 * 4)); - uv1.zw = unpack_half2(bindless_buffers[NonUniformResourceIndex(mesh.vb_uv1)].Load(i1 * 4)); - uv2.zw = unpack_half2(bindless_buffers[NonUniformResourceIndex(mesh.vb_uv1)].Load(i2 * 4)); - } - float3 n0 = 0, n1 = 0, n2 = 0; - [branch] - if (mesh.vb_pos_nor_wind >= 0) - { - const uint stride_POS = 16; - n0 = unpack_unitvector(bindless_buffers[NonUniformResourceIndex(mesh.vb_pos_nor_wind)].Load4(i0 * stride_POS).w); - n1 = unpack_unitvector(bindless_buffers[NonUniformResourceIndex(mesh.vb_pos_nor_wind)].Load4(i1 * stride_POS).w); - n2 = unpack_unitvector(bindless_buffers[NonUniformResourceIndex(mesh.vb_pos_nor_wind)].Load4(i2 * stride_POS).w); - } - else - { - surface.init(); - return; // error, this should always be good - } - - float u = barycentrics.x; - float v = barycentrics.y; - float w = 1 - u - v; - float4 uvsets = uv0 * w + uv1 * u + uv2 * v; - - float4 baseColor = material.baseColor; - [branch] - if (material.texture_basecolormap_index >= 0 && (g_xFrame_Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) - { - const float2 UV_baseColorMap = material.uvset_baseColorMap == 0 ? uvsets.xy : uvsets.zw; - float4 baseColorMap = bindless_textures[NonUniformResourceIndex(material.texture_basecolormap_index)].SampleLevel(sampler_linear_wrap, UV_baseColorMap, 0); - baseColorMap.rgb *= DEGAMMA(baseColorMap.rgb); - baseColor *= baseColorMap; - } - - [branch] - if (mesh.vb_col >= 0 && material.IsUsingVertexColors()) - { - float4 c0, c1, c2; - const uint stride_COL = 4; - c0 = unpack_rgba(bindless_buffers[NonUniformResourceIndex(mesh.vb_col)].Load(i0 * stride_COL)); - c1 = unpack_rgba(bindless_buffers[NonUniformResourceIndex(mesh.vb_col)].Load(i1 * stride_COL)); - c2 = unpack_rgba(bindless_buffers[NonUniformResourceIndex(mesh.vb_col)].Load(i2 * stride_COL)); - float4 vertexColor = c0 * w + c1 * u + c2 * v; - baseColor *= vertexColor; - } - - float4 surfaceMap = 1; - [branch] - if (material.texture_surfacemap_index >= 0) - { - const float2 UV_surfaceMap = material.uvset_surfaceMap == 0 ? uvsets.xy : uvsets.zw; - surfaceMap = bindless_textures[NonUniformResourceIndex(material.texture_surfacemap_index)].SampleLevel(sampler_linear_wrap, UV_surfaceMap, 0); - } - - float4 specularMap = 1; - [branch] - if (material.texture_specularmap_index >= 0) - { - const float2 UV_specularMap = material.uvset_specularMap == 0 ? uvsets.xy : uvsets.zw; - specularMap = bindless_textures[NonUniformResourceIndex(material.texture_specularmap_index)].SampleLevel(sampler_linear_wrap, UV_specularMap, 0); - specularMap.rgb = DEGAMMA(specularMap.rgb); - } - - surface.create(material, baseColor, surfaceMap, specularMap); - - surface.emissiveColor = material.emissiveColor; - [branch] - if (material.texture_emissivemap_index >= 0) - { - const float2 UV_emissiveMap = material.uvset_emissiveMap == 0 ? uvsets.xy : uvsets.zw; - float4 emissiveMap = bindless_textures[NonUniformResourceIndex(material.texture_emissivemap_index)].SampleLevel(sampler_linear_wrap, UV_emissiveMap, 0); - emissiveMap.rgb = DEGAMMA(emissiveMap.rgb); - surface.emissiveColor *= emissiveMap; - } - - surface.transmission = material.transmission; - if (material.texture_transmissionmap_index >= 0) - { - const float2 UV_transmissionMap = material.uvset_transmissionMap == 0 ? uvsets.xy : uvsets.zw; - float transmissionMap = bindless_textures[NonUniformResourceIndex(material.texture_transmissionmap_index)].SampleLevel(sampler_linear_wrap, UV_transmissionMap, 0).r; - surface.transmission *= transmissionMap; - } - - [branch] - if (material.IsOcclusionEnabled_Secondary() && material.texture_occlusionmap_index >= 0) - { - const float2 UV_occlusionMap = material.uvset_occlusionMap == 0 ? uvsets.xy : uvsets.zw; - surface.occlusion *= bindless_textures[NonUniformResourceIndex(material.texture_occlusionmap_index)].SampleLevel(sampler_linear_wrap, UV_occlusionMap, 0).r; - } - - surface.N = n0 * w + n1 * u + n2 * v; - surface.N = mul((float3x3)worldMatrix, surface.N); - surface.N = normalize(surface.N); - surface.facenormal = surface.N; - - [branch] - if (mesh.vb_tan >= 0 && material.texture_normalmap_index >= 0 && material.normalMapStrength > 0) - { - float4 t0, t1, t2; - const uint stride_TAN = 4; - t0 = unpack_utangent(bindless_buffers[NonUniformResourceIndex(mesh.vb_tan)].Load(i0 * stride_TAN)); - t1 = unpack_utangent(bindless_buffers[NonUniformResourceIndex(mesh.vb_tan)].Load(i1 * stride_TAN)); - t2 = unpack_utangent(bindless_buffers[NonUniformResourceIndex(mesh.vb_tan)].Load(i2 * stride_TAN)); - float4 T = t0 * w + t1 * u + t2 * v; - T = T * 2 - 1; - T.xyz = mul((float3x3)worldMatrix, T.xyz); - T.xyz = normalize(T.xyz); - float3 B = normalize(cross(T.xyz, surface.N) * T.w); - float3x3 TBN = float3x3(T.xyz, B, surface.N); - - const float2 UV_normalMap = material.uvset_normalMap == 0 ? uvsets.xy : uvsets.zw; - float3 normalMap = bindless_textures[NonUniformResourceIndex(material.texture_normalmap_index)].SampleLevel(sampler_linear_wrap, UV_normalMap, 0).rgb; - normalMap.b = normalMap.b == 0 ? 1 : normalMap.b; // fix for missing blue channel - normalMap = normalMap * 2 - 1; - surface.N = normalize(lerp(surface.N, mul(normalMap, TBN), material.normalMapStrength)); - } -} #else @@ -194,18 +47,15 @@ void EvaluateObjectSurface( groupshared uint stack[RAYTRACE_STACKSIZE][RAYTRACING_LAUNCH_BLOCKSIZE * RAYTRACING_LAUNCH_BLOCKSIZE]; #endif // RAYTRACE_STACK_SHARED -STRUCTUREDBUFFER(materialBuffer, ShaderMaterial, TEXSLOT_ONDEMAND0); -TEXTURE2D(materialTextureAtlas, float4, TEXSLOT_ONDEMAND1); -RAWBUFFER(primitiveCounterBuffer, TEXSLOT_ONDEMAND2); -STRUCTUREDBUFFER(primitiveBuffer, BVHPrimitive, TEXSLOT_ONDEMAND3); -STRUCTUREDBUFFER(primitiveDataBuffer, BVHPrimitiveData, TEXSLOT_ONDEMAND4); -STRUCTUREDBUFFER(bvhNodeBuffer, BVHNode, TEXSLOT_ONDEMAND5); +RAWBUFFER(primitiveCounterBuffer, TEXSLOT_BVH_COUNTER); +STRUCTUREDBUFFER(primitiveBuffer, BVHPrimitive, TEXSLOT_BVH_PRIMITIVES); +STRUCTUREDBUFFER(bvhNodeBuffer, BVHNode, TEXSLOT_BVH_NODES); struct RayHit { float2 bary; float distance; - uint primitiveID; + PrimitiveID primitiveID; }; inline RayHit CreateRayHit() @@ -213,135 +63,30 @@ inline RayHit CreateRayHit() RayHit hit; hit.bary = 0; hit.distance = FLT_MAX; - hit.primitiveID = ~0u; return hit; } -struct TriangleData -{ - float3 n0, n1, n2; // normals - float4 u0, u1, u2; // uv sets - float4 c0, c1, c2; // vertex colors - float3 tangent; - float3 binormal; - uint materialIndex; -}; -inline TriangleData TriangleData_Unpack(in BVHPrimitive prim, in BVHPrimitiveData primdata) -{ - TriangleData tri; - - tri.n0 = unpack_unitvector(prim.n0); - tri.n1 = unpack_unitvector(prim.n1); - tri.n2 = unpack_unitvector(prim.n2); - - tri.u0 = unpack_half4(primdata.u0); - tri.u1 = unpack_half4(primdata.u1); - tri.u2 = unpack_half4(primdata.u2); - - tri.c0 = unpack_rgba(primdata.c0); - tri.c1 = unpack_rgba(primdata.c1); - tri.c2 = unpack_rgba(primdata.c2); - - tri.tangent = unpack_unitvector(primdata.tangent); - tri.binormal = unpack_unitvector(primdata.binormal); - - tri.materialIndex = primdata.materialIndex; - - return tri; -} - -void EvaluateObjectSurface( - in RayHit hit, - out ShaderMaterial material, - out Surface surface -) -{ - surface = (Surface)0; // otherwise it won't let "out" parameter - - TriangleData tri = TriangleData_Unpack(primitiveBuffer[hit.primitiveID], primitiveDataBuffer[hit.primitiveID]); - - float u = hit.bary.x; - float v = hit.bary.y; - float w = 1 - u - v; - - float4 uvsets = tri.u0 * w + tri.u1 * u + tri.u2 * v; - float4 color = tri.c0 * w + tri.c1 * u + tri.c2 * v; - uint materialIndex = tri.materialIndex; - - material = materialBuffer[materialIndex]; - - uvsets = frac(uvsets); // emulate wrap - - float4 baseColor = material.baseColor * color; - [branch] - if (material.uvset_baseColorMap >= 0 && (g_xFrame_Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) - { - const float2 UV_baseColorMap = material.uvset_baseColorMap == 0 ? uvsets.xy : uvsets.zw; - float4 baseColorMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, UV_baseColorMap * material.baseColorAtlasMulAdd.xy + material.baseColorAtlasMulAdd.zw, 0); - baseColorMap.rgb = DEGAMMA(baseColorMap.rgb); - baseColor *= baseColorMap; - } - - float4 surfaceMap = 1; - [branch] - if (material.uvset_surfaceMap >= 0) - { - const float2 UV_surfaceMap = material.uvset_surfaceMap == 0 ? uvsets.xy : uvsets.zw; - surfaceMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, UV_surfaceMap * material.surfaceMapAtlasMulAdd.xy + material.surfaceMapAtlasMulAdd.zw, 0); - } - - surface.create(material, baseColor, surfaceMap); - - surface.emissiveColor = material.emissiveColor; - [branch] - if (surface.emissiveColor.a > 0 && material.uvset_emissiveMap >= 0) - { - const float2 UV_emissiveMap = material.uvset_emissiveMap == 0 ? uvsets.xy : uvsets.zw; - float4 emissiveMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, UV_emissiveMap * material.emissiveMapAtlasMulAdd.xy + material.emissiveMapAtlasMulAdd.zw, 0); - emissiveMap.rgb = DEGAMMA(emissiveMap.rgb); - surface.emissiveColor *= emissiveMap; - } - - surface.transmission = material.transmission; - - surface.N = normalize(tri.n0 * w + tri.n1 * u + tri.n2 * v); - surface.facenormal = surface.N; - - [branch] - if (material.uvset_normalMap >= 0) - { - const float2 UV_normalMap = material.uvset_normalMap == 0 ? uvsets.xy : uvsets.zw; - float3 normalMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, UV_normalMap * material.normalMapAtlasMulAdd.xy + material.normalMapAtlasMulAdd.zw, 0).rgb; - normalMap.b = normalMap.b == 0 ? 1 : normalMap.b; // fix for missing blue channel - normalMap = normalMap.rgb * 2 - 1; - const float3x3 TBN = float3x3(tri.tangent, tri.binormal, surface.N); - surface.N = normalize(lerp(surface.N, mul(normalMap, TBN), material.normalMapStrength)); - } - -} inline void IntersectTriangle( in RayDesc ray, inout RayHit bestHit, - in BVHPrimitive prim, - uint primitiveID + in BVHPrimitive prim ) { float3 v0v1 = prim.v1() - prim.v0(); float3 v0v2 = prim.v2() - prim.v0(); float3 pvec = cross(ray.Direction, v0v2); float det = dot(v0v1, pvec); + #ifdef RAY_BACKFACE_CULLING - // if the determinant is negative the triangle is backfacing - // if the determinant is close to 0, the ray misses the triangle - if (det < 0.000001) + if (det > 0.000001 && (prim.flags & BVH_PRIMITIVE_FLAG_DOUBLE_SIDED) == 0) return; -#else +#endif // RAY_BACKFACE_CULLING + // ray and triangle are parallel if det is close to 0 if (abs(det) < 0.000001) return; -#endif - float invDet = 1 / det; + float invDet = rcp(det); float3 tvec = ray.Origin - prim.v0(); float u = dot(tvec, pvec) * invDet; @@ -358,25 +103,25 @@ inline void IntersectTriangle( if (t >= ray.TMin && t <= bestHit.distance) { bestHit.distance = t; - bestHit.primitiveID = primitiveID; + bestHit.primitiveID = prim.primitiveID(); bestHit.bary = float2(u, v); } } inline bool IntersectTriangleANY( in RayDesc ray, - in BVHPrimitive prim, - uint primitiveID + in BVHPrimitive prim ) { float3 v0v1 = prim.v1() - prim.v0(); float3 v0v2 = prim.v2() - prim.v0(); float3 pvec = cross(ray.Direction, v0v2); float det = dot(v0v1, pvec); + // ray and triangle are parallel if det is close to 0 if (abs(det) < 0.000001) return false; - float invDet = 1 / det; + float invDet = rcp(det); float3 tvec = ray.Origin - prim.v0(); float u = dot(tvec, pvec) * invDet; @@ -392,36 +137,20 @@ inline bool IntersectTriangleANY( if (t >= ray.TMin && t <= ray.TMax) { - RayHit hit; - hit.distance = t; - hit.primitiveID = primitiveID; - hit.bary = float2(u, v); - - TriangleData tri = TriangleData_Unpack(prim, primitiveDataBuffer[hit.primitiveID]); - - float u = hit.bary.x; - float v = hit.bary.y; - float w = 1 - u - v; - - float4 uvsets = tri.u0 * w + tri.u1 * u + tri.u2 * v; - float4 color = tri.c0 * w + tri.c1 * u + tri.c2 * v; - uint materialIndex = tri.materialIndex; - - ShaderMaterial material = materialBuffer[materialIndex]; - - uvsets = frac(uvsets); // emulate wrap - - float4 baseColor = material.baseColor * color; - [branch] - if (material.uvset_baseColorMap >= 0 && (g_xFrame_Options & OPTION_BIT_DISABLE_ALBEDO_MAPS) == 0) + if (prim.flags & BVH_PRIMITIVE_FLAG_TRANSPARENT) { - const float2 UV_baseColorMap = material.uvset_baseColorMap == 0 ? uvsets.xy : uvsets.zw; - float4 baseColorMap = materialTextureAtlas.SampleLevel(sampler_linear_clamp, UV_baseColorMap * material.baseColorAtlasMulAdd.xy + material.baseColorAtlasMulAdd.zw, 0); - baseColorMap.rgb = DEGAMMA(baseColorMap.rgb); - baseColor *= baseColorMap; - } + RayHit hit; + hit.distance = t; + hit.primitiveID = prim.primitiveID(); + hit.bary = float2(u, v); - return baseColor.a > material.alphaTest; + Surface surface; + if (surface.load(prim.primitiveID(), float2(u, v))) + { + return surface.opacity > surface.material.alphaTest; + } + } + return true; } return false; @@ -504,7 +233,7 @@ inline RayHit TraceRay_Closest(RayDesc ray, uint groupIndex = 0) // Leaf node const uint primitiveID = node.LeftChildIndex; const BVHPrimitive prim = primitiveBuffer[primitiveID]; - IntersectTriangle(ray, bestHit, prim, primitiveID); + IntersectTriangle(ray, bestHit, prim); } else { @@ -564,7 +293,7 @@ inline bool TraceRay_Any(RayDesc ray, uint groupIndex = 0) const uint primitiveID = node.LeftChildIndex; const BVHPrimitive prim = primitiveBuffer[primitiveID]; - if (IntersectTriangleANY(ray, prim, primitiveID)) + if (IntersectTriangleANY(ray, prim)) { shadow = true; break; diff --git a/WickedEngine/shaders/renderlightmapPS.hlsl b/WickedEngine/shaders/renderlightmapPS.hlsl index 7b944ec16..6644466c0 100644 --- a/WickedEngine/shaders/renderlightmapPS.hlsl +++ b/WickedEngine/shaders/renderlightmapPS.hlsl @@ -34,9 +34,9 @@ float4 main(Input input) : SV_TARGET surface.P = ray.Origin; [loop] - for (uint iterator = 0; iterator < g_xFrame_LightArrayCount; iterator++) + for (uint iterator = 0; iterator < g_xFrame.LightArrayCount; iterator++) { - ShaderEntity light = EntityArray[g_xFrame_LightArrayOffset + iterator]; + ShaderEntity light = EntityArray[g_xFrame.LightArrayOffset + iterator]; Lighting lighting; lighting.create(0, 0, 0, 0); @@ -63,9 +63,9 @@ float4 main(Input input) : SV_TARGET if (NdotL > 0) { float3 atmosphereTransmittance = 1.0; - if (g_xFrame_Options & OPTION_BIT_REALISTIC_SKY) + if (g_xFrame.Options & OPTION_BIT_REALISTIC_SKY) { - atmosphereTransmittance = GetAtmosphericLightTransmittance(g_xFrame_Atmosphere, surface.P, L, texture_transmittancelut); + atmosphereTransmittance = GetAtmosphericLightTransmittance(g_xFrame.Atmosphere, surface.P, L, texture_transmittancelut); } float3 lightColor = light.GetColor().rgb * light.GetEnergy() * atmosphereTransmittance; @@ -163,25 +163,13 @@ float4 main(Input input) : SV_TARGET ); while (q.Proceed()) { - ShaderMesh mesh = bindless_buffers[NonUniformResourceIndex(q.CandidateInstanceID())].Load(0); - ShaderMeshSubset subset = bindless_subsets[NonUniformResourceIndex(mesh.subsetbuffer)][q.CandidateGeometryIndex()]; - ShaderMaterial material = bindless_buffers[NonUniformResourceIndex(subset.material)].Load(0); - [branch] - if (!material.IsCastingShadow()) - { - continue; - } + PrimitiveID prim; + prim.primitiveIndex = q.CandidatePrimitiveIndex(); + prim.instanceIndex = q.CandidateInstanceID(); + prim.subsetIndex = q.CandidateGeometryIndex(); Surface surface; - EvaluateObjectSurface( - mesh, - subset, - material, - q.CandidatePrimitiveIndex(), - q.CandidateTriangleBarycentrics(), - q.CandidateObjectToWorld3x4(), - surface - ); + surface.load(prim, q.CandidateTriangleBarycentrics()); shadow *= lerp(1, surface.albedo * surface.transmission, surface.opacity); @@ -246,40 +234,29 @@ float4 main(Input input) : SV_TARGET break; } - ShaderMaterial material; - #ifdef RTAPI // ray origin updated for next bounce: ray.Origin = q.WorldRayOrigin() + q.WorldRayDirection() * q.CommittedRayT(); - ShaderMesh mesh = bindless_buffers[NonUniformResourceIndex(q.CommittedInstanceID())].Load(0); - ShaderMeshSubset subset = bindless_subsets[NonUniformResourceIndex(mesh.subsetbuffer)][q.CommittedGeometryIndex()]; - material = bindless_buffers[NonUniformResourceIndex(subset.material)].Load(0); + PrimitiveID prim; + prim.primitiveIndex = q.CommittedPrimitiveIndex(); + prim.instanceIndex = q.CommittedInstanceID(); + prim.subsetIndex = q.CommittedGeometryIndex(); - EvaluateObjectSurface( - mesh, - subset, - material, - q.CommittedPrimitiveIndex(), - q.CommittedTriangleBarycentrics(), - q.CommittedObjectToWorld3x4(), - surface - ); + surface.load(prim, q.CommittedTriangleBarycentrics()); #else // ray origin updated for next bounce: ray.Origin = ray.Origin + ray.Direction * hit.distance; - EvaluateObjectSurface( - hit, - material, - surface - ); + surface.load(hit.primitiveID, hit.bary); #endif // RTAPI surface.update(); + result += max(0, energy * surface.emissiveColor.rgb * surface.emissiveColor.a); + // Calculate chances of reflection types: const float refractChance = surface.transmission; @@ -288,7 +265,7 @@ float4 main(Input input) : SV_TARGET if (roulette < refractChance) { // Refraction - const float3 R = refract(ray.Direction, surface.N, 1 - material.refraction); + const float3 R = refract(ray.Direction, surface.N, 1 - surface.material.refraction); ray.Direction = lerp(R, SampleHemisphere_cos(R, seed, uv), surface.roughnessBRDF); energy *= surface.albedo; @@ -316,7 +293,6 @@ float4 main(Input input) : SV_TARGET } } - result += max(0, energy * surface.emissiveColor.rgb * surface.emissiveColor.a); } return float4(result, xTraceAccumulationFactor); diff --git a/WickedEngine/shaders/rtaoCS.hlsl b/WickedEngine/shaders/rtaoCS.hlsl index 9e3d3049c..1512157a9 100644 --- a/WickedEngine/shaders/rtaoCS.hlsl +++ b/WickedEngine/shaders/rtaoCS.hlsl @@ -15,16 +15,10 @@ groupshared float tile_Z[TILE_SIZE * TILE_SIZE]; [numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)] void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint groupIndex : SV_GroupIndex) { - // ray traced ao works better with GBUFFER normal: - // Reprojection issues are mostly solved by denoiser anyway const float2 uv = ((float2)DTid.xy + 0.5) * xPPResolution_rcp; - const float2 velocity = texture_gbuffer2.SampleLevel(sampler_point_clamp, uv, 0).xy; - const float2 prevUV = uv + velocity; - const float4 g1 = texture_gbuffer1.SampleLevel(sampler_linear_clamp, prevUV, 0); - const float3 N = normalize(g1.rgb * 2 - 1); - const float depth = texture_depth.SampleLevel(sampler_linear_clamp, uv, 0); - const float3 P = reconstructPosition(uv, depth); + if (depth == 0) + return; uint flatTileIdx = 0; if (GTid.y < 4) @@ -37,6 +31,18 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : } output_tiles[flatTileIdx] = 0; + const float3 P = reconstructPosition(uv, depth); + + PrimitiveID prim; + prim.unpack(texture_gbuffer0[DTid.xy * 2]); + + Surface surface; + if (!surface.load(prim, P)) + { + return; + } + float3 N = surface.facenormal; + RayDesc ray; ray.TMin = 0.01; ray.TMax = rtao_range; @@ -60,34 +66,16 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : ); while (q.Proceed()) { - ShaderMesh mesh = bindless_buffers[NonUniformResourceIndex(q.CandidateInstanceID())].Load(0); - ShaderMeshSubset subset = bindless_subsets[NonUniformResourceIndex(mesh.subsetbuffer)][q.CandidateGeometryIndex()]; - ShaderMaterial material = bindless_buffers[NonUniformResourceIndex(subset.material)].Load(0); - [branch] - if (!material.IsCastingShadow()) - { - continue; - } - [branch] - if (material.texture_basecolormap_index < 0) - { - q.CommitNonOpaqueTriangleHit(); - break; - } + PrimitiveID prim; + prim.primitiveIndex = q.CandidatePrimitiveIndex(); + prim.instanceIndex = q.CandidateInstanceID(); + prim.subsetIndex = q.CandidateGeometryIndex(); Surface surface; - EvaluateObjectSurface( - mesh, - subset, - material, - q.CandidatePrimitiveIndex(), - q.CandidateTriangleBarycentrics(), - q.CandidateObjectToWorld3x4(), - surface - ); + surface.load(prim, q.CandidateTriangleBarycentrics()); [branch] - if (surface.opacity >= material.alphaTest) + if (surface.opacity >= surface.material.alphaTest) { q.CommitNonOpaqueTriangleHit(); break; diff --git a/WickedEngine/shaders/rtao_denoise_filterCS.hlsl b/WickedEngine/shaders/rtao_denoise_filterCS.hlsl index 7786af640..c4d975fb7 100644 --- a/WickedEngine/shaders/rtao_denoise_filterCS.hlsl +++ b/WickedEngine/shaders/rtao_denoise_filterCS.hlsl @@ -22,7 +22,7 @@ float2 FFX_DNSR_Shadows_GetInvBufferDimensions() } float4x4 FFX_DNSR_Shadows_GetProjectionInverse() { - return g_xCamera_InvP; + return g_xCamera.InvP; } float FFX_DNSR_Shadows_GetDepthSimilaritySigma() diff --git a/WickedEngine/shaders/rtao_denoise_tileclassificationCS.hlsl b/WickedEngine/shaders/rtao_denoise_tileclassificationCS.hlsl index 87982a4b3..2a4a92b5f 100644 --- a/WickedEngine/shaders/rtao_denoise_tileclassificationCS.hlsl +++ b/WickedEngine/shaders/rtao_denoise_tileclassificationCS.hlsl @@ -25,19 +25,19 @@ float2 FFX_DNSR_Shadows_GetInvBufferDimensions() } float3 FFX_DNSR_Shadows_GetEye() { - return g_xCamera_CamPos; + return g_xCamera.CamPos; } float4x4 FFX_DNSR_Shadows_GetProjectionInverse() { - return g_xCamera_InvP; + return g_xCamera.InvP; } float4x4 FFX_DNSR_Shadows_GetViewProjectionInverse() { - return g_xCamera_InvVP; + return g_xCamera.InvVP; } float4x4 FFX_DNSR_Shadows_GetReprojectionMatrix() { - return g_xCamera_Reprojection; + return g_xCamera.Reprojection; } float FFX_DNSR_Shadows_ReadDepth(uint2 did) @@ -66,7 +66,7 @@ float FFX_DNSR_Shadows_ReadHistory(float2 history_uv) } float2 FFX_DNSR_Shadows_ReadVelocity(uint2 did) { - return -texture_gbuffer2[did * 2].xy; + return -texture_gbuffer1[did * 2].xy; } void FFX_DNSR_Shadows_WriteReprojectionResults(uint2 did, float2 value) diff --git a/WickedEngine/shaders/rtreflectionLIB.hlsl b/WickedEngine/shaders/rtreflectionLIB.hlsl index e83bc59e4..a044f2030 100644 --- a/WickedEngine/shaders/rtreflectionLIB.hlsl +++ b/WickedEngine/shaders/rtreflectionLIB.hlsl @@ -27,67 +27,24 @@ void RTReflection_Raygen() if (depth == 0) return; - bool disocclusion = false; - const float2 velocity = texture_gbuffer2.SampleLevel(sampler_point_clamp, uv, 0).xy; - const float2 prevUV = uv + velocity; - if (!is_saturated(prevUV)) - { - //output[DTid.xy] = float4(1, 0, 0, 1); - //return; - disocclusion = true; - } - - // Disocclusion fallback: - float depth_current = getLinearDepth(depth); - float depth_history = getLinearDepth(texture_depth_history.SampleLevel(sampler_point_clamp, prevUV, 1)); - if (abs(depth_current - depth_history) > 1) - { - //output[DTid.xy] = float4(1, 0, 0, 1); - //return; - disocclusion = true; - } - const float3 P = reconstructPosition(uv, depth); - const float3 V = normalize(g_xCamera_CamPos - P); + const float3 V = normalize(g_xCamera.CamPos - P); - float3 N; - float roughness; - if (disocclusion) + PrimitiveID prim; + prim.unpack(texture_gbuffer0[DTid.xy * 2]); + + Surface surface; + surface.load(prim, P); + if (surface.roughness > 0.6) { - // When reprojection is invalid, trace the surface parameters: - RayDesc ray; - ray.Origin = P - V * 0.005; - ray.Direction = V; - ray.TMin = 0; - ray.TMax = 0.01; - - RayPayload payload; - payload.data = -1; // indicate closesthit shader will just fill normal and roughness - - TraceRay( - scene_acceleration_structure, // AccelerationStructure - RAY_FLAG_FORCE_OPAQUE | - RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH | - 0, // RayFlags - ~0, // InstanceInclusionMask - 0, // RayContributionToHitGroupIndex - 0, // MultiplierForGeomtryContributionToShaderIndex - 0, // MissShaderIndex - ray, // Ray - payload // Payload - ); - - N = payload.data.xyz; - roughness = payload.data.w; - } - else - { - // When reprojection valid, just sample surface parameters from gbuffer: - const float4 g1 = texture_gbuffer1.SampleLevel(sampler_linear_clamp, prevUV, 0); - N = normalize(g1.rgb * 2 - 1); - roughness = g1.a; + output[DTid.xy] = float4(max(0, EnvironmentReflection_Global(surface)), 1); + output_rayLengths[DTid.xy] = FLT_MAX; + return; } + float3 N = surface.N; + float roughness = surface.roughness; + // The ray direction selection part is the same as in from ssr_raytraceCS.hlsl: float4 H; float3 L; @@ -119,7 +76,7 @@ void RTReflection_Raygen() const float3 R = L; - float seed = g_xFrame_Time; + float seed = g_xFrame.Time; RayDesc ray; ray.TMin = 0.01; @@ -149,21 +106,13 @@ void RTReflection_Raygen() [shader("closesthit")] void RTReflection_ClosestHit(inout RayPayload payload, in BuiltInTriangleIntersectionAttributes attr) { - ShaderMesh mesh = bindless_buffers[NonUniformResourceIndex(InstanceID())].Load(0); - ShaderMeshSubset subset = bindless_subsets[NonUniformResourceIndex(mesh.subsetbuffer)][GeometryIndex()]; - ShaderMaterial material = bindless_buffers[NonUniformResourceIndex(subset.material)].Load(0); + PrimitiveID prim; + prim.primitiveIndex = PrimitiveIndex(); + prim.instanceIndex = InstanceID(); + prim.subsetIndex = GeometryIndex(); Surface surface; - - EvaluateObjectSurface( - mesh, - subset, - material, - PrimitiveIndex(), - attr.barycentrics, - ObjectToWorld3x4(), - surface - ); + surface.load(prim, attr.barycentrics); [branch] if (payload.data.w < 0) @@ -185,10 +134,10 @@ void RTReflection_ClosestHit(inout RayPayload payload, in BuiltInTriangleInterse lighting.create(0, 0, GetAmbient(surface.N), 0); [loop] - for (uint iterator = 0; iterator < g_xFrame_LightArrayCount; iterator++) + for (uint iterator = 0; iterator < g_xFrame.LightArrayCount; iterator++) { - ShaderEntity light = EntityArray[g_xFrame_LightArrayOffset + iterator]; - if ((light.layerMask & material.layerMask) == 0) + ShaderEntity light = EntityArray[g_xFrame.LightArrayOffset + iterator]; + if ((light.layerMask & surface.material.layerMask) == 0) continue; if (light.GetFlags() & ENTITY_FLAG_LIGHT_STATIC) @@ -226,24 +175,16 @@ void RTReflection_ClosestHit(inout RayPayload payload, in BuiltInTriangleInterse [shader("anyhit")] void RTReflection_AnyHit(inout RayPayload payload, in BuiltInTriangleIntersectionAttributes attr) { - ShaderMesh mesh = bindless_buffers[NonUniformResourceIndex(InstanceID())].Load(0); - ShaderMeshSubset subset = bindless_subsets[NonUniformResourceIndex(mesh.subsetbuffer)][GeometryIndex()]; - ShaderMaterial material = bindless_buffers[NonUniformResourceIndex(subset.material)].Load(0); + PrimitiveID prim; + prim.primitiveIndex = PrimitiveIndex(); + prim.instanceIndex = InstanceID(); + prim.subsetIndex = GeometryIndex(); Surface surface; - - EvaluateObjectSurface( - mesh, - subset, - material, - PrimitiveIndex(), - attr.barycentrics, - ObjectToWorld3x4(), - surface - ); + surface.load(prim, attr.barycentrics); [branch] - if (surface.opacity < material.alphaTest) + if (surface.opacity < surface.material.alphaTest) { IgnoreHit(); } diff --git a/WickedEngine/shaders/rtshadow_denoise_filterCS.hlsl b/WickedEngine/shaders/rtshadow_denoise_filterCS.hlsl index a03c0d204..3916dbc0b 100644 --- a/WickedEngine/shaders/rtshadow_denoise_filterCS.hlsl +++ b/WickedEngine/shaders/rtshadow_denoise_filterCS.hlsl @@ -24,7 +24,7 @@ float2 FFX_DNSR_Shadows_GetInvBufferDimensions() } float4x4 FFX_DNSR_Shadows_GetProjectionInverse() { - return g_xCamera_InvP; + return g_xCamera.InvP; } float FFX_DNSR_Shadows_GetDepthSimilaritySigma() diff --git a/WickedEngine/shaders/rtshadow_denoise_temporalCS.hlsl b/WickedEngine/shaders/rtshadow_denoise_temporalCS.hlsl index 914b2390f..becbd4cdf 100644 --- a/WickedEngine/shaders/rtshadow_denoise_temporalCS.hlsl +++ b/WickedEngine/shaders/rtshadow_denoise_temporalCS.hlsl @@ -80,7 +80,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3 const float2 uv = (DTid.xy + 0.5f) * xPPResolution_rcp; - const float2 velocity = texture_gbuffer2.SampleLevel(sampler_point_clamp, uv, 0).xy; + const float2 velocity = texture_gbuffer1.SampleLevel(sampler_point_clamp, uv, 0).xy; const float2 prevUV = uv + velocity; if (!is_saturated(prevUV)) { diff --git a/WickedEngine/shaders/rtshadow_denoise_tileclassificationCS.hlsl b/WickedEngine/shaders/rtshadow_denoise_tileclassificationCS.hlsl index 3a5a21c1a..8474fffec 100644 --- a/WickedEngine/shaders/rtshadow_denoise_tileclassificationCS.hlsl +++ b/WickedEngine/shaders/rtshadow_denoise_tileclassificationCS.hlsl @@ -30,19 +30,19 @@ float2 FFX_DNSR_Shadows_GetInvBufferDimensions() } float3 FFX_DNSR_Shadows_GetEye() { - return g_xCamera_CamPos; + return g_xCamera.CamPos; } float4x4 FFX_DNSR_Shadows_GetProjectionInverse() { - return g_xCamera_InvP; + return g_xCamera.InvP; } float4x4 FFX_DNSR_Shadows_GetViewProjectionInverse() { - return g_xCamera_InvVP; + return g_xCamera.InvVP; } float4x4 FFX_DNSR_Shadows_GetReprojectionMatrix() { - return g_xCamera_Reprojection; + return g_xCamera.Reprojection; } float FFX_DNSR_Shadows_ReadDepth(uint2 did) @@ -71,7 +71,7 @@ float FFX_DNSR_Shadows_ReadHistory(float2 history_uv) } float2 FFX_DNSR_Shadows_ReadVelocity(uint2 did) { - return -texture_gbuffer2[did * 2].xy; + return -texture_gbuffer1[did * 2].xy; } void FFX_DNSR_Shadows_WriteReprojectionResults(uint2 did, float2 value) diff --git a/WickedEngine/shaders/screenPS.hlsl b/WickedEngine/shaders/screenPS.hlsl index 637979da4..51fdb968e 100644 --- a/WickedEngine/shaders/screenPS.hlsl +++ b/WickedEngine/shaders/screenPS.hlsl @@ -2,5 +2,12 @@ float4 main(float4 pos : SV_Position, float2 uv : TEXCOORD) : SV_TARGET { - return texture_base.SampleLevel(Sampler, uv, 0) * xColor; -} \ No newline at end of file + SamplerState sam = bindless_samplers[push.sampler_index]; + float4 color = unpack_half4(push.packed_color); + [branch] + if (push.texture_base_index >= 0) + { + color *= bindless_textures[push.texture_base_index].Sample(sam, uv); + } + return color; +} diff --git a/WickedEngine/shaders/screenspaceshadowCS.hlsl b/WickedEngine/shaders/screenspaceshadowCS.hlsl index bc4e5b3f6..6144f63fd 100644 --- a/WickedEngine/shaders/screenspaceshadowCS.hlsl +++ b/WickedEngine/shaders/screenspaceshadowCS.hlsl @@ -1,4 +1,4 @@ -#define BRDF_NDOTL_BIAS 0.1 +//#define BRDF_NDOTL_BIAS 0.1 #include "globals.hlsli" #include "ShaderInterop_Postprocess.h" #include "raytracingHF.hlsli" @@ -21,19 +21,12 @@ groupshared float tile_Z[TILE_SIZE * TILE_SIZE]; [numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)] void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint groupIndex : SV_GroupIndex) { -#ifdef RTSHADOW - - // ray traced shadow works better with GBUFFER normal: - // Reprojection issues are mostly solved by denoiser anyway const float2 uv = ((float2)DTid.xy + 0.5) * xPPResolution_rcp; - const float2 velocity = texture_gbuffer2.SampleLevel(sampler_point_clamp, uv, 0).xy; - const float2 prevUV = uv + velocity; - const float4 g1 = texture_gbuffer1.SampleLevel(sampler_linear_clamp, prevUV, 0); - const float3 N = normalize(g1.rgb * 2 - 1); - const float depth = texture_depth.SampleLevel(sampler_linear_clamp, uv, 0); - const float3 P = reconstructPosition(uv, depth); + if (depth == 0) + return; +#ifdef RTSHADOW uint flatTileIdx = 0; if (GTid.y < 4) { @@ -44,84 +37,24 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : flatTileIdx = flatten2D(Gid.xy * uint2(1, 2) + uint2(0, 1), (xPPResolution + uint2(7, 3)) / uint2(8, 4)); } output_tiles[flatTileIdx] = 0; +#endif // RTSHADOW + + float3 P = reconstructPosition(uv, depth); + + PrimitiveID prim; + prim.unpack(texture_gbuffer0[DTid.xy * 2]); + + Surface surface; + if (!surface.load(prim, P)) + { + return; + } + float3 N = surface.N; const float2 bluenoise = blue_noise(DTid.xy).xy; -#else - - // Screen space shadow will reconstruct normal from depth: - - const int2 tile_upperleft = Gid.xy * POSTPROCESS_BLOCKSIZE - TILE_BORDER; - for (uint t = groupIndex; t < TILE_SIZE * TILE_SIZE; t += POSTPROCESS_BLOCKSIZE * POSTPROCESS_BLOCKSIZE) - { - const uint2 pixel = tile_upperleft + unflatten2D(t, TILE_SIZE); - const float2 uv = (pixel + 0.5f) * xPPResolution_rcp; - const float depth = texture_depth.SampleLevel(sampler_linear_clamp, uv, 0); - const float3 position = reconstructPosition(uv, depth); - tile_XY[t] = position.xy; - tile_Z[t] = position.z; - } - GroupMemoryBarrierWithGroupSync(); - - // reconstruct flat normals from depth buffer: - // Explanation: There are two main ways to reconstruct flat normals from depth buffer: - // 1: use ddx() and ddy() on the reconstructed positions to compute triangle, this has artifacts on depth discontinuities and doesn't work in compute shader - // 2: Take 3 taps from the depth buffer, reconstruct positions and compute triangle. This can still produce artifacts - // on discontinuities, but a little less. To fix the remaining artifacts, we can take 4 taps around the center, and find the "best triangle" - // by only computing the positions from those depths that have the least amount of discontinuity - - const uint cross_idx[5] = { - flatten2D(TILE_BORDER + GTid.xy, TILE_SIZE), // 0: center - flatten2D(TILE_BORDER + GTid.xy + int2(1, 0), TILE_SIZE), // 1: right - flatten2D(TILE_BORDER + GTid.xy + int2(-1, 0), TILE_SIZE), // 2: left - flatten2D(TILE_BORDER + GTid.xy + int2(0, 1), TILE_SIZE), // 3: down - flatten2D(TILE_BORDER + GTid.xy + int2(0, -1), TILE_SIZE), // 4: up - }; - - const float center_Z = tile_Z[cross_idx[0]]; - - [branch] - if (center_Z >= g_xCamera_ZFarP) - return; - - const uint best_Z_horizontal = abs(tile_Z[cross_idx[1]] - center_Z) < abs(tile_Z[cross_idx[2]] - center_Z) ? 1 : 2; - const uint best_Z_vertical = abs(tile_Z[cross_idx[3]] - center_Z) < abs(tile_Z[cross_idx[4]] - center_Z) ? 3 : 4; - - float3 p1 = 0, p2 = 0; - if (best_Z_horizontal == 1 && best_Z_vertical == 4) - { - p1 = float3(tile_XY[cross_idx[1]], tile_Z[cross_idx[1]]); - p2 = float3(tile_XY[cross_idx[4]], tile_Z[cross_idx[4]]); - } - else if (best_Z_horizontal == 1 && best_Z_vertical == 3) - { - p1 = float3(tile_XY[cross_idx[3]], tile_Z[cross_idx[3]]); - p2 = float3(tile_XY[cross_idx[1]], tile_Z[cross_idx[1]]); - } - else if (best_Z_horizontal == 2 && best_Z_vertical == 4) - { - p1 = float3(tile_XY[cross_idx[4]], tile_Z[cross_idx[4]]); - p2 = float3(tile_XY[cross_idx[2]], tile_Z[cross_idx[2]]); - } - else if (best_Z_horizontal == 2 && best_Z_vertical == 3) - { - p1 = float3(tile_XY[cross_idx[2]], tile_Z[cross_idx[2]]); - p2 = float3(tile_XY[cross_idx[3]], tile_Z[cross_idx[3]]); - } - - const float3 P = float3(tile_XY[cross_idx[0]], tile_Z[cross_idx[0]]); - const float3 N = normalize(cross(p2 - P, p1 - P)); - -#endif // RTSHADOW - - Surface surface; - surface.init(); - surface.pixel = DTid.xy; - surface.P = P; - surface.N = N; - - const uint2 tileIndex = uint2(floor(surface.pixel * 2 / TILED_CULLING_BLOCKSIZE)); - const uint flatTileIndex = flatten2D(tileIndex, g_xFrame_EntityCullingTileCount.xy) * SHADER_ENTITY_TILE_BUCKET_COUNT; + const uint2 tileIndex = uint2(floor(DTid.xy * 2 / TILED_CULLING_BLOCKSIZE)); + const uint flatTileIndex = flatten2D(tileIndex, g_xFrame.EntityCullingTileCount.xy) * SHADER_ENTITY_TILE_BUCKET_COUNT; uint shadow_mask[4] = {0,0,0,0}; // FXC issue: can't dynamically index into uint4, unless unrolling all loops uint shadow_index = 0; @@ -131,7 +64,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : ray.Origin = P; #ifndef RTSHADOW - ray.Origin = mul(g_xCamera_View, float4(ray.Origin, 1)).xyz; + ray.Origin = mul(g_xCamera.View, float4(ray.Origin, 1)).xyz; const float range = xPPParams0.x; const uint samplecount = xPPParams0.y; @@ -141,11 +74,11 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : #endif // RTSHADOW [branch] - if (g_xFrame_LightArrayCount > 0) + if (g_xFrame.LightArrayCount > 0) { // Loop through light buckets in the tile: - const uint first_item = g_xFrame_LightArrayOffset; - const uint last_item = first_item + g_xFrame_LightArrayCount - 1; + const uint first_item = g_xFrame.LightArrayOffset; + const uint last_item = first_item + g_xFrame.LightArrayCount - 1; const uint first_bucket = first_item / 32; const uint last_bucket = min(last_item / 32, max(0, SHADER_ENTITY_TILE_BUCKET_COUNT - 1)); [loop] @@ -168,7 +101,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : [branch] if (entity_index >= first_item && entity_index <= last_item) { - shadow_index = entity_index - g_xFrame_LightArrayOffset; + shadow_index = entity_index - g_xFrame.LightArrayOffset; if (shadow_index >= MAX_RTSHADOWS) break; @@ -286,34 +219,16 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : ); while (q.Proceed()) { - ShaderMesh mesh = bindless_buffers[NonUniformResourceIndex(q.CandidateInstanceID())].Load(0); - ShaderMeshSubset subset = bindless_subsets[NonUniformResourceIndex(mesh.subsetbuffer)][q.CandidateGeometryIndex()]; - ShaderMaterial material = bindless_buffers[NonUniformResourceIndex(subset.material)].Load(0); - [branch] - if (!material.IsCastingShadow()) - { - continue; - } - [branch] - if (material.texture_basecolormap_index < 0) - { - q.CommitNonOpaqueTriangleHit(); - break; - } + PrimitiveID prim; + prim.primitiveIndex = q.CandidatePrimitiveIndex(); + prim.instanceIndex = q.CandidateInstanceID(); + prim.subsetIndex = q.CandidateGeometryIndex(); Surface surface; - EvaluateObjectSurface( - mesh, - subset, - material, - q.CandidatePrimitiveIndex(), - q.CandidateTriangleBarycentrics(), - q.CandidateObjectToWorld3x4(), - surface - ); + surface.load(prim, q.CandidateTriangleBarycentrics()); [branch] - if (surface.opacity >= material.alphaTest) + if (surface.opacity >= surface.material.alphaTest) { q.CommitNonOpaqueTriangleHit(); break; @@ -326,7 +241,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : #else // screen space raymarch shadow: - ray.Direction = normalize(mul((float3x3)g_xCamera_View, L)); + ray.Direction = normalize(mul((float3x3)g_xCamera.View, L)); float3 rayPos = ray.Origin + ray.Direction * stepsize * offset; float occlusion = 0; @@ -335,7 +250,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : { rayPos += ray.Direction * stepsize; - float4 proj = mul(g_xCamera_Proj, float4(rayPos, 1)); + float4 proj = mul(g_xCamera.Proj, float4(rayPos, 1)); proj.xyz /= proj.w; proj.xy = proj.xy * float2(0.5f, -0.5f) + float2(0.5f, 0.5f); @@ -343,7 +258,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : if (is_saturated(proj.xy)) { const float ray_depth_real = proj.w; - const float ray_depth_sample = texture_lineardepth.SampleLevel(sampler_point_clamp, proj.xy, 1) * g_xCamera_ZFarP; + const float ray_depth_sample = texture_lineardepth.SampleLevel(sampler_point_clamp, proj.xy, 1) * g_xCamera.ZFarP; const float ray_depth_delta = ray_depth_real - ray_depth_sample; if (ray_depth_delta > 0 && ray_depth_delta < thickness) { diff --git a/WickedEngine/shaders/shadingRateClassificationCS.hlsl b/WickedEngine/shaders/shadingRateClassificationCS.hlsl index eeb2f7b7e..f5304b661 100644 --- a/WickedEngine/shaders/shadingRateClassificationCS.hlsl +++ b/WickedEngine/shaders/shadingRateClassificationCS.hlsl @@ -21,7 +21,7 @@ void main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint groupInde GroupMemoryBarrierWithGroupSync(); uint2 dim; - texture_gbuffer2.GetDimensions(dim.x, dim.y); + texture_gbuffer1.GetDimensions(dim.x, dim.y); const uint2 tile = Gid.xy; @@ -33,7 +33,7 @@ void main( uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID, uint groupInde const uint2 tile_pixel = unflatten2D(i, xShadingRateTileSize); const uint2 pixel = min(tile * xShadingRateTileSize + tile_pixel, dim - 1); - const float2 velocity = abs(texture_gbuffer2[pixel].xy); + const float2 velocity = abs(texture_gbuffer1[pixel].xy); const float magnitude = max(velocity.x, velocity.y); uint rate = 0; diff --git a/WickedEngine/shaders/shadowPS_alphatest.hlsl b/WickedEngine/shaders/shadowPS_alphatest.hlsl index d8050861d..d4e81b2d4 100644 --- a/WickedEngine/shaders/shadowPS_alphatest.hlsl +++ b/WickedEngine/shaders/shadowPS_alphatest.hlsl @@ -1,4 +1,4 @@ -#define OBJECTSHADER_LAYOUT_POS_TEX +#define OBJECTSHADER_LAYOUT_SHADOW_TEX #include "objectHF.hlsli" void main(PixelInput input) diff --git a/WickedEngine/shaders/shadowPS_transparent.hlsl b/WickedEngine/shaders/shadowPS_transparent.hlsl index 3857ffee2..50c60665d 100644 --- a/WickedEngine/shaders/shadowPS_transparent.hlsl +++ b/WickedEngine/shaders/shadowPS_transparent.hlsl @@ -1,4 +1,4 @@ -#define OBJECTSHADER_LAYOUT_POS_TEX +#define OBJECTSHADER_LAYOUT_SHADOW_TEX #define OBJECTSHADER_USE_COLOR #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/shadowPS_water.hlsl b/WickedEngine/shaders/shadowPS_water.hlsl index 091c5e559..e50288bbd 100644 --- a/WickedEngine/shaders/shadowPS_water.hlsl +++ b/WickedEngine/shaders/shadowPS_water.hlsl @@ -1,4 +1,4 @@ -#define OBJECTSHADER_LAYOUT_POS_TEX +#define OBJECTSHADER_LAYOUT_SHADOW_TEX #define OBJECTSHADER_USE_COLOR #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/shadowVS.hlsl b/WickedEngine/shaders/shadowVS.hlsl index 8130d56b0..63adad972 100644 --- a/WickedEngine/shaders/shadowVS.hlsl +++ b/WickedEngine/shaders/shadowVS.hlsl @@ -1,3 +1,3 @@ #define OBJECTSHADER_COMPILE_VS -#define OBJECTSHADER_LAYOUT_POS +#define OBJECTSHADER_LAYOUT_SHADOW #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/shadowVS_alphatest.hlsl b/WickedEngine/shaders/shadowVS_alphatest.hlsl index 4013f127a..8d7a436b3 100644 --- a/WickedEngine/shaders/shadowVS_alphatest.hlsl +++ b/WickedEngine/shaders/shadowVS_alphatest.hlsl @@ -1,3 +1,3 @@ #define OBJECTSHADER_COMPILE_VS -#define OBJECTSHADER_LAYOUT_POS_TEX +#define OBJECTSHADER_LAYOUT_SHADOW_TEX #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/shadowVS_transparent.hlsl b/WickedEngine/shaders/shadowVS_transparent.hlsl index f6b448015..ba84a94e2 100644 --- a/WickedEngine/shaders/shadowVS_transparent.hlsl +++ b/WickedEngine/shaders/shadowVS_transparent.hlsl @@ -1,4 +1,4 @@ #define OBJECTSHADER_COMPILE_VS -#define OBJECTSHADER_LAYOUT_POS_TEX +#define OBJECTSHADER_LAYOUT_SHADOW_TEX #define OBJECTSHADER_USE_COLOR #include "objectHF.hlsli" diff --git a/WickedEngine/shaders/skinningCS.hlsl b/WickedEngine/shaders/skinningCS.hlsl index 52166072b..d89f45a14 100644 --- a/WickedEngine/shaders/skinningCS.hlsl +++ b/WickedEngine/shaders/skinningCS.hlsl @@ -1,20 +1,7 @@ #include "ResourceMapping.h" -#include "ShaderInterop_Skinning.h" +#include "ShaderInterop_Renderer.h" -// This will make use of LDS to preload bones into local memory: -// #define USE_LDS - -struct Bone -{ - float4 pose0; - float4 pose1; - float4 pose2; -}; -STRUCTUREDBUFFER(boneBuffer, Bone, SKINNINGSLOT_IN_BONEBUFFER); - -#ifdef USE_LDS -groupshared Bone LDS_BoneList[SKINNING_COMPUTE_THREADCOUNT]; -#endif // USE_LDS +STRUCTUREDBUFFER(boneBuffer, ShaderTransform, SKINNINGSLOT_IN_BONEBUFFER); RAWBUFFER(vertexBuffer_POS, SKINNINGSLOT_IN_VERTEX_POS); RAWBUFFER(vertexBuffer_TAN, SKINNINGSLOT_IN_VERTEX_TAN); @@ -38,18 +25,7 @@ inline void Skinning(inout float3 pos, inout float3 nor, inout float3 tan, in fl [loop] for (uint i = 0; ((i < 4) && (weisum < 1.0f)); ++i) { - float4x4 m = float4x4( -#ifdef USE_LDS - LDS_BoneList[(uint)inBon[i]].pose0, - LDS_BoneList[(uint)inBon[i]].pose1, - LDS_BoneList[(uint)inBon[i]].pose2, -#else - boneBuffer[(uint)inBon[i]].pose0, - boneBuffer[(uint)inBon[i]].pose1, - boneBuffer[(uint)inBon[i]].pose2, -#endif // USE_LDS - float4(0, 0, 0, 1) - ); + float4x4 m = boneBuffer[(uint)inBon[i]].GetMatrix(); p += mul(m, float4(pos.xyz, 1)) * inWei[i]; n += mul((float3x3)m, nor.xyz) * inWei[i]; @@ -65,21 +41,12 @@ inline void Skinning(inout float3 pos, inout float3 nor, inout float3 tan, in fl } -[numthreads(SKINNING_COMPUTE_THREADCOUNT, 1, 1)] +[numthreads(64, 1, 1)] void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID) { -#ifdef USE_LDS - LDS_BoneList[GTid.x] = boneBuffer[GTid.x]; -#endif // USE_LDS - - const uint stride_POS_NOR = 16; - const uint stride_TAN = 4; - const uint stride_BON_IND = 8; - const uint stride_BON_WEI = 8; - - const uint fetchAddress_POS_NOR = DTid.x * stride_POS_NOR; - const uint fetchAddress_TAN = DTid.x * stride_TAN; - const uint fetchAddress_BON = DTid.x * (stride_BON_IND + stride_BON_WEI); + const uint fetchAddress_POS_NOR = DTid.x * sizeof(float4); + const uint fetchAddress_TAN = DTid.x * sizeof(uint); + const uint fetchAddress_BON = DTid.x * sizeof(uint4); // Manual type-conversion for pos: uint4 pos_nor_u = vertexBuffer_POS.Load4(fetchAddress_POS_NOR); @@ -120,10 +87,6 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID) wei.w = (float)((ind_wei_u.w >> 16) & 0x0000FFFF) / 65535.0f; } -#ifdef USE_LDS - GroupMemoryBarrierWithGroupSync(); -#endif // USE_LDS - // Perform skinning: Skinning(pos, nor.xyz, tan.xyz, ind, wei); @@ -155,4 +118,4 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID) // Store data: streamoutBuffer_POS.Store4(fetchAddress_POS_NOR, pos_nor_u); streamoutBuffer_TAN.Store(fetchAddress_TAN, vtan); -} \ No newline at end of file +} diff --git a/WickedEngine/shaders/skinningCS_LDS.hlsl b/WickedEngine/shaders/skinningCS_LDS.hlsl deleted file mode 100644 index 8ed342714..000000000 --- a/WickedEngine/shaders/skinningCS_LDS.hlsl +++ /dev/null @@ -1,3 +0,0 @@ -#define USE_LDS - -#include "skinningCS.hlsl" diff --git a/WickedEngine/shaders/skyAtmosphere.hlsli b/WickedEngine/shaders/skyAtmosphere.hlsli index 4fa23a7aa..7634409f0 100644 --- a/WickedEngine/shaders/skyAtmosphere.hlsli +++ b/WickedEngine/shaders/skyAtmosphere.hlsli @@ -568,7 +568,7 @@ SingleScatteringResult IntegrateScatteredLuminance( //if (Sampling.PerPixelNoise) //{ - // t = t0 + (t1 - t0) * InterleavedGradientNoise(pixPos, g_xFrame_FrameCount % 16); + // t = t0 + (t1 - t0) * InterleavedGradientNoise(pixPos, g_xFrame.FrameCount % 16); //} //else //{ diff --git a/WickedEngine/shaders/skyAtmosphere_multiScatteredLuminanceLutCS.hlsl b/WickedEngine/shaders/skyAtmosphere_multiScatteredLuminanceLutCS.hlsl index 721664265..def02623f 100644 --- a/WickedEngine/shaders/skyAtmosphere_multiScatteredLuminanceLutCS.hlsl +++ b/WickedEngine/shaders/skyAtmosphere_multiScatteredLuminanceLutCS.hlsl @@ -19,7 +19,7 @@ void main(uint3 DTid : SV_DispatchThreadID) uv = float2(FromSubUvsToUnit(uv.x, multiScatteringLUTRes.x), FromSubUvsToUnit(uv.y, multiScatteringLUTRes.y)); - AtmosphereParameters atmosphere = g_xFrame_Atmosphere; + AtmosphereParameters atmosphere = g_xFrame.Atmosphere; float cosSunZenithAngle = uv.x * 2.0 - 1.0; float3 sunDirection = float3(0.0, sqrt(saturate(1.0 - cosSunZenithAngle * cosSunZenithAngle)), cosSunZenithAngle); diff --git a/WickedEngine/shaders/skyAtmosphere_skyLuminanceLutCS.hlsl b/WickedEngine/shaders/skyAtmosphere_skyLuminanceLutCS.hlsl index de1875c52..21eb360e8 100644 --- a/WickedEngine/shaders/skyAtmosphere_skyLuminanceLutCS.hlsl +++ b/WickedEngine/shaders/skyAtmosphere_skyLuminanceLutCS.hlsl @@ -16,7 +16,7 @@ void main(uint3 DTid : SV_DispatchThreadID) float2 uv = pixelPosition * rcp(multiScatteringLUTRes); - AtmosphereParameters atmosphere = g_xFrame_Atmosphere; + AtmosphereParameters atmosphere = g_xFrame.Atmosphere; float viewHeight = atmosphere.bottomRadius + skyLuminanceSampleHeight; diff --git a/WickedEngine/shaders/skyAtmosphere_skyViewLutCS.hlsl b/WickedEngine/shaders/skyAtmosphere_skyViewLutCS.hlsl index 959021ad4..2c0a16da1 100644 --- a/WickedEngine/shaders/skyAtmosphere_skyViewLutCS.hlsl +++ b/WickedEngine/shaders/skyAtmosphere_skyViewLutCS.hlsl @@ -8,12 +8,12 @@ RWTEXTURE2D(output, float4, 0); [numthreads(8, 8, 1)] void main(uint3 DTid : SV_DispatchThreadID) { - AtmosphereParameters atmosphere = g_xFrame_Atmosphere; + AtmosphereParameters atmosphere = g_xFrame.Atmosphere; float2 pixelPosition = float2(DTid.xy) + 0.5; float2 uv = pixelPosition * rcp(skyViewLUTRes); - float3 skyRelativePosition = g_xCamera_CamPos; + float3 skyRelativePosition = g_xCamera.CamPos; float3 worldPosition = GetCameraPlanetPos(atmosphere, skyRelativePosition); float viewHeight = length(worldPosition); diff --git a/WickedEngine/shaders/skyAtmosphere_transmittanceLutCS.hlsl b/WickedEngine/shaders/skyAtmosphere_transmittanceLutCS.hlsl index 67cb40196..faafb43d7 100644 --- a/WickedEngine/shaders/skyAtmosphere_transmittanceLutCS.hlsl +++ b/WickedEngine/shaders/skyAtmosphere_transmittanceLutCS.hlsl @@ -9,7 +9,7 @@ RWTEXTURE2D(output, float4, 0); void main(uint3 DTid : SV_DispatchThreadID) { float2 pixelPosition = float2(DTid.xy) + 0.5; - AtmosphereParameters atmosphere = g_xFrame_Atmosphere; + AtmosphereParameters atmosphere = g_xFrame.Atmosphere; // Compute camera position from LUT coords const float2 uv = pixelPosition * rcp(transmittanceLUTRes); diff --git a/WickedEngine/shaders/skyHF.hlsli b/WickedEngine/shaders/skyHF.hlsli index 73c93103c..e3e05d73c 100644 --- a/WickedEngine/shaders/skyHF.hlsli +++ b/WickedEngine/shaders/skyHF.hlsli @@ -8,7 +8,7 @@ float3 AccurateAtmosphericScattering(Texture2D skyViewLutTexture, Texture2D transmittanceLUT, Texture2D multiScatteringLUT, float3 rayOrigin, float3 rayDirection, float3 sunDirection, float sunEnergy, float3 sunColor, bool enableSun, bool darkMode, bool stationary) { - AtmosphereParameters atmosphere = g_xFrame_Atmosphere; + AtmosphereParameters atmosphere = g_xFrame.Atmosphere; float3 worldDirection = rayDirection; @@ -119,7 +119,7 @@ float3 CustomAtmosphericScattering(float3 V, float3 sunDirection, float3 sunColo const float zenith = V.y; // how much is above (0: horizon, 1: directly above) const float sunScatter = saturate(sunDirection.y + 0.1f); // how much the sun is directly above. Even if sunis at horizon, we add a constant scattering amount so that light still scatters at horizon - const float atmosphereDensity = 0.5 + g_xFrame_FogHeightSky; // constant of air density, or "fog height" as interpreted here (bigger is more obstruction of sun) + const float atmosphereDensity = 0.5 + g_xFrame.FogHeightSky; // constant of air density, or "fog height" as interpreted here (bigger is more obstruction of sun) const float zenithDensity = atmosphereDensity / pow(max(0.000001f, zenith), 0.75f); const float sunScatterDensity = atmosphereDensity / pow(max(0.000001f, sunScatter), 0.75f); @@ -153,13 +153,13 @@ float3 CustomAtmosphericScattering(float3 V, float3 sunDirection, float3 sunColo void CalculateClouds(inout float3 sky, float3 V, bool dark_enabled) { - if (g_xFrame_Cloudiness <= 0) + if (g_xFrame.Cloudiness <= 0) { return; } // Trace a cloud layer plane: - const float3 o = g_xCamera_CamPos; + const float3 o = g_xCamera.CamPos; const float3 d = V; const float3 planeOrigin = float3(0, 1000, 0); const float3 planeNormal = float3(0, -1, 0); @@ -171,8 +171,8 @@ void CalculateClouds(inout float3 sky, float3 V, bool dark_enabled) } const float3 cloudPos = o + d * t; - const float2 cloudUV = cloudPos.xz * g_xFrame_CloudScale; - const float cloudTime = g_xFrame_Time * g_xFrame_CloudSpeed; + const float2 cloudUV = cloudPos.xz * g_xFrame.CloudScale; + const float cloudTime = g_xFrame.Time * g_xFrame.CloudSpeed; const float2x2 m = float2x2(1.6, 1.2, -1.2, 1.6); const uint quality = 8; @@ -224,8 +224,8 @@ void CalculateClouds(inout float3 sky, float3 V, bool dark_enabled) // lerp between "choppy clouds" and "uniform clouds". Lower cloudiness will produce choppy clouds, but very high cloudiness will switch to overcast unfiform clouds: - clouds = lerp(clouds * 9.0f * g_xFrame_Cloudiness + 0.3f, clouds * 0.5f + 0.5f, pow(saturate(g_xFrame_Cloudiness), 8)); - clouds = saturate(clouds - (1 - g_xFrame_Cloudiness)); // modulate constant cloudiness + clouds = lerp(clouds * 9.0f * g_xFrame.Cloudiness + 0.3f, clouds * 0.5f + 0.5f, pow(saturate(g_xFrame.Cloudiness), 8)); + clouds = saturate(clouds - (1 - g_xFrame.Cloudiness)); // modulate constant cloudiness clouds *= pow(1 - saturate(length(abs(cloudPos.xz * 0.00001f))), 16); //fade close to horizon if (dark_enabled) @@ -242,9 +242,9 @@ void CalculateClouds(inout float3 sky, float3 V, bool dark_enabled) // V : view direction float3 GetDynamicSkyColor(in float3 V, bool sun_enabled = true, bool clouds_enabled = true, bool dark_enabled = false, bool realistic_sky_stationary = false) { - if (g_xFrame_Options & OPTION_BIT_SIMPLE_SKY) + if (g_xFrame.Options & OPTION_BIT_SIMPLE_SKY) { - return lerp(GetHorizonColor(), GetZenithColor(), saturate(V.y * 0.5f + 0.5f)) * g_xFrame_SkyExposure; + return lerp(GetHorizonColor(), GetZenithColor(), saturate(V.y * 0.5f + 0.5f)) * g_xFrame.SkyExposure; } const float3 sunDirection = GetSunDirection(); @@ -253,14 +253,14 @@ float3 GetDynamicSkyColor(in float3 V, bool sun_enabled = true, bool clouds_enab float3 sky = float3(0, 0, 0); - if (g_xFrame_Options & OPTION_BIT_REALISTIC_SKY) + if (g_xFrame.Options & OPTION_BIT_REALISTIC_SKY) { sky = AccurateAtmosphericScattering ( texture_skyviewlut, // Sky View Lut (combination of precomputed atmospheric LUTs) texture_transmittancelut, texture_multiscatteringlut, - g_xCamera_CamPos, // Ray origin + g_xCamera.CamPos, // Ray origin V, // Ray direction sunDirection, // Position of the sun sunEnergy, // Sun energy @@ -282,7 +282,7 @@ float3 GetDynamicSkyColor(in float3 V, bool sun_enabled = true, bool clouds_enab ); } - sky *= g_xFrame_SkyExposure; + sky *= g_xFrame.SkyExposure; if (clouds_enabled) { diff --git a/WickedEngine/shaders/skyPS_dynamic.hlsl b/WickedEngine/shaders/skyPS_dynamic.hlsl index 33e86ac96..dfef0bf93 100644 --- a/WickedEngine/shaders/skyPS_dynamic.hlsl +++ b/WickedEngine/shaders/skyPS_dynamic.hlsl @@ -3,10 +3,10 @@ float4 main(float4 pos : SV_POSITION, float2 clipspace : TEXCOORD) : SV_TARGET { - float4 unprojected = mul(g_xCamera_InvVP, float4(clipspace, 0.0f, 1.0f)); + float4 unprojected = mul(g_xCamera.InvVP, float4(clipspace, 0.0f, 1.0f)); unprojected.xyz /= unprojected.w; - const float3 V = normalize(unprojected.xyz - g_xCamera_CamPos); + const float3 V = normalize(unprojected.xyz - g_xCamera.CamPos); float4 color = float4(GetDynamicSkyColor(V), 1); diff --git a/WickedEngine/shaders/skyPS_static.hlsl b/WickedEngine/shaders/skyPS_static.hlsl index 65b858136..4b9c72d3e 100644 --- a/WickedEngine/shaders/skyPS_static.hlsl +++ b/WickedEngine/shaders/skyPS_static.hlsl @@ -3,16 +3,16 @@ float4 main(float4 pos : SV_POSITION, float2 clipspace : TEXCOORD) : SV_TARGET { - float4 unprojected = mul(g_xCamera_InvVP, float4(clipspace, 0.0f, 1.0f)); + float4 unprojected = mul(g_xCamera.InvVP, float4(clipspace, 0.0f, 1.0f)); unprojected.xyz /= unprojected.w; - const float3 V = normalize(unprojected.xyz - g_xCamera_CamPos); + const float3 V = normalize(unprojected.xyz - g_xCamera.CamPos); float4 color = float4(DEGAMMA_SKY(texture_globalenvmap.SampleLevel(sampler_linear_clamp, V, 0).rgb), 1); CalculateClouds(color.rgb, V, false); - float4 pos2DPrev = mul(g_xCamera_PrevVP, float4(unprojected.xyz, 1)); - float2 velocity = ((pos2DPrev.xy / pos2DPrev.w - g_xFrame_TemporalAAJitterPrev) - (clipspace - g_xFrame_TemporalAAJitter)) * float2(0.5f, -0.5f); + float4 pos2DPrev = mul(g_xCamera.PrevVP, float4(unprojected.xyz, 1)); + float2 velocity = ((pos2DPrev.xy / pos2DPrev.w - g_xCamera.TemporalAAJitterPrev) - (clipspace - g_xCamera.TemporalAAJitter)) * float2(0.5f, -0.5f); return color; } diff --git a/WickedEngine/shaders/skyPS_velocity.hlsl b/WickedEngine/shaders/skyPS_velocity.hlsl deleted file mode 100644 index c104cb5fb..000000000 --- a/WickedEngine/shaders/skyPS_velocity.hlsl +++ /dev/null @@ -1,13 +0,0 @@ -#include "objectHF.hlsli" -#include "skyHF.hlsli" - -float4 main(float4 pos : SV_POSITION, float2 clipspace : TEXCOORD) : SV_TARGET -{ - float4 unprojected = mul(g_xCamera_InvVP, float4(clipspace, 0.0f, 1.0f)); - unprojected.xyz /= unprojected.w; - - float4 pos2DPrev = mul(g_xCamera_PrevVP, float4(unprojected.xyz, 1)); - float2 velocity = ((pos2DPrev.xy / pos2DPrev.w - g_xFrame_TemporalAAJitterPrev) - (clipspace - g_xFrame_TemporalAAJitter)) * float2(0.5f, -0.5f); - - return float4(velocity, 0, 0); -} diff --git a/WickedEngine/shaders/sphereVS.hlsl b/WickedEngine/shaders/sphereVS.hlsl index 8cbfdc9b0..f17d6bb22 100644 --- a/WickedEngine/shaders/sphereVS.hlsl +++ b/WickedEngine/shaders/sphereVS.hlsl @@ -15,6 +15,6 @@ VSOut_Sphere main( uint vID : SV_VERTEXID ) o.nor = o.pos.xyz; o.pos = mul(g_xTransform, o.pos); o.pos3D = o.pos.xyz; - o.pos = mul(g_xCamera_VP, o.pos); + o.pos = mul(g_xCamera.VP, o.pos); return o; } \ No newline at end of file diff --git a/WickedEngine/shaders/ssaoCS.hlsl b/WickedEngine/shaders/ssaoCS.hlsl index 118145b6e..4e028203f 100644 --- a/WickedEngine/shaders/ssaoCS.hlsl +++ b/WickedEngine/shaders/ssaoCS.hlsl @@ -20,7 +20,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : const uint2 pixel = tile_upperleft + unflatten2D(t, TILE_SIZE); const float2 uv = (pixel + 0.5f) * xPPResolution_rcp; const float depth = texture_depth.SampleLevel(sampler_linear_clamp, uv, 1); - const float3 position = reconstructPosition(uv, depth, g_xCamera_InvP); // specify matrix to get view-space position! + const float3 position = reconstructPosition(uv, depth, g_xCamera.InvP); // specify matrix to get view-space position! tile_XY[t] = position.xy; tile_Z[t] = position.z; } @@ -44,7 +44,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : const float center_Z = tile_Z[cross_idx[0]]; [branch] - if (center_Z >= g_xCamera_ZFarP) + if (center_Z >= g_xCamera.ZFarP) return; const uint best_Z_horizontal = abs(tile_Z[cross_idx[1]] - center_Z) < abs(tile_Z[cross_idx[2]] - center_Z) ? 1 : 2; @@ -93,7 +93,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : const float ray_range = ssao_range * lerp(0.2f, 1.0f, rand(seed, uv)); // modulate ray-length a bit to avoid uniform look const float3 sam = P + cone * ray_range; - float4 vProjectedCoord = mul(g_xCamera_Proj, float4(sam, 1.0f)); + float4 vProjectedCoord = mul(g_xCamera.Proj, float4(sam, 1.0f)); vProjectedCoord.xyz /= vProjectedCoord.w; vProjectedCoord.xy = vProjectedCoord.xy * float2(0.5f, -0.5f) + float2(0.5f, 0.5f); @@ -102,7 +102,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 Gid : SV_GroupID, uint3 GTid : { #ifdef USE_LINEARDEPTH const float ray_depth_real = vProjectedCoord.w; // .w is also linear depth, could be also written as getLinearDepth(vProjectedCoord.z) - const float ray_depth_sample = texture_lineardepth.SampleLevel(sampler_point_clamp, vProjectedCoord.xy, 0) * g_xCamera_ZFarP; + const float ray_depth_sample = texture_lineardepth.SampleLevel(sampler_point_clamp, vProjectedCoord.xy, 0) * g_xCamera.ZFarP; const float depth_fix = 1 - saturate(abs(ray_depth_real - ray_depth_sample) * 0.2f); // too much depth difference cancels the effect ao += (ray_depth_sample < ray_depth_real) * depth_fix; #else diff --git a/WickedEngine/shaders/ssr_raytraceCS.hlsl b/WickedEngine/shaders/ssr_raytraceCS.hlsl index d54b86c27..eb5b14bc4 100644 --- a/WickedEngine/shaders/ssr_raytraceCS.hlsl +++ b/WickedEngine/shaders/ssr_raytraceCS.hlsl @@ -7,9 +7,6 @@ TEXTURE2D(input, float4, TEXSLOT_ONDEMAND0); RWTEXTURE2D(texture_raytrace, float4, 0); RWTEXTURE2D(texture_rayLengths, float, 1); -// Use this to use reduced precision, but higher framerate: -#define USE_LINEARDEPTH - static const float rayTraceStrideMin = 1.0f; // Step in horizontal or vertical pixels between samples. static const float rayTraceStrideMax = 10.0f; // Define max stride between samples. Roughness will interpolate between it's min and max counterparts. static const float rayTraceMaxStep = 512.0f; // Maximum number of iterations. Higher gives better images but may be slow. @@ -20,7 +17,7 @@ static const float rayTraceMaxDistance = 1000.0f; // Maximum camera-space distan static const float rayTraceStrideCutoff = 100.0f; // More distant pixels are smaller in screen space. This value tells at what point to // start relaxing the stride to give higher quality reflections for objects far from the camera. static const float raytraceHZBBias = 0.05f; // This value tells how fast the roughness increases the level. -static const float raytraceHZBStartLevel = 0.0f; +static const float raytraceHZBStartLevel = 1.0f; static const float raytraceHZBMinStep = 0.005f; // Minimum level increasement per iteration. @@ -34,10 +31,12 @@ bool IntersectsDepthBuffer(float sceneZMax, float rayZMin, float rayZMax) { // Increase thickness along distance. float thickness = max(sceneZMax * rayTraceThicknessBias + rayTraceThicknessOffset, 1.0); - + +#if 0 // precision issues in DX12 // Effectively remove line/tiny artifacts, mostly caused by Zbuffers precision. float depthScale = min(1.0f, sceneZMax / rayTraceStrideCutoff); sceneZMax += lerp(0.05f, 0.0f, depthScale); +#endif if (raytraceThicknessInfinite) return (rayZMin >= sceneZMax); @@ -49,21 +48,22 @@ bool IntersectsDepthBuffer(float sceneZMax, float rayZMin, float rayZMax) // http://casual-effects.blogspot.com/2014/08/screen-space-ray-tracing.html bool ScreenSpaceRayTrace(float3 csOrig, float3 csDir, float jitter, float roughness, out float2 hitPixel, out float3 hitPoint, out float iterations) { - float rayLength = ((csOrig.z + csDir.z * rayTraceMaxDistance) < g_xCamera_ZNearP) ? - (g_xCamera_ZNearP - csOrig.z) / csDir.z : rayTraceMaxDistance; + csOrig += csDir * 0.001; // precision issues in DX12 + float rayLength = ((csOrig.z + csDir.z * rayTraceMaxDistance) < g_xCamera.ZNearP) ? + (g_xCamera.ZNearP - csOrig.z) / csDir.z : rayTraceMaxDistance; float3 csRayEnd = csOrig + csDir * rayLength; // Project into homogeneous clip space - float4 clipRayOrigin = mul(g_xCamera_Proj, float4(csOrig, 1.0f)); - float4 clipRayEnd = mul(g_xCamera_Proj, float4(csRayEnd, 1.0f)); + float4 clipRayOrigin = mul(g_xCamera.Proj, float4(csOrig, 1.0f)); + float4 clipRayEnd = mul(g_xCamera.Proj, float4(csRayEnd, 1.0f)); float k0 = 1.0f / clipRayOrigin.w; float k1 = 1.0f / clipRayEnd.w; float3 Q0 = csOrig * k0; float3 Q1 = csRayEnd * k1; - + // Screen-space endpoints float2 P0 = clipRayOrigin.xy * k0; float2 P1 = clipRayEnd.xy * k1; @@ -201,11 +201,7 @@ bool ScreenSpaceRayTrace(float3 csOrig, float3 csDir, float jitter, float roughn hitPixel = permute ? PQk.yx : PQk.xy; hitPixel *= xPPResolution_rcp; -#ifdef USE_LINEARDEPTH - sceneZMax = texture_lineardepth.SampleLevel(sampler_point_clamp, hitPixel, level) * g_xCamera_ZFarP; -#else - sceneZMax = getLinearDepth(texture_depth.SampleLevel(sampler_point_clamp, hitPixel, 0).r); -#endif + sceneZMax = texture_lineardepth.SampleLevel(sampler_linear_clamp, hitPixel, level) * g_xCamera.ZFarP; } // Undo the last increment, which ran after the test variables were set up @@ -226,20 +222,27 @@ bool ScreenSpaceRayTrace(float3 csOrig, float3 csDir, float jitter, float roughn void main(uint3 DTid : SV_DispatchThreadID) { const float2 uv = (DTid.xy + 0.5f) * xPPResolution_rcp; - const float depth = texture_depth.SampleLevel(sampler_point_clamp, uv, 1); + const float depth = texture_depth.SampleLevel(sampler_linear_clamp, uv, 1); if (depth == 0) return; - const float2 velocity = texture_gbuffer2.SampleLevel(sampler_point_clamp, uv, 0).xy; - const float2 prevUV = uv + velocity; + PrimitiveID prim; + prim.unpack(texture_gbuffer0[DTid.xy * 2]); - // Everything in view space: - const float4 g1 = texture_gbuffer1.SampleLevel(sampler_linear_clamp, prevUV, 0); - const float3 P = reconstructPosition(uv, depth, g_xCamera_InvP); - const float3 N = normalize(mul((float3x3)g_xCamera_View, g1.rgb * 2 - 1).xyz); - const float3 V = normalize(-P); + Surface surface; + surface.load(prim, reconstructPosition(uv, depth)); + if (surface.roughness > 0.6) + { + texture_raytrace[DTid.xy] = 0; + texture_rayLengths[DTid.xy] = 0; + return; + } - const float roughness = GetRoughness(g1.a); + // Everything in view space: + float3 N = normalize(mul((float3x3)g_xCamera.View, surface.N)); + float3 P = reconstructPosition(uv, depth, g_xCamera.InvP); + float3 V = normalize(-P); + const float roughness = GetRoughness(surface.roughness); const float roughnessFade = GetRoughnessFade(roughness, SSRMaxRoughness); if (roughnessFade <= 0) @@ -270,7 +273,7 @@ void main(uint3 DTid : SV_DispatchThreadID) #else // Old // Low-discrepancy sequence - uint2 Random = Rand_PCG16(int3((DTid.xy + 0.5f), g_xFrame_FrameCount)).xy; + uint2 Random = Rand_PCG16(int3((DTid.xy + 0.5f), g_xFrame.FrameCount)).xy; float2 Xi = HammersleyRandom16(1, Random); // SingleSPP @@ -288,7 +291,7 @@ void main(uint3 DTid : SV_DispatchThreadID) const float surfaceMargin = 0.0f; const float maxRegenCount = 15.0f; - uint2 Random = Rand_PCG16(int3((DTid.xy + 0.5f), g_xFrame_FrameCount)).xy; + uint2 Random = Rand_PCG16(int3((DTid.xy + 0.5f), g_xFrame.FrameCount)).xy; // By using an uniform importance sampling method, some rays go below the surface. // We simply re-generate them at a negligible cost, to get some nice ones. @@ -315,7 +318,7 @@ void main(uint3 DTid : SV_DispatchThreadID) #endif L = reflect(-V, H.xyz); - jitter = InterleavedGradientNoise(DTid.xy, g_xFrame_FrameCount); + jitter = InterleavedGradientNoise(DTid.xy, g_xFrame.FrameCount); } else { @@ -331,7 +334,7 @@ void main(uint3 DTid : SV_DispatchThreadID) bool hit = ScreenSpaceRayTrace(P, L, jitter, roughness, hitPixel, hitPoint, iterations); - float hitDepth = texture_depth.SampleLevel(sampler_point_clamp, hitPixel, 0); + float hitDepth = texture_depth.SampleLevel(sampler_linear_clamp, hitPixel, 1); // Output: // xy: hit pixel @@ -342,7 +345,7 @@ void main(uint3 DTid : SV_DispatchThreadID) if (hit) { - const float3 Phit = reconstructPosition(uv, hitDepth, g_xCamera_InvP); + const float3 Phit = reconstructPosition(uv, hitDepth, g_xCamera.InvP); texture_rayLengths[DTid.xy] = distance(P, Phit); } else diff --git a/WickedEngine/shaders/ssr_resolveCS.hlsl b/WickedEngine/shaders/ssr_resolveCS.hlsl index 9c2d8368e..f2c427e3a 100644 --- a/WickedEngine/shaders/ssr_resolveCS.hlsl +++ b/WickedEngine/shaders/ssr_resolveCS.hlsl @@ -63,7 +63,7 @@ void GetSampleInfo(float2 velocity, float2 neighborUV, float2 uv, float3 P, floa // BRDF Weight - float3 hitViewPosition = reconstructPosition(hitPixel, hitDepth, g_xCamera_InvP); + float3 hitViewPosition = reconstructPosition(hitPixel, hitDepth, g_xCamera.InvP); float3 L = normalize(hitViewPosition - P); float3 H = normalize(L + V); @@ -91,21 +91,27 @@ void GetSampleInfo(float2 velocity, float2 neighborUV, float2 uv, float3 P, floa void main(uint3 DTid : SV_DispatchThreadID) { const float2 uv = (DTid.xy + 0.5f) * xPPResolution_rcp; - const float depth = texture_depth.SampleLevel(sampler_point_clamp, uv, 1); + const float depth = texture_depth.SampleLevel(sampler_linear_clamp, uv, 0); if (depth == 0.0f) return; - const float2 velocity = texture_gbuffer2.SampleLevel(sampler_point_clamp, uv, 0).xy; - const float2 prevUV = uv + velocity; - // Everthing in view space: - const float4 g1 = texture_gbuffer1.SampleLevel(sampler_linear_clamp, prevUV, 0); - const float3 P = reconstructPosition(uv, depth, g_xCamera_InvP); - const float3 N = normalize(mul((float3x3)g_xCamera_View, g1.rgb * 2 - 1).xyz); + const float3 P = reconstructPosition(uv, depth, g_xCamera.InvP); const float3 V = normalize(-P); + + PrimitiveID prim; + prim.unpack(texture_gbuffer0[DTid.xy * 2]); + + Surface surface; + surface.load(prim, P); + + const float3 N = normalize(mul((float3x3)g_xCamera.View, surface.N)); + const float roughness = GetRoughness(surface.roughness); + const float NdotV = saturate(dot(N, V)); - - const float roughness = GetRoughness(g1.a); + + const float2 velocity = texture_gbuffer1.SampleLevel(sampler_point_clamp, uv, 0).xy; + const float2 prevUV = uv + velocity; // Early out, useless if the roughness is out of range float roughnessFade = GetRoughnessFade(roughness, SSRMaxRoughness); diff --git a/WickedEngine/shaders/ssr_temporalCS.hlsl b/WickedEngine/shaders/ssr_temporalCS.hlsl index 2a1f2095e..c3cba0919 100644 --- a/WickedEngine/shaders/ssr_temporalCS.hlsl +++ b/WickedEngine/shaders/ssr_temporalCS.hlsl @@ -95,12 +95,12 @@ inline void ResolverAABB(Texture2D currentColor, SamplerState currentSam [numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)] void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3 Gid : SV_GroupID, uint groupIndex : SV_GroupIndex) { - if (texture_depth.Load(uint3(DTid.xy, 1)) == 0) + const float2 uv = (DTid.xy + 0.5f) * xPPResolution_rcp; + const float depth = texture_depth.SampleLevel(sampler_linear_clamp, uv, 0); + if (depth == 0) return; - const float2 uv = (DTid.xy + 0.5f) * xPPResolution_rcp; - - const float2 velocity = texture_gbuffer2.SampleLevel(sampler_point_clamp, uv, 0).xy; + const float2 velocity = texture_gbuffer1.SampleLevel(sampler_point_clamp, uv, 0).xy; float2 prevUV = uv + velocity; if (!is_saturated(prevUV)) { @@ -108,15 +108,22 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3 return; } - const float roughness = texture_gbuffer1.SampleLevel(sampler_point_clamp, prevUV, 0).a; + const float3 P = reconstructPosition(uv, depth, g_xCamera.InvP); + + PrimitiveID prim; + prim.unpack(texture_gbuffer0[DTid.xy * 2]); + + Surface surface; + surface.load(prim, P); + + const float roughness = surface.roughness; + if (roughness < 0.01) { output[DTid.xy] = resolve_current[DTid.xy]; //return; } - const float depth = texture_depth.SampleLevel(sampler_point_clamp, uv, 0); - // Secondary reprojection based on ray lengths: // https://www.ea.com/seed/news/seed-dd18-presentation-slides-raytracing (Slide 45) if (roughness < 0.5) @@ -125,9 +132,9 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3 if (rayLength > 0) { const float3 P = reconstructPosition(uv, depth); - const float3 V = normalize(g_xCamera_CamPos - P); + const float3 V = normalize(g_xCamera.CamPos - P); const float3 rayEnd = P - V * rayLength; - float4 rayEndPrev = mul(g_xCamera_PrevVP, float4(rayEnd, 1)); + float4 rayEndPrev = mul(g_xCamera.PrevVP, float4(rayEnd, 1)); rayEndPrev.xy /= rayEndPrev.w; prevUV = rayEndPrev.xy * float2(0.5, -0.5) + 0.5; } diff --git a/WickedEngine/shaders/stochasticSSRHF.hlsli b/WickedEngine/shaders/stochasticSSRHF.hlsli index 05ffaf5cb..0655d9072 100644 --- a/WickedEngine/shaders/stochasticSSRHF.hlsli +++ b/WickedEngine/shaders/stochasticSSRHF.hlsli @@ -1,5 +1,6 @@ #ifndef WI_STOCHASTICSSR_HF #define WI_STOCHASTICSSR_HF +#include "brdf.hlsli" // Stochastic Screen Space Reflections reference: // https://www.ea.com/frostbite/news/stochastic-screen-space-reflections diff --git a/WickedEngine/shaders/sunPS.hlsl b/WickedEngine/shaders/sunPS.hlsl index c1ff19a9b..0fb309436 100644 --- a/WickedEngine/shaders/sunPS.hlsl +++ b/WickedEngine/shaders/sunPS.hlsl @@ -4,10 +4,10 @@ float4 main(float4 pos : SV_POSITION, float2 clipspace : TEXCOORD) : SV_TARGET { - float4 unprojected = mul(g_xCamera_InvVP, float4(clipspace, 0.0f, 1.0f)); + float4 unprojected = mul(g_xCamera.InvVP, float4(clipspace, 0.0f, 1.0f)); unprojected.xyz /= unprojected.w; - const float3 origin = g_xCamera_CamPos; + const float3 origin = g_xCamera.CamPos; const float3 direction = normalize(unprojected.xyz - origin); return float4(GetDynamicSkyColor(direction, true, true, true), 1); diff --git a/WickedEngine/shaders/surfel_binningCS.hlsl b/WickedEngine/shaders/surfel_binningCS.hlsl new file mode 100644 index 000000000..065b5c1f4 --- /dev/null +++ b/WickedEngine/shaders/surfel_binningCS.hlsl @@ -0,0 +1,36 @@ +#include "globals.hlsli" +#include "ShaderInterop_SurfelGI.h" + +STRUCTUREDBUFFER(surfelBuffer, Surfel, TEXSLOT_ONDEMAND0); +RAWBUFFER(surfelStatsBuffer, TEXSLOT_ONDEMAND1); + +RWSTRUCTUREDBUFFER(surfelGridBuffer, SurfelGridCell, 0); +RWSTRUCTUREDBUFFER(surfelCellBuffer, uint, 1); + +[numthreads(64, 1, 1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + uint surfel_count = surfelStatsBuffer.Load(SURFEL_STATS_OFFSET_COUNT); + if (DTid.x >= surfel_count) + return; + + uint surfel_index = DTid.x; + Surfel surfel = surfelBuffer[surfel_index]; + if (surfel.radius > 0) + { + int3 center_cell = surfel_cell(surfel.position); + for (uint i = 0; i < 27; ++i) + { + int3 gridpos = center_cell + surfel_neighbor_offsets[i]; + + if (surfel_cellintersects(surfel, gridpos)) + { + uint cellindex = surfel_cellindex(gridpos); + uint prevCount; + InterlockedAdd(surfelGridBuffer[cellindex].count, 1, prevCount); + surfelCellBuffer[surfelGridBuffer[cellindex].offset + prevCount] = surfel_index; + } + } + + } +} diff --git a/WickedEngine/shaders/surfel_coverageCS.hlsl b/WickedEngine/shaders/surfel_coverageCS.hlsl new file mode 100644 index 000000000..f5f463184 --- /dev/null +++ b/WickedEngine/shaders/surfel_coverageCS.hlsl @@ -0,0 +1,253 @@ +#include "globals.hlsli" +#include "ShaderInterop_SurfelGI.h" +#include "brdf.hlsli" + +//#define SURFEL_DEBUG_NORMAL +//#define SURFEL_DEBUG_COLOR +#define SURFEL_DEBUG_POINT +//#define SURFEL_DEBUG_RANDOM +//#define SURFEL_DEBUG_HEATMAP + + +static const uint random_colors_size = 11; +static const float3 random_colors[random_colors_size] = { + float3(0,0,1), + float3(0,1,1), + float3(0,1,0), + float3(1,1,0), + float3(1,0,0), + float3(1,0,1), + float3(0.5,1,1), + float3(0.5,1,0.5), + float3(1,1,0.5), + float3(1,0.5,0.5), + float3(1,0.5,1), +}; +float3 random_color(uint index) +{ + return random_colors[index % random_colors_size]; +} + +STRUCTUREDBUFFER(surfelBuffer, Surfel, TEXSLOT_ONDEMAND0); +STRUCTUREDBUFFER(surfelGridBuffer, SurfelGridCell, TEXSLOT_ONDEMAND2); +STRUCTUREDBUFFER(surfelCellBuffer, uint, TEXSLOT_ONDEMAND3); +TEXTURE2D(surfelMomentsTexture, float2, TEXSLOT_ONDEMAND4); + +RWSTRUCTUREDBUFFER(surfelDataBuffer, SurfelData, 0); +RWRAWBUFFER(surfelStatsBuffer, 1); +RWTEXTURE2D(result, float3, 2); +RWTEXTURE2D(debugUAV, unorm float4, 3); + +void write_result(uint2 DTid, float4 color) +{ +#ifdef SURFEL_COVERAGE_HALFRES + result[DTid * 2 + uint2(0, 0)] = color.rgb; + result[DTid * 2 + uint2(1, 0)] = color.rgb; + result[DTid * 2 + uint2(0, 1)] = color.rgb; + result[DTid * 2 + uint2(1, 1)] = color.rgb; +#else + result[DTid] = color.rgb; +#endif // SURFEL_COVERAGE_HALFRES +} +void write_debug(uint2 DTid, float4 debug) +{ +#ifdef SURFEL_COVERAGE_HALFRES + debugUAV[DTid * 2 + uint2(0, 0)] = debug; + debugUAV[DTid * 2 + uint2(1, 0)] = debug; + debugUAV[DTid * 2 + uint2(0, 1)] = debug; + debugUAV[DTid * 2 + uint2(1, 1)] = debug; +#else + debugUAV[DTid] = debug; +#endif // SURFEL_COVERAGE_HALFRES +} + +groupshared uint GroupMinSurfelCount; + +[numthreads(16, 16, 1)] +void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex, uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID) +{ + if (groupIndex == 0) + { + GroupMinSurfelCount = ~0; + } + GroupMemoryBarrierWithGroupSync(); + +#ifdef SURFEL_COVERAGE_HALFRES + uint2 pixel = DTid.xy * 2 + GetTemporalAASampleRotation(); +#else + uint2 pixel = DTid.xy; +#endif // SURFEL_COVERAGE_HALFRES + + const float depth = texture_depth[pixel]; + if (depth == 0) + { + write_debug(DTid.xy, 0); + return; + } + + float4 debug = 0; + float4 color = 0; + + const float2 uv = ((float2)pixel + 0.5) * g_xFrame.InternalResolution_rcp; + const float3 P = reconstructPosition(uv, depth); + + uint2 primitiveID = texture_gbuffer0[pixel]; + + PrimitiveID prim; + prim.unpack(primitiveID); + + Surface surface; + if (!surface.load(prim, P)) + { + return; + } + + const float3 N = surface.facenormal; + + float coverage = 0; + + int3 gridpos = surfel_cell(P); + if (!surfel_cellvalid(gridpos)) + { + write_debug(DTid.xy, 0); + return; + } + + uint cellindex = surfel_cellindex(gridpos); + SurfelGridCell cell = surfelGridBuffer[cellindex]; + for (uint i = 0; i < cell.count; ++i) + { + uint surfel_index = surfelCellBuffer[cell.offset + i]; + Surfel surfel = surfelBuffer[surfel_index]; + + float3 L = surfel.position - P; + float dist2 = dot(L, L); + if (dist2 < sqr(surfel.radius)) + { + float3 normal = normalize(unpack_unitvector(surfel.normal)); + float dotN = dot(N, normal); + if (dotN > 0) + { + float dist = sqrt(dist2); + float contribution = 1; + + float2 moments = surfelMomentsTexture.SampleLevel(sampler_linear_clamp, surfel_moment_uv(surfel_index, normal, -L / dist), 0); + contribution *= surfel_moment_weight(moments, dist); + + + contribution *= saturate(dotN); + contribution *= saturate(1 - dist / surfel.radius); + contribution = smoothstep(0, 1, contribution); + coverage += contribution; + + color += float4(surfel.color, 1) * contribution; + +#ifdef SURFEL_DEBUG_NORMAL + debug.rgb += normal * contribution; + debug.a = 1; +#endif // SURFEL_DEBUG_NORMAL + +#ifdef SURFEL_DEBUG_RANDOM + debug += float4(random_color(surfel_index), 1) * contribution; +#endif // SURFEL_DEBUG_RANDOM + + } + +#ifdef SURFEL_DEBUG_POINT + if (dist2 <= sqr(0.05)) + debug = float4(1, 0, 1, 1); +#endif // SURFEL_DEBUG_POINT + } + + } + + if (cell.count < SURFEL_CELL_LIMIT) + { + uint surfel_count_at_pixel = 0; + surfel_count_at_pixel |= (uint(coverage) & 0xFF) << 8; + surfel_count_at_pixel |= (GTid.x & 0xF) << 4; + surfel_count_at_pixel |= (GTid.y & 0xF) << 0; + InterlockedMin(GroupMinSurfelCount, surfel_count_at_pixel); + } + + if (color.a > 0) + { + color.rgb /= color.a; + color.a = saturate(color.a); + } + +#ifdef SURFEL_DEBUG_NORMAL + debug.rgb = normalize(debug.rgb) * 0.5 + 0.5; +#endif // SURFEL_DEBUG_NORMAL + +#ifdef SURFEL_DEBUG_COLOR + debug = color; + debug.rgb = tonemap(debug.rgb); +#endif // SURFEL_DEBUG_COLOR + +#if defined(SURFEL_DEBUG_RANDOM) + if (debug.a > 0) + { + debug /= debug.a; + } + else + { + debug = 0; + } +#endif // SURFEL_DEBUG_RANDOM + +#ifdef SURFEL_DEBUG_HEATMAP + const float3 mapTex[] = { + float3(0,0,0), + float3(0,0,1), + float3(0,1,1), + float3(0,1,0), + float3(1,1,0), + float3(1,0,0), + }; + const uint mapTexLen = 5; + const uint maxHeat = 50; + float l = saturate((float)cell.count / maxHeat) * mapTexLen; + float3 a = mapTex[floor(l)]; + float3 b = mapTex[ceil(l)]; + float4 heatmap = float4(lerp(a, b, l - floor(l)), 0.8); + debug = heatmap; +#endif // SURFEL_DEBUG_HEATMAP + + + GroupMemoryBarrierWithGroupSync(); + + uint surfel_coverage = GroupMinSurfelCount; + uint2 minGTid; + minGTid.x = (surfel_coverage >> 4) & 0xF; + minGTid.y = (surfel_coverage >> 0) & 0xF; + uint coverage_amount = surfel_coverage >> 8; + if (GTid.x == minGTid.x && GTid.y == minGTid.y && coverage < SURFEL_TARGET_COVERAGE) + { + // Slow down the propagation by chance + // Closer surfaces have less chance to avoid excessive clumping of surfels + const float lineardepth = getLinearDepth(depth) * g_xCamera.ZFarP_rcp; +#ifdef SURFEL_COVERAGE_HALFRES + const float chance = pow(1 - lineardepth, 8); +#else + const float chance = pow(1 - lineardepth, 4); +#endif // SURFEL_COVERAGE_HALFRES + if (blue_noise(Gid.xy).x < chance) + return; + + uint surfel_alloc; + surfelStatsBuffer.InterlockedAdd(SURFEL_STATS_OFFSET_COUNT, 1, surfel_alloc); + if (surfel_alloc < SURFEL_CAPACITY) + { + SurfelData surfel_data = (SurfelData)0; + surfel_data.primitiveID = primitiveID; + surfel_data.bary = pack_half2(surface.bary.xy); + surfel_data.uid = surface.inst.uid; + surfel_data.inconsistency = 1; + surfelDataBuffer[surfel_alloc] = surfel_data; + } + } + + write_result(DTid.xy, color); + write_debug(DTid.xy, debug); +} diff --git a/WickedEngine/shaders/surfel_gridoffsetsCS.hlsl b/WickedEngine/shaders/surfel_gridoffsetsCS.hlsl new file mode 100644 index 000000000..ed2bbaa1c --- /dev/null +++ b/WickedEngine/shaders/surfel_gridoffsetsCS.hlsl @@ -0,0 +1,15 @@ +#include "globals.hlsli" +#include "ShaderInterop_SurfelGI.h" + +RWSTRUCTUREDBUFFER(surfelGridBuffer, SurfelGridCell, 0); +RWSTRUCTUREDBUFFER(surfelCellBuffer, uint, 1); +RWRAWBUFFER(surfelStatsBuffer, 2); + +[numthreads(64, 1, 1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + SurfelGridCell cell = surfelGridBuffer[DTid.x]; + surfelStatsBuffer.InterlockedAdd(SURFEL_STATS_OFFSET_CELLALLOCATOR, cell.count, cell.offset); + cell.count = 0; + surfelGridBuffer[DTid.x] = cell; +} diff --git a/WickedEngine/shaders/surfel_gridresetCS.hlsl b/WickedEngine/shaders/surfel_gridresetCS.hlsl new file mode 100644 index 000000000..d68f45fa3 --- /dev/null +++ b/WickedEngine/shaders/surfel_gridresetCS.hlsl @@ -0,0 +1,10 @@ +#include "globals.hlsli" +#include "ShaderInterop_SurfelGI.h" + +RWSTRUCTUREDBUFFER(surfelGridBuffer, SurfelGridCell, 0); + +[numthreads(64, 1, 1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + surfelGridBuffer[DTid.x].count = 0; +} diff --git a/WickedEngine/shaders/surfel_indirectprepareCS.hlsl b/WickedEngine/shaders/surfel_indirectprepareCS.hlsl new file mode 100644 index 000000000..9973c197f --- /dev/null +++ b/WickedEngine/shaders/surfel_indirectprepareCS.hlsl @@ -0,0 +1,15 @@ +#include "globals.hlsli" +#include "ShaderInterop_SurfelGI.h" + +RWRAWBUFFER(surfelStatsBuffer, 0); + +[numthreads(1, 1, 1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + uint surfel_count = surfelStatsBuffer.Load(SURFEL_STATS_OFFSET_COUNT); + surfel_count = min(surfel_count, SURFEL_CAPACITY); + surfelStatsBuffer.Store(SURFEL_STATS_OFFSET_COUNT, surfel_count); + surfelStatsBuffer.Store(SURFEL_STATS_OFFSET_CELLALLOCATOR, 0); + + surfelStatsBuffer.Store3(SURFEL_STATS_OFFSET_INDIRECT, uint3((surfel_count + SURFEL_INDIRECT_NUMTHREADS - 1) / SURFEL_INDIRECT_NUMTHREADS, 1, 1)); +} diff --git a/WickedEngine/shaders/surfel_raytraceCS.hlsl b/WickedEngine/shaders/surfel_raytraceCS.hlsl new file mode 100644 index 000000000..58b57ae54 --- /dev/null +++ b/WickedEngine/shaders/surfel_raytraceCS.hlsl @@ -0,0 +1,322 @@ +#include "globals.hlsli" +#include "raytracingHF.hlsli" +#include "lightingHF.hlsli" +#include "ShaderInterop_SurfelGI.h" + + +STRUCTUREDBUFFER(surfelBuffer, Surfel, TEXSLOT_ONDEMAND0); +RAWBUFFER(surfelStatsBuffer, TEXSLOT_ONDEMAND1); +STRUCTUREDBUFFER(surfelGridBuffer, SurfelGridCell, TEXSLOT_ONDEMAND2); +STRUCTUREDBUFFER(surfelCellBuffer, uint, TEXSLOT_ONDEMAND3); + +RWSTRUCTUREDBUFFER(surfelDataBuffer, SurfelData, 0); +RWTEXTURE2D(surfelMomentsTexture, float2, 1); + +void surfel_moments_write(uint2 moments_pixel, float dist) +{ + float2 prev = surfelMomentsTexture[moments_pixel]; + float2 blend = prev.x < dist ? 0.005 : 0.5; + surfelMomentsTexture[moments_pixel] = lerp(prev, float2(dist, sqr(dist)), blend); +} + +[numthreads(SURFEL_INDIRECT_NUMTHREADS, 1, 1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + uint surfel_count = surfelStatsBuffer.Load(SURFEL_STATS_OFFSET_COUNT); + if (DTid.x >= surfel_count) + return; + + uint surfel_index = DTid.x; + Surfel surfel = surfelBuffer[surfel_index]; + SurfelData surfel_data = surfelDataBuffer[surfel_index]; + + if (surfel_data.life == 0) + { + uint2 moments_pixel = unflatten2D(surfel_index, SQRT_SURFEL_CAPACITY) * SURFEL_MOMENT_TEXELS; + for (int i = 0; i < SURFEL_MOMENT_TEXELS; ++i) + { + for (int j = 0; j < SURFEL_MOMENT_TEXELS; ++j) + { + uint2 pixel_write = moments_pixel + uint2(i, j); + surfelMomentsTexture[pixel_write] = float2(surfel.radius, sqr(surfel.radius)); + } + } + } + + const float3 N = normalize(unpack_unitvector(surfel.normal)); + + float seed = 0.123456; + float2 uv = float2(frac(g_xFrame.FrameCount.x / 4096.0), (float)surfel_index / SURFEL_CAPACITY); + + RayDesc ray; + ray.Origin = surfel.position; + ray.TMin = 0.001; + ray.TMax = FLT_MAX; + ray.Direction = normalize(SampleHemisphere_cos(N, seed, uv)); + + uint2 moments_pixel = surfel_moment_pixel(surfel_index, N, ray.Direction); + float moment_blend = 0.5; + + float3 result = 0; + float3 energy = 1; + + +#ifdef RTAPI + RayQuery< + RAY_FLAG_SKIP_PROCEDURAL_PRIMITIVES | + RAY_FLAG_FORCE_OPAQUE + > q; + q.TraceRayInline( + scene_acceleration_structure, // RaytracingAccelerationStructure AccelerationStructure + 0, // uint RayFlags + 0xFF, // uint InstanceInclusionMask + ray // RayDesc Ray + ); + q.Proceed(); + if (q.CommittedStatus() != COMMITTED_TRIANGLE_HIT) +#else + RayHit hit = TraceRay_Closest(ray); + + if (hit.distance >= FLT_MAX - 1) +#endif // RTAPI + + { + surfel_data.hitpos = 0; + surfel_data.hitnormal = ~0; + + surfel_moments_write(moments_pixel, surfel.radius); + + float3 envColor; + [branch] + if (IsStaticSky()) + { + // We have envmap information in a texture: + envColor = DEGAMMA_SKY(texture_globalenvmap.SampleLevel(sampler_linear_clamp, ray.Direction, 0).rgb); + } + else + { + envColor = GetDynamicSkyColor(ray.Direction, true, true, false, true); + } + result += max(0, energy * envColor); + + // Erase the ray's energy + energy = 0; + } + + Surface surface; + + float hit_depth = 0; + +#ifdef RTAPI + + // ray origin updated for next bounce: + ray.Origin = q.WorldRayOrigin() + q.WorldRayDirection() * q.CommittedRayT(); + hit_depth = q.CommittedRayT(); + + PrimitiveID prim; + prim.primitiveIndex = q.CommittedPrimitiveIndex(); + prim.instanceIndex = q.CommittedInstanceID(); + prim.subsetIndex = q.CommittedGeometryIndex(); + + surface.load(prim, q.CommittedTriangleBarycentrics()); + +#else + + // ray origin updated for next bounce: + ray.Origin = ray.Origin + ray.Direction * hit.distance; + hit_depth = hit.distance; + + surface.load(hit.primitiveID, hit.bary); + +#endif // RTAPI + + hit_depth = min(hit_depth, surfel.radius); + surfel_moments_write(moments_pixel, hit_depth); + + surface.P = ray.Origin; + surface.V = -ray.Direction; + surface.update(); + + result += max(0, energy * surface.emissiveColor.rgb * surface.emissiveColor.a); + + // Calculate chances of reflection types: + const float specChance = dot(surface.F, 0.333f); + + float roulette = rand(seed, uv); + if (roulette < specChance) + { + // Specular reflection + const float3 R = reflect(ray.Direction, surface.N); + ray.Direction = lerp(R, SampleHemisphere_cos(R, seed, uv), surface.roughnessBRDF); + energy *= surface.F / specChance; + } + else + { + // Diffuse reflection + ray.Direction = SampleHemisphere_cos(surface.N, seed, uv); + energy *= surface.albedo / (1 - specChance); + } + + + + + + + + +#if 1 + // Light sampling: + [loop] + for (uint iterator = 0; iterator < g_xFrame.LightArrayCount; iterator++) + { + ShaderEntity light = EntityArray[g_xFrame.LightArrayOffset + iterator]; + + Lighting lighting; + lighting.create(0, 0, 0, 0); + + float3 L = 0; + float dist = 0; + float NdotL = 0; + + switch (light.GetType()) + { + case ENTITY_TYPE_DIRECTIONALLIGHT: + { + dist = FLT_MAX; + + L = light.GetDirection().xyz; + NdotL = saturate(dot(L, surface.N)); + + [branch] + if (NdotL > 0) + { + float3 atmosphereTransmittance = 1.0; + if (g_xFrame.Options & OPTION_BIT_REALISTIC_SKY) + { + atmosphereTransmittance = GetAtmosphericLightTransmittance(g_xFrame.Atmosphere, surface.P, L, texture_transmittancelut); + } + + float3 lightColor = light.GetColor().rgb * light.GetEnergy() * atmosphereTransmittance; + + lighting.direct.diffuse = lightColor; + } + } + break; + case ENTITY_TYPE_POINTLIGHT: + { + L = light.position - surface.P; + const float dist2 = dot(L, L); + const float range2 = light.GetRange() * light.GetRange(); + + [branch] + if (dist2 < range2) + { + dist = sqrt(dist2); + L /= dist; + NdotL = saturate(dot(L, surface.N)); + + [branch] + if (NdotL > 0) + { + const float3 lightColor = light.GetColor().rgb * light.GetEnergy(); + + lighting.direct.diffuse = lightColor; + + const float range2 = light.GetRange() * light.GetRange(); + const float att = saturate(1.0 - (dist2 / range2)); + const float attenuation = att * att; + + lighting.direct.diffuse *= attenuation; + } + } + } + break; + case ENTITY_TYPE_SPOTLIGHT: + { + L = light.position - surface.P; + const float dist2 = dot(L, L); + const float range2 = light.GetRange() * light.GetRange(); + + [branch] + if (dist2 < range2) + { + dist = sqrt(dist2); + L /= dist; + NdotL = saturate(dot(L, surface.N)); + + [branch] + if (NdotL > 0) + { + const float SpotFactor = dot(L, light.GetDirection()); + const float spotCutOff = light.GetConeAngleCos(); + + [branch] + if (SpotFactor > spotCutOff) + { + const float3 lightColor = light.GetColor().rgb * light.GetEnergy(); + + lighting.direct.diffuse = lightColor; + + const float range2 = light.GetRange() * light.GetRange(); + const float att = saturate(1.0 - (dist2 / range2)); + float attenuation = att * att; + attenuation *= saturate((1.0 - (1.0 - SpotFactor) * 1.0 / (1.0 - spotCutOff))); + + lighting.direct.diffuse *= attenuation; + } + } + } + } + break; + } + + if (NdotL > 0 && dist > 0) + { + float3 shadow = NdotL * energy; + + RayDesc newRay; + newRay.Origin = surface.P; + newRay.Direction = normalize(lerp(L, SampleHemisphere_cos(L, seed, uv), 0.025f)); + newRay.TMin = 0.001; + newRay.TMax = dist; +#ifdef RTAPI + q.TraceRayInline( + scene_acceleration_structure, // RaytracingAccelerationStructure AccelerationStructure + RAY_FLAG_ACCEPT_FIRST_HIT_AND_END_SEARCH, // uint RayFlags + 0xFF, // uint InstanceInclusionMask + newRay // RayDesc Ray + ); + q.Proceed(); + shadow = q.CommittedStatus() == COMMITTED_TRIANGLE_HIT ? 0 : shadow; +#else + shadow = TraceRay_Any(newRay) ? 0 : shadow; +#endif // RTAPI + if (any(shadow)) + { + result += max(0, shadow * lighting.direct.diffuse / PI); + } + } + } + +#endif + + + uint2 moments_topleft = unflatten2D(surfel_index, SQRT_SURFEL_CAPACITY) * SURFEL_MOMENT_TEXELS; + for (uint i = 0; i < SURFEL_MOMENT_TEXELS; ++i) + { + for (uint j = 0; j < SURFEL_MOMENT_TEXELS; ++j) + { + uint2 pixel_write = moments_topleft + uint2(i, j); + uint2 pixel_read = clamp(pixel_write, moments_topleft + 1, moments_topleft + SURFEL_MOMENT_TEXELS - 2); + surfelMomentsTexture[pixel_write] = surfelMomentsTexture[pixel_read]; + } + } + + surfel_data.hitpos = surface.P; + surfel_data.hitnormal = pack_unitvector(surface.facenormal); + surfel_data.hitenergy = energy; + surfel_data.traceresult = result; + + surfel_data.life++; + surfelDataBuffer[surfel_index] = surfel_data; +} diff --git a/WickedEngine/shaders/surfel_raytraceCS_rtapi.hlsl b/WickedEngine/shaders/surfel_raytraceCS_rtapi.hlsl new file mode 100644 index 000000000..7485b7f52 --- /dev/null +++ b/WickedEngine/shaders/surfel_raytraceCS_rtapi.hlsl @@ -0,0 +1,2 @@ +#define RTAPI +#include "surfel_raytraceCS.hlsl" diff --git a/WickedEngine/shaders/surfel_shadeCS.hlsl b/WickedEngine/shaders/surfel_shadeCS.hlsl new file mode 100644 index 000000000..7c838abad --- /dev/null +++ b/WickedEngine/shaders/surfel_shadeCS.hlsl @@ -0,0 +1,180 @@ +#include "globals.hlsli" +#include "brdf.hlsli" +#include "ShaderInterop_SurfelGI.h" + + +void MultiscaleMeanEstimator( + float3 y, + inout SurfelData data, + float shortWindowBlend = 0.08f +) +{ + float3 mean = data.mean; + float3 shortMean = data.shortMean; + float vbbr = data.vbbr; + float3 variance = data.variance; + float inconsistency = data.inconsistency; + + // Suppress fireflies. + { + float3 dev = sqrt(max(1e-5, variance)); + float3 highThreshold = 0.1 + shortMean + dev * 8; + float3 overflow = max(0, y - highThreshold); + y -= overflow; + } + + float3 delta = y - shortMean; + shortMean = lerp(shortMean, y, shortWindowBlend); + float3 delta2 = y - shortMean; + + // This should be a longer window than shortWindowBlend to avoid bias + // from the variance getting smaller when the short-term mean does. + float varianceBlend = shortWindowBlend * 0.5; + variance = lerp(variance, delta * delta2, varianceBlend); + float3 dev = sqrt(max(1e-5, variance)); + + float3 shortDiff = mean - shortMean; + + float relativeDiff = dot(float3(0.299, 0.587, 0.114), + abs(shortDiff) / max(1e-5, dev)); + inconsistency = lerp(inconsistency, relativeDiff, 0.08); + + float varianceBasedBlendReduction = + clamp(dot(float3(0.299, 0.587, 0.114), + 0.5 * shortMean / max(1e-5, dev)), 1.0 / 32, 1); + + float3 catchUpBlend = clamp(smoothstep(0, 1, + relativeDiff * max(0.02, inconsistency - 0.2)), 1.0 / 256, 1); + catchUpBlend *= vbbr; + + vbbr = lerp(vbbr, varianceBasedBlendReduction, 0.1); + mean = lerp(mean, y, saturate(catchUpBlend)); + + // Output + data.mean = mean; + data.shortMean = shortMean; + data.vbbr = vbbr; + data.variance = variance; + data.inconsistency = inconsistency; +} + +STRUCTUREDBUFFER(surfelBuffer, Surfel, TEXSLOT_ONDEMAND0); +RAWBUFFER(surfelStatsBuffer, TEXSLOT_ONDEMAND1); +STRUCTUREDBUFFER(surfelGridBuffer, SurfelGridCell, TEXSLOT_ONDEMAND2); +STRUCTUREDBUFFER(surfelCellBuffer, uint, TEXSLOT_ONDEMAND3); +TEXTURE2D(surfelMomentsTexture, float2, TEXSLOT_ONDEMAND4); + +RWSTRUCTUREDBUFFER(surfelDataBuffer, SurfelData, 0); + +[numthreads(SURFEL_INDIRECT_NUMTHREADS, 1, 1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + uint surfel_count = surfelStatsBuffer.Load(SURFEL_STATS_OFFSET_COUNT); + if (DTid.x >= surfel_count) + return; + + uint surfel_index = DTid.x; + Surfel surfel = surfelBuffer[surfel_index]; + SurfelData surfel_data = surfelDataBuffer[surfel_index]; + + float4 result = float4(surfel_data.traceresult, 1); + +#if 1 + // Evaluate surfel cache at hit point for multi bounce: + { + Surface surface; + surface.P = surfel_data.hitpos; + surface.N = normalize(unpack_unitvector(surfel_data.hitnormal)); + + float4 surfel_gi = 0; + uint cellindex = surfel_cellindex(surfel_cell(surface.P)); + SurfelGridCell cell = surfelGridBuffer[cellindex]; + for (uint i = 0; i < cell.count; ++i) + { + uint surfel_index = surfelCellBuffer[cell.offset + i]; + Surfel surfel = surfelBuffer[surfel_index]; + + float3 L = surfel.position - surface.P; + float dist2 = dot(L, L); + if (dist2 < sqr(surfel.radius)) + { + float3 normal = normalize(unpack_unitvector(surfel.normal)); + float dotN = dot(surface.N, normal); + if (dotN > 0) + { + float dist = sqrt(dist2); + float contribution = 1; + + float2 moments = surfelMomentsTexture.SampleLevel(sampler_linear_clamp, surfel_moment_uv(surfel_index, normal, -L / dist), 0); + contribution *= surfel_moment_weight(moments, dist); + + contribution *= saturate(1 - dist / surfel.radius); + contribution = smoothstep(0, 1, contribution); + contribution *= saturate(dotN); + + surfel_gi += float4(surfel.color, 1) * contribution; + + } + } + } + if (surfel_gi.a > 0) + { + surfel_gi.rgb /= surfel_gi.a; + surfel_gi.a = saturate(surfel_gi.a); + result.rgb += max(0, surfel_data.hitenergy * surfel_gi.rgb); + } + } +#endif + + + + +#if 1 + // Surfel irradiance sharing: + { + Surface surface; + surface.P = surfel.position; + surface.N = normalize(unpack_unitvector(surfel.normal)); + float radius = surfel.radius; + + uint cellindex = surfel_cellindex(surfel_cell(surface.P)); + SurfelGridCell cell = surfelGridBuffer[cellindex]; + for (uint i = 0; i < cell.count; ++i) + { + uint surfel_index = surfelCellBuffer[cell.offset + i]; + Surfel surfel = surfelBuffer[surfel_index]; + surfel.radius += radius; + + float3 L = surfel.position - surface.P; + float dist2 = dot(L, L); + if (dist2 < sqr(surfel.radius)) + { + float3 normal = normalize(unpack_unitvector(surfel.normal)); + float dotN = dot(surface.N, normal); + if (dotN > 0) + { + float dist = sqrt(dist2); + float contribution = 1; + + float2 moments = surfelMomentsTexture.SampleLevel(sampler_linear_clamp, surfel_moment_uv(surfel_index, normal, -L / dist), 0); + contribution *= surfel_moment_weight(moments, dist); + + contribution *= saturate(1 - dist / surfel.radius); + contribution = smoothstep(0, 1, contribution); + contribution *= saturate(dotN); + + result += float4(surfel.color, 1) * contribution; + + } + } + } + } +#endif + + result /= result.a; + + + MultiscaleMeanEstimator(result.rgb, surfel_data, 0.08); + + surfelDataBuffer[surfel_index] = surfel_data; +} diff --git a/WickedEngine/shaders/surfel_updateCS.hlsl b/WickedEngine/shaders/surfel_updateCS.hlsl new file mode 100644 index 000000000..c1813dddd --- /dev/null +++ b/WickedEngine/shaders/surfel_updateCS.hlsl @@ -0,0 +1,52 @@ +#include "globals.hlsli" +#include "ShaderInterop_SurfelGI.h" +#include "brdf.hlsli" + +RAWBUFFER(surfelStatsBuffer, TEXSLOT_ONDEMAND0); +STRUCTUREDBUFFER(surfelDataBuffer, SurfelData, TEXSLOT_ONDEMAND1); + +RWSTRUCTUREDBUFFER(surfelBuffer, Surfel, 0); +RWSTRUCTUREDBUFFER(surfelGridBuffer, SurfelGridCell, 1); + +[numthreads(SURFEL_INDIRECT_NUMTHREADS, 1, 1)] +void main(uint3 DTid : SV_DispatchThreadID) +{ + uint surfel_count = surfelStatsBuffer.Load(SURFEL_STATS_OFFSET_COUNT); + if (DTid.x >= surfel_count) + return; + + uint surfel_index = DTid.x; + SurfelData surfel_data = surfelDataBuffer[surfel_index]; + Surfel surfel = surfelBuffer[surfel_index]; + + + PrimitiveID prim; + prim.unpack(surfel_data.primitiveID); + + Surface surface; + if (surface.load(prim, unpack_half2(surfel_data.bary), surfel_data.uid)) + { + surfel.normal = pack_unitvector(surface.facenormal); + surfel.position = surface.P; + surfel.color = surfel_data.mean; + surfel.radius = SURFEL_MAX_RADIUS; + + int3 center_cell = surfel_cell(surfel.position); + for (uint i = 0; i < 27; ++i) + { + int3 gridpos = center_cell + surfel_neighbor_offsets[i]; + + if(surfel_cellintersects(surfel, gridpos)) + { + uint cellindex = surfel_cellindex(gridpos); + InterlockedAdd(surfelGridBuffer[cellindex].count, 1); + } + } + } + else + { + surfel.radius = 0; + } + + surfelBuffer[surfel_index] = surfel; +} diff --git a/WickedEngine/shaders/temporalaaCS.hlsl b/WickedEngine/shaders/temporalaaCS.hlsl index d8453f072..630e065bf 100644 --- a/WickedEngine/shaders/temporalaaCS.hlsl +++ b/WickedEngine/shaders/temporalaaCS.hlsl @@ -66,7 +66,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3 } } } - const float2 velocity = texture_gbuffer2[DTid.xy + bestOffset].xy; + const float2 velocity = texture_gbuffer1[DTid.xy + bestOffset].xy; #else @@ -94,7 +94,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3 } } } - const float2 velocity = texture_gbuffer2[bestPixel].xy; + const float2 velocity = texture_gbuffer1[bestPixel].xy; #endif // USE_LDS @@ -102,7 +102,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3 #if 0 // Disocclusion fallback: - float depth_current = texture_lineardepth[DTid.xy] * g_xCamera_ZFarP; + float depth_current = texture_lineardepth[DTid.xy] * g_xCamera.ZFarP; float depth_history = getLinearDepth(texture_depth_history.SampleLevel(sampler_point_clamp, prevUV, 0)); if (length(velocity) > 0.01 && abs(depth_current - depth_history) > 1) { @@ -119,7 +119,7 @@ void main(uint3 DTid : SV_DispatchThreadID, uint3 GTid : SV_GroupThreadID, uint3 history.rgb = clamp(history.rgb, neighborhoodMin, neighborhoodMax); // the linear filtering can cause blurry image, try to account for that: - float subpixelCorrection = frac(max(abs(velocity.x)*g_xFrame_InternalResolution.x, abs(velocity.y)*g_xFrame_InternalResolution.y)) * 0.5f; + float subpixelCorrection = frac(max(abs(velocity.x)*g_xFrame.InternalResolution.x, abs(velocity.y)*g_xFrame.InternalResolution.y)) * 0.5f; // compute a nice blend factor: float blendfactor = saturate(lerp(0.05f, 0.8f, subpixelCorrection)); diff --git a/WickedEngine/shaders/tileFrustumsCS.hlsl b/WickedEngine/shaders/tileFrustumsCS.hlsl index 7a9adc66c..c7adbb8f5 100644 --- a/WickedEngine/shaders/tileFrustumsCS.hlsl +++ b/WickedEngine/shaders/tileFrustumsCS.hlsl @@ -46,8 +46,8 @@ void main(uint3 DTid : SV_DispatchThreadID) frustum.planes[3] = ComputePlane(viewSpace[3], eyePos, viewSpace[2]); // Store the computed frustum in global memory (if our thread ID is in bounds of the grid). - if (DTid.x < g_xFrame_EntityCullingTileCount.x && DTid.y < g_xFrame_EntityCullingTileCount.y) + if (DTid.x < g_xFrame.EntityCullingTileCount.x && DTid.y < g_xFrame.EntityCullingTileCount.y) { - out_Frustums[flatten2D(DTid.xy, g_xFrame_EntityCullingTileCount.xy)] = frustum; + out_Frustums[flatten2D(DTid.xy, g_xFrame.EntityCullingTileCount.xy)] = frustum; } } diff --git a/WickedEngine/shaders/tonemapCS.hlsl b/WickedEngine/shaders/tonemapCS.hlsl index bcd92580f..3d71a1223 100644 --- a/WickedEngine/shaders/tonemapCS.hlsl +++ b/WickedEngine/shaders/tonemapCS.hlsl @@ -1,19 +1,7 @@ #include "globals.hlsli" #include "ShaderInterop_Postprocess.h" -#ifdef BINDLESS PUSHCONSTANT(push, PushConstantsTonemap); -Texture2D bindless_textures[] : register(t0, space1); -Texture3D bindless_textures3D[] : register(t0, space2); -RWTexture2D bindless_rwtextures[] : register(u0, space3); -#else -TEXTURE2D(input, float4, TEXSLOT_ONDEMAND0); -TEXTURE2D(input_luminance, float, TEXSLOT_ONDEMAND1); -TEXTURE2D(input_distortion, float4, TEXSLOT_ONDEMAND2); -TEXTURE3D(colorgrade_lookuptable, float4, TEXSLOT_ONDEMAND3); - -RWTEXTURE2D(output, unorm float4, 0); -#endif // BINDLESS // https://github.com/TheRealMJP/BakingLab/blob/master/BakingLab/ACES.hlsl // sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT @@ -57,7 +45,6 @@ float3 ACESFitted(float3 color) [numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)] void main(uint3 DTid : SV_DispatchThreadID) { -#ifdef BINDLESS const float2 uv = (DTid.xy + 0.5f) * push.xPPResolution_rcp; float exposure = push.exposure; const bool is_dither = push.dither != 0; @@ -79,29 +66,6 @@ void main(uint3 DTid : SV_DispatchThreadID) { exposure *= push.eyeadaptionkey / max(bindless_textures[push.texture_input_luminance][uint2(0, 0)].r, 0.0001); } -#else - const float2 uv = (DTid.xy + 0.5f) * xPPResolution_rcp; - float exposure = tonemap_exposure; - const bool is_dither = tonemap_dither != 0; - const bool is_colorgrading = tonemap_colorgrading != 0; - const bool is_eyeadaption = tonemap_eyeadaption != 0; - const bool is_distortion = tonemap_distortion != 0; - - float2 distortion = 0; - [branch] - if (is_distortion) - { - distortion = input_distortion.SampleLevel(sampler_linear_clamp, uv, 0).rg; - } - - float4 hdr = input.SampleLevel(sampler_linear_clamp, uv + distortion, 0); - - [branch] - if (is_eyeadaption) - { - exposure *= tonemap_eyeadaptionkey / max(input_luminance[uint2(0, 0)].r, 0.0001); - } -#endif // BINDLESS hdr.rgb *= exposure; float4 ldr = float4(ACESFitted(hdr.rgb), hdr.a); @@ -116,11 +80,7 @@ void main(uint3 DTid : SV_DispatchThreadID) if (is_colorgrading) { -#ifdef BINDLESS ldr.rgb = bindless_textures3D[push.texture_colorgrade_lookuptable].SampleLevel(sampler_linear_clamp, ldr.rgb, 0).rgb; -#else - ldr.rgb = colorgrade_lookuptable.SampleLevel(sampler_linear_clamp, ldr.rgb, 0).rgb; -#endif // BINDLESS } if (is_dither) @@ -129,9 +89,5 @@ void main(uint3 DTid : SV_DispatchThreadID) ldr.rgb += (dither((float2)DTid.xy) - 0.5f) / 64.0f; } -#ifdef BINDLESS bindless_rwtextures[push.texture_output][DTid.xy] = ldr; -#else - output[DTid.xy] = ldr; -#endif // BINDLESS } diff --git a/WickedEngine/shaders/upsample_bilateral_float4CS.hlsl b/WickedEngine/shaders/upsample_bilateral_float4CS.hlsl index 0b7c388fe..4f6ba4431 100644 --- a/WickedEngine/shaders/upsample_bilateral_float4CS.hlsl +++ b/WickedEngine/shaders/upsample_bilateral_float4CS.hlsl @@ -43,7 +43,7 @@ void main(uint3 DTid : SV_DispatchThreadID) texture_lineardepth.SampleLevel(sampler_point_clamp, uv11, lowres_depthchain_mip) ); - const float4 depth_diff = abs(lineardepth_highres - lineardepth_lowres) * g_xCamera_ZFarP; + const float4 depth_diff = abs(lineardepth_highres - lineardepth_lowres) * g_xCamera.ZFarP; const float accum_diff = dot(depth_diff, float4(1, 1, 1, 1)); UPSAMPLE_FORMAT color; diff --git a/WickedEngine/shaders/vPointLightVS.hlsl b/WickedEngine/shaders/vPointLightVS.hlsl index 75f89db2f..324c7e5b4 100644 --- a/WickedEngine/shaders/vPointLightVS.hlsl +++ b/WickedEngine/shaders/vPointLightVS.hlsl @@ -7,7 +7,7 @@ VertexToPixel main(uint vID : SV_VertexID) float4 pos = CIRCLE[vID]; pos = mul(lightWorld, pos); - Out.pos = mul(g_xCamera_VP, pos); + Out.pos = mul(g_xCamera.VP, pos); Out.col = lerp( float4(lightColor.rgb, 1), float4(0, 0, 0, 0), distance(pos.xyz, float3(lightWorld._14, lightWorld._24, lightWorld._34)) / (lightEnerdis.w) diff --git a/WickedEngine/shaders/vSpotLightVS.hlsl b/WickedEngine/shaders/vSpotLightVS.hlsl index 2ad338e21..554827fc1 100644 --- a/WickedEngine/shaders/vSpotLightVS.hlsl +++ b/WickedEngine/shaders/vSpotLightVS.hlsl @@ -7,7 +7,7 @@ VertexToPixel main(uint vID : SV_VertexID) float4 pos = CONE[vID]; pos = mul(lightWorld, pos); - Out.pos = mul(g_xCamera_VP, pos); + Out.pos = mul(g_xCamera.VP, pos); Out.col = lerp( float4(lightColor.rgb, 1), float4(0, 0, 0, 0), distance(pos.xyz, float3(lightWorld._14, lightWorld._24, lightWorld._34)) / (lightEnerdis.w) diff --git a/WickedEngine/shaders/visibility_resolveCS.hlsl b/WickedEngine/shaders/visibility_resolveCS.hlsl new file mode 100644 index 000000000..b56060468 --- /dev/null +++ b/WickedEngine/shaders/visibility_resolveCS.hlsl @@ -0,0 +1,97 @@ +#include "globals.hlsli" +#include "ShaderInterop_Renderer.h" +#include "brdf.hlsli" + +RWTEXTURE2D(output_velocity, float2, 0); + +RWTEXTURE2D(output_depth_mip0, float, 1); +RWTEXTURE2D(output_depth_mip1, float, 2); +RWTEXTURE2D(output_depth_mip2, float, 3); +RWTEXTURE2D(output_depth_mip3, float, 4); +RWTEXTURE2D(output_depth_mip4, float, 5); + +RWTEXTURE2D(output_lineardepth_mip0, float, 6); +RWTEXTURE2D(output_lineardepth_mip1, float, 7); +RWTEXTURE2D(output_lineardepth_mip2, float, 8); +RWTEXTURE2D(output_lineardepth_mip3, float, 9); +RWTEXTURE2D(output_lineardepth_mip4, float, 10); + +#ifdef VISIBILITY_MSAA +TEXTURE2DMS(texture_primitiveID, uint2, TEXSLOT_ONDEMAND0); +TEXTURE2DMS(texture_depthbuffer, float, TEXSLOT_ONDEMAND1); +RWTEXTURE2D(output_primitiveID, uint2, 11); +#else +TEXTURE2D(texture_primitiveID, uint2, TEXSLOT_ONDEMAND0); +TEXTURE2D(texture_depthbuffer, float, TEXSLOT_ONDEMAND1); +#endif // VISIBILITY_MSAA + +[numthreads(16, 16, 1)] +void main(uint3 DTid : SV_DispatchThreadID, uint groupIndex : SV_GroupIndex, uint3 Gid : SV_GroupID, uint3 GTid : SV_GroupThreadID) +{ + uint2 pixel = DTid.xy; + + const float2 uv = ((float2)pixel + 0.5) * g_xFrame.InternalResolution_rcp; + const float depth = texture_depthbuffer[pixel]; + const float3 P = reconstructPosition(uv, depth); + + float3 pre = P; + + if (depth > 0) + { + uint2 primitiveID = texture_primitiveID[pixel]; + +#ifdef VISIBILITY_MSAA + output_primitiveID[pixel] = primitiveID; +#endif // VISIBILITY_MSAA + + PrimitiveID prim; + prim.unpack(primitiveID); + + Surface surface; + if (surface.load(prim, P)) + { + pre = surface.pre; + } + + } + + float4 pos2DPrev = mul(g_xCamera.PrevVP, float4(pre, 1)); + pos2DPrev.xy /= pos2DPrev.w; + float2 pos2D = uv * 2 - 1; + pos2D.y *= -1; + float2 velocity = ((pos2DPrev.xy - g_xCamera.TemporalAAJitterPrev) - (pos2D.xy - g_xCamera.TemporalAAJitter)) * float2(0.5, -0.5); + + output_velocity[pixel] = velocity; + + + + // Downsample depths: + output_depth_mip0[pixel] = depth; + float lineardepth = getLinearDepth(depth) * g_xCamera.ZFarP_rcp; + output_lineardepth_mip0[pixel] = lineardepth; + + if (GTid.x % 2 == 0 && GTid.y % 2 == 0) + { + output_depth_mip1[pixel / 2] = depth; + output_lineardepth_mip1[pixel / 2] = lineardepth; + } + + if (GTid.x % 4 == 0 && GTid.y % 4 == 0) + { + output_depth_mip2[pixel / 4] = depth; + output_lineardepth_mip2[pixel / 4] = lineardepth; + } + + if (GTid.x % 8 == 0 && GTid.y % 8 == 0) + { + output_depth_mip3[pixel / 8] = depth; + output_lineardepth_mip3[pixel / 8] = lineardepth; + } + + if (GTid.x % 16 == 0 && GTid.y % 16 == 0) + { + output_depth_mip4[pixel / 16] = depth; + output_lineardepth_mip4[pixel / 16] = lineardepth; + } + +} diff --git a/WickedEngine/shaders/visibility_resolveCS_MSAA.hlsl b/WickedEngine/shaders/visibility_resolveCS_MSAA.hlsl new file mode 100644 index 000000000..bcff67e88 --- /dev/null +++ b/WickedEngine/shaders/visibility_resolveCS_MSAA.hlsl @@ -0,0 +1,2 @@ +#define VISIBILITY_MSAA +#include "visibility_resolveCS.hlsl" diff --git a/WickedEngine/shaders/volumetricCloud_renderCS.hlsl b/WickedEngine/shaders/volumetricCloud_renderCS.hlsl index 374247d07..1bff47ffd 100644 --- a/WickedEngine/shaders/volumetricCloud_renderCS.hlsl +++ b/WickedEngine/shaders/volumetricCloud_renderCS.hlsl @@ -44,7 +44,7 @@ float GetHeightFractionForPoint(AtmosphereParameters atmosphere, float3 pos) float planetRadius = atmosphere.bottomRadius * SKY_UNIT_TO_M; float3 planetCenterWorld = atmosphere.planetCenter * SKY_UNIT_TO_M; - return saturate((distance(pos, planetCenterWorld) - (planetRadius + g_xFrame_VolumetricClouds.CloudStartHeight)) / g_xFrame_VolumetricClouds.CloudThickness); + return saturate((distance(pos, planetCenterWorld) - (planetRadius + g_xFrame.VolumetricClouds.CloudStartHeight)) / g_xFrame.VolumetricClouds.CloudThickness); } float SampleGradient(float4 gradient, float heightFraction) @@ -60,21 +60,21 @@ float GetDensityHeightGradient(float heightFraction, float3 weatherData) float mediumType = 1.0f - abs(cloudType - 0.5f) * 2.0f; float largeType = saturate(cloudType - 0.5f) * 2.0f; - float4 cloudGradient = (g_xFrame_VolumetricClouds.CloudGradientSmall * smallType) + (g_xFrame_VolumetricClouds.CloudGradientMedium * mediumType) + (g_xFrame_VolumetricClouds.CloudGradientLarge * largeType); + float4 cloudGradient = (g_xFrame.VolumetricClouds.CloudGradientSmall * smallType) + (g_xFrame.VolumetricClouds.CloudGradientMedium * mediumType) + (g_xFrame.VolumetricClouds.CloudGradientLarge * largeType); return SampleGradient(cloudGradient, heightFraction); } float3 SampleWeather(float3 pos, float heightFraction, float2 coverageWindOffset) { - float4 weatherData = texture_weatherMap.SampleLevel(sampler_linear_wrap, (pos.xz + coverageWindOffset) * g_xFrame_VolumetricClouds.WeatherScale * 0.0004, 0); + float4 weatherData = texture_weatherMap.SampleLevel(sampler_linear_wrap, (pos.xz + coverageWindOffset) * g_xFrame.VolumetricClouds.WeatherScale * 0.0004, 0); // Anvil clouds - weatherData.r = pow(abs(weatherData.r), RemapClamped(heightFraction * g_xFrame_VolumetricClouds.AnvilOverhangHeight, 0.7, 0.8, 1.0, lerp(1.0, 0.5, g_xFrame_VolumetricClouds.AnvilAmount))); + weatherData.r = pow(abs(weatherData.r), RemapClamped(heightFraction * g_xFrame.VolumetricClouds.AnvilOverhangHeight, 0.7, 0.8, 1.0, lerp(1.0, 0.5, g_xFrame.VolumetricClouds.AnvilAmount))); //weatherData.r *= lerp(1, RemapClamped(pow(heightFraction * xPPDebugParams.y, 0.5), 0.4, 0.95, 1.0, 0.2), xPPDebugParams.x); // Apply effects for coverage - weatherData.r = RemapClamped(weatherData.r * g_xFrame_VolumetricClouds.CoverageAmount, 0.0, 1.0, saturate(g_xFrame_VolumetricClouds.CoverageMinimum - 1.0), 1.0); - weatherData.g = RemapClamped(weatherData.g * g_xFrame_VolumetricClouds.TypeAmount, 0.0, 1.0, g_xFrame_VolumetricClouds.TypeOverall, 1.0); + weatherData.r = RemapClamped(weatherData.r * g_xFrame.VolumetricClouds.CoverageAmount, 0.0, 1.0, saturate(g_xFrame.VolumetricClouds.CoverageMinimum - 1.0), 1.0); + weatherData.g = RemapClamped(weatherData.g * g_xFrame.VolumetricClouds.TypeAmount, 0.0, 1.0, g_xFrame.VolumetricClouds.TypeOverall, 1.0); return weatherData.rgb; } @@ -82,7 +82,7 @@ float3 SampleWeather(float3 pos, float heightFraction, float2 coverageWindOffset float WeatherDensity(float3 weatherData) { const float wetness = saturate(weatherData.b); - return lerp(1.0, 1.0 - g_xFrame_VolumetricClouds.WeatherDensityAmount, wetness); + return lerp(1.0, 1.0 - g_xFrame.VolumetricClouds.WeatherDensityAmount, wetness); } float SampleCloudDensity(float3 p, float heightFraction, float3 weatherData, float3 windOffset, float3 windDirection, float lod, bool sampleDetail) @@ -90,10 +90,10 @@ float SampleCloudDensity(float3 p, float heightFraction, float3 weatherData, flo #ifdef CLOUD_MODE_SIMPLE_FBM float3 pos = p + windOffset; - pos += heightFraction * windDirection * g_xFrame_VolumetricClouds.SkewAlongWindDirection; + pos += heightFraction * windDirection * g_xFrame.VolumetricClouds.SkewAlongWindDirection; // Since the clouds have a massive size, we have to adjust scale accordingly - float noiseScale = max(g_xFrame_VolumetricClouds.TotalNoiseScale * 0.0004, 0.00001); + float noiseScale = max(g_xFrame.VolumetricClouds.TotalNoiseScale * 0.0004, 0.00001); float4 lowFrequencyNoises = texture_shapeNoise.SampleLevel(sampler_linear_wrap, pos * noiseScale, lod); @@ -104,7 +104,7 @@ float SampleCloudDensity(float3 p, float heightFraction, float3 weatherData, flo lowFrequencyFBM = saturate(lowFrequencyFBM); - float cloudSample = Remap(lowFrequencyNoises.r * pow(1.2 - heightFraction, 0.1), lowFrequencyFBM * g_xFrame_VolumetricClouds.ShapeNoiseMinMax.x, g_xFrame_VolumetricClouds.ShapeNoiseMinMax.y, 0.0, 1.0); + float cloudSample = Remap(lowFrequencyNoises.r * pow(1.2 - heightFraction, 0.1), lowFrequencyFBM * g_xFrame.VolumetricClouds.ShapeNoiseMinMax.x, g_xFrame.VolumetricClouds.ShapeNoiseMinMax.y, 0.0, 1.0); cloudSample *= GetDensityHeightGradient(heightFraction, weatherData); float cloudCoverage = weatherData.r; @@ -114,25 +114,25 @@ float SampleCloudDensity(float3 p, float heightFraction, float3 weatherData, flo #else float3 pos = p + windOffset; - pos += heightFraction * windDirection * g_xFrame_VolumetricClouds.SkewAlongWindDirection; + pos += heightFraction * windDirection * g_xFrame.VolumetricClouds.SkewAlongWindDirection; - float noiseScale = max(g_xFrame_VolumetricClouds.TotalNoiseScale * 0.0004, 0.00001); + float noiseScale = max(g_xFrame.VolumetricClouds.TotalNoiseScale * 0.0004, 0.00001); float4 lowFrequencyNoises = texture_shapeNoise.SampleLevel(sampler_linear_wrap, pos * noiseScale, lod); - float3 heightGradient = float3(SampleGradient(g_xFrame_VolumetricClouds.CloudGradientSmall, heightFraction), - SampleGradient(g_xFrame_VolumetricClouds.CloudGradientMedium, heightFraction), - SampleGradient(g_xFrame_VolumetricClouds.CloudGradientLarge, heightFraction)); + float3 heightGradient = float3(SampleGradient(g_xFrame.VolumetricClouds.CloudGradientSmall, heightFraction), + SampleGradient(g_xFrame.VolumetricClouds.CloudGradientMedium, heightFraction), + SampleGradient(g_xFrame.VolumetricClouds.CloudGradientLarge, heightFraction)); // Depending on the type, clouds with higher altitudes may recieve smaller noises - lowFrequencyNoises.gba *= heightGradient * g_xFrame_VolumetricClouds.ShapeNoiseHeightGradientAmount; + lowFrequencyNoises.gba *= heightGradient * g_xFrame.VolumetricClouds.ShapeNoiseHeightGradientAmount; float densityHeightGradient = GetDensityHeightGradient(heightFraction, weatherData); - float cloudSample = (lowFrequencyNoises.r + lowFrequencyNoises.g + lowFrequencyNoises.b + lowFrequencyNoises.a) * g_xFrame_VolumetricClouds.ShapeNoiseMultiplier * densityHeightGradient; - cloudSample = pow(abs(cloudSample), min(1.0, g_xFrame_VolumetricClouds.ShapeNoisePower * heightFraction)); + float cloudSample = (lowFrequencyNoises.r + lowFrequencyNoises.g + lowFrequencyNoises.b + lowFrequencyNoises.a) * g_xFrame.VolumetricClouds.ShapeNoiseMultiplier * densityHeightGradient; + cloudSample = pow(abs(cloudSample), min(1.0, g_xFrame.VolumetricClouds.ShapeNoisePower * heightFraction)); - cloudSample = smoothstep(g_xFrame_VolumetricClouds.ShapeNoiseMinMax.x, g_xFrame_VolumetricClouds.ShapeNoiseMinMax.y, cloudSample); + cloudSample = smoothstep(g_xFrame.VolumetricClouds.ShapeNoiseMinMax.x, g_xFrame.VolumetricClouds.ShapeNoiseMinMax.y, cloudSample); // Remap function for noise against coverage, see GPU Pro 7 float cloudCoverage = weatherData.r; @@ -144,10 +144,10 @@ float SampleCloudDensity(float3 p, float heightFraction, float3 weatherData, flo if (cloudSample > 0.0 && sampleDetail) { // Apply our curl noise to erode with tiny details. - float3 curlNoise = DecodeCurlNoise(texture_curlNoise.SampleLevel(sampler_linear_wrap, p.xz * g_xFrame_VolumetricClouds.CurlScale * noiseScale, 0).rgb); - pos += float3(curlNoise.r, curlNoise.b, curlNoise.g) * heightFraction * g_xFrame_VolumetricClouds.CurlNoiseModifier; + float3 curlNoise = DecodeCurlNoise(texture_curlNoise.SampleLevel(sampler_linear_wrap, p.xz * g_xFrame.VolumetricClouds.CurlScale * noiseScale, 0).rgb); + pos += float3(curlNoise.r, curlNoise.b, curlNoise.g) * heightFraction * g_xFrame.VolumetricClouds.CurlNoiseModifier; - float3 highFrequencyNoises = texture_detailNoise.SampleLevel(sampler_linear_wrap, pos * g_xFrame_VolumetricClouds.DetailScale * noiseScale, lod).rgb; + float3 highFrequencyNoises = texture_detailNoise.SampleLevel(sampler_linear_wrap, pos * g_xFrame.VolumetricClouds.DetailScale * noiseScale, lod).rgb; // Create an FBM out of the high-frequency Worley Noises float highFrequencyFBM = (highFrequencyNoises.r * 0.625) + @@ -157,10 +157,10 @@ float SampleCloudDensity(float3 p, float heightFraction, float3 weatherData, flo highFrequencyFBM = saturate(highFrequencyFBM); // Dilate detail noise based on height - float highFrequenceNoiseModifier = lerp(1.0 - highFrequencyFBM, highFrequencyFBM, saturate(heightFraction * g_xFrame_VolumetricClouds.DetailNoiseHeightFraction)); + float highFrequenceNoiseModifier = lerp(1.0 - highFrequencyFBM, highFrequencyFBM, saturate(heightFraction * g_xFrame.VolumetricClouds.DetailNoiseHeightFraction)); // Erode with base of clouds - cloudSample = Remap(cloudSample, highFrequenceNoiseModifier * g_xFrame_VolumetricClouds.DetailNoiseModifier, 1.0, 0.0, 1.0); + cloudSample = Remap(cloudSample, highFrequenceNoiseModifier * g_xFrame.VolumetricClouds.DetailNoiseModifier, 1.0, 0.0, 1.0); } return max(cloudSample, 0.0); @@ -212,7 +212,7 @@ void VolumetricShadow(inout ParticipatingMedia participatingMedia, in Atmosphere extinctionAccumulation[ms] = 0.0f; } - const float sampleCount = g_xFrame_VolumetricClouds.ShadowSampleCount; + const float sampleCount = g_xFrame.VolumetricClouds.ShadowSampleCount; const float sampleSegmentT = 0.5f; float lodOffset = 0.5; @@ -228,7 +228,7 @@ void VolumetricShadow(inout ParticipatingMedia participatingMedia, in Atmosphere float delta = t1 - t0; // 5 samples: 0.04, 0.12, 0.2, 0.28, 0.36 float t = t0 + delta * sampleSegmentT; // 5 samples: 0.02, 0.1, 0.26, 0.5, 0.82 - float shadowSampleT = g_xFrame_VolumetricClouds.ShadowStepLength * t; + float shadowSampleT = g_xFrame.VolumetricClouds.ShadowStepLength * t; float3 samplePoint = worldPosition + sunDirection * shadowSampleT; // Step futher towards the light float heightFraction = GetHeightFractionForPoint(atmosphere, samplePoint); @@ -245,8 +245,8 @@ void VolumetricShadow(inout ParticipatingMedia participatingMedia, in Atmosphere float shadowCloudDensity = SampleCloudDensity(samplePoint, heightFraction, weatherData, windOffset, windDirection, lod + lodOffset, true); - float3 shadowExtinction = g_xFrame_VolumetricClouds.ExtinctionCoefficient * shadowCloudDensity; - ParticipatingMedia shadowParticipatingMedia = SampleParticipatingMedia(0.0f, shadowExtinction, g_xFrame_VolumetricClouds.MultiScatteringScattering, g_xFrame_VolumetricClouds.MultiScatteringExtinction, 0.0f); + float3 shadowExtinction = g_xFrame.VolumetricClouds.ExtinctionCoefficient * shadowCloudDensity; + ParticipatingMedia shadowParticipatingMedia = SampleParticipatingMedia(0.0f, shadowExtinction, g_xFrame.VolumetricClouds.MultiScatteringScattering, g_xFrame.VolumetricClouds.MultiScatteringExtinction, 0.0f); [unroll] for (ms = 0; ms < MS_COUNT; ms++) @@ -260,7 +260,7 @@ void VolumetricShadow(inout ParticipatingMedia participatingMedia, in Atmosphere [unroll] for (ms = 0; ms < MS_COUNT; ms++) { - participatingMedia.transmittanceToLight[ms] *= exp(-extinctionAccumulation[ms] * g_xFrame_VolumetricClouds.ShadowStepLength); + participatingMedia.transmittanceToLight[ms] *= exp(-extinctionAccumulation[ms] * g_xFrame.VolumetricClouds.ShadowStepLength); } } @@ -269,7 +269,7 @@ void VolumetricGroundContribution(inout float3 environmentLuminance, in Atmosphe float planetRadius = atmosphere.bottomRadius * SKY_UNIT_TO_M; float3 planetCenterWorld = atmosphere.planetCenter * SKY_UNIT_TO_M; - float cloudBottomRadius = planetRadius + g_xFrame_VolumetricClouds.CloudStartHeight; + float cloudBottomRadius = planetRadius + g_xFrame.VolumetricClouds.CloudStartHeight; float cloudSampleAltitudde = length(worldPosition - planetCenterWorld); // Distance from planet center to tracing sample float cloudSampleHeightToBottom = cloudSampleAltitudde - cloudBottomRadius; // Distance from altitude to bottom of clouds @@ -279,7 +279,7 @@ void VolumetricGroundContribution(inout float3 environmentLuminance, in Atmosphe const float contributionStepLength = min(4000.0, cloudSampleHeightToBottom); const float3 groundScatterDirection = float3(0.0, -1.0, 0.0); - const float sampleCount = g_xFrame_VolumetricClouds.GroundContributionSampleCount; + const float sampleCount = g_xFrame.VolumetricClouds.GroundContributionSampleCount; const float sampleSegmentT = 0.5f; // Ground Contribution tracing loop, same idea as volumetric shadow @@ -313,7 +313,7 @@ void VolumetricGroundContribution(inout float3 environmentLuminance, in Atmosphe float contributionCloudDensity = SampleCloudDensity(samplePoint, heightFraction, weatherData, windOffset, windDirection, lod + lodOffset, true); - float3 contributionExtinction = g_xFrame_VolumetricClouds.ExtinctionCoefficient * contributionCloudDensity; + float3 contributionExtinction = g_xFrame.VolumetricClouds.ExtinctionCoefficient * contributionCloudDensity; opticalDepth += contributionExtinction * contributionStepLength * delta; @@ -366,12 +366,12 @@ ParticipatingMediaPhase SampleParticipatingMediaPhase(float basePhase, float bas float3 SampleAmbientLight(float heightFraction) { // Early experiment by adding directionality to ambient, based on: http://patapom.com/topics/Revision2013/Revision%202013%20-%20Real-time%20Volumetric%20Rendering%20Course%20Notes.pdf - //float ambientTerm = -cloudDensity * (1.0 - saturate(g_xFrame_VolumetricClouds.CloudAmbientGroundMultiplier + heightFraction)); + //float ambientTerm = -cloudDensity * (1.0 - saturate(g_xFrame.VolumetricClouds.CloudAmbientGroundMultiplier + heightFraction)); //float isotropicScatteringTopContribution = max(0.0, exp(ambientTerm) - ambientTerm * ExponentialIntegral(ambientTerm)); - float isotropicScatteringTopContribution = saturate(g_xFrame_VolumetricClouds.CloudAmbientGroundMultiplier + heightFraction); + float isotropicScatteringTopContribution = saturate(g_xFrame.VolumetricClouds.CloudAmbientGroundMultiplier + heightFraction); - if (g_xFrame_Options & OPTION_BIT_REALISTIC_SKY) + if (g_xFrame.Options & OPTION_BIT_REALISTIC_SKY) { float3 skyLuminance = texture_skyluminancelut.SampleLevel(sampler_point_clamp, float2(0.5, 0.5), 0).rgb; return isotropicScatteringTopContribution * skyLuminance; @@ -388,18 +388,18 @@ void VolumetricCloudLighting(AtmosphereParameters atmosphere, float3 startPositi inout float3 luminance, inout float3 transmittanceToView, inout float depthWeightedSum, inout float depthWeightsSum) { // Setup base parameters - //float3 albedo = g_xFrame_VolumetricClouds.Albedo * cloudDensity; - float3 albedo = pow(saturate(g_xFrame_VolumetricClouds.Albedo * cloudDensity * g_xFrame_VolumetricClouds.BeerPowder), g_xFrame_VolumetricClouds.BeerPowderPower); // Artistic approach - float3 extinction = g_xFrame_VolumetricClouds.ExtinctionCoefficient * cloudDensity; + //float3 albedo = g_xFrame.VolumetricClouds.Albedo * cloudDensity; + float3 albedo = pow(saturate(g_xFrame.VolumetricClouds.Albedo * cloudDensity * g_xFrame.VolumetricClouds.BeerPowder), g_xFrame.VolumetricClouds.BeerPowderPower); // Artistic approach + float3 extinction = g_xFrame.VolumetricClouds.ExtinctionCoefficient * cloudDensity; float3 atmosphereTransmittanceToLight = 1.0; - if (g_xFrame_Options & OPTION_BIT_REALISTIC_SKY) + if (g_xFrame.Options & OPTION_BIT_REALISTIC_SKY) { atmosphereTransmittanceToLight = GetAtmosphericLightTransmittance(atmosphere, worldPosition, sunDirection, texture_transmittancelut); // Has to be in meters } // Sample participating media with multiple scattering - ParticipatingMedia participatingMedia = SampleParticipatingMedia(albedo, extinction, g_xFrame_VolumetricClouds.MultiScatteringScattering, g_xFrame_VolumetricClouds.MultiScatteringExtinction, atmosphereTransmittanceToLight); + ParticipatingMedia participatingMedia = SampleParticipatingMedia(albedo, extinction, g_xFrame.VolumetricClouds.MultiScatteringScattering, g_xFrame.VolumetricClouds.MultiScatteringExtinction, atmosphereTransmittanceToLight); // Sample environment lighting @@ -423,8 +423,8 @@ void VolumetricCloudLighting(AtmosphereParameters atmosphere, float3 startPositi // Sample dual lob phase with multiple scattering - float phaseFunction = DualLobPhase(g_xFrame_VolumetricClouds.PhaseG, g_xFrame_VolumetricClouds.PhaseG2, g_xFrame_VolumetricClouds.PhaseBlend, -cosTheta); - ParticipatingMediaPhase participatingMediaPhase = SampleParticipatingMediaPhase(phaseFunction, g_xFrame_VolumetricClouds.MultiScatteringEccentricity); + float phaseFunction = DualLobPhase(g_xFrame.VolumetricClouds.PhaseG, g_xFrame.VolumetricClouds.PhaseG2, g_xFrame.VolumetricClouds.PhaseBlend, -cosTheta); + ParticipatingMediaPhase participatingMediaPhase = SampleParticipatingMediaPhase(phaseFunction, g_xFrame.VolumetricClouds.MultiScatteringEccentricity); // Update depth sampling @@ -466,14 +466,14 @@ void RenderClouds(float3 rayOrigin, float3 rayDirection, float t, float steps, f inout float3 luminance, inout float3 transmittanceToView, inout float depthWeightedSum, inout float depthWeightsSum) { // Wind animation offsets - float3 windDirection = float3(cos(g_xFrame_VolumetricClouds.WindAngle), -g_xFrame_VolumetricClouds.WindUpAmount, sin(g_xFrame_VolumetricClouds.WindAngle)); - float3 windOffset = g_xFrame_VolumetricClouds.WindSpeed * g_xFrame_VolumetricClouds.AnimationMultiplier * windDirection * g_xFrame_Time; + float3 windDirection = float3(cos(g_xFrame.VolumetricClouds.WindAngle), -g_xFrame.VolumetricClouds.WindUpAmount, sin(g_xFrame.VolumetricClouds.WindAngle)); + float3 windOffset = g_xFrame.VolumetricClouds.WindSpeed * g_xFrame.VolumetricClouds.AnimationMultiplier * windDirection * g_xFrame.Time; - float2 coverageWindDirection = float2(cos(g_xFrame_VolumetricClouds.CoverageWindAngle), sin(g_xFrame_VolumetricClouds.CoverageWindAngle)); - float2 coverageWindOffset = g_xFrame_VolumetricClouds.CoverageWindSpeed * g_xFrame_VolumetricClouds.AnimationMultiplier * coverageWindDirection * g_xFrame_Time; + float2 coverageWindDirection = float2(cos(g_xFrame.VolumetricClouds.CoverageWindAngle), sin(g_xFrame.VolumetricClouds.CoverageWindAngle)); + float2 coverageWindOffset = g_xFrame.VolumetricClouds.CoverageWindSpeed * g_xFrame.VolumetricClouds.AnimationMultiplier * coverageWindDirection * g_xFrame.Time; - AtmosphereParameters atmosphere = g_xFrame_Atmosphere; + AtmosphereParameters atmosphere = g_xFrame.Atmosphere; float3 sunIlluminance = GetSunColor() * GetSunEnergy(); float3 sunDirection = GetSunDirection(); @@ -483,7 +483,7 @@ void RenderClouds(float3 rayOrigin, float3 rayDirection, float t, float steps, f // Init float zeroDensitySampleCount = 0.0; - float stepLength = g_xFrame_VolumetricClouds.BigStepMarch; + float stepLength = g_xFrame.VolumetricClouds.BigStepMarch; float3 sampleWorldPosition = rayOrigin + rayDirection * t; @@ -502,13 +502,13 @@ void RenderClouds(float3 rayOrigin, float3 rayDirection, float t, float steps, f // If value is low, continue marching until we quit or hit something. sampleWorldPosition += rayDirection * stepSize * stepLength; zeroDensitySampleCount += 1.0; - stepLength = zeroDensitySampleCount > 10.0 ? g_xFrame_VolumetricClouds.BigStepMarch : 1.0; // If zero count has reached a high number, switch to big steps + stepLength = zeroDensitySampleCount > 10.0 ? g_xFrame.VolumetricClouds.BigStepMarch : 1.0; // If zero count has reached a high number, switch to big steps continue; } - float rayDepth = distance(g_xCamera_CamPos, sampleWorldPosition); - float lod = step(g_xFrame_VolumetricClouds.LODDistance, rayDepth) + g_xFrame_VolumetricClouds.LODMin; + float rayDepth = distance(g_xCamera.CamPos, sampleWorldPosition); + float lod = step(g_xFrame.VolumetricClouds.LODDistance, rayDepth) + g_xFrame.VolumetricClouds.LODMin; float cloudDensity = saturate(SampleCloudDensity(sampleWorldPosition, heightFraction, weatherData, windOffset, windDirection, lod, true)); if (cloudDensity > 0.0) @@ -529,7 +529,7 @@ void RenderClouds(float3 rayOrigin, float3 rayDirection, float t, float steps, f stepSize, heightFraction, cloudDensity, weatherData, windOffset, windDirection, coverageWindOffset, lod, luminance, transmittanceToView, depthWeightedSum, depthWeightsSum); - if (all(transmittanceToView < g_xFrame_VolumetricClouds.TransmittanceThreshold)) + if (all(transmittanceToView < g_xFrame.VolumetricClouds.TransmittanceThreshold)) { break; } @@ -539,7 +539,7 @@ void RenderClouds(float3 rayOrigin, float3 rayDirection, float t, float steps, f zeroDensitySampleCount += 1.0; } - stepLength = zeroDensitySampleCount > 10.0 ? g_xFrame_VolumetricClouds.BigStepMarch : 1.0; + stepLength = zeroDensitySampleCount > 10.0 ? g_xFrame.VolumetricClouds.BigStepMarch : 1.0; sampleWorldPosition += rayDirection * stepSize * stepLength; } @@ -548,9 +548,9 @@ void RenderClouds(float3 rayOrigin, float3 rayDirection, float t, float steps, f float CalculateAtmosphereBlend(float tDepth) { // Progressively increase alpha as clouds reaches the desired distance. - float fogDistance = saturate(tDepth * g_xFrame_VolumetricClouds.HorizonBlendAmount * 0.00001); + float fogDistance = saturate(tDepth * g_xFrame.VolumetricClouds.HorizonBlendAmount * 0.00001); - float fade = pow(fogDistance, g_xFrame_VolumetricClouds.HorizonBlendPower); + float fade = pow(fogDistance, g_xFrame.VolumetricClouds.HorizonBlendPower); fade = smoothstep(0.0, 1.0, fade); const float maxHorizonFade = 0.0; @@ -572,7 +572,7 @@ int ComputeCheckerBoardIndex(int2 renderCoord, int subPixelIndex) [numthreads(POSTPROCESS_BLOCKSIZE, POSTPROCESS_BLOCKSIZE, 1)] void main(uint3 DTid : SV_DispatchThreadID) { - int subPixelIndex = g_xFrame_FrameCount % 4; + int subPixelIndex = g_xFrame.FrameCount % 4; int checkerBoardIndex = ComputeCheckerBoardIndex(DTid.xy, subPixelIndex); uint2 halfResCoord = DTid.xy * 2 + g_HalfResIndexToCoordinateOffset[checkerBoardIndex]; @@ -582,10 +582,10 @@ void main(uint3 DTid : SV_DispatchThreadID) float y = (1 - uv.y) * 2 - 1; float2 screenPosition = float2(x, y); - float4 unprojected = mul(g_xCamera_InvVP, float4(screenPosition, 0, 1)); + float4 unprojected = mul(g_xCamera.InvVP, float4(screenPosition, 0, 1)); unprojected.xyz /= unprojected.w; - float3 rayOrigin = g_xCamera_CamPos; + float3 rayOrigin = g_xCamera.CamPos; float3 rayDirection = normalize(unprojected.xyz - rayOrigin); @@ -596,13 +596,13 @@ void main(uint3 DTid : SV_DispatchThreadID) float steps; float stepSize; { - AtmosphereParameters parameters = g_xFrame_Atmosphere; + AtmosphereParameters parameters = g_xFrame.Atmosphere; float planetRadius = parameters.bottomRadius * SKY_UNIT_TO_M; float3 planetCenterWorld = parameters.planetCenter * SKY_UNIT_TO_M; - const float cloudBottomRadius = planetRadius + g_xFrame_VolumetricClouds.CloudStartHeight; - const float cloudTopRadius = planetRadius + g_xFrame_VolumetricClouds.CloudStartHeight + g_xFrame_VolumetricClouds.CloudThickness; + const float cloudBottomRadius = planetRadius + g_xFrame.VolumetricClouds.CloudStartHeight; + const float cloudTopRadius = planetRadius + g_xFrame.VolumetricClouds.CloudStartHeight + g_xFrame.VolumetricClouds.CloudThickness; float2 tTopSolutions = RaySphereIntersect(rayOrigin, rayDirection, planetCenterWorld, cloudTopRadius); if (tTopSolutions.x > 0.0 || tTopSolutions.y > 0.0) @@ -639,7 +639,7 @@ void main(uint3 DTid : SV_DispatchThreadID) return; } - if (tMax <= tMin || tMin > g_xFrame_VolumetricClouds.RenderDistance) + if (tMax <= tMin || tMin > g_xFrame.VolumetricClouds.RenderDistance) { texture_render[DTid.xy] = float4(0.0, 0.0, 0.0, 0.0); // Inverted alpha texture_cloudDepth[DTid.xy] = FLT_MAX; @@ -653,18 +653,18 @@ void main(uint3 DTid : SV_DispatchThreadID) tToDepthBuffer = length(depthWorldPosition - rayOrigin); tMax = depth == 0.0 ? tMax : min(tMax, tToDepthBuffer); // Exclude skybox - const float marchingDistance = min(g_xFrame_VolumetricClouds.MaxMarchingDistance, tMax - tMin); + const float marchingDistance = min(g_xFrame.VolumetricClouds.MaxMarchingDistance, tMax - tMin); tMax = tMin + marchingDistance; - steps = g_xFrame_VolumetricClouds.MaxStepCount * saturate((tMax - tMin) * (1.0 / g_xFrame_VolumetricClouds.InverseDistanceStepCount)); + steps = g_xFrame.VolumetricClouds.MaxStepCount * saturate((tMax - tMin) * (1.0 / g_xFrame.VolumetricClouds.InverseDistanceStepCount)); stepSize = (tMax - tMin) / steps; //float offset = dither(DTid.xy + GetTemporalAASampleRotation()); float offset = blue_noise(DTid.xy).x; - //float offset = InterleavedGradientNoise(DTid.xy, g_xFrame_FrameCount % 16); + //float offset = InterleavedGradientNoise(DTid.xy, g_xFrame.FrameCount % 16); //t = tMin + 0.5 * stepSize; - t = tMin + offset * stepSize * g_xFrame_VolumetricClouds.BigStepMarch; // offset avg = 0.5 + t = tMin + offset * stepSize * g_xFrame.VolumetricClouds.BigStepMarch; // offset avg = 0.5 } @@ -681,7 +681,7 @@ void main(uint3 DTid : SV_DispatchThreadID) //float3 absoluteWorldPosition = rayOrigin + rayDirection * tDepth; // Could be used for other effects later that require worldPosition float approxTransmittance = dot(transmittanceToView.rgb, 1.0 / 3.0); - float grayScaleTransmittance = approxTransmittance < g_xFrame_VolumetricClouds.TransmittanceThreshold ? 0.0 : approxTransmittance; + float grayScaleTransmittance = approxTransmittance < g_xFrame.VolumetricClouds.TransmittanceThreshold ? 0.0 : approxTransmittance; float4 color = float4(luminance, grayScaleTransmittance); diff --git a/WickedEngine/shaders/volumetricCloud_reprojectCS.hlsl b/WickedEngine/shaders/volumetricCloud_reprojectCS.hlsl index 7c49f38d0..ccb5d7e98 100644 --- a/WickedEngine/shaders/volumetricCloud_reprojectCS.hlsl +++ b/WickedEngine/shaders/volumetricCloud_reprojectCS.hlsl @@ -35,13 +35,13 @@ void main(uint3 DTid : SV_DispatchThreadID) // Calculate screen dependant motion vector float4 prevPos = float4(uv * 2.0 - 1.0, 1.0, 1.0); - prevPos = mul(g_xCamera_InvP, prevPos); + prevPos = mul(g_xCamera.InvP, prevPos); prevPos = prevPos / prevPos.w; - prevPos.xyz = mul((float3x3)g_xCamera_InvV, prevPos.xyz); - prevPos.xyz = mul((float3x3)g_xCamera_PrevV, prevPos.xyz); + prevPos.xyz = mul((float3x3)g_xCamera.InvV, prevPos.xyz); + prevPos.xyz = mul((float3x3)g_xCamera.PrevV, prevPos.xyz); - float4 reproj = mul(g_xCamera_Proj, prevPos); + float4 reproj = mul(g_xCamera.Proj, prevPos); reproj /= reproj.w; float2 prevUV = reproj.xy * 0.5 + 0.5; @@ -53,14 +53,14 @@ void main(uint3 DTid : SV_DispatchThreadID) float2 screenPosition = float2(x, y); float currentCloudLinearDepth = cloud_depth_current.SampleLevel(sampler_point_clamp, uv, 0).x; - float currentCloudDepth = getInverseLinearDepth(currentCloudLinearDepth, g_xCamera_ZNearP, g_xCamera_ZFarP); + float currentCloudDepth = getInverseLinearDepth(currentCloudLinearDepth, g_xCamera.ZNearP, g_xCamera.ZFarP); float4 thisClip = float4(screenPosition, currentCloudDepth, 1.0); - float4 prevClip = mul(g_xCamera_InvVP, thisClip); - prevClip = mul(g_xCamera_PrevVP, prevClip); + float4 prevClip = mul(g_xCamera.InvVP, thisClip); + prevClip = mul(g_xCamera.PrevVP, prevClip); - //float4 prevClip = mul(g_xCamera_PrevVP, worldPosition); + //float4 prevClip = mul(g_xCamera.PrevVP, worldPosition); float2 prevScreen = prevClip.xy / prevClip.w; float2 screenVelocity = screenPosition - prevScreen; @@ -73,7 +73,7 @@ void main(uint3 DTid : SV_DispatchThreadID) bool validHistory = is_saturated(prevUV); - int subPixelIndex = g_xFrame_FrameCount % 4; + int subPixelIndex = g_xFrame.FrameCount % 4; int localIndex = (DTid.x & 1) + (DTid.y & 1) * 2; int currentIndex = ComputeCheckerBoardIndex(renderCoord, subPixelIndex); @@ -120,7 +120,7 @@ void main(uint3 DTid : SV_DispatchThreadID) float depth = texture_depth.SampleLevel(sampler_point_clamp, uv, 1).r; // Half res float3 depthWorldPosition = reconstructPosition(uv, depth); - float tToDepthBuffer = length(depthWorldPosition - g_xCamera_CamPos); + float tToDepthBuffer = length(depthWorldPosition - g_xCamera.CamPos); if (abs(tToDepthBuffer - previousDepthResult.y) > tToDepthBuffer * 0.1) { diff --git a/WickedEngine/shaders/volumetricCloud_temporalCS.hlsl b/WickedEngine/shaders/volumetricCloud_temporalCS.hlsl index 790473e11..1a1049ae0 100644 --- a/WickedEngine/shaders/volumetricCloud_temporalCS.hlsl +++ b/WickedEngine/shaders/volumetricCloud_temporalCS.hlsl @@ -84,7 +84,7 @@ inline void ResolverAABB(Texture2D currentColor, SamplerState currentSam float depth = texture_depth.SampleLevel(sampler_point_clamp, uv, 1).r; // Half res float3 depthWorldPosition = reconstructPosition(uv, depth); - float tToDepthBuffer = length(depthWorldPosition - g_xCamera_CamPos); + float tToDepthBuffer = length(depthWorldPosition - g_xCamera.CamPos); float validSampleCount = 1.0; @@ -141,13 +141,13 @@ void main(uint3 DTid : SV_DispatchThreadID) // Calculate screen dependant motion vector float4 prevPos = float4(uv * 2.0 - 1.0, 1.0, 1.0); - prevPos = mul(g_xCamera_InvP, prevPos); + prevPos = mul(g_xCamera.InvP, prevPos); prevPos = prevPos / prevPos.w; - prevPos.xyz = mul((float3x3)g_xCamera_InvV, prevPos.xyz); - prevPos.xyz = mul((float3x3)g_xCamera_PrevV, prevPos.xyz); + prevPos.xyz = mul((float3x3)g_xCamera.InvV, prevPos.xyz); + prevPos.xyz = mul((float3x3)g_xCamera.PrevV, prevPos.xyz); - float4 reproj = mul(g_xCamera_Proj, prevPos); + float4 reproj = mul(g_xCamera.Proj, prevPos); reproj /= reproj.w; float2 prevUV = reproj.xy * 0.5 + 0.5; @@ -161,14 +161,14 @@ void main(uint3 DTid : SV_DispatchThreadID) float2 screenPosition = float2(x, y); float currentCloudLinearDepth = cloud_reproject_depth[DTid.xy].x; - float currentCloudDepth = getInverseLinearDepth(currentCloudLinearDepth, g_xCamera_ZNearP, g_xCamera_ZFarP); + float currentCloudDepth = getInverseLinearDepth(currentCloudLinearDepth, g_xCamera.ZNearP, g_xCamera.ZFarP); float4 thisClip = float4(screenPosition, currentCloudDepth, 1.0); - float4 prevClip = mul(g_xCamera_InvVP, thisClip); - prevClip = mul(g_xCamera_PrevVP, prevClip); + float4 prevClip = mul(g_xCamera.InvVP, thisClip); + prevClip = mul(g_xCamera.PrevVP, prevClip); - //float4 prevClip = mul(g_xCamera_PrevVP, worldPosition); + //float4 prevClip = mul(g_xCamera.PrevVP, worldPosition); float2 prevScreen = prevClip.xy / prevClip.w; float2 screenVelocity = screenPosition - prevScreen; diff --git a/WickedEngine/shaders/volumetricLight_DirectionalPS.hlsl b/WickedEngine/shaders/volumetricLight_DirectionalPS.hlsl index bf02232e4..c39727bf3 100644 --- a/WickedEngine/shaders/volumetricLight_DirectionalPS.hlsl +++ b/WickedEngine/shaders/volumetricLight_DirectionalPS.hlsl @@ -4,7 +4,7 @@ float4 main(VertexToPixel input) : SV_TARGET { - ShaderEntity light = EntityArray[g_xFrame_LightArrayOffset + (uint)g_xColor.x]; + ShaderEntity light = EntityArray[g_xFrame.LightArrayOffset + (uint)g_xColor.x]; if (!light.IsCastingShadow()) { @@ -15,7 +15,7 @@ float4 main(VertexToPixel input) : SV_TARGET float2 ScreenCoord = input.pos2D.xy / input.pos2D.w * float2(0.5f, -0.5f) + 0.5f; float depth = max(input.pos.z, texture_depth.SampleLevel(sampler_point_clamp, ScreenCoord, 2)); float3 P = reconstructPosition(ScreenCoord, depth); - float3 V = g_xCamera_CamPos - P; + float3 V = g_xCamera.CamPos - P; float cameraDistance = length(V); V /= cameraDistance; @@ -25,7 +25,7 @@ float4 main(VertexToPixel input) : SV_TARGET const float3 L = light.GetDirection(); const float scattering = ComputeScattering(saturate(dot(L, -V))); - float3 rayEnd = g_xCamera_CamPos; + float3 rayEnd = g_xCamera.CamPos; const uint sampleCount = 16; const float stepSize = length(P - rayEnd) / sampleCount; @@ -39,7 +39,7 @@ float4 main(VertexToPixel input) : SV_TARGET { bool valid = false; - for (uint cascade = 0; cascade < g_xFrame_ShadowCascadeCount; ++cascade) + for (uint cascade = 0; cascade < g_xFrame.ShadowCascadeCount; ++cascade) { float3 ShPos = mul(MatrixArray[light.GetMatrixIndex() + cascade], float4(P, 1)).xyz; // ortho matrix, no divide by .w float3 ShTex = ShPos.xyz * float3(0.5f, -0.5f, 0.5f) + 0.5f; @@ -69,9 +69,9 @@ float4 main(VertexToPixel input) : SV_TARGET accumulation /= sampleCount; float3 atmosphereTransmittance = 1; - if (g_xFrame_Options & OPTION_BIT_REALISTIC_SKY) + if (g_xFrame.Options & OPTION_BIT_REALISTIC_SKY) { - atmosphereTransmittance = GetAtmosphericLightTransmittance(g_xFrame_Atmosphere, P, L, texture_transmittancelut); + atmosphereTransmittance = GetAtmosphericLightTransmittance(g_xFrame.Atmosphere, P, L, texture_transmittancelut); } return max(0, float4(accumulation * light.GetColor().rgb * light.GetEnergy() * atmosphereTransmittance, 1)); diff --git a/WickedEngine/shaders/volumetricLight_PointPS.hlsl b/WickedEngine/shaders/volumetricLight_PointPS.hlsl index 2f7a446c9..d016a5237 100644 --- a/WickedEngine/shaders/volumetricLight_PointPS.hlsl +++ b/WickedEngine/shaders/volumetricLight_PointPS.hlsl @@ -4,19 +4,19 @@ float4 main(VertexToPixel input) : SV_TARGET { - ShaderEntity light = EntityArray[g_xFrame_LightArrayOffset + (uint)g_xColor.x]; + ShaderEntity light = EntityArray[g_xFrame.LightArrayOffset + (uint)g_xColor.x]; float2 ScreenCoord = input.pos2D.xy / input.pos2D.w * float2(0.5f, -0.5f) + 0.5f; float depth = max(input.pos.z, texture_depth.SampleLevel(sampler_point_clamp, ScreenCoord, 2)); float3 P = reconstructPosition(ScreenCoord, depth); - float3 V = g_xCamera_CamPos - P; + float3 V = g_xCamera.CamPos - P; float cameraDistance = length(V); V /= cameraDistance; float marchedDistance = 0; float3 accumulation = 0; - float3 rayEnd = g_xCamera_CamPos; + float3 rayEnd = g_xCamera.CamPos; if (length(rayEnd - light.position) > light.GetRange()) { // if we are outside the light volume, then rayEnd will be the traced sphere frontface: diff --git a/WickedEngine/shaders/volumetricLight_SpotPS.hlsl b/WickedEngine/shaders/volumetricLight_SpotPS.hlsl index 3a81c5e86..28725e368 100644 --- a/WickedEngine/shaders/volumetricLight_SpotPS.hlsl +++ b/WickedEngine/shaders/volumetricLight_SpotPS.hlsl @@ -4,19 +4,19 @@ float4 main(VertexToPixel input) : SV_TARGET { - ShaderEntity light = EntityArray[g_xFrame_LightArrayOffset + (uint)g_xColor.x]; + ShaderEntity light = EntityArray[g_xFrame.LightArrayOffset + (uint)g_xColor.x]; float2 ScreenCoord = input.pos2D.xy / input.pos2D.w * float2(0.5f, -0.5f) + 0.5f; float depth = max(input.pos.z, texture_depth.SampleLevel(sampler_point_clamp, ScreenCoord, 2)); float3 P = reconstructPosition(ScreenCoord, depth); - float3 V = g_xCamera_CamPos - P; + float3 V = g_xCamera.CamPos - P; float cameraDistance = length(V); V /= cameraDistance; float marchedDistance = 0; float3 accumulation = 0; - float3 rayEnd = g_xCamera_CamPos; + float3 rayEnd = g_xCamera.CamPos; // todo: rayEnd should be clamped to the closest cone intersection point when camera is outside volume const uint sampleCount = 16; diff --git a/WickedEngine/shaders/voxelConeTracingHF.hlsli b/WickedEngine/shaders/voxelConeTracingHF.hlsli index a65f451ed..c79f85844 100644 --- a/WickedEngine/shaders/voxelConeTracingHF.hlsli +++ b/WickedEngine/shaders/voxelConeTracingHF.hlsli @@ -18,24 +18,24 @@ inline float4 ConeTrace(in Texture3D voxels, in float3 P, in float3 N, i // We need to offset the cone start position to avoid sampling its own voxel (self-occlusion): // Unfortunately, it will result in disconnection between nearby surfaces :( - float dist = g_xFrame_VoxelRadianceDataSize; // offset by cone dir so that first sample of all cones are not the same - float3 startPos = P + N * g_xFrame_VoxelRadianceDataSize * VOXEL_INITIAL_OFFSET * SQRT2; // sqrt2 is diagonal voxel half-extent + float dist = g_xFrame.VoxelRadianceDataSize; // offset by cone dir so that first sample of all cones are not the same + float3 startPos = P + N * g_xFrame.VoxelRadianceDataSize * VOXEL_INITIAL_OFFSET * SQRT2; // sqrt2 is diagonal voxel half-extent // We will break off the loop if the sampling distance is too far for performance reasons: - while (dist < g_xFrame_VoxelRadianceMaxDistance && alpha < 1) + while (dist < g_xFrame.VoxelRadianceMaxDistance && alpha < 1) { - float diameter = max(g_xFrame_VoxelRadianceDataSize, 2 * coneAperture * dist); - float mip = log2(diameter * g_xFrame_VoxelRadianceDataSize_rcp); + float diameter = max(g_xFrame.VoxelRadianceDataSize, 2 * coneAperture * dist); + float mip = log2(diameter * g_xFrame.VoxelRadianceDataSize_rcp); // Because we do the ray-marching in world space, we need to remap into 3d texture space before sampling: // todo: optimization could be doing ray-marching in texture space float3 tc = startPos + coneDirection * dist; - tc = (tc - g_xFrame_VoxelRadianceDataCenter) * g_xFrame_VoxelRadianceDataSize_rcp; - tc *= g_xFrame_VoxelRadianceDataRes_rcp; + tc = (tc - g_xFrame.VoxelRadianceDataCenter) * g_xFrame.VoxelRadianceDataSize_rcp; + tc *= g_xFrame.VoxelRadianceDataRes_rcp; tc = tc * float3(0.5f, -0.5f, 0.5f) + 0.5f; // break if the ray exits the voxel grid, or we sample from the last mip: - if (!is_saturated(tc) || mip >= (float)g_xFrame_VoxelRadianceDataMIPs) + if (!is_saturated(tc) || mip >= (float)g_xFrame.VoxelRadianceDataMIPs) break; float4 sam = voxels.SampleLevel(sampler_linear_clamp, tc, mip); @@ -46,7 +46,7 @@ inline float4 ConeTrace(in Texture3D voxels, in float3 P, in float3 N, i alpha += a * sam.a; // step along ray: - dist += diameter * g_xFrame_VoxelRadianceRayStepSize; + dist += diameter * g_xFrame.VoxelRadianceRayStepSize; } return float4(color, alpha); @@ -60,9 +60,9 @@ inline float4 ConeTraceDiffuse(in Texture3D voxels, in float3 P, in floa float4 amount = 0; float3x3 tangentSpace = GetTangentSpace(N); - for (uint cone = 0; cone < g_xFrame_VoxelRadianceNumCones; ++cone) // quality is between 1 and 16 cones + for (uint cone = 0; cone < g_xFrame.VoxelRadianceNumCones; ++cone) // quality is between 1 and 16 cones { - float2 hamm = hammersley2d(cone, g_xFrame_VoxelRadianceNumCones); + float2 hamm = hammersley2d(cone, g_xFrame.VoxelRadianceNumCones); float3 hemisphere = hemispherepoint_cos(hamm.x, hamm.y); float3 coneDirection = mul(hemisphere, tangentSpace); @@ -70,7 +70,7 @@ inline float4 ConeTraceDiffuse(in Texture3D voxels, in float3 P, in floa } // final radiance is average of all the cones radiances - amount *= g_xFrame_VoxelRadianceNumCones_rcp; + amount *= g_xFrame.VoxelRadianceNumCones_rcp; amount.rgb = max(0, amount.rgb); amount.a = saturate(amount.a); diff --git a/WickedEngine/shaders/voxelGS.hlsl b/WickedEngine/shaders/voxelGS.hlsl index 2d4c8ce02..34ba43ba1 100644 --- a/WickedEngine/shaders/voxelGS.hlsl +++ b/WickedEngine/shaders/voxelGS.hlsl @@ -21,11 +21,11 @@ void main( element.pos = input[0].pos; element.col = input[0].col; - element.pos.xyz = element.pos.xyz / g_xFrame_VoxelRadianceDataRes * 2 - 1; + element.pos.xyz = element.pos.xyz / g_xFrame.VoxelRadianceDataRes * 2 - 1; element.pos.y = -element.pos.y; - element.pos.xyz *= g_xFrame_VoxelRadianceDataRes; + element.pos.xyz *= g_xFrame.VoxelRadianceDataRes; element.pos.xyz += (CreateCube(i) - float3(0, 1, 0)) * 2; - element.pos.xyz *= g_xFrame_VoxelRadianceDataRes * g_xFrame_VoxelRadianceDataSize / g_xFrame_VoxelRadianceDataRes; + element.pos.xyz *= g_xFrame.VoxelRadianceDataRes * g_xFrame.VoxelRadianceDataSize / g_xFrame.VoxelRadianceDataRes; element.pos = mul(g_xTransform, float4(element.pos.xyz, 1)); element.col *= g_xColor; diff --git a/WickedEngine/shaders/voxelRadianceSecondaryBounceCS.hlsl b/WickedEngine/shaders/voxelRadianceSecondaryBounceCS.hlsl index 9fe34a5d3..0b8039aa8 100644 --- a/WickedEngine/shaders/voxelRadianceSecondaryBounceCS.hlsl +++ b/WickedEngine/shaders/voxelRadianceSecondaryBounceCS.hlsl @@ -18,12 +18,12 @@ void main( uint3 DTid : SV_DispatchThreadID ) { float3 N = unpack_unitvector(input_voxelscene[DTid.x].normalMask); - float3 P = ((float3)writecoord + 0.5f) * g_xFrame_VoxelRadianceDataRes_rcp; + float3 P = ((float3)writecoord + 0.5f) * g_xFrame.VoxelRadianceDataRes_rcp; P = P * 2 - 1; P.y *= -1; - P *= g_xFrame_VoxelRadianceDataSize; - P *= g_xFrame_VoxelRadianceDataRes; - P += g_xFrame_VoxelRadianceDataCenter; + P *= g_xFrame.VoxelRadianceDataSize; + P *= g_xFrame.VoxelRadianceDataRes; + P += g_xFrame.VoxelRadianceDataCenter; float4 radiance = ConeTraceDiffuse(input_emission, P, N); diff --git a/WickedEngine/shaders/voxelSceneCopyClearCS.hlsl b/WickedEngine/shaders/voxelSceneCopyClearCS.hlsl index 9b193bc6e..1555d5538 100644 --- a/WickedEngine/shaders/voxelSceneCopyClearCS.hlsl +++ b/WickedEngine/shaders/voxelSceneCopyClearCS.hlsl @@ -11,7 +11,7 @@ void main( uint3 DTid : SV_DispatchThreadID ) const float4 color = UnpackVoxelColor(voxel.colorMask); - const uint3 writecoord = unflatten3D(DTid.x, g_xFrame_VoxelRadianceDataRes); + const uint3 writecoord = unflatten3D(DTid.x, g_xFrame.VoxelRadianceDataRes); [branch] if (color.a > 0) @@ -19,7 +19,7 @@ void main( uint3 DTid : SV_DispatchThreadID ) #ifdef TEMPORAL_SMOOTHING // Blend voxels with the previous frame's data to avoid popping artifacts for dynamic objects: [branch] - if (g_xFrame_Options & OPTION_BIT_VOXELGI_RETARGETTED) + if (g_xFrame.Options & OPTION_BIT_VOXELGI_RETARGETTED) { // Do not perform the blend if an offset happened to the voxel grid's center. // The offset is not accounted for in the blend operation which can introduce severe light leaking. diff --git a/WickedEngine/shaders/voxelVS.hlsl b/WickedEngine/shaders/voxelVS.hlsl index d28f2183f..05f32c684 100644 --- a/WickedEngine/shaders/voxelVS.hlsl +++ b/WickedEngine/shaders/voxelVS.hlsl @@ -12,9 +12,9 @@ VSOut main( uint vertexID : SV_VERTEXID ) { VSOut o; - uint3 coord = unflatten3D(vertexID, g_xFrame_VoxelRadianceDataRes); + uint3 coord = unflatten3D(vertexID, g_xFrame.VoxelRadianceDataRes); o.pos = float4(coord, 1); - o.col = texture_voxelradiance[coord]; + o.col = texture_voxelgi[coord]; return o; -} \ No newline at end of file +} diff --git a/WickedEngine/wiEmittedParticle.cpp b/WickedEngine/wiEmittedParticle.cpp index 291e38547..e3ead606f 100644 --- a/WickedEngine/wiEmittedParticle.cpp +++ b/WickedEngine/wiEmittedParticle.cpp @@ -67,7 +67,6 @@ void wiEmittedParticle::CreateSelfBuffers() GPUBufferDesc bd; bd.Usage = USAGE_DEFAULT; bd.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - bd.CPUAccessFlags = 0; bd.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; SubresourceData data; @@ -126,13 +125,13 @@ void wiEmittedParticle::CreateSelfBuffers() data.pSysMem = &counters; bd.ByteWidth = sizeof(counters); bd.StructureByteStride = sizeof(counters); - bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + bd.MiscFlags = RESOURCE_MISC_BUFFER_RAW; wiRenderer::GetDevice()->CreateBuffer(&bd, &data, &counterBuffer); data.pSysMem = nullptr; // Indirect Execution buffer: bd.BindFlags = BIND_UNORDERED_ACCESS; - bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS | RESOURCE_MISC_INDIRECT_ARGS; + bd.MiscFlags = RESOURCE_MISC_BUFFER_RAW | RESOURCE_MISC_INDIRECT_ARGS; bd.ByteWidth = sizeof(wiGraphics::IndirectDispatchArgs) + sizeof(wiGraphics::IndirectDispatchArgs) + @@ -143,17 +142,14 @@ void wiEmittedParticle::CreateSelfBuffers() bd.Usage = USAGE_DEFAULT; bd.ByteWidth = sizeof(EmittedParticleCB); bd.BindFlags = BIND_CONSTANT_BUFFER; - bd.CPUAccessFlags = 0; - bd.MiscFlags = 0; wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, &constantBuffer); // Debug information CPU-readback buffer: { GPUBufferDesc debugBufDesc = counterBuffer.GetDesc(); - debugBufDesc.Usage = USAGE_STAGING; - debugBufDesc.CPUAccessFlags = CPU_ACCESS_READ; - debugBufDesc.BindFlags = 0; - debugBufDesc.MiscFlags = 0; + debugBufDesc.Usage = USAGE_READBACK; + debugBufDesc.BindFlags = BIND_NONE; + debugBufDesc.MiscFlags = RESOURCE_MISC_NONE; for (int i = 0; i < arraysize(statisticsReadbackBuffer); ++i) { wiRenderer::GetDevice()->CreateBuffer(&debugBufDesc, nullptr, &statisticsReadbackBuffer[i]); @@ -207,16 +203,7 @@ void wiEmittedParticle::UpdateCPU(const TransformComponent& transform, float dt) if (statisticsReadBackIndex > arraysize(statisticsReadbackBuffer)) { const uint32_t oldest_stat_index = (statisticsReadBackIndex + 1) % arraysize(statisticsReadbackBuffer); - GraphicsDevice* device = wiRenderer::GetDevice(); - Mapping mapping; - mapping._flags = Mapping::FLAG_READ; - mapping.size = sizeof(statistics); - device->Map(&statisticsReadbackBuffer[oldest_stat_index], &mapping); - if (mapping.data != nullptr) - { - memcpy(&statistics, mapping.data, sizeof(statistics)); - device->Unmap(&statisticsReadbackBuffer[oldest_stat_index]); - } + memcpy(&statistics, statisticsReadbackBuffer[oldest_stat_index].mapped_data, sizeof(statistics)); } statisticsReadBackIndex++; } @@ -233,7 +220,7 @@ void wiEmittedParticle::Restart() SetPaused(false); } -void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const MaterialComponent& material, const MeshComponent* mesh, CommandList cmd) const +void wiEmittedParticle::UpdateGPU(uint32_t materialIndex, const TransformComponent& transform, const MeshComponent* mesh, CommandList cmd) const { if (!particleBuffer.IsValid()) { @@ -241,11 +228,10 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat } GraphicsDevice* device = wiRenderer::GetDevice(); + device->EventBegin("UpdateEmittedParticles", cmd); if (!IsPaused()) { - device->EventBegin("UpdateEmittedParticles", cmd); - EmittedParticleCB cb; cb.xEmitterWorld = transform.world; cb.xEmitCount = (uint32_t)emit; @@ -260,9 +246,6 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat cb.xParticleSize = size; cb.xParticleMotionBlurAmount = motionBlurAmount; cb.xParticleRotation = rotation * XM_PI * 60; - cb.xParticleColor = wiMath::CompressColor(XMFLOAT4(material.baseColor.x, material.baseColor.y, material.baseColor.z, 1)); - cb.xParticleEmissive = material.emissiveColor.w; - cb.xEmitterOpacity = material.GetOpacity(); cb.xParticleMass = mass; cb.xEmitterMaxParticleCount = MAX_PARTICLES; cb.xEmitterFixedTimestep = FIXED_TIMESTEP; @@ -276,6 +259,7 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat XMStoreFloat3(&cb.xParticleVelocity, XMVector3TransformNormal(XMLoadFloat3(&velocity), XMLoadFloat4x4(&transform.world))); cb.xParticleRandomColorFactor = random_color; cb.xEmitterLayerMask = layerMask; + cb.xEmitterMaterialIndex = materialIndex; cb.xEmitterOptions = 0; if (IsSPHEnabled()) @@ -304,8 +288,21 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat cb.xSPH_p0 = SPH_p0; cb.xSPH_e = SPH_e; + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&constantBuffer, RESOURCE_STATE_CONSTANT_BUFFER, RESOURCE_STATE_COPY_DST), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } device->UpdateBuffer(&constantBuffer, &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffer, CB_GETBINDSLOT(EmittedParticleCB), cmd); + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&constantBuffer, RESOURCE_STATE_COPY_DST, RESOURCE_STATE_CONSTANT_BUFFER), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->BindConstantBuffer(&constantBuffer, CB_GETBINDSLOT(EmittedParticleCB), cmd); const GPUResource* uavs[] = { &particleBuffer, @@ -316,7 +313,7 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat &indirectBuffers, &distanceBuffer, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); if (mesh != nullptr) { @@ -324,18 +321,18 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat &mesh->indexBuffer, (mesh->streamoutBuffer_POS.IsValid() ? &mesh->streamoutBuffer_POS : &mesh->vertexBuffer_POS), }; - device->BindResources(CS, resources, TEXSLOT_ONDEMAND0, arraysize(resources), cmd); + device->BindResources(resources, TEXSLOT_ONDEMAND0, arraysize(resources), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Buffer(&mesh->indexBuffer, BUFFER_STATE_INDEX_BUFFER, BUFFER_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&mesh->indexBuffer, RESOURCE_STATE_INDEX_BUFFER, RESOURCE_STATE_SHADER_RESOURCE), }; device->Barrier(barriers, arraysize(barriers), cmd); } } - GPUBarrier barrier_indirect_uav = GPUBarrier::Buffer(&indirectBuffers, BUFFER_STATE_INDIRECT_ARGUMENT, BUFFER_STATE_UNORDERED_ACCESS); - GPUBarrier barrier_uav_indirect = GPUBarrier::Buffer(&indirectBuffers, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_INDIRECT_ARGUMENT); + GPUBarrier barrier_indirect_uav = GPUBarrier::Buffer(&indirectBuffers, RESOURCE_STATE_INDIRECT_ARGUMENT, RESOURCE_STATE_UNORDERED_ACCESS); + GPUBarrier barrier_uav_indirect = GPUBarrier::Buffer(&indirectBuffers, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_INDIRECT_ARGUMENT); GPUBarrier barrier_memory = GPUBarrier::Memory(); device->Barrier(&barrier_indirect_uav, 1, cmd); @@ -367,17 +364,16 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat // 1.) Assign particles into partitioning grid: device->EventBegin("Partitioning", cmd); device->BindComputeShader(&sphpartitionCS, cmd); - device->UnbindUAVs(0, 8, cmd); const GPUResource* res_partition[] = { &aliveList[0], // CURRENT alivelist &counterBuffer, &particleBuffer, }; - device->BindResources(CS, res_partition, 0, arraysize(res_partition), cmd); + device->BindResources(res_partition, 0, arraysize(res_partition), cmd); const GPUResource* uav_partition[] = { &sphPartitionCellIndices, }; - device->BindUAVs(CS, uav_partition, 0, arraysize(uav_partition), cmd); + device->BindUAVs(uav_partition, 0, arraysize(uav_partition), cmd); device->DispatchIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, cmd); device->Barrier(&barrier_memory, 1, cmd); device->EventEnd(cmd); @@ -388,11 +384,10 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat // 3.) Reset grid cell offset buffer with invalid offsets (max uint): device->EventBegin("PartitionOffsetsReset", cmd); device->BindComputeShader(&sphpartitionoffsetsresetCS, cmd); - device->UnbindUAVs(0, 8, cmd); const GPUResource* uav_partitionoffsets[] = { &sphPartitionCellOffsets, }; - device->BindUAVs(CS, uav_partitionoffsets, 0, arraysize(uav_partitionoffsets), cmd); + device->BindUAVs(uav_partitionoffsets, 0, arraysize(uav_partitionoffsets), cmd); device->Dispatch((uint32_t)ceilf((float)SPH_PARTITION_BUCKET_COUNT / (float)THREADCOUNT_SIMULATION), 1, 1, cmd); device->Barrier(&barrier_memory, 1, cmd); device->EventEnd(cmd); @@ -405,7 +400,7 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat &counterBuffer, &sphPartitionCellIndices, }; - device->BindResources(CS, res_partitionoffsets, 0, arraysize(res_partitionoffsets), cmd); + device->BindResources(res_partitionoffsets, 0, arraysize(res_partitionoffsets), cmd); device->DispatchIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, cmd); device->Barrier(&barrier_memory, 1, cmd); device->EventEnd(cmd); @@ -415,7 +410,6 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat // 5.) Compute particle density field: device->EventBegin("Density Evaluation", cmd); device->BindComputeShader(&sphdensityCS, cmd); - device->UnbindUAVs(0, 8, cmd); const GPUResource* res_density[] = { &aliveList[0], // CURRENT alivelist &counterBuffer, @@ -423,11 +417,11 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat &sphPartitionCellIndices, &sphPartitionCellOffsets, }; - device->BindResources(CS, res_density, 0, arraysize(res_density), cmd); + device->BindResources(res_density, 0, arraysize(res_density), cmd); const GPUResource* uav_density[] = { &densityBuffer }; - device->BindUAVs(CS, uav_density, 0, arraysize(uav_density), cmd); + device->BindUAVs(uav_density, 0, arraysize(uav_density), cmd); device->DispatchIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, cmd); device->Barrier(&barrier_memory, 1, cmd); device->EventEnd(cmd); @@ -435,7 +429,6 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat // 6.) Compute particle pressure forces: device->EventBegin("Force Evaluation", cmd); device->BindComputeShader(&sphforceCS, cmd); - device->UnbindUAVs(0, 8, cmd); const GPUResource* res_force[] = { &aliveList[0], // CURRENT alivelist &counterBuffer, @@ -443,17 +436,15 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat &sphPartitionCellIndices, &sphPartitionCellOffsets, }; - device->BindResources(CS, res_force, 0, arraysize(res_force), cmd); + device->BindResources(res_force, 0, arraysize(res_force), cmd); const GPUResource* uav_force[] = { &particleBuffer, }; - device->BindUAVs(CS, uav_force, 0, arraysize(uav_force), cmd); + device->BindUAVs(uav_force, 0, arraysize(uav_force), cmd); device->DispatchIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DISPATCHSIMULATION, cmd); device->Barrier(&barrier_memory, 1, cmd); device->EventEnd(cmd); - device->UnbindResources(0, 3, cmd); - device->UnbindUAVs(0, 8, cmd); device->EventEnd(cmd); @@ -461,7 +452,7 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat } device->EventBegin("Simulate", cmd); - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); // update CURRENT alive list, write NEW alive list if (IsSorted()) @@ -490,11 +481,6 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat device->Barrier(&barrier_memory, 1, cmd); device->EventEnd(cmd); - - device->UnbindUAVs(0, arraysize(uavs), cmd); - - device->EventEnd(cmd); - } if (IsSorted()) @@ -511,26 +497,24 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat const GPUResource* res[] = { &counterBuffer, }; - device->BindResources(CS, res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); + device->BindResources(res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); const GPUResource* uavs[] = { &indirectBuffers, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Buffer(&counterBuffer, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), - GPUBarrier::Buffer(&indirectBuffers, BUFFER_STATE_INDIRECT_ARGUMENT, BUFFER_STATE_UNORDERED_ACCESS), + GPUBarrier::Buffer(&counterBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&indirectBuffers, RESOURCE_STATE_INDIRECT_ARGUMENT, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } device->Dispatch(1, 1, 1, cmd); - device->UnbindUAVs(0, arraysize(uavs), cmd); - device->UnbindResources(TEXSLOT_ONDEMAND0, arraysize(res), cmd); device->EventEnd(cmd); } @@ -538,7 +522,7 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Buffer(&counterBuffer, BUFFER_STATE_SHADER_RESOURCE, BUFFER_STATE_COPY_SRC), + GPUBarrier::Buffer(&counterBuffer, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_COPY_SRC), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -548,10 +532,10 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat { const GPUBarrier barriers[] = { - GPUBarrier::Buffer(&indirectBuffers, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_INDIRECT_ARGUMENT), - GPUBarrier::Buffer(&counterBuffer, BUFFER_STATE_COPY_SRC, BUFFER_STATE_SHADER_RESOURCE), - GPUBarrier::Buffer(&particleBuffer, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), - GPUBarrier::Buffer(&aliveList[1], BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&indirectBuffers, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_INDIRECT_ARGUMENT), + GPUBarrier::Buffer(&counterBuffer, RESOURCE_STATE_COPY_SRC, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&particleBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&aliveList[1], RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -559,14 +543,16 @@ void wiEmittedParticle::UpdateGPU(const TransformComponent& transform, const Mat if (mesh != nullptr) { GPUBarrier barriers[] = { - GPUBarrier::Buffer(&mesh->indexBuffer, BUFFER_STATE_SHADER_RESOURCE, BUFFER_STATE_INDEX_BUFFER), + GPUBarrier::Buffer(&mesh->indexBuffer, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_INDEX_BUFFER), }; device->Barrier(barriers, arraysize(barriers), cmd); } + + device->EventEnd(cmd); } -void wiEmittedParticle::Draw(const CameraComponent& camera, const MaterialComponent& material, CommandList cmd) const +void wiEmittedParticle::Draw(const MaterialComponent& material, CommandList cmd) const { GraphicsDevice* device = wiRenderer::GetDevice(); device->EventBegin("EmittedParticle", cmd); @@ -579,20 +565,11 @@ void wiEmittedParticle::Draw(const CameraComponent& camera, const MaterialCompon { const BLENDMODE blendMode = material.GetBlendMode(); device->BindPipelineState(&PSO[blendMode][shaderType], cmd); - if (material.textures[MaterialComponent::BASECOLORMAP].resource == nullptr) - { - device->BindResource(PS, wiTextureHelper::getWhite(), TEXSLOT_ONDEMAND0, cmd); - } - else - { - device->BindResource(PS, material.textures[MaterialComponent::BASECOLORMAP].GetGPUResource(), TEXSLOT_ONDEMAND0, cmd); - } + device->BindShadingRate(material.shadingRate, cmd); } - device->BindConstantBuffer(VS, &constantBuffer, CB_GETBINDSLOT(EmittedParticleCB), cmd); - device->BindConstantBuffer(PS, &constantBuffer, CB_GETBINDSLOT(EmittedParticleCB), cmd); - device->BindConstantBuffer(PS, &material.constantBuffer, CB_GETBINDSLOT(MaterialCB), cmd); + device->BindConstantBuffer(&constantBuffer, CB_GETBINDSLOT(EmittedParticleCB), cmd); if (ALLOW_MESH_SHADER && device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_MESH_SHADER)) { @@ -601,7 +578,7 @@ void wiEmittedParticle::Draw(const CameraComponent& camera, const MaterialCompon &particleBuffer, &aliveList[1], // NEW aliveList }; - device->BindResources(MS, res, TEXSLOT_ONDEMAND20, arraysize(res), cmd); + device->BindResources(res, TEXSLOT_ONDEMAND20, arraysize(res), cmd); device->DispatchMeshIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DRAWPARTICLES, cmd); } else @@ -610,7 +587,7 @@ void wiEmittedParticle::Draw(const CameraComponent& camera, const MaterialCompon &particleBuffer, &aliveList[1] // NEW aliveList }; - device->BindResources(VS, res, TEXSLOT_ONDEMAND21, arraysize(res), cmd); + device->BindResources(res, TEXSLOT_ONDEMAND21, arraysize(res), cmd); device->DrawInstancedIndirect(&indirectBuffers, ARGUMENTBUFFER_OFFSET_DRAWPARTICLES, cmd); } diff --git a/WickedEngine/wiEmittedParticle.h b/WickedEngine/wiEmittedParticle.h index c21ba5f26..e1bdde1d0 100644 --- a/WickedEngine/wiEmittedParticle.h +++ b/WickedEngine/wiEmittedParticle.h @@ -57,8 +57,8 @@ public: void Restart(); // Must have a transform and material component, but mesh is optional - void UpdateGPU(const TransformComponent& transform, const MaterialComponent& material, const MeshComponent* mesh, wiGraphics::CommandList cmd) const; - void Draw(const CameraComponent& camera, const MaterialComponent& material, wiGraphics::CommandList cmd) const; + void UpdateGPU(uint32_t materialIndex, const TransformComponent& transform, const MeshComponent* mesh, wiGraphics::CommandList cmd) const; + void Draw(const MaterialComponent& material, wiGraphics::CommandList cmd) const; ParticleCounters GetStatistics() { return statistics; } diff --git a/WickedEngine/wiEnums.h b/WickedEngine/wiEnums.h index e0cf1cebd..a6a3bfaf6 100644 --- a/WickedEngine/wiEnums.h +++ b/WickedEngine/wiEnums.h @@ -13,8 +13,7 @@ enum BLENDMODE enum GBUFFER { - GBUFFER_COLOR, - GBUFFER_NORMAL_ROUGHNESS, + GBUFFER_PRIMITIVEID, GBUFFER_VELOCITY, GBUFFER_COUNT }; @@ -40,33 +39,6 @@ enum RENDERPASS RENDERPASS_COUNT }; -enum OBJECT_VERTEXINPUT -{ - INPUT_SLOT_POSITION_NORMAL_WIND, - INPUT_SLOT_PREVPOS, - INPUT_SLOT_UV0, - INPUT_SLOT_UV1, - INPUT_SLOT_ATLAS, - INPUT_SLOT_COLOR, - INPUT_SLOT_TANGENT, - INPUT_SLOT_INSTANCEDATA, - INPUT_SLOT_COUNT, -}; -enum INSTANCETYPE -{ - INSTANCETYPE_MATRIX_USERDATA, - INSTANCETYPE_MATRIX_USERDATA_ATLAS, - INSTANCETYPE_MATRIX_USERDATA_MATRIXPREV, -}; -static const INSTANCETYPE instanceTypes[RENDERPASS_COUNT] = { - INSTANCETYPE_MATRIX_USERDATA_ATLAS, // RENDERPASS_MAIN, - INSTANCETYPE_MATRIX_USERDATA_MATRIXPREV, // RENDERPASS_PREPASS, - INSTANCETYPE_MATRIX_USERDATA_ATLAS, // RENDERPASS_ENVMAPCAPTURE, - INSTANCETYPE_MATRIX_USERDATA, // RENDERPASS_SHADOW, - INSTANCETYPE_MATRIX_USERDATA, // RENDERPASS_SHADOWCUBE, - INSTANCETYPE_MATRIX_USERDATA_ATLAS, // RENDERPASS_VOXELIZE, -}; - // There are two different kinds of stencil refs: // ENGINE : managed by the engine systems (STENCILREF enum values between 0-15) // USER : managed by the user (raw numbers between 0-15) @@ -91,24 +63,6 @@ enum STENCILREF enum CBTYPES { CBTYPE_FRAME, - CBTYPE_CAMERA, - CBTYPE_MISC, - CBTYPE_VOLUMELIGHT, - CBTYPE_CUBEMAPRENDER, - CBTYPE_TESSELLATION, - CBTYPE_RAYTRACE, - CBTYPE_MIPGEN, - CBTYPE_FILTERENVMAP, - CBTYPE_COPYTEXTURE, - CBTYPE_FORWARDENTITYMASK, - CBTYPE_POSTPROCESS, - CBTYPE_POSTPROCESS_FSR, - CBTYPE_POSTPROCESS_MSAO, - CBTYPE_POSTPROCESS_MSAO_UPSAMPLE, - CBTYPE_LENSFLARE, - CBTYPE_PAINTRADIUS, - CBTYPE_SHADINGRATECLASSIFICATION, - CBTYPE_VOLUMETRICCLOUDS, CBTYPE_COUNT }; @@ -220,7 +174,6 @@ enum SHADERTYPE PSTYPE_VOLUMETRICLIGHT_SPOT, PSTYPE_SKY_STATIC, PSTYPE_SKY_DYNAMIC, - PSTYPE_SKY_VELOCITY, PSTYPE_SUN, PSTYPE_ENVMAP, PSTYPE_ENVMAP_TERRAIN, @@ -301,7 +254,6 @@ enum SHADERTYPE CSTYPE_COPYTEXTURE2D_UNORM4_BORDEREXPAND, CSTYPE_COPYTEXTURE2D_FLOAT4_BORDEREXPAND, CSTYPE_SKINNING, - CSTYPE_SKINNING_LDS, CSTYPE_RAYTRACE, CSTYPE_PAINT_TEXTURE, CSTYPE_POSTPROCESS_BLUR_GAUSSIAN_FLOAT1, @@ -368,7 +320,6 @@ enum SHADERTYPE CSTYPE_POSTPROCESS_VOLUMETRICCLOUDS_TEMPORAL, CSTYPE_POSTPROCESS_FXAA, CSTYPE_POSTPROCESS_TEMPORALAA, - CSTYPE_POSTPROCESS_LINEARDEPTH, CSTYPE_POSTPROCESS_SHARPEN, CSTYPE_POSTPROCESS_TONEMAP, CSTYPE_POSTPROCESS_FSR_UPSCALING, @@ -389,6 +340,16 @@ enum SHADERTYPE CSTYPE_POSTPROCESS_RTAO, CSTYPE_POSTPROCESS_RTAO_DENOISE_TILECLASSIFICATION, CSTYPE_POSTPROCESS_RTAO_DENOISE_FILTER, + CSTYPE_SURFEL_COVERAGE, + CSTYPE_SURFEL_INDIRECTPREPARE, + CSTYPE_SURFEL_RAYTRACE, + CSTYPE_SURFEL_SHADE, + CSTYPE_SURFEL_UPDATE, + CSTYPE_SURFEL_GRIDRESET, + CSTYPE_SURFEL_GRIDOFFSETS, + CSTYPE_SURFEL_BINNING, + CSTYPE_VISIBILITY_RESOLVE, + CSTYPE_VISIBILITY_RESOLVE_MSAA, // raytracing pipelines: @@ -401,11 +362,6 @@ enum SHADERTYPE // input layouts enum ILTYPES { - ILTYPE_OBJECT_POS, - ILTYPE_OBJECT_POS_TEX, - ILTYPE_OBJECT_POS_PREVPOS, - ILTYPE_OBJECT_POS_PREVPOS_TEX, - ILTYPE_OBJECT_COMMON, ILTYPE_OBJECT_DEBUG, ILTYPE_RENDERLIGHTMAP, ILTYPE_VERTEXCOLOR, diff --git a/WickedEngine/wiFFTGenerator.cpp b/WickedEngine/wiFFTGenerator.cpp index 2494a9e73..c12e95d3b 100644 --- a/WickedEngine/wiFFTGenerator.cpp +++ b/WickedEngine/wiFFTGenerator.cpp @@ -37,10 +37,10 @@ namespace wiFFTGenerator // Buffers const GPUResource* srvs[1] = { &pSRV_Src }; - device->BindResources(CS, srvs, TEXSLOT_ONDEMAND0, 1, cmd); + device->BindResources(srvs, TEXSLOT_ONDEMAND0, 1, cmd); const GPUResource* uavs[1] = { &pUAV_Dst }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); // Shader if (istride > 1) @@ -61,8 +61,6 @@ namespace wiFFTGenerator device->Barrier(barriers, arraysize(barriers), cmd); // Unbind resource - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); - device->UnbindUAVs(0, 1, cmd); } void fft_512x512_c2c( @@ -78,32 +76,32 @@ namespace wiFFTGenerator uint32_t istride = 512 * 512 / 8; cs_cbs = &fft_plan.pRadix008A_CB[0]; - device->BindConstantBuffer(CS, cs_cbs, CB_GETBINDSLOT(FFTGeneratorCB), cmd); + device->BindConstantBuffer(cs_cbs, CB_GETBINDSLOT(FFTGeneratorCB), cmd); radix008A(fft_plan, fft_plan.pBuffer_Tmp, pSRV_Src, thread_count, istride, cmd); istride /= 8; cs_cbs = &fft_plan.pRadix008A_CB[1]; - device->BindConstantBuffer(CS, cs_cbs, CB_GETBINDSLOT(FFTGeneratorCB), cmd); + device->BindConstantBuffer(cs_cbs, CB_GETBINDSLOT(FFTGeneratorCB), cmd); radix008A(fft_plan, pUAV_Dst, fft_plan.pBuffer_Tmp, thread_count, istride, cmd); istride /= 8; cs_cbs = &fft_plan.pRadix008A_CB[2]; - device->BindConstantBuffer(CS, cs_cbs, CB_GETBINDSLOT(FFTGeneratorCB), cmd); + device->BindConstantBuffer(cs_cbs, CB_GETBINDSLOT(FFTGeneratorCB), cmd); radix008A(fft_plan, fft_plan.pBuffer_Tmp, pSRV_Dst, thread_count, istride, cmd); istride /= 8; cs_cbs = &fft_plan.pRadix008A_CB[3]; - device->BindConstantBuffer(CS, cs_cbs, CB_GETBINDSLOT(FFTGeneratorCB), cmd); + device->BindConstantBuffer(cs_cbs, CB_GETBINDSLOT(FFTGeneratorCB), cmd); radix008A(fft_plan, pUAV_Dst, fft_plan.pBuffer_Tmp, thread_count, istride, cmd); istride /= 8; cs_cbs = &fft_plan.pRadix008A_CB[4]; - device->BindConstantBuffer(CS, cs_cbs, CB_GETBINDSLOT(FFTGeneratorCB), cmd); + device->BindConstantBuffer(cs_cbs, CB_GETBINDSLOT(FFTGeneratorCB), cmd); radix008A(fft_plan, fft_plan.pBuffer_Tmp, pSRV_Dst, thread_count, istride, cmd); istride /= 8; cs_cbs = &fft_plan.pRadix008A_CB[5]; - device->BindConstantBuffer(CS, cs_cbs, CB_GETBINDSLOT(FFTGeneratorCB), cmd); + device->BindConstantBuffer(cs_cbs, CB_GETBINDSLOT(FFTGeneratorCB), cmd); radix008A(fft_plan, pUAV_Dst, fft_plan.pBuffer_Tmp, thread_count, istride, cmd); } @@ -112,10 +110,7 @@ namespace wiFFTGenerator // Create 6 cbuffers for 512x512 transform. GPUBufferDesc cb_desc; - cb_desc.Usage = USAGE_IMMUTABLE; cb_desc.BindFlags = BIND_CONSTANT_BUFFER; - cb_desc.CPUAccessFlags = 0; - cb_desc.MiscFlags = 0; cb_desc.ByteWidth = sizeof(FFTGeneratorCB); cb_desc.StructureByteStride = 0; @@ -196,7 +191,6 @@ namespace wiFFTGenerator buf_desc.ByteWidth = sizeof(float) * 2 * (512 * slices) * 512; buf_desc.Usage = USAGE_DEFAULT; buf_desc.BindFlags = BIND_UNORDERED_ACCESS | BIND_SHADER_RESOURCE; - buf_desc.CPUAccessFlags = 0; buf_desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; buf_desc.StructureByteStride = sizeof(float) * 2; diff --git a/WickedEngine/wiFont.cpp b/WickedEngine/wiFont.cpp index 1c126a42e..5bf7ce5cb 100644 --- a/WickedEngine/wiFont.cpp +++ b/WickedEngine/wiFont.cpp @@ -30,7 +30,6 @@ using namespace wiRectPacker; namespace wiFont_Internal { - GPUBuffer constantBuffer; BlendState blendState; RasterizerState rasterizerState; DepthStencilState depthStencilState; @@ -282,18 +281,6 @@ void Initialize() GraphicsDevice* device = wiRenderer::GetDevice(); - { - GPUBufferDesc bd; - bd.Usage = USAGE_DYNAMIC; - bd.ByteWidth = sizeof(FontCB); - bd.BindFlags = BIND_CONSTANT_BUFFER; - bd.CPUAccessFlags = CPU_ACCESS_WRITE; - - device->CreateBuffer(&bd, nullptr, &constantBuffer); - } - - - RasterizerState rs; rs.FillMode = FILL_SOLID; rs.CullMode = CULL_FRONT; @@ -597,22 +584,10 @@ void Draw_internal(const T* text, size_t text_length, const wiFontParams& params device->BindPipelineState(&PSO, cmd); - device->BindConstantBuffer(VS, &constantBuffer, CB_GETBINDSLOT(FontCB), cmd); - device->BindConstantBuffer(PS, &constantBuffer, CB_GETBINDSLOT(FontCB), cmd); - - FontCB cb; - cb.g_xFont_BufferOffset = mem.offset; - - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS)) - { - cb.g_xFont_TextureIndex = device->GetDescriptorIndex(&texture, SRV); - } - else - { - device->BindResource(PS, &texture, TEXSLOT_FONTATLAS, cmd); - } - - device->BindResource(VS, mem.buffer, 0, cmd); + PushConstantsFont push; + push.buffer_index = device->GetDescriptorIndex(&mem.buffer, SRV); + push.buffer_offset = mem.offset; + push.texture_index = device->GetDescriptorIndex(&texture, SRV); const wiCanvas& canvas = canvases[cmd]; // Asserts will check that a proper canvas was set for this cmd with wiImage::SetCanvas() @@ -625,24 +600,24 @@ void Draw_internal(const T* text, size_t text_length, const wiFontParams& params if (newProps.shadowColor.getA() > 0) { // font shadow render: - XMStoreFloat4x4(&cb.g_xFont_Transform, + XMStoreFloat4x4(&push.transform, XMMatrixTranslation((float)newProps.posX + 1, (float)newProps.posY + 1, 0) * Projection ); - cb.g_xFont_Color = newProps.shadowColor.toFloat4(); - device->UpdateBuffer(&constantBuffer, &cb, cmd); + push.color = newProps.shadowColor.rgba; + device->PushConstants(&push, sizeof(push), cmd); device->DrawInstanced(4, quadCount, 0, 0, cmd); } // font base render: - XMStoreFloat4x4(&cb.g_xFont_Transform, + XMStoreFloat4x4(&push.transform, XMMatrixTranslation((float)newProps.posX, (float)newProps.posY, 0) * Projection ); - cb.g_xFont_Color = newProps.color.toFloat4(); - device->UpdateBuffer(&constantBuffer, &cb, cmd); + push.color = newProps.color.rgba; + device->PushConstants(&push, sizeof(push), cmd); device->DrawInstanced(4, quadCount, 0, 0, cmd); device->EventEnd(cmd); diff --git a/WickedEngine/wiGPUBVH.cpp b/WickedEngine/wiGPUBVH.cpp index 49a4a9d0f..397cd4ace 100644 --- a/WickedEngine/wiGPUBVH.cpp +++ b/WickedEngine/wiGPUBVH.cpp @@ -26,224 +26,19 @@ enum CSTYPES_BVH CSTYPE_BVH_COUNT }; static Shader computeShaders[CSTYPE_BVH_COUNT]; -static GPUBuffer constantBuffer; - -static const int atlasWrapBorder = 1; - -void wiGPUBVH::UpdateGlobalMaterialResources(const Scene& scene) -{ - GraphicsDevice* device = wiRenderer::GetDevice(); - - using namespace wiRectPacker; - - for (size_t i = 0; i < scene.objects.GetCount(); ++i) - { - const ObjectComponent& object = scene.objects[i]; - - if (object.meshID != INVALID_ENTITY) - { - const MeshComponent& mesh = *scene.meshes.GetComponent(object.meshID); - - for (auto& subset : mesh.subsets) - { - const MaterialComponent& material = *scene.materials.GetComponent(subset.materialID); - - if (material.textures[MaterialComponent::BASECOLORMAP].resource != nullptr) - { - sceneTextures.insert(material.textures[MaterialComponent::BASECOLORMAP].resource); - } - if (material.textures[MaterialComponent::SURFACEMAP].resource != nullptr) - { - sceneTextures.insert(material.textures[MaterialComponent::SURFACEMAP].resource); - } - if (material.textures[MaterialComponent::EMISSIVEMAP].resource != nullptr) - { - sceneTextures.insert(material.textures[MaterialComponent::EMISSIVEMAP].resource); - } - if (material.textures[MaterialComponent::NORMALMAP].resource != nullptr) - { - sceneTextures.insert(material.textures[MaterialComponent::NORMALMAP].resource); - } - } - } - - } - - repackAtlas = false; - for (auto res : sceneTextures) - { - if (res == nullptr) - { - continue; - } - - if (storedTextures.find(res) == storedTextures.end()) - { - // we need to pack this texture into the atlas - rect_xywh newRect = rect_xywh(0, 0, res->texture.desc.Width + atlasWrapBorder * 2, res->texture.desc.Height + atlasWrapBorder * 2); - storedTextures[res] = newRect; - - repackAtlas = true; - } - - } - - if (repackAtlas) - { - std::vector out_rects(storedTextures.size()); - int i = 0; - for (auto& it : storedTextures) - { - out_rects[i] = &it.second; - i++; - } - - std::vector bins; - if (pack(out_rects.data(), (int)storedTextures.size(), 16384, bins)) - { - assert(bins.size() == 1 && "The regions won't fit into the texture!"); - - TextureDesc desc; - desc.Width = (uint32_t)bins[0].size.w; - desc.Height = (uint32_t)bins[0].size.h; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = FORMAT_R8G8B8A8_UNORM; - desc.SampleCount = 1; - desc.Usage = USAGE_DEFAULT; - desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - device->CreateTexture(&desc, nullptr, &globalMaterialAtlas); - device->SetName(&globalMaterialAtlas, "globalMaterialAtlas"); - } - else - { - wiBackLog::post("Tracing atlas packing failed!"); - } - } - - materialArray.clear(); - - // Pre-gather scene properties: - for (size_t i = 0; i < scene.objects.GetCount(); ++i) - { - const ObjectComponent& object = scene.objects[i]; - - if (object.meshID != INVALID_ENTITY) - { - const MeshComponent& mesh = *scene.meshes.GetComponent(object.meshID); - - for (auto& subset : mesh.subsets) - { - const MaterialComponent& material = *scene.materials.GetComponent(subset.materialID); - ShaderMaterial global_material; - material.WriteShaderMaterial(&global_material); - - // Add extended properties: - const TextureDesc& desc = globalMaterialAtlas.GetDesc(); - - if (material.textures[MaterialComponent::BASECOLORMAP].resource != nullptr) - { - rect_xywh rect = storedTextures[material.textures[MaterialComponent::BASECOLORMAP].resource]; - // eliminate border expansion: - rect.x += atlasWrapBorder; - rect.y += atlasWrapBorder; - rect.w -= atlasWrapBorder * 2; - rect.h -= atlasWrapBorder * 2; - global_material.baseColorAtlasMulAdd = XMFLOAT4((float)rect.w / (float)desc.Width, (float)rect.h / (float)desc.Height, - (float)rect.x / (float)desc.Width, (float)rect.y / (float)desc.Height); - } - - if (material.textures[MaterialComponent::SURFACEMAP].resource != nullptr) - { - rect_xywh rect = storedTextures[material.textures[MaterialComponent::SURFACEMAP].resource]; - // eliminate border expansion: - rect.x += atlasWrapBorder; - rect.y += atlasWrapBorder; - rect.w -= atlasWrapBorder * 2; - rect.h -= atlasWrapBorder * 2; - global_material.surfaceMapAtlasMulAdd = XMFLOAT4((float)rect.w / (float)desc.Width, (float)rect.h / (float)desc.Height, - (float)rect.x / (float)desc.Width, (float)rect.y / (float)desc.Height); - } - - if (material.textures[MaterialComponent::EMISSIVEMAP].resource != nullptr) - { - rect_xywh rect = storedTextures[material.textures[MaterialComponent::EMISSIVEMAP].resource]; - // eliminate border expansion: - rect.x += atlasWrapBorder; - rect.y += atlasWrapBorder; - rect.w -= atlasWrapBorder * 2; - rect.h -= atlasWrapBorder * 2; - global_material.emissiveMapAtlasMulAdd = XMFLOAT4((float)rect.w / (float)desc.Width, (float)rect.h / (float)desc.Height, - (float)rect.x / (float)desc.Width, (float)rect.y / (float)desc.Height); - } - - if (material.textures[MaterialComponent::NORMALMAP].resource != nullptr) - { - rect_xywh rect = storedTextures[material.textures[MaterialComponent::NORMALMAP].resource]; - // eliminate border expansion: - rect.x += atlasWrapBorder; - rect.y += atlasWrapBorder; - rect.w -= atlasWrapBorder * 2; - rect.h -= atlasWrapBorder * 2; - global_material.normalMapAtlasMulAdd = XMFLOAT4((float)rect.w / (float)desc.Width, (float)rect.h / (float)desc.Height, - (float)rect.x / (float)desc.Width, (float)rect.y / (float)desc.Height); - } - - materialArray.push_back(global_material); - } - } - } - - if (materialArray.empty()) - { - return; - } - - if (globalMaterialBuffer.GetDesc().ByteWidth != sizeof(ShaderMaterial) * materialArray.size()) - { - GPUBufferDesc desc; - - desc.BindFlags = BIND_SHADER_RESOURCE; - desc.StructureByteStride = sizeof(ShaderMaterial); - desc.ByteWidth = desc.StructureByteStride * (uint32_t)materialArray.size(); - desc.CPUAccessFlags = 0; - desc.Format = FORMAT_UNKNOWN; - desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; - desc.Usage = USAGE_DEFAULT; - - device->CreateBuffer(&desc, nullptr, &globalMaterialBuffer); - } - -} void wiGPUBVH::Update(const wiScene::Scene& scene) { GraphicsDevice* device = wiRenderer::GetDevice(); - if (!constantBuffer.IsValid()) - { - GPUBufferDesc bd; - bd.Usage = USAGE_DYNAMIC; - bd.CPUAccessFlags = CPU_ACCESS_WRITE; - bd.BindFlags = BIND_CONSTANT_BUFFER; - bd.ByteWidth = sizeof(BVHCB); - - device->CreateBuffer(&bd, nullptr, &constantBuffer); - device->SetName(&constantBuffer, "BVHGeneratorCB"); - } - if (!primitiveCounterBuffer.IsValid()) { GPUBufferDesc desc; desc.BindFlags = BIND_SHADER_RESOURCE; desc.StructureByteStride = sizeof(uint); desc.ByteWidth = desc.StructureByteStride; - desc.CPUAccessFlags = 0; desc.Format = FORMAT_UNKNOWN; - desc.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + desc.MiscFlags = RESOURCE_MISC_BUFFER_RAW; desc.Usage = USAGE_DEFAULT; device->CreateBuffer(&desc, nullptr, &primitiveCounterBuffer); device->SetName(&primitiveCounterBuffer, "primitiveCounterBuffer"); @@ -262,6 +57,15 @@ void wiGPUBVH::Update(const wiScene::Scene& scene) totalTriangles += (uint)mesh.indices.size() / 3; } } + for (size_t i = 0; i < scene.hairs.GetCount(); ++i) + { + const wiHairParticle& hair = scene.hairs[i]; + + if (hair.meshID != INVALID_ENTITY) + { + totalTriangles += hair.segmentCount * hair.strandCount * 2; + } + } if (totalTriangles > primitiveCapacity) { @@ -272,7 +76,6 @@ void wiGPUBVH::Update(const wiScene::Scene& scene) desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; desc.StructureByteStride = sizeof(BVHNode); desc.ByteWidth = desc.StructureByteStride * primitiveCapacity * 2; - desc.CPUAccessFlags = 0; desc.Format = FORMAT_UNKNOWN; desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; desc.Usage = USAGE_DEFAULT; @@ -282,7 +85,6 @@ void wiGPUBVH::Update(const wiScene::Scene& scene) desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; desc.StructureByteStride = sizeof(uint); desc.ByteWidth = desc.StructureByteStride * primitiveCapacity * 2; - desc.CPUAccessFlags = 0; desc.Format = FORMAT_UNKNOWN; desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; desc.Usage = USAGE_DEFAULT; @@ -292,7 +94,6 @@ void wiGPUBVH::Update(const wiScene::Scene& scene) desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; desc.StructureByteStride = sizeof(uint); desc.ByteWidth = desc.StructureByteStride * (((primitiveCapacity - 1) + 31) / 32); // bitfield for internal nodes - desc.CPUAccessFlags = 0; desc.Format = FORMAT_UNKNOWN; desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; desc.Usage = USAGE_DEFAULT; @@ -302,7 +103,6 @@ void wiGPUBVH::Update(const wiScene::Scene& scene) desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; desc.StructureByteStride = sizeof(uint); desc.ByteWidth = desc.StructureByteStride * primitiveCapacity; - desc.CPUAccessFlags = 0; desc.Format = FORMAT_UNKNOWN; desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; desc.Usage = USAGE_DEFAULT; @@ -312,7 +112,6 @@ void wiGPUBVH::Update(const wiScene::Scene& scene) desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; desc.StructureByteStride = sizeof(BVHPrimitive); desc.ByteWidth = desc.StructureByteStride * primitiveCapacity; - desc.CPUAccessFlags = 0; desc.Format = FORMAT_UNKNOWN; desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; desc.Usage = USAGE_DEFAULT; @@ -320,18 +119,7 @@ void wiGPUBVH::Update(const wiScene::Scene& scene) device->SetName(&primitiveBuffer, "primitiveBuffer"); desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - desc.StructureByteStride = sizeof(BVHPrimitiveData); desc.ByteWidth = desc.StructureByteStride * primitiveCapacity; - desc.CPUAccessFlags = 0; - desc.Format = FORMAT_UNKNOWN; - desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; - desc.Usage = USAGE_DEFAULT; - device->CreateBuffer(&desc, nullptr, &primitiveDataBuffer); - device->SetName(&primitiveDataBuffer, "primitiveDataBuffer"); - - desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - desc.ByteWidth = desc.StructureByteStride * primitiveCapacity; - desc.CPUAccessFlags = 0; desc.Format = FORMAT_UNKNOWN; desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; desc.Usage = USAGE_DEFAULT; @@ -339,40 +127,14 @@ void wiGPUBVH::Update(const wiScene::Scene& scene) device->CreateBuffer(&desc, nullptr, &primitiveMortonBuffer); device->SetName(&primitiveMortonBuffer, "primitiveMortonBuffer"); } - - UpdateGlobalMaterialResources(scene); } void wiGPUBVH::Build(const Scene& scene, CommandList cmd) const { GraphicsDevice* device = wiRenderer::GetDevice(); - // Pre-gather scene properties: - uint totalTriangles = 0; - for (size_t i = 0; i < scene.objects.GetCount(); ++i) - { - const ObjectComponent& object = scene.objects[i]; - - if (object.meshID != INVALID_ENTITY) - { - const MeshComponent& mesh = *scene.meshes.GetComponent(object.meshID); - - totalTriangles += (uint)mesh.indices.size() / 3; - } - } - auto range = wiProfiler::BeginRangeGPU("BVH Rebuild", cmd); - if (repackAtlas) - { - for (auto& it : storedTextures) - { - wiRenderer::CopyTexture2D(globalMaterialAtlas, -1, it.second.x + atlasWrapBorder, it.second.y + atlasWrapBorder, it.first->texture, 0, cmd, wiRenderer::BORDEREXPAND_WRAP); - } - } - device->UpdateBuffer(&globalMaterialBuffer, materialArray.data(), cmd, sizeof(ShaderMaterial) * (int)materialArray.size()); - uint32_t primitiveCount = 0; - uint32_t materialCount = 0; device->EventBegin("BVH - Primitive Builder", cmd); { @@ -380,10 +142,9 @@ void wiGPUBVH::Build(const Scene& scene, CommandList cmd) const const GPUResource* uavs[] = { &primitiveIDBuffer, &primitiveBuffer, - &primitiveDataBuffer, &primitiveMortonBuffer, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); for (size_t i = 0; i < scene.objects.GetCount(); ++i) { @@ -393,34 +154,51 @@ void wiGPUBVH::Build(const Scene& scene, CommandList cmd) const { const MeshComponent& mesh = *scene.meshes.GetComponent(object.meshID); - BVHCB cb; - cb.xBVHWorld = object.transform_index >= 0 ? scene.transforms[object.transform_index].world : IDENTITYMATRIX; - cb.xBVHInstanceColor = object.color; - cb.xBVHMaterialOffset = materialCount; - cb.xBVHMeshTriangleOffset = primitiveCount; - cb.xBVHMeshTriangleCount = (uint)mesh.indices.size() / 3; - cb.xBVHMeshVertexPOSStride = sizeof(MeshComponent::Vertex_POS); + for (size_t j = 0; j < mesh.subsets.size(); ++j) + { + auto& subset = mesh.subsets[j]; - device->UpdateBuffer(&constantBuffer, &cb, cmd); + BVHPushConstants push; + push.instanceIndex = (uint)i; + push.subsetIndex = (uint)j; + push.primitiveCount = subset.indexCount / 3; + push.primitiveOffset = primitiveCount; + device->PushConstants(&push, sizeof(push), cmd); - primitiveCount += cb.xBVHMeshTriangleCount; + primitiveCount += push.primitiveCount; - device->BindConstantBuffer(CS, &constantBuffer, CB_GETBINDSLOT(BVHCB), cmd); + device->Dispatch( + (push.primitiveCount + BVH_BUILDER_GROUPSIZE - 1) / BVH_BUILDER_GROUPSIZE, + 1, + 1, + cmd + ); + } - const GPUResource* res[] = { - &globalMaterialBuffer, - &mesh.indexBuffer, - mesh.streamoutBuffer_POS.IsValid() ? &mesh.streamoutBuffer_POS : &mesh.vertexBuffer_POS, - &mesh.vertexBuffer_UV0, - &mesh.vertexBuffer_UV1, - &mesh.vertexBuffer_COL, - &mesh.vertexBuffer_SUB, - }; - device->BindResources(CS, res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); + } + } - device->Dispatch((cb.xBVHMeshTriangleCount + BVH_BUILDER_GROUPSIZE - 1) / BVH_BUILDER_GROUPSIZE, 1, 1, cmd); + for (size_t i = 0; i < scene.hairs.GetCount(); ++i) + { + const wiHairParticle& hair = scene.hairs[i]; - materialCount += (uint32_t)mesh.subsets.size(); + if (hair.meshID != INVALID_ENTITY) + { + BVHPushConstants push; + push.instanceIndex = (uint)(scene.objects.GetCount() + i); + push.subsetIndex = 0; + push.primitiveCount = hair.segmentCount * hair.strandCount * 2; + push.primitiveOffset = primitiveCount; + device->PushConstants(&push, sizeof(push), cmd); + + primitiveCount += push.primitiveCount; + + device->Dispatch( + (push.primitiveCount + BVH_BUILDER_GROUPSIZE - 1) / BVH_BUILDER_GROUPSIZE, + 1, + 1, + cmd + ); } } @@ -428,9 +206,22 @@ void wiGPUBVH::Build(const Scene& scene, CommandList cmd) const GPUBarrier::Memory() }; device->Barrier(barriers, arraysize(barriers), cmd); - device->UnbindUAVs(0, arraysize(uavs), cmd); + } + + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&primitiveCounterBuffer, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_COPY_DST), + }; + device->Barrier(barriers, arraysize(barriers), cmd); } device->UpdateBuffer(&primitiveCounterBuffer, &primitiveCount, cmd); + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&primitiveCounterBuffer, RESOURCE_STATE_COPY_DST, RESOURCE_STATE_SHADER_RESOURCE), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + device->EventEnd(cmd); device->EventBegin("BVH - Sort Primitive Mortons", cmd); @@ -445,14 +236,14 @@ void wiGPUBVH::Build(const Scene& scene, CommandList cmd) const &bvhParentBuffer, &bvhFlagBuffer }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); const GPUResource* res[] = { &primitiveCounterBuffer, &primitiveIDBuffer, &primitiveMortonBuffer, }; - device->BindResources(CS, res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); + device->BindResources(res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); device->Dispatch((primitiveCount + BVH_BUILDER_GROUPSIZE - 1) / BVH_BUILDER_GROUPSIZE, 1, 1, cmd); @@ -460,7 +251,6 @@ void wiGPUBVH::Build(const Scene& scene, CommandList cmd) const GPUBarrier::Memory() }; device->Barrier(barriers, arraysize(barriers), cmd); - device->UnbindUAVs(0, arraysize(uavs), cmd); } device->EventEnd(cmd); @@ -476,7 +266,7 @@ void wiGPUBVH::Build(const Scene& scene, CommandList cmd) const &bvhNodeBuffer, &bvhFlagBuffer, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); const GPUResource* res[] = { &primitiveCounterBuffer, @@ -484,12 +274,11 @@ void wiGPUBVH::Build(const Scene& scene, CommandList cmd) const &primitiveBuffer, &bvhParentBuffer, }; - device->BindResources(CS, res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); + device->BindResources(res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); device->Dispatch((primitiveCount + BVH_BUILDER_GROUPSIZE - 1) / BVH_BUILDER_GROUPSIZE, 1, 1, cmd); device->Barrier(barriers, arraysize(barriers), cmd); - device->UnbindUAVs(0, arraysize(uavs), cmd); } device->EventEnd(cmd); @@ -505,7 +294,7 @@ void wiGPUBVH::Build(const Scene& scene, CommandList cmd) const readback_desc.Usage = USAGE_STAGING; readback_desc.CPUAccessFlags = CPU_ACCESS_READ; readback_desc.BindFlags = 0; - readback_desc.MiscFlags = 0; + readback_desc.Flags = 0; GPUBuffer readback_primitiveCounterBuffer; device->CreateBuffer(&readback_desc, nullptr, &readback_primitiveCounterBuffer); uint primitiveCount; @@ -521,7 +310,7 @@ void wiGPUBVH::Build(const Scene& scene, CommandList cmd) const readback_desc.Usage = USAGE_STAGING; readback_desc.CPUAccessFlags = CPU_ACCESS_READ; readback_desc.BindFlags = 0; - readback_desc.MiscFlags = 0; + readback_desc.Flags = 0; GPUBuffer readback_nodeBuffer; device->CreateBuffer(&readback_desc, nullptr, &readback_nodeBuffer); vector nodes(readback_desc.ByteWidth / sizeof(BVHNode)); @@ -562,7 +351,7 @@ void wiGPUBVH::Build(const Scene& scene, CommandList cmd) const readback_desc.Usage = USAGE_STAGING; readback_desc.CPUAccessFlags = CPU_ACCESS_READ; readback_desc.BindFlags = 0; - readback_desc.MiscFlags = 0; + readback_desc.Flags = 0; GPUBuffer readback_flagBuffer; device->CreateBuffer(&readback_desc, nullptr, &readback_flagBuffer); vector flags(readback_desc.ByteWidth / sizeof(uint)); @@ -581,27 +370,21 @@ void wiGPUBVH::Build(const Scene& scene, CommandList cmd) const #endif // BVH_VALIDATE } -void wiGPUBVH::Bind(SHADERSTAGE stage, CommandList cmd) const +void wiGPUBVH::Bind(CommandList cmd) const { GraphicsDevice* device = wiRenderer::GetDevice(); const GPUResource* res[] = { - &globalMaterialBuffer, - (globalMaterialAtlas.IsValid() ? &globalMaterialAtlas : wiTextureHelper::getWhite()), &primitiveCounterBuffer, &primitiveBuffer, - &primitiveDataBuffer, &bvhNodeBuffer, }; - device->BindResources(stage, res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); + device->BindResources(res, TEXSLOT_BVH_COUNTER, arraysize(res), cmd); } void wiGPUBVH::Clear() { primitiveCapacity = 0; - materialArray.clear(); - storedTextures.clear(); - sceneTextures.clear(); } namespace wiGPUBVH_Internal diff --git a/WickedEngine/wiGPUBVH.h b/WickedEngine/wiGPUBVH.h index 197fad025..50c102951 100644 --- a/WickedEngine/wiGPUBVH.h +++ b/WickedEngine/wiGPUBVH.h @@ -20,23 +20,13 @@ private: wiGraphics::GPUBuffer primitiveCounterBuffer; wiGraphics::GPUBuffer primitiveIDBuffer; wiGraphics::GPUBuffer primitiveBuffer; - wiGraphics::GPUBuffer primitiveDataBuffer; wiGraphics::GPUBuffer primitiveMortonBuffer; uint32_t primitiveCapacity = 0; - // Scene material resources: - wiGraphics::GPUBuffer globalMaterialBuffer; - wiGraphics::Texture globalMaterialAtlas; - std::vector materialArray; - std::unordered_map, wiRectPacker::rect_xywh> storedTextures; - std::unordered_set> sceneTextures; - bool repackAtlas = false; - void UpdateGlobalMaterialResources(const wiScene::Scene& scene); - public: void Update(const wiScene::Scene& scene); void Build(const wiScene::Scene& scene, wiGraphics::CommandList cmd) const; - void Bind(wiGraphics::SHADERSTAGE stage, wiGraphics::CommandList cmd) const; + void Bind(wiGraphics::CommandList cmd) const; void Clear(); diff --git a/WickedEngine/wiGPUSortLib.cpp b/WickedEngine/wiGPUSortLib.cpp index f5571b781..76e44e5c7 100644 --- a/WickedEngine/wiGPUSortLib.cpp +++ b/WickedEngine/wiGPUSortLib.cpp @@ -9,7 +9,6 @@ using namespace wiGraphics; namespace wiGPUSortLib { static GPUBuffer indirectBuffer; - static GPUBuffer sortCB; static Shader kickoffSortCS; static Shader sortCS; static Shader sortInnerCS; @@ -30,19 +29,9 @@ namespace wiGPUSortLib void Initialize() { GPUBufferDesc bd; - - bd.Usage = USAGE_DYNAMIC; - bd.CPUAccessFlags = CPU_ACCESS_WRITE; - bd.BindFlags = BIND_CONSTANT_BUFFER; - bd.MiscFlags = 0; - bd.ByteWidth = sizeof(SortConstants); - wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, &sortCB); - - bd.Usage = USAGE_DEFAULT; - bd.CPUAccessFlags = 0; bd.BindFlags = BIND_UNORDERED_ACCESS; - bd.MiscFlags = RESOURCE_MISC_INDIRECT_ARGS | RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + bd.MiscFlags = RESOURCE_MISC_INDIRECT_ARGS | RESOURCE_MISC_BUFFER_RAW; bd.ByteWidth = sizeof(IndirectDispatchArgs); wiRenderer::GetDevice()->CreateBuffer(&bd, nullptr, &indirectBuffer); @@ -66,10 +55,7 @@ namespace wiGPUSortLib SortConstants sc; sc.counterReadOffset = counterReadOffset; - device->UpdateBuffer(&sortCB, &sc, cmd); - device->BindConstantBuffer(CS, &sortCB, CB_GETBINDSLOT(SortConstants), cmd); - - device->UnbindUAVs(0, 8, cmd); + device->BindDynamicConstantBuffer(sc, CB_GETBINDSLOT(SortConstants), cmd); // initialize sorting arguments: { @@ -78,16 +64,16 @@ namespace wiGPUSortLib const GPUResource* res[] = { &counterBuffer_read, }; - device->BindResources(CS, res, 0, arraysize(res), cmd); + device->BindResources(res, 0, arraysize(res), cmd); const GPUResource* uavs[] = { &indirectBuffer, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Buffer(&indirectBuffer, BUFFER_STATE_INDIRECT_ARGUMENT, BUFFER_STATE_UNORDERED_ACCESS) + GPUBarrier::Buffer(&indirectBuffer, RESOURCE_STATE_INDIRECT_ARGUMENT, RESOURCE_STATE_UNORDERED_ACCESS) }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -97,25 +83,24 @@ namespace wiGPUSortLib { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Buffer(&indirectBuffer, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_INDIRECT_ARGUMENT) + GPUBarrier::Buffer(&indirectBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_INDIRECT_ARGUMENT) }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); } const GPUResource* uavs[] = { &indexBuffer_write, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); const GPUResource* resources[] = { &counterBuffer_read, &comparisonBuffer_read, }; - device->BindResources(CS, resources, 0, arraysize(resources), cmd); + device->BindResources(resources, 0, arraysize(resources), cmd); // initial sorting: bool bDone = true; @@ -183,8 +168,7 @@ namespace wiGPUSortLib } sc.counterReadOffset = counterReadOffset; - device->UpdateBuffer(&sortCB, &sc, cmd); - device->BindConstantBuffer(CS, &sortCB, CB_GETBINDSLOT(SortConstants), cmd); + device->BindDynamicConstantBuffer(sc, CB_GETBINDSLOT(SortConstants), cmd); device->Dispatch(numThreadGroups, 1, 1, cmd); @@ -205,8 +189,6 @@ namespace wiGPUSortLib presorted *= 2; } - device->UnbindUAVs(0, arraysize(uavs), cmd); - device->UnbindResources(0, arraysize(resources), cmd); device->EventEnd(cmd); diff --git a/WickedEngine/wiGraphics.h b/WickedEngine/wiGraphics.h index 8a4b3dca8..27f8fbe48 100644 --- a/WickedEngine/wiGraphics.h +++ b/WickedEngine/wiGraphics.h @@ -4,6 +4,7 @@ #include #include #include +#include namespace wiGraphics { @@ -46,7 +47,7 @@ namespace wiGraphics }; enum PRIMITIVETOPOLOGY { - UNDEFINED, + UNDEFINED_TOPOLOGY, TRIANGLELIST, TRIANGLESTRIP, POINTLIST, @@ -101,15 +102,6 @@ namespace wiGraphics BLEND_SRC1_ALPHA, BLEND_INV_SRC1_ALPHA, }; - enum COLOR_WRITE_ENABLE - { - COLOR_WRITE_DISABLE = 0, - COLOR_WRITE_ENABLE_RED = 1, - COLOR_WRITE_ENABLE_GREEN = 2, - COLOR_WRITE_ENABLE_BLUE = 4, - COLOR_WRITE_ENABLE_ALPHA = 8, - COLOR_WRITE_ENABLE_ALL = (((COLOR_WRITE_ENABLE_RED | COLOR_WRITE_ENABLE_GREEN) | COLOR_WRITE_ENABLE_BLUE) | COLOR_WRITE_ENABLE_ALPHA) - }; enum BLEND_OP { BLEND_OP_ADD, @@ -136,10 +128,9 @@ namespace wiGraphics }; enum USAGE { - USAGE_DEFAULT, - USAGE_IMMUTABLE, - USAGE_DYNAMIC, - USAGE_STAGING, + USAGE_DEFAULT, // CPU no access, GPU read/write + USAGE_UPLOAD, // CPU write, GPU read + USAGE_READBACK, // CPU read, GPU write }; enum TEXTURE_ADDRESS_MODE { @@ -285,39 +276,12 @@ namespace wiGraphics }; enum SUBRESOURCE_TYPE { - CBV, // constant buffer view SRV, // shader resource view UAV, // unordered access view RTV, // render target view DSV, // depth stencil view }; - enum IMAGE_LAYOUT - { - IMAGE_LAYOUT_UNDEFINED, // invalid state - IMAGE_LAYOUT_RENDERTARGET, // render target, write enabled - IMAGE_LAYOUT_DEPTHSTENCIL, // depth stencil, write enabled - IMAGE_LAYOUT_DEPTHSTENCIL_READONLY, // depth stencil, read only - IMAGE_LAYOUT_SHADER_RESOURCE, // shader resource, read only - IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE, // shader resource, read only, non-pixel shader - IMAGE_LAYOUT_UNORDERED_ACCESS, // shader resource, write enabled - IMAGE_LAYOUT_COPY_SRC, // copy from - IMAGE_LAYOUT_COPY_DST, // copy to - IMAGE_LAYOUT_SHADING_RATE_SOURCE, // shading rate control per tile - }; - enum BUFFER_STATE - { - BUFFER_STATE_UNDEFINED, // invalid state - BUFFER_STATE_VERTEX_BUFFER, // vertex buffer, read only - BUFFER_STATE_INDEX_BUFFER, // index buffer, read only - BUFFER_STATE_CONSTANT_BUFFER, // constant buffer, read only - BUFFER_STATE_INDIRECT_ARGUMENT, // argument buffer to DrawIndirect() or DispatchIndirect() - BUFFER_STATE_SHADER_RESOURCE, // shader resource, read only - BUFFER_STATE_SHADER_RESOURCE_COMPUTE, // shader resource, read only, non-pixel shader - BUFFER_STATE_UNORDERED_ACCESS, // shader resource, write enabled - BUFFER_STATE_COPY_SRC, // copy from - BUFFER_STATE_COPY_DST, // copy to - BUFFER_STATE_RAYTRACING_ACCELERATION_STRUCTURE, - }; + enum SHADING_RATE { SHADING_RATE_1X1, @@ -332,33 +296,74 @@ namespace wiGraphics }; // Flags //////////////////////////////////////////// + + // Enable enum flags: + // https://www.justsoftwaresolutions.co.uk/cplusplus/using-enum-classes-as-bitfields.html + template + struct enable_bitmask_operators { + static constexpr bool enable = true; + }; + template + typename std::enable_if::enable, E>::type operator|(E lhs, E rhs) + { + typedef typename std::underlying_type::type underlying; + return static_cast( + static_cast(lhs) | static_cast(rhs)); + } + template + typename std::enable_if::enable, E&>::type operator|=(E& lhs, E rhs) + { + typedef typename std::underlying_type::type underlying; + lhs = static_cast( + static_cast(lhs) | static_cast(rhs)); + return lhs; + } + + enum COLOR_WRITE_ENABLE + { + COLOR_WRITE_DISABLE = 0, + COLOR_WRITE_ENABLE_RED = 1 << 0, + COLOR_WRITE_ENABLE_GREEN = 1 << 1, + COLOR_WRITE_ENABLE_BLUE = 1 << 2, + COLOR_WRITE_ENABLE_ALPHA = 1 << 3, + COLOR_WRITE_ENABLE_ALL = ~0, + }; + template<> + struct enable_bitmask_operators { + static const bool enable = true; + }; + enum BIND_FLAG { + BIND_NONE = 0, BIND_VERTEX_BUFFER = 1 << 0, BIND_INDEX_BUFFER = 1 << 1, BIND_CONSTANT_BUFFER = 1 << 2, BIND_SHADER_RESOURCE = 1 << 3, - BIND_STREAM_OUTPUT = 1 << 4, - BIND_RENDER_TARGET = 1 << 5, - BIND_DEPTH_STENCIL = 1 << 6, - BIND_UNORDERED_ACCESS = 1 << 7, - BIND_SHADING_RATE = 1 << 8, + BIND_RENDER_TARGET = 1 << 4, + BIND_DEPTH_STENCIL = 1 << 5, + BIND_UNORDERED_ACCESS = 1 << 6, + BIND_SHADING_RATE = 1 << 7, }; - enum CPU_ACCESS - { - CPU_ACCESS_WRITE = 1 << 0, - CPU_ACCESS_READ = 1 << 1, + template<> + struct enable_bitmask_operators { + static const bool enable = true; }; + enum RESOURCE_MISC_FLAG { - RESOURCE_MISC_SHARED = 1 << 0, - RESOURCE_MISC_TEXTURECUBE = 1 << 1, - RESOURCE_MISC_INDIRECT_ARGS = 1 << 2, - RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS = 1 << 3, - RESOURCE_MISC_BUFFER_STRUCTURED = 1 << 4, - RESOURCE_MISC_TILED = 1 << 5, - RESOURCE_MISC_RAY_TRACING = 1 << 6, + RESOURCE_MISC_NONE = 0, + RESOURCE_MISC_TEXTURECUBE = 1 << 0, + RESOURCE_MISC_INDIRECT_ARGS = 1 << 1, + RESOURCE_MISC_BUFFER_RAW = 1 << 2, + RESOURCE_MISC_BUFFER_STRUCTURED = 1 << 3, + RESOURCE_MISC_RAY_TRACING = 1 << 4, }; + template<> + struct enable_bitmask_operators { + static const bool enable = true; + }; + enum GRAPHICSDEVICE_CAPABILITY { GRAPHICSDEVICE_CAPABILITY_TESSELLATION = 1 << 0, @@ -367,17 +372,37 @@ namespace wiGraphics GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_COMMON = 1 << 3, // eg: R16G16B16A16_FLOAT, R8G8B8A8_UNORM and more common ones GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_R11G11B10_FLOAT = 1 << 4, GRAPHICSDEVICE_CAPABILITY_RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS = 1 << 5, - GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE = 1 << 6, - GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE = 1 << 7, - GRAPHICSDEVICE_CAPABILITY_RAYTRACING_GEOMETRYINDEX = 1 << 8, - GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING = 1 << 9, - GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2 = 1 << 10, - GRAPHICSDEVICE_CAPABILITY_MESH_SHADER = 1 << 11, - GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS = 1 << 12, + GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING = 1 << 6, + GRAPHICSDEVICE_CAPABILITY_VARIABLE_RATE_SHADING_TIER2 = 1 << 7, + GRAPHICSDEVICE_CAPABILITY_MESH_SHADER = 1 << 8, + GRAPHICSDEVICE_CAPABILITY_RAYTRACING = 1 << 9, + }; + enum RESOURCE_STATE + { + // Common resource states: + RESOURCE_STATE_UNDEFINED = 0, // invalid state + RESOURCE_STATE_SHADER_RESOURCE = 1 << 0, // shader resource, read only + RESOURCE_STATE_SHADER_RESOURCE_COMPUTE = 1 << 1, // shader resource, read only, non-pixel shader + RESOURCE_STATE_UNORDERED_ACCESS = 1 << 2, // shader resource, write enabled + RESOURCE_STATE_COPY_SRC = 1 << 3, // copy from + RESOURCE_STATE_COPY_DST = 1 << 4, // copy to + // Texture specific resource states: + RESOURCE_STATE_RENDERTARGET = 1 << 5, // render target, write enabled + RESOURCE_STATE_DEPTHSTENCIL = 1 << 6, // depth stencil, write enabled + RESOURCE_STATE_DEPTHSTENCIL_READONLY = 1 << 7, // depth stencil, read only + RESOURCE_STATE_SHADING_RATE_SOURCE = 1 << 8, // shading rate control per tile - // helper query for full raytracing support: - GRAPHICSDEVICE_CAPABILITY_RAYTRACING = GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE | GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE | GRAPHICSDEVICE_CAPABILITY_RAYTRACING_GEOMETRYINDEX, + // GPUBuffer specific resource states: + RESOURCE_STATE_VERTEX_BUFFER = 1 << 9, // vertex buffer, read only + RESOURCE_STATE_INDEX_BUFFER = 1 << 10, // index buffer, read only + RESOURCE_STATE_CONSTANT_BUFFER = 1 << 11, // constant buffer, read only + RESOURCE_STATE_INDIRECT_ARGUMENT = 1 << 12, // argument buffer to DrawIndirect() or DispatchIndirect() + RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE = 1 << 13, // acceleration structure storage or scratch + }; + template<> + struct enable_bitmask_operators { + static const bool enable = true; }; // Descriptor structs: @@ -431,11 +456,10 @@ namespace wiGraphics FORMAT Format = FORMAT_UNKNOWN; uint32_t SampleCount = 1; USAGE Usage = USAGE_DEFAULT; - uint32_t BindFlags = 0; - uint32_t CPUAccessFlags = 0; - uint32_t MiscFlags = 0; + BIND_FLAG BindFlags = BIND_NONE; + RESOURCE_MISC_FLAG MiscFlags = RESOURCE_MISC_NONE; ClearValue clear = {}; - IMAGE_LAYOUT layout = IMAGE_LAYOUT_SHADER_RESOURCE; + RESOURCE_STATE layout = RESOURCE_STATE_SHADER_RESOURCE; }; struct SamplerDesc { @@ -505,9 +529,8 @@ namespace wiGraphics { uint32_t ByteWidth = 0; USAGE Usage = USAGE_DEFAULT; - uint32_t BindFlags = 0; - uint32_t CPUAccessFlags = 0; - uint32_t MiscFlags = 0; + BIND_FLAG BindFlags = BIND_NONE; + RESOURCE_MISC_FLAG MiscFlags = RESOURCE_MISC_NONE; uint32_t StructureByteStride = 0; // needed for typed and structured buffer types! FORMAT Format = FORMAT_UNKNOWN; // only needed for typed buffer! }; @@ -548,16 +571,16 @@ namespace wiGraphics struct Image { const Texture* texture; - IMAGE_LAYOUT layout_before; - IMAGE_LAYOUT layout_after; + RESOURCE_STATE layout_before; + RESOURCE_STATE layout_after; int mip; int slice; }; struct Buffer { const GPUBuffer* buffer; - BUFFER_STATE state_before; - BUFFER_STATE state_after; + RESOURCE_STATE state_before; + RESOURCE_STATE state_after; }; union { @@ -573,7 +596,7 @@ namespace wiGraphics barrier.memory.resource = resource; return barrier; } - static GPUBarrier Image(const Texture* texture, IMAGE_LAYOUT before, IMAGE_LAYOUT after, + static GPUBarrier Image(const Texture* texture, RESOURCE_STATE before, RESOURCE_STATE after, int mip = -1, int slice = -1) { GPUBarrier barrier; @@ -585,7 +608,7 @@ namespace wiGraphics barrier.image.slice = slice; return barrier; } - static GPUBarrier Buffer(const GPUBuffer* buffer, BUFFER_STATE before, BUFFER_STATE after) + static GPUBarrier Buffer(const GPUBuffer* buffer, RESOURCE_STATE before, RESOURCE_STATE after) { GPUBarrier barrier; barrier.type = BUFFER_BARRIER; @@ -617,17 +640,17 @@ namespace wiGraphics STOREOP_STORE, STOREOP_DONTCARE, } storeop = STOREOP_STORE; - IMAGE_LAYOUT initial_layout = IMAGE_LAYOUT_UNDEFINED; // layout before the render pass - IMAGE_LAYOUT subpass_layout = IMAGE_LAYOUT_UNDEFINED; // layout within the render pass - IMAGE_LAYOUT final_layout = IMAGE_LAYOUT_UNDEFINED; // layout after the render pass + RESOURCE_STATE initial_layout = RESOURCE_STATE_UNDEFINED; // layout before the render pass + RESOURCE_STATE subpass_layout = RESOURCE_STATE_UNDEFINED; // layout within the render pass + RESOURCE_STATE final_layout = RESOURCE_STATE_UNDEFINED; // layout after the render pass static RenderPassAttachment RenderTarget( const Texture* resource = nullptr, LOAD_OPERATION load_op = LOADOP_LOAD, STORE_OPERATION store_op = STOREOP_STORE, - IMAGE_LAYOUT initial_layout = IMAGE_LAYOUT_SHADER_RESOURCE, - IMAGE_LAYOUT subpass_layout = IMAGE_LAYOUT_RENDERTARGET, - IMAGE_LAYOUT final_layout = IMAGE_LAYOUT_SHADER_RESOURCE + RESOURCE_STATE initial_layout = RESOURCE_STATE_SHADER_RESOURCE, + RESOURCE_STATE subpass_layout = RESOURCE_STATE_RENDERTARGET, + RESOURCE_STATE final_layout = RESOURCE_STATE_SHADER_RESOURCE ) { RenderPassAttachment attachment; @@ -645,9 +668,9 @@ namespace wiGraphics const Texture* resource = nullptr, LOAD_OPERATION load_op = LOADOP_LOAD, STORE_OPERATION store_op = STOREOP_STORE, - IMAGE_LAYOUT initial_layout = IMAGE_LAYOUT_DEPTHSTENCIL, - IMAGE_LAYOUT subpass_layout = IMAGE_LAYOUT_DEPTHSTENCIL, - IMAGE_LAYOUT final_layout = IMAGE_LAYOUT_DEPTHSTENCIL + RESOURCE_STATE initial_layout = RESOURCE_STATE_DEPTHSTENCIL, + RESOURCE_STATE subpass_layout = RESOURCE_STATE_DEPTHSTENCIL, + RESOURCE_STATE final_layout = RESOURCE_STATE_DEPTHSTENCIL ) { RenderPassAttachment attachment; @@ -663,8 +686,8 @@ namespace wiGraphics static RenderPassAttachment Resolve( const Texture* resource = nullptr, - IMAGE_LAYOUT initial_layout = IMAGE_LAYOUT_SHADER_RESOURCE, - IMAGE_LAYOUT final_layout = IMAGE_LAYOUT_SHADER_RESOURCE + RESOURCE_STATE initial_layout = RESOURCE_STATE_SHADER_RESOURCE, + RESOURCE_STATE final_layout = RESOURCE_STATE_SHADER_RESOURCE ) { RenderPassAttachment attachment; @@ -677,15 +700,15 @@ namespace wiGraphics static RenderPassAttachment ShadingRateSource( const Texture* resource = nullptr, - IMAGE_LAYOUT initial_layout = IMAGE_LAYOUT_SHADING_RATE_SOURCE, - IMAGE_LAYOUT final_layout = IMAGE_LAYOUT_SHADING_RATE_SOURCE + RESOURCE_STATE initial_layout = RESOURCE_STATE_SHADING_RATE_SOURCE, + RESOURCE_STATE final_layout = RESOURCE_STATE_SHADING_RATE_SOURCE ) { RenderPassAttachment attachment; attachment.type = SHADING_RATE_SOURCE; attachment.texture = resource; attachment.initial_layout = initial_layout; - attachment.subpass_layout = IMAGE_LAYOUT_SHADING_RATE_SOURCE; + attachment.subpass_layout = RESOURCE_STATE_SHADING_RATE_SOURCE; attachment.final_layout = final_layout; return attachment; } @@ -744,20 +767,6 @@ namespace wiGraphics int32_t right = 0; int32_t bottom = 0; }; - struct Mapping - { - enum FLAGS - { - FLAG_EMPTY = 0, - FLAG_READ = 1 << 0, - FLAG_WRITE = 1 << 1, - }; - uint32_t _flags = FLAG_EMPTY; - size_t offset = 0; - size_t size = 0; - uint32_t rowpitch = 0; // output - void* data = nullptr; // output - }; // Resources: @@ -798,6 +807,9 @@ namespace wiGraphics inline bool IsTexture() const { return type == GPU_RESOURCE_TYPE::TEXTURE; } inline bool IsBuffer() const { return type == GPU_RESOURCE_TYPE::BUFFER; } inline bool IsAccelerationStructure() const { return type == GPU_RESOURCE_TYPE::RAYTRACING_ACCELERATION_STRUCTURE; } + + void* mapped_data = nullptr; + uint32_t mapped_rowpitch = 0; }; struct GPUBuffer : public GPUResource diff --git a/WickedEngine/wiGraphicsDevice.h b/WickedEngine/wiGraphicsDevice.h index 7ecbe63f8..d58440f47 100644 --- a/WickedEngine/wiGraphicsDevice.h +++ b/WickedEngine/wiGraphicsDevice.h @@ -3,12 +3,31 @@ #include "wiGraphics.h" #include "wiPlatform.h" +#include +#include + namespace wiGraphics { typedef uint8_t CommandList; static const CommandList COMMANDLIST_COUNT = 32; static const CommandList INVALID_COMMANDLIST = COMMANDLIST_COUNT; + // Descriptor binding counts: + // It's OK increase these limits if not enough + static const uint32_t DESCRIPTORBINDER_CBV_COUNT = 15; + static const uint32_t DESCRIPTORBINDER_SRV_COUNT = 64; + static const uint32_t DESCRIPTORBINDER_UAV_COUNT = 16; + static const uint32_t DESCRIPTORBINDER_SAMPLER_COUNT = 16; + + inline size_t Align(size_t uLocation, size_t uAlign) + { + if ((0 == uAlign) || (uAlign & (uAlign - 1))) + { + assert(0); + } + return ((uLocation + (uAlign - 1)) & ~(uAlign - 1)); + } + enum QUEUE_TYPE { QUEUE_GRAPHICS, @@ -28,6 +47,7 @@ namespace wiGraphics size_t TOPLEVEL_ACCELERATION_STRUCTURE_INSTANCE_SIZE = 0; uint32_t VARIABLE_RATE_SHADING_TILE_SIZE = 0; uint64_t TIMESTAMP_FREQUENCY = 0; + size_t ALLOCATION_MIN_ALIGNMENT = 0; public: virtual ~GraphicsDevice() = default; @@ -53,10 +73,6 @@ namespace wiGraphics virtual void WriteTopLevelAccelerationStructureInstance(const RaytracingAccelerationStructureDesc::TopLevel::Instance* instance, void* dest) const {} virtual void WriteShaderIdentifier(const RaytracingPipelineState* rtpso, uint32_t group_index, void* dest) const {} - virtual void Map(const GPUResource* resource, Mapping* mapping) const = 0; - virtual void Unmap(const GPUResource* resource) const = 0; - virtual void QueryRead(const GPUQueryHeap* heap, uint32_t index, uint32_t count, uint64_t* results) const = 0; - virtual void SetCommonSampler(const StaticSampler* sam) = 0; virtual void SetName(GPUResource* pResource, const char* name) = 0; @@ -81,6 +97,7 @@ namespace wiGraphics bool IsFormatStencilSupport(FORMAT value) const; static constexpr uint32_t GetBufferCount() { return BUFFERCOUNT; } + constexpr uint32_t GetBufferIndex() const { return GetFrameCount() % BUFFERCOUNT; } constexpr bool IsDebugDevice() const { return DEBUGDEVICE; } @@ -101,14 +118,12 @@ namespace wiGraphics virtual void RenderPassEnd(CommandList cmd) = 0; virtual void BindScissorRects(uint32_t numRects, const Rect* rects, CommandList cmd) = 0; virtual void BindViewports(uint32_t NumViewports, const Viewport* pViewports, CommandList cmd) = 0; - virtual void BindResource(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource = -1) = 0; - virtual void BindResources(SHADERSTAGE stage, const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) = 0; - virtual void BindUAV(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource = -1) = 0; - virtual void BindUAVs(SHADERSTAGE stage, const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) = 0; - virtual void UnbindResources(uint32_t slot, uint32_t num, CommandList cmd) = 0; - virtual void UnbindUAVs(uint32_t slot, uint32_t num, CommandList cmd) = 0; - virtual void BindSampler(SHADERSTAGE stage, const Sampler* sampler, uint32_t slot, CommandList cmd) = 0; - virtual void BindConstantBuffer(SHADERSTAGE stage, const GPUBuffer* buffer, uint32_t slot, CommandList cmd) = 0; + virtual void BindResource(const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource = -1) = 0; + virtual void BindResources(const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) = 0; + virtual void BindUAV(const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource = -1) = 0; + virtual void BindUAVs(const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) = 0; + virtual void BindSampler(const Sampler* sampler, uint32_t slot, CommandList cmd) = 0; + virtual void BindConstantBuffer(const GPUBuffer* buffer, uint32_t slot, CommandList cmd, uint64_t offset = 0ull) = 0; virtual void BindVertexBuffers(const GPUBuffer *const* vertexBuffers, uint32_t slot, uint32_t count, const uint32_t* strides, const uint32_t* offsets, CommandList cmd) = 0; virtual void BindIndexBuffer(const GPUBuffer* indexBuffer, const INDEXBUFFER_FORMAT format, uint32_t offset, CommandList cmd) = 0; virtual void BindStencilRef(uint32_t value, CommandList cmd) = 0; @@ -127,34 +142,105 @@ namespace wiGraphics virtual void DispatchMesh(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ, CommandList cmd) {} virtual void DispatchMeshIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) {} virtual void CopyResource(const GPUResource* pDst, const GPUResource* pSrc, CommandList cmd) = 0; - virtual void UpdateBuffer(const GPUBuffer* buffer, const void* data, CommandList cmd, int dataSize = -1) = 0; + virtual void CopyBuffer(const GPUBuffer* pDst, uint64_t dst_offset, const GPUBuffer* pSrc, uint64_t src_offset, uint64_t size, CommandList cmd) = 0; virtual void QueryBegin(const GPUQueryHeap *heap, uint32_t index, CommandList cmd) = 0; virtual void QueryEnd(const GPUQueryHeap *heap, uint32_t index, CommandList cmd) = 0; - virtual void QueryResolve(const GPUQueryHeap* heap, uint32_t index, uint32_t count, CommandList cmd) {} + virtual void QueryResolve(const GPUQueryHeap* heap, uint32_t index, uint32_t count, const GPUBuffer* dest, uint64_t dest_offset, CommandList cmd) {} + virtual void QueryReset(const GPUQueryHeap* heap, uint32_t index, uint32_t count, CommandList cmd) {} virtual void Barrier(const GPUBarrier* barriers, uint32_t numBarriers, CommandList cmd) = 0; virtual void BuildRaytracingAccelerationStructure(const RaytracingAccelerationStructure* dst, CommandList cmd, const RaytracingAccelerationStructure* src = nullptr) {} virtual void BindRaytracingPipelineState(const RaytracingPipelineState* rtpso, CommandList cmd) {} virtual void DispatchRays(const DispatchRaysDesc* desc, CommandList cmd) {} virtual void PushConstants(const void* data, uint32_t size, CommandList cmd) {} - - struct GPUAllocation - { - void* data = nullptr; // application can write to this. Reads might be not supported or slow. The offset is already applied - const GPUBuffer* buffer = nullptr; // application can bind it to the GPU - uint32_t offset = 0; // allocation's offset from the GPUbuffer's beginning - - // Returns true if the allocation was successful - inline bool IsValid() const { return data != nullptr && buffer != nullptr; } - }; - // Allocates temporary memory that the CPU can write and GPU can read. - // It is only alive for one frame and automatically invalidated after that. - // The CPU pointer gets invalidated as soon as there is a Draw() or Dispatch() event on the same thread - // This allocation can be used to provide temporary vertex buffer, index buffer or raw buffer data to shaders - virtual GPUAllocation AllocateGPU(size_t dataSize, CommandList cmd) = 0; virtual void EventBegin(const char* name, CommandList cmd) = 0; virtual void EventEnd(CommandList cmd) = 0; virtual void SetMarker(const char* name, CommandList cmd) = 0; + + + + + // Some useful helpers: + + struct GPULinearAllocator + { + GPUBuffer buffer; + size_t offset = 0; + uint64_t frame_index = 0; + } frame_allocators[BUFFERCOUNT][COMMANDLIST_COUNT]; + + struct GPUAllocation + { + void* data = nullptr; // application can write to this. Reads might be not supported or slow. The offset is already applied + GPUBuffer buffer; // application can bind it to the GPU + uint32_t offset = 0; // allocation's offset from the GPUbuffer's beginning + + // Returns true if the allocation was successful + inline bool IsValid() const { return data != nullptr && buffer.IsValid(); } + }; + // Allocates temporary memory that the CPU can write and GPU can read. + // It is only alive for one frame and automatically invalidated after that. + GPUAllocation AllocateGPU(size_t dataSize, CommandList cmd) + { + GPUAllocation allocation; + if (dataSize == 0) + return allocation; + + GPULinearAllocator& allocator = frame_allocators[GetBufferIndex()][cmd]; + if (FRAMECOUNT != allocator.frame_index) + { + allocator.frame_index = FRAMECOUNT; + allocator.offset = 0; + } + + size_t free_space = (size_t)allocator.buffer.desc.ByteWidth - allocator.offset; + if (dataSize > free_space) + { + GPUBufferDesc desc; + desc.Usage = USAGE_UPLOAD; + desc.ByteWidth = (uint32_t)Align((allocator.buffer.desc.ByteWidth + dataSize) * 2, ALLOCATION_MIN_ALIGNMENT); + desc.BindFlags = BIND_CONSTANT_BUFFER | BIND_VERTEX_BUFFER | BIND_INDEX_BUFFER | BIND_SHADER_RESOURCE; + desc.MiscFlags = RESOURCE_MISC_BUFFER_RAW; + CreateBuffer(&desc, nullptr, &allocator.buffer); + SetName(&allocator.buffer, "frame_allocator"); + allocator.offset = 0; + } + + allocation.buffer = allocator.buffer; + allocation.offset = (uint32_t)allocator.offset; + allocation.data = (void*)((size_t)allocator.buffer.mapped_data + allocator.offset); + + allocator.offset += Align(dataSize, ALLOCATION_MIN_ALIGNMENT); + + assert(allocation.IsValid()); + return allocation; + } + + // Updates a USAGE_DEFAULT buffer data + // Since it uses a GPU Copy operation, appropriate synchronization is expected + // And it cannot be used inside a RenderPass + void UpdateBuffer(const GPUBuffer* buffer, const void* data, CommandList cmd, size_t size = ~0, size_t offset = 0) + { + if (buffer == nullptr || data == nullptr) + return; + size = std::min((size_t)buffer->desc.ByteWidth, size); + if (size == 0) + return; + GPUAllocation allocation = AllocateGPU(size, cmd); + std::memcpy(allocation.data, data, size); + CopyBuffer(buffer, offset, &allocation.buffer, allocation.offset, size, cmd); + } + + // Helper util to bind a constant buffer with data for a specific command list: + // This will be done on the CPU to an UPLOAD buffer, so this can be used inside a RenderPass + // But this will be only visible on the command list it was bound to + template + void BindDynamicConstantBuffer(const T& data, uint32_t slot, wiGraphics::CommandList cmd) + { + GPUAllocation allocation = AllocateGPU(sizeof(T), cmd); + std::memcpy(allocation.data, &data, sizeof(T)); + BindConstantBuffer(&allocation.buffer, slot, cmd, allocation.offset); + } }; } diff --git a/WickedEngine/wiGraphicsDevice_DX11.cpp b/WickedEngine/wiGraphicsDevice_DX11.cpp deleted file mode 100644 index c20d668de..000000000 --- a/WickedEngine/wiGraphicsDevice_DX11.cpp +++ /dev/null @@ -1,3362 +0,0 @@ -#include "wiGraphicsDevice_DX11.h" - -#ifdef WICKEDENGINE_BUILD_DX11 - -#include "wiHelper.h" -#include "wiBackLog.h" - -#pragma comment(lib,"dxguid.lib") - -#include -#include - -// These will let the driver select the dedicated GPU in favour of the integrated one: -extern "C" { - _declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001; - _declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; -} - -using namespace Microsoft::WRL; - -namespace wiGraphics -{ - -namespace DX11_Internal -{ - -#ifdef PLATFORM_UWP - // UWP will use static link + /DELAYLOAD linker feature for the dlls (optionally) -#pragma comment(lib,"d3d11.lib") -#else - static PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = nullptr; -#endif // PLATFORM_UWP - - // Engine -> Native converters - - constexpr uint32_t _ParseBindFlags(uint32_t value) - { - uint32_t _flag = 0; - - if (value & BIND_VERTEX_BUFFER) - _flag |= D3D11_BIND_VERTEX_BUFFER; - if (value & BIND_INDEX_BUFFER) - _flag |= D3D11_BIND_INDEX_BUFFER; - if (value & BIND_CONSTANT_BUFFER) - _flag |= D3D11_BIND_CONSTANT_BUFFER; - if (value & BIND_SHADER_RESOURCE) - _flag |= D3D11_BIND_SHADER_RESOURCE; - if (value & BIND_STREAM_OUTPUT) - _flag |= D3D11_BIND_STREAM_OUTPUT; - if (value & BIND_RENDER_TARGET) - _flag |= D3D11_BIND_RENDER_TARGET; - if (value & BIND_DEPTH_STENCIL) - _flag |= D3D11_BIND_DEPTH_STENCIL; - if (value & BIND_UNORDERED_ACCESS) - _flag |= D3D11_BIND_UNORDERED_ACCESS; - - return _flag; - } - constexpr uint32_t _ParseCPUAccessFlags(uint32_t value) - { - uint32_t _flag = 0; - - if (value & CPU_ACCESS_WRITE) - _flag |= D3D11_CPU_ACCESS_WRITE; - if (value & CPU_ACCESS_READ) - _flag |= D3D11_CPU_ACCESS_READ; - - return _flag; - } - constexpr uint32_t _ParseResourceMiscFlags(uint32_t value) - { - uint32_t _flag = 0; - - if (value & RESOURCE_MISC_SHARED) - _flag |= D3D11_RESOURCE_MISC_SHARED; - if (value & RESOURCE_MISC_TEXTURECUBE) - _flag |= D3D11_RESOURCE_MISC_TEXTURECUBE; - if (value & RESOURCE_MISC_INDIRECT_ARGS) - _flag |= D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS; - if (value & RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) - _flag |= D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; - if (value & RESOURCE_MISC_BUFFER_STRUCTURED) - _flag |= D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; - if (value & RESOURCE_MISC_TILED) - _flag |= D3D11_RESOURCE_MISC_TILED; - - return _flag; - } - constexpr uint32_t _ParseColorWriteMask(uint32_t value) - { - uint32_t _flag = 0; - - if (value == D3D11_COLOR_WRITE_ENABLE_ALL) - { - return D3D11_COLOR_WRITE_ENABLE_ALL; - } - else - { - if (value & COLOR_WRITE_ENABLE_RED) - _flag |= D3D11_COLOR_WRITE_ENABLE_RED; - if (value & COLOR_WRITE_ENABLE_GREEN) - _flag |= D3D11_COLOR_WRITE_ENABLE_GREEN; - if (value & COLOR_WRITE_ENABLE_BLUE) - _flag |= D3D11_COLOR_WRITE_ENABLE_BLUE; - if (value & COLOR_WRITE_ENABLE_ALPHA) - _flag |= D3D11_COLOR_WRITE_ENABLE_ALPHA; - } - - return _flag; - } - - constexpr D3D11_FILTER _ConvertFilter(FILTER value) - { - switch (value) - { - case FILTER_MIN_MAG_MIP_POINT: - return D3D11_FILTER_MIN_MAG_MIP_POINT; - break; - case FILTER_MIN_MAG_POINT_MIP_LINEAR: - return D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; - break; - case FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT: - return D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; - break; - case FILTER_MIN_POINT_MAG_MIP_LINEAR: - return D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR; - break; - case FILTER_MIN_LINEAR_MAG_MIP_POINT: - return D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT; - break; - case FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR: - return D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR; - break; - case FILTER_MIN_MAG_LINEAR_MIP_POINT: - return D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; - break; - case FILTER_MIN_MAG_MIP_LINEAR: - return D3D11_FILTER_MIN_MAG_MIP_LINEAR; - break; - case FILTER_ANISOTROPIC: - return D3D11_FILTER_ANISOTROPIC; - break; - case FILTER_COMPARISON_MIN_MAG_MIP_POINT: - return D3D11_FILTER_COMPARISON_MIN_MAG_MIP_POINT; - break; - case FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR: - return D3D11_FILTER_COMPARISON_MIN_MAG_POINT_MIP_LINEAR; - break; - case FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT: - return D3D11_FILTER_COMPARISON_MIN_POINT_MAG_LINEAR_MIP_POINT; - break; - case FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR: - return D3D11_FILTER_COMPARISON_MIN_POINT_MAG_MIP_LINEAR; - break; - case FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT: - return D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_MIP_POINT; - break; - case FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR: - return D3D11_FILTER_COMPARISON_MIN_LINEAR_MAG_POINT_MIP_LINEAR; - break; - case FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT: - return D3D11_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT; - break; - case FILTER_COMPARISON_MIN_MAG_MIP_LINEAR: - return D3D11_FILTER_COMPARISON_MIN_MAG_MIP_LINEAR; - break; - case FILTER_COMPARISON_ANISOTROPIC: - return D3D11_FILTER_COMPARISON_ANISOTROPIC; - break; - case FILTER_MINIMUM_MIN_MAG_MIP_POINT: - return D3D11_FILTER_MINIMUM_MIN_MAG_MIP_POINT; - break; - case FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR: - return D3D11_FILTER_MINIMUM_MIN_MAG_POINT_MIP_LINEAR; - break; - case FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT: - return D3D11_FILTER_MINIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT; - break; - case FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR: - return D3D11_FILTER_MINIMUM_MIN_POINT_MAG_MIP_LINEAR; - break; - case FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT: - return D3D11_FILTER_MINIMUM_MIN_LINEAR_MAG_MIP_POINT; - break; - case FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR: - return D3D11_FILTER_MINIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR; - break; - case FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT: - return D3D11_FILTER_MINIMUM_MIN_MAG_LINEAR_MIP_POINT; - break; - case FILTER_MINIMUM_MIN_MAG_MIP_LINEAR: - return D3D11_FILTER_MINIMUM_MIN_MAG_MIP_LINEAR; - break; - case FILTER_MINIMUM_ANISOTROPIC: - return D3D11_FILTER_MINIMUM_ANISOTROPIC; - break; - case FILTER_MAXIMUM_MIN_MAG_MIP_POINT: - return D3D11_FILTER_MAXIMUM_MIN_MAG_MIP_POINT; - break; - case FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR: - return D3D11_FILTER_MAXIMUM_MIN_MAG_POINT_MIP_LINEAR; - break; - case FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT: - return D3D11_FILTER_MAXIMUM_MIN_POINT_MAG_LINEAR_MIP_POINT; - break; - case FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR: - return D3D11_FILTER_MAXIMUM_MIN_POINT_MAG_MIP_LINEAR; - break; - case FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT: - return D3D11_FILTER_MAXIMUM_MIN_LINEAR_MAG_MIP_POINT; - break; - case FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR: - return D3D11_FILTER_MAXIMUM_MIN_LINEAR_MAG_POINT_MIP_LINEAR; - break; - case FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT: - return D3D11_FILTER_MAXIMUM_MIN_MAG_LINEAR_MIP_POINT; - break; - case FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR: - return D3D11_FILTER_MAXIMUM_MIN_MAG_MIP_LINEAR; - break; - case FILTER_MAXIMUM_ANISOTROPIC: - return D3D11_FILTER_MAXIMUM_ANISOTROPIC; - break; - default: - break; - } - return D3D11_FILTER_MIN_MAG_MIP_POINT; - } - constexpr D3D11_TEXTURE_ADDRESS_MODE _ConvertTextureAddressMode(TEXTURE_ADDRESS_MODE value) - { - switch (value) - { - case TEXTURE_ADDRESS_WRAP: - return D3D11_TEXTURE_ADDRESS_WRAP; - break; - case TEXTURE_ADDRESS_MIRROR: - return D3D11_TEXTURE_ADDRESS_MIRROR; - break; - case TEXTURE_ADDRESS_CLAMP: - return D3D11_TEXTURE_ADDRESS_CLAMP; - break; - case TEXTURE_ADDRESS_BORDER: - return D3D11_TEXTURE_ADDRESS_BORDER; - break; - default: - break; - } - return D3D11_TEXTURE_ADDRESS_WRAP; - } - constexpr D3D11_COMPARISON_FUNC _ConvertComparisonFunc(COMPARISON_FUNC value) - { - switch (value) - { - case COMPARISON_NEVER: - return D3D11_COMPARISON_NEVER; - break; - case COMPARISON_LESS: - return D3D11_COMPARISON_LESS; - break; - case COMPARISON_EQUAL: - return D3D11_COMPARISON_EQUAL; - break; - case COMPARISON_LESS_EQUAL: - return D3D11_COMPARISON_LESS_EQUAL; - break; - case COMPARISON_GREATER: - return D3D11_COMPARISON_GREATER; - break; - case COMPARISON_NOT_EQUAL: - return D3D11_COMPARISON_NOT_EQUAL; - break; - case COMPARISON_GREATER_EQUAL: - return D3D11_COMPARISON_GREATER_EQUAL; - break; - case COMPARISON_ALWAYS: - return D3D11_COMPARISON_ALWAYS; - break; - default: - break; - } - return D3D11_COMPARISON_NEVER; - } - constexpr D3D11_FILL_MODE _ConvertFillMode(FILL_MODE value) - { - switch (value) - { - case FILL_WIREFRAME: - return D3D11_FILL_WIREFRAME; - break; - case FILL_SOLID: - return D3D11_FILL_SOLID; - break; - default: - break; - } - return D3D11_FILL_WIREFRAME; - } - constexpr D3D11_CULL_MODE _ConvertCullMode(CULL_MODE value) - { - switch (value) - { - case CULL_NONE: - return D3D11_CULL_NONE; - break; - case CULL_FRONT: - return D3D11_CULL_FRONT; - break; - case CULL_BACK: - return D3D11_CULL_BACK; - break; - default: - break; - } - return D3D11_CULL_NONE; - } - constexpr D3D11_DEPTH_WRITE_MASK _ConvertDepthWriteMask(DEPTH_WRITE_MASK value) - { - switch (value) - { - case DEPTH_WRITE_MASK_ZERO: - return D3D11_DEPTH_WRITE_MASK_ZERO; - break; - case DEPTH_WRITE_MASK_ALL: - return D3D11_DEPTH_WRITE_MASK_ALL; - break; - default: - break; - } - return D3D11_DEPTH_WRITE_MASK_ZERO; - } - constexpr D3D11_STENCIL_OP _ConvertStencilOp(STENCIL_OP value) - { - switch (value) - { - case STENCIL_OP_KEEP: - return D3D11_STENCIL_OP_KEEP; - break; - case STENCIL_OP_ZERO: - return D3D11_STENCIL_OP_ZERO; - break; - case STENCIL_OP_REPLACE: - return D3D11_STENCIL_OP_REPLACE; - break; - case STENCIL_OP_INCR_SAT: - return D3D11_STENCIL_OP_INCR_SAT; - break; - case STENCIL_OP_DECR_SAT: - return D3D11_STENCIL_OP_DECR_SAT; - break; - case STENCIL_OP_INVERT: - return D3D11_STENCIL_OP_INVERT; - break; - case STENCIL_OP_INCR: - return D3D11_STENCIL_OP_INCR; - break; - case STENCIL_OP_DECR: - return D3D11_STENCIL_OP_DECR; - break; - default: - break; - } - return D3D11_STENCIL_OP_KEEP; - } - constexpr D3D11_BLEND _ConvertBlend(BLEND value) - { - switch (value) - { - case BLEND_ZERO: - return D3D11_BLEND_ZERO; - break; - case BLEND_ONE: - return D3D11_BLEND_ONE; - break; - case BLEND_SRC_COLOR: - return D3D11_BLEND_SRC_COLOR; - break; - case BLEND_INV_SRC_COLOR: - return D3D11_BLEND_INV_SRC_COLOR; - break; - case BLEND_SRC_ALPHA: - return D3D11_BLEND_SRC_ALPHA; - break; - case BLEND_INV_SRC_ALPHA: - return D3D11_BLEND_INV_SRC_ALPHA; - break; - case BLEND_DEST_ALPHA: - return D3D11_BLEND_DEST_ALPHA; - break; - case BLEND_INV_DEST_ALPHA: - return D3D11_BLEND_INV_DEST_ALPHA; - break; - case BLEND_DEST_COLOR: - return D3D11_BLEND_DEST_COLOR; - break; - case BLEND_INV_DEST_COLOR: - return D3D11_BLEND_INV_DEST_COLOR; - break; - case BLEND_SRC_ALPHA_SAT: - return D3D11_BLEND_SRC_ALPHA_SAT; - break; - case BLEND_BLEND_FACTOR: - return D3D11_BLEND_BLEND_FACTOR; - break; - case BLEND_INV_BLEND_FACTOR: - return D3D11_BLEND_INV_BLEND_FACTOR; - break; - case BLEND_SRC1_COLOR: - return D3D11_BLEND_SRC1_COLOR; - break; - case BLEND_INV_SRC1_COLOR: - return D3D11_BLEND_INV_SRC1_COLOR; - break; - case BLEND_SRC1_ALPHA: - return D3D11_BLEND_SRC1_ALPHA; - break; - case BLEND_INV_SRC1_ALPHA: - return D3D11_BLEND_INV_SRC1_ALPHA; - break; - default: - break; - } - return D3D11_BLEND_ZERO; - } - constexpr D3D11_BLEND_OP _ConvertBlendOp(BLEND_OP value) - { - switch (value) - { - case BLEND_OP_ADD: - return D3D11_BLEND_OP_ADD; - break; - case BLEND_OP_SUBTRACT: - return D3D11_BLEND_OP_SUBTRACT; - break; - case BLEND_OP_REV_SUBTRACT: - return D3D11_BLEND_OP_REV_SUBTRACT; - break; - case BLEND_OP_MIN: - return D3D11_BLEND_OP_MIN; - break; - case BLEND_OP_MAX: - return D3D11_BLEND_OP_MAX; - break; - default: - break; - } - return D3D11_BLEND_OP_ADD; - } - constexpr D3D11_USAGE _ConvertUsage(USAGE value) - { - switch (value) - { - case USAGE_DEFAULT: - return D3D11_USAGE_DEFAULT; - break; - case USAGE_IMMUTABLE: - return D3D11_USAGE_IMMUTABLE; - break; - case USAGE_DYNAMIC: - return D3D11_USAGE_DYNAMIC; - break; - case USAGE_STAGING: - return D3D11_USAGE_STAGING; - break; - default: - break; - } - return D3D11_USAGE_DEFAULT; - } - constexpr D3D11_INPUT_CLASSIFICATION _ConvertInputClassification(INPUT_CLASSIFICATION value) - { - switch (value) - { - case INPUT_PER_VERTEX_DATA: - return D3D11_INPUT_PER_VERTEX_DATA; - break; - case INPUT_PER_INSTANCE_DATA: - return D3D11_INPUT_PER_INSTANCE_DATA; - break; - default: - break; - } - return D3D11_INPUT_PER_VERTEX_DATA; - } - constexpr DXGI_FORMAT _ConvertFormat(FORMAT value) - { - switch (value) - { - case FORMAT_UNKNOWN: - return DXGI_FORMAT_UNKNOWN; - break; - case FORMAT_R32G32B32A32_FLOAT: - return DXGI_FORMAT_R32G32B32A32_FLOAT; - break; - case FORMAT_R32G32B32A32_UINT: - return DXGI_FORMAT_R32G32B32A32_UINT; - break; - case FORMAT_R32G32B32A32_SINT: - return DXGI_FORMAT_R32G32B32A32_SINT; - break; - case FORMAT_R32G32B32_FLOAT: - return DXGI_FORMAT_R32G32B32_FLOAT; - break; - case FORMAT_R32G32B32_UINT: - return DXGI_FORMAT_R32G32B32_UINT; - break; - case FORMAT_R32G32B32_SINT: - return DXGI_FORMAT_R32G32B32_SINT; - break; - case FORMAT_R16G16B16A16_FLOAT: - return DXGI_FORMAT_R16G16B16A16_FLOAT; - break; - case FORMAT_R16G16B16A16_UNORM: - return DXGI_FORMAT_R16G16B16A16_UNORM; - break; - case FORMAT_R16G16B16A16_UINT: - return DXGI_FORMAT_R16G16B16A16_UINT; - break; - case FORMAT_R16G16B16A16_SNORM: - return DXGI_FORMAT_R16G16B16A16_SNORM; - break; - case FORMAT_R16G16B16A16_SINT: - return DXGI_FORMAT_R16G16B16A16_SINT; - break; - case FORMAT_R32G32_FLOAT: - return DXGI_FORMAT_R32G32_FLOAT; - break; - case FORMAT_R32G32_UINT: - return DXGI_FORMAT_R32G32_UINT; - break; - case FORMAT_R32G32_SINT: - return DXGI_FORMAT_R32G32_SINT; - break; - case FORMAT_R32G8X24_TYPELESS: - return DXGI_FORMAT_R32G8X24_TYPELESS; - break; - case FORMAT_D32_FLOAT_S8X24_UINT: - return DXGI_FORMAT_D32_FLOAT_S8X24_UINT; - break; - case FORMAT_R10G10B10A2_UNORM: - return DXGI_FORMAT_R10G10B10A2_UNORM; - break; - case FORMAT_R10G10B10A2_UINT: - return DXGI_FORMAT_R10G10B10A2_UINT; - break; - case FORMAT_R11G11B10_FLOAT: - return DXGI_FORMAT_R11G11B10_FLOAT; - break; - case FORMAT_R8G8B8A8_UNORM: - return DXGI_FORMAT_R8G8B8A8_UNORM; - break; - case FORMAT_R8G8B8A8_UNORM_SRGB: - return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB; - break; - case FORMAT_R8G8B8A8_UINT: - return DXGI_FORMAT_R8G8B8A8_UINT; - break; - case FORMAT_R8G8B8A8_SNORM: - return DXGI_FORMAT_R8G8B8A8_SNORM; - break; - case FORMAT_R8G8B8A8_SINT: - return DXGI_FORMAT_R8G8B8A8_SINT; - break; - case FORMAT_R16G16_FLOAT: - return DXGI_FORMAT_R16G16_FLOAT; - break; - case FORMAT_R16G16_UNORM: - return DXGI_FORMAT_R16G16_UNORM; - break; - case FORMAT_R16G16_UINT: - return DXGI_FORMAT_R16G16_UINT; - break; - case FORMAT_R16G16_SNORM: - return DXGI_FORMAT_R16G16_SNORM; - break; - case FORMAT_R16G16_SINT: - return DXGI_FORMAT_R16G16_SINT; - break; - case FORMAT_R32_TYPELESS: - return DXGI_FORMAT_R32_TYPELESS; - break; - case FORMAT_D32_FLOAT: - return DXGI_FORMAT_D32_FLOAT; - break; - case FORMAT_R32_FLOAT: - return DXGI_FORMAT_R32_FLOAT; - break; - case FORMAT_R32_UINT: - return DXGI_FORMAT_R32_UINT; - break; - case FORMAT_R32_SINT: - return DXGI_FORMAT_R32_SINT; - break; - case FORMAT_R24G8_TYPELESS: - return DXGI_FORMAT_R24G8_TYPELESS; - break; - case FORMAT_D24_UNORM_S8_UINT: - return DXGI_FORMAT_D24_UNORM_S8_UINT; - break; - case FORMAT_R8G8_UNORM: - return DXGI_FORMAT_R8G8_UNORM; - break; - case FORMAT_R8G8_UINT: - return DXGI_FORMAT_R8G8_UINT; - break; - case FORMAT_R8G8_SNORM: - return DXGI_FORMAT_R8G8_SNORM; - break; - case FORMAT_R8G8_SINT: - return DXGI_FORMAT_R8G8_SINT; - break; - case FORMAT_R16_TYPELESS: - return DXGI_FORMAT_R16_TYPELESS; - break; - case FORMAT_R16_FLOAT: - return DXGI_FORMAT_R16_FLOAT; - break; - case FORMAT_D16_UNORM: - return DXGI_FORMAT_D16_UNORM; - break; - case FORMAT_R16_UNORM: - return DXGI_FORMAT_R16_UNORM; - break; - case FORMAT_R16_UINT: - return DXGI_FORMAT_R16_UINT; - break; - case FORMAT_R16_SNORM: - return DXGI_FORMAT_R16_SNORM; - break; - case FORMAT_R16_SINT: - return DXGI_FORMAT_R16_SINT; - break; - case FORMAT_R8_UNORM: - return DXGI_FORMAT_R8_UNORM; - break; - case FORMAT_R8_UINT: - return DXGI_FORMAT_R8_UINT; - break; - case FORMAT_R8_SNORM: - return DXGI_FORMAT_R8_SNORM; - break; - case FORMAT_R8_SINT: - return DXGI_FORMAT_R8_SINT; - break; - case FORMAT_BC1_UNORM: - return DXGI_FORMAT_BC1_UNORM; - break; - case FORMAT_BC1_UNORM_SRGB: - return DXGI_FORMAT_BC1_UNORM_SRGB; - break; - case FORMAT_BC2_UNORM: - return DXGI_FORMAT_BC2_UNORM; - break; - case FORMAT_BC2_UNORM_SRGB: - return DXGI_FORMAT_BC2_UNORM_SRGB; - break; - case FORMAT_BC3_UNORM: - return DXGI_FORMAT_BC3_UNORM; - break; - case FORMAT_BC3_UNORM_SRGB: - return DXGI_FORMAT_BC3_UNORM_SRGB; - break; - case FORMAT_BC4_UNORM: - return DXGI_FORMAT_BC4_UNORM; - break; - case FORMAT_BC4_SNORM: - return DXGI_FORMAT_BC4_SNORM; - break; - case FORMAT_BC5_UNORM: - return DXGI_FORMAT_BC5_UNORM; - break; - case FORMAT_BC5_SNORM: - return DXGI_FORMAT_BC5_SNORM; - break; - case FORMAT_B8G8R8A8_UNORM: - return DXGI_FORMAT_B8G8R8A8_UNORM; - break; - case FORMAT_B8G8R8A8_UNORM_SRGB: - return DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; - break; - case FORMAT_BC6H_UF16: - return DXGI_FORMAT_BC6H_UF16; - break; - case FORMAT_BC6H_SF16: - return DXGI_FORMAT_BC6H_SF16; - break; - case FORMAT_BC7_UNORM: - return DXGI_FORMAT_BC7_UNORM; - break; - case FORMAT_BC7_UNORM_SRGB: - return DXGI_FORMAT_BC7_UNORM_SRGB; - break; - } - return DXGI_FORMAT_UNKNOWN; - } - - inline D3D11_TEXTURE1D_DESC _ConvertTextureDesc1D(const TextureDesc* pDesc) - { - D3D11_TEXTURE1D_DESC desc; - desc.Width = pDesc->Width; - desc.MipLevels = pDesc->MipLevels; - desc.ArraySize = pDesc->ArraySize; - desc.Format = _ConvertFormat(pDesc->Format); - desc.Usage = _ConvertUsage(pDesc->Usage); - desc.BindFlags = _ParseBindFlags(pDesc->BindFlags); - desc.CPUAccessFlags = _ParseCPUAccessFlags(pDesc->CPUAccessFlags); - desc.MiscFlags = _ParseResourceMiscFlags(pDesc->MiscFlags); - - return desc; - } - inline D3D11_TEXTURE2D_DESC _ConvertTextureDesc2D(const TextureDesc* pDesc) - { - D3D11_TEXTURE2D_DESC desc; - desc.Width = pDesc->Width; - desc.Height = pDesc->Height; - desc.MipLevels = pDesc->MipLevels; - desc.ArraySize = pDesc->ArraySize; - desc.Format = _ConvertFormat(pDesc->Format); - desc.SampleDesc.Count = pDesc->SampleCount; - desc.SampleDesc.Quality = 0; - desc.Usage = _ConvertUsage(pDesc->Usage); - desc.BindFlags = _ParseBindFlags(pDesc->BindFlags); - desc.CPUAccessFlags = _ParseCPUAccessFlags(pDesc->CPUAccessFlags); - desc.MiscFlags = _ParseResourceMiscFlags(pDesc->MiscFlags); - - return desc; - } - inline D3D11_TEXTURE3D_DESC _ConvertTextureDesc3D(const TextureDesc* pDesc) - { - D3D11_TEXTURE3D_DESC desc; - desc.Width = pDesc->Width; - desc.Height = pDesc->Height; - desc.Depth = pDesc->Depth; - desc.MipLevels = pDesc->MipLevels; - desc.Format = _ConvertFormat(pDesc->Format); - desc.Usage = _ConvertUsage(pDesc->Usage); - desc.BindFlags = _ParseBindFlags(pDesc->BindFlags); - desc.CPUAccessFlags = _ParseCPUAccessFlags(pDesc->CPUAccessFlags); - desc.MiscFlags = _ParseResourceMiscFlags(pDesc->MiscFlags); - - return desc; - } - inline D3D11_SUBRESOURCE_DATA _ConvertSubresourceData(const SubresourceData& pInitialData) - { - D3D11_SUBRESOURCE_DATA data; - data.pSysMem = pInitialData.pSysMem; - data.SysMemPitch = pInitialData.SysMemPitch; - data.SysMemSlicePitch = pInitialData.SysMemSlicePitch; - - return data; - } - - - // Native -> Engine converters - - constexpr uint32_t _ParseBindFlags_Inv(uint32_t value) - { - uint32_t _flag = 0; - - if (value & D3D11_BIND_VERTEX_BUFFER) - _flag |= BIND_VERTEX_BUFFER; - if (value & D3D11_BIND_INDEX_BUFFER) - _flag |= BIND_INDEX_BUFFER; - if (value & D3D11_BIND_CONSTANT_BUFFER) - _flag |= BIND_CONSTANT_BUFFER; - if (value & D3D11_BIND_SHADER_RESOURCE) - _flag |= BIND_SHADER_RESOURCE; - if (value & D3D11_BIND_STREAM_OUTPUT) - _flag |= BIND_STREAM_OUTPUT; - if (value & D3D11_BIND_RENDER_TARGET) - _flag |= BIND_RENDER_TARGET; - if (value & D3D11_BIND_DEPTH_STENCIL) - _flag |= BIND_DEPTH_STENCIL; - if (value & D3D11_BIND_UNORDERED_ACCESS) - _flag |= BIND_UNORDERED_ACCESS; - - return _flag; - } - constexpr uint32_t _ParseCPUAccessFlags_Inv(uint32_t value) - { - uint32_t _flag = 0; - - if (value & D3D11_CPU_ACCESS_WRITE) - _flag |= CPU_ACCESS_WRITE; - if (value & D3D11_CPU_ACCESS_READ) - _flag |= CPU_ACCESS_READ; - - return _flag; - } - constexpr uint32_t _ParseResourceMiscFlags_Inv(uint32_t value) - { - uint32_t _flag = 0; - - if (value & D3D11_RESOURCE_MISC_SHARED) - _flag |= RESOURCE_MISC_SHARED; - if (value & D3D11_RESOURCE_MISC_TEXTURECUBE) - _flag |= RESOURCE_MISC_TEXTURECUBE; - if (value & D3D11_RESOURCE_MISC_DRAWINDIRECT_ARGS) - _flag |= RESOURCE_MISC_INDIRECT_ARGS; - if (value & D3D11_RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) - _flag |= RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; - if (value & D3D11_RESOURCE_MISC_BUFFER_STRUCTURED) - _flag |= RESOURCE_MISC_BUFFER_STRUCTURED; - if (value & D3D11_RESOURCE_MISC_TILED) - _flag |= RESOURCE_MISC_TILED; - - return _flag; - } - - constexpr FORMAT _ConvertFormat_Inv(DXGI_FORMAT value) - { - switch (value) - { - case DXGI_FORMAT_UNKNOWN: - return FORMAT_UNKNOWN; - break; - case DXGI_FORMAT_R32G32B32A32_FLOAT: - return FORMAT_R32G32B32A32_FLOAT; - break; - case DXGI_FORMAT_R32G32B32A32_UINT: - return FORMAT_R32G32B32A32_UINT; - break; - case DXGI_FORMAT_R32G32B32A32_SINT: - return FORMAT_R32G32B32A32_SINT; - break; - case DXGI_FORMAT_R32G32B32_FLOAT: - return FORMAT_R32G32B32_FLOAT; - break; - case DXGI_FORMAT_R32G32B32_UINT: - return FORMAT_R32G32B32_UINT; - break; - case DXGI_FORMAT_R32G32B32_SINT: - return FORMAT_R32G32B32_SINT; - break; - case DXGI_FORMAT_R16G16B16A16_FLOAT: - return FORMAT_R16G16B16A16_FLOAT; - break; - case DXGI_FORMAT_R16G16B16A16_UNORM: - return FORMAT_R16G16B16A16_UNORM; - break; - case DXGI_FORMAT_R16G16B16A16_UINT: - return FORMAT_R16G16B16A16_UINT; - break; - case DXGI_FORMAT_R16G16B16A16_SNORM: - return FORMAT_R16G16B16A16_SNORM; - break; - case DXGI_FORMAT_R16G16B16A16_SINT: - return FORMAT_R16G16B16A16_SINT; - break; - case DXGI_FORMAT_R32G32_FLOAT: - return FORMAT_R32G32_FLOAT; - break; - case DXGI_FORMAT_R32G32_UINT: - return FORMAT_R32G32_UINT; - break; - case DXGI_FORMAT_R32G32_SINT: - return FORMAT_R32G32_SINT; - break; - case DXGI_FORMAT_R32G8X24_TYPELESS: - return FORMAT_R32G8X24_TYPELESS; - break; - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: - return FORMAT_D32_FLOAT_S8X24_UINT; - break; - case DXGI_FORMAT_R10G10B10A2_UNORM: - return FORMAT_R10G10B10A2_UNORM; - break; - case DXGI_FORMAT_R10G10B10A2_UINT: - return FORMAT_R10G10B10A2_UINT; - break; - case DXGI_FORMAT_R11G11B10_FLOAT: - return FORMAT_R11G11B10_FLOAT; - break; - case DXGI_FORMAT_R8G8B8A8_UNORM: - return FORMAT_R8G8B8A8_UNORM; - break; - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - return FORMAT_R8G8B8A8_UNORM_SRGB; - break; - case DXGI_FORMAT_R8G8B8A8_UINT: - return FORMAT_R8G8B8A8_UINT; - break; - case DXGI_FORMAT_R8G8B8A8_SNORM: - return FORMAT_R8G8B8A8_SNORM; - break; - case DXGI_FORMAT_R8G8B8A8_SINT: - return FORMAT_R8G8B8A8_SINT; - break; - case DXGI_FORMAT_R16G16_FLOAT: - return FORMAT_R16G16_FLOAT; - break; - case DXGI_FORMAT_R16G16_UNORM: - return FORMAT_R16G16_UNORM; - break; - case DXGI_FORMAT_R16G16_UINT: - return FORMAT_R16G16_UINT; - break; - case DXGI_FORMAT_R16G16_SNORM: - return FORMAT_R16G16_SNORM; - break; - case DXGI_FORMAT_R16G16_SINT: - return FORMAT_R16G16_SINT; - break; - case DXGI_FORMAT_R32_TYPELESS: - return FORMAT_R32_TYPELESS; - break; - case DXGI_FORMAT_D32_FLOAT: - return FORMAT_D32_FLOAT; - break; - case DXGI_FORMAT_R32_FLOAT: - return FORMAT_R32_FLOAT; - break; - case DXGI_FORMAT_R32_UINT: - return FORMAT_R32_UINT; - break; - case DXGI_FORMAT_R32_SINT: - return FORMAT_R32_SINT; - break; - case DXGI_FORMAT_R24G8_TYPELESS: - return FORMAT_R24G8_TYPELESS; - break; - case DXGI_FORMAT_D24_UNORM_S8_UINT: - return FORMAT_D24_UNORM_S8_UINT; - break; - case DXGI_FORMAT_R8G8_UNORM: - return FORMAT_R8G8_UNORM; - break; - case DXGI_FORMAT_R8G8_UINT: - return FORMAT_R8G8_UINT; - break; - case DXGI_FORMAT_R8G8_SNORM: - return FORMAT_R8G8_SNORM; - break; - case DXGI_FORMAT_R8G8_SINT: - return FORMAT_R8G8_SINT; - break; - case DXGI_FORMAT_R16_TYPELESS: - return FORMAT_R16_TYPELESS; - break; - case DXGI_FORMAT_R16_FLOAT: - return FORMAT_R16_FLOAT; - break; - case DXGI_FORMAT_D16_UNORM: - return FORMAT_D16_UNORM; - break; - case DXGI_FORMAT_R16_UNORM: - return FORMAT_R16_UNORM; - break; - case DXGI_FORMAT_R16_UINT: - return FORMAT_R16_UINT; - break; - case DXGI_FORMAT_R16_SNORM: - return FORMAT_R16_SNORM; - break; - case DXGI_FORMAT_R16_SINT: - return FORMAT_R16_SINT; - break; - case DXGI_FORMAT_R8_UNORM: - return FORMAT_R8_UNORM; - break; - case DXGI_FORMAT_R8_UINT: - return FORMAT_R8_UINT; - break; - case DXGI_FORMAT_R8_SNORM: - return FORMAT_R8_SNORM; - break; - case DXGI_FORMAT_R8_SINT: - return FORMAT_R8_SINT; - break; - case DXGI_FORMAT_BC1_UNORM: - return FORMAT_BC1_UNORM; - break; - case DXGI_FORMAT_BC1_UNORM_SRGB: - return FORMAT_BC1_UNORM_SRGB; - break; - case DXGI_FORMAT_BC2_UNORM: - return FORMAT_BC2_UNORM; - break; - case DXGI_FORMAT_BC2_UNORM_SRGB: - return FORMAT_BC2_UNORM_SRGB; - break; - case DXGI_FORMAT_BC3_UNORM: - return FORMAT_BC3_UNORM; - break; - case DXGI_FORMAT_BC3_UNORM_SRGB: - return FORMAT_BC3_UNORM_SRGB; - break; - case DXGI_FORMAT_BC4_UNORM: - return FORMAT_BC4_UNORM; - break; - case DXGI_FORMAT_BC4_SNORM: - return FORMAT_BC4_SNORM; - break; - case DXGI_FORMAT_BC5_UNORM: - return FORMAT_BC5_UNORM; - break; - case DXGI_FORMAT_BC5_SNORM: - return FORMAT_BC5_SNORM; - break; - case DXGI_FORMAT_B8G8R8A8_UNORM: - return FORMAT_B8G8R8A8_UNORM; - break; - case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: - return FORMAT_B8G8R8A8_UNORM_SRGB; - break; - case DXGI_FORMAT_BC6H_UF16: - return FORMAT_BC6H_UF16; - break; - case DXGI_FORMAT_BC6H_SF16: - return FORMAT_BC6H_SF16; - break; - case DXGI_FORMAT_BC7_UNORM: - return FORMAT_BC7_UNORM; - break; - case DXGI_FORMAT_BC7_UNORM_SRGB: - return FORMAT_BC7_UNORM_SRGB; - break; - } - return FORMAT_UNKNOWN; - } - constexpr USAGE _ConvertUsage_Inv(D3D11_USAGE value) - { - switch (value) - { - case D3D11_USAGE_DEFAULT: - return USAGE_DEFAULT; - break; - case D3D11_USAGE_IMMUTABLE: - return USAGE_IMMUTABLE; - break; - case D3D11_USAGE_DYNAMIC: - return USAGE_DYNAMIC; - break; - case D3D11_USAGE_STAGING: - return USAGE_STAGING; - break; - default: - break; - } - return USAGE_DEFAULT; - } - - inline TextureDesc _ConvertTextureDesc_Inv(const D3D11_TEXTURE1D_DESC* pDesc) - { - TextureDesc desc; - desc.Width = pDesc->Width; - desc.MipLevels = pDesc->MipLevels; - desc.ArraySize = pDesc->ArraySize; - desc.Format = _ConvertFormat_Inv(pDesc->Format); - desc.Usage = _ConvertUsage_Inv(pDesc->Usage); - desc.BindFlags = _ParseBindFlags_Inv(pDesc->BindFlags); - desc.CPUAccessFlags = _ParseCPUAccessFlags_Inv(pDesc->CPUAccessFlags); - desc.MiscFlags = _ParseResourceMiscFlags_Inv(pDesc->MiscFlags); - - return desc; - } - inline TextureDesc _ConvertTextureDesc_Inv(const D3D11_TEXTURE2D_DESC* pDesc) - { - TextureDesc desc; - desc.Width = pDesc->Width; - desc.Height = pDesc->Height; - desc.MipLevels = pDesc->MipLevels; - desc.ArraySize = pDesc->ArraySize; - desc.Format = _ConvertFormat_Inv(pDesc->Format); - desc.SampleCount = pDesc->SampleDesc.Count; - desc.Usage = _ConvertUsage_Inv(pDesc->Usage); - desc.BindFlags = _ParseBindFlags_Inv(pDesc->BindFlags); - desc.CPUAccessFlags = _ParseCPUAccessFlags_Inv(pDesc->CPUAccessFlags); - desc.MiscFlags = _ParseResourceMiscFlags_Inv(pDesc->MiscFlags); - - return desc; - } - inline TextureDesc _ConvertTextureDesc_Inv(const D3D11_TEXTURE3D_DESC* pDesc) - { - TextureDesc desc; - desc.Width = pDesc->Width; - desc.Height = pDesc->Height; - desc.Depth = pDesc->Depth; - desc.MipLevels = pDesc->MipLevels; - desc.Format = _ConvertFormat_Inv(pDesc->Format); - desc.Usage = _ConvertUsage_Inv(pDesc->Usage); - desc.BindFlags = _ParseBindFlags_Inv(pDesc->BindFlags); - desc.CPUAccessFlags = _ParseCPUAccessFlags_Inv(pDesc->CPUAccessFlags); - desc.MiscFlags = _ParseResourceMiscFlags_Inv(pDesc->MiscFlags); - - return desc; - } - - - // Local Helpers: - const void* const __nullBlob[128] = {}; // this is initialized to nullptrs and used to unbind resources! - - - struct Resource_DX11 - { - ComPtr resource; - ComPtr srv; - ComPtr uav; - std::vector> subresources_srv; - std::vector> subresources_uav; - }; - struct Texture_DX11 : public Resource_DX11 - { - ComPtr rtv; - ComPtr dsv; - std::vector> subresources_rtv; - std::vector> subresources_dsv; - }; - struct VertexShader_DX11 - { - ComPtr resource; - std::vector shadercode; - }; - struct HullShader_DX11 - { - ComPtr resource; - }; - struct DomainShader_DX11 - { - ComPtr resource; - }; - struct GeometryShader_DX11 - { - ComPtr resource; - }; - struct PixelShader_DX11 - { - ComPtr resource; - }; - struct ComputeShader_DX11 - { - ComPtr resource; - }; - struct PipelineState_DX11 - { - ComPtr bs; - ComPtr dss; - ComPtr rs; - ComPtr il; - }; - struct Sampler_DX11 - { - ComPtr resource; - }; - struct QueryHeap_DX11 - { - std::vector> resources; - }; - struct SwapChain_DX11 - { - Microsoft::WRL::ComPtr swapChain; - Microsoft::WRL::ComPtr renderTargetView; - Microsoft::WRL::ComPtr backBuffer; - }; - - Resource_DX11* to_internal(const GPUResource* param) - { - return static_cast(param->internal_state.get()); - } - Resource_DX11* to_internal(const GPUBuffer* param) - { - return static_cast(param->internal_state.get()); - } - Texture_DX11* to_internal(const Texture* param) - { - return static_cast(param->internal_state.get()); - } - PipelineState_DX11* to_internal(const PipelineState* param) - { - return static_cast(param->internal_state.get()); - } - Sampler_DX11* to_internal(const Sampler* param) - { - return static_cast(param->internal_state.get()); - } - QueryHeap_DX11* to_internal(const GPUQueryHeap* param) - { - return static_cast(param->internal_state.get()); - } - SwapChain_DX11* to_internal(const SwapChain* param) - { - return static_cast(param->internal_state.get()); - } -} -using namespace DX11_Internal; - -void GraphicsDevice_DX11::pso_validate(CommandList cmd) -{ - if (!dirty_pso[cmd]) - return; - - const PipelineState* pso = active_pso[cmd]; - const PipelineStateDesc& desc = pso != nullptr ? pso->GetDesc() : PipelineStateDesc(); - - auto internal_state = to_internal(pso); - - ID3D11VertexShader* vs = desc.vs == nullptr ? nullptr : static_cast(desc.vs->internal_state.get())->resource.Get(); - if (vs != prev_vs[cmd]) - { - deviceContexts[cmd]->VSSetShader(vs, nullptr, 0); - prev_vs[cmd] = vs; - - if (desc.vs != nullptr) - { - for (auto& x : desc.vs->auto_samplers) - { - BindSampler(VS, &x.sampler, x.slot, cmd); - } - } - } - ID3D11PixelShader* ps = desc.ps == nullptr ? nullptr : static_cast(desc.ps->internal_state.get())->resource.Get(); - if (ps != prev_ps[cmd]) - { - deviceContexts[cmd]->PSSetShader(ps, nullptr, 0); - prev_ps[cmd] = ps; - - if (desc.ps != nullptr) - { - for (auto& x : desc.ps->auto_samplers) - { - BindSampler(PS, &x.sampler, x.slot, cmd); - } - } - } - ID3D11HullShader* hs = desc.hs == nullptr ? nullptr : static_cast(desc.hs->internal_state.get())->resource.Get(); - if (hs != prev_hs[cmd]) - { - deviceContexts[cmd]->HSSetShader(hs, nullptr, 0); - prev_hs[cmd] = hs; - - if (desc.hs != nullptr) - { - for (auto& x : desc.hs->auto_samplers) - { - BindSampler(HS, &x.sampler, x.slot, cmd); - } - } - } - ID3D11DomainShader* ds = desc.ds == nullptr ? nullptr : static_cast(desc.ds->internal_state.get())->resource.Get(); - if (ds != prev_ds[cmd]) - { - deviceContexts[cmd]->DSSetShader(ds, nullptr, 0); - prev_ds[cmd] = ds; - - if (desc.ds != nullptr) - { - for (auto& x : desc.ds->auto_samplers) - { - BindSampler(DS, &x.sampler, x.slot, cmd); - } - } - } - ID3D11GeometryShader* gs = desc.gs == nullptr ? nullptr : static_cast(desc.gs->internal_state.get())->resource.Get(); - if (gs != prev_gs[cmd]) - { - deviceContexts[cmd]->GSSetShader(gs, nullptr, 0); - prev_gs[cmd] = gs; - - if (desc.gs != nullptr) - { - for (auto& x : desc.gs->auto_samplers) - { - BindSampler(GS, &x.sampler, x.slot, cmd); - } - } - } - - ID3D11BlendState* bs = desc.bs == nullptr ? nullptr : internal_state->bs.Get(); - if (desc.bs != prev_bs[cmd] || desc.sampleMask != prev_samplemask[cmd] || - blendFactor[cmd].x != prev_blendfactor[cmd].x || - blendFactor[cmd].y != prev_blendfactor[cmd].y || - blendFactor[cmd].z != prev_blendfactor[cmd].z || - blendFactor[cmd].w != prev_blendfactor[cmd].w - ) - { - const float fact[4] = { blendFactor[cmd].x, blendFactor[cmd].y, blendFactor[cmd].z, blendFactor[cmd].w }; - deviceContexts[cmd]->OMSetBlendState(bs, fact, desc.sampleMask); - prev_bs[cmd] = desc.bs; - prev_blendfactor[cmd] = blendFactor[cmd]; - prev_samplemask[cmd] = desc.sampleMask; - } - - ID3D11RasterizerState* rs = desc.rs == nullptr ? nullptr : internal_state->rs.Get(); - if (desc.rs != prev_rs[cmd]) - { - deviceContexts[cmd]->RSSetState(rs); - prev_rs[cmd] = desc.rs; - } - - ID3D11DepthStencilState* dss = desc.dss == nullptr ? nullptr : internal_state->dss.Get(); - if (desc.dss != prev_dss[cmd] || stencilRef[cmd] != prev_stencilRef[cmd]) - { - deviceContexts[cmd]->OMSetDepthStencilState(dss, stencilRef[cmd]); - prev_dss[cmd] = desc.dss; - prev_stencilRef[cmd] = stencilRef[cmd]; - } - - ID3D11InputLayout* il = desc.il == nullptr ? nullptr : internal_state->il.Get(); - if (desc.il != prev_il[cmd]) - { - deviceContexts[cmd]->IASetInputLayout(il); - prev_il[cmd] = desc.il; - } - - if (prev_pt[cmd] != desc.pt) - { - D3D11_PRIMITIVE_TOPOLOGY d3dType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - switch (desc.pt) - { - case TRIANGLELIST: - d3dType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; - break; - case TRIANGLESTRIP: - d3dType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; - break; - case POINTLIST: - d3dType = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; - break; - case LINELIST: - d3dType = D3D11_PRIMITIVE_TOPOLOGY_LINELIST; - break; - case LINESTRIP: - d3dType = D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP; - break; - case PATCHLIST: - d3dType = D3D11_PRIMITIVE_TOPOLOGY_3_CONTROL_POINT_PATCHLIST; - break; - default: - d3dType = D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; - break; - }; - deviceContexts[cmd]->IASetPrimitiveTopology(d3dType); - - prev_pt[cmd] = desc.pt; - } -} - -// Engine functions -GraphicsDevice_DX11::GraphicsDevice_DX11(bool debuglayer) -{ - DEBUGDEVICE = debuglayer; - -#ifndef PLATFORM_UWP - HMODULE dx11 = LoadLibraryEx(L"d3d11.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32); - - D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(dx11, "D3D11CreateDevice"); - assert(D3D11CreateDevice != nullptr); -#endif // PLATFORM_UWP - - HRESULT hr = E_FAIL; - - uint32_t createDeviceFlags = 0; - - if (debuglayer) - { - createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; - } - - D3D_DRIVER_TYPE driverTypes[] = - { - D3D_DRIVER_TYPE_HARDWARE, - D3D_DRIVER_TYPE_WARP, - D3D_DRIVER_TYPE_REFERENCE, - }; - uint32_t numDriverTypes = arraysize(driverTypes); - - D3D_FEATURE_LEVEL featureLevels[] = - { - D3D_FEATURE_LEVEL_11_1, - D3D_FEATURE_LEVEL_11_0, - }; - uint32_t numFeatureLevels = arraysize(featureLevels); - - for (uint32_t driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++) - { - driverType = driverTypes[driverTypeIndex]; - hr = D3D11CreateDevice(nullptr, driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels, D3D11_SDK_VERSION, &device - , &featureLevel, &immediateContext); - - if (SUCCEEDED(hr)) - break; - } - if (FAILED(hr)) - { - std::stringstream ss(""); - ss << "Failed to create the graphics device! ERROR: " << std::hex << hr; - wiHelper::messageBox(ss.str(), "Error!"); - wiPlatform::Exit(); - } - - ComPtr pDXGIDevice; - hr = device.As(&pDXGIDevice); - assert(SUCCEEDED(hr)); - - // Ensure that DXGI does not queue more than one frame at a time. This both reduces latency and - // ensures that the application will only render after each VSync, minimizing power consumption. - hr = pDXGIDevice->SetMaximumFrameLatency(1); - assert(SUCCEEDED(hr)); - - ComPtr DXGIAdapter; - hr = pDXGIDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&DXGIAdapter); - assert(SUCCEEDED(hr)); - - hr = DXGIAdapter->GetParent(__uuidof(IDXGIFactory2), (void**)&DXGIFactory); - assert(SUCCEEDED(hr)); - - if (debuglayer) - { - ID3D11Debug* d3dDebug = nullptr; - if (SUCCEEDED(device->QueryInterface(__uuidof(ID3D11Debug), (void**)&d3dDebug))) - { - ID3D11InfoQueue* d3dInfoQueue = nullptr; - if (SUCCEEDED(d3dDebug->QueryInterface(__uuidof(ID3D11InfoQueue), (void**)&d3dInfoQueue))) - { - d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true); - d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true); - - D3D11_MESSAGE_ID hide[] = - { - D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS, - // Add more message IDs here as needed - }; - - D3D11_INFO_QUEUE_FILTER filter = {}; - filter.DenyList.NumIDs = _countof(hide); - filter.DenyList.pIDList = hide; - d3dInfoQueue->AddStorageFilterEntries(&filter); - d3dInfoQueue->Release(); - } - d3dDebug->Release(); - } - } - - D3D11_QUERY_DESC queryDesc = {}; - queryDesc.Query = D3D11_QUERY_TIMESTAMP_DISJOINT; - for (auto& x : disjointQueries) - { - hr = device->CreateQuery(&queryDesc, &x); - assert(SUCCEEDED(hr)); - } - - D3D_FEATURE_LEVEL aquiredFeatureLevel = device->GetFeatureLevel(); - if (aquiredFeatureLevel >= D3D_FEATURE_LEVEL_11_0) - { - capabilities |= GRAPHICSDEVICE_CAPABILITY_TESSELLATION; - } - - //D3D11_FEATURE_DATA_D3D11_OPTIONS features_0; - //hr = device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &features_0, sizeof(features_0)); - - //D3D11_FEATURE_DATA_D3D11_OPTIONS1 features_1; - //hr = device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS1, &features_1, sizeof(features_1)); - - D3D11_FEATURE_DATA_D3D11_OPTIONS2 features_2; - hr = device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS2, &features_2, sizeof(features_2)); - if (features_2.ConservativeRasterizationTier >= D3D11_CONSERVATIVE_RASTERIZATION_TIER_1) - { - capabilities |= GRAPHICSDEVICE_CAPABILITY_CONSERVATIVE_RASTERIZATION; - } - if (features_2.ROVsSupported == TRUE) - { - capabilities |= GRAPHICSDEVICE_CAPABILITY_RASTERIZER_ORDERED_VIEWS; - } - - if (features_2.TypedUAVLoadAdditionalFormats) - { - // More info about UAV format load support: https://docs.microsoft.com/en-us/windows/win32/direct3d12/typed-unordered-access-view-loads - capabilities |= GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_COMMON; - - D3D11_FEATURE_DATA_FORMAT_SUPPORT2 FormatSupport = {}; - FormatSupport.InFormat = DXGI_FORMAT_R11G11B10_FLOAT; - hr = device->CheckFeatureSupport(D3D11_FEATURE_FORMAT_SUPPORT2, &FormatSupport, sizeof(FormatSupport)); - if (SUCCEEDED(hr) && (FormatSupport.OutFormatSupport2 & D3D11_FORMAT_SUPPORT2_UAV_TYPED_LOAD) != 0) - { - capabilities |= GRAPHICSDEVICE_CAPABILITY_UAV_LOAD_FORMAT_R11G11B10_FLOAT; - } - } - - D3D11_FEATURE_DATA_D3D11_OPTIONS3 features_3; - hr = device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &features_3, sizeof(features_3)); - if (features_3.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer == TRUE) - { - capabilities |= GRAPHICSDEVICE_CAPABILITY_RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS; - } - - CreateBackBufferResources(); - - emptyresource = std::make_shared(); - - wiBackLog::post("Created GraphicsDevice_DX11"); -} - -void GraphicsDevice_DX11::CreateBackBufferResources() -{ - //HRESULT hr; - - //hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), &backBuffer); - //if (FAILED(hr)) { - // wiHelper::messageBox("BackBuffer creation Failed!", "Error!"); - // wiPlatform::Exit(); - //} - - //hr = device->CreateRenderTargetView(backBuffer.Get(), nullptr, &renderTargetView); - //if (FAILED(hr)) { - // wiHelper::messageBox("Main Rendertarget creation Failed!", "Error!"); - // wiPlatform::Exit(); - //} -} - -bool GraphicsDevice_DX11::CreateSwapChain(const SwapChainDesc* pDesc, wiPlatform::window_type window, SwapChain* swapChain) const -{ - auto internal_state = std::static_pointer_cast(swapChain->internal_state); - if (swapChain->internal_state == nullptr) - { - internal_state = std::make_shared(); - } - swapChain->internal_state = internal_state; - swapChain->desc = *pDesc; - HRESULT hr; - - if (internal_state->swapChain == nullptr) - { - // Create swapchain: - DXGI_SWAP_CHAIN_DESC1 sd = {}; - sd.Width = pDesc->width; - sd.Height = pDesc->height; - sd.Format = _ConvertFormat(pDesc->format); - sd.Stereo = false; - sd.SampleDesc.Count = 1; - sd.SampleDesc.Quality = 0; - sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - sd.BufferCount = pDesc->buffercount; - sd.Flags = 0; - sd.AlphaMode = DXGI_ALPHA_MODE_IGNORE; - sd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - -#ifdef PLATFORM_UWP - sd.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH; - - hr = DXGIFactory->CreateSwapChainForCoreWindow( - device.Get(), - static_cast(winrt::get_abi(*window)), - &sd, - nullptr, - &internal_state->swapChain - ); -#else - sd.Scaling = DXGI_SCALING_STRETCH; - - DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreenDesc; - fullscreenDesc.RefreshRate.Numerator = 60; - fullscreenDesc.RefreshRate.Denominator = 1; - fullscreenDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; // needs to be unspecified for correct fullscreen scaling! - fullscreenDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_PROGRESSIVE; - fullscreenDesc.Windowed = !pDesc->fullscreen; - hr = DXGIFactory->CreateSwapChainForHwnd( - device.Get(), - window, - &sd, - &fullscreenDesc, - nullptr, - &internal_state->swapChain - ); -#endif - - if (FAILED(hr)) - { - return false; - } - } - else - { - // Resize swapchain: - internal_state->backBuffer.Reset(); - internal_state->renderTargetView.Reset(); - - hr = internal_state->swapChain->ResizeBuffers( - pDesc->buffercount, - pDesc->width, - pDesc->height, - _ConvertFormat(pDesc->format), - 0 - ); - assert(SUCCEEDED(hr)); - } - - hr = internal_state->swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), &internal_state->backBuffer); - if (FAILED(hr)) - { - return false; - } - - hr = device->CreateRenderTargetView(internal_state->backBuffer.Get(), nullptr, &internal_state->renderTargetView); - if (FAILED(hr)) - { - return false; - } - - return true; -} -bool GraphicsDevice_DX11::CreateBuffer(const GPUBufferDesc *pDesc, const SubresourceData* pInitialData, GPUBuffer *pBuffer) const -{ - auto internal_state = std::make_shared(); - pBuffer->internal_state = internal_state; - pBuffer->type = GPUResource::GPU_RESOURCE_TYPE::BUFFER; - - D3D11_BUFFER_DESC desc; - desc.ByteWidth = pDesc->ByteWidth; - desc.Usage = _ConvertUsage(pDesc->Usage); - desc.BindFlags = _ParseBindFlags(pDesc->BindFlags); - desc.CPUAccessFlags = _ParseCPUAccessFlags(pDesc->CPUAccessFlags); - desc.MiscFlags = _ParseResourceMiscFlags(pDesc->MiscFlags); - desc.StructureByteStride = pDesc->StructureByteStride; - - D3D11_SUBRESOURCE_DATA data; - if (pInitialData != nullptr) - { - data = _ConvertSubresourceData(*pInitialData); - } - - pBuffer->desc = *pDesc; - HRESULT hr = device->CreateBuffer(&desc, pInitialData == nullptr ? nullptr : &data, (ID3D11Buffer**)internal_state->resource.ReleaseAndGetAddressOf()); - assert(SUCCEEDED(hr) && "GPUBuffer creation failed!"); - - if (SUCCEEDED(hr)) - { - // Create resource views if needed - if (pDesc->BindFlags & BIND_SHADER_RESOURCE) - { - CreateSubresource(pBuffer, SRV, 0); - } - if (pDesc->BindFlags & BIND_UNORDERED_ACCESS) - { - CreateSubresource(pBuffer, UAV, 0); - } - } - - return SUCCEEDED(hr); -} -bool GraphicsDevice_DX11::CreateTexture(const TextureDesc* pDesc, const SubresourceData *pInitialData, Texture *pTexture) const -{ - auto internal_state = std::make_shared(); - pTexture->internal_state = internal_state; - pTexture->type = GPUResource::GPU_RESOURCE_TYPE::TEXTURE; - - pTexture->desc = *pDesc; - - std::vector data; - if (pInitialData != nullptr) - { - uint32_t dataCount = pDesc->ArraySize * std::max(1u, pDesc->MipLevels); - data.resize(dataCount); - for (uint32_t slice = 0; slice < dataCount; ++slice) - { - data[slice] = _ConvertSubresourceData(pInitialData[slice]); - } - } - - HRESULT hr = S_OK; - - switch (pTexture->desc.type) - { - case TextureDesc::TEXTURE_1D: - { - D3D11_TEXTURE1D_DESC desc = _ConvertTextureDesc1D(&pTexture->desc); - hr = device->CreateTexture1D(&desc, data.data(), (ID3D11Texture1D**)internal_state->resource.ReleaseAndGetAddressOf()); - } - break; - case TextureDesc::TEXTURE_2D: - { - D3D11_TEXTURE2D_DESC desc = _ConvertTextureDesc2D(&pTexture->desc); - hr = device->CreateTexture2D(&desc, data.data(), (ID3D11Texture2D**)internal_state->resource.ReleaseAndGetAddressOf()); - } - break; - case TextureDesc::TEXTURE_3D: - { - D3D11_TEXTURE3D_DESC desc = _ConvertTextureDesc3D(&pTexture->desc); - hr = device->CreateTexture3D(&desc, data.data(), (ID3D11Texture3D**)internal_state->resource.ReleaseAndGetAddressOf()); - } - break; - default: - assert(0); - break; - } - - assert(SUCCEEDED(hr)); - if (FAILED(hr)) - return SUCCEEDED(hr); - - if (pTexture->desc.MipLevels == 0) - { - pTexture->desc.MipLevels = (uint32_t)log2(std::max(pTexture->desc.Width, pTexture->desc.Height)) + 1; - } - - if (pTexture->desc.BindFlags & BIND_RENDER_TARGET) - { - CreateSubresource(pTexture, RTV, 0, -1, 0, -1); - } - if (pTexture->desc.BindFlags & BIND_DEPTH_STENCIL) - { - CreateSubresource(pTexture, DSV, 0, -1, 0, -1); - } - if (pTexture->desc.BindFlags & BIND_SHADER_RESOURCE) - { - CreateSubresource(pTexture, SRV, 0, -1, 0, -1); - } - if (pTexture->desc.BindFlags & BIND_UNORDERED_ACCESS) - { - CreateSubresource(pTexture, UAV, 0, -1, 0, -1); - } - - return SUCCEEDED(hr); -} -bool GraphicsDevice_DX11::CreateShader(SHADERSTAGE stage, const void *pShaderBytecode, size_t BytecodeLength, Shader *pShader) const -{ - pShader->stage = stage; - - HRESULT hr = E_FAIL; - - switch (stage) - { - case wiGraphics::VS: - { - auto internal_state = std::make_shared(); - pShader->internal_state = internal_state; - internal_state->shadercode.resize(BytecodeLength); - std::memcpy(internal_state->shadercode.data(), pShaderBytecode, BytecodeLength); - hr = device->CreateVertexShader(pShaderBytecode, BytecodeLength, nullptr, &internal_state->resource); - } - break; - case wiGraphics::HS: - { - auto internal_state = std::make_shared(); - pShader->internal_state = internal_state; - hr = device->CreateHullShader(pShaderBytecode, BytecodeLength, nullptr, &internal_state->resource); - } - break; - case wiGraphics::DS: - { - auto internal_state = std::make_shared(); - pShader->internal_state = internal_state; - hr = device->CreateDomainShader(pShaderBytecode, BytecodeLength, nullptr, &internal_state->resource); - } - break; - case wiGraphics::GS: - { - auto internal_state = std::make_shared(); - pShader->internal_state = internal_state; - hr = device->CreateGeometryShader(pShaderBytecode, BytecodeLength, nullptr, &internal_state->resource); - } - break; - case wiGraphics::PS: - { - auto internal_state = std::make_shared(); - pShader->internal_state = internal_state; - hr = device->CreatePixelShader(pShaderBytecode, BytecodeLength, nullptr, &internal_state->resource); - } - break; - case wiGraphics::CS: - { - auto internal_state = std::make_shared(); - pShader->internal_state = internal_state; - hr = device->CreateComputeShader(pShaderBytecode, BytecodeLength, nullptr, &internal_state->resource); - } - break; - } - - assert(SUCCEEDED(hr)); - - return SUCCEEDED(hr); -} -bool GraphicsDevice_DX11::CreateSampler(const SamplerDesc *pSamplerDesc, Sampler *pSamplerState) const -{ - auto internal_state = std::make_shared(); - pSamplerState->internal_state = internal_state; - - D3D11_SAMPLER_DESC desc; - desc.Filter = _ConvertFilter(pSamplerDesc->Filter); - desc.AddressU = _ConvertTextureAddressMode(pSamplerDesc->AddressU); - desc.AddressV = _ConvertTextureAddressMode(pSamplerDesc->AddressV); - desc.AddressW = _ConvertTextureAddressMode(pSamplerDesc->AddressW); - desc.MipLODBias = pSamplerDesc->MipLODBias; - desc.MaxAnisotropy = pSamplerDesc->MaxAnisotropy; - desc.ComparisonFunc = _ConvertComparisonFunc(pSamplerDesc->ComparisonFunc); - switch (pSamplerDesc->BorderColor) - { - case SAMPLER_BORDER_COLOR_OPAQUE_BLACK: - desc.BorderColor[0] = 0.0f; - desc.BorderColor[1] = 0.0f; - desc.BorderColor[2] = 0.0f; - desc.BorderColor[3] = 1.0f; - break; - - case SAMPLER_BORDER_COLOR_OPAQUE_WHITE: - desc.BorderColor[0] = 1.0f; - desc.BorderColor[1] = 1.0f; - desc.BorderColor[2] = 1.0f; - desc.BorderColor[3] = 1.0f; - break; - - default: - desc.BorderColor[0] = 0.0f; - desc.BorderColor[1] = 0.0f; - desc.BorderColor[2] = 0.0f; - desc.BorderColor[3] = 0.0f; - break; - } - desc.MinLOD = pSamplerDesc->MinLOD; - desc.MaxLOD = pSamplerDesc->MaxLOD; - - pSamplerState->desc = *pSamplerDesc; - HRESULT hr = device->CreateSamplerState(&desc, &internal_state->resource); - assert(SUCCEEDED(hr)); - - return SUCCEEDED(hr); -} -bool GraphicsDevice_DX11::CreateQueryHeap(const GPUQueryHeapDesc* pDesc, GPUQueryHeap* pQueryHeap) const -{ - auto internal_state = std::make_shared(); - pQueryHeap->internal_state = internal_state; - - pQueryHeap->desc = *pDesc; - - D3D11_QUERY_DESC desc; - desc.MiscFlags = 0; - desc.Query = D3D11_QUERY_EVENT; - switch (pDesc->type) - { - default: - case GPU_QUERY_TYPE_TIMESTAMP: - desc.Query = D3D11_QUERY_TIMESTAMP; - break; - case GPU_QUERY_TYPE_OCCLUSION: - desc.Query = D3D11_QUERY_OCCLUSION; - break; - case GPU_QUERY_TYPE_OCCLUSION_BINARY: - desc.Query = D3D11_QUERY_OCCLUSION_PREDICATE; - break; - } - - internal_state->resources.resize(pDesc->queryCount); - for (uint32_t i = 0; i < pDesc->queryCount; ++i) - { - HRESULT hr = device->CreateQuery(&desc, &internal_state->resources[i]); - if (!SUCCEEDED(hr)) - { - return false; - } - } - - return true; -} -bool GraphicsDevice_DX11::CreatePipelineState(const PipelineStateDesc* pDesc, PipelineState* pso) const -{ - auto internal_state = std::make_shared(); - pso->internal_state = internal_state; - - pso->desc = *pDesc; - - HRESULT hr; - - - - if (pDesc->il != nullptr) - { - std::vector desc(pDesc->il->elements.size()); - for (size_t i = 0; i < desc.size(); ++i) - { - desc[i].SemanticName = pDesc->il->elements[i].SemanticName.c_str(); - desc[i].SemanticIndex = pDesc->il->elements[i].SemanticIndex; - desc[i].Format = _ConvertFormat(pDesc->il->elements[i].Format); - desc[i].InputSlot = pDesc->il->elements[i].InputSlot; - desc[i].AlignedByteOffset = pDesc->il->elements[i].AlignedByteOffset; - if (desc[i].AlignedByteOffset == InputLayout::APPEND_ALIGNED_ELEMENT) - desc[i].AlignedByteOffset = D3D11_APPEND_ALIGNED_ELEMENT; - desc[i].InputSlotClass = _ConvertInputClassification(pDesc->il->elements[i].InputSlotClass); - desc[i].InstanceDataStepRate = 0; - if (desc[i].InputSlotClass == D3D11_INPUT_PER_INSTANCE_DATA) - { - desc[i].InstanceDataStepRate = 1; - } - } - - assert(pDesc->vs != nullptr); - auto vs_internal = static_cast(pDesc->vs->internal_state.get()); - hr = device->CreateInputLayout(desc.data(), (UINT)desc.size(), vs_internal->shadercode.data(), vs_internal->shadercode.size(), &internal_state->il); - assert(SUCCEEDED(hr)); - } - - - - if (pDesc->bs != nullptr) - { - D3D11_BLEND_DESC desc; - desc.AlphaToCoverageEnable = pDesc->bs->AlphaToCoverageEnable; - desc.IndependentBlendEnable = pDesc->bs->IndependentBlendEnable; - for (int i = 0; i < 8; ++i) - { - desc.RenderTarget[i].BlendEnable = pDesc->bs->RenderTarget[i].BlendEnable; - desc.RenderTarget[i].SrcBlend = _ConvertBlend(pDesc->bs->RenderTarget[i].SrcBlend); - desc.RenderTarget[i].DestBlend = _ConvertBlend(pDesc->bs->RenderTarget[i].DestBlend); - desc.RenderTarget[i].BlendOp = _ConvertBlendOp(pDesc->bs->RenderTarget[i].BlendOp); - desc.RenderTarget[i].SrcBlendAlpha = _ConvertBlend(pDesc->bs->RenderTarget[i].SrcBlendAlpha); - desc.RenderTarget[i].DestBlendAlpha = _ConvertBlend(pDesc->bs->RenderTarget[i].DestBlendAlpha); - desc.RenderTarget[i].BlendOpAlpha = _ConvertBlendOp(pDesc->bs->RenderTarget[i].BlendOpAlpha); - desc.RenderTarget[i].RenderTargetWriteMask = _ParseColorWriteMask(pDesc->bs->RenderTarget[i].RenderTargetWriteMask); - } - - hr = device->CreateBlendState(&desc, &internal_state->bs); - assert(SUCCEEDED(hr)); - } - - - if (pDesc->dss != nullptr) - { - D3D11_DEPTH_STENCIL_DESC desc; - desc.DepthEnable = pDesc->dss->DepthEnable; - desc.DepthWriteMask = _ConvertDepthWriteMask(pDesc->dss->DepthWriteMask); - desc.DepthFunc = _ConvertComparisonFunc(pDesc->dss->DepthFunc); - desc.StencilEnable = pDesc->dss->StencilEnable; - desc.StencilReadMask = pDesc->dss->StencilReadMask; - desc.StencilWriteMask = pDesc->dss->StencilWriteMask; - desc.FrontFace.StencilDepthFailOp = _ConvertStencilOp(pDesc->dss->FrontFace.StencilDepthFailOp); - desc.FrontFace.StencilFailOp = _ConvertStencilOp(pDesc->dss->FrontFace.StencilFailOp); - desc.FrontFace.StencilFunc = _ConvertComparisonFunc(pDesc->dss->FrontFace.StencilFunc); - desc.FrontFace.StencilPassOp = _ConvertStencilOp(pDesc->dss->FrontFace.StencilPassOp); - desc.BackFace.StencilDepthFailOp = _ConvertStencilOp(pDesc->dss->BackFace.StencilDepthFailOp); - desc.BackFace.StencilFailOp = _ConvertStencilOp(pDesc->dss->BackFace.StencilFailOp); - desc.BackFace.StencilFunc = _ConvertComparisonFunc(pDesc->dss->BackFace.StencilFunc); - desc.BackFace.StencilPassOp = _ConvertStencilOp(pDesc->dss->BackFace.StencilPassOp); - - hr = device->CreateDepthStencilState(&desc, &internal_state->dss); - assert(SUCCEEDED(hr)); - } - - - if (pDesc->rs != nullptr) - { - D3D11_RASTERIZER_DESC desc; - desc.FillMode = _ConvertFillMode(pDesc->rs->FillMode); - desc.CullMode = _ConvertCullMode(pDesc->rs->CullMode); - desc.FrontCounterClockwise = pDesc->rs->FrontCounterClockwise; - desc.DepthBias = pDesc->rs->DepthBias; - desc.DepthBiasClamp = pDesc->rs->DepthBiasClamp; - desc.SlopeScaledDepthBias = pDesc->rs->SlopeScaledDepthBias; - desc.DepthClipEnable = pDesc->rs->DepthClipEnable; - desc.ScissorEnable = true; - desc.MultisampleEnable = pDesc->rs->MultisampleEnable; - desc.AntialiasedLineEnable = pDesc->rs->AntialiasedLineEnable; - - - if (CheckCapability(GRAPHICSDEVICE_CAPABILITY_CONSERVATIVE_RASTERIZATION) && pDesc->rs->ConservativeRasterizationEnable == TRUE) - { - ComPtr device3; - if (SUCCEEDED(device.As(&device3))) - { - D3D11_RASTERIZER_DESC2 desc2; - desc2.FillMode = desc.FillMode; - desc2.CullMode = desc.CullMode; - desc2.FrontCounterClockwise = desc.FrontCounterClockwise; - desc2.DepthBias = desc.DepthBias; - desc2.DepthBiasClamp = desc.DepthBiasClamp; - desc2.SlopeScaledDepthBias = desc.SlopeScaledDepthBias; - desc2.DepthClipEnable = desc.DepthClipEnable; - desc2.ScissorEnable = desc.ScissorEnable; - desc2.MultisampleEnable = desc.MultisampleEnable; - desc2.AntialiasedLineEnable = desc.AntialiasedLineEnable; - desc2.ConservativeRaster = D3D11_CONSERVATIVE_RASTERIZATION_MODE_ON; - desc2.ForcedSampleCount = pDesc->rs->ForcedSampleCount; - - ComPtr rasterizer2; - hr = device3->CreateRasterizerState2(&desc2, &rasterizer2); - assert(SUCCEEDED(hr)); - - internal_state->rs = rasterizer2; - } - } - else if (pDesc->rs->ForcedSampleCount > 0) - { - ComPtr device1; - if (SUCCEEDED(device.As(&device1))) - { - D3D11_RASTERIZER_DESC1 desc1; - desc1.FillMode = desc.FillMode; - desc1.CullMode = desc.CullMode; - desc1.FrontCounterClockwise = desc.FrontCounterClockwise; - desc1.DepthBias = desc.DepthBias; - desc1.DepthBiasClamp = desc.DepthBiasClamp; - desc1.SlopeScaledDepthBias = desc.SlopeScaledDepthBias; - desc1.DepthClipEnable = desc.DepthClipEnable; - desc1.ScissorEnable = desc.ScissorEnable; - desc1.MultisampleEnable = desc.MultisampleEnable; - desc1.AntialiasedLineEnable = desc.AntialiasedLineEnable; - desc1.ForcedSampleCount = pDesc->rs->ForcedSampleCount; - - ComPtr rasterizer1; - hr = device1->CreateRasterizerState1(&desc1, &rasterizer1); - assert(SUCCEEDED(hr)); - - internal_state->rs = rasterizer1; - } - } - - hr = device->CreateRasterizerState(&desc, &internal_state->rs); - assert(SUCCEEDED(hr)); - } - - return true; -} -bool GraphicsDevice_DX11::CreateRenderPass(const RenderPassDesc* pDesc, RenderPass* renderpass) const -{ - renderpass->internal_state = emptyresource; - - renderpass->desc = *pDesc; - - return true; -} - -int GraphicsDevice_DX11::CreateSubresource(Texture* texture, SUBRESOURCE_TYPE type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount) const -{ - auto internal_state = to_internal(texture); - - switch (type) - { - case wiGraphics::SRV: - { - D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = {}; - - // Try to resolve resource format: - switch (texture->desc.Format) - { - case FORMAT_R16_TYPELESS: - srv_desc.Format = DXGI_FORMAT_R16_UNORM; - break; - case FORMAT_R32_TYPELESS: - srv_desc.Format = DXGI_FORMAT_R32_FLOAT; - break; - case FORMAT_R24G8_TYPELESS: - srv_desc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; - break; - case FORMAT_R32G8X24_TYPELESS: - srv_desc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; - break; - default: - srv_desc.Format = _ConvertFormat(texture->desc.Format); - break; - } - - if (texture->desc.type == TextureDesc::TEXTURE_1D) - { - if (texture->desc.ArraySize > 1) - { - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1DARRAY; - srv_desc.Texture1DArray.FirstArraySlice = firstSlice; - srv_desc.Texture1DArray.ArraySize = sliceCount; - srv_desc.Texture1DArray.MostDetailedMip = firstMip; - srv_desc.Texture1DArray.MipLevels = mipCount; - } - else - { - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE1D; - srv_desc.Texture1D.MostDetailedMip = firstMip; - srv_desc.Texture1D.MipLevels = mipCount; - } - } - else if (texture->desc.type == TextureDesc::TEXTURE_2D) - { - if (texture->desc.ArraySize > 1) - { - if (texture->desc.MiscFlags & RESOURCE_MISC_TEXTURECUBE) - { - if (texture->desc.ArraySize > 6) - { - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBEARRAY; - srv_desc.TextureCubeArray.First2DArrayFace = firstSlice; - srv_desc.TextureCubeArray.NumCubes = std::min(texture->desc.ArraySize, sliceCount) / 6; - srv_desc.TextureCubeArray.MostDetailedMip = firstMip; - srv_desc.TextureCubeArray.MipLevels = mipCount; - } - else - { - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; - srv_desc.TextureCube.MostDetailedMip = firstMip; - srv_desc.TextureCube.MipLevels = mipCount; - } - } - else - { - if (texture->desc.SampleCount > 1) - { - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY; - srv_desc.Texture2DMSArray.FirstArraySlice = firstSlice; - srv_desc.Texture2DMSArray.ArraySize = sliceCount; - } - else - { - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; - srv_desc.Texture2DArray.FirstArraySlice = firstSlice; - srv_desc.Texture2DArray.ArraySize = sliceCount; - srv_desc.Texture2DArray.MostDetailedMip = firstMip; - srv_desc.Texture2DArray.MipLevels = mipCount; - } - } - } - else - { - if (texture->desc.SampleCount > 1) - { - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS; - } - else - { - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srv_desc.Texture2D.MostDetailedMip = firstMip; - srv_desc.Texture2D.MipLevels = mipCount; - } - } - } - else if (texture->desc.type == TextureDesc::TEXTURE_3D) - { - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; - srv_desc.Texture3D.MostDetailedMip = firstMip; - srv_desc.Texture3D.MipLevels = mipCount; - } - - ComPtr srv; - HRESULT hr = device->CreateShaderResourceView(internal_state->resource.Get(), &srv_desc, &srv); - if (SUCCEEDED(hr)) - { - if (!internal_state->srv) - { - internal_state->srv = srv; - return -1; - } - internal_state->subresources_srv.push_back(srv); - return int(internal_state->subresources_srv.size() - 1); - } - else - { - assert(0); - } - } - break; - case wiGraphics::UAV: - { - D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc = {}; - - // Try to resolve resource format: - switch (texture->desc.Format) - { - case FORMAT_R16_TYPELESS: - uav_desc.Format = DXGI_FORMAT_R16_UNORM; - break; - case FORMAT_R32_TYPELESS: - uav_desc.Format = DXGI_FORMAT_R32_FLOAT; - break; - case FORMAT_R24G8_TYPELESS: - uav_desc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; - break; - case FORMAT_R32G8X24_TYPELESS: - uav_desc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; - break; - default: - uav_desc.Format = _ConvertFormat(texture->desc.Format); - break; - } - - if (texture->desc.type == TextureDesc::TEXTURE_1D) - { - if (texture->desc.ArraySize > 1) - { - uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1DARRAY; - uav_desc.Texture1DArray.FirstArraySlice = firstSlice; - uav_desc.Texture1DArray.ArraySize = sliceCount; - uav_desc.Texture1DArray.MipSlice = firstMip; - } - else - { - uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE1D; - uav_desc.Texture1D.MipSlice = firstMip; - } - } - else if (texture->desc.type == TextureDesc::TEXTURE_2D) - { - if (texture->desc.ArraySize > 1) - { - uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2DARRAY; - uav_desc.Texture2DArray.FirstArraySlice = firstSlice; - uav_desc.Texture2DArray.ArraySize = sliceCount; - uav_desc.Texture2DArray.MipSlice = firstMip; - } - else - { - uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; - uav_desc.Texture2D.MipSlice = firstMip; - } - } - else if (texture->desc.type == TextureDesc::TEXTURE_3D) - { - uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D; - uav_desc.Texture3D.MipSlice = firstMip; - uav_desc.Texture3D.FirstWSlice = 0; - uav_desc.Texture3D.WSize = -1; - } - - ComPtr uav; - HRESULT hr = device->CreateUnorderedAccessView(internal_state->resource.Get(), &uav_desc, &uav); - if (SUCCEEDED(hr)) - { - if (!internal_state->uav) - { - internal_state->uav = uav; - return -1; - } - internal_state->subresources_uav.push_back(uav); - return int(internal_state->subresources_uav.size() - 1); - } - else - { - assert(0); - } - } - break; - case wiGraphics::RTV: - { - D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = {}; - - // Try to resolve resource format: - switch (texture->desc.Format) - { - case FORMAT_R16_TYPELESS: - rtv_desc.Format = DXGI_FORMAT_R16_UNORM; - break; - case FORMAT_R32_TYPELESS: - rtv_desc.Format = DXGI_FORMAT_R32_FLOAT; - break; - case FORMAT_R24G8_TYPELESS: - rtv_desc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS; - break; - case FORMAT_R32G8X24_TYPELESS: - rtv_desc.Format = DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; - break; - default: - rtv_desc.Format = _ConvertFormat(texture->desc.Format); - break; - } - - if (texture->desc.type == TextureDesc::TEXTURE_1D) - { - if (texture->desc.ArraySize > 1) - { - rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1DARRAY; - rtv_desc.Texture1DArray.FirstArraySlice = firstSlice; - rtv_desc.Texture1DArray.ArraySize = sliceCount; - rtv_desc.Texture1DArray.MipSlice = firstMip; - } - else - { - rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE1D; - rtv_desc.Texture1D.MipSlice = firstMip; - } - } - else if (texture->desc.type == TextureDesc::TEXTURE_2D) - { - if (texture->desc.ArraySize > 1) - { - if (texture->desc.SampleCount > 1) - { - rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY; - rtv_desc.Texture2DMSArray.FirstArraySlice = firstSlice; - rtv_desc.Texture2DMSArray.ArraySize = sliceCount; - } - else - { - rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtv_desc.Texture2DArray.FirstArraySlice = firstSlice; - rtv_desc.Texture2DArray.ArraySize = sliceCount; - rtv_desc.Texture2DArray.MipSlice = firstMip; - } - } - else - { - if (texture->desc.SampleCount > 1) - { - rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; - } - else - { - rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtv_desc.Texture2D.MipSlice = firstMip; - } - } - } - else if (texture->desc.type == TextureDesc::TEXTURE_3D) - { - rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; - rtv_desc.Texture3D.MipSlice = firstMip; - rtv_desc.Texture3D.FirstWSlice = 0; - rtv_desc.Texture3D.WSize = -1; - } - - ComPtr rtv; - HRESULT hr = device->CreateRenderTargetView(internal_state->resource.Get(), &rtv_desc, &rtv); - if (SUCCEEDED(hr)) - { - if (!internal_state->rtv) - { - internal_state->rtv = rtv; - return -1; - } - internal_state->subresources_rtv.push_back(rtv); - return int(internal_state->subresources_rtv.size() - 1); - } - else - { - assert(0); - } - } - break; - case wiGraphics::DSV: - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsv_desc = {}; - - // Try to resolve resource format: - switch (texture->desc.Format) - { - case FORMAT_R16_TYPELESS: - dsv_desc.Format = DXGI_FORMAT_D16_UNORM; - break; - case FORMAT_R32_TYPELESS: - dsv_desc.Format = DXGI_FORMAT_D32_FLOAT; - break; - case FORMAT_R24G8_TYPELESS: - dsv_desc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; - break; - case FORMAT_R32G8X24_TYPELESS: - dsv_desc.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT; - break; - default: - dsv_desc.Format = _ConvertFormat(texture->desc.Format); - break; - } - - if (texture->desc.type == TextureDesc::TEXTURE_1D) - { - if (texture->desc.ArraySize > 1) - { - dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1DARRAY; - dsv_desc.Texture1DArray.FirstArraySlice = firstSlice; - dsv_desc.Texture1DArray.ArraySize = sliceCount; - dsv_desc.Texture1DArray.MipSlice = firstMip; - } - else - { - dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE1D; - dsv_desc.Texture1D.MipSlice = firstMip; - } - } - else if (texture->desc.type == TextureDesc::TEXTURE_2D) - { - if (texture->desc.ArraySize > 1) - { - if (texture->desc.SampleCount > 1) - { - dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY; - dsv_desc.Texture2DMSArray.FirstArraySlice = firstSlice; - dsv_desc.Texture2DMSArray.ArraySize = sliceCount; - } - else - { - dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; - dsv_desc.Texture2DArray.FirstArraySlice = firstSlice; - dsv_desc.Texture2DArray.ArraySize = sliceCount; - dsv_desc.Texture2DArray.MipSlice = firstMip; - } - } - else - { - if (texture->desc.SampleCount > 1) - { - dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS; - } - else - { - dsv_desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; - dsv_desc.Texture2D.MipSlice = firstMip; - } - } - } - - ComPtr dsv; - HRESULT hr = device->CreateDepthStencilView(internal_state->resource.Get(), &dsv_desc, &dsv); - if (SUCCEEDED(hr)) - { - if (!internal_state->dsv) - { - internal_state->dsv = dsv; - return -1; - } - internal_state->subresources_dsv.push_back(dsv); - return int(internal_state->subresources_dsv.size() - 1); - } - else - { - assert(0); - } - } - break; - default: - break; - } - return -1; -} -int GraphicsDevice_DX11::CreateSubresource(GPUBuffer* buffer, SUBRESOURCE_TYPE type, uint64_t offset, uint64_t size) const -{ - auto internal_state = to_internal(buffer); - const GPUBufferDesc& desc = buffer->GetDesc(); - HRESULT hr = E_FAIL; - - switch (type) - { - case wiGraphics::SRV: - { - D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = {}; - - if (desc.MiscFlags & RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) - { - // This is a Raw Buffer - srv_desc.Format = DXGI_FORMAT_R32_TYPELESS; - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; - srv_desc.BufferEx.Flags = D3D11_BUFFEREX_SRV_FLAG_RAW; - srv_desc.BufferEx.FirstElement = (UINT)offset / sizeof(uint32_t); - srv_desc.BufferEx.NumElements = std::min((UINT)size, desc.ByteWidth - (UINT)offset) / sizeof(uint32_t); - } - else if (desc.MiscFlags & RESOURCE_MISC_BUFFER_STRUCTURED) - { - // This is a Structured Buffer - srv_desc.Format = DXGI_FORMAT_UNKNOWN; - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFEREX; - srv_desc.BufferEx.FirstElement = (UINT)offset / desc.StructureByteStride; - srv_desc.BufferEx.NumElements = std::min((UINT)size, desc.ByteWidth - (UINT)offset) / desc.StructureByteStride; - } - else - { - // This is a Typed Buffer - uint32_t stride = GetFormatStride(desc.Format); - srv_desc.Format = _ConvertFormat(desc.Format); - srv_desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; - srv_desc.Buffer.FirstElement = (UINT)offset / stride; - srv_desc.Buffer.NumElements = std::min((UINT)size, desc.ByteWidth - (UINT)offset) / stride; - } - - ComPtr srv; - hr = device->CreateShaderResourceView(internal_state->resource.Get(), &srv_desc, &srv); - - if (SUCCEEDED(hr)) - { - if (internal_state->srv == nullptr) - { - internal_state->srv = srv; - return -1; - } - else - { - internal_state->subresources_srv.push_back(srv); - return int(internal_state->subresources_srv.size() - 1); - } - } - else - { - assert(0); - } - } - break; - case wiGraphics::UAV: - { - D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc = {}; - uav_desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; - - if (desc.MiscFlags & RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) - { - // This is a Raw Buffer - uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; // Format must be DXGI_FORMAT_R32_TYPELESS, when creating Raw Unordered Access View - uav_desc.Buffer.Flags = D3D11_BUFFER_UAV_FLAG_RAW; - uav_desc.Buffer.FirstElement = (UINT)offset / sizeof(uint32_t); - uav_desc.Buffer.NumElements = std::min((UINT)size, desc.ByteWidth - (UINT)offset) / sizeof(uint32_t); - } - else if (desc.MiscFlags & RESOURCE_MISC_BUFFER_STRUCTURED) - { - // This is a Structured Buffer - uav_desc.Format = DXGI_FORMAT_UNKNOWN; // Format must be must be DXGI_FORMAT_UNKNOWN, when creating a View of a Structured Buffer - uav_desc.Buffer.FirstElement = (UINT)offset / desc.StructureByteStride; - uav_desc.Buffer.NumElements = std::min((UINT)size, desc.ByteWidth - (UINT)offset) / desc.StructureByteStride; - } - else - { - // This is a Typed Buffer - uint32_t stride = GetFormatStride(desc.Format); - uav_desc.Format = _ConvertFormat(desc.Format); - uav_desc.Buffer.FirstElement = (UINT)offset / stride; - uav_desc.Buffer.NumElements = std::min((UINT)size, desc.ByteWidth - (UINT)offset) / stride; - } - - ComPtr uav; - hr = device->CreateUnorderedAccessView(internal_state->resource.Get(), &uav_desc, &uav); - - if (SUCCEEDED(hr)) - { - if (internal_state->uav == nullptr) - { - internal_state->uav = uav; - return -1; - } - else - { - internal_state->subresources_uav.push_back(uav); - return int(internal_state->subresources_uav.size() - 1); - } - } - else - { - assert(0); - } - } - break; - default: - assert(0); - break; - } - return -1; -} - -void GraphicsDevice_DX11::Map(const GPUResource* resource, Mapping* mapping) const -{ - auto internal_state = to_internal(resource); - - D3D11_MAPPED_SUBRESOURCE map_result = {}; - D3D11_MAP map_type = D3D11_MAP_READ_WRITE; - UINT map_flags = 0; - if (mapping->_flags & Mapping::FLAG_READ) - { - if (mapping->_flags & Mapping::FLAG_WRITE) - { - map_type = D3D11_MAP_READ_WRITE; - } - else - { - map_type = D3D11_MAP_READ; - } - map_flags |= D3D11_MAP_FLAG_DO_NOT_WAIT; - } - else if (mapping->_flags & Mapping::FLAG_WRITE) - { - map_type = D3D11_MAP_WRITE_NO_OVERWRITE; - } - HRESULT hr = immediateContext->Map(internal_state->resource.Get(), 0, map_type, map_flags, &map_result); - if (SUCCEEDED(hr)) - { - mapping->data = map_result.pData; - mapping->rowpitch = map_result.RowPitch; - } - else - { - assert(0); - mapping->data = nullptr; - mapping->rowpitch = 0; - } -} -void GraphicsDevice_DX11::Unmap(const GPUResource* resource) const -{ - auto internal_state = to_internal(resource); - immediateContext->Unmap(internal_state->resource.Get(), 0); -} -void GraphicsDevice_DX11::QueryRead(const GPUQueryHeap* heap, uint32_t index, uint32_t count, uint64_t* results) const -{ - if (count == 0) - return; - - auto internal_state = to_internal(heap); - - const uint32_t _flags = D3D11_ASYNC_GETDATA_DONOTFLUSH; - - HRESULT hr = S_OK; - - assert(index + count <= internal_state->resources.size()); - for (uint32_t i = 0; i < count; ++i) - { - ID3D11Query* QUERY = internal_state->resources[index + i].Get(); - - switch (heap->desc.type) - { - case GPU_QUERY_TYPE_TIMESTAMP: - hr = immediateContext->GetData(QUERY, &results[i], sizeof(uint64_t), _flags); - break; - case GPU_QUERY_TYPE_OCCLUSION: - hr = immediateContext->GetData(QUERY, &results[i], sizeof(uint64_t), _flags); - break; - case GPU_QUERY_TYPE_OCCLUSION_BINARY: - { - BOOL passed = FALSE; - hr = immediateContext->GetData(QUERY, &passed, sizeof(BOOL), _flags); - results[i] = (uint64_t)passed; - break; - } - } - } -} - -void GraphicsDevice_DX11::SetCommonSampler(const StaticSampler* sam) -{ - common_samplers.push_back(*sam); -} - -void GraphicsDevice_DX11::SetName(GPUResource* pResource, const char* name) -{ - auto internal_state = to_internal(pResource); - internal_state->resource->SetPrivateData(WKPDID_D3DDebugObjectName, (UINT)strlen(name), name); -} - -CommandList GraphicsDevice_DX11::BeginCommandList(QUEUE_TYPE queue) -{ - CommandList cmd = cmd_count.fetch_add(1); - assert(cmd < COMMANDLIST_COUNT); - - if (deviceContexts[cmd] == nullptr) - { - // need to create one more command list: - - HRESULT hr = device->CreateDeferredContext(0, &deviceContexts[cmd]); - assert(SUCCEEDED(hr)); - - hr = deviceContexts[cmd].As(&userDefinedAnnotations[cmd]); - assert(SUCCEEDED(hr)); - - // Temporary allocations will use the following buffer type: - GPUBufferDesc frameAllocatorDesc; - frameAllocatorDesc.ByteWidth = 1024 * 1024; // 1 MB starting size - frameAllocatorDesc.BindFlags = BIND_SHADER_RESOURCE | BIND_INDEX_BUFFER | BIND_VERTEX_BUFFER; - frameAllocatorDesc.Usage = USAGE_DYNAMIC; - frameAllocatorDesc.CPUAccessFlags = CPU_ACCESS_WRITE; - frameAllocatorDesc.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; - bool success = CreateBuffer(&frameAllocatorDesc, nullptr, &frame_allocators[cmd].buffer); - assert(success); - SetName(&frame_allocators[cmd].buffer, "frame_allocator"); - - } - - BindPipelineState(nullptr, cmd); - BindComputeShader(nullptr, cmd); - - for (int stage = 0; stage < SHADERSTAGE_COUNT; ++stage) - { - for (auto& sam : common_samplers) - { - BindSampler((SHADERSTAGE)stage, &sam.sampler, sam.slot, cmd); - } - } - - D3D11_RECT pRects[8]; - for (uint32_t i = 0; i < 8; ++i) - { - pRects[i].bottom = INT32_MAX; - pRects[i].left = INT32_MIN; - pRects[i].right = INT32_MAX; - pRects[i].top = INT32_MIN; - } - deviceContexts[cmd]->RSSetScissorRects(8, pRects); - - stencilRef[cmd] = 0; - blendFactor[cmd] = XMFLOAT4(1, 1, 1, 1); - - prev_vs[cmd] = {}; - prev_ps[cmd] = {}; - prev_hs[cmd] = {}; - prev_ds[cmd] = {}; - prev_gs[cmd] = {}; - prev_cs[cmd] = {}; - prev_blendfactor[cmd] = {}; - prev_samplemask[cmd] = {}; - prev_bs[cmd] = {}; - prev_rs[cmd] = {}; - prev_stencilRef[cmd] = {}; - prev_dss[cmd] = {}; - prev_il[cmd] = {}; - prev_pt[cmd] = {}; - swapchains[cmd].clear(); - - memset(raster_uavs[cmd], 0, sizeof(raster_uavs[cmd])); - raster_uavs_slot[cmd] = {}; - raster_uavs_count[cmd] = {}; - - active_pso[cmd] = nullptr; - dirty_pso[cmd] = false; - active_renderpass[cmd] = nullptr; - - return cmd; -} -void GraphicsDevice_DX11::SubmitCommandLists() -{ - const int disjoint_write = FRAMECOUNT % arraysize(disjointQueries); - const int disjoint_read = (FRAMECOUNT + 1) % arraysize(disjointQueries); - immediateContext->Begin(disjointQueries[disjoint_write].Get()); - - // Execute deferred command lists: - CommandList cmd_last = cmd_count.load(); - cmd_count.store(0); - for (CommandList cmd = 0; cmd < cmd_last; ++cmd) - { - HRESULT hr = deviceContexts[cmd]->FinishCommandList(false, &commandLists[cmd]); - assert(SUCCEEDED(hr)); - immediateContext->ExecuteCommandList(commandLists[cmd].Get(), false); - commandLists[cmd].Reset(); - - for (auto& swapchain : swapchains[cmd]) - { - to_internal(swapchain)->swapChain->Present(swapchain->desc.vsync, 0); - } - } - immediateContext->ClearState(); - - immediateContext->End(disjointQueries[disjoint_write].Get()); - D3D11_QUERY_DATA_TIMESTAMP_DISJOINT disjoint; - HRESULT hr = immediateContext->GetData( - disjointQueries[disjoint_read].Get(), - &disjoint, - sizeof(disjoint), - D3D11_ASYNC_GETDATA_DONOTFLUSH - ); - if (disjoint.Disjoint == FALSE && hr == S_OK) - { - TIMESTAMP_FREQUENCY = disjoint.Frequency; - } - - FRAMECOUNT++; -} - -void GraphicsDevice_DX11::WaitForGPU() const -{ - immediateContext->Flush(); - - - D3D11_QUERY_DESC desc; - desc.MiscFlags = 0; - desc.Query = D3D11_QUERY_EVENT; - - ComPtr query; - HRESULT hr = device->CreateQuery(&desc, &query); - assert(SUCCEEDED(hr)); - immediateContext->End(query.Get()); - BOOL result; - while (immediateContext->GetData(query.Get(), &result, sizeof(result), 0) == S_FALSE); - assert(result == TRUE); -} - - -Texture GraphicsDevice_DX11::GetBackBuffer(const SwapChain* swapchain) const -{ - auto swapchain_internal = to_internal(swapchain); - - auto internal_state = std::make_shared(); - internal_state->resource = swapchain_internal->backBuffer; - - Texture result; - result.internal_state = internal_state; - result.type = GPUResource::GPU_RESOURCE_TYPE::TEXTURE; - - D3D11_TEXTURE2D_DESC desc; - swapchain_internal->backBuffer->GetDesc(&desc); - result.desc = _ConvertTextureDesc_Inv(&desc); - - return result; -} - -void GraphicsDevice_DX11::commit_allocations(CommandList cmd) -{ - // DX11 needs to unmap allocations before it can execute safely - - if (frame_allocators[cmd].dirty) - { - auto internal_state = to_internal(&frame_allocators[cmd].buffer); - deviceContexts[cmd]->Unmap(internal_state->resource.Get(), 0); - frame_allocators[cmd].dirty = false; - } -} - - -void GraphicsDevice_DX11::RenderPassBegin(const SwapChain* swapchain, CommandList cmd) -{ - swapchains[cmd].push_back(swapchain); - active_renderpass[cmd] = &dummyrenderpass; - auto internal_state = to_internal(swapchain); - - ID3D11RenderTargetView* RTV = internal_state->renderTargetView.Get(); - deviceContexts[cmd]->OMSetRenderTargets(1, &RTV, 0); - deviceContexts[cmd]->ClearRenderTargetView(RTV, swapchain->desc.clearcolor); -} -void GraphicsDevice_DX11::RenderPassBegin(const RenderPass* renderpass, CommandList cmd) -{ - active_renderpass[cmd] = renderpass; - const RenderPassDesc& desc = renderpass->GetDesc(); - - uint32_t rt_count = 0; - ID3D11RenderTargetView* RTVs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {}; - ID3D11DepthStencilView* DSV = nullptr; - for (auto& attachment : desc.attachments) - { - const Texture* texture = attachment.texture; - int subresource = attachment.subresource; - auto internal_state = to_internal(texture); - - if (attachment.type == RenderPassAttachment::RENDERTARGET) - { - if (subresource < 0 || internal_state->subresources_rtv.empty()) - { - RTVs[rt_count] = internal_state->rtv.Get(); - } - else - { - assert(internal_state->subresources_rtv.size() > size_t(subresource) && "Invalid RTV subresource!"); - RTVs[rt_count] = internal_state->subresources_rtv[subresource].Get(); - } - - if (attachment.loadop == RenderPassAttachment::LOADOP_CLEAR) - { - deviceContexts[cmd]->ClearRenderTargetView(RTVs[rt_count], texture->desc.clear.color); - } - - rt_count++; - } - else if (attachment.type == RenderPassAttachment::DEPTH_STENCIL) - { - if (subresource < 0 || internal_state->subresources_dsv.empty()) - { - DSV = internal_state->dsv.Get(); - } - else - { - assert(internal_state->subresources_dsv.size() > size_t(subresource) && "Invalid DSV subresource!"); - DSV = internal_state->subresources_dsv[subresource].Get(); - } - - if (attachment.loadop == RenderPassAttachment::LOADOP_CLEAR) - { - uint32_t _flags = D3D11_CLEAR_DEPTH; - if (IsFormatStencilSupport(texture->desc.Format)) - _flags |= D3D11_CLEAR_STENCIL; - deviceContexts[cmd]->ClearDepthStencilView(DSV, _flags, texture->desc.clear.depthstencil.depth, texture->desc.clear.depthstencil.stencil); - } - } - } - - if (raster_uavs_count[cmd] > 0) - { - // UAVs: - const uint32_t count = raster_uavs_count[cmd]; - const uint32_t slot = raster_uavs_slot[cmd]; - - deviceContexts[cmd]->OMSetRenderTargetsAndUnorderedAccessViews(rt_count, RTVs, DSV, slot, count, &raster_uavs[cmd][slot], nullptr); - - raster_uavs_count[cmd] = 0; - raster_uavs_slot[cmd] = 8; - } - else - { - deviceContexts[cmd]->OMSetRenderTargets(rt_count, RTVs, DSV); - } -} -void GraphicsDevice_DX11::RenderPassEnd(CommandList cmd) -{ - deviceContexts[cmd]->OMSetRenderTargets(0, nullptr, nullptr); - - // Perform resolves: - int dst_counter = 0; - for (auto& attachment : active_renderpass[cmd]->desc.attachments) - { - if (attachment.type == RenderPassAttachment::RESOLVE) - { - if (attachment.texture != nullptr) - { - auto dst_internal = to_internal(attachment.texture); - - int src_counter = 0; - for (auto& src : active_renderpass[cmd]->desc.attachments) - { - if (src.type == RenderPassAttachment::RENDERTARGET && src.texture != nullptr) - { - if (src_counter == dst_counter) - { - auto src_internal = to_internal(src.texture); - deviceContexts[cmd]->ResolveSubresource(dst_internal->resource.Get(), 0, src_internal->resource.Get(), 0, _ConvertFormat(attachment.texture->desc.Format)); - break; - } - src_counter++; - } - } - } - - dst_counter++; - } - } - active_renderpass[cmd] = nullptr; -} -void GraphicsDevice_DX11::BindScissorRects(uint32_t numRects, const Rect* rects, CommandList cmd) -{ - assert(rects != nullptr); - assert(numRects <= D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX); - D3D11_RECT pRects[D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX]; - for(uint32_t i = 0; i < numRects; ++i) { - pRects[i].bottom = (LONG)rects[i].bottom; - pRects[i].left = (LONG)rects[i].left; - pRects[i].right = (LONG)rects[i].right; - pRects[i].top = (LONG)rects[i].top; - } - deviceContexts[cmd]->RSSetScissorRects(numRects, pRects); -} -void GraphicsDevice_DX11::BindViewports(uint32_t NumViewports, const Viewport* pViewports, CommandList cmd) -{ - assert(pViewports != nullptr); - assert(NumViewports <= D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX); - D3D11_VIEWPORT d3dViewPorts[D3D11_VIEWPORT_AND_SCISSORRECT_MAX_INDEX]; - for (uint32_t i = 0; i < NumViewports; ++i) - { - d3dViewPorts[i].TopLeftX = pViewports[i].TopLeftX; - d3dViewPorts[i].TopLeftY = pViewports[i].TopLeftY; - d3dViewPorts[i].Width = pViewports[i].Width; - d3dViewPorts[i].Height = pViewports[i].Height; - d3dViewPorts[i].MinDepth = pViewports[i].MinDepth; - d3dViewPorts[i].MaxDepth = pViewports[i].MaxDepth; - } - deviceContexts[cmd]->RSSetViewports(NumViewports, d3dViewPorts); -} -void GraphicsDevice_DX11::BindResource(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource) -{ - if (resource != nullptr && resource->IsValid()) - { - auto internal_state = to_internal(resource); - ID3D11ShaderResourceView* SRV; - - if (subresource < 0) - { - SRV = internal_state->srv.Get(); - } - else - { - assert(internal_state->subresources_srv.size() > static_cast(subresource) && "Invalid subresource!"); - SRV = internal_state->subresources_srv[subresource].Get(); - } - - switch (stage) - { - case wiGraphics::VS: - deviceContexts[cmd]->VSSetShaderResources(slot, 1, &SRV); - break; - case wiGraphics::HS: - deviceContexts[cmd]->HSSetShaderResources(slot, 1, &SRV); - break; - case wiGraphics::DS: - deviceContexts[cmd]->DSSetShaderResources(slot, 1, &SRV); - break; - case wiGraphics::GS: - deviceContexts[cmd]->GSSetShaderResources(slot, 1, &SRV); - break; - case wiGraphics::PS: - deviceContexts[cmd]->PSSetShaderResources(slot, 1, &SRV); - break; - case wiGraphics::CS: - deviceContexts[cmd]->CSSetShaderResources(slot, 1, &SRV); - break; - default: - break; - } - } -} -void GraphicsDevice_DX11::BindResources(SHADERSTAGE stage, const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) -{ - assert(count <= 16); - ID3D11ShaderResourceView* srvs[16]; - for (uint32_t i = 0; i < count; ++i) - { - srvs[i] = resources[i] != nullptr && resources[i]->IsValid() ? to_internal(resources[i])->srv.Get() : nullptr; - } - - switch (stage) - { - case wiGraphics::VS: - deviceContexts[cmd]->VSSetShaderResources(slot, count, srvs); - break; - case wiGraphics::HS: - deviceContexts[cmd]->HSSetShaderResources(slot, count, srvs); - break; - case wiGraphics::DS: - deviceContexts[cmd]->DSSetShaderResources(slot, count, srvs); - break; - case wiGraphics::GS: - deviceContexts[cmd]->GSSetShaderResources(slot, count, srvs); - break; - case wiGraphics::PS: - deviceContexts[cmd]->PSSetShaderResources(slot, count, srvs); - break; - case wiGraphics::CS: - deviceContexts[cmd]->CSSetShaderResources(slot, count, srvs); - break; - default: - break; - } -} -void GraphicsDevice_DX11::BindUAV(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource) -{ - if (resource != nullptr && resource->IsValid()) - { - auto internal_state = to_internal(resource); - ID3D11UnorderedAccessView* UAV; - - if (subresource < 0) - { - UAV = internal_state->uav.Get(); - } - else - { - assert(internal_state->subresources_uav.size() > static_cast(subresource) && "Invalid subresource!"); - UAV = internal_state->subresources_uav[subresource].Get(); - } - - if (stage == CS) - { - deviceContexts[cmd]->CSSetUnorderedAccessViews(slot, 1, &UAV, nullptr); - } - else - { - raster_uavs[cmd][slot] = UAV; - raster_uavs_slot[cmd] = std::min(raster_uavs_slot[cmd], uint8_t(slot)); - raster_uavs_count[cmd] = std::max(raster_uavs_count[cmd], uint8_t(1)); - } - } -} -void GraphicsDevice_DX11::BindUAVs(SHADERSTAGE stage, const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) -{ - assert(slot + count <= 8); - ID3D11UnorderedAccessView* uavs[8]; - for (uint32_t i = 0; i < count; ++i) - { - uavs[i] = resources[i] != nullptr && resources[i]->IsValid() ? to_internal(resources[i])->uav.Get() : nullptr; - - if(stage != CS) - { - raster_uavs[cmd][slot + i] = uavs[i]; - } - } - - if(stage == CS) - { - deviceContexts[cmd]->CSSetUnorderedAccessViews(static_cast(slot), static_cast(count), uavs, nullptr); - } - else - { - raster_uavs_slot[cmd] = std::min(raster_uavs_slot[cmd], uint8_t(slot)); - raster_uavs_count[cmd] = std::max(raster_uavs_count[cmd], uint8_t(count)); - } -} -void GraphicsDevice_DX11::UnbindResources(uint32_t slot, uint32_t num, CommandList cmd) -{ - assert(num <= arraysize(__nullBlob) && "Extend nullBlob to support more resource unbinding!"); - deviceContexts[cmd]->PSSetShaderResources(slot, num, (ID3D11ShaderResourceView**)__nullBlob); - deviceContexts[cmd]->VSSetShaderResources(slot, num, (ID3D11ShaderResourceView**)__nullBlob); - deviceContexts[cmd]->GSSetShaderResources(slot, num, (ID3D11ShaderResourceView**)__nullBlob); - deviceContexts[cmd]->HSSetShaderResources(slot, num, (ID3D11ShaderResourceView**)__nullBlob); - deviceContexts[cmd]->DSSetShaderResources(slot, num, (ID3D11ShaderResourceView**)__nullBlob); - deviceContexts[cmd]->CSSetShaderResources(slot, num, (ID3D11ShaderResourceView**)__nullBlob); -} -void GraphicsDevice_DX11::UnbindUAVs(uint32_t slot, uint32_t num, CommandList cmd) -{ - assert(num <= arraysize(__nullBlob) && "Extend nullBlob to support more resource unbinding!"); - deviceContexts[cmd]->CSSetUnorderedAccessViews(slot, num, (ID3D11UnorderedAccessView**)__nullBlob, 0); - - raster_uavs_count[cmd] = 0; - raster_uavs_slot[cmd] = 8; -} -void GraphicsDevice_DX11::BindSampler(SHADERSTAGE stage, const Sampler* sampler, uint32_t slot, CommandList cmd) -{ - if (sampler != nullptr && sampler->IsValid()) - { - auto internal_state = to_internal(sampler); - ID3D11SamplerState* SAM = internal_state->resource.Get(); - - switch (stage) - { - case wiGraphics::VS: - deviceContexts[cmd]->VSSetSamplers(slot, 1, &SAM); - break; - case wiGraphics::HS: - deviceContexts[cmd]->HSSetSamplers(slot, 1, &SAM); - break; - case wiGraphics::DS: - deviceContexts[cmd]->DSSetSamplers(slot, 1, &SAM); - break; - case wiGraphics::GS: - deviceContexts[cmd]->GSSetSamplers(slot, 1, &SAM); - break; - case wiGraphics::PS: - deviceContexts[cmd]->PSSetSamplers(slot, 1, &SAM); - break; - case wiGraphics::CS: - deviceContexts[cmd]->CSSetSamplers(slot, 1, &SAM); - break; - default: - break; - } - } -} -void GraphicsDevice_DX11::BindConstantBuffer(SHADERSTAGE stage, const GPUBuffer* buffer, uint32_t slot, CommandList cmd) -{ - ID3D11Buffer* res = buffer != nullptr && buffer->IsValid() ? (ID3D11Buffer*)to_internal(buffer)->resource.Get() : nullptr; - switch (stage) - { - case wiGraphics::VS: - deviceContexts[cmd]->VSSetConstantBuffers(slot, 1, &res); - break; - case wiGraphics::HS: - deviceContexts[cmd]->HSSetConstantBuffers(slot, 1, &res); - break; - case wiGraphics::DS: - deviceContexts[cmd]->DSSetConstantBuffers(slot, 1, &res); - break; - case wiGraphics::GS: - deviceContexts[cmd]->GSSetConstantBuffers(slot, 1, &res); - break; - case wiGraphics::PS: - deviceContexts[cmd]->PSSetConstantBuffers(slot, 1, &res); - break; - case wiGraphics::CS: - deviceContexts[cmd]->CSSetConstantBuffers(slot, 1, &res); - break; - default: - break; - } -} -void GraphicsDevice_DX11::BindVertexBuffers(const GPUBuffer *const* vertexBuffers, uint32_t slot, uint32_t count, const uint32_t* strides, const uint32_t* offsets, CommandList cmd) -{ - assert(count <= 8); - ID3D11Buffer* res[8] = {}; - for (uint32_t i = 0; i < count; ++i) - { - res[i] = vertexBuffers[i] != nullptr && vertexBuffers[i]->IsValid() ? (ID3D11Buffer*)to_internal(vertexBuffers[i])->resource.Get() : nullptr; - } - deviceContexts[cmd]->IASetVertexBuffers(slot, count, res, strides, (offsets != nullptr ? offsets : reinterpret_cast(__nullBlob))); -} -void GraphicsDevice_DX11::BindIndexBuffer(const GPUBuffer* indexBuffer, const INDEXBUFFER_FORMAT format, uint32_t offset, CommandList cmd) -{ - ID3D11Buffer* res = indexBuffer != nullptr && indexBuffer->IsValid() ? (ID3D11Buffer*)to_internal(indexBuffer)->resource.Get() : nullptr; - deviceContexts[cmd]->IASetIndexBuffer(res, (format == INDEXBUFFER_FORMAT::INDEXFORMAT_16BIT ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT), offset); -} -void GraphicsDevice_DX11::BindStencilRef(uint32_t value, CommandList cmd) -{ - stencilRef[cmd] = value; -} -void GraphicsDevice_DX11::BindBlendFactor(float r, float g, float b, float a, CommandList cmd) -{ - blendFactor[cmd].x = r; - blendFactor[cmd].y = g; - blendFactor[cmd].z = b; - blendFactor[cmd].w = a; -} -void GraphicsDevice_DX11::BindPipelineState(const PipelineState* pso, CommandList cmd) -{ - if (active_pso[cmd] == pso) - return; - - active_pso[cmd] = pso; - dirty_pso[cmd] = true; -} -void GraphicsDevice_DX11::BindComputeShader(const Shader* cs, CommandList cmd) -{ - ID3D11ComputeShader* _cs = cs == nullptr ? nullptr : static_cast(cs->internal_state.get())->resource.Get(); - if (_cs != prev_cs[cmd]) - { - deviceContexts[cmd]->CSSetShader(_cs, nullptr, 0); - prev_cs[cmd] = _cs; - - if (cs != nullptr) - { - for (auto& x : cs->auto_samplers) - { - BindSampler(CS, &x.sampler, x.slot, cmd); - } - } - } -} -void GraphicsDevice_DX11::Draw(uint32_t vertexCount, uint32_t startVertexLocation, CommandList cmd) -{ - pso_validate(cmd); - commit_allocations(cmd); - - deviceContexts[cmd]->Draw(vertexCount, startVertexLocation); -} -void GraphicsDevice_DX11::DrawIndexed(uint32_t indexCount, uint32_t startIndexLocation, uint32_t baseVertexLocation, CommandList cmd) -{ - pso_validate(cmd); - commit_allocations(cmd); - - deviceContexts[cmd]->DrawIndexed(indexCount, startIndexLocation, baseVertexLocation); -} -void GraphicsDevice_DX11::DrawInstanced(uint32_t vertexCount, uint32_t instanceCount, uint32_t startVertexLocation, uint32_t startInstanceLocation, CommandList cmd) -{ - pso_validate(cmd); - commit_allocations(cmd); - - deviceContexts[cmd]->DrawInstanced(vertexCount, instanceCount, startVertexLocation, startInstanceLocation); -} -void GraphicsDevice_DX11::DrawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount, uint32_t startIndexLocation, uint32_t baseVertexLocation, uint32_t startInstanceLocation, CommandList cmd) -{ - pso_validate(cmd); - commit_allocations(cmd); - - deviceContexts[cmd]->DrawIndexedInstanced(indexCount, instanceCount, startIndexLocation, baseVertexLocation, startInstanceLocation); -} -void GraphicsDevice_DX11::DrawInstancedIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) -{ - pso_validate(cmd); - commit_allocations(cmd); - - deviceContexts[cmd]->DrawInstancedIndirect((ID3D11Buffer*)to_internal(args)->resource.Get(), args_offset); -} -void GraphicsDevice_DX11::DrawIndexedInstancedIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) -{ - pso_validate(cmd); - commit_allocations(cmd); - - deviceContexts[cmd]->DrawIndexedInstancedIndirect((ID3D11Buffer*)to_internal(args)->resource.Get(), args_offset); -} -void GraphicsDevice_DX11::Dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ, CommandList cmd) -{ - commit_allocations(cmd); - - deviceContexts[cmd]->Dispatch(threadGroupCountX, threadGroupCountY, threadGroupCountZ); -} -void GraphicsDevice_DX11::DispatchIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) -{ - commit_allocations(cmd); - - deviceContexts[cmd]->DispatchIndirect((ID3D11Buffer*)to_internal(args)->resource.Get(), args_offset); -} -void GraphicsDevice_DX11::CopyResource(const GPUResource* pDst, const GPUResource* pSrc, CommandList cmd) -{ - assert(pDst != nullptr && pSrc != nullptr); - auto internal_state_src = to_internal(pSrc); - auto internal_state_dst = to_internal(pDst); - deviceContexts[cmd]->CopyResource(internal_state_dst->resource.Get(), internal_state_src->resource.Get()); -} -void GraphicsDevice_DX11::UpdateBuffer(const GPUBuffer* buffer, const void* data, CommandList cmd, int dataSize) -{ - assert(buffer->desc.Usage != USAGE_IMMUTABLE && "Cannot update IMMUTABLE GPUBuffer!"); - assert((int)buffer->desc.ByteWidth >= dataSize || dataSize < 0 && "Data size is too big!"); - - if (dataSize == 0) - { - return; - } - - auto internal_state = to_internal(buffer); - - dataSize = std::min((int)buffer->desc.ByteWidth, dataSize); - - if (buffer->desc.Usage == USAGE_DYNAMIC) - { - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT hr = deviceContexts[cmd]->Map(internal_state->resource.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - assert(SUCCEEDED(hr) && "GPUBuffer mapping failed!"); - memcpy(mappedResource.pData, data, (dataSize >= 0 ? dataSize : buffer->desc.ByteWidth)); - deviceContexts[cmd]->Unmap(internal_state->resource.Get(), 0); - } - else if (buffer->desc.BindFlags & BIND_CONSTANT_BUFFER || dataSize < 0) - { - deviceContexts[cmd]->UpdateSubresource(internal_state->resource.Get(), 0, nullptr, data, 0, 0); - } - else - { - D3D11_BOX box = {}; - box.left = 0; - box.right = static_cast(dataSize); - box.top = 0; - box.bottom = 1; - box.front = 0; - box.back = 1; - deviceContexts[cmd]->UpdateSubresource(internal_state->resource.Get(), 0, &box, data, 0, 0); - } -} -void GraphicsDevice_DX11::QueryBegin(const GPUQueryHeap* heap, uint32_t index, CommandList cmd) -{ - auto internal_state = to_internal(heap); - deviceContexts[cmd]->Begin(internal_state->resources[index].Get()); -} -void GraphicsDevice_DX11::QueryEnd(const GPUQueryHeap* heap, uint32_t index, CommandList cmd) -{ - auto internal_state = to_internal(heap); - deviceContexts[cmd]->End(internal_state->resources[index].Get()); -} - -GraphicsDevice::GPUAllocation GraphicsDevice_DX11::AllocateGPU(size_t dataSize, CommandList cmd) -{ - GPUAllocation result; - if (dataSize == 0) - { - return result; - } - - GPUAllocator& allocator = frame_allocators[cmd]; - if (allocator.buffer.desc.ByteWidth <= dataSize) - { - // If allocation too large, grow the allocator: - allocator.buffer.desc.ByteWidth = uint32_t((dataSize + 1) * 2); - bool success = CreateBuffer(&allocator.buffer.desc, nullptr, &allocator.buffer); - assert(success); - SetName(&allocator.buffer, "frame_allocator"); - allocator.byteOffset = 0; - } - - auto internal_state = to_internal(&allocator.buffer); - - allocator.dirty = true; - - size_t position = allocator.byteOffset; - bool wrap = position == 0 || position + dataSize > allocator.buffer.desc.ByteWidth || allocator.residentFrame != FRAMECOUNT; - position = wrap ? 0 : position; - - // Issue buffer rename (realloc) on wrap, otherwise just append data: - D3D11_MAP mapping = wrap ? D3D11_MAP_WRITE_DISCARD : D3D11_MAP_WRITE_NO_OVERWRITE; - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT hr = deviceContexts[cmd]->Map(internal_state->resource.Get(), 0, mapping, 0, &mappedResource); - assert(SUCCEEDED(hr) && "GPUBuffer mapping failed!"); - - allocator.byteOffset = position + dataSize; - allocator.residentFrame = FRAMECOUNT; - - result.buffer = &allocator.buffer; - result.offset = (uint32_t)position; - result.data = (void*)((size_t)mappedResource.pData + position); - return result; -} - -void GraphicsDevice_DX11::EventBegin(const char* name, CommandList cmd) -{ - wchar_t text[128]; - if (wiHelper::StringConvert(name, text) > 0) - { - userDefinedAnnotations[cmd]->BeginEvent(text); - } -} -void GraphicsDevice_DX11::EventEnd(CommandList cmd) -{ - userDefinedAnnotations[cmd]->EndEvent(); -} -void GraphicsDevice_DX11::SetMarker(const char* name, CommandList cmd) -{ - wchar_t text[128]; - if (wiHelper::StringConvert(name, text) > 0) - { - userDefinedAnnotations[cmd]->SetMarker(text); - } -} - -} - -#endif // WICKEDENGINE_BUILD_DX11 diff --git a/WickedEngine/wiGraphicsDevice_DX11.h b/WickedEngine/wiGraphicsDevice_DX11.h deleted file mode 100644 index a75f0c807..000000000 --- a/WickedEngine/wiGraphicsDevice_DX11.h +++ /dev/null @@ -1,159 +0,0 @@ -#pragma once -#include "CommonInclude.h" - -#if __has_include("d3d11_3.h") -#define WICKEDENGINE_BUILD_DX11 -#endif // HAS DX11 - -#ifdef WICKEDENGINE_BUILD_DX11 -#include "wiGraphicsDevice.h" - -#include -#include -#include // ComPtr - -#include - -namespace wiGraphics -{ - - class GraphicsDevice_DX11 : public GraphicsDevice - { - protected: - D3D_DRIVER_TYPE driverType; - D3D_FEATURE_LEVEL featureLevel; - Microsoft::WRL::ComPtr DXGIFactory; - Microsoft::WRL::ComPtr device; - Microsoft::WRL::ComPtr immediateContext; - Microsoft::WRL::ComPtr deviceContexts[COMMANDLIST_COUNT]; - Microsoft::WRL::ComPtr commandLists[COMMANDLIST_COUNT]; - Microsoft::WRL::ComPtr userDefinedAnnotations[COMMANDLIST_COUNT]; - - Microsoft::WRL::ComPtr disjointQueries[BUFFERCOUNT + 3]; - - uint32_t stencilRef[COMMANDLIST_COUNT]; - XMFLOAT4 blendFactor[COMMANDLIST_COUNT]; - - ID3D11VertexShader* prev_vs[COMMANDLIST_COUNT] = {}; - ID3D11PixelShader* prev_ps[COMMANDLIST_COUNT] = {}; - ID3D11HullShader* prev_hs[COMMANDLIST_COUNT] = {}; - ID3D11DomainShader* prev_ds[COMMANDLIST_COUNT] = {}; - ID3D11GeometryShader* prev_gs[COMMANDLIST_COUNT] = {}; - ID3D11ComputeShader* prev_cs[COMMANDLIST_COUNT] = {}; - XMFLOAT4 prev_blendfactor[COMMANDLIST_COUNT] = {}; - uint32_t prev_samplemask[COMMANDLIST_COUNT] = {}; - const BlendState* prev_bs[COMMANDLIST_COUNT] = {}; - const RasterizerState* prev_rs[COMMANDLIST_COUNT] = {}; - uint32_t prev_stencilRef[COMMANDLIST_COUNT] = {}; - const DepthStencilState* prev_dss[COMMANDLIST_COUNT] = {}; - const InputLayout* prev_il[COMMANDLIST_COUNT] = {}; - PRIMITIVETOPOLOGY prev_pt[COMMANDLIST_COUNT] = {}; - std::vector swapchains[COMMANDLIST_COUNT]; - - const PipelineState* active_pso[COMMANDLIST_COUNT] = {}; - bool dirty_pso[COMMANDLIST_COUNT] = {}; - void pso_validate(CommandList cmd); - - const RenderPass* active_renderpass[COMMANDLIST_COUNT] = {}; - RenderPass dummyrenderpass; - - ID3D11UnorderedAccessView* raster_uavs[COMMANDLIST_COUNT][8] = {}; - uint8_t raster_uavs_slot[COMMANDLIST_COUNT] = {}; - uint8_t raster_uavs_count[COMMANDLIST_COUNT] = {}; - void validate_raster_uavs(CommandList cmd); - - struct GPUAllocator - { - GPUBuffer buffer; - size_t byteOffset = 0; - uint64_t residentFrame = 0; - bool dirty = false; - } frame_allocators[COMMANDLIST_COUNT]; - void commit_allocations(CommandList cmd); - - void CreateBackBufferResources(); - - std::atomic cmd_count{ 0 }; - - std::vector common_samplers; - - struct EmptyResourceHandle {}; // only care about control-block - std::shared_ptr emptyresource; - - public: - GraphicsDevice_DX11(bool debuglayer = false); - - bool CreateSwapChain(const SwapChainDesc* pDesc, wiPlatform::window_type window, SwapChain* swapChain) const override; - bool CreateBuffer(const GPUBufferDesc *pDesc, const SubresourceData* pInitialData, GPUBuffer *pBuffer) const override; - bool CreateTexture(const TextureDesc* pDesc, const SubresourceData *pInitialData, Texture *pTexture) const override; - bool CreateShader(SHADERSTAGE stage, const void *pShaderBytecode, size_t BytecodeLength, Shader *pShader) const override; - bool CreateSampler(const SamplerDesc *pSamplerDesc, Sampler *pSamplerState) const override; - bool CreateQueryHeap(const GPUQueryHeapDesc *pDesc, GPUQueryHeap *pQueryHeap) const override; - bool CreatePipelineState(const PipelineStateDesc* pDesc, PipelineState* pso) const override; - bool CreateRenderPass(const RenderPassDesc* pDesc, RenderPass* renderpass) const override; - - int CreateSubresource(Texture* texture, SUBRESOURCE_TYPE type, uint32_t firstSlice, uint32_t sliceCount, uint32_t firstMip, uint32_t mipCount) const override; - int CreateSubresource(GPUBuffer* buffer, SUBRESOURCE_TYPE type, uint64_t offset, uint64_t size = ~0) const override; - - void Map(const GPUResource* resource, Mapping* mapping) const override; - void Unmap(const GPUResource* resource) const override; - void QueryRead(const GPUQueryHeap* resource, uint32_t index, uint32_t count, uint64_t* results) const override; - - void SetCommonSampler(const StaticSampler* sam) override; - - void SetName(GPUResource* pResource, const char* name) override; - - void WaitForGPU() const override; - - CommandList BeginCommandList(QUEUE_TYPE queue = QUEUE_GRAPHICS) override; - void SubmitCommandLists() override; - - SHADERFORMAT GetShaderFormat() const override { return SHADERFORMAT_HLSL5; } - - Texture GetBackBuffer(const SwapChain* swapchain) const override; - - ///////////////Thread-sensitive//////////////////////// - - void RenderPassBegin(const SwapChain* swapchain, CommandList cmd) override; - void RenderPassBegin(const RenderPass* renderpass, CommandList cmd) override; - void RenderPassEnd(CommandList cmd) override; - void BindScissorRects(uint32_t numRects, const Rect* rects, CommandList cmd) override; - void BindViewports(uint32_t NumViewports, const Viewport* pViewports, CommandList cmd) override; - void BindResource(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource = -1) override; - void BindResources(SHADERSTAGE stage, const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) override; - void BindUAV(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource = -1) override; - void BindUAVs(SHADERSTAGE stage, const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) override; - void UnbindResources(uint32_t slot, uint32_t num, CommandList cmd) override; - void UnbindUAVs(uint32_t slot, uint32_t num, CommandList cmd) override; - void BindSampler(SHADERSTAGE stage, const Sampler* sampler, uint32_t slot, CommandList cmd) override; - void BindConstantBuffer(SHADERSTAGE stage, const GPUBuffer* buffer, uint32_t slot, CommandList cmd) override; - void BindVertexBuffers(const GPUBuffer *const* vertexBuffers, uint32_t slot, uint32_t count, const uint32_t* strides, const uint32_t* offsets, CommandList cmd) override; - void BindIndexBuffer(const GPUBuffer* indexBuffer, const INDEXBUFFER_FORMAT format, uint32_t offset, CommandList cmd) override; - void BindStencilRef(uint32_t value, CommandList cmd) override; - void BindBlendFactor(float r, float g, float b, float a, CommandList cmd) override; - void BindPipelineState(const PipelineState* pso, CommandList cmd) override; - void BindComputeShader(const Shader* cs, CommandList cmd) override; - void Draw(uint32_t vertexCount, uint32_t startVertexLocation, CommandList cmd) override; - void DrawIndexed(uint32_t indexCount, uint32_t startIndexLocation, uint32_t baseVertexLocation, CommandList cmd) override; - void DrawInstanced(uint32_t vertexCount, uint32_t instanceCount, uint32_t startVertexLocation, uint32_t startInstanceLocation, CommandList cmd) override; - void DrawIndexedInstanced(uint32_t indexCount, uint32_t instanceCount, uint32_t startIndexLocation, uint32_t baseVertexLocation, uint32_t startInstanceLocation, CommandList cmd) override; - void DrawInstancedIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) override; - void DrawIndexedInstancedIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) override; - void Dispatch(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ, CommandList cmd) override; - void DispatchIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) override; - void CopyResource(const GPUResource* pDst, const GPUResource* pSrc, CommandList cmd) override; - void UpdateBuffer(const GPUBuffer* buffer, const void* data, CommandList cmd, int dataSize = -1) override; - void QueryBegin(const GPUQueryHeap* heap, uint32_t index, CommandList cmd) override; - void QueryEnd(const GPUQueryHeap* heap, uint32_t index, CommandList cmd) override; - void Barrier(const GPUBarrier* barriers, uint32_t numBarriers, CommandList cmd) override {} - - GPUAllocation AllocateGPU(size_t dataSize, CommandList cmd) override; - - void EventBegin(const char* name, CommandList cmd) override; - void EventEnd(CommandList cmd) override; - void SetMarker(const char* name, CommandList cmd) override; - }; - -} - -#endif // WICKEDENGINE_BUILD_DX11 diff --git a/WickedEngine/wiGraphicsDevice_DX12.cpp b/WickedEngine/wiGraphicsDevice_DX12.cpp index a9aec3748..e700fd45e 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.cpp +++ b/WickedEngine/wiGraphicsDevice_DX12.cpp @@ -2,7 +2,6 @@ #ifdef WICKEDENGINE_BUILD_DX12 -#include "wiGraphicsDevice_SharedInternals.h" #include "wiHelper.h" #include "wiBackLog.h" @@ -19,19 +18,12 @@ #ifdef _DEBUG #include +#pragma comment(lib,"dxguid.lib") #endif #include #include -// Bindless allocation limits: -#define BINDLESS_RESOURCE_CAPACITY 500000 -#define BINDLESS_SAMPLER_CAPACITY 256 - -// Choose how many constant buffers will be placed in root in auto root signature: -#define CONSTANT_BUFFER_AUTO_PLACEMENT_IN_ROOT 4 -static_assert(GPU_RESOURCE_HEAP_CBV_COUNT < 32, "cbv root mask must fit into uint32_t!"); - using namespace Microsoft::WRL; namespace wiGraphics @@ -39,6 +31,14 @@ namespace wiGraphics namespace DX12_Internal { + // Bindless allocation limits: +#define BINDLESS_RESOURCE_CAPACITY 500000 +#define BINDLESS_SAMPLER_CAPACITY 256 + +// Choose how many constant buffers will be placed in root in auto root signature: +#define CONSTANT_BUFFER_AUTO_PLACEMENT_IN_ROOT 4 + static_assert(DESCRIPTORBINDER_CBV_COUNT < 32, "cbv root mask must fit into uint32_t!"); + #ifdef PLATFORM_UWP // UWP will use static link + /DELAYLOAD linker feature for the dlls (optionally) @@ -61,7 +61,7 @@ namespace DX12_Internal // Engine -> Native converters - inline uint32_t _ParseColorWriteMask(uint32_t value) + constexpr uint32_t _ParseColorWriteMask(uint32_t value) { uint32_t _flag = 0; @@ -83,6 +83,45 @@ namespace DX12_Internal return _flag; } + constexpr D3D12_RESOURCE_STATES _ParseResourceState(RESOURCE_STATE value) + { + D3D12_RESOURCE_STATES ret = {}; + + if (value & RESOURCE_STATE_UNDEFINED) + ret |= D3D12_RESOURCE_STATE_COMMON; + if (value & RESOURCE_STATE_SHADER_RESOURCE) + ret |= D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + if (value & RESOURCE_STATE_SHADER_RESOURCE_COMPUTE) + ret |= D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; + if (value & RESOURCE_STATE_UNORDERED_ACCESS) + ret |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS; + if (value & RESOURCE_STATE_COPY_SRC) + ret |= D3D12_RESOURCE_STATE_COPY_SOURCE; + if (value & RESOURCE_STATE_COPY_DST) + ret |= D3D12_RESOURCE_STATE_COPY_DEST; + + if (value & RESOURCE_STATE_RENDERTARGET) + ret |= D3D12_RESOURCE_STATE_RENDER_TARGET; + if (value & RESOURCE_STATE_DEPTHSTENCIL) + ret |= D3D12_RESOURCE_STATE_DEPTH_WRITE; + if (value & RESOURCE_STATE_DEPTHSTENCIL_READONLY) + ret |= D3D12_RESOURCE_STATE_DEPTH_READ; + if (value & RESOURCE_STATE_SHADING_RATE_SOURCE) + ret |= D3D12_RESOURCE_STATE_SHADING_RATE_SOURCE; + + if (value & RESOURCE_STATE_VERTEX_BUFFER) + ret |= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER; + if (value & RESOURCE_STATE_INDEX_BUFFER) + ret |= D3D12_RESOURCE_STATE_INDEX_BUFFER; + if (value & RESOURCE_STATE_CONSTANT_BUFFER) + ret |= D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER; + if (value & RESOURCE_STATE_INDIRECT_ARGUMENT) + ret |= D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT; + if (value & RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE) + ret |= D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE; + + return ret; + } constexpr D3D12_FILTER _ConvertFilter(FILTER value) { @@ -675,64 +714,6 @@ namespace DX12_Internal return data; } - constexpr D3D12_RESOURCE_STATES _ConvertImageLayout(IMAGE_LAYOUT value) - { - switch (value) - { - case wiGraphics::IMAGE_LAYOUT_UNDEFINED: - return D3D12_RESOURCE_STATE_COMMON; - case wiGraphics::IMAGE_LAYOUT_RENDERTARGET: - return D3D12_RESOURCE_STATE_RENDER_TARGET; - case wiGraphics::IMAGE_LAYOUT_DEPTHSTENCIL: - return D3D12_RESOURCE_STATE_DEPTH_WRITE; - case wiGraphics::IMAGE_LAYOUT_DEPTHSTENCIL_READONLY: - return D3D12_RESOURCE_STATE_DEPTH_READ; - case wiGraphics::IMAGE_LAYOUT_SHADER_RESOURCE: - return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; - case wiGraphics::IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE: - return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; - case wiGraphics::IMAGE_LAYOUT_UNORDERED_ACCESS: - return D3D12_RESOURCE_STATE_UNORDERED_ACCESS; - case wiGraphics::IMAGE_LAYOUT_COPY_SRC: - return D3D12_RESOURCE_STATE_COPY_SOURCE; - case wiGraphics::IMAGE_LAYOUT_COPY_DST: - return D3D12_RESOURCE_STATE_COPY_DEST; - case wiGraphics::IMAGE_LAYOUT_SHADING_RATE_SOURCE: - return D3D12_RESOURCE_STATE_SHADING_RATE_SOURCE; - } - - return D3D12_RESOURCE_STATE_COMMON; - } - constexpr D3D12_RESOURCE_STATES _ConvertBufferState(BUFFER_STATE value) - { - switch (value) - { - case wiGraphics::BUFFER_STATE_UNDEFINED: - return D3D12_RESOURCE_STATE_COMMON; - case wiGraphics::BUFFER_STATE_VERTEX_BUFFER: - return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER; - case wiGraphics::BUFFER_STATE_INDEX_BUFFER: - return D3D12_RESOURCE_STATE_INDEX_BUFFER; - case wiGraphics::BUFFER_STATE_CONSTANT_BUFFER: - return D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER; - case wiGraphics::BUFFER_STATE_INDIRECT_ARGUMENT: - return D3D12_RESOURCE_STATE_INDIRECT_ARGUMENT; - case wiGraphics::BUFFER_STATE_SHADER_RESOURCE: - return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; - case wiGraphics::BUFFER_STATE_SHADER_RESOURCE_COMPUTE: - return D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE; - case wiGraphics::BUFFER_STATE_UNORDERED_ACCESS: - return D3D12_RESOURCE_STATE_UNORDERED_ACCESS; - case wiGraphics::BUFFER_STATE_COPY_SRC: - return D3D12_RESOURCE_STATE_COPY_SOURCE; - case wiGraphics::BUFFER_STATE_COPY_DST: - return D3D12_RESOURCE_STATE_COPY_DEST; - case wiGraphics::BUFFER_STATE_RAYTRACING_ACCELERATION_STRUCTURE: - return D3D12_RESOURCE_STATE_RAYTRACING_ACCELERATION_STRUCTURE; - } - - return D3D12_RESOURCE_STATE_COMMON; - } constexpr D3D12_SHADER_VISIBILITY _ConvertShaderVisibility(SHADERSTAGE value) { switch (value) @@ -1034,18 +1015,6 @@ namespace DX12_Internal } - // Local Helpers: - - inline size_t Align(size_t uLocation, size_t uAlign) - { - if ((0 == uAlign) || (uAlign & (uAlign - 1))) - { - assert(0); - } - - return ((uLocation + (uAlign - 1)) & ~(uAlign - 1)); - } - enum RESOURCEBINDING { CONSTANTBUFFER, @@ -1244,7 +1213,6 @@ namespace DX12_Internal std::shared_ptr allocationhandler; D3D12MA::Allocation* allocation = nullptr; ComPtr resource; - SingleDescriptor cbv; SingleDescriptor srv; SingleDescriptor uav; std::vector subresources_srv; @@ -1254,11 +1222,8 @@ namespace DX12_Internal D3D12_GPU_VIRTUAL_ADDRESS gpu_address = 0; - GraphicsDevice::GPUAllocation dynamic[COMMANDLIST_COUNT]; - uint64_t cbv_mask_frame[COMMANDLIST_COUNT] = {}; - uint32_t cbv_mask_gfx[COMMANDLIST_COUNT] = {}; - uint32_t cbv_mask_compute[COMMANDLIST_COUNT] = {}; + uint32_t cbv_mask[COMMANDLIST_COUNT] = {}; virtual ~Resource_DX12() { @@ -1268,7 +1233,6 @@ namespace DX12_Internal if (resource) allocationhandler->destroyer_resources.push_back(std::make_pair(resource, framecount)); allocationhandler->destroylocker.unlock(); - cbv.destroy(); srv.destroy(); uav.destroy(); for (auto& x : subresources_srv) @@ -1323,16 +1287,12 @@ namespace DX12_Internal struct QueryHeap_DX12 { std::shared_ptr allocationhandler; - D3D12MA::Allocation* allocation = nullptr; - Microsoft::WRL::ComPtr resource; Microsoft::WRL::ComPtr heap; ~QueryHeap_DX12() { allocationhandler->destroylocker.lock(); uint64_t framecount = allocationhandler->framecount; - if (allocation) allocationhandler->destroyer_allocations.push_back(std::make_pair(allocation, framecount)); - if (resource) allocationhandler->destroyer_resources.push_back(std::make_pair(resource, framecount)); if (heap) allocationhandler->destroyer_queryheaps.push_back(std::make_pair(heap, framecount)); allocationhandler->destroylocker.unlock(); } @@ -1591,7 +1551,7 @@ using namespace DX12_Internal; { GPUBufferDesc uploaddesc; uploaddesc.ByteWidth = wiMath::GetNextPowerOfTwo(staging_size); - uploaddesc.Usage = USAGE_STAGING; + uploaddesc.Usage = USAGE_UPLOAD; bool upload_success = device->CreateBuffer(&uploaddesc, nullptr, &cmd.uploadbuffer); assert(upload_success); @@ -1630,78 +1590,6 @@ using namespace DX12_Internal; locker.unlock(); } - void GraphicsDevice_DX12::FrameResources::ResourceFrameAllocator::init(GraphicsDevice_DX12* device, size_t size) - { - this->device = device; - auto internal_state = std::make_shared(); - internal_state->allocationhandler = device->allocationhandler; - buffer.internal_state = internal_state; - - HRESULT hr; - - D3D12MA::ALLOCATION_DESC allocationDesc = {}; - allocationDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD; - - CD3DX12_RESOURCE_DESC resdesc = CD3DX12_RESOURCE_DESC::Buffer(size); - - hr = device->allocationhandler->allocator->CreateResource( - &allocationDesc, - &resdesc, - D3D12_RESOURCE_STATE_GENERIC_READ, - nullptr, - &internal_state->allocation, - IID_PPV_ARGS(&internal_state->resource) - ); - assert(SUCCEEDED(hr)); - - void* pData; - CD3DX12_RANGE readRange(0, 0); - internal_state->resource->Map(0, &readRange, &pData); - dataCur = dataBegin = reinterpret_cast(pData); - dataEnd = dataBegin + size; - - // Because the "buffer" is created by hand in this, fill the desc to indicate how it can be used: - buffer.type = GPUResource::GPU_RESOURCE_TYPE::BUFFER; - buffer.desc.ByteWidth = (uint32_t)((size_t)dataEnd - (size_t)dataBegin); - buffer.desc.Usage = USAGE_DYNAMIC; - buffer.desc.BindFlags = BIND_VERTEX_BUFFER | BIND_INDEX_BUFFER | BIND_SHADER_RESOURCE; - buffer.desc.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; - - internal_state->gpu_address = internal_state->resource->GetGPUVirtualAddress(); - - D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = {}; - srv_desc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER; - srv_desc.Format = DXGI_FORMAT_R32_TYPELESS; - srv_desc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_RAW; - srv_desc.Buffer.NumElements = buffer.desc.ByteWidth / sizeof(uint32_t); - srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - internal_state->srv.init(device, srv_desc, internal_state->resource.Get()); - } - uint8_t* GraphicsDevice_DX12::FrameResources::ResourceFrameAllocator::allocate(size_t dataSize, size_t alignment) - { - dataCur = reinterpret_cast(Align(reinterpret_cast(dataCur), alignment)); - - if (dataCur + dataSize > dataEnd) - { - init(device, ((size_t)dataEnd + dataSize - (size_t)dataBegin) * 2); - } - - uint8_t* retVal = dataCur; - - dataCur += dataSize; - - return retVal; - } - void GraphicsDevice_DX12::FrameResources::ResourceFrameAllocator::clear() - { - dataCur = dataBegin; - } - uint64_t GraphicsDevice_DX12::FrameResources::ResourceFrameAllocator::calculateOffset(uint8_t* address) - { - assert(address >= dataBegin && address < dataEnd); - return static_cast(address - dataBegin); - } - void GraphicsDevice_DX12::DescriptorBinder::init(GraphicsDevice_DX12* device) { this->device = device; @@ -1717,6 +1605,7 @@ using namespace DX12_Internal; ringOffset_sam = 0; memset(CBV, 0, sizeof(CBV)); + memset(CBV_offset, 0, sizeof(CBV_offset)); memset(SRV, 0, sizeof(SRV)); memset(SRV_index, -1, sizeof(SRV_index)); memset(UAV, 0, sizeof(UAV)); @@ -1728,31 +1617,24 @@ using namespace DX12_Internal; auto pso_internal = graphics ? to_internal(device->active_pso[cmd]) : to_internal(device->active_cs[cmd]); // Bind root descriptors: - if ((dirty_root_cbvs_gfx != 0 && graphics) || (dirty_root_cbvs_compute != 0 && !graphics)) + if (dirty_root_cbvs != 0) { uint32_t root_param = pso_internal->bindpoint_rootdescriptor; for (auto& x : pso_internal->root_cbvs) { - bool dirty; - if (graphics) - { - dirty = dirty_root_cbvs_gfx & (1 << x.ShaderRegister); - } - else - { - dirty = dirty_root_cbvs_compute & (1 << x.ShaderRegister); - } + bool dirty = dirty_root_cbvs & (1 << x.ShaderRegister); if (!dirty) { root_param++; continue; } - const GPUBuffer* buffer = CBV[x.ShaderRegister]; + const GPUBuffer& buffer = CBV[x.ShaderRegister]; + uint64_t offset = CBV_offset[x.ShaderRegister]; D3D12_GPU_VIRTUAL_ADDRESS address; - if (buffer == nullptr || !buffer->IsValid()) + if (!buffer.IsValid()) { // this must not happen, root descriptor must be always valid! // this happens when constant buffer was not bound by engine @@ -1762,18 +1644,9 @@ using namespace DX12_Internal; } else { - auto internal_state = to_internal(buffer); - - if (buffer->desc.Usage == USAGE_DYNAMIC) - { - GraphicsDevice::GPUAllocation allocation = internal_state->dynamic[cmd]; - address = to_internal(allocation.buffer)->gpu_address; - address += (D3D12_GPU_VIRTUAL_ADDRESS)allocation.offset; - } - else - { - address = internal_state->cbv.cbv.BufferLocation; - } + auto internal_state = to_internal(&buffer); + address = internal_state->gpu_address; + address += offset; } if (graphics) @@ -1787,14 +1660,7 @@ using namespace DX12_Internal; root_param++; } - if (graphics) - { - dirty_root_cbvs_gfx = 0; - } - else - { - dirty_root_cbvs_compute = 0; - } + dirty_root_cbvs = 0; } @@ -1864,9 +1730,9 @@ using namespace DX12_Internal; default: case D3D12_DESCRIPTOR_RANGE_TYPE_SRV: { - const GPUResource* resource = SRV[ShaderRegister]; + const GPUResource& resource = SRV[ShaderRegister]; const int subresource = SRV_index[ShaderRegister]; - if (resource == nullptr || !resource->IsValid()) + if (!resource.IsValid()) { switch (binding) { @@ -1906,9 +1772,9 @@ using namespace DX12_Internal; } else { - auto internal_state = to_internal(resource); + auto internal_state = to_internal(&resource); - if (resource->IsAccelerationStructure()) + if (resource.IsAccelerationStructure()) { device->device->CopyDescriptorsSimple(1, dst, internal_state->srv.handle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } @@ -1929,9 +1795,9 @@ using namespace DX12_Internal; case D3D12_DESCRIPTOR_RANGE_TYPE_UAV: { - const GPUResource* resource = UAV[ShaderRegister]; + const GPUResource& resource = UAV[ShaderRegister]; const int subresource = UAV_index[ShaderRegister]; - if (resource == nullptr || !resource->IsValid()) + if (!resource.IsValid()) { switch (binding) { @@ -1962,7 +1828,7 @@ using namespace DX12_Internal; } else { - auto internal_state = to_internal(resource); + auto internal_state = to_internal(&resource); if (subresource < 0) { @@ -1978,30 +1844,23 @@ using namespace DX12_Internal; case D3D12_DESCRIPTOR_RANGE_TYPE_CBV: { - const GPUBuffer* buffer = CBV[ShaderRegister]; + const GPUBuffer& buffer = CBV[ShaderRegister]; + uint64_t offset = CBV_offset[ShaderRegister]; - if (buffer == nullptr || !buffer->IsValid()) + if (!buffer.IsValid()) { device->device->CopyDescriptorsSimple(1, dst, device->nullCBV, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); } else { - auto internal_state = to_internal(buffer); + auto internal_state = to_internal(&buffer); - if (buffer->desc.Usage == USAGE_DYNAMIC) - { - GraphicsDevice::GPUAllocation allocation = internal_state->dynamic[cmd]; - D3D12_CONSTANT_BUFFER_VIEW_DESC cbv; - cbv.BufferLocation = to_internal(allocation.buffer)->gpu_address; - cbv.BufferLocation += (D3D12_GPU_VIRTUAL_ADDRESS)allocation.offset; - cbv.SizeInBytes = (uint32_t)Align((size_t)buffer->desc.ByteWidth, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT); + D3D12_CONSTANT_BUFFER_VIEW_DESC cbv; + cbv.BufferLocation = internal_state->gpu_address; + cbv.BufferLocation += offset; + cbv.SizeInBytes = (uint32_t)Align((size_t)buffer.desc.ByteWidth, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT); - device->device->CreateConstantBufferView(&cbv, dst); - } - else - { - device->device->CopyDescriptorsSimple(1, dst, internal_state->cbv.handle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); - } + device->device->CreateConstantBufferView(&cbv, dst); } } break; @@ -2061,14 +1920,14 @@ using namespace DX12_Internal; UINT ShaderRegister = x.BaseShaderRegister + descriptor_index; - const Sampler* sampler = SAM[ShaderRegister]; - if (sampler == nullptr || !sampler->IsValid()) + const Sampler& sampler = SAM[ShaderRegister]; + if (!sampler.IsValid()) { device->device->CopyDescriptorsSimple(1, dst, device->nullSAM, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); } else { - auto internal_state = to_internal(sampler); + auto internal_state = to_internal(&sampler); device->device->CopyDescriptorsSimple(1, dst, internal_state->descriptor.handle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); } } @@ -2239,129 +2098,36 @@ using namespace DX12_Internal; } } - void GraphicsDevice_DX12::query_flush(CommandList cmd) - { - // Perform query resolves (must be outside of render pass): - assert(active_renderpass[cmd] == nullptr); - - if (!query_resolves[cmd].empty()) - { - for (auto& x : query_resolves[cmd]) - { - auto internal_state = to_internal(x.heap); - - switch (x.heap->desc.type) - { - case GPU_QUERY_TYPE_TIMESTAMP: - GetCommandList(cmd)->ResolveQueryData( - internal_state->heap.Get(), - D3D12_QUERY_TYPE_TIMESTAMP, - x.index, - x.count, - internal_state->resource.Get(), - sizeof(uint64_t) * x.index - ); - break; - case GPU_QUERY_TYPE_OCCLUSION_BINARY: - GetCommandList(cmd)->ResolveQueryData( - internal_state->heap.Get(), - D3D12_QUERY_TYPE_BINARY_OCCLUSION, - x.index, - x.count, - internal_state->resource.Get(), - sizeof(uint64_t) * x.index - ); - break; - case GPU_QUERY_TYPE_OCCLUSION: - GetCommandList(cmd)->ResolveQueryData( - internal_state->heap.Get(), - D3D12_QUERY_TYPE_OCCLUSION, - x.index, - x.count, - internal_state->resource.Get(), - sizeof(uint64_t) * x.index - ); - break; - } - - } - query_resolves[cmd].clear(); - } - } - void GraphicsDevice_DX12::barrier_flush(CommandList cmd) - { - auto& barriers = frame_barriers[cmd]; - if (!barriers.empty()) - { - for (size_t i = 0; i < barriers.size(); ++i) - { - auto& barrier = barriers[i]; - if (barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_TRANSITION && - cmd_meta[cmd].queue > QUEUE_GRAPHICS) - { - // Only graphics queue can do pixel shader state: - barrier.Transition.StateBefore &= ~D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; - barrier.Transition.StateAfter &= ~D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; - } - if (barrier.Type == D3D12_RESOURCE_BARRIER_TYPE_TRANSITION && - barrier.Transition.StateBefore == barrier.Transition.StateAfter) - { - // Remove NOP barriers: - barrier = barriers.back(); - barriers.pop_back(); - i--; - } - } - if (!barriers.empty()) - { - GetCommandList(cmd)->ResourceBarrier( - (UINT)barriers.size(), - barriers.data() - ); - barriers.clear(); - } - } - } void GraphicsDevice_DX12::predraw(CommandList cmd) { pso_validate(cmd); descriptors[cmd].flush(true, cmd); - if (pushconstants[cmd].size > 0) + auto pso_internal = to_internal(active_pso[cmd]); + if (pso_internal->rootconstants.Constants.Num32BitValues > 0) { - auto pso_internal = to_internal(active_pso[cmd]); - if (pso_internal->rootconstants.Constants.Num32BitValues > 0) - { - GetCommandList(cmd)->SetGraphicsRoot32BitConstants( - pso_internal->bindpoint_rootconstant, - pso_internal->rootconstants.Constants.Num32BitValues, - pushconstants[cmd].data, - 0 - ); - pushconstants[cmd].size = 0; - } + GetCommandList(cmd)->SetGraphicsRoot32BitConstants( + pso_internal->bindpoint_rootconstant, + pso_internal->rootconstants.Constants.Num32BitValues, + pushconstants[cmd].data, + 0 + ); } } void GraphicsDevice_DX12::predispatch(CommandList cmd) { - barrier_flush(cmd); - descriptors[cmd].flush(false, cmd); - if (pushconstants[cmd].size > 0) + auto cs_internal = to_internal(active_cs[cmd]); + if (cs_internal->rootconstants.Constants.Num32BitValues > 0) { - auto cs_internal = to_internal(active_cs[cmd]); - if (cs_internal->rootconstants.Constants.Num32BitValues > 0) - { - GetCommandList(cmd)->SetComputeRoot32BitConstants( - cs_internal->bindpoint_rootconstant, - cs_internal->rootconstants.Constants.Num32BitValues, - pushconstants[cmd].data, - 0 - ); - pushconstants[cmd].size = 0; - } + GetCommandList(cmd)->SetComputeRoot32BitConstants( + cs_internal->bindpoint_rootconstant, + cs_internal->rootconstants.Constants.Num32BitValues, + pushconstants[cmd].data, + 0 + ); } } @@ -2369,7 +2135,7 @@ using namespace DX12_Internal; // Engine functions GraphicsDevice_DX12::GraphicsDevice_DX12(bool debuglayer, bool gpuvalidation) { - capabilities |= GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS; + ALLOCATION_MIN_ALIGNMENT = D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT; SHADER_IDENTIFIER_SIZE = D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES; TOPLEVEL_ACCELERATION_STRUCTURE_INSTANCE_SIZE = sizeof(D3D12_RAYTRACING_INSTANCE_DESC); @@ -2679,14 +2445,9 @@ using namespace DX12_Internal; } hr = device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS5, &features_5, sizeof(features_5)); - if (features_5.RaytracingTier >= D3D12_RAYTRACING_TIER_1_0) + if (features_5.RaytracingTier >= D3D12_RAYTRACING_TIER_1_1) { - capabilities |= GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE; - if (features_5.RaytracingTier >= D3D12_RAYTRACING_TIER_1_1) - { - capabilities |= GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE; - capabilities |= GRAPHICSDEVICE_CAPABILITY_RAYTRACING_GEOMETRYINDEX; - } + capabilities |= GRAPHICSDEVICE_CAPABILITY_RAYTRACING; } hr = device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS6, &features_6, sizeof(features_6)); @@ -2842,7 +2603,7 @@ using namespace DX12_Internal; nullSRV_texture3d = allocationhandler->descriptors_res.allocate(); device->CreateShaderResourceView(nullptr, &srv_desc, nullSRV_texture3d); } - if(CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) || CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if(CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = {}; srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; @@ -3025,15 +2786,11 @@ using namespace DX12_Internal; internal_state->allocationhandler = allocationhandler; pBuffer->internal_state = internal_state; pBuffer->type = GPUResource::GPU_RESOURCE_TYPE::BUFFER; + pBuffer->mapped_data = nullptr; + pBuffer->mapped_rowpitch = 0; pBuffer->desc = *pDesc; - if (pDesc->Usage == USAGE_DYNAMIC && pDesc->BindFlags & BIND_CONSTANT_BUFFER) - { - // this special case will use frame allocator - return true; - } - HRESULT hr = E_FAIL; size_t alignedSize = pDesc->ByteWidth; @@ -3063,18 +2820,15 @@ using namespace DX12_Internal; D3D12MA::ALLOCATION_DESC allocationDesc = {}; allocationDesc.HeapType = D3D12_HEAP_TYPE_DEFAULT; - if (pDesc->Usage == USAGE_STAGING) + if (pDesc->Usage == USAGE_READBACK) { - if (pDesc->CPUAccessFlags & CPU_ACCESS_READ) - { - allocationDesc.HeapType = D3D12_HEAP_TYPE_READBACK; - resourceState = D3D12_RESOURCE_STATE_COPY_DEST; - } - else - { - allocationDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD; - resourceState = D3D12_RESOURCE_STATE_GENERIC_READ; - } + allocationDesc.HeapType = D3D12_HEAP_TYPE_READBACK; + resourceState = D3D12_RESOURCE_STATE_COPY_DEST; + } + else if (pDesc->Usage == USAGE_UPLOAD) + { + allocationDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD; + resourceState = D3D12_RESOURCE_STATE_GENERIC_READ; } device->GetCopyableFootprints(&desc, 0, 1, 0, &internal_state->footprint, nullptr, nullptr, nullptr); @@ -3091,6 +2845,20 @@ using namespace DX12_Internal; internal_state->gpu_address = internal_state->resource->GetGPUVirtualAddress(); + if (pDesc->Usage == USAGE_READBACK) + { + hr = internal_state->resource->Map(0, nullptr, &pBuffer->mapped_data); + assert(SUCCEEDED(hr)); + pBuffer->mapped_rowpitch = pDesc->ByteWidth; + } + else if (pDesc->Usage == USAGE_UPLOAD) + { + D3D12_RANGE read_range = {}; + hr = internal_state->resource->Map(0, &read_range, &pBuffer->mapped_data); + assert(SUCCEEDED(hr)); + pBuffer->mapped_rowpitch = pDesc->ByteWidth; + } + // Issue data copy on request: if (pInitialData != nullptr) { @@ -3111,10 +2879,6 @@ using namespace DX12_Internal; // Create resource views if needed - if (pDesc->BindFlags & BIND_CONSTANT_BUFFER) - { - CreateSubresource(pBuffer, CBV, 0); - } if (pDesc->BindFlags & BIND_SHADER_RESOURCE) { CreateSubresource(pBuffer, SRV, 0); @@ -3132,6 +2896,8 @@ using namespace DX12_Internal; internal_state->allocationhandler = allocationhandler; pTexture->internal_state = internal_state; pTexture->type = GPUResource::GPU_RESOURCE_TYPE::TEXTURE; + pTexture->mapped_data = nullptr; + pTexture->mapped_rowpitch = 0; pTexture->desc = *pDesc; @@ -3155,7 +2921,7 @@ using namespace DX12_Internal; if (pDesc->BindFlags & BIND_DEPTH_STENCIL) { desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; - allocationDesc.Flags |= D3D12MA::ALLOCATION_FLAG_COMMITTED; + //allocationDesc.Flags |= D3D12MA::ALLOCATION_FLAG_COMMITTED; if (!(pDesc->BindFlags & BIND_SHADER_RESOURCE)) { desc.Flags |= D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE; @@ -3164,16 +2930,11 @@ using namespace DX12_Internal; if (pDesc->BindFlags & BIND_RENDER_TARGET) { desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; - allocationDesc.Flags |= D3D12MA::ALLOCATION_FLAG_COMMITTED; + //allocationDesc.Flags |= D3D12MA::ALLOCATION_FLAG_COMMITTED; } if (pDesc->BindFlags & BIND_UNORDERED_ACCESS) { desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS; - //desc.Flags |= D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS; - if (pInitialData == nullptr) - { - allocationDesc.Flags |= D3D12MA::ALLOCATION_FLAG_COMMITTED; - } } switch (pTexture->desc.type) @@ -3215,14 +2976,14 @@ using namespace DX12_Internal; } bool useClearValue = pDesc->BindFlags & BIND_RENDER_TARGET || pDesc->BindFlags & BIND_DEPTH_STENCIL; - D3D12_RESOURCE_STATES resourceState = _ConvertImageLayout(pTexture->desc.layout); + D3D12_RESOURCE_STATES resourceState = _ParseResourceState(pTexture->desc.layout); if (pInitialData != nullptr) { resourceState = D3D12_RESOURCE_STATE_COMMON; } - if (pTexture->desc.Usage == USAGE_STAGING) + if (pTexture->desc.Usage == USAGE_READBACK || pTexture->desc.Usage == USAGE_UPLOAD) { UINT64 RequiredSize = 0; device->GetCopyableFootprints(&desc, 0, 1, 0, &internal_state->footprint, nullptr, nullptr, &RequiredSize); @@ -3234,12 +2995,12 @@ using namespace DX12_Internal; desc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; desc.Flags = D3D12_RESOURCE_FLAG_NONE; - if (pTexture->desc.CPUAccessFlags & CPU_ACCESS_READ) + if (pTexture->desc.Usage == USAGE_READBACK) { allocationDesc.HeapType = D3D12_HEAP_TYPE_READBACK; resourceState = D3D12_RESOURCE_STATE_COPY_DEST; } - else + else if(pTexture->desc.Usage == USAGE_UPLOAD) { allocationDesc.HeapType = D3D12_HEAP_TYPE_UPLOAD; resourceState = D3D12_RESOURCE_STATE_GENERIC_READ; @@ -3256,6 +3017,20 @@ using namespace DX12_Internal; ); assert(SUCCEEDED(hr)); + if (pTexture->desc.Usage == USAGE_READBACK) + { + hr = internal_state->resource->Map(0, nullptr, &pTexture->mapped_data); + assert(SUCCEEDED(hr)); + pTexture->mapped_rowpitch = internal_state->footprint.Footprint.RowPitch; + } + else if(pTexture->desc.Usage == USAGE_UPLOAD) + { + D3D12_RANGE read_range = {}; + hr = internal_state->resource->Map(0, &read_range, &pTexture->mapped_data); + assert(SUCCEEDED(hr)); + pTexture->mapped_rowpitch = internal_state->footprint.Footprint.RowPitch; + } + if (pTexture->desc.MipLevels == 0) { pTexture->desc.MipLevels = (uint32_t)log2(std::max(pTexture->desc.Width, pTexture->desc.Height)) + 1; @@ -3952,32 +3727,6 @@ using namespace DX12_Internal; HRESULT hr = allocationhandler->device->CreateQueryHeap(&desc, IID_PPV_ARGS(&internal_state->heap)); assert(SUCCEEDED(hr)); - D3D12MA::ALLOCATION_DESC allocationDesc = {}; - allocationDesc.HeapType = D3D12_HEAP_TYPE_READBACK; - - D3D12_RESOURCE_DESC resdesc = {}; - resdesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER; - resdesc.Format = DXGI_FORMAT_UNKNOWN; - resdesc.Width = (UINT64)(desc.Count * sizeof(uint64_t)); - resdesc.Height = 1; - resdesc.MipLevels = 1; - resdesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR; - resdesc.DepthOrArraySize = 1; - resdesc.Alignment = 0; - resdesc.Flags = D3D12_RESOURCE_FLAG_NONE; - resdesc.SampleDesc.Count = 1; - resdesc.SampleDesc.Quality = 0; - - hr = allocationhandler->allocator->CreateResource( - &allocationDesc, - &resdesc, - D3D12_RESOURCE_STATE_COPY_DEST, - nullptr, - &internal_state->allocation, - IID_PPV_ARGS(&internal_state->resource) - ); - assert(SUCCEEDED(hr)); - return SUCCEEDED(hr); } bool GraphicsDevice_DX12::CreatePipelineState(const PipelineStateDesc* pDesc, PipelineState* pso) const @@ -4658,14 +4407,14 @@ using namespace DX12_Internal; barrierdesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barrierdesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barrierdesc.Transition.pResource = texture_internal->resource.Get(); - barrierdesc.Transition.StateBefore = _ConvertImageLayout(attachment.initial_layout); + barrierdesc.Transition.StateBefore = _ParseResourceState(attachment.initial_layout); if (attachment.type == RenderPassAttachment::RESOLVE) { barrierdesc.Transition.StateAfter = D3D12_RESOURCE_STATE_RESOLVE_DEST; } else { - barrierdesc.Transition.StateAfter = _ConvertImageLayout(attachment.subpass_layout); + barrierdesc.Transition.StateAfter = _ParseResourceState(attachment.subpass_layout); } barrierdesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; @@ -4695,9 +4444,9 @@ using namespace DX12_Internal; } else { - barrierdesc.Transition.StateBefore = _ConvertImageLayout(attachment.subpass_layout); + barrierdesc.Transition.StateBefore = _ParseResourceState(attachment.subpass_layout); } - barrierdesc.Transition.StateAfter = _ConvertImageLayout(attachment.final_layout); + barrierdesc.Transition.StateAfter = _ParseResourceState(attachment.final_layout); barrierdesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; if (barrierdesc.Transition.StateBefore == barrierdesc.Transition.StateAfter) @@ -5337,23 +5086,13 @@ using namespace DX12_Internal; switch (type) { - case wiGraphics::CBV: - { - size = std::min(size, (uint64_t)buffer->desc.ByteWidth); - D3D12_CONSTANT_BUFFER_VIEW_DESC cbv_desc = {}; - cbv_desc.SizeInBytes = (uint32_t)Align(size, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT); - cbv_desc.BufferLocation = internal_state->gpu_address + offset; - internal_state->cbv.init(this, cbv_desc); - return -1; - } - break; case wiGraphics::SRV: { D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = {}; srv_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - if (desc.MiscFlags & RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) + if (desc.MiscFlags & RESOURCE_MISC_BUFFER_RAW) { // This is a Raw Buffer srv_desc.Format = DXGI_FORMAT_R32_TYPELESS; @@ -5400,7 +5139,7 @@ using namespace DX12_Internal; uav_desc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER; uav_desc.Buffer.FirstElement = 0; - if (desc.MiscFlags & RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS) + if (desc.MiscFlags & RESOURCE_MISC_BUFFER_RAW) { // This is a Raw Buffer uav_desc.Format = DXGI_FORMAT_R32_TYPELESS; @@ -5455,9 +5194,6 @@ using namespace DX12_Internal; switch (type) { default: - case wiGraphics::CBV: - return internal_state->cbv.index; - break; case wiGraphics::SRV: if (subresource < 0) { @@ -5522,53 +5258,6 @@ using namespace DX12_Internal; memcpy(dest, identifier, D3D12_SHADER_IDENTIFIER_SIZE_IN_BYTES); } - void GraphicsDevice_DX12::Map(const GPUResource* resource, Mapping* mapping) const - { - auto internal_state = to_internal(resource); - D3D12_RANGE read_range = {}; - if (mapping->_flags & Mapping::FLAG_READ) - { - read_range.Begin = mapping->offset; - read_range.End = mapping->size; - } - HRESULT hr = internal_state->resource->Map(0, &read_range, &mapping->data); - if (SUCCEEDED(hr)) - { - mapping->rowpitch = internal_state->footprint.Footprint.RowPitch; - } - else - { - assert(0); - mapping->data = nullptr; - mapping->rowpitch = 0; - } - } - void GraphicsDevice_DX12::Unmap(const GPUResource* resource) const - { - auto internal_state = to_internal(resource); - internal_state->resource->Unmap(0, nullptr); - } - void GraphicsDevice_DX12::QueryRead(const GPUQueryHeap* heap, uint32_t index, uint32_t count, uint64_t* results) const - { - if (count == 0) - return; - - auto internal_state = to_internal(heap); - - D3D12_RANGE range; - range.Begin = (size_t)index * sizeof(uint64_t); - range.End = range.Begin + sizeof(uint64_t) * count; - D3D12_RANGE nullrange = {}; - void* data = nullptr; - - HRESULT hr = internal_state->resource->Map(0, &range, &data); - if (SUCCEEDED(hr)) - { - std::memcpy(results, (void*)((size_t)data + range.Begin), sizeof(uint64_t) * count); - internal_state->resource->Unmap(0, &nullrange); - } - } - void GraphicsDevice_DX12::SetCommonSampler(const StaticSampler* sam) { common_samplers.push_back(_ConvertStaticSampler(*sam)); @@ -5605,8 +5294,6 @@ using namespace DX12_Internal; hr = device->CreateCommandAllocator(queues[queue].desc.Type, IID_PPV_ARGS(&frames[fr].commandAllocators[cmd][queue])); assert(SUCCEEDED(hr)); - frames[fr].resourceBuffer[cmd].init(this, 1024 * 1024); // 1 MB starting size - } hr = device->CreateCommandList1(0, queues[queue].desc.Type, D3D12_COMMAND_LIST_FLAG_NONE, IID_PPV_ARGS(&commandLists[cmd][queue])); @@ -5632,7 +5319,6 @@ using namespace DX12_Internal; GetCommandList(cmd)->SetDescriptorHeaps(arraysize(heaps), heaps); descriptors[cmd].reset(); - GetFrameResources().resourceBuffer[cmd].clear(); if (queue == QUEUE_GRAPHICS) { @@ -5647,7 +5333,7 @@ using namespace DX12_Internal; GetCommandList(cmd)->RSSetScissorRects(8, pRects); } - prev_pt[cmd] = PRIMITIVETOPOLOGY::UNDEFINED; + prev_pt[cmd] = UNDEFINED_TOPOLOGY; prev_pipeline_hash[cmd] = 0; active_pso[cmd] = nullptr; active_cs[cmd] = nullptr; @@ -5677,9 +5363,6 @@ using namespace DX12_Internal; cmd_count.store(0); for (CommandList cmd = 0; cmd < cmd_last; ++cmd) { - query_flush(cmd); - barrier_flush(cmd); - hr = GetCommandList(cmd)->Close(); assert(SUCCEEDED(hr)); @@ -5884,9 +5567,7 @@ using namespace DX12_Internal; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_RENDER_TARGET; barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - - frame_barriers[cmd].push_back(barrier); - barrier_flush(cmd); + GetCommandList(cmd)->ResourceBarrier(1, &barrier); D3D12_RENDER_PASS_RENDER_TARGET_DESC RTV = {}; RTV.cpuDescriptor = internal_state->backbufferRTV[internal_state->swapChain->GetCurrentBackBufferIndex()]; @@ -5905,11 +5586,7 @@ using namespace DX12_Internal; auto internal_state = to_internal(active_renderpass[cmd]); - for (uint32_t i = 0; i < internal_state->num_barriers_begin; ++i) - { - frame_barriers[cmd].push_back(internal_state->barrierdescs_begin[i]); - } - barrier_flush(cmd); + GetCommandList(cmd)->ResourceBarrier(internal_state->num_barriers_begin, internal_state->barrierdescs_begin); if (internal_state->shading_rate_image != nullptr) { @@ -5937,16 +5614,11 @@ using namespace DX12_Internal; GetCommandList(cmd)->RSSetShadingRateImage(nullptr); } - for (uint32_t i = 0; i < internal_state->num_barriers_end; ++i) - { - frame_barriers[cmd].push_back(internal_state->barrierdescs_end[i]); - } + GetCommandList(cmd)->ResourceBarrier(internal_state->num_barriers_end, internal_state->barrierdescs_end); } active_renderpass[cmd] = nullptr; - query_flush(cmd); - if (active_backbuffer[cmd]) { D3D12_RESOURCE_BARRIER barrier = {}; @@ -5956,7 +5628,7 @@ using namespace DX12_Internal; barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_PRESENT; barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - frame_barriers[cmd].push_back(barrier); + GetCommandList(cmd)->ResourceBarrier(1, &barrier); active_backbuffer[cmd] = nullptr; } @@ -5990,67 +5662,62 @@ using namespace DX12_Internal; } GetCommandList(cmd)->RSSetViewports(NumViewports, d3dViewPorts); } - void GraphicsDevice_DX12::BindResource(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource) + void GraphicsDevice_DX12::BindResource(const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource) { - assert(slot < GPU_RESOURCE_HEAP_SRV_COUNT); - if (descriptors[cmd].SRV[slot] != resource || descriptors[cmd].SRV_index[slot] != subresource) + assert(slot < DESCRIPTORBINDER_SRV_COUNT); + if (descriptors[cmd].SRV[slot].internal_state != resource->internal_state || descriptors[cmd].SRV_index[slot] != subresource) { - descriptors[cmd].SRV[slot] = resource; + descriptors[cmd].SRV[slot] = *resource; descriptors[cmd].SRV_index[slot] = subresource; descriptors[cmd].dirty_res = true; } } - void GraphicsDevice_DX12::BindResources(SHADERSTAGE stage, const GPUResource* const* resources, uint32_t slot, uint32_t count, CommandList cmd) + void GraphicsDevice_DX12::BindResources(const GPUResource* const* resources, uint32_t slot, uint32_t count, CommandList cmd) { if (resources != nullptr) { for (uint32_t i = 0; i < count; ++i) { - BindResource(stage, resources[i], slot + i, cmd, -1); + BindResource(resources[i], slot + i, cmd, -1); } } } - void GraphicsDevice_DX12::BindUAV(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource) + void GraphicsDevice_DX12::BindUAV(const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource) { - assert(slot < GPU_RESOURCE_HEAP_UAV_COUNT); - if (descriptors[cmd].UAV[slot] != resource || descriptors[cmd].UAV_index[slot] != subresource) + assert(slot < DESCRIPTORBINDER_UAV_COUNT); + if (descriptors[cmd].UAV[slot].internal_state != resource->internal_state || descriptors[cmd].UAV_index[slot] != subresource) { - descriptors[cmd].UAV[slot] = resource; + descriptors[cmd].UAV[slot] = *resource; descriptors[cmd].UAV_index[slot] = subresource; descriptors[cmd].dirty_res = true; } } - void GraphicsDevice_DX12::BindUAVs(SHADERSTAGE stage, const GPUResource* const* resources, uint32_t slot, uint32_t count, CommandList cmd) + void GraphicsDevice_DX12::BindUAVs(const GPUResource* const* resources, uint32_t slot, uint32_t count, CommandList cmd) { if (resources != nullptr) { for (uint32_t i = 0; i < count; ++i) { - BindUAV(stage, resources[i], slot + i, cmd, -1); + BindUAV(resources[i], slot + i, cmd, -1); } } } - void GraphicsDevice_DX12::UnbindResources(uint32_t slot, uint32_t num, CommandList cmd) + void GraphicsDevice_DX12::BindSampler(const Sampler* sampler, uint32_t slot, CommandList cmd) { - } - void GraphicsDevice_DX12::UnbindUAVs(uint32_t slot, uint32_t num, CommandList cmd) - { - } - void GraphicsDevice_DX12::BindSampler(SHADERSTAGE stage, const Sampler* sampler, uint32_t slot, CommandList cmd) - { - assert(slot < GPU_SAMPLER_HEAP_COUNT); - if (descriptors[cmd].SAM[slot] != sampler) + assert(slot < DESCRIPTORBINDER_SAMPLER_COUNT); + if (descriptors[cmd].SAM[slot].internal_state != sampler->internal_state) { - descriptors[cmd].SAM[slot] = sampler; + descriptors[cmd].SAM[slot] = *sampler; descriptors[cmd].dirty_sam = true; } } - void GraphicsDevice_DX12::BindConstantBuffer(SHADERSTAGE stage, const GPUBuffer* buffer, uint32_t slot, CommandList cmd) + void GraphicsDevice_DX12::BindConstantBuffer(const GPUBuffer* buffer, uint32_t slot, CommandList cmd, uint64_t offset) { - assert(slot < GPU_RESOURCE_HEAP_CBV_COUNT); - if (buffer->desc.Usage == USAGE_DYNAMIC || descriptors[cmd].CBV[slot] != buffer) + assert(slot < DESCRIPTORBINDER_CBV_COUNT); + if (descriptors[cmd].CBV[slot].internal_state != buffer->internal_state || descriptors[cmd].CBV_offset[slot] != offset) { - descriptors[cmd].CBV[slot] = buffer; + descriptors[cmd].CBV[slot] = *buffer; + descriptors[cmd].CBV_offset[slot] = offset; descriptors[cmd].dirty_res = true; // Root constant buffer root signature state tracking: @@ -6059,23 +5726,14 @@ using namespace DX12_Internal; { // This is the first binding as constant buffer in this frame for this resource, // so clear the cbv flags completely - internal_state->cbv_mask_gfx[cmd] = 0; - internal_state->cbv_mask_compute[cmd] = 0; + internal_state->cbv_mask[cmd] = 0; internal_state->cbv_mask_frame[cmd] = FRAMECOUNT; } // CBV flag marked as bound for this slot: // Also, the corresponding slot is marked dirty - if (stage == CS) - { - internal_state->cbv_mask_compute[cmd] |= 1 << slot; - descriptors[cmd].dirty_root_cbvs_compute |= 1 << slot; - } - else - { - internal_state->cbv_mask_gfx[cmd] |= 1 << slot; - descriptors[cmd].dirty_root_cbvs_gfx |= 1 << slot; - } + internal_state->cbv_mask[cmd] |= 1 << slot; + descriptors[cmd].dirty_root_cbvs |= 1 << slot; } } void GraphicsDevice_DX12::BindVertexBuffers(const GPUBuffer* const* vertexBuffers, uint32_t slot, uint32_t count, const uint32_t* strides, const uint32_t* offsets, CommandList cmd) @@ -6164,7 +5822,7 @@ using namespace DX12_Internal; // Invalidate graphics root bindings: descriptors[cmd].dirty_res = true; descriptors[cmd].dirty_sam = true; - descriptors[cmd].dirty_root_cbvs_gfx = ~0; + descriptors[cmd].dirty_root_cbvs = ~0; // Set the bindless tables: uint32_t bindpoint = internal_state->bindpoint_bindless; @@ -6208,7 +5866,7 @@ using namespace DX12_Internal; // Invalidate compute root bindings: descriptors[cmd].dirty_res = true; descriptors[cmd].dirty_sam = true; - descriptors[cmd].dirty_root_cbvs_compute = ~0; + descriptors[cmd].dirty_root_cbvs = ~0; // Set the bindless tables: uint32_t bindpoint = internal_state->bindpoint_bindless; @@ -6280,7 +5938,6 @@ using namespace DX12_Internal; } void GraphicsDevice_DX12::CopyResource(const GPUResource* pDst, const GPUResource* pSrc, CommandList cmd) { - barrier_flush(cmd); auto internal_state_src = to_internal(pSrc); auto internal_state_dst = to_internal(pDst); D3D12_RESOURCE_DESC desc_src = internal_state_src->resource->GetDesc(); @@ -6302,71 +5959,12 @@ using namespace DX12_Internal; GetCommandList(cmd)->CopyResource(internal_state_dst->resource.Get(), internal_state_src->resource.Get()); } } - void GraphicsDevice_DX12::UpdateBuffer(const GPUBuffer* buffer, const void* data, CommandList cmd, int dataSize) + void GraphicsDevice_DX12::CopyBuffer(const GPUBuffer* pDst, uint64_t dst_offset, const GPUBuffer* pSrc, uint64_t src_offset, uint64_t size, CommandList cmd) { - assert(buffer->desc.Usage != USAGE_IMMUTABLE && "Cannot update IMMUTABLE GPUBuffer!"); - assert((int)buffer->desc.ByteWidth >= dataSize || dataSize < 0 && "Data size is too big!"); - - if (dataSize == 0) - { - return; - } - - dataSize = std::min((int)buffer->desc.ByteWidth, dataSize); - dataSize = (dataSize >= 0 ? dataSize : buffer->desc.ByteWidth); - - auto internal_state_dst = to_internal(buffer); - - GPUAllocation allocation = AllocateGPU(dataSize, cmd); - memcpy(allocation.data, data, dataSize); - - if (buffer->desc.Usage == USAGE_DYNAMIC && buffer->desc.BindFlags & BIND_CONSTANT_BUFFER) - { - // Dynamic buffer will be used from host memory directly: - internal_state_dst->dynamic[cmd] = allocation; - - // The proper binding slot is not tracked properly, but instead all the previous bindings are invalidated: - descriptors[cmd].dirty_res = true; - descriptors[cmd].dirty_root_cbvs_gfx |= internal_state_dst->cbv_mask_gfx[cmd]; - descriptors[cmd].dirty_root_cbvs_compute |= internal_state_dst->cbv_mask_compute[cmd]; - } - else - { - // Contents will be transferred to device memory: - assert(active_renderpass[cmd] == nullptr); - - auto internal_state_src = to_internal(&GetFrameResources().resourceBuffer[cmd].buffer); - - D3D12_RESOURCE_BARRIER barrier = {}; - barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; - barrier.Transition.pResource = internal_state_dst->resource.Get(); - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COMMON; - if (buffer->desc.BindFlags & BIND_CONSTANT_BUFFER || buffer->desc.BindFlags & BIND_VERTEX_BUFFER) - { - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER; - } - else if (buffer->desc.BindFlags & BIND_INDEX_BUFFER) - { - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_INDEX_BUFFER; - } - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COPY_DEST; - barrier.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; - barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; - frame_barriers[cmd].push_back(barrier); - barrier_flush(cmd); - - GetCommandList(cmd)->CopyBufferRegion( - internal_state_dst->resource.Get(), 0, - internal_state_src->resource.Get(), allocation.offset, - dataSize - ); - - barrier.Transition.StateBefore = D3D12_RESOURCE_STATE_COPY_DEST; - barrier.Transition.StateAfter = D3D12_RESOURCE_STATE_COMMON; - frame_barriers[cmd].push_back(barrier); - - } + auto src_internal = to_internal((const GPUBuffer*)pSrc); + auto dst_internal = to_internal((const GPUBuffer*)pDst); + GetCommandList(cmd)->CopyBufferRegion(dst_internal->resource.Get(), dst_offset, src_internal->resource.Get(), src_offset, size); } void GraphicsDevice_DX12::QueryBegin(const GPUQueryHeap* heap, uint32_t index, CommandList cmd) { @@ -6426,16 +6024,46 @@ using namespace DX12_Internal; break; } } - void GraphicsDevice_DX12::QueryResolve(const GPUQueryHeap* heap, uint32_t index, uint32_t count, CommandList cmd) + void GraphicsDevice_DX12::QueryResolve(const GPUQueryHeap* heap, uint32_t index, uint32_t count, const GPUBuffer* dest, uint64_t dest_offset, CommandList cmd) { - if (count == 0) - return; + assert(active_renderpass[cmd] == nullptr); // Can't resolve inside renderpass! - QueryResolver resolver; - resolver.heap = heap; - resolver.index = index; - resolver.count = count; - query_resolves[cmd].push_back(resolver); + auto internal_state = to_internal(heap); + auto dst_internal = to_internal(dest); + + switch (heap->desc.type) + { + case GPU_QUERY_TYPE_TIMESTAMP: + GetCommandList(cmd)->ResolveQueryData( + internal_state->heap.Get(), + D3D12_QUERY_TYPE_TIMESTAMP, + index, + count, + dst_internal->resource.Get(), + dest_offset + ); + break; + case GPU_QUERY_TYPE_OCCLUSION_BINARY: + GetCommandList(cmd)->ResolveQueryData( + internal_state->heap.Get(), + D3D12_QUERY_TYPE_BINARY_OCCLUSION, + index, + count, + dst_internal->resource.Get(), + dest_offset + ); + break; + case GPU_QUERY_TYPE_OCCLUSION: + GetCommandList(cmd)->ResolveQueryData( + internal_state->heap.Get(), + D3D12_QUERY_TYPE_OCCLUSION, + index, + count, + dst_internal->resource.Get(), + dest_offset + ); + break; + } } void GraphicsDevice_DX12::Barrier(const GPUBarrier* barriers, uint32_t numBarriers, CommandList cmd) { @@ -6445,6 +6073,11 @@ using namespace DX12_Internal; { const GPUBarrier& barrier = barriers[i]; + if (barrier.type == GPUBarrier::IMAGE_BARRIER && (barrier.image.texture == nullptr || !barrier.image.texture->IsValid())) + continue; + if (barrier.type == GPUBarrier::BUFFER_BARRIER && (barrier.buffer.buffer == nullptr || !barrier.buffer.buffer->IsValid())) + continue; + D3D12_RESOURCE_BARRIER barrierdesc = {}; switch (barrier.type) @@ -6462,8 +6095,8 @@ using namespace DX12_Internal; barrierdesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barrierdesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barrierdesc.Transition.pResource = to_internal(barrier.image.texture)->resource.Get(); - barrierdesc.Transition.StateBefore = _ConvertImageLayout(barrier.image.layout_before); - barrierdesc.Transition.StateAfter = _ConvertImageLayout(barrier.image.layout_after); + barrierdesc.Transition.StateBefore = _ParseResourceState(barrier.image.layout_before); + barrierdesc.Transition.StateAfter = _ParseResourceState(barrier.image.layout_after); if (barrier.image.mip >= 0 || barrier.image.slice >= 0) { barrierdesc.Transition.Subresource = D3D12CalcSubresource( @@ -6485,45 +6118,35 @@ using namespace DX12_Internal; barrierdesc.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION; barrierdesc.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; barrierdesc.Transition.pResource = to_internal(barrier.buffer.buffer)->resource.Get(); - barrierdesc.Transition.StateBefore = _ConvertBufferState(barrier.buffer.state_before); - barrierdesc.Transition.StateAfter = _ConvertBufferState(barrier.buffer.state_after); + barrierdesc.Transition.StateBefore = _ParseResourceState(barrier.buffer.state_before); + barrierdesc.Transition.StateAfter = _ParseResourceState(barrier.buffer.state_after); barrierdesc.Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES; } break; } - // Try to detect redundant barriers: - bool found = false; - for (auto& x : barrierdescs) + if (barrierdesc.Type == D3D12_RESOURCE_BARRIER_TYPE_TRANSITION && + cmd_meta[cmd].queue > QUEUE_GRAPHICS) { - if (x.Type == barrierdesc.Type && x.Flags == barrierdesc.Flags) - { - switch (x.Type) - { - default: - case D3D12_RESOURCE_BARRIER_TYPE_TRANSITION: - if (x.Transition.pResource == barrierdesc.Transition.pResource && - x.Transition.Subresource == barrierdesc.Transition.Subresource) - { - found = true; - x.Transition.StateAfter = barrierdesc.Transition.StateAfter; - } - break; - } - } - if (found) - break; - } - if (!found) - { - barrierdescs.push_back(barrierdesc); + // Only graphics queue can do pixel shader state: + barrierdesc.Transition.StateBefore &= ~D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; + barrierdesc.Transition.StateAfter &= ~D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE; } + + barrierdescs.push_back(barrierdesc); + } + + if (!barrierdescs.empty()) + { + GetCommandList(cmd)->ResourceBarrier( + (UINT)barrierdescs.size(), + barrierdescs.data() + ); + barrierdescs.clear(); } } void GraphicsDevice_DX12::BuildRaytracingAccelerationStructure(const RaytracingAccelerationStructure* dst, CommandList cmd, const RaytracingAccelerationStructure* src) { - barrier_flush(cmd); - auto dst_internal = to_internal(dst); D3D12_BUILD_RAYTRACING_ACCELERATION_STRUCTURE_DESC desc = {}; @@ -6664,24 +6287,6 @@ using namespace DX12_Internal; pushconstants[cmd].size = size; } - GraphicsDevice::GPUAllocation GraphicsDevice_DX12::AllocateGPU(size_t dataSize, CommandList cmd) - { - GPUAllocation result; - if (dataSize == 0) - { - return result; - } - - FrameResources::ResourceFrameAllocator& allocator = GetFrameResources().resourceBuffer[cmd]; - uint8_t* dest = allocator.allocate(dataSize, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT); - assert(dest != nullptr); - - result.buffer = &allocator.buffer; - result.offset = (uint32_t)allocator.calculateOffset(dest); - result.data = (void*)dest; - return result; - } - void GraphicsDevice_DX12::EventBegin(const char* name, CommandList cmd) { wchar_t text[128]; diff --git a/WickedEngine/wiGraphicsDevice_DX12.h b/WickedEngine/wiGraphicsDevice_DX12.h index adaedf978..6a8549e97 100644 --- a/WickedEngine/wiGraphicsDevice_DX12.h +++ b/WickedEngine/wiGraphicsDevice_DX12.h @@ -8,7 +8,6 @@ #ifdef WICKEDENGINE_BUILD_DX12 #include "wiGraphicsDevice.h" -#include "wiGraphicsDevice_SharedInternals.h" #include "wiMath.h" #include @@ -105,25 +104,9 @@ namespace wiGraphics { Microsoft::WRL::ComPtr fence[QUEUE_COUNT]; Microsoft::WRL::ComPtr commandAllocators[COMMANDLIST_COUNT][QUEUE_COUNT]; - - struct ResourceFrameAllocator - { - GraphicsDevice_DX12* device = nullptr; - GPUBuffer buffer; - uint8_t* dataBegin = nullptr; - uint8_t* dataCur = nullptr; - uint8_t* dataEnd = nullptr; - - void init(GraphicsDevice_DX12* device, size_t size); - - uint8_t* allocate(size_t dataSize, size_t alignment); - void clear(); - uint64_t calculateOffset(uint8_t* address); - }; - ResourceFrameAllocator resourceBuffer[COMMANDLIST_COUNT]; }; FrameResources frames[BUFFERCOUNT]; - FrameResources& GetFrameResources() { return frames[GetFrameCount() % BUFFERCOUNT]; } + FrameResources& GetFrameResources() { return frames[GetBufferIndex()]; } struct CommandListMetadata { @@ -145,15 +128,15 @@ namespace wiGraphics bool dirty_res = false; bool dirty_sam = false; - const GPUBuffer* CBV[GPU_RESOURCE_HEAP_CBV_COUNT]; - const GPUResource* SRV[GPU_RESOURCE_HEAP_SRV_COUNT]; - int SRV_index[GPU_RESOURCE_HEAP_SRV_COUNT]; - const GPUResource* UAV[GPU_RESOURCE_HEAP_UAV_COUNT]; - int UAV_index[GPU_RESOURCE_HEAP_UAV_COUNT]; - const Sampler* SAM[GPU_SAMPLER_HEAP_COUNT]; + GPUBuffer CBV[DESCRIPTORBINDER_CBV_COUNT]; + uint64_t CBV_offset[DESCRIPTORBINDER_CBV_COUNT]; + GPUResource SRV[DESCRIPTORBINDER_SRV_COUNT]; + int SRV_index[DESCRIPTORBINDER_SRV_COUNT]; + GPUResource UAV[DESCRIPTORBINDER_UAV_COUNT]; + int UAV_index[DESCRIPTORBINDER_UAV_COUNT]; + Sampler SAM[DESCRIPTORBINDER_SAMPLER_COUNT]; - uint32_t dirty_root_cbvs_gfx = 0; // bitmask - uint32_t dirty_root_cbvs_compute = 0; // bitmask + uint32_t dirty_root_cbvs = 0; // bitmask struct DescriptorHandles { @@ -197,19 +180,9 @@ namespace wiGraphics bool dirty_pso[COMMANDLIST_COUNT] = {}; void pso_validate(CommandList cmd); - void query_flush(CommandList cmd); - void barrier_flush(CommandList cmd); void predraw(CommandList cmd); void predispatch(CommandList cmd); - struct QueryResolver - { - const GPUQueryHeap* heap = nullptr; - uint32_t index = 0; - uint32_t count = 0; - }; - std::vector query_resolves[COMMANDLIST_COUNT]; - std::atomic cmd_count{ 0 }; public: @@ -237,10 +210,6 @@ namespace wiGraphics void WriteTopLevelAccelerationStructureInstance(const RaytracingAccelerationStructureDesc::TopLevel::Instance* instance, void* dest) const override; void WriteShaderIdentifier(const RaytracingPipelineState* rtpso, uint32_t group_index, void* dest) const override; - void Map(const GPUResource* resource, Mapping* mapping) const override; - void Unmap(const GPUResource* resource) const override; - void QueryRead(const GPUQueryHeap* heap, uint32_t index, uint32_t count, uint64_t* results) const override; - void SetCommonSampler(const StaticSampler* sam) override; void SetName(GPUResource* pResource, const char* name) override; @@ -263,14 +232,12 @@ namespace wiGraphics void RenderPassEnd(CommandList cmd) override; void BindScissorRects(uint32_t numRects, const Rect* rects, CommandList cmd) override; void BindViewports(uint32_t NumViewports, const Viewport* pViewports, CommandList cmd) override; - void BindResource(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource = -1) override; - void BindResources(SHADERSTAGE stage, const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) override; - void BindUAV(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource = -1) override; - void BindUAVs(SHADERSTAGE stage, const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) override; - void UnbindResources(uint32_t slot, uint32_t num, CommandList cmd) override; - void UnbindUAVs(uint32_t slot, uint32_t num, CommandList cmd) override; - void BindSampler(SHADERSTAGE stage, const Sampler* sampler, uint32_t slot, CommandList cmd) override; - void BindConstantBuffer(SHADERSTAGE stage, const GPUBuffer* buffer, uint32_t slot, CommandList cmd) override; + void BindResource(const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource = -1) override; + void BindResources(const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) override; + void BindUAV(const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource = -1) override; + void BindUAVs(const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) override; + void BindSampler(const Sampler* sampler, uint32_t slot, CommandList cmd) override; + void BindConstantBuffer(const GPUBuffer* buffer, uint32_t slot, CommandList cmd, uint64_t offset = 0ull) override; void BindVertexBuffers(const GPUBuffer *const* vertexBuffers, uint32_t slot, uint32_t count, const uint32_t* strides, const uint32_t* offsets, CommandList cmd) override; void BindIndexBuffer(const GPUBuffer* indexBuffer, const INDEXBUFFER_FORMAT format, uint32_t offset, CommandList cmd) override; void BindStencilRef(uint32_t value, CommandList cmd) override; @@ -289,18 +256,17 @@ namespace wiGraphics void DispatchMesh(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ, CommandList cmd) override; void DispatchMeshIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) override; void CopyResource(const GPUResource* pDst, const GPUResource* pSrc, CommandList cmd) override; - void UpdateBuffer(const GPUBuffer* buffer, const void* data, CommandList cmd, int dataSize = -1) override; + void CopyBuffer(const GPUBuffer* pDst, uint64_t dst_offset, const GPUBuffer* pSrc, uint64_t src_offset, uint64_t size, CommandList cmd) override; void QueryBegin(const GPUQueryHeap* heap, uint32_t index, CommandList cmd) override; void QueryEnd(const GPUQueryHeap* heap, uint32_t index, CommandList cmd) override; - void QueryResolve(const GPUQueryHeap* heap, uint32_t index, uint32_t count, CommandList cmd) override; + void QueryResolve(const GPUQueryHeap* heap, uint32_t index, uint32_t count, const GPUBuffer* dest, uint64_t dest_offset, CommandList cmd) override; + void QueryReset(const GPUQueryHeap* heap, uint32_t index, uint32_t count, CommandList cmd) override {} void Barrier(const GPUBarrier* barriers, uint32_t numBarriers, CommandList cmd) override; void BuildRaytracingAccelerationStructure(const RaytracingAccelerationStructure* dst, CommandList cmd, const RaytracingAccelerationStructure* src = nullptr) override; void BindRaytracingPipelineState(const RaytracingPipelineState* rtpso, CommandList cmd) override; void DispatchRays(const DispatchRaysDesc* desc, CommandList cmd) override; void PushConstants(const void* data, uint32_t size, CommandList cmd) override; - GPUAllocation AllocateGPU(size_t dataSize, CommandList cmd) override; - void EventBegin(const char* name, CommandList cmd) override; void EventEnd(CommandList cmd) override; void SetMarker(const char* name, CommandList cmd) override; diff --git a/WickedEngine/wiGraphicsDevice_SharedInternals.h b/WickedEngine/wiGraphicsDevice_SharedInternals.h deleted file mode 100644 index f4d91d4be..000000000 --- a/WickedEngine/wiGraphicsDevice_SharedInternals.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef WI_GRAPHICSDEVICE_SHAREDINTERNALS_H -#define WI_GRAPHICSDEVICE_SHAREDINTERNALS_H - -// Descriptor binding counts: -#define GPU_RESOURCE_HEAP_CBV_COUNT 15 -#define GPU_RESOURCE_HEAP_SRV_COUNT 64 -#define GPU_RESOURCE_HEAP_UAV_COUNT 16 -#define GPU_SAMPLER_HEAP_COUNT 16 - -#endif // WI_GRAPHICSDEVICE_SHAREDINTERNALS_H diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index 29e7e31b4..67a34dd27 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -7,7 +7,6 @@ #include "Utility/spirv_reflect.h" -#include "wiGraphicsDevice_SharedInternals.h" #include "wiHelper.h" #include "wiBackLog.h" #include "wiVersion.h" @@ -399,28 +398,28 @@ namespace Vulkan_Internal } return VK_STENCIL_OP_KEEP; } - constexpr VkImageLayout _ConvertImageLayout(IMAGE_LAYOUT value) + constexpr VkImageLayout _ConvertImageLayout(RESOURCE_STATE value) { switch (value) { - case wiGraphics::IMAGE_LAYOUT_UNDEFINED: + case wiGraphics::RESOURCE_STATE_UNDEFINED: return VK_IMAGE_LAYOUT_UNDEFINED; - case wiGraphics::IMAGE_LAYOUT_RENDERTARGET: + case wiGraphics::RESOURCE_STATE_RENDERTARGET: return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - case wiGraphics::IMAGE_LAYOUT_DEPTHSTENCIL: + case wiGraphics::RESOURCE_STATE_DEPTHSTENCIL: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - case wiGraphics::IMAGE_LAYOUT_DEPTHSTENCIL_READONLY: + case wiGraphics::RESOURCE_STATE_DEPTHSTENCIL_READONLY: return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL; - case wiGraphics::IMAGE_LAYOUT_SHADER_RESOURCE: - case wiGraphics::IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE: + case wiGraphics::RESOURCE_STATE_SHADER_RESOURCE: + case wiGraphics::RESOURCE_STATE_SHADER_RESOURCE_COMPUTE: return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; - case wiGraphics::IMAGE_LAYOUT_UNORDERED_ACCESS: + case wiGraphics::RESOURCE_STATE_UNORDERED_ACCESS: return VK_IMAGE_LAYOUT_GENERAL; - case wiGraphics::IMAGE_LAYOUT_COPY_SRC: + case wiGraphics::RESOURCE_STATE_COPY_SRC: return VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - case wiGraphics::IMAGE_LAYOUT_COPY_DST: + case wiGraphics::RESOURCE_STATE_COPY_DST: return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - case wiGraphics::IMAGE_LAYOUT_SHADING_RATE_SOURCE: + case wiGraphics::RESOURCE_STATE_SHADING_RATE_SOURCE: return VK_IMAGE_LAYOUT_FRAGMENT_SHADING_RATE_ATTACHMENT_OPTIMAL_KHR; } return VK_IMAGE_LAYOUT_UNDEFINED; @@ -451,82 +450,66 @@ namespace Vulkan_Internal } - inline VkAccessFlags _ParseImageLayout(IMAGE_LAYOUT value) + inline VkAccessFlags _ParseResourceState(RESOURCE_STATE value) { VkAccessFlags flags = 0; - switch (value) + if (value & RESOURCE_STATE_SHADER_RESOURCE) { - case wiGraphics::IMAGE_LAYOUT_UNDEFINED: - break; - case wiGraphics::IMAGE_LAYOUT_RENDERTARGET: - flags |= VK_ACCESS_SHADER_WRITE_BIT; - break; - case wiGraphics::IMAGE_LAYOUT_DEPTHSTENCIL: - flags |= VK_ACCESS_SHADER_WRITE_BIT; - break; - case wiGraphics::IMAGE_LAYOUT_DEPTHSTENCIL_READONLY: flags |= VK_ACCESS_SHADER_READ_BIT; - break; - case wiGraphics::IMAGE_LAYOUT_SHADER_RESOURCE: - case wiGraphics::IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE: + flags |= VK_ACCESS_UNIFORM_READ_BIT; + } + if (value & RESOURCE_STATE_SHADER_RESOURCE_COMPUTE) + { flags |= VK_ACCESS_SHADER_READ_BIT; - break; - case wiGraphics::IMAGE_LAYOUT_UNORDERED_ACCESS: + flags |= VK_ACCESS_UNIFORM_READ_BIT; + } + if (value & RESOURCE_STATE_UNORDERED_ACCESS) + { flags |= VK_ACCESS_SHADER_READ_BIT; flags |= VK_ACCESS_SHADER_WRITE_BIT; - break; - case wiGraphics::IMAGE_LAYOUT_COPY_SRC: + } + if (value & RESOURCE_STATE_COPY_SRC) + { flags |= VK_ACCESS_TRANSFER_READ_BIT; - break; - case wiGraphics::IMAGE_LAYOUT_COPY_DST: + } + if (value & RESOURCE_STATE_COPY_DST) + { flags |= VK_ACCESS_TRANSFER_WRITE_BIT; - break; } - return flags; - } - inline VkAccessFlags _ParseBufferState(BUFFER_STATE value) - { - VkAccessFlags flags = 0; - - switch (value) + if (value & RESOURCE_STATE_RENDERTARGET) + { + flags |= VK_ACCESS_SHADER_WRITE_BIT; + } + if (value & RESOURCE_STATE_DEPTHSTENCIL) + { + flags |= VK_ACCESS_SHADER_WRITE_BIT; + } + if (value & RESOURCE_STATE_DEPTHSTENCIL_READONLY) + { + flags |= VK_ACCESS_SHADER_READ_BIT; + } + + if (value & RESOURCE_STATE_VERTEX_BUFFER) { - case wiGraphics::BUFFER_STATE_UNDEFINED: - break; - case wiGraphics::BUFFER_STATE_VERTEX_BUFFER: flags |= VK_ACCESS_SHADER_READ_BIT; flags |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; - break; - case wiGraphics::BUFFER_STATE_INDEX_BUFFER: + } + if (value & RESOURCE_STATE_INDEX_BUFFER) + { flags |= VK_ACCESS_SHADER_READ_BIT; flags |= VK_ACCESS_INDEX_READ_BIT; - break; - case wiGraphics::BUFFER_STATE_CONSTANT_BUFFER: + } + if (value & RESOURCE_STATE_CONSTANT_BUFFER) + { flags |= VK_ACCESS_SHADER_READ_BIT; flags |= VK_ACCESS_UNIFORM_READ_BIT; - break; - case wiGraphics::BUFFER_STATE_INDIRECT_ARGUMENT: + } + if (value & RESOURCE_STATE_INDIRECT_ARGUMENT) + { flags |= VK_ACCESS_SHADER_READ_BIT; flags |= VK_ACCESS_INDIRECT_COMMAND_READ_BIT; - break; - case wiGraphics::BUFFER_STATE_SHADER_RESOURCE: - case wiGraphics::BUFFER_STATE_SHADER_RESOURCE_COMPUTE: - flags |= VK_ACCESS_SHADER_READ_BIT; - flags |= VK_ACCESS_UNIFORM_READ_BIT; - break; - case wiGraphics::BUFFER_STATE_UNORDERED_ACCESS: - flags |= VK_ACCESS_SHADER_READ_BIT; - flags |= VK_ACCESS_SHADER_WRITE_BIT; - break; - case wiGraphics::BUFFER_STATE_COPY_SRC: - flags |= VK_ACCESS_TRANSFER_READ_BIT; - break; - case wiGraphics::BUFFER_STATE_COPY_DST: - flags |= VK_ACCESS_TRANSFER_WRITE_BIT; - break; - default: - break; } return flags; @@ -630,25 +613,12 @@ namespace Vulkan_Internal } - // Memory tools: - - inline size_t Align(size_t uLocation, size_t uAlign) - { - if ((0 == uAlign) || (uAlign & (uAlign - 1))) - { - assert(0); - } - - return ((uLocation + (uAlign - 1)) & ~(uAlign - 1)); - } - struct Buffer_Vulkan { std::shared_ptr allocationhandler; VmaAllocation allocation = nullptr; VkBuffer resource = VK_NULL_HANDLE; - int cbv_index = -1; VkBufferView srv = VK_NULL_HANDLE; int srv_index = -1; VkBufferView uav = VK_NULL_HANDLE; @@ -660,8 +630,6 @@ namespace Vulkan_Internal VkDeviceAddress address = 0; bool is_typedbuffer = false; - GraphicsDevice::GPUAllocation dynamic[COMMANDLIST_COUNT]; - ~Buffer_Vulkan() { if (allocationhandler == nullptr) @@ -679,7 +647,6 @@ namespace Vulkan_Internal { allocationhandler->destroyer_bufferviews.push_back(std::make_pair(x, framecount)); } - if (cbv_index >= 0) allocationhandler->destroyer_bindlessUniformBuffers.push_back(std::make_pair(cbv_index, framecount)); if (is_typedbuffer) { if (srv_index >= 0) allocationhandler->destroyer_bindlessUniformTexelBuffers.push_back(std::make_pair(srv_index, framecount)); @@ -1083,7 +1050,7 @@ using namespace Vulkan_Internal; { GPUBufferDesc uploaddesc; uploaddesc.ByteWidth = wiMath::GetNextPowerOfTwo(staging_size); - uploaddesc.Usage = USAGE_STAGING; + uploaddesc.Usage = USAGE_UPLOAD; bool upload_success = device->CreateBuffer(&uploaddesc, nullptr, &cmd.uploadbuffer); assert(upload_success); @@ -1172,99 +1139,6 @@ using namespace Vulkan_Internal; return value; } - void GraphicsDevice_Vulkan::FrameResources::ResourceFrameAllocator::init(GraphicsDevice_Vulkan* device, size_t size) - { - this->device = device; - auto internal_state = std::make_shared(); - internal_state->allocationhandler = device->allocationhandler; - buffer.internal_state = internal_state; - - VkBufferCreateInfo bufferInfo = {}; - bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferInfo.size = size; - bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - bufferInfo.usage |= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; - bufferInfo.usage |= VK_BUFFER_USAGE_INDEX_BUFFER_BIT; - bufferInfo.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; - bufferInfo.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; - if (device->features_1_2.bufferDeviceAddress == VK_TRUE) - { - bufferInfo.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT; - } - bufferInfo.flags = 0; - - VkResult res; - - VmaAllocationCreateInfo allocInfo = {}; - allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; - allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; - - res = vmaCreateBuffer(device->allocationhandler->allocator, &bufferInfo, &allocInfo, &internal_state->resource, &internal_state->allocation, nullptr); - assert(res == VK_SUCCESS); - - if (bufferInfo.usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) - { - VkBufferDeviceAddressInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO; - info.buffer = internal_state->resource; - internal_state->address = vkGetBufferDeviceAddress(device->device, &info); - } - - void* pData = internal_state->allocation->GetMappedData(); - dataCur = dataBegin = reinterpret_cast(pData); - dataEnd = dataBegin + size; - - // Because the "buffer" is created by hand in this, fill the desc to indicate how it can be used: - this->buffer.type = GPUResource::GPU_RESOURCE_TYPE::BUFFER; - this->buffer.desc.ByteWidth = (uint32_t)((size_t)dataEnd - (size_t)dataBegin); - this->buffer.desc.Usage = USAGE_DYNAMIC; - this->buffer.desc.BindFlags = BIND_VERTEX_BUFFER | BIND_INDEX_BUFFER | BIND_SHADER_RESOURCE; - this->buffer.desc.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; - - int index = device->allocationhandler->bindlessStorageBuffers.allocate(); - if (index >= 0) - { - VkDescriptorBufferInfo bufferInfo = {}; - bufferInfo.buffer = internal_state->resource; - bufferInfo.offset = 0; - bufferInfo.range = (VkDeviceSize)size; - VkWriteDescriptorSet write = {}; - write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - write.dstBinding = 0; - write.dstArrayElement = index; - write.descriptorCount = 1; - write.dstSet = device->allocationhandler->bindlessStorageBuffers.descriptorSet; - write.pBufferInfo = &bufferInfo; - vkUpdateDescriptorSets(device->device, 1, &write, 0, nullptr); - } - internal_state->srv_index = index; - } - uint8_t* GraphicsDevice_Vulkan::FrameResources::ResourceFrameAllocator::allocate(size_t dataSize, size_t alignment) - { - dataCur = reinterpret_cast(Align(reinterpret_cast(dataCur), alignment)); - - if (dataCur + dataSize > dataEnd) - { - init(device, ((size_t)dataEnd + dataSize - (size_t)dataBegin) * 2); - } - - uint8_t* retVal = dataCur; - - dataCur += dataSize; - - return retVal; - } - void GraphicsDevice_Vulkan::FrameResources::ResourceFrameAllocator::clear() - { - dataCur = dataBegin; - } - uint64_t GraphicsDevice_Vulkan::FrameResources::ResourceFrameAllocator::calculateOffset(uint8_t* address) - { - assert(address >= dataBegin && address < dataEnd); - return static_cast(address - dataBegin); - } - void GraphicsDevice_Vulkan::FrameResources::DescriptorBinder::init(GraphicsDevice_Vulkan* device) { this->device = device; @@ -1283,41 +1157,41 @@ using namespace Vulkan_Internal; uint32_t count = 0; poolSizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - poolSizes[0].descriptorCount = GPU_RESOURCE_HEAP_CBV_COUNT * poolSize; + poolSizes[0].descriptorCount = DESCRIPTORBINDER_CBV_COUNT * poolSize; count++; poolSizes[1].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; - poolSizes[1].descriptorCount = GPU_RESOURCE_HEAP_SRV_COUNT * poolSize; + poolSizes[1].descriptorCount = DESCRIPTORBINDER_SRV_COUNT * poolSize; count++; poolSizes[2].type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER; - poolSizes[2].descriptorCount = GPU_RESOURCE_HEAP_SRV_COUNT * poolSize; + poolSizes[2].descriptorCount = DESCRIPTORBINDER_SRV_COUNT * poolSize; count++; poolSizes[3].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - poolSizes[3].descriptorCount = GPU_RESOURCE_HEAP_SRV_COUNT * poolSize; + poolSizes[3].descriptorCount = DESCRIPTORBINDER_SRV_COUNT * poolSize; count++; poolSizes[4].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; - poolSizes[4].descriptorCount = GPU_RESOURCE_HEAP_UAV_COUNT * poolSize; + poolSizes[4].descriptorCount = DESCRIPTORBINDER_UAV_COUNT * poolSize; count++; poolSizes[5].type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER; - poolSizes[5].descriptorCount = GPU_RESOURCE_HEAP_UAV_COUNT * poolSize; + poolSizes[5].descriptorCount = DESCRIPTORBINDER_UAV_COUNT * poolSize; count++; poolSizes[6].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; - poolSizes[6].descriptorCount = GPU_RESOURCE_HEAP_UAV_COUNT * poolSize; + poolSizes[6].descriptorCount = DESCRIPTORBINDER_UAV_COUNT * poolSize; count++; poolSizes[7].type = VK_DESCRIPTOR_TYPE_SAMPLER; - poolSizes[7].descriptorCount = GPU_SAMPLER_HEAP_COUNT * poolSize; + poolSizes[7].descriptorCount = DESCRIPTORBINDER_SAMPLER_COUNT * poolSize; count++; - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) || device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { poolSizes[8].type = VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; - poolSizes[8].descriptorCount = GPU_RESOURCE_HEAP_SRV_COUNT * poolSize; + poolSizes[8].descriptorCount = DESCRIPTORBINDER_SRV_COUNT * poolSize; count++; } @@ -1331,6 +1205,9 @@ using namespace Vulkan_Internal; res = vkCreateDescriptorPool(device->device, &poolInfo, nullptr, &descriptorPool); assert(res == VK_SUCCESS); + // WARNING: MUST NOT CALL reset() HERE! + // This is because init can be called mid-frame when there is allocation error, but the bindings must be retained! + } void GraphicsDevice_Vulkan::FrameResources::DescriptorBinder::destroy() { @@ -1353,6 +1230,7 @@ using namespace Vulkan_Internal; } memset(CBV, 0, sizeof(CBV)); + memset(CBV_offset, 0, sizeof(CBV_offset)); memset(SRV, 0, sizeof(SRV)); memset(SRV_index, -1, sizeof(SRV_index)); memset(UAV, 0, sizeof(UAV)); @@ -1443,14 +1321,14 @@ using namespace Vulkan_Internal; imageInfos.back() = {}; const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_S; - const Sampler* sampler = SAM[original_binding]; - if (sampler == nullptr || !sampler->IsValid()) + const Sampler& sampler = SAM[original_binding]; + if (!sampler.IsValid()) { imageInfos.back().sampler = device->nullSampler; } else { - imageInfos.back().sampler = to_internal(sampler)->resource; + imageInfos.back().sampler = to_internal(&sampler)->resource; } } break; @@ -1462,8 +1340,8 @@ using namespace Vulkan_Internal; imageInfos.back() = {}; const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_T; - const GPUResource* resource = SRV[original_binding]; - if (resource == nullptr || !resource->IsValid() || !resource->IsTexture()) + const GPUResource& resource = SRV[original_binding]; + if (!resource.IsValid() || !resource.IsTexture()) { switch (viewtype) { @@ -1498,14 +1376,14 @@ using namespace Vulkan_Internal; else { int subresource = SRV_index[original_binding]; - const Texture* texture = (const Texture*)resource; + auto texture_internal = to_internal((const Texture*)&resource); if (subresource >= 0) { - imageInfos.back().imageView = to_internal(texture)->subresources_srv[subresource]; + imageInfos.back().imageView = texture_internal->subresources_srv[subresource]; } else { - imageInfos.back().imageView = to_internal(texture)->srv; + imageInfos.back().imageView = texture_internal->srv; } imageInfos.back().imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; @@ -1521,8 +1399,8 @@ using namespace Vulkan_Internal; imageInfos.back().imageLayout = VK_IMAGE_LAYOUT_GENERAL; const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_U; - const GPUResource* resource = UAV[original_binding]; - if (resource == nullptr || !resource->IsValid() || !resource->IsTexture()) + const GPUResource& resource = UAV[original_binding]; + if (!resource.IsValid() || !resource.IsTexture()) { switch (viewtype) { @@ -1556,14 +1434,14 @@ using namespace Vulkan_Internal; else { int subresource = UAV_index[original_binding]; - const Texture* texture = (const Texture*)resource; + auto texture_internal = to_internal((const Texture*)&resource); if (subresource >= 0) { - imageInfos.back().imageView = to_internal(texture)->subresources_uav[subresource]; + imageInfos.back().imageView = texture_internal->subresources_uav[subresource]; } else { - imageInfos.back().imageView = to_internal(texture)->uav; + imageInfos.back().imageView = texture_internal->uav; } } } @@ -1576,28 +1454,20 @@ using namespace Vulkan_Internal; bufferInfos.back() = {}; const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_B; - const GPUBuffer* buffer = CBV[original_binding]; - if (buffer == nullptr || !buffer->IsValid()) + const GPUBuffer& buffer = CBV[original_binding]; + uint64_t offset = CBV_offset[original_binding]; + + if (!buffer.IsValid()) { bufferInfos.back().buffer = device->nullBuffer; bufferInfos.back().range = VK_WHOLE_SIZE; } else { - auto internal_state = to_internal(buffer); - if (buffer->desc.Usage == USAGE_DYNAMIC) - { - const GPUAllocation& allocation = internal_state->dynamic[cmd]; - bufferInfos.back().buffer = to_internal(allocation.buffer)->resource; - bufferInfos.back().offset = allocation.offset; - bufferInfos.back().range = buffer->desc.ByteWidth; - } - else - { - bufferInfos.back().buffer = internal_state->resource; - bufferInfos.back().offset = 0; - bufferInfos.back().range = buffer->desc.ByteWidth; - } + auto internal_state = to_internal(&buffer); + bufferInfos.back().buffer = internal_state->resource; + bufferInfos.back().offset = offset; + bufferInfos.back().range = (VkDeviceSize)std::min(buffer.desc.ByteWidth - offset, (uint64_t)device->properties2.properties.limits.maxUniformBufferRange); } } break; @@ -1609,22 +1479,22 @@ using namespace Vulkan_Internal; texelBufferViews.back() = {}; const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_T; - const GPUResource* resource = SRV[original_binding]; - if (resource == nullptr || !resource->IsValid() || !resource->IsBuffer()) + const GPUResource& resource = SRV[original_binding]; + if (!resource.IsValid() || !resource.IsBuffer()) { texelBufferViews.back() = device->nullBufferView; } else { int subresource = SRV_index[original_binding]; - const GPUBuffer* buffer = (const GPUBuffer*)resource; + auto buffer_internal = to_internal((const GPUBuffer*)&resource); if (subresource >= 0) { - texelBufferViews.back() = to_internal(buffer)->subresources_srv[subresource]; + texelBufferViews.back() = buffer_internal->subresources_srv[subresource]; } else { - texelBufferViews.back() = to_internal(buffer)->srv; + texelBufferViews.back() = buffer_internal->srv; } } } @@ -1637,22 +1507,22 @@ using namespace Vulkan_Internal; texelBufferViews.back() = {}; const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_U; - const GPUResource* resource = UAV[original_binding]; - if (resource == nullptr || !resource->IsValid() || !resource->IsBuffer()) + const GPUResource& resource = UAV[original_binding]; + if (!resource.IsValid() || !resource.IsBuffer()) { texelBufferViews.back() = device->nullBufferView; } else { int subresource = UAV_index[original_binding]; - const GPUBuffer* buffer = (const GPUBuffer*)resource; + auto buffer_internal = to_internal((const GPUBuffer*)&resource); if (subresource >= 0) { - texelBufferViews.back() = to_internal(buffer)->subresources_uav[subresource]; + texelBufferViews.back() = buffer_internal->subresources_uav[subresource]; } else { - texelBufferViews.back() = to_internal(buffer)->uav; + texelBufferViews.back() = buffer_internal->uav; } } } @@ -1668,8 +1538,8 @@ using namespace Vulkan_Internal; { // SRV const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_T; - const GPUResource* resource = SRV[original_binding]; - if (resource == nullptr || !resource->IsValid() || !resource->IsBuffer()) + const GPUResource& resource = SRV[original_binding]; + if (!resource.IsValid() || !resource.IsBuffer()) { bufferInfos.back().buffer = device->nullBuffer; bufferInfos.back().range = VK_WHOLE_SIZE; @@ -1677,17 +1547,17 @@ using namespace Vulkan_Internal; else { int subresource = SRV_index[original_binding]; - const GPUBuffer* buffer = (const GPUBuffer*)resource; - bufferInfos.back().buffer = to_internal(buffer)->resource; - bufferInfos.back().range = buffer->desc.ByteWidth; + auto buffer_internal = to_internal((const GPUBuffer*)&resource); + bufferInfos.back().buffer = buffer_internal->resource; + bufferInfos.back().range = VK_WHOLE_SIZE; } } else { // UAV const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_U; - const GPUResource* resource = UAV[original_binding]; - if (resource == nullptr || !resource->IsValid() || !resource->IsBuffer()) + const GPUResource& resource = UAV[original_binding]; + if (!resource.IsValid() || !resource.IsBuffer()) { bufferInfos.back().buffer = device->nullBuffer; bufferInfos.back().range = VK_WHOLE_SIZE; @@ -1695,9 +1565,9 @@ using namespace Vulkan_Internal; else { int subresource = UAV_index[original_binding]; - const GPUBuffer* buffer = (const GPUBuffer*)resource; - bufferInfos.back().buffer = to_internal(buffer)->resource; - bufferInfos.back().range = buffer->desc.ByteWidth; + auto buffer_internal = to_internal((const GPUBuffer*)&resource); + bufferInfos.back().buffer = buffer_internal->resource; + bufferInfos.back().range = VK_WHOLE_SIZE; } } } @@ -1712,15 +1582,15 @@ using namespace Vulkan_Internal; accelerationStructureViews.back().accelerationStructureCount = 1; const uint32_t original_binding = unrolled_binding - VULKAN_BINDING_SHIFT_T; - const GPUResource* resource = SRV[original_binding]; - if (resource == nullptr || !resource->IsValid() || !resource->IsAccelerationStructure()) + const GPUResource& resource = SRV[original_binding]; + if (!resource.IsValid() || !resource.IsAccelerationStructure()) { assert(0); // invalid acceleration structure! } else { - const RaytracingAccelerationStructure* as = (const RaytracingAccelerationStructure*)resource; - accelerationStructureViews.back().pAccelerationStructures = &to_internal(as)->resource; + auto as_internal = to_internal((const RaytracingAccelerationStructure*)&resource); + accelerationStructureViews.back().pAccelerationStructures = &as_internal->resource; } } break; @@ -1944,123 +1814,40 @@ using namespace Vulkan_Internal; vkCmdBindPipeline(GetCommandList(cmd), VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); } - void GraphicsDevice_Vulkan::barrier_flush(CommandList cmd) - { - auto& memoryBarriers = frame_memoryBarriers[cmd]; - auto& imageBarriers = frame_imageBarriers[cmd]; - auto& bufferBarriers = frame_bufferBarriers[cmd]; - - if (!memoryBarriers.empty() || - !bufferBarriers.empty() || - !imageBarriers.empty() - ) - { - // Remove NOP barriers: - for (size_t i = 0; i < memoryBarriers.size(); ++i) - { - auto& barrier = memoryBarriers[i]; - if (barrier.srcAccessMask == barrier.dstAccessMask) - { - barrier = memoryBarriers.back(); - memoryBarriers.pop_back(); - i--; - } - } - for (size_t i = 0; i < bufferBarriers.size(); ++i) - { - auto& barrier = bufferBarriers[i]; - if (barrier.srcAccessMask == barrier.dstAccessMask) - { - barrier = bufferBarriers.back(); - bufferBarriers.pop_back(); - i--; - } - } - for (size_t i = 0; i < imageBarriers.size(); ++i) - { - auto& barrier = imageBarriers[i]; - if (barrier.oldLayout == barrier.newLayout) - { - barrier = imageBarriers.back(); - imageBarriers.pop_back(); - i--; - } - } - - if (!memoryBarriers.empty() || - !bufferBarriers.empty() || - !imageBarriers.empty() - ) - { - VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; - VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; - - if (CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) || CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) - { - srcStage |= VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR; - dstStage |= VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR; - } - - vkCmdPipelineBarrier( - GetCommandList(cmd), - srcStage, - dstStage, - 0, - (uint32_t)memoryBarriers.size(), memoryBarriers.data(), - (uint32_t)bufferBarriers.size(), bufferBarriers.data(), - (uint32_t)imageBarriers.size(), imageBarriers.data() - ); - - memoryBarriers.clear(); - imageBarriers.clear(); - bufferBarriers.clear(); - } - } - } void GraphicsDevice_Vulkan::predraw(CommandList cmd) { pso_validate(cmd); GetFrameResources().descriptors[cmd].flush(true, cmd); - if (pushconstants[cmd].size > 0) + auto pso_internal = to_internal(active_pso[cmd]); + if (pso_internal->pushconstants.size > 0) { - auto pso_internal = to_internal(active_pso[cmd]); - if (pso_internal->pushconstants.size > 0) - { - vkCmdPushConstants( - GetCommandList(cmd), - pso_internal->pipelineLayout, - pso_internal->pushconstants.stageFlags, - pso_internal->pushconstants.offset, - pso_internal->pushconstants.size, - pushconstants[cmd].data - ); - pushconstants[cmd].size = 0; - } + vkCmdPushConstants( + GetCommandList(cmd), + pso_internal->pipelineLayout, + pso_internal->pushconstants.stageFlags, + pso_internal->pushconstants.offset, + pso_internal->pushconstants.size, + pushconstants[cmd].data + ); } } void GraphicsDevice_Vulkan::predispatch(CommandList cmd) { - barrier_flush(cmd); - GetFrameResources().descriptors[cmd].flush(false, cmd); - if (pushconstants[cmd].size > 0) + auto cs_internal = to_internal(active_cs[cmd]); + if (cs_internal->pushconstants.size > 0) { - auto cs_internal = to_internal(active_cs[cmd]); - if (cs_internal->pushconstants.size > 0) - { - vkCmdPushConstants( - GetCommandList(cmd), - cs_internal->pipelineLayout_cs, - cs_internal->pushconstants.stageFlags, - cs_internal->pushconstants.offset, - cs_internal->pushconstants.size, - pushconstants[cmd].data - ); - pushconstants[cmd].size = 0; - } + vkCmdPushConstants( + GetCommandList(cmd), + cs_internal->pipelineLayout_cs, + cs_internal->pushconstants.stageFlags, + cs_internal->pushconstants.offset, + cs_internal->pushconstants.size, + pushconstants[cmd].data + ); } } @@ -2339,21 +2126,16 @@ using namespace Vulkan_Internal; } capabilities |= GRAPHICSDEVICE_CAPABILITY_RENDERTARGET_AND_VIEWPORT_ARRAYINDEX_WITHOUT_GS; // let's hope for the best... - if (raytracing_features.rayTracingPipeline == VK_TRUE) + if ( + raytracing_features.rayTracingPipeline == VK_TRUE && + raytracing_query_features.rayQuery == VK_TRUE && + acceleration_structure_features.accelerationStructure == VK_TRUE && + features_1_2.bufferDeviceAddress == VK_TRUE + ) { - assert(acceleration_structure_features.accelerationStructure == VK_TRUE); - assert(features_1_2.bufferDeviceAddress == VK_TRUE); - capabilities |= GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE; - capabilities |= GRAPHICSDEVICE_CAPABILITY_RAYTRACING_GEOMETRYINDEX; + capabilities |= GRAPHICSDEVICE_CAPABILITY_RAYTRACING; SHADER_IDENTIFIER_SIZE = raytracing_properties.shaderGroupHandleSize; } - if (raytracing_query_features.rayQuery == VK_TRUE) - { - assert(acceleration_structure_features.accelerationStructure == VK_TRUE); - assert(features_1_2.bufferDeviceAddress == VK_TRUE); - capabilities |= GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE; - capabilities |= GRAPHICSDEVICE_CAPABILITY_RAYTRACING_GEOMETRYINDEX; - } if (mesh_shader_features.meshShader == VK_TRUE && mesh_shader_features.taskShader == VK_TRUE) { capabilities |= GRAPHICSDEVICE_CAPABILITY_MESH_SHADER; @@ -2368,12 +2150,7 @@ using namespace Vulkan_Internal; VARIABLE_RATE_SHADING_TILE_SIZE = std::min(fragment_shading_rate_properties.maxFragmentShadingRateAttachmentTexelSize.width, fragment_shading_rate_properties.maxFragmentShadingRateAttachmentTexelSize.height); } - assert(features_1_2.hostQueryReset == VK_TRUE); - - if (features_1_2.descriptorIndexing) - { - capabilities |= GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS; - } + assert(features_1_2.descriptorIndexing == VK_TRUE); VkFormatProperties formatProperties = {}; vkGetPhysicalDeviceFormatProperties(physicalDevice, _ConvertFormat(FORMAT_R11G11B10_FLOAT), &formatProperties); @@ -2729,10 +2506,6 @@ using namespace Vulkan_Internal; dynamicStateInfo.dynamicStateCount = (uint32_t)pso_dynamicStates.size(); dynamicStateInfo.pDynamicStates = pso_dynamicStates.data(); - if (features_1_2.descriptorBindingUniformBufferUpdateAfterBind) - { - allocationhandler->bindlessUniformBuffers.init(device, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, properties_1_2.maxDescriptorSetUpdateAfterBindUniformBuffers / 4); - } if (features_1_2.descriptorBindingSampledImageUpdateAfterBind) { allocationhandler->bindlessSampledImages.init(device, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, properties_1_2.maxDescriptorSetUpdateAfterBindSampledImages / 4); @@ -2757,11 +2530,18 @@ using namespace Vulkan_Internal; { allocationhandler->bindlessSamplers.init(device, VK_DESCRIPTOR_TYPE_SAMPLER, 256); } - if (CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) || CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { allocationhandler->bindlessAccelerationStructures.init(device, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 32); } + ALLOCATION_MIN_ALIGNMENT = std::max( + properties2.properties.limits.minUniformBufferOffsetAlignment, + std::max( + properties2.properties.limits.minStorageBufferOffsetAlignment, + properties2.properties.limits.minTexelBufferOffsetAlignment + ) + ); wiBackLog::post("Created GraphicsDevice_Vulkan"); } @@ -3115,15 +2895,11 @@ using namespace Vulkan_Internal; internal_state->allocationhandler = allocationhandler; pBuffer->internal_state = internal_state; pBuffer->type = GPUResource::GPU_RESOURCE_TYPE::BUFFER; + pBuffer->mapped_data = nullptr; + pBuffer->mapped_rowpitch = 0; pBuffer->desc = *pDesc; - if (pDesc->Usage == USAGE_DYNAMIC && pDesc->BindFlags & BIND_CONSTANT_BUFFER) - { - // this special case will use frame allocator - return true; - } - VkBufferCreateInfo bufferInfo = {}; bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferInfo.size = pBuffer->desc.ByteWidth; @@ -3162,6 +2938,14 @@ using namespace Vulkan_Internal; bufferInfo.usage |= VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT; } } + if (pBuffer->desc.MiscFlags & RESOURCE_MISC_BUFFER_RAW) + { + bufferInfo.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + } + if (pBuffer->desc.MiscFlags & RESOURCE_MISC_BUFFER_STRUCTURED) + { + bufferInfo.usage |= VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; + } if (pBuffer->desc.MiscFlags & RESOURCE_MISC_INDIRECT_ARGS) { bufferInfo.usage |= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT; @@ -3198,28 +2982,28 @@ using namespace Vulkan_Internal; //allocInfo.flags = VMA_ALLOCATION_CREATE_STRATEGY_MIN_MEMORY_BIT; //allocInfo.flags = VMA_ALLOCATION_CREATE_STRATEGY_MIN_FRAGMENTATION_BIT; allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; - if (pDesc->Usage == USAGE_STAGING) + if (pDesc->Usage == USAGE_READBACK) { - if (pDesc->CPUAccessFlags & CPU_ACCESS_READ) - { - allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU; - bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; - } - else - { - allocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY; - allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; - bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; - } + allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; + allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU; + bufferInfo.usage |= VK_BUFFER_USAGE_TRANSFER_DST_BIT; } - if (pDesc->Usage == USAGE_DYNAMIC) + else if(pDesc->Usage == USAGE_UPLOAD) { - allocInfo.usage = VMA_MEMORY_USAGE_CPU_TO_GPU; + allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; + allocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY; + bufferInfo.usage |= VK_BUFFER_USAGE_TRANSFER_SRC_BIT; } res = vmaCreateBuffer(allocationhandler->allocator, &bufferInfo, &allocInfo, &internal_state->resource, &internal_state->allocation, nullptr); assert(res == VK_SUCCESS); + if (pDesc->Usage == USAGE_READBACK || pDesc->Usage == USAGE_UPLOAD) + { + pBuffer->mapped_data = internal_state->allocation->GetMappedData(); + pBuffer->mapped_rowpitch = pDesc->ByteWidth; + } + if (bufferInfo.usage & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) { VkBufferDeviceAddressInfo info = {}; @@ -3313,7 +3097,7 @@ using namespace Vulkan_Internal; copyAllocator.submit(cmd); } } - else if(pDesc->Usage != USAGE_STAGING) + else if(pDesc->Usage != USAGE_UPLOAD && pDesc->Usage != USAGE_READBACK) { // zero-initialize: initLocker.lock(); @@ -3339,10 +3123,6 @@ using namespace Vulkan_Internal; // Create resource views if needed - if (pDesc->BindFlags & BIND_CONSTANT_BUFFER) - { - CreateSubresource(pBuffer, CBV, 0); - } if (pDesc->BindFlags & BIND_SHADER_RESOURCE) { CreateSubresource(pBuffer, SRV, 0); @@ -3362,6 +3142,8 @@ using namespace Vulkan_Internal; internal_state->allocationhandler = allocationhandler; pTexture->internal_state = internal_state; pTexture->type = GPUResource::GPU_RESOURCE_TYPE::TEXTURE; + pTexture->mapped_data = nullptr; + pTexture->mapped_rowpitch = 0; pTexture->desc = *pDesc; @@ -3398,12 +3180,12 @@ using namespace Vulkan_Internal; if (pTexture->desc.BindFlags & BIND_RENDER_TARGET) { imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - allocInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; + //allocInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; } if (pTexture->desc.BindFlags & BIND_DEPTH_STENCIL) { imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - allocInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; + //allocInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; } if(pTexture->desc.BindFlags & BIND_SHADING_RATE) { @@ -3448,23 +3230,22 @@ using namespace Vulkan_Internal; VkResult res; - if (pTexture->desc.Usage == USAGE_STAGING) + if (pTexture->desc.Usage == USAGE_READBACK || pTexture->desc.Usage == USAGE_UPLOAD) { VkBufferCreateInfo bufferInfo = {}; bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferInfo.size = imageInfo.extent.width * imageInfo.extent.height * imageInfo.extent.depth * imageInfo.arrayLayers * GetFormatStride(pTexture->desc.Format); - if (pDesc->CPUAccessFlags & CPU_ACCESS_READ) + allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; + if (pTexture->desc.Usage == USAGE_READBACK) { - allocInfo.flags |= VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; // I don't know why but consecutive resource downloads could fail without this allocInfo.usage = VMA_MEMORY_USAGE_GPU_TO_CPU; bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT; } - else + else if(pTexture->desc.Usage == USAGE_UPLOAD) { allocInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY; - allocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; } @@ -3480,6 +3261,12 @@ using namespace Vulkan_Internal; subresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; vkGetImageSubresourceLayout(device, image, &subresource, &internal_state->subresourcelayout); + if (pDesc->Usage == USAGE_READBACK || pTexture->desc.Usage == USAGE_UPLOAD) + { + pTexture->mapped_data = internal_state->allocation->GetMappedData(); + pTexture->mapped_rowpitch = (uint32_t)internal_state->subresourcelayout.rowPitch; + } + vkDestroyImage(device, image, nullptr); return res == VK_SUCCESS; } @@ -3572,7 +3359,7 @@ using namespace Vulkan_Internal; barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; barrier.newLayout = _ConvertImageLayout(pTexture->desc.layout); barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = _ParseImageLayout(pTexture->desc.layout); + barrier.dstAccessMask = _ParseResourceState(pTexture->desc.layout); initLocker.lock(); vkCmdPipelineBarrier( @@ -3596,7 +3383,7 @@ using namespace Vulkan_Internal; barrier.oldLayout = imageInfo.initialLayout; barrier.newLayout = _ConvertImageLayout(pTexture->desc.layout); barrier.srcAccessMask = 0; - barrier.dstAccessMask = _ParseImageLayout(pTexture->desc.layout); + barrier.dstAccessMask = _ParseResourceState(pTexture->desc.layout); if (pTexture->desc.BindFlags & BIND_DEPTH_STENCIL) { barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; @@ -3912,8 +3699,7 @@ using namespace Vulkan_Internal; switch (x.descriptorType) { case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: - layouts.push_back(allocationhandler->bindlessUniformBuffers.descriptorSetLayout); - internal_state->bindlessSets.push_back(allocationhandler->bindlessUniformBuffers.descriptorSet); + assert(0); // not supported, use the raw buffers for same functionality break; case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: layouts.push_back(allocationhandler->bindlessSampledImages.descriptorSetLayout); @@ -3966,12 +3752,13 @@ using namespace Vulkan_Internal; res = vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &internal_state->pipelineLayout_cs); assert(res == VK_SUCCESS); pso_layout_cache[internal_state->binding_hash].pipelineLayout = internal_state->pipelineLayout_cs; + pso_layout_cache[internal_state->binding_hash].bindlessSets = internal_state->bindlessSets; + pso_layout_cache[internal_state->binding_hash].bindlessFirstSet = internal_state->bindlessFirstSet; } - else - { - internal_state->descriptorSetLayout = pso_layout_cache[internal_state->binding_hash].descriptorSetLayout; - internal_state->pipelineLayout_cs = pso_layout_cache[internal_state->binding_hash].pipelineLayout; - } + internal_state->descriptorSetLayout = pso_layout_cache[internal_state->binding_hash].descriptorSetLayout; + internal_state->pipelineLayout_cs = pso_layout_cache[internal_state->binding_hash].pipelineLayout; + internal_state->bindlessSets = pso_layout_cache[internal_state->binding_hash].bindlessSets; + internal_state->bindlessFirstSet = pso_layout_cache[internal_state->binding_hash].bindlessFirstSet; pso_layout_cache_mutex.unlock(); } } @@ -4223,7 +4010,6 @@ using namespace Vulkan_Internal; VkResult res = vkCreateQueryPool(device, &poolInfo, nullptr, &internal_state->pool); assert(res == VK_SUCCESS); - vkResetQueryPool(device, internal_state->pool, 0, poolInfo.queryCount); return res == VK_SUCCESS; } @@ -4293,9 +4079,10 @@ using namespace Vulkan_Internal; if (shader_internal->pushconstants.size > 0) { - internal_state->pushconstants.offset = shader_internal->pushconstants.offset; - internal_state->pushconstants.size = shader_internal->pushconstants.size; - internal_state->pushconstants.stageFlags |= shader_internal->pushconstants.stageFlags; + internal_state->pushconstants.offset = std::min(internal_state->pushconstants.offset, shader_internal->pushconstants.offset); + internal_state->pushconstants.size = std::max(internal_state->pushconstants.size, shader_internal->pushconstants.size); + //internal_state->pushconstants.stageFlags |= shader_internal->pushconstants.stageFlags; + internal_state->pushconstants.stageFlags = VK_SHADER_STAGE_ALL_GRAPHICS; // combining only the used stage flags gives some validation errors for some reason while rendering... } }; @@ -4376,8 +4163,7 @@ using namespace Vulkan_Internal; switch (x.descriptorType) { case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: - layouts.push_back(allocationhandler->bindlessUniformBuffers.descriptorSetLayout); - pso_layout_cache[internal_state->binding_hash].bindlessSets.push_back(allocationhandler->bindlessUniformBuffers.descriptorSet); + assert(0); // not supported, use the raw buffers for same functionality break; case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: layouts.push_back(allocationhandler->bindlessSampledImages.descriptorSetLayout); @@ -5077,7 +4863,6 @@ using namespace Vulkan_Internal; VmaAllocationCreateInfo allocInfo = {}; allocInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY; - allocInfo.flags = VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT; VkResult res = vmaCreateBuffer( allocationhandler->allocator, @@ -5495,29 +5280,6 @@ using namespace Vulkan_Internal; switch (type) { - case wiGraphics::CBV: - { - int index = allocationhandler->bindlessUniformBuffers.allocate(); - if (index >= 0) - { - VkDescriptorBufferInfo bufferInfo = {}; - bufferInfo.buffer = internal_state->resource; - bufferInfo.offset = offset; - bufferInfo.range = size; - VkWriteDescriptorSet write = {}; - write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - write.dstBinding = 0; - write.dstArrayElement = index; - write.descriptorCount = 1; - write.dstSet = allocationhandler->bindlessUniformBuffers.descriptorSet; - write.pBufferInfo = &bufferInfo; - vkUpdateDescriptorSets(device, 1, &write, 0, nullptr); - internal_state->cbv_index = index; - } - return -1; - } - break; case wiGraphics::SRV: case wiGraphics::UAV: @@ -5656,13 +5418,6 @@ using namespace Vulkan_Internal; switch (type) { default: - case wiGraphics::CBV: - if (resource->IsBuffer()) - { - auto internal_state = to_internal((const GPUBuffer*)resource); - return internal_state->cbv_index; - } - break; case wiGraphics::SRV: if (resource->IsBuffer()) { @@ -5784,82 +5539,6 @@ using namespace Vulkan_Internal; assert(res == VK_SUCCESS); } - void GraphicsDevice_Vulkan::Map(const GPUResource* resource, Mapping* mapping) const - { - VkDeviceMemory memory = VK_NULL_HANDLE; - - if (resource->type == GPUResource::GPU_RESOURCE_TYPE::BUFFER) - { - const GPUBuffer* buffer = (const GPUBuffer*)resource; - auto internal_state = to_internal(buffer); - memory = internal_state->allocation->GetMemory(); - mapping->rowpitch = (uint32_t)buffer->desc.ByteWidth; - } - else if (resource->type == GPUResource::GPU_RESOURCE_TYPE::TEXTURE) - { - const Texture* texture = (const Texture*)resource; - auto internal_state = to_internal(texture); - memory = internal_state->allocation->GetMemory(); - mapping->rowpitch = (uint32_t)internal_state->subresourcelayout.rowPitch; - } - else - { - assert(0); - return; - } - - VkDeviceSize offset = mapping->offset; - VkDeviceSize size = mapping->size; - - VkResult res = vkMapMemory(device, memory, offset, size, 0, &mapping->data); - if (res != VK_SUCCESS) - { - assert(0); - mapping->data = nullptr; - mapping->rowpitch = 0; - } - } - void GraphicsDevice_Vulkan::Unmap(const GPUResource* resource) const - { - if (resource->type == GPUResource::GPU_RESOURCE_TYPE::BUFFER) - { - const GPUBuffer* buffer = (const GPUBuffer*)resource; - auto internal_state = to_internal(buffer); - vkUnmapMemory(device, internal_state->allocation->GetMemory()); - } - else if (resource->type == GPUResource::GPU_RESOURCE_TYPE::TEXTURE) - { - const Texture* texture = (const Texture*)resource; - auto internal_state = to_internal(texture); - vkUnmapMemory(device, internal_state->allocation->GetMemory()); - } - } - void GraphicsDevice_Vulkan::QueryRead(const GPUQueryHeap* heap, uint32_t index, uint32_t count, uint64_t* results) const - { - if (count == 0) - return; - - auto internal_state = to_internal(heap); - - VkResult res = vkGetQueryPoolResults( - device, - internal_state->pool, - index, - count, - sizeof(uint64_t) * count, - results, - sizeof(uint64_t), - VK_QUERY_RESULT_64_BIT - ); - - vkResetQueryPool( - device, - internal_state->pool, - index, - count - ); - } - void GraphicsDevice_Vulkan::SetCommonSampler(const StaticSampler* sam) { common_samplers.push_back(*sam); @@ -5941,7 +5620,6 @@ using namespace Vulkan_Internal; res = vkAllocateCommandBuffers(device, &commandBufferInfo, &frame.commandBuffers[cmd][queue]); assert(res == VK_SUCCESS); - frame.resourceBuffer[cmd].init(this, 1024 * 1024); // 1 MB starting size frame.descriptors[cmd].init(this); } } @@ -5960,9 +5638,6 @@ using namespace Vulkan_Internal; // reset descriptor allocators: GetFrameResources().descriptors[cmd].reset(); - // reset immediate resource allocators: - GetFrameResources().resourceBuffer[cmd].clear(); - if (queue == QUEUE_GRAPHICS) { VkRect2D scissors[8]; @@ -6020,8 +5695,6 @@ using namespace Vulkan_Internal; cmd_count.store(0); for (CommandList cmd = 0; cmd < cmd_last; ++cmd) { - barrier_flush(cmd); - res = vkEndCommandBuffer(GetCommandList(cmd)); assert(res == VK_SUCCESS); @@ -6225,7 +5898,6 @@ using namespace Vulkan_Internal; // return; // } //} - barrier_flush(cmd); VkClearValue clearColor = { swapchain->desc.clearcolor[0], @@ -6246,8 +5918,6 @@ using namespace Vulkan_Internal; } void GraphicsDevice_Vulkan::RenderPassBegin(const RenderPass* renderpass, CommandList cmd) { - barrier_flush(cmd); - active_renderpass[cmd] = renderpass; auto internal_state = to_internal(renderpass); @@ -6257,7 +5927,7 @@ using namespace Vulkan_Internal; { vkCmdEndRenderPass(GetCommandList(cmd)); - active_renderpass[cmd] = VK_NULL_HANDLE; + active_renderpass[cmd] = nullptr; } void GraphicsDevice_Vulkan::BindScissorRects(uint32_t numRects, const Rect* rects, CommandList cmd) { @@ -6288,71 +5958,66 @@ using namespace Vulkan_Internal; } vkCmdSetViewport(GetCommandList(cmd), 0, NumViewports, vp); } - void GraphicsDevice_Vulkan::BindResource(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource) + void GraphicsDevice_Vulkan::BindResource(const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource) { - assert(slot < GPU_RESOURCE_HEAP_SRV_COUNT); + assert(slot < DESCRIPTORBINDER_SRV_COUNT); auto& descriptors = GetFrameResources().descriptors[cmd]; - if (descriptors.SRV[slot] != resource || descriptors.SRV_index[slot] != subresource) + if (descriptors.SRV[slot].internal_state != resource->internal_state || descriptors.SRV_index[slot] != subresource) { - descriptors.SRV[slot] = resource; + descriptors.SRV[slot] = *resource; descriptors.SRV_index[slot] = subresource; descriptors.dirty = true; } } - void GraphicsDevice_Vulkan::BindResources(SHADERSTAGE stage, const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) + void GraphicsDevice_Vulkan::BindResources(const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) { if (resources != nullptr) { for (uint32_t i = 0; i < count; ++i) { - BindResource(stage, resources[i], slot + i, cmd, -1); + BindResource(resources[i], slot + i, cmd, -1); } } } - void GraphicsDevice_Vulkan::BindUAV(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource) + void GraphicsDevice_Vulkan::BindUAV(const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource) { - assert(slot < GPU_RESOURCE_HEAP_UAV_COUNT); + assert(slot < DESCRIPTORBINDER_UAV_COUNT); auto& descriptors = GetFrameResources().descriptors[cmd]; - if (descriptors.UAV[slot] != resource || descriptors.UAV_index[slot] != subresource) + if (descriptors.UAV[slot].internal_state != resource->internal_state || descriptors.UAV_index[slot] != subresource) { - descriptors.UAV[slot] = resource; + descriptors.UAV[slot] = *resource; descriptors.UAV_index[slot] = subresource; descriptors.dirty = true; } } - void GraphicsDevice_Vulkan::BindUAVs(SHADERSTAGE stage, const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) + void GraphicsDevice_Vulkan::BindUAVs(const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) { if (resources != nullptr) { for (uint32_t i = 0; i < count; ++i) { - BindUAV(stage, resources[i], slot + i, cmd, -1); + BindUAV(resources[i], slot + i, cmd, -1); } } } - void GraphicsDevice_Vulkan::UnbindResources(uint32_t slot, uint32_t num, CommandList cmd) + void GraphicsDevice_Vulkan::BindSampler(const Sampler* sampler, uint32_t slot, CommandList cmd) { - } - void GraphicsDevice_Vulkan::UnbindUAVs(uint32_t slot, uint32_t num, CommandList cmd) - { - } - void GraphicsDevice_Vulkan::BindSampler(SHADERSTAGE stage, const Sampler* sampler, uint32_t slot, CommandList cmd) - { - assert(slot < GPU_SAMPLER_HEAP_COUNT); + assert(slot < DESCRIPTORBINDER_SAMPLER_COUNT); auto& descriptors = GetFrameResources().descriptors[cmd]; - if (descriptors.SAM[slot] != sampler) + if (descriptors.SAM[slot].internal_state != sampler->internal_state) { - descriptors.SAM[slot] = sampler; + descriptors.SAM[slot] = *sampler; descriptors.dirty = true; } } - void GraphicsDevice_Vulkan::BindConstantBuffer(SHADERSTAGE stage, const GPUBuffer* buffer, uint32_t slot, CommandList cmd) + void GraphicsDevice_Vulkan::BindConstantBuffer(const GPUBuffer* buffer, uint32_t slot, CommandList cmd, uint64_t offset) { - assert(slot < GPU_RESOURCE_HEAP_CBV_COUNT); + assert(slot < DESCRIPTORBINDER_CBV_COUNT); auto& descriptors = GetFrameResources().descriptors[cmd]; - if (buffer->desc.Usage == USAGE_DYNAMIC || descriptors.CBV[slot] != buffer) + if (descriptors.CBV[slot].internal_state != buffer->internal_state || descriptors.CBV_offset[slot] != offset) { - descriptors.CBV[slot] = buffer; + descriptors.CBV[slot] = *buffer; + descriptors.CBV_offset[slot] = offset; descriptors.dirty = true; } } @@ -6648,8 +6313,6 @@ using namespace Vulkan_Internal; } void GraphicsDevice_Vulkan::CopyResource(const GPUResource* pDst, const GPUResource* pSrc, CommandList cmd) { - barrier_flush(cmd); - if (pDst->type == GPUResource::GPU_RESOURCE_TYPE::TEXTURE && pSrc->type == GPUResource::GPU_RESOURCE_TYPE::TEXTURE) { auto internal_state_src = to_internal((const Texture*)pSrc); @@ -6658,7 +6321,7 @@ using namespace Vulkan_Internal; const TextureDesc& src_desc = ((const Texture*)pSrc)->GetDesc(); const TextureDesc& dst_desc = ((const Texture*)pDst)->GetDesc(); - if (src_desc.Usage & USAGE_STAGING) + if (src_desc.Usage == USAGE_UPLOAD) { VkBufferImageCopy copy = {}; copy.imageExtent.width = dst_desc.Width; @@ -6676,7 +6339,7 @@ using namespace Vulkan_Internal; © ); } - else if (dst_desc.Usage & USAGE_STAGING) + else if (dst_desc.Usage == USAGE_READBACK) { VkBufferImageCopy copy = {}; copy.imageExtent.width = src_desc.Width; @@ -6768,92 +6431,21 @@ using namespace Vulkan_Internal; ); } } - void GraphicsDevice_Vulkan::UpdateBuffer(const GPUBuffer* buffer, const void* data, CommandList cmd, int dataSize) + void GraphicsDevice_Vulkan::CopyBuffer(const GPUBuffer* pDst, uint64_t dst_offset, const GPUBuffer* pSrc, uint64_t src_offset, uint64_t size, CommandList cmd) { - assert(buffer->desc.Usage != USAGE_IMMUTABLE && "Cannot update IMMUTABLE GPUBuffer!"); - assert((int)buffer->desc.ByteWidth >= dataSize || dataSize < 0 && "Data size is too big!"); + auto internal_state_src = to_internal((const GPUBuffer*)pSrc); + auto internal_state_dst = to_internal((const GPUBuffer*)pDst); - if (dataSize == 0) - { - return; - } - - dataSize = std::min((int)buffer->desc.ByteWidth, dataSize); - dataSize = (dataSize >= 0 ? dataSize : buffer->desc.ByteWidth); - - auto internal_state_dst = to_internal(buffer); - - GPUAllocation allocation = AllocateGPU(dataSize, cmd); - memcpy(allocation.data, data, dataSize); - - if (buffer->desc.Usage == USAGE_DYNAMIC && buffer->desc.BindFlags & BIND_CONSTANT_BUFFER) - { - // Dynamic buffer will be used from host memory directly: - internal_state_dst->dynamic[cmd] = allocation; - GetFrameResources().descriptors[cmd].dirty = true; - } - else - { - // Contents will be transferred to device memory: - assert(active_renderpass[cmd] == nullptr); // must not be inside render pass - - auto internal_state_src = to_internal(&GetFrameResources().resourceBuffer[cmd].buffer); - - VkBufferMemoryBarrier barrier = {}; - barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; - barrier.buffer = internal_state_dst->resource; - barrier.srcAccessMask = 0; - if (buffer->desc.BindFlags & BIND_CONSTANT_BUFFER) - { - barrier.srcAccessMask |= VK_ACCESS_UNIFORM_READ_BIT; - } - if (buffer->desc.BindFlags & BIND_VERTEX_BUFFER) - { - barrier.srcAccessMask |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT; - } - if (buffer->desc.BindFlags & BIND_INDEX_BUFFER) - { - barrier.srcAccessMask |= VK_ACCESS_INDEX_READ_BIT; - } - if (buffer->desc.BindFlags & BIND_SHADER_RESOURCE) - { - barrier.srcAccessMask |= VK_ACCESS_SHADER_READ_BIT; - } - if (buffer->desc.BindFlags & BIND_UNORDERED_ACCESS) - { - barrier.srcAccessMask |= VK_ACCESS_SHADER_WRITE_BIT; - } - if (buffer->desc.MiscFlags & RESOURCE_MISC_RAY_TRACING) - { - barrier.srcAccessMask |= VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; - } - barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - barrier.size = VK_WHOLE_SIZE; - - frame_bufferBarriers[cmd].push_back(barrier); - barrier_flush(cmd); - - VkBufferCopy copyRegion = {}; - copyRegion.size = dataSize; - copyRegion.srcOffset = (VkDeviceSize)allocation.offset; - copyRegion.dstOffset = 0; - - vkCmdCopyBuffer( - GetCommandList(cmd), - internal_state_src->resource, - internal_state_dst->resource, - 1, - ©Region - ); - - // reverse barrier: - std::swap(barrier.srcAccessMask, barrier.dstAccessMask); - frame_bufferBarriers[cmd].push_back(barrier); - - } + VkBufferCopy copy = {}; + copy.srcOffset = src_offset; + copy.dstOffset = dst_offset; + copy.size = size; + vkCmdCopyBuffer(GetCommandList(cmd), + internal_state_src->resource, + internal_state_dst->resource, + 1, © + ); } void GraphicsDevice_Vulkan::QueryBegin(const GPUQueryHeap* heap, uint32_t index, CommandList cmd) { @@ -6876,7 +6468,7 @@ using namespace Vulkan_Internal; switch (heap->desc.type) { case GPU_QUERY_TYPE_TIMESTAMP: - vkCmdWriteTimestamp(GetCommandList(cmd), VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, internal_state->pool, index); + vkCmdWriteTimestamp(GetCommandList(cmd), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, internal_state->pool, index); break; case GPU_QUERY_TYPE_OCCLUSION_BINARY: case GPU_QUERY_TYPE_OCCLUSION: @@ -6884,6 +6476,55 @@ using namespace Vulkan_Internal; break; } } + void GraphicsDevice_Vulkan::QueryResolve(const GPUQueryHeap* heap, uint32_t index, uint32_t count, const GPUBuffer* dest, uint64_t dest_offset, CommandList cmd) + { + assert(active_renderpass[cmd] == nullptr); // Can't resolve inside renderpass! + + // Looks like the vulkan needs this barrier, otherwise the queries didn't finish + // It was still a problem with VK_QUERY_RESULT_WAIT_BIT, but that + // also caused deadlocks, so I decided to do a safer memory barrier here + GPUBarrier memory_barrier = GPUBarrier::Memory(); + Barrier(&memory_barrier, 1, cmd); + + auto internal_state = to_internal(heap); + auto dst_internal = to_internal(dest); + + VkQueryResultFlags flags = VK_QUERY_RESULT_64_BIT; + + switch (heap->desc.type) + { + case GPU_QUERY_TYPE_OCCLUSION_BINARY: + flags |= VK_QUERY_RESULT_PARTIAL_BIT; + break; + default: + break; + } + + vkCmdCopyQueryPoolResults( + GetCommandList(cmd), + internal_state->pool, + index, + count, + dst_internal->resource, + dest_offset, + sizeof(uint64_t), + flags + ); + + } + void GraphicsDevice_Vulkan::QueryReset(const GPUQueryHeap* heap, uint32_t index, uint32_t count, CommandList cmd) + { + assert(active_renderpass[cmd] == nullptr); // Can't resolve inside renderpass! + + auto internal_state = to_internal(heap); + + vkCmdResetQueryPool( + GetCommandList(cmd), + internal_state->pool, + index, + count + ); + } void GraphicsDevice_Vulkan::Barrier(const GPUBarrier* barriers, uint32_t numBarriers, CommandList cmd) { auto& memoryBarriers = frame_memoryBarriers[cmd]; @@ -6894,6 +6535,11 @@ using namespace Vulkan_Internal; { const GPUBarrier& barrier = barriers[i]; + if (barrier.type == GPUBarrier::IMAGE_BARRIER && (barrier.image.texture == nullptr || !barrier.image.texture->IsValid())) + continue; + if (barrier.type == GPUBarrier::BUFFER_BARRIER && (barrier.buffer.buffer == nullptr || !barrier.buffer.buffer->IsValid())) + continue; + switch (barrier.type) { default: @@ -6904,7 +6550,7 @@ using namespace Vulkan_Internal; barrierdesc.pNext = nullptr; barrierdesc.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT | VK_ACCESS_SHADER_WRITE_BIT; barrierdesc.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_SHADER_READ_BIT; - if (CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) || CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { barrierdesc.srcAccessMask |= VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR; barrierdesc.dstAccessMask |= VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR | VK_ACCESS_ACCELERATION_STRUCTURE_WRITE_BIT_KHR; @@ -6924,8 +6570,8 @@ using namespace Vulkan_Internal; barrierdesc.image = internal_state->resource; barrierdesc.oldLayout = _ConvertImageLayout(barrier.image.layout_before); barrierdesc.newLayout = _ConvertImageLayout(barrier.image.layout_after); - barrierdesc.srcAccessMask = _ParseImageLayout(barrier.image.layout_before); - barrierdesc.dstAccessMask = _ParseImageLayout(barrier.image.layout_after); + barrierdesc.srcAccessMask = _ParseResourceState(barrier.image.layout_before); + barrierdesc.dstAccessMask = _ParseResourceState(barrier.image.layout_after); if (desc.BindFlags & BIND_DEPTH_STENCIL) { barrierdesc.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; @@ -6955,28 +6601,7 @@ using namespace Vulkan_Internal; barrierdesc.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrierdesc.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - bool found = false; - for (auto& x : imageBarriers) - { - // Two duplicate barriers will be combined into one: - if (x.image == barrierdesc.image && - x.subresourceRange.baseMipLevel == barrierdesc.subresourceRange.baseMipLevel && - x.subresourceRange.levelCount == barrierdesc.subresourceRange.levelCount && - x.subresourceRange.baseArrayLayer == barrierdesc.subresourceRange.baseArrayLayer && - x.subresourceRange.layerCount == barrierdesc.subresourceRange.layerCount - ) - { - found = true; - x.newLayout = barrierdesc.newLayout; - x.dstAccessMask |= barrierdesc.dstAccessMask; - break; - } - } - - if (!found) - { - imageBarriers.push_back(barrierdesc); - } + imageBarriers.push_back(barrierdesc); } break; case GPUBarrier::BUFFER_BARRIER: @@ -6989,39 +6614,48 @@ using namespace Vulkan_Internal; barrierdesc.buffer = internal_state->resource; barrierdesc.size = barrier.buffer.buffer->GetDesc().ByteWidth; barrierdesc.offset = 0; - barrierdesc.srcAccessMask = _ParseBufferState(barrier.buffer.state_before); - barrierdesc.dstAccessMask = _ParseBufferState(barrier.buffer.state_after); + barrierdesc.srcAccessMask = _ParseResourceState(barrier.buffer.state_before); + barrierdesc.dstAccessMask = _ParseResourceState(barrier.buffer.state_after); barrierdesc.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; barrierdesc.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; - bool found = false; - for (auto& x : bufferBarriers) - { - // Two duplicate barriers will be combined into one: - if (x.buffer == barrierdesc.buffer && - x.srcAccessMask == barrierdesc.srcAccessMask && - x.dstAccessMask == barrierdesc.dstAccessMask - ) - { - found = true; - x.dstAccessMask |= barrierdesc.dstAccessMask; - break; - } - } - - if (!found) - { - bufferBarriers.push_back(barrierdesc); - } + bufferBarriers.push_back(barrierdesc); } break; } } + + if (!memoryBarriers.empty() || + !bufferBarriers.empty() || + !imageBarriers.empty() + ) + { + VkPipelineStageFlags srcStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + VkPipelineStageFlags dstStage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; + + if (CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) + { + srcStage |= VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR; + dstStage |= VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR | VK_PIPELINE_STAGE_RAY_TRACING_SHADER_BIT_KHR; + } + + vkCmdPipelineBarrier( + GetCommandList(cmd), + srcStage, + dstStage, + 0, + (uint32_t)memoryBarriers.size(), memoryBarriers.data(), + (uint32_t)bufferBarriers.size(), bufferBarriers.data(), + (uint32_t)imageBarriers.size(), imageBarriers.data() + ); + + memoryBarriers.clear(); + imageBarriers.clear(); + bufferBarriers.clear(); + } } void GraphicsDevice_Vulkan::BuildRaytracingAccelerationStructure(const RaytracingAccelerationStructure* dst, CommandList cmd, const RaytracingAccelerationStructure* src) { - barrier_flush(cmd); - auto dst_internal = to_internal(dst); VkAccelerationStructureBuildGeometryInfoKHR info = dst_internal->buildInfo; @@ -7176,24 +6810,6 @@ using namespace Vulkan_Internal; pushconstants[cmd].size = size; } - GraphicsDevice::GPUAllocation GraphicsDevice_Vulkan::AllocateGPU(size_t dataSize, CommandList cmd) - { - GPUAllocation result; - if (dataSize == 0) - { - return result; - } - - FrameResources::ResourceFrameAllocator& allocator = GetFrameResources().resourceBuffer[cmd]; - uint8_t* dest = allocator.allocate(dataSize, 256); - assert(dest != nullptr); - - result.buffer = &allocator.buffer; - result.offset = (uint32_t)allocator.calculateOffset(dest); - result.data = (void*)dest; - return result; - } - void GraphicsDevice_Vulkan::EventBegin(const char* name, CommandList cmd) { if (!debugUtils) @@ -7207,7 +6823,6 @@ using namespace Vulkan_Internal; label.color[3] = 1.0f; vkCmdBeginDebugUtilsLabelEXT(GetCommandList(cmd), &label); } - void GraphicsDevice_Vulkan::EventEnd(CommandList cmd) { if (!debugUtils) @@ -7215,7 +6830,6 @@ using namespace Vulkan_Internal; vkCmdEndDebugUtilsLabelEXT(GetCommandList(cmd)); } - void GraphicsDevice_Vulkan::SetMarker(const char* name, CommandList cmd) { if (!debugUtils) diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.h b/WickedEngine/wiGraphicsDevice_Vulkan.h index 09ee8c9f4..e362994b8 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.h +++ b/WickedEngine/wiGraphicsDevice_Vulkan.h @@ -8,7 +8,6 @@ #ifdef WICKEDENGINE_BUILD_VULKAN #include "wiGraphicsDevice.h" -#include "wiGraphicsDevice_SharedInternals.h" #include "wiMath.h" #ifdef _WIN32 @@ -203,12 +202,13 @@ namespace wiGraphics std::vector accelerationStructureViews; bool dirty = false; - const GPUBuffer* CBV[GPU_RESOURCE_HEAP_CBV_COUNT]; - const GPUResource* SRV[GPU_RESOURCE_HEAP_SRV_COUNT]; - int SRV_index[GPU_RESOURCE_HEAP_SRV_COUNT]; - const GPUResource* UAV[GPU_RESOURCE_HEAP_UAV_COUNT]; - int UAV_index[GPU_RESOURCE_HEAP_UAV_COUNT]; - const Sampler* SAM[GPU_SAMPLER_HEAP_COUNT]; + GPUBuffer CBV[DESCRIPTORBINDER_CBV_COUNT]; + uint64_t CBV_offset[DESCRIPTORBINDER_CBV_COUNT]; + GPUResource SRV[DESCRIPTORBINDER_SRV_COUNT]; + int SRV_index[DESCRIPTORBINDER_SRV_COUNT]; + GPUResource UAV[DESCRIPTORBINDER_UAV_COUNT]; + int UAV_index[DESCRIPTORBINDER_UAV_COUNT]; + Sampler SAM[DESCRIPTORBINDER_SAMPLER_COUNT]; void init(GraphicsDevice_Vulkan* device); void destroy(); @@ -216,27 +216,10 @@ namespace wiGraphics void flush(bool graphics, CommandList cmd); }; DescriptorBinder descriptors[COMMANDLIST_COUNT]; - - - struct ResourceFrameAllocator - { - GraphicsDevice_Vulkan* device = nullptr; - GPUBuffer buffer; - uint8_t* dataBegin = nullptr; - uint8_t* dataCur = nullptr; - uint8_t* dataEnd = nullptr; - - void init(GraphicsDevice_Vulkan* device, size_t size); - - uint8_t* allocate(size_t dataSize, size_t alignment); - void clear(); - uint64_t calculateOffset(uint8_t* address); - }; - ResourceFrameAllocator resourceBuffer[COMMANDLIST_COUNT]; }; FrameResources frames[BUFFERCOUNT]; - const FrameResources& GetFrameResources() const { return frames[GetFrameCount() % BUFFERCOUNT]; } - FrameResources& GetFrameResources() { return frames[GetFrameCount() % BUFFERCOUNT]; } + const FrameResources& GetFrameResources() const { return frames[GetBufferIndex()]; } + FrameResources& GetFrameResources() { return frames[GetBufferIndex()]; } struct CommandListMetadata { @@ -286,10 +269,10 @@ namespace wiGraphics bool dirty_pso[COMMANDLIST_COUNT] = {}; void pso_validate(CommandList cmd); - void barrier_flush(CommandList cmd); void predraw(CommandList cmd); void predispatch(CommandList cmd); + std::atomic cmd_count{ 0 }; std::vector common_samplers; @@ -319,10 +302,6 @@ namespace wiGraphics void WriteTopLevelAccelerationStructureInstance(const RaytracingAccelerationStructureDesc::TopLevel::Instance* instance, void* dest) const override; void WriteShaderIdentifier(const RaytracingPipelineState* rtpso, uint32_t group_index, void* dest) const override; - void Map(const GPUResource* resource, Mapping* mapping) const override; - void Unmap(const GPUResource* resource) const override; - void QueryRead(const GPUQueryHeap* heap, uint32_t index, uint32_t count, uint64_t* results) const override; - void SetCommonSampler(const StaticSampler* sam) override; void SetName(GPUResource* pResource, const char* name) override; @@ -345,14 +324,12 @@ namespace wiGraphics void RenderPassEnd(CommandList cmd) override; void BindScissorRects(uint32_t numRects, const Rect* rects, CommandList cmd) override; void BindViewports(uint32_t NumViewports, const Viewport *pViewports, CommandList cmd) override; - void BindResource(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource = -1) override; - void BindResources(SHADERSTAGE stage, const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) override; - void BindUAV(SHADERSTAGE stage, const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource = -1) override; - void BindUAVs(SHADERSTAGE stage, const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) override; - void UnbindResources(uint32_t slot, uint32_t num, CommandList cmd) override; - void UnbindUAVs(uint32_t slot, uint32_t num, CommandList cmd) override; - void BindSampler(SHADERSTAGE stage, const Sampler* sampler, uint32_t slot, CommandList cmd) override; - void BindConstantBuffer(SHADERSTAGE stage, const GPUBuffer* buffer, uint32_t slot, CommandList cmd) override; + void BindResource(const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource = -1) override; + void BindResources(const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) override; + void BindUAV(const GPUResource* resource, uint32_t slot, CommandList cmd, int subresource = -1) override; + void BindUAVs(const GPUResource *const* resources, uint32_t slot, uint32_t count, CommandList cmd) override; + void BindSampler(const Sampler* sampler, uint32_t slot, CommandList cmd) override; + void BindConstantBuffer(const GPUBuffer* buffer, uint32_t slot, CommandList cmd, uint64_t offset = 0ull) override; void BindVertexBuffers(const GPUBuffer *const* vertexBuffers, uint32_t slot, uint32_t count, const uint32_t* strides, const uint32_t* offsets, CommandList cmd) override; void BindIndexBuffer(const GPUBuffer* indexBuffer, const INDEXBUFFER_FORMAT format, uint32_t offset, CommandList cmd) override; void BindStencilRef(uint32_t value, CommandList cmd) override; @@ -371,17 +348,17 @@ namespace wiGraphics void DispatchMesh(uint32_t threadGroupCountX, uint32_t threadGroupCountY, uint32_t threadGroupCountZ, CommandList cmd) override; void DispatchMeshIndirect(const GPUBuffer* args, uint32_t args_offset, CommandList cmd) override; void CopyResource(const GPUResource* pDst, const GPUResource* pSrc, CommandList cmd) override; - void UpdateBuffer(const GPUBuffer* buffer, const void* data, CommandList cmd, int dataSize = -1) override; + void CopyBuffer(const GPUBuffer* pDst, uint64_t dst_offset, const GPUBuffer* pSrc, uint64_t src_offset, uint64_t size, CommandList cmd) override; void QueryBegin(const GPUQueryHeap* heap, uint32_t index, CommandList cmd) override; void QueryEnd(const GPUQueryHeap* heap, uint32_t index, CommandList cmd) override; + void QueryResolve(const GPUQueryHeap* heap, uint32_t index, uint32_t count, const GPUBuffer* dest, uint64_t dest_offset, CommandList cmd) override; + void QueryReset(const GPUQueryHeap* heap, uint32_t index, uint32_t count, CommandList cmd) override; void Barrier(const GPUBarrier* barriers, uint32_t numBarriers, CommandList cmd) override; void BuildRaytracingAccelerationStructure(const RaytracingAccelerationStructure* dst, CommandList cmd, const RaytracingAccelerationStructure* src = nullptr) override; void BindRaytracingPipelineState(const RaytracingPipelineState* rtpso, CommandList cmd) override; void DispatchRays(const DispatchRaysDesc* desc, CommandList cmd) override; void PushConstants(const void* data, uint32_t size, CommandList cmd) override; - GPUAllocation AllocateGPU(size_t dataSize, CommandList cmd) override; - void EventBegin(const char* name, CommandList cmd) override; void EventEnd(CommandList cmd) override; void SetMarker(const char* name, CommandList cmd) override; @@ -486,7 +463,6 @@ namespace wiGraphics locker.unlock(); } }; - BindlessDescriptorHeap bindlessUniformBuffers; BindlessDescriptorHeap bindlessSampledImages; BindlessDescriptorHeap bindlessUniformTexelBuffers; BindlessDescriptorHeap bindlessStorageBuffers; @@ -521,7 +497,6 @@ namespace wiGraphics ~AllocationHandler() { - bindlessUniformBuffers.destroy(device); bindlessSampledImages.destroy(device); bindlessUniformTexelBuffers.destroy(device); bindlessStorageBuffers.destroy(device); @@ -741,7 +716,6 @@ namespace wiGraphics { int index= destroyer_bindlessUniformBuffers.front().first; destroyer_bindlessUniformBuffers.pop_front(); - bindlessUniformBuffers.free(index); } else { diff --git a/WickedEngine/wiHairParticle.cpp b/WickedEngine/wiHairParticle.cpp index badbf8bc6..c879c1c37 100644 --- a/WickedEngine/wiHairParticle.cpp +++ b/WickedEngine/wiHairParticle.cpp @@ -48,111 +48,168 @@ void wiHairParticle::UpdateCPU(const TransformComponent& transform, const MeshCo aabb = AABB(_min, _max); aabb = aabb.transform(world); - if (dt > 0) + GraphicsDevice* device = wiRenderer::GetDevice(); + + if (_flags & REBUILD_BUFFERS || !cb.IsValid() || (strandCount * segmentCount) != simulationBuffer.GetDesc().ByteWidth / sizeof(PatchSimulationData)) { - GraphicsDevice* device = wiRenderer::GetDevice(); + _flags &= ~REBUILD_BUFFERS; + regenerate_frame = true; - if (_flags & REBUILD_BUFFERS || !cb.IsValid() || (strandCount * segmentCount) != particleBuffer.GetDesc().ByteWidth / sizeof(Patch)) + GPUBufferDesc bd; + bd.Usage = USAGE_DEFAULT; + bd.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; + bd.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; + + if (strandCount * segmentCount > 0) { - _flags &= ~REBUILD_BUFFERS; - regenerate_frame = true; + bd.StructureByteStride = sizeof(PatchSimulationData); + bd.ByteWidth = bd.StructureByteStride * strandCount * segmentCount; + device->CreateBuffer(&bd, nullptr, &simulationBuffer); + device->SetName(&simulationBuffer, "simulationBuffer"); + + bd.MiscFlags = RESOURCE_MISC_BUFFER_RAW; + bd.StructureByteStride = sizeof(MeshComponent::Vertex_POS); + bd.ByteWidth = bd.StructureByteStride * 4 * strandCount * segmentCount; + device->CreateBuffer(&bd, nullptr, &vertexBuffer_POS[0]); + device->SetName(&vertexBuffer_POS[0], "vertexBuffer_POS[0]"); + device->CreateBuffer(&bd, nullptr, &vertexBuffer_POS[1]); + device->SetName(&vertexBuffer_POS[1], "vertexBuffer_POS[1]"); + + bd.StructureByteStride = sizeof(MeshComponent::Vertex_TEX); + bd.ByteWidth = bd.StructureByteStride * 4 * strandCount * segmentCount; + device->CreateBuffer(&bd, nullptr, &vertexBuffer_TEX); + device->SetName(&vertexBuffer_TEX, "vertexBuffer_TEX"); - GPUBufferDesc bd; - bd.Usage = USAGE_DEFAULT; bd.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - bd.CPUAccessFlags = 0; - bd.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; - - if (strandCount*segmentCount > 0) - { - bd.StructureByteStride = sizeof(Patch); - bd.ByteWidth = bd.StructureByteStride * strandCount * segmentCount; - device->CreateBuffer(&bd, nullptr, &particleBuffer); - - bd.StructureByteStride = sizeof(PatchSimulationData); - bd.ByteWidth = bd.StructureByteStride * strandCount * segmentCount; - device->CreateBuffer(&bd, nullptr, &simulationBuffer); - - bd.StructureByteStride = sizeof(uint); - bd.ByteWidth = bd.StructureByteStride * strandCount * segmentCount; - device->CreateBuffer(&bd, nullptr, &culledIndexBuffer); - } - - bd.Usage = USAGE_DEFAULT; - bd.ByteWidth = sizeof(HairParticleCB); - bd.BindFlags = BIND_CONSTANT_BUFFER; - bd.CPUAccessFlags = 0; - bd.MiscFlags = 0; - device->CreateBuffer(&bd, nullptr, &cb); - - if (vertex_lengths.size() != mesh.vertex_positions.size()) - { - vertex_lengths.resize(mesh.vertex_positions.size()); - std::fill(vertex_lengths.begin(), vertex_lengths.end(), 1.0f); - } - - indices.clear(); - for (size_t j = 0; j < mesh.indices.size(); j += 3) - { - const uint32_t triangle[] = { - mesh.indices[j + 0], - mesh.indices[j + 1], - mesh.indices[j + 2], - }; - if (vertex_lengths[triangle[0]] > 0 || vertex_lengths[triangle[1]] > 0 || vertex_lengths[triangle[2]] > 0) - { - indices.push_back(triangle[0]); - indices.push_back(triangle[1]); - indices.push_back(triangle[2]); - } - } - - if (!vertex_lengths.empty()) - { - std::vector ulengths; - ulengths.reserve(vertex_lengths.size()); - for (auto& x : vertex_lengths) - { - ulengths.push_back(uint8_t(wiMath::Clamp(x, 0, 1) * 255.0f)); - } - - bd.MiscFlags = 0; - bd.BindFlags = BIND_SHADER_RESOURCE; - bd.Format = FORMAT_R8_UNORM; - bd.StructureByteStride = sizeof(uint8_t); - bd.ByteWidth = bd.StructureByteStride * (uint32_t)ulengths.size(); - SubresourceData initData; - initData.pSysMem = ulengths.data(); - device->CreateBuffer(&bd, &initData, &vertexBuffer_length); - } - if (!indices.empty()) - { - bd.MiscFlags = 0; - bd.BindFlags = BIND_SHADER_RESOURCE; - bd.Format = FORMAT_R32_UINT; - bd.StructureByteStride = sizeof(uint32_t); - bd.ByteWidth = bd.StructureByteStride * (uint32_t)indices.size(); - SubresourceData initData; - initData.pSysMem = indices.data(); - device->CreateBuffer(&bd, &initData, &indexBuffer); - } + bd.MiscFlags = RESOURCE_MISC_NONE; + bd.Format = FORMAT_R32_UINT; + bd.StructureByteStride = sizeof(uint); + bd.ByteWidth = bd.StructureByteStride * 6 * strandCount * segmentCount; + device->CreateBuffer(&bd, nullptr, &primitiveBuffer); + device->SetName(&primitiveBuffer, "primitiveBuffer"); + bd.BindFlags = BIND_INDEX_BUFFER | BIND_UNORDERED_ACCESS; + bd.MiscFlags = RESOURCE_MISC_NONE; + bd.Format = FORMAT_R32_UINT; + bd.StructureByteStride = sizeof(uint); + bd.ByteWidth = bd.StructureByteStride * 6 * strandCount * segmentCount; + device->CreateBuffer(&bd, nullptr, &culledIndexBuffer); + device->SetName(&culledIndexBuffer, "culledIndexBuffer"); } - if (!indirectBuffer.IsValid()) + bd.Usage = USAGE_DEFAULT; + bd.ByteWidth = sizeof(HairParticleCB); + bd.BindFlags = BIND_CONSTANT_BUFFER; + bd.MiscFlags = RESOURCE_MISC_NONE; + device->CreateBuffer(&bd, nullptr, &cb); + + if (vertex_lengths.size() != mesh.vertex_positions.size()) { - GPUBufferDesc desc; - desc.ByteWidth = sizeof(uint) + sizeof(IndirectDrawArgsInstanced); // counter + draw args - desc.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS | RESOURCE_MISC_INDIRECT_ARGS; - desc.BindFlags = BIND_UNORDERED_ACCESS; - device->CreateBuffer(&desc, nullptr, &indirectBuffer); + vertex_lengths.resize(mesh.vertex_positions.size()); + std::fill(vertex_lengths.begin(), vertex_lengths.end(), 1.0f); + } + + indices.clear(); + for (size_t j = 0; j < mesh.indices.size(); j += 3) + { + const uint32_t triangle[] = { + mesh.indices[j + 0], + mesh.indices[j + 1], + mesh.indices[j + 2], + }; + if (vertex_lengths[triangle[0]] > 0 || vertex_lengths[triangle[1]] > 0 || vertex_lengths[triangle[2]] > 0) + { + indices.push_back(triangle[0]); + indices.push_back(triangle[1]); + indices.push_back(triangle[2]); + } + } + + if (!vertex_lengths.empty()) + { + std::vector ulengths; + ulengths.reserve(vertex_lengths.size()); + for (auto& x : vertex_lengths) + { + ulengths.push_back(uint8_t(wiMath::Clamp(x, 0, 1) * 255.0f)); + } + + bd.MiscFlags = RESOURCE_MISC_NONE; + bd.BindFlags = BIND_SHADER_RESOURCE; + bd.Format = FORMAT_R8_UNORM; + bd.StructureByteStride = sizeof(uint8_t); + bd.ByteWidth = bd.StructureByteStride * (uint32_t)ulengths.size(); + SubresourceData initData; + initData.pSysMem = ulengths.data(); + device->CreateBuffer(&bd, &initData, &vertexBuffer_length); + } + if (!indices.empty()) + { + bd.MiscFlags = RESOURCE_MISC_NONE; + bd.BindFlags = BIND_SHADER_RESOURCE; + bd.Format = FORMAT_R32_UINT; + bd.StructureByteStride = sizeof(uint32_t); + bd.ByteWidth = bd.StructureByteStride * (uint32_t)indices.size(); + SubresourceData initData; + initData.pSysMem = indices.data(); + device->CreateBuffer(&bd, &initData, &indexBuffer); + } + + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) + { + RaytracingAccelerationStructureDesc desc; + desc.type = RaytracingAccelerationStructureDesc::BOTTOMLEVEL; + desc._flags |= RaytracingAccelerationStructureDesc::FLAG_ALLOW_UPDATE; + desc._flags |= RaytracingAccelerationStructureDesc::FLAG_PREFER_FAST_BUILD; + + desc.bottomlevel.geometries.emplace_back(); + auto& geometry = desc.bottomlevel.geometries.back(); + geometry.type = RaytracingAccelerationStructureDesc::BottomLevel::Geometry::TRIANGLES; + geometry.triangles.vertexBuffer = vertexBuffer_POS[0]; + geometry.triangles.indexBuffer = primitiveBuffer; + geometry.triangles.indexFormat = INDEXFORMAT_32BIT; + geometry.triangles.indexCount = primitiveBuffer.desc.ByteWidth / primitiveBuffer.desc.StructureByteStride; + geometry.triangles.indexOffset = 0; + geometry.triangles.vertexCount = vertexBuffer_POS[0].desc.ByteWidth / vertexBuffer_POS[0].desc.StructureByteStride; + geometry.triangles.vertexFormat = FORMAT_R32G32B32_FLOAT; + geometry.triangles.vertexStride = sizeof(MeshComponent::Vertex_POS); + + bool success = device->CreateRaytracingAccelerationStructure(&desc, &BLAS); + assert(success); + device->SetName(&BLAS, "BLAS_hair"); } } + if (!indirectBuffer.IsValid()) + { + GPUBufferDesc desc; + desc.ByteWidth = sizeof(uint) + sizeof(IndirectDrawArgsIndexedInstanced); // counter + draw args + desc.MiscFlags = RESOURCE_MISC_BUFFER_RAW | RESOURCE_MISC_INDIRECT_ARGS; + desc.BindFlags = BIND_UNORDERED_ACCESS; + device->CreateBuffer(&desc, nullptr, &indirectBuffer); + } + + if (!subsetBuffer.IsValid()) + { + GPUBufferDesc desc; + desc.StructureByteStride = sizeof(ShaderMeshSubset); + desc.ByteWidth = desc.StructureByteStride; + desc.MiscFlags = RESOURCE_MISC_BUFFER_RAW; + desc.BindFlags = BIND_SHADER_RESOURCE; + device->CreateBuffer(&desc, nullptr, &subsetBuffer); + } + + std::swap(vertexBuffer_POS[0], vertexBuffer_POS[1]); + + if (BLAS.IsValid() && !BLAS.desc.bottomlevel.geometries.empty()) + { + BLAS.desc.bottomlevel.geometries.back().triangles.vertexBuffer = vertexBuffer_POS[0]; + } + } -void wiHairParticle::UpdateGPU(const MeshComponent& mesh, const MaterialComponent& material, CommandList cmd) const +void wiHairParticle::UpdateGPU(uint32_t instanceIndex, uint32_t materialIndex, const MeshComponent& mesh, const MaterialComponent& material, CommandList cmd) const { - if (strandCount == 0 || !particleBuffer.IsValid()) + if (strandCount == 0 || !simulationBuffer.IsValid()) { return; } @@ -165,10 +222,8 @@ void wiHairParticle::UpdateGPU(const MeshComponent& mesh, const MaterialComponen { desc = material.textures[MaterialComponent::BASECOLORMAP].resource->texture.GetDesc(); } - HairParticleCB hcb; - hcb.xWorld = world; - hcb.xColor = material.baseColor; + hcb.xHairWorld = world; hcb.xHairRegenerate = regenerate_frame ? 1 : 0; hcb.xLength = length; hcb.xStiffness = stiffness; @@ -188,31 +243,48 @@ void wiHairParticle::UpdateGPU(const MeshComponent& mesh, const MaterialComponen hcb.xHairTexMul = float2(1.0f / (float)hcb.xHairFramesXY.x, 1.0f / (float)hcb.xHairFramesXY.y); hcb.xHairAspect = (float)std::max(1u, desc.Width) / (float)std::max(1u, desc.Height); hcb.xHairLayerMask = layerMask; + hcb.xHairInstanceIndex = instanceIndex; device->UpdateBuffer(&cb, &hcb, cmd); + ShaderMeshSubset subset; + subset.init(); + subset.indexOffset = 0; + subset.materialIndex = materialIndex; + device->UpdateBuffer(&subsetBuffer, &subset, cmd); + + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&cb, RESOURCE_STATE_COPY_DST, RESOURCE_STATE_CONSTANT_BUFFER), + GPUBarrier::Buffer(&subsetBuffer, RESOURCE_STATE_COPY_DST, RESOURCE_STATE_SHADER_RESOURCE), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + // Simulate: { device->BindComputeShader(&cs_simulate, cmd); - device->BindConstantBuffer(CS, &cb, CB_GETBINDSLOT(HairParticleCB), cmd); + device->BindConstantBuffer(&cb, CB_GETBINDSLOT(HairParticleCB), cmd); const GPUResource* uavs[] = { - &particleBuffer, &simulationBuffer, + &vertexBuffer_POS[0], + &vertexBuffer_TEX, + &primitiveBuffer, &culledIndexBuffer, &indirectBuffer }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); const GPUResource* res[] = { indexBuffer.IsValid() ? &indexBuffer : &mesh.indexBuffer, mesh.streamoutBuffer_POS.IsValid() ? &mesh.streamoutBuffer_POS : &mesh.vertexBuffer_POS, &vertexBuffer_length }; - device->BindResources(CS, res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); + device->BindResources(res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Buffer(&mesh.indexBuffer, BUFFER_STATE_INDEX_BUFFER, BUFFER_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&mesh.indexBuffer, RESOURCE_STATE_INDEX_BUFFER, RESOURCE_STATE_SHADER_RESOURCE), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -224,8 +296,6 @@ void wiHairParticle::UpdateGPU(const MeshComponent& mesh, const MaterialComponen }; device->Barrier(barriers, arraysize(barriers), cmd); - device->UnbindUAVs(0, arraysize(uavs), cmd); - device->UnbindResources(TEXSLOT_ONDEMAND0, arraysize(res), cmd); } // Finish update (reset counter, create indirect draw args): @@ -235,24 +305,25 @@ void wiHairParticle::UpdateGPU(const MeshComponent& mesh, const MaterialComponen const GPUResource* uavs[] = { &indirectBuffer }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); device->Dispatch(1, 1, 1, cmd); GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Buffer(&indirectBuffer, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_INDIRECT_ARGUMENT), - GPUBarrier::Buffer(&culledIndexBuffer, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), - GPUBarrier::Buffer(&particleBuffer, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&indirectBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_INDIRECT_ARGUMENT), + GPUBarrier::Buffer(&vertexBuffer_POS[0], RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&vertexBuffer_TEX, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&primitiveBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&culledIndexBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_INDEX_BUFFER), }; device->Barrier(barriers, arraysize(barriers), cmd); - device->UnbindUAVs(0, arraysize(uavs), cmd); } { GPUBarrier barriers[] = { - GPUBarrier::Buffer(&mesh.indexBuffer, BUFFER_STATE_SHADER_RESOURCE, BUFFER_STATE_INDEX_BUFFER), + GPUBarrier::Buffer(&mesh.indexBuffer, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_INDEX_BUFFER), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -262,7 +333,7 @@ void wiHairParticle::UpdateGPU(const MeshComponent& mesh, const MaterialComponen regenerate_frame = false; } -void wiHairParticle::Draw(const CameraComponent& camera, const MaterialComponent& material, RENDERPASS renderPass, CommandList cmd) const +void wiHairParticle::Draw(const MaterialComponent& material, RENDERPASS renderPass, CommandList cmd) const { if (strandCount == 0 || !cb.IsValid()) { @@ -281,36 +352,24 @@ void wiHairParticle::Draw(const CameraComponent& camera, const MaterialComponent return; } device->BindPipelineState(&PSO_wire, cmd); - device->BindResource(VS, wiTextureHelper::getWhite(), TEXSLOT_ONDEMAND0, cmd); + device->BindResource(wiTextureHelper::getWhite(), TEXSLOT_ONDEMAND0, cmd); } else { device->BindPipelineState(&PSO[renderPass], cmd); - if (material.textures[MaterialComponent::BASECOLORMAP].resource == nullptr) - { - device->BindResource(PS, wiTextureHelper::getWhite(), TEXSLOT_ONDEMAND0, cmd); - device->BindResource(VS, wiTextureHelper::getWhite(), TEXSLOT_ONDEMAND0, cmd); - } - else - { - device->BindResource(PS, material.textures[MaterialComponent::BASECOLORMAP].GetGPUResource(), TEXSLOT_ONDEMAND0, cmd); - device->BindResource(VS, material.textures[MaterialComponent::BASECOLORMAP].GetGPUResource(), TEXSLOT_ONDEMAND0, cmd); - } - if (renderPass != RENDERPASS_PREPASS) // depth only alpha test will be full res { device->BindShadingRate(material.shadingRate, cmd); } } - device->BindConstantBuffer(VS, &cb, CB_GETBINDSLOT(HairParticleCB), cmd); - device->BindConstantBuffer(PS, &material.constantBuffer, CB_GETBINDSLOT(MaterialCB), cmd); + device->BindConstantBuffer(&cb, CB_GETBINDSLOT(HairParticleCB), cmd); + device->BindResource(&primitiveBuffer, 0, cmd); - device->BindResource(VS, &particleBuffer, 0, cmd); - device->BindResource(VS, &culledIndexBuffer, 1, cmd); + device->BindIndexBuffer(&culledIndexBuffer, INDEXFORMAT_32BIT, 0, cmd); - device->DrawInstancedIndirect(&indirectBuffer, 4, cmd); + device->DrawIndexedInstancedIndirect(&indirectBuffer, 4, cmd); device->EventEnd(cmd); } @@ -398,7 +457,7 @@ namespace wiHairParticle_Internal desc.bs = &bs; desc.rs = &ncrs; desc.dss = &dss_default; - desc.pt = TRIANGLESTRIP; + desc.pt = TRIANGLELIST; switch (i) { @@ -422,7 +481,7 @@ namespace wiHairParticle_Internal desc.bs = &bs; desc.rs = &wirers; desc.dss = &dss_default; - desc.pt = TRIANGLESTRIP; + desc.pt = TRIANGLELIST; device->CreatePipelineState(&desc, &PSO_wire); } diff --git a/WickedEngine/wiHairParticle.h b/WickedEngine/wiHairParticle.h index e7ca4b284..851b1679b 100644 --- a/WickedEngine/wiHairParticle.h +++ b/WickedEngine/wiHairParticle.h @@ -15,20 +15,24 @@ namespace wiScene class wiHairParticle { -private: +public: wiGraphics::GPUBuffer cb; - wiGraphics::GPUBuffer particleBuffer; wiGraphics::GPUBuffer simulationBuffer; + wiGraphics::GPUBuffer vertexBuffer_POS[2]; + wiGraphics::GPUBuffer vertexBuffer_TEX; + wiGraphics::GPUBuffer primitiveBuffer; wiGraphics::GPUBuffer culledIndexBuffer; wiGraphics::GPUBuffer indirectBuffer; + wiGraphics::GPUBuffer subsetBuffer; wiGraphics::GPUBuffer indexBuffer; wiGraphics::GPUBuffer vertexBuffer_length; -public: + + wiGraphics::RaytracingAccelerationStructure BLAS; void UpdateCPU(const TransformComponent& transform, const MeshComponent& mesh, float dt); - void UpdateGPU(const MeshComponent& mesh, const MaterialComponent& material, wiGraphics::CommandList cmd) const; - void Draw(const CameraComponent& camera, const MaterialComponent& material, RENDERPASS renderPass, wiGraphics::CommandList cmd) const; + void UpdateGPU(uint32_t instanceIndex, uint32_t materialIndex, const MeshComponent& mesh, const MaterialComponent& material, wiGraphics::CommandList cmd) const; + void Draw(const MaterialComponent& material, RENDERPASS renderPass, wiGraphics::CommandList cmd) const; enum FLAGS { diff --git a/WickedEngine/wiHelper.cpp b/WickedEngine/wiHelper.cpp index 9d15b02bb..de68a734f 100644 --- a/WickedEngine/wiHelper.cpp +++ b/WickedEngine/wiHelper.cpp @@ -113,49 +113,28 @@ namespace wiHelper Texture stagingTex; TextureDesc staging_desc = desc; - staging_desc.Usage = USAGE_STAGING; - staging_desc.CPUAccessFlags = CPU_ACCESS_READ; - staging_desc.BindFlags = 0; - staging_desc.MiscFlags = 0; + staging_desc.Usage = USAGE_READBACK; staging_desc.MipLevels = 1; - staging_desc.layout = IMAGE_LAYOUT_COPY_DST; + staging_desc.layout = RESOURCE_STATE_COPY_DST; bool success = device->CreateTexture(&staging_desc, nullptr, &stagingTex); assert(success); CommandList cmd = device->BeginCommandList(); - { - GPUBarrier barriers[] = { - GPUBarrier::Image(&texture, texture.desc.layout, IMAGE_LAYOUT_COPY_SRC, 0) - }; - device->Barrier(barriers, arraysize(barriers), cmd); - } - device->CopyResource(&stagingTex, &texture, cmd); - { - GPUBarrier barriers[] = { - GPUBarrier::Image(&texture, IMAGE_LAYOUT_COPY_SRC, texture.desc.layout, 0) - }; - device->Barrier(barriers, arraysize(barriers), cmd); - } - device->SubmitCommandLists(); device->WaitForGPU(); - Mapping mapping; - mapping._flags = Mapping::FLAG_READ; - mapping.size = data_size; - device->Map(&stagingTex, &mapping); - if (mapping.data != nullptr) + if (stagingTex.mapped_data != nullptr) { - if (mapping.rowpitch / data_stride != desc.Width) + if (stagingTex.mapped_rowpitch / data_stride != desc.Width) { // Copy padded texture row by row: const uint32_t cpysize = desc.Width * data_stride; for (uint32_t i = 0; i < desc.Height; ++i) { - void* src = (void*)((size_t)mapping.data + size_t(i * mapping.rowpitch)); + void* src = (void*)((size_t)stagingTex.mapped_data + size_t(i * stagingTex.mapped_rowpitch)); void* dst = (void*)((size_t)texturedata.data() + size_t(i * cpysize)); memcpy(dst, src, cpysize); } @@ -163,16 +142,15 @@ namespace wiHelper else { // Copy whole - std::memcpy(texturedata.data(), mapping.data, texturedata.size()); + std::memcpy(texturedata.data(), stagingTex.mapped_data, texturedata.size()); } - device->Unmap(&stagingTex); } else { assert(0); } - return mapping.data != nullptr; + return stagingTex.mapped_data != nullptr; } bool saveTextureToMemoryFile(const wiGraphics::Texture& texture, const std::string& fileExtension, std::vector& filedata) diff --git a/WickedEngine/wiImage.cpp b/WickedEngine/wiImage.cpp index 99946d895..8760151ba 100644 --- a/WickedEngine/wiImage.cpp +++ b/WickedEngine/wiImage.cpp @@ -18,15 +18,10 @@ namespace wiImage enum IMAGE_SHADER { IMAGE_SHADER_STANDARD, - IMAGE_SHADER_SEPARATENORMALMAP, - IMAGE_SHADER_MASKED, - IMAGE_SHADER_BACKGROUND, - IMAGE_SHADER_BACKGROUND_MASKED, IMAGE_SHADER_FULLSCREEN, IMAGE_SHADER_COUNT }; - GPUBuffer constantBuffer; Shader vertexShader; Shader screenVS; Shader imagePS[IMAGE_SHADER_COUNT]; @@ -96,36 +91,46 @@ namespace wiImage sampler = wiRenderer::GetSampler(SSLOT_ANISO_CLAMP); } - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS)) + PushConstantsImage push; + push.texture_base_index = device->GetDescriptorIndex(texture, SRV); + push.texture_mask_index = device->GetDescriptorIndex(params.maskMap, SRV); + if (params.isBackgroundEnabled()) { - PushConstantsImage push; - push.texture_base_index = device->GetDescriptorIndex(texture, SRV); - push.texture_mask_index = device->GetDescriptorIndex(params.maskMap, SRV); push.texture_background_index = device->GetDescriptorIndex(&backgroundTextures[cmd], SRV); - push.sampler_index = device->GetDescriptorIndex(sampler); - device->PushConstants(&push, sizeof(push), cmd); } else { - device->BindResource(PS, texture, TEXSLOT_IMAGE_BASE, cmd); - device->BindResource(PS, params.maskMap, TEXSLOT_IMAGE_MASK, cmd); - device->BindResource(PS, &backgroundTextures[cmd], TEXSLOT_IMAGE_BACKGROUND, cmd); - device->BindSampler(PS, sampler, SSLOT_ONDEMAND0, cmd); + push.texture_background_index = -1; } + push.sampler_index = device->GetDescriptorIndex(sampler); - ImageCB cb; - cb.xColor = params.color; + XMFLOAT4 color = params.color; const float darken = 1 - params.fade; - cb.xColor.x *= darken; - cb.xColor.y *= darken; - cb.xColor.z *= darken; - cb.xColor.w *= params.opacity; + color.x *= darken; + color.y *= darken; + color.z *= darken; + color.w *= params.opacity; + + XMHALF4 packed_color; + packed_color.x = XMConvertFloatToHalf(color.x); + packed_color.y = XMConvertFloatToHalf(color.y); + packed_color.z = XMConvertFloatToHalf(color.z); + packed_color.w = XMConvertFloatToHalf(color.w); + + push.packed_color.x = uint(packed_color.v); + push.packed_color.y = uint(packed_color.v >> 32ull); + + push.flags = 0; + if (params.isExtractNormalMapEnabled()) + { + push.flags |= IMAGE_FLAG_EXTRACT_NORMALMAP; + } if (params.isFullScreenEnabled()) { + // Full screen image uses a fast path with full screen triangle and no effects device->BindPipelineState(&imagePSO[IMAGE_SHADER_FULLSCREEN][params.blendFlag][params.stencilComp][params.stencilRefMode], cmd); - device->UpdateBuffer(&constantBuffer, &cb, cmd); - device->BindConstantBuffer(PS, &constantBuffer, CB_GETBINDSLOT(ImageCB), cmd); + device->PushConstants(&push, sizeof(push), cmd); device->Draw(3, 0, cmd); device->EventEnd(cmd); return; @@ -161,13 +166,13 @@ namespace wiImage { XMVECTOR V = XMVectorSet(params.corners[i].x - params.pivot.x, params.corners[i].y - params.pivot.y, 0, 1); V = XMVector2Transform(V, M); // division by w will happen on GPU - XMStoreFloat4(&cb.xCorners[i], V); + XMStoreFloat4(&push.corners[i], V); } if (params.isMirrorEnabled()) { - std::swap(cb.xCorners[0], cb.xCorners[1]); - std::swap(cb.xCorners[2], cb.xCorners[3]); + std::swap(push.corners[0], push.corners[1]); + std::swap(push.corners[2], push.corners[3]); } const TextureDesc& desc = texture->GetDesc(); @@ -176,73 +181,35 @@ namespace wiImage if (params.isDrawRectEnabled()) { - cb.xTexMulAdd.x = params.drawRect.z * inv_width; // drawRec.width: mul - cb.xTexMulAdd.y = params.drawRect.w * inv_height; // drawRec.heigh: mul - cb.xTexMulAdd.z = params.drawRect.x * inv_width; // drawRec.x: add - cb.xTexMulAdd.w = params.drawRect.y * inv_height; // drawRec.y: add + push.texMulAdd.x = params.drawRect.z * inv_width; // drawRec.width: mul + push.texMulAdd.y = params.drawRect.w * inv_height; // drawRec.heigh: mul + push.texMulAdd.z = params.drawRect.x * inv_width; // drawRec.x: add + push.texMulAdd.w = params.drawRect.y * inv_height; // drawRec.y: add } else { - cb.xTexMulAdd = XMFLOAT4(1, 1, 0, 0); // disabled draw rect + push.texMulAdd = XMFLOAT4(1, 1, 0, 0); // disabled draw rect } - cb.xTexMulAdd.z += params.texOffset.x * inv_width; // texOffset.x: add - cb.xTexMulAdd.w += params.texOffset.y * inv_height; // texOffset.y: add + push.texMulAdd.z += params.texOffset.x * inv_width; // texOffset.x: add + push.texMulAdd.w += params.texOffset.y * inv_height; // texOffset.y: add if (params.isDrawRect2Enabled()) { - cb.xTexMulAdd2.x = params.drawRect2.z * inv_width; // drawRec.width: mul - cb.xTexMulAdd2.y = params.drawRect2.w * inv_height; // drawRec.heigh: mul - cb.xTexMulAdd2.z = params.drawRect2.x * inv_width; // drawRec.x: add - cb.xTexMulAdd2.w = params.drawRect2.y * inv_height; // drawRec.y: add + push.texMulAdd2.x = params.drawRect2.z * inv_width; // drawRec.width: mul + push.texMulAdd2.y = params.drawRect2.w * inv_height; // drawRec.heigh: mul + push.texMulAdd2.z = params.drawRect2.x * inv_width; // drawRec.x: add + push.texMulAdd2.w = params.drawRect2.y * inv_height; // drawRec.y: add } else { - cb.xTexMulAdd2 = XMFLOAT4(1, 1, 0, 0); // disabled draw rect + push.texMulAdd2 = XMFLOAT4(1, 1, 0, 0); // disabled draw rect } - cb.xTexMulAdd2.z += params.texOffset2.x * inv_width; // texOffset.x: add - cb.xTexMulAdd2.w += params.texOffset2.y * inv_height; // texOffset.y: add + push.texMulAdd2.z += params.texOffset2.x * inv_width; // texOffset.x: add + push.texMulAdd2.w += params.texOffset2.y * inv_height; // texOffset.y: add - device->UpdateBuffer(&constantBuffer, &cb, cmd); + device->BindPipelineState(&imagePSO[IMAGE_SHADER_STANDARD][params.blendFlag][params.stencilComp][params.stencilRefMode], cmd); - // Determine relevant image rendering pixel shader: - IMAGE_SHADER targetShader; - const bool NormalmapSeparate = params.isExtractNormalMapEnabled(); - const bool Mask = params.maskMap != nullptr; - const bool background_blur = params.isBackgroundEnabled(); - if (NormalmapSeparate) - { - targetShader = IMAGE_SHADER_SEPARATENORMALMAP; - } - else - { - if (Mask) - { - if (background_blur) - { - targetShader = IMAGE_SHADER_BACKGROUND_MASKED; - } - else - { - targetShader = IMAGE_SHADER_MASKED; - } - } - else - { - if (background_blur) - { - targetShader = IMAGE_SHADER_BACKGROUND; - } - else - { - targetShader = IMAGE_SHADER_STANDARD; - } - } - } - - device->BindPipelineState(&imagePSO[targetShader][params.blendFlag][params.stencilComp][params.stencilRefMode], cmd); - - device->BindConstantBuffer(VS, &constantBuffer, CB_GETBINDSLOT(ImageCB), cmd); - device->BindConstantBuffer(PS, &constantBuffer, CB_GETBINDSLOT(ImageCB), cmd); + device->PushConstants(&push, sizeof(push), cmd); device->Draw(4, 0, cmd); @@ -258,10 +225,6 @@ namespace wiImage wiRenderer::LoadShader(VS, screenVS, "screenVS.cso"); wiRenderer::LoadShader(PS, imagePS[IMAGE_SHADER_STANDARD], "imagePS.cso"); - wiRenderer::LoadShader(PS, imagePS[IMAGE_SHADER_SEPARATENORMALMAP], "imagePS_separatenormalmap.cso"); - wiRenderer::LoadShader(PS, imagePS[IMAGE_SHADER_MASKED], "imagePS_masked.cso"); - wiRenderer::LoadShader(PS, imagePS[IMAGE_SHADER_BACKGROUND], "imagePS_backgroundblur.cso"); - wiRenderer::LoadShader(PS, imagePS[IMAGE_SHADER_BACKGROUND_MASKED], "imagePS_backgroundblur_masked.cso"); wiRenderer::LoadShader(PS, imagePS[IMAGE_SHADER_FULLSCREEN], "screenPS.cso"); @@ -303,15 +266,6 @@ namespace wiImage { GraphicsDevice* device = wiRenderer::GetDevice(); - { - GPUBufferDesc bd; - bd.Usage = USAGE_DYNAMIC; - bd.ByteWidth = sizeof(ImageCB); - bd.BindFlags = BIND_CONSTANT_BUFFER; - bd.CPUAccessFlags = CPU_ACCESS_WRITE; - device->CreateBuffer(&bd, nullptr, &constantBuffer); - } - RasterizerState rs; rs.FillMode = FILL_SOLID; rs.CullMode = CULL_NONE; diff --git a/WickedEngine/wiOcean.cpp b/WickedEngine/wiOcean.cpp index 3e5d47526..93a715dbf 100644 --- a/WickedEngine/wiOcean.cpp +++ b/WickedEngine/wiOcean.cpp @@ -21,7 +21,6 @@ namespace wiOcean_Internal Shader wireframePS; Shader oceanSurfPS; - GPUBuffer shadingCB; RasterizerState rasterizerState; RasterizerState wireRS; DepthStencilState depthStencilState; @@ -126,7 +125,6 @@ void wiOcean::Create(const OceanParameters& params) GPUBufferDesc buf_desc; buf_desc.Usage = USAGE_DEFAULT; buf_desc.BindFlags = BIND_UNORDERED_ACCESS | BIND_SHADER_RESOURCE; - buf_desc.CPUAccessFlags = 0; buf_desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; SubresourceData init_data; @@ -167,7 +165,6 @@ void wiOcean::Create(const OceanParameters& params) tex_desc.SampleCount = 1; tex_desc.Usage = USAGE_DEFAULT; tex_desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - tex_desc.CPUAccessFlags = 0; tex_desc.Format = FORMAT_R16G16B16A16_FLOAT; tex_desc.MipLevels = 0; @@ -200,17 +197,12 @@ void wiOcean::Create(const OceanParameters& params) init_cb0.pSysMem = &immutable_consts; GPUBufferDesc cb_desc; - cb_desc.Usage = USAGE_IMMUTABLE; cb_desc.BindFlags = BIND_CONSTANT_BUFFER; - cb_desc.CPUAccessFlags = 0; - cb_desc.MiscFlags = 0; cb_desc.ByteWidth = sizeof(Ocean_Simulation_ImmutableCB); device->CreateBuffer(&cb_desc, &init_cb0, &immutableCB); cb_desc.Usage = USAGE_DEFAULT; cb_desc.BindFlags = BIND_CONSTANT_BUFFER; - cb_desc.CPUAccessFlags = 0; - cb_desc.MiscFlags = 0; cb_desc.ByteWidth = sizeof(Ocean_Simulation_PerFrameCB); device->CreateBuffer(&cb_desc, nullptr, &perFrameCB); } @@ -277,19 +269,32 @@ void wiOcean::UpdateDisplacementMap(const OceanParameters& params, CommandList c &buffer_Float2_H0, &buffer_Float_Omega }; - device->BindResources(CS, cs0_srvs, TEXSLOT_ONDEMAND0, arraysize(cs0_srvs), cmd); + device->BindResources(cs0_srvs, TEXSLOT_ONDEMAND0, arraysize(cs0_srvs), cmd); const GPUResource* cs0_uavs[1] = { &buffer_Float2_Ht }; - device->BindUAVs(CS, cs0_uavs, 0, arraysize(cs0_uavs), cmd); + device->BindUAVs(cs0_uavs, 0, arraysize(cs0_uavs), cmd); Ocean_Simulation_PerFrameCB perFrameData; perFrameData.g_TimeScale = params.time_scale; perFrameData.g_ChoppyScale = params.choppy_scale; perFrameData.g_GridLen = params.dmap_dim / params.patch_length; - device->UpdateBuffer(&perFrameCB, &perFrameData, cmd); - device->BindConstantBuffer(CS, &immutableCB, CB_GETBINDSLOT(Ocean_Simulation_ImmutableCB), cmd); - device->BindConstantBuffer(CS, &perFrameCB, CB_GETBINDSLOT(Ocean_Simulation_PerFrameCB), cmd); + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&perFrameCB, RESOURCE_STATE_CONSTANT_BUFFER, RESOURCE_STATE_COPY_DST), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + device->UpdateBuffer(&perFrameCB, &perFrameData, cmd); + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&perFrameCB, RESOURCE_STATE_COPY_DST, RESOURCE_STATE_CONSTANT_BUFFER), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->BindConstantBuffer(&immutableCB, CB_GETBINDSLOT(Ocean_Simulation_ImmutableCB), cmd); + device->BindConstantBuffer(&perFrameCB, CB_GETBINDSLOT(Ocean_Simulation_PerFrameCB), cmd); // Run the CS uint32_t group_count_x = (params.dmap_dim + OCEAN_COMPUTE_TILESIZE - 1) / OCEAN_COMPUTE_TILESIZE; @@ -300,8 +305,6 @@ void wiOcean::UpdateDisplacementMap(const OceanParameters& params, CommandList c }; device->Barrier(barriers, arraysize(barriers), cmd); - device->UnbindUAVs(0, 1, cmd); - device->UnbindResources(TEXSLOT_ONDEMAND0, 2, cmd); // ------------------------------------ Perform FFT ------------------------------------------- @@ -309,31 +312,29 @@ void wiOcean::UpdateDisplacementMap(const OceanParameters& params, CommandList c - device->BindConstantBuffer(CS, &immutableCB, CB_GETBINDSLOT(Ocean_Simulation_ImmutableCB), cmd); - device->BindConstantBuffer(CS, &perFrameCB, CB_GETBINDSLOT(Ocean_Simulation_PerFrameCB), cmd); + device->BindConstantBuffer(&immutableCB, CB_GETBINDSLOT(Ocean_Simulation_ImmutableCB), cmd); + device->BindConstantBuffer(&perFrameCB, CB_GETBINDSLOT(Ocean_Simulation_PerFrameCB), cmd); // Update displacement map: device->BindComputeShader(&updateDisplacementMapCS, cmd); const GPUResource* cs_uavs[] = { &displacementMap }; - device->BindUAVs(CS, cs_uavs, 0, 1, cmd); + device->BindUAVs(cs_uavs, 0, 1, cmd); const GPUResource* cs_srvs[1] = { &buffer_Float_Dxyz }; - device->BindResources(CS, cs_srvs, TEXSLOT_ONDEMAND0, 1, cmd); + device->BindResources(cs_srvs, TEXSLOT_ONDEMAND0, 1, cmd); device->Dispatch(params.dmap_dim / OCEAN_COMPUTE_TILESIZE, params.dmap_dim / OCEAN_COMPUTE_TILESIZE, 1, cmd); device->Barrier(barriers, arraysize(barriers), cmd); // Update gradient map: device->BindComputeShader(&updateGradientFoldingCS, cmd); cs_uavs[0] = { &gradientMap }; - device->BindUAVs(CS, cs_uavs, 0, 1, cmd); + device->BindUAVs(cs_uavs, 0, 1, cmd); cs_srvs[0] = &displacementMap; - device->BindResources(CS, cs_srvs, TEXSLOT_ONDEMAND0, 1, cmd); + device->BindResources(cs_srvs, TEXSLOT_ONDEMAND0, 1, cmd); device->Dispatch(params.dmap_dim / OCEAN_COMPUTE_TILESIZE, params.dmap_dim / OCEAN_COMPUTE_TILESIZE, 1, cmd); device->Barrier(barriers, arraysize(barriers), cmd); // Unbind - device->UnbindUAVs(0, 1, cmd); - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); wiRenderer::GenerateMipChain(gradientMap, wiRenderer::MIPGENFILTER_LINEAR, cmd); @@ -371,13 +372,10 @@ void wiOcean::Render(const CameraComponent& camera, const OceanParameters& param cb.xOceanWaterHeight = params.waterHeight; cb.xOceanSurfaceDisplacementTolerance = std::max(1.0f, params.surfaceDisplacementTolerance); - device->UpdateBuffer(&shadingCB, &cb, cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(Ocean_RenderCB), cmd); - device->BindConstantBuffer(VS, &shadingCB, CB_GETBINDSLOT(Ocean_RenderCB), cmd); - device->BindConstantBuffer(PS, &shadingCB, CB_GETBINDSLOT(Ocean_RenderCB), cmd); - - device->BindResource(VS, &displacementMap, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(PS, &gradientMap, TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&displacementMap, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&gradientMap, TEXSLOT_ONDEMAND1, cmd); device->Draw(dim.x*dim.y*6, 0, cmd); @@ -390,15 +388,6 @@ void wiOcean::Initialize() GraphicsDevice* device = wiRenderer::GetDevice(); - GPUBufferDesc cb_desc; - cb_desc.Usage = USAGE_DYNAMIC; - cb_desc.CPUAccessFlags = CPU_ACCESS_WRITE; - cb_desc.ByteWidth = sizeof(Ocean_RenderCB); - cb_desc.StructureByteStride = 0; - cb_desc.BindFlags = BIND_CONSTANT_BUFFER; - device->CreateBuffer(&cb_desc, nullptr, &shadingCB); - - RasterizerState ras_desc; ras_desc.FillMode = FILL_SOLID; ras_desc.CullMode = CULL_NONE; diff --git a/WickedEngine/wiPhysicsEngine_Bullet.cpp b/WickedEngine/wiPhysicsEngine_Bullet.cpp index 48f624c11..01d7133c2 100644 --- a/WickedEngine/wiPhysicsEngine_Bullet.cpp +++ b/WickedEngine/wiPhysicsEngine_Bullet.cpp @@ -425,15 +425,6 @@ namespace wiPhysicsEngine const ArmatureComponent* armature = mesh.IsSkinned() ? scene.armatures.GetComponent(mesh.armatureID) : nullptr; mesh.SetDynamic(true); - if (!mesh.vertexBuffer_PRE.IsValid()) - { - using namespace wiGraphics; - GraphicsDevice* device = wiRenderer::GetDevice(); - device->CreateBuffer(&mesh.vertexBuffer_POS.desc, nullptr, &mesh.streamoutBuffer_POS); - device->CreateBuffer(&mesh.vertexBuffer_POS.desc, nullptr, &mesh.vertexBuffer_PRE); - device->CreateBuffer(&mesh.vertexBuffer_TAN.desc, nullptr, &mesh.streamoutBuffer_TAN); - } - if (physicscomponent._flags & SoftBodyPhysicsComponent::FORCE_RESET) { physicscomponent._flags &= ~SoftBodyPhysicsComponent::FORCE_RESET; diff --git a/WickedEngine/wiPlatform.h b/WickedEngine/wiPlatform.h index 80d0508fc..da6cd5a84 100644 --- a/WickedEngine/wiPlatform.h +++ b/WickedEngine/wiPlatform.h @@ -8,6 +8,7 @@ #ifdef _WIN32 +#define NOMINMAX #define WIN32_LEAN_AND_MEAN #include #include diff --git a/WickedEngine/wiProfiler.cpp b/WickedEngine/wiProfiler.cpp index c9ff27bb1..72eae13d2 100644 --- a/WickedEngine/wiProfiler.cpp +++ b/WickedEngine/wiProfiler.cpp @@ -24,7 +24,7 @@ namespace wiProfiler range_id cpu_frame; range_id gpu_frame; GPUQueryHeap queryHeap[wiGraphics::GraphicsDevice::GetBufferCount() + 1]; - std::vector queryResults; + GPUBuffer queryResultBuffer[arraysize(queryHeap)]; std::atomic nextQuery{ 0 }; uint32_t writtenQueries[arraysize(queryHeap)] = {}; int queryheap_idx = 0; @@ -58,21 +58,38 @@ namespace wiProfiler ranges.reserve(100); + GraphicsDevice* device = wiRenderer::GetDevice(); + GPUQueryHeapDesc desc; desc.type = GPU_QUERY_TYPE_TIMESTAMP; desc.queryCount = 1024; + + GPUBufferDesc bd; + bd.Usage = USAGE_READBACK; + bd.ByteWidth = desc.queryCount * sizeof(uint64_t); + for (int i = 0; i < arraysize(queryHeap); ++i) { - bool success = wiRenderer::GetDevice()->CreateQueryHeap(&desc, &queryHeap[i]); + bool success = device->CreateQueryHeap(&desc, &queryHeap[i]); + assert(success); + + success = device->CreateBuffer(&bd, nullptr, &queryResultBuffer[i]); assert(success); } - - queryResults.resize(desc.queryCount); } cpu_frame = BeginRangeCPU("CPU Frame"); - CommandList cmd = wiRenderer::GetDevice()->BeginCommandList(); + GraphicsDevice* device = wiRenderer::GetDevice(); + CommandList cmd = device->BeginCommandList(); + + device->QueryReset( + &queryHeap[queryheap_idx], + 0, + queryHeap[queryheap_idx].desc.queryCount, + cmd + ); + gpu_frame = BeginRangeGPU("GPU Frame", cmd); } void EndFrame(CommandList cmd) @@ -91,15 +108,19 @@ namespace wiProfiler double gpu_frequency = (double)device->GetTimestampFrequency() / 1000.0; - device->QueryResolve(&queryHeap[queryheap_idx], 0, nextQuery.load(), cmd); + device->QueryResolve( + &queryHeap[queryheap_idx], + 0, + nextQuery.load(), + &queryResultBuffer[queryheap_idx], + 0ull, + cmd + ); writtenQueries[queryheap_idx] = nextQuery.load(); nextQuery.store(0); queryheap_idx = (queryheap_idx + 1) % arraysize(queryHeap); - if (writtenQueries[queryheap_idx] > 0) - { - wiRenderer::GetDevice()->QueryRead(&queryHeap[queryheap_idx], 0, writtenQueries[queryheap_idx], queryResults.data()); - } + uint64_t* queryResults = (uint64_t*)queryResultBuffer[queryheap_idx].mapped_data; for (auto& x : ranges) { @@ -114,7 +135,7 @@ namespace wiProfiler { int begin_query = range.gpuBegin[queryheap_idx]; int end_query = range.gpuEnd[queryheap_idx]; - if (begin_query >= 0 && end_query >= 0) + if (queryResultBuffer[queryheap_idx].mapped_data != nullptr && begin_query >= 0 && end_query >= 0) { uint64_t begin_result = queryResults[begin_query]; uint64_t end_result = queryResults[end_query]; diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index 661421821..de13be786 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -22,11 +22,9 @@ #include "wiShaderCompiler.h" #include "shaders/ShaderInterop_Postprocess.h" -#include "shaders/ShaderInterop_Skinning.h" #include "shaders/ShaderInterop_Raytracing.h" #include "shaders/ShaderInterop_BVH.h" -#include "shaders/ShaderInterop_Utility.h" -#include "shaders/ShaderInterop_Paint.h" +#include "shaders/ShaderInterop_SurfelGI.h" #include #include @@ -64,6 +62,15 @@ inline LinearAllocator& GetRenderFrameAllocator(CommandList cmd) return renderFrameAllocators[cmd]; } +std::vector barrier_stack[COMMANDLIST_COUNT]; +void barrier_stack_flush(CommandList cmd) +{ + if (barrier_stack[cmd].empty()) + return; + device->Barrier(barrier_stack[cmd].data(), (uint32_t)barrier_stack[cmd].size(), cmd); + barrier_stack[cmd].clear(); +} + float GAMMA = 2.2f; uint32_t SHADOWRES_2D = 1024; uint32_t SHADOWRES_CUBE = 256; @@ -83,18 +90,20 @@ bool voxelHelper = false; bool advancedLightCulling = true; bool variableRateShadingClassification = false; bool variableRateShadingClassificationDebug = false; -bool ldsSkinningEnabled = true; float GameSpeed = 1; bool debugLightCulling = false; bool occlusionCulling = false; bool temporalAA = false; bool temporalAADEBUG = false; -uint32_t raytraceBounceCount = 2; +uint32_t raytraceBounceCount = 3; bool raytraceDebugVisualizer = false; bool raytracedShadows = false; bool tessellationEnabled = true; bool disableAlbedoMaps = false; +bool forceDiffuseLighting = false; bool SCREENSPACESHADOWS = false; +bool SURFELGI = false; +bool SURFELGI_DEBUG = false; struct VoxelizedSceneData @@ -351,87 +360,6 @@ struct RenderQueue } }; -struct Instance -{ - XMFLOAT4 mat0; - XMFLOAT4 mat1; - XMFLOAT4 mat2; - XMUINT4 userdata; - - inline void Create( - const XMFLOAT4X4& matIn, - const XMFLOAT4& colorIn = XMFLOAT4(1, 1, 1, 1), - float dither = 0, - uint32_t subInstance = 0, - const XMFLOAT4& emissiveColor = XMFLOAT4(1, 1, 1, 1) - ) volatile - { - mat0.x = matIn._11; - mat0.y = matIn._21; - mat0.z = matIn._31; - mat0.w = matIn._41; - - mat1.x = matIn._12; - mat1.y = matIn._22; - mat1.z = matIn._32; - mat1.w = matIn._42; - - mat2.x = matIn._13; - mat2.y = matIn._23; - mat2.z = matIn._33; - mat2.w = matIn._43; - - XMFLOAT4 color = colorIn; - color.w *= 1 - dither; - userdata.x = wiMath::CompressColor(color); - userdata.y = subInstance; - - userdata.z = wiMath::CompressColor(emissiveColor); - userdata.w = 0; - } -}; -struct InstancePrev -{ - XMFLOAT4 mat0; - XMFLOAT4 mat1; - XMFLOAT4 mat2; - - inline void Create(const XMFLOAT4X4& matIn) volatile - { - mat0.x = matIn._11; - mat0.y = matIn._21; - mat0.z = matIn._31; - mat0.w = matIn._41; - - mat1.x = matIn._12; - mat1.y = matIn._22; - mat1.z = matIn._32; - mat1.w = matIn._42; - - mat2.x = matIn._13; - mat2.y = matIn._23; - mat2.z = matIn._33; - mat2.w = matIn._43; - } -}; -struct InstanceAtlas -{ - XMFLOAT4 atlasMulAdd; - - InstanceAtlas(){} - InstanceAtlas(const XMFLOAT4& atlasRemap) - { - Create(atlasRemap); - } - inline void Create(const XMFLOAT4& atlasRemap) volatile - { - atlasMulAdd.x = atlasRemap.x; - atlasMulAdd.y = atlasRemap.y; - atlasMulAdd.z = atlasRemap.z; - atlasMulAdd.w = atlasRemap.w; - } -}; - const Sampler* GetSampler(int slot) { @@ -510,49 +438,6 @@ const std::vector& GetCustomShaders() } -ILTYPES GetILTYPE(RENDERPASS renderPass, bool tessellation, bool alphatest, bool transparent) -{ - ILTYPES realVL = ILTYPE_OBJECT_POS_TEX; - - switch (renderPass) - { - case RENDERPASS_MAIN: - case RENDERPASS_ENVMAPCAPTURE: - case RENDERPASS_VOXELIZE: - realVL = ILTYPE_OBJECT_COMMON; - break; - case RENDERPASS_PREPASS: - if (tessellation) - { - realVL = ILTYPE_OBJECT_POS_PREVPOS_TEX; // tessellation needs tex because displacement mapping - } - else - { - if (alphatest) - { - realVL = ILTYPE_OBJECT_POS_PREVPOS_TEX; - } - else - { - realVL = ILTYPE_OBJECT_POS_PREVPOS; - } - } - break; - case RENDERPASS_SHADOW: - case RENDERPASS_SHADOWCUBE: - if (alphatest || transparent) - { - realVL = ILTYPE_OBJECT_POS_TEX; - } - else - { - realVL = ILTYPE_OBJECT_POS; - } - break; - } - - return realVL; -} SHADERTYPE GetVSTYPE(RENDERPASS renderPass, bool tessellation, bool alphatest, bool transparent) { SHADERTYPE realVS = VSTYPE_OBJECT_SIMPLE; @@ -811,20 +696,6 @@ PipelineState PSO_impostor_wire; PipelineState PSO_captureimpostor_albedo; PipelineState PSO_captureimpostor_normal; PipelineState PSO_captureimpostor_surface; -inline const PipelineState* GetImpostorPSO(RENDERPASS renderPass) -{ - if (IsWireRender()) - { - switch (renderPass) - { - case RENDERPASS_MAIN: - return &PSO_impostor_wire; - } - return nullptr; - } - - return &PSO_impostor[renderPass]; -} PipelineState PSO_lightvisualizer[LightComponent::LIGHTTYPE_COUNT]; PipelineState PSO_volumetriclight[LightComponent::LIGHTTYPE_COUNT]; @@ -850,7 +721,6 @@ enum SKYRENDERING SKYRENDERING_STATIC, SKYRENDERING_DYNAMIC, SKYRENDERING_SUN, - SKYRENDERING_VELOCITY, SKYRENDERING_ENVMAPCAPTURE_STATIC, SKYRENDERING_ENVMAPCAPTURE_DYNAMIC, SKYRENDERING_COUNT @@ -962,91 +832,28 @@ void LoadShaders() wiJobSystem::Execute(ctx, [](wiJobArgs args) { inputLayouts[ILTYPE_OBJECT_DEBUG].elements = { - { "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, INPUT_SLOT_POSITION_NORMAL_WIND, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, + { "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, 0, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, }; LoadShader(VS, shaders[VSTYPE_OBJECT_DEBUG], "objectVS_debug.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { - inputLayouts[ILTYPE_OBJECT_COMMON].elements = - { - { "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, INPUT_SLOT_POSITION_NORMAL_WIND, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - { "UVSET", 0, MeshComponent::Vertex_TEX::FORMAT, INPUT_SLOT_UV0, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - { "UVSET", 1, MeshComponent::Vertex_TEX::FORMAT, INPUT_SLOT_UV1, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - { "ATLAS", 0, MeshComponent::Vertex_TEX::FORMAT, INPUT_SLOT_ATLAS, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - { "COLOR", 0, MeshComponent::Vertex_COL::FORMAT, INPUT_SLOT_COLOR, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - { "TANGENT", 0, MeshComponent::Vertex_TAN::FORMAT, INPUT_SLOT_TANGENT, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - - { "INSTANCEMATRIX", 0, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIX", 1, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIX", 2, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEUSERDATA", 0, FORMAT_R32G32B32A32_UINT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEATLAS", 0, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - }; LoadShader(VS, shaders[VSTYPE_OBJECT_COMMON], "objectVS_common.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { - inputLayouts[ILTYPE_OBJECT_POS_PREVPOS].elements = - { - { "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, INPUT_SLOT_POSITION_NORMAL_WIND, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - { "PREVPOS", 0, MeshComponent::Vertex_POS::FORMAT, INPUT_SLOT_PREVPOS, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - - { "INSTANCEMATRIX", 0, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIX", 1, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIX", 2, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEUSERDATA", 0, FORMAT_R32G32B32A32_UINT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIXPREV", 0, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIXPREV", 1, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIXPREV", 2, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - }; LoadShader(VS, shaders[VSTYPE_OBJECT_PREPASS], "objectVS_prepass.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { - inputLayouts[ILTYPE_OBJECT_POS_PREVPOS_TEX].elements = - { - { "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, INPUT_SLOT_POSITION_NORMAL_WIND, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - { "PREVPOS", 0, MeshComponent::Vertex_POS::FORMAT, INPUT_SLOT_PREVPOS, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - { "UVSET", 0, MeshComponent::Vertex_TEX::FORMAT, INPUT_SLOT_UV0, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - { "UVSET", 1, MeshComponent::Vertex_TEX::FORMAT, INPUT_SLOT_UV1, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - - { "INSTANCEMATRIX", 0, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIX", 1, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIX", 2, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEUSERDATA", 0, FORMAT_R32G32B32A32_UINT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIXPREV", 0, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIXPREV", 1, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIXPREV", 2, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - }; LoadShader(VS, shaders[VSTYPE_OBJECT_PREPASS_ALPHATEST], "objectVS_prepass_alphatest.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { - inputLayouts[ILTYPE_OBJECT_POS].elements = - { - { "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, INPUT_SLOT_POSITION_NORMAL_WIND, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - - { "INSTANCEMATRIX", 0, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIX", 1, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIX", 2, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEUSERDATA", 0, FORMAT_R32G32B32A32_UINT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - }; LoadShader(VS, shaders[VSTYPE_SHADOW], "shadowVS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { - inputLayouts[ILTYPE_OBJECT_POS_TEX].elements = - { - { "POSITION_NORMAL_WIND", 0, MeshComponent::Vertex_POS::FORMAT, INPUT_SLOT_POSITION_NORMAL_WIND, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - { "UVSET", 0, MeshComponent::Vertex_TEX::FORMAT, INPUT_SLOT_UV0, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - { "UVSET", 1, MeshComponent::Vertex_TEX::FORMAT, INPUT_SLOT_UV1, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_VERTEX_DATA }, - - { "INSTANCEMATRIX", 0, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIX", 1, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEMATRIX", 2, FORMAT_R32G32B32A32_FLOAT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - { "INSTANCEUSERDATA", 0, FORMAT_R32G32B32A32_UINT, INPUT_SLOT_INSTANCEDATA, InputLayout::APPEND_ALIGNED_ELEMENT, INPUT_PER_INSTANCE_DATA }, - }; LoadShader(VS, shaders[VSTYPE_OBJECT_SIMPLE], "objectVS_simple.cso"); LoadShader(VS, shaders[VSTYPE_SHADOW_ALPHATEST], "shadowVS_alphatest.cso"); LoadShader(VS, shaders[VSTYPE_SHADOW_TRANSPARENT], "shadowVS_transparent.cso"); @@ -1161,7 +968,6 @@ void LoadShaders() wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(PS, shaders[PSTYPE_VERTEXCOLOR], "vertexcolorPS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(PS, shaders[PSTYPE_SKY_STATIC], "skyPS_static.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(PS, shaders[PSTYPE_SKY_DYNAMIC], "skyPS_dynamic.cso"); }); - wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(PS, shaders[PSTYPE_SKY_VELOCITY], "skyPS_velocity.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(PS, shaders[PSTYPE_SUN], "sunPS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(PS, shaders[PSTYPE_SHADOW_ALPHATEST], "shadowPS_alphatest.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(PS, shaders[PSTYPE_SHADOW_TRANSPARENT], "shadowPS_transparent.cso"); }); @@ -1170,7 +976,7 @@ void LoadShaders() wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(PS, shaders[PSTYPE_VOXELIZER_TERRAIN], "objectPS_voxelizer_terrain.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(PS, shaders[PSTYPE_VOXEL], "voxelPS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(PS, shaders[PSTYPE_FORCEFIELDVISUALIZER], "forceFieldVisualizerPS.cso"); }); - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(PS, shaders[PSTYPE_RENDERLIGHTMAP], "renderlightmapPS_rtapi.cso", SHADERMODEL_6_5); }); } @@ -1220,8 +1026,7 @@ void LoadShaders() wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_COPYTEXTURE2D_UNORM4_BORDEREXPAND], "copytexture2D_unorm4_borderexpandCS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_COPYTEXTURE2D_FLOAT4_BORDEREXPAND], "copytexture2D_float4_borderexpandCS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_SKINNING], "skinningCS.cso"); }); - wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_SKINNING_LDS], "skinningCS_LDS.cso"); }); - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_RAYTRACE], "raytraceCS_rtapi.cso", SHADERMODEL_6_5); }); } @@ -1296,7 +1101,6 @@ void LoadShaders() wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_VOLUMETRICCLOUDS_TEMPORAL], "volumetricCloud_temporalCS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_FXAA], "fxaaCS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_TEMPORALAA], "temporalaaCS.cso"); }); - wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_LINEARDEPTH], "lineardepthCS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_SHARPEN], "sharpenCS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_TONEMAP], "tonemapCS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_FSR_UPSCALING], "fsr_upscalingCS.cso"); }); @@ -1311,7 +1115,7 @@ void LoadShaders() wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_NORMALSFROMDEPTH], "normalsfromdepthCS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_SCREENSPACESHADOW], "screenspaceshadowCS.cso"); }); - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_RTSHADOW], "rtshadowCS.cso", SHADERMODEL_6_5); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_POSTPROCESS_RTSHADOW_DENOISE_TILECLASSIFICATION], "rtshadow_denoise_tileclassificationCS.cso"); }); @@ -1324,6 +1128,25 @@ void LoadShaders() } + wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_SURFEL_COVERAGE], "surfel_coverageCS.cso"); }); + wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_SURFEL_INDIRECTPREPARE], "surfel_indirectprepareCS.cso"); }); + wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_SURFEL_UPDATE], "surfel_updateCS.cso"); }); + wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_SURFEL_GRIDRESET], "surfel_gridresetCS.cso"); }); + wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_SURFEL_GRIDOFFSETS], "surfel_gridoffsetsCS.cso"); }); + wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_SURFEL_BINNING], "surfel_binningCS.cso"); }); + wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_SURFEL_SHADE], "surfel_shadeCS.cso"); }); + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) + { + wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_SURFEL_RAYTRACE], "surfel_raytraceCS_rtapi.cso", SHADERMODEL_6_5); }); + } + else + { + wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_SURFEL_RAYTRACE], "surfel_raytraceCS.cso"); }); + } + + wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_VISIBILITY_RESOLVE], "visibility_resolveCS.cso"); }); + wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(CS, shaders[CSTYPE_VISIBILITY_RESOLVE_MSAA], "visibility_resolveCS_MSAA.cso"); }); + wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(HS, shaders[HSTYPE_OBJECT], "objectHS.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(HS, shaders[HSTYPE_OBJECT_PREPASS], "objectHS_prepass.cso"); }); wiJobSystem::Execute(ctx, [](wiJobArgs args) { LoadShader(HS, shaders[HSTYPE_OBJECT_PREPASS_ALPHATEST], "objectHS_prepass_alphatest.cso"); }); @@ -1352,7 +1175,6 @@ void LoadShaders() { const bool transparency = blendMode != BLENDMODE_OPAQUE; SHADERTYPE realVS = GetVSTYPE((RENDERPASS)renderPass, tessellation, alphatest, transparency); - ILTYPES realVL = GetILTYPE((RENDERPASS)renderPass, tessellation, alphatest, transparency); SHADERTYPE realHS = GetHSTYPE((RENDERPASS)renderPass, tessellation, alphatest); SHADERTYPE realDS = GetDSTYPE((RENDERPASS)renderPass, tessellation, alphatest); SHADERTYPE realGS = GetGSTYPE((RENDERPASS)renderPass, alphatest, transparency); @@ -1364,18 +1186,12 @@ void LoadShaders() } PipelineStateDesc desc; - desc.il = realVL < ILTYPE_COUNT ? &inputLayouts[realVL] : nullptr; desc.vs = realVS < SHADERTYPE_COUNT ? &shaders[realVS] : nullptr; desc.hs = realHS < SHADERTYPE_COUNT ? &shaders[realHS] : nullptr; desc.ds = realDS < SHADERTYPE_COUNT ? &shaders[realDS] : nullptr; desc.gs = realGS < SHADERTYPE_COUNT ? &shaders[realGS] : nullptr; desc.ps = realPS < SHADERTYPE_COUNT ? &shaders[realPS] : nullptr; - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS)) - { - desc.il = nullptr; - } - switch (blendMode) { case BLENDMODE_OPAQUE: @@ -1488,13 +1304,11 @@ void LoadShaders() wiJobSystem::Dispatch(ctx, RENDERPASS_COUNT, 1, [](wiJobArgs args) { SHADERTYPE realVS = GetVSTYPE((RENDERPASS) args.jobIndex, false, false, false); - ILTYPES realVL = GetILTYPE((RENDERPASS)args.jobIndex, false, false, false); PipelineStateDesc desc; desc.rs = &rasterizers[RSTYPE_FRONT]; desc.bs = &blendStates[BSTYPE_OPAQUE]; desc.dss = &depthStencils[DSSTYPE_DEFAULT]; - desc.il = &inputLayouts[realVL]; desc.vs = &shaders[realVS]; switch (args.jobIndex) @@ -1535,11 +1349,9 @@ void LoadShaders() // Hologram sample shader will be registered as custom shader: wiJobSystem::Execute(ctx, [](wiJobArgs args) { SHADERTYPE realVS = GetVSTYPE(RENDERPASS_MAIN, false, false, true); - ILTYPES realVL = GetILTYPE(RENDERPASS_MAIN, false, false, true); PipelineStateDesc desc; desc.vs = &shaders[realVS]; - desc.il = &inputLayouts[realVL]; desc.ps = &shaders[PSTYPE_OBJECT_HOLOGRAM]; desc.bs = &blendStates[BSTYPE_ADDITIVE]; @@ -1565,12 +1377,6 @@ void LoadShaders() desc.rs = &rasterizers[RSTYPE_WIRE]; desc.bs = &blendStates[BSTYPE_OPAQUE]; desc.dss = &depthStencils[DSSTYPE_DEFAULT]; - desc.il = &inputLayouts[ILTYPE_OBJECT_POS_TEX]; - - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS)) - { - desc.il = nullptr; - } device->CreatePipelineState(&desc, &PSO_object_wire); @@ -1643,7 +1449,6 @@ void LoadShaders() desc.rs = &rasterizers[RSTYPE_DOUBLESIDED]; desc.bs = &blendStates[BSTYPE_OPAQUE]; desc.dss = &depthStencils[DSSTYPE_CAPTUREIMPOSTOR]; - desc.il = &inputLayouts[ILTYPE_OBJECT_COMMON]; desc.ps = &shaders[PSTYPE_CAPTUREIMPOSTOR_ALBEDO]; device->CreatePipelineState(&desc, &PSO_captureimpostor_albedo); @@ -1790,11 +1595,6 @@ void LoadShaders() desc.vs = &shaders[VSTYPE_SKY]; desc.ps = &shaders[PSTYPE_SUN]; break; - case SKYRENDERING_VELOCITY: - desc.bs = &blendStates[BSTYPE_OPAQUE]; - desc.vs = &shaders[VSTYPE_SKY]; - desc.ps = &shaders[PSTYPE_SKY_VELOCITY]; - break; case SKYRENDERING_ENVMAPCAPTURE_STATIC: desc.bs = &blendStates[BSTYPE_OPAQUE]; desc.vs = &shaders[VSTYPE_ENVMAP_SKY]; @@ -1887,7 +1687,6 @@ void LoadShaders() case DEBUGRENDERING_PAINTRADIUS: desc.vs = &shaders[VSTYPE_OBJECT_SIMPLE]; desc.ps = &shaders[PSTYPE_OBJECT_PAINTRADIUS]; - desc.il = &inputLayouts[ILTYPE_OBJECT_POS_TEX]; desc.dss = &depthStencils[DSSTYPE_DEPTHREAD]; desc.rs = &rasterizers[RSTYPE_FRONT]; desc.bs = &blendStates[BSTYPE_TRANSPARENT]; @@ -1931,8 +1730,7 @@ void LoadShaders() device->CreatePipelineState(&desc, &PSO_debug[args.jobIndex]); }); - if(device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) && - device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_GEOMETRYINDEX)) + if(device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { wiJobSystem::Execute(ctx, [](wiJobArgs args) { @@ -1993,9 +1791,7 @@ void LoadBuffers() GPUBufferDesc bd; // The following buffers will be DEFAULT (long lifetime, slow update, fast read): - bd.CPUAccessFlags = 0; bd.Usage = USAGE_DEFAULT; - bd.MiscFlags = 0; bd.ByteWidth = sizeof(FrameCB); bd.BindFlags = BIND_CONSTANT_BUFFER; @@ -2017,81 +1813,6 @@ void LoadBuffers() device->CreateBuffer(&bd, nullptr, &resourceBuffers[RBTYPE_MATRIXARRAY]); device->SetName(&resourceBuffers[RBTYPE_MATRIXARRAY], "MatrixArray"); - - // The following buffers will be DYNAMIC (short lifetime, fast update, slow read): - bd.Usage = USAGE_DYNAMIC; - bd.CPUAccessFlags = CPU_ACCESS_WRITE; - bd.MiscFlags = 0; - bd.BindFlags = BIND_CONSTANT_BUFFER; - - bd.ByteWidth = sizeof(CameraCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_CAMERA]); - device->SetName(&constantBuffers[CBTYPE_CAMERA], "CameraCB"); - - bd.ByteWidth = sizeof(MiscCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_MISC]); - device->SetName(&constantBuffers[CBTYPE_MISC], "MiscCB"); - - bd.ByteWidth = sizeof(VolumeLightCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_VOLUMELIGHT]); - device->SetName(&constantBuffers[CBTYPE_VOLUMELIGHT], "VolumelightCB"); - - bd.ByteWidth = sizeof(CubemapRenderCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_CUBEMAPRENDER]); - device->SetName(&constantBuffers[CBTYPE_CUBEMAPRENDER], "CubemapRenderCB"); - - bd.ByteWidth = sizeof(TessellationCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_TESSELLATION]); - device->SetName(&constantBuffers[CBTYPE_TESSELLATION], "TessellationCB"); - - bd.ByteWidth = sizeof(RaytracingCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_RAYTRACE]); - device->SetName(&constantBuffers[CBTYPE_RAYTRACE], "RayTraceCB"); - - bd.ByteWidth = sizeof(GenerateMIPChainCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_MIPGEN]); - device->SetName(&constantBuffers[CBTYPE_MIPGEN], "MipGeneratorCB"); - - bd.ByteWidth = sizeof(FilterEnvmapCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_FILTERENVMAP]); - device->SetName(&constantBuffers[CBTYPE_FILTERENVMAP], "FilterEnvmapCB"); - - bd.ByteWidth = sizeof(CopyTextureCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_COPYTEXTURE]); - device->SetName(&constantBuffers[CBTYPE_COPYTEXTURE], "CopyTextureCB"); - - bd.ByteWidth = sizeof(ForwardEntityMaskCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_FORWARDENTITYMASK]); - device->SetName(&constantBuffers[CBTYPE_FORWARDENTITYMASK], "ForwardEntityMaskCB"); - - bd.ByteWidth = sizeof(PostProcessCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_POSTPROCESS]); - device->SetName(&constantBuffers[CBTYPE_POSTPROCESS], "PostProcessCB"); - - bd.ByteWidth = sizeof(FSRCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_POSTPROCESS_FSR]); - device->SetName(&constantBuffers[CBTYPE_POSTPROCESS_FSR], "FSRCB"); - - bd.ByteWidth = sizeof(MSAOCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_POSTPROCESS_MSAO]); - device->SetName(&constantBuffers[CBTYPE_POSTPROCESS_MSAO], "MSAOCB"); - - bd.ByteWidth = sizeof(MSAO_UPSAMPLECB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_POSTPROCESS_MSAO_UPSAMPLE]); - device->SetName(&constantBuffers[CBTYPE_POSTPROCESS_MSAO_UPSAMPLE], "MSAO_UPSAMPLECB"); - - bd.ByteWidth = sizeof(LensFlareCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_LENSFLARE]); - device->SetName(&constantBuffers[CBTYPE_LENSFLARE], "LensFlareCB"); - - bd.ByteWidth = sizeof(PaintRadiusCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_PAINTRADIUS]); - device->SetName(&constantBuffers[CBTYPE_PAINTRADIUS], "PaintRadiusCB"); - - bd.ByteWidth = sizeof(ShadingRateClassificationCB); - device->CreateBuffer(&bd, nullptr, &constantBuffers[CBTYPE_SHADINGRATECLASSIFICATION]); - device->SetName(&constantBuffers[CBTYPE_SHADINGRATECLASSIFICATION], "ShadingRateClassificationCB"); - { TextureDesc desc; desc.BindFlags = BIND_SHADER_RESOURCE; @@ -2703,22 +2424,6 @@ ForwardEntityMaskCB ForwardEntityCullingCPU(const Visibility& vis, const AABB& b return cb; } -void BindConstantBuffers(SHADERSTAGE stage, CommandList cmd) -{ - device->BindConstantBuffer(stage, &constantBuffers[CBTYPE_FRAME], CB_GETBINDSLOT(FrameCB), cmd); - device->BindConstantBuffer(stage, &constantBuffers[CBTYPE_CAMERA], CB_GETBINDSLOT(CameraCB), cmd); -} -void BindShadowmaps(SHADERSTAGE stage, CommandList cmd) -{ - device->BindResource(stage, &shadowMapArray_2D, TEXSLOT_SHADOWARRAY_2D, cmd); - device->BindResource(stage, &shadowMapArray_Cube, TEXSLOT_SHADOWARRAY_CUBE, cmd); - if (GetTransparentShadowsEnabled()) - { - device->BindResource(stage, &shadowMapArray_Transparent_2D, TEXSLOT_SHADOWARRAY_TRANSPARENT_2D, cmd); - device->BindResource(stage, &shadowMapArray_Transparent_Cube, TEXSLOT_SHADOWARRAY_TRANSPARENT_CUBE, cmd); - } -} - void RenderMeshes( const Visibility& vis, const RenderQueue& renderQueue, @@ -2734,189 +2439,37 @@ void RenderMeshes( return; device->EventBegin("RenderMeshes", cmd); - const bool bindless = device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS); tessellation = tessellation && device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_TESSELLATION); - if (tessellation) - { - BindConstantBuffers(DS, cmd); - } - - const TextureDesc& lightmap_desc = vis.scene->lightmap.GetDesc(); - const float lightmap_width_rcp = 1.0f / lightmap_desc.Width; - const float lightmap_height_rcp = 1.0f / lightmap_desc.Height; - + // Do we need to compute a light mask for this pass on the CPU? const bool forwardLightmaskRequest = renderPass == RENDERPASS_ENVMAPCAPTURE || renderPass == RENDERPASS_VOXELIZE; - const INSTANCETYPE instanceRequest = instanceTypes[renderPass]; - struct Instance_MATRIX_USERDATA - { - Instance instance; - }; - struct Instance_MATRIX_USERDATA_ATLAS - { - Instance instance; - InstanceAtlas instanceAtlas; - }; - struct Instance_MATRIX_USERDATA_MATRIXPREV - { - Instance instance; - InstancePrev instancePrev; - }; - // Pre-allocate space for all the instances in GPU-buffer: - uint32_t instanceDataSize = 0; - switch (instanceRequest) - { - default: - case INSTANCETYPE_MATRIX_USERDATA: - instanceDataSize = sizeof(Instance_MATRIX_USERDATA); - break; - case INSTANCETYPE_MATRIX_USERDATA_ATLAS: - instanceDataSize = sizeof(Instance_MATRIX_USERDATA_ATLAS); - break; - case INSTANCETYPE_MATRIX_USERDATA_MATRIXPREV: - instanceDataSize = sizeof(Instance_MATRIX_USERDATA_MATRIXPREV); - break; - } + uint32_t instanceDataSize = sizeof(ShaderMeshInstancePointer); size_t alloc_size = renderQueue.batchCount * frustum_count * instanceDataSize; GraphicsDevice::GPUAllocation instances = device->AllocateGPU(alloc_size, cmd); - // Purpose of InstancedBatch: - // The RenderQueue is sorted by meshIndex. There can be multiple instances for a single meshIndex, - // and the InstancedBatchArray contains this information. The array size will be the unique mesh count here. + // This will correspond to a single draw call + // It's used to render multiple instances of a single mesh struct InstancedBatch { - uint32_t meshIndex; - int instanceCount; - uint32_t dataOffset; - uint8_t userStencilRefOverride; - uint8_t forceAlphatestForDithering; // padded bool - uint16_t padding; + uint32_t meshIndex = ~0u; + uint32_t instanceCount = 0; + uint32_t dataOffset = 0; + uint8_t userStencilRefOverride = 0; + bool forceAlphatestForDithering = false; AABB aabb; - }; - InstancedBatch* instancedBatchArray = nullptr; - int instancedBatchCount = 0; + } instancedBatch = {}; - // The following loop is writing the instancing batches to a GPUBuffer: - size_t prevMeshIndex = ~0; - uint8_t prevUserStencilRefOverride = 0; - uint32_t instanceCount = 0; - for (uint32_t batchID = 0; batchID < renderQueue.batchCount; ++batchID) // Do not break out of this loop! + + // This will be called every time we start a new draw call: + auto batch_flush = [&]() { - const RenderBatch& batch = renderQueue.batchArray[batchID]; - const uint32_t meshIndex = batch.GetMeshIndex(); - const uint32_t instanceIndex = batch.GetInstanceIndex(); - const ObjectComponent& instance = vis.scene->objects[instanceIndex]; - const AABB& instanceAABB = vis.scene->aabb_objects[instanceIndex]; - const uint8_t userStencilRefOverride = instance.userStencilRef; - - // When we encounter a new mesh inside the global instance array, we begin a new InstancedBatch: - if (meshIndex != prevMeshIndex || userStencilRefOverride != prevUserStencilRefOverride) - { - prevMeshIndex = meshIndex; - prevUserStencilRefOverride = userStencilRefOverride; - - instancedBatchCount++; - InstancedBatch* instancedBatch = (InstancedBatch*)GetRenderFrameAllocator(cmd).allocate(sizeof(InstancedBatch)); - instancedBatch->meshIndex = meshIndex; - instancedBatch->instanceCount = 0; - instancedBatch->dataOffset = instances.offset + instanceCount * instanceDataSize; - instancedBatch->userStencilRefOverride = userStencilRefOverride; - instancedBatch->forceAlphatestForDithering = 0; - instancedBatch->aabb = AABB(); - if (instancedBatchArray == nullptr) - { - instancedBatchArray = instancedBatch; - } - } - - InstancedBatch& current_batch = instancedBatchArray[instancedBatchCount - 1]; - - float dither = instance.GetTransparency(); - - if (instance.IsImpostorPlacement()) - { - float distance = wiMath::Distance(instanceAABB.getCenter(), vis.camera->Eye); - float swapDistance = instance.impostorSwapDistance; - float fadeThreshold = instance.impostorFadeThresholdRadius; - dither = std::max(0.0f, distance - swapDistance) / fadeThreshold; - } - - if (dither > 0) - { - current_batch.forceAlphatestForDithering = 1; - } - - if (forwardLightmaskRequest) - { - current_batch.aabb = AABB::Merge(current_batch.aabb, instanceAABB); - } - - const XMFLOAT4X4& worldMatrix = instance.transform_index >= 0 ? vis.scene->transforms[instance.transform_index].world : IDENTITYMATRIX; - - for (uint32_t frustum_index = 0; frustum_index < frustum_count; ++frustum_index) - { - if (frusta != nullptr && !frusta[frustum_index].CheckBoxFast(instanceAABB)) - { - // In case multiple cameras were provided and no intersection detected with frustum, we don't add the instance for the face: - continue; - } - - // Write into actual GPU-buffer: - switch (instanceRequest) - { - default: - case INSTANCETYPE_MATRIX_USERDATA: - ((volatile Instance_MATRIX_USERDATA*)instances.data)[instanceCount].instance.Create(worldMatrix, instance.color, dither, frustum_index, instance.emissiveColor); - break; - case INSTANCETYPE_MATRIX_USERDATA_ATLAS: - ((volatile Instance_MATRIX_USERDATA_ATLAS*)instances.data)[instanceCount].instance.Create(worldMatrix, instance.color, dither, frustum_index, instance.emissiveColor); - { - XMFLOAT4 lightMapMulAdd; - if (instance.lightmap.IsValid()) - { - auto rect = instance.lightmap_rect; - - // eliminate border expansion: - rect.x += Scene::atlasClampBorder; - rect.y += Scene::atlasClampBorder; - rect.w -= Scene::atlasClampBorder * 2; - rect.h -= Scene::atlasClampBorder * 2; - - lightMapMulAdd = XMFLOAT4( - (float)rect.w / (float)lightmap_desc.Width, - (float)rect.h / (float)lightmap_desc.Height, - (float)rect.x / (float)lightmap_desc.Width, - (float)rect.y / (float)lightmap_desc.Height - ); - } - else - { - lightMapMulAdd = XMFLOAT4(0, 0, 0, 0); - } - ((volatile Instance_MATRIX_USERDATA_ATLAS*)instances.data)[instanceCount].instanceAtlas.Create(lightMapMulAdd); - } - break; - case INSTANCETYPE_MATRIX_USERDATA_MATRIXPREV: - ((volatile Instance_MATRIX_USERDATA_MATRIXPREV*)instances.data)[instanceCount].instance.Create(worldMatrix, instance.color, dither, frustum_index, instance.emissiveColor); - ((volatile Instance_MATRIX_USERDATA_MATRIXPREV*)instances.data)[instanceCount].instancePrev.Create(instance.prev_transform_index >= 0 ? vis.scene->prev_transforms[instance.prev_transform_index].world_prev : IDENTITYMATRIX); - break; - } - - current_batch.instanceCount++; // next instance in current InstancedBatch - instanceCount++; - } - - } - - // Render instanced batches: - for (int instancedBatchID = 0; instancedBatchID < instancedBatchCount; ++instancedBatchID) - { - const InstancedBatch& instancedBatch = instancedBatchArray[instancedBatchID]; + if (instancedBatch.instanceCount == 0) + return; const MeshComponent& mesh = vis.scene->meshes[instancedBatch.meshIndex]; const bool forceAlphaTestForDithering = instancedBatch.forceAlphatestForDithering != 0; const uint8_t userStencilRefOverride = instancedBatch.userStencilRefOverride; @@ -2925,71 +2478,17 @@ void RenderMeshes( const bool tessellatorRequested = tessF > 0 && tessellation; const bool terrain = mesh.IsTerrain(); - if (tessellatorRequested) - { - TessellationCB tessCB; - tessCB.xTessellationFactors = XMFLOAT4(tessF, tessF, tessF, tessF); - device->UpdateBuffer(&constantBuffers[CBTYPE_TESSELLATION], &tessCB, cmd); - device->BindConstantBuffer(HS, &constantBuffers[CBTYPE_TESSELLATION], CBSLOT_RENDERER_TESSELLATION, cmd); - } - if (forwardLightmaskRequest) { ForwardEntityMaskCB cb = ForwardEntityCullingCPU(vis, instancedBatch.aabb, renderPass); - device->UpdateBuffer(&constantBuffers[CBTYPE_FORWARDENTITYMASK], &cb, cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_FORWARDENTITYMASK], CB_GETBINDSLOT(ForwardEntityMaskCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(ForwardEntityMaskCB), cmd); } device->BindIndexBuffer(&mesh.indexBuffer, mesh.GetIndexFormat(), 0, cmd); - ObjectPushConstants push; // used with bindless model only - - if (bindless) - { - push.mesh = device->GetDescriptorIndex(&mesh.descriptor, SRV); - push.instances = device->GetDescriptorIndex(instances.buffer, SRV); - push.instance_offset = instancedBatch.dataOffset; - } - else - { - const GPUBuffer* vbs[] = { - mesh.streamoutBuffer_POS.IsValid() ? &mesh.streamoutBuffer_POS : &mesh.vertexBuffer_POS, - mesh.vertexBuffer_PRE.IsValid() ? &mesh.vertexBuffer_PRE : &mesh.vertexBuffer_POS, - &mesh.vertexBuffer_UV0, - &mesh.vertexBuffer_UV1, - &mesh.vertexBuffer_ATL, - &mesh.vertexBuffer_COL, - mesh.streamoutBuffer_TAN.IsValid() ? &mesh.streamoutBuffer_TAN : &mesh.vertexBuffer_TAN, - instances.buffer - }; - uint32_t strides[] = { - sizeof(MeshComponent::Vertex_POS), - sizeof(MeshComponent::Vertex_POS), - sizeof(MeshComponent::Vertex_TEX), - sizeof(MeshComponent::Vertex_TEX), - sizeof(MeshComponent::Vertex_TEX), - sizeof(MeshComponent::Vertex_COL), - sizeof(MeshComponent::Vertex_TAN), - instanceDataSize - }; - uint32_t offsets[] = { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - instancedBatch.dataOffset - }; - static_assert(arraysize(vbs) == INPUT_SLOT_COUNT, "This layout must conform to OBJECT_VERTEXINPUT enum!"); - static_assert(arraysize(vbs) == arraysize(strides), "Mismatch between vertex buffers and strides!"); - static_assert(arraysize(vbs) == arraysize(offsets), "Mismatch between vertex buffers and offsets!"); - device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); - } - - for (const MeshComponent::MeshSubset& subset : mesh.subsets) + for (size_t subsetIndex = 0; subsetIndex < mesh.subsets.size(); ++subsetIndex) { + const MeshComponent::MeshSubset& subset = mesh.subsets[subsetIndex]; if (subset.indexCount == 0) { continue; @@ -3063,72 +2562,17 @@ void RenderMeshes( device->BindShadingRate(material.shadingRate, cmd); } - if (bindless) - { - push.material = device->GetDescriptorIndex(&material.constantBuffer, SRV); - device->PushConstants(&push, sizeof(push), cmd); - } - else - { - device->BindConstantBuffer(VS, &material.constantBuffer, CB_GETBINDSLOT(MaterialCB), cmd); - device->BindConstantBuffer(PS, &material.constantBuffer, CB_GETBINDSLOT(MaterialCB), cmd); + assert(subsetIndex < 256u); // subsets must be represented as 8-bit - // Bind all material textures: - const GPUResource* materialtextures[MaterialComponent::TEXTURESLOT_COUNT]; - material.WriteTextures(materialtextures, arraysize(materialtextures)); - device->BindResources(PS, materialtextures, TEXSLOT_RENDERER_BASECOLORMAP, arraysize(materialtextures), cmd); - - if (tessellatorRequested) - { - device->BindConstantBuffer(DS, &material.constantBuffer, CB_GETBINDSLOT(MaterialCB), cmd); - device->BindResources(DS, materialtextures, TEXSLOT_RENDERER_BASECOLORMAP, arraysize(materialtextures), cmd); - } - - if (terrain) - { - if (mesh.terrain_material1 == INVALID_ENTITY || !vis.scene->materials.Contains(mesh.terrain_material1)) - { - device->BindResources(PS, materialtextures, TEXSLOT_RENDERER_BLEND1_BASECOLORMAP, 4, cmd); - device->BindConstantBuffer(PS, &material.constantBuffer, CB_GETBINDSLOT(MaterialCB_Blend1), cmd); - } - else - { - const MaterialComponent& blendmat = *vis.scene->materials.GetComponent(mesh.terrain_material1); - const GPUResource* res[4]; - blendmat.WriteTextures(res, arraysize(res)); - device->BindResources(PS, res, TEXSLOT_RENDERER_BLEND1_BASECOLORMAP, arraysize(res), cmd); - device->BindConstantBuffer(PS, &blendmat.constantBuffer, CB_GETBINDSLOT(MaterialCB_Blend1), cmd); - } - - if (mesh.terrain_material2 == INVALID_ENTITY || !vis.scene->materials.Contains(mesh.terrain_material2)) - { - device->BindResources(PS, materialtextures, TEXSLOT_RENDERER_BLEND2_BASECOLORMAP, 4, cmd); - device->BindConstantBuffer(PS, &material.constantBuffer, CB_GETBINDSLOT(MaterialCB_Blend2), cmd); - } - else - { - const MaterialComponent& blendmat = *vis.scene->materials.GetComponent(mesh.terrain_material2); - const GPUResource* res[4]; - blendmat.WriteTextures(res, arraysize(res)); - device->BindResources(PS, res, TEXSLOT_RENDERER_BLEND2_BASECOLORMAP, arraysize(res), cmd); - device->BindConstantBuffer(PS, &blendmat.constantBuffer, CB_GETBINDSLOT(MaterialCB_Blend2), cmd); - } - - if (mesh.terrain_material3 == INVALID_ENTITY || !vis.scene->materials.Contains(mesh.terrain_material3)) - { - device->BindResources(PS, materialtextures, TEXSLOT_RENDERER_BLEND3_BASECOLORMAP, 4, cmd); - device->BindConstantBuffer(PS, &material.constantBuffer, CB_GETBINDSLOT(MaterialCB_Blend3), cmd); - } - else - { - const MaterialComponent& blendmat = *vis.scene->materials.GetComponent(mesh.terrain_material3); - const GPUResource* res[4]; - blendmat.WriteTextures(res, arraysize(res)); - device->BindResources(PS, res, TEXSLOT_RENDERER_BLEND3_BASECOLORMAP, arraysize(res), cmd); - device->BindConstantBuffer(PS, &blendmat.constantBuffer, CB_GETBINDSLOT(MaterialCB_Blend3), cmd); - } - } - } + ObjectPushConstants push; + push.init( + instancedBatch.meshIndex, + (uint)subsetIndex, + subset.materialIndex, + device->GetDescriptorIndex(&instances.buffer, SRV), + instancedBatch.dataOffset + ); + device->PushConstants(&push, sizeof(push), cmd); if (pso_backside != nullptr) { @@ -3139,9 +2583,74 @@ void RenderMeshes( device->BindPipelineState(pso, cmd); device->DrawIndexedInstanced(subset.indexCount, instancedBatch.instanceCount, subset.indexOffset, 0, 0, cmd); } + }; + + // The following loop is writing the instancing batches to a GPUBuffer: + // RenderQueue is sorted based on mesh index, so when a new mesh or stencil request is encountered, we need to flush the batch + uint32_t instanceCount = 0; + for (uint32_t batchID = 0; batchID < renderQueue.batchCount; ++batchID) // Do not break out of this loop! + { + const RenderBatch& batch = renderQueue.batchArray[batchID]; + const uint32_t meshIndex = batch.GetMeshIndex(); + const uint32_t instanceIndex = batch.GetInstanceIndex(); + const ObjectComponent& instance = vis.scene->objects[instanceIndex]; + const AABB& instanceAABB = vis.scene->aabb_objects[instanceIndex]; + const uint8_t userStencilRefOverride = instance.userStencilRef; + + // When we encounter a new mesh inside the global instance array, we begin a new RenderBatch: + if (meshIndex != instancedBatch.meshIndex || userStencilRefOverride != instancedBatch.userStencilRefOverride) + { + batch_flush(); + + instancedBatch = {}; + instancedBatch.meshIndex = meshIndex; + instancedBatch.instanceCount = 0; + instancedBatch.dataOffset = instances.offset + instanceCount * instanceDataSize; + instancedBatch.userStencilRefOverride = userStencilRefOverride; + instancedBatch.forceAlphatestForDithering = 0; + instancedBatch.aabb = AABB(); + } + + float dither = instance.GetTransparency(); + + if (instance.IsImpostorPlacement()) + { + float distance = wiMath::Distance(instanceAABB.getCenter(), vis.camera->Eye); + float swapDistance = instance.impostorSwapDistance; + float fadeThreshold = instance.impostorFadeThresholdRadius; + dither = std::max(0.0f, distance - swapDistance) / fadeThreshold; + } + + if (dither > 0) + { + instancedBatch.forceAlphatestForDithering = 1; + } + + if (forwardLightmaskRequest) + { + instancedBatch.aabb = AABB::Merge(instancedBatch.aabb, instanceAABB); + } + + for (uint32_t frustum_index = 0; frustum_index < frustum_count; ++frustum_index) + { + if (frusta != nullptr && !frusta[frustum_index].CheckBoxFast(instanceAABB)) + { + // In case multiple cameras were provided and no intersection detected with frustum, we don't add the instance for the face: + continue; + } + + // Write into actual GPU-buffer: + ShaderMeshInstancePointer poi; + poi.Create(instanceIndex, frustum_index, dither); + std::memcpy((ShaderMeshInstancePointer*)instances.data + instanceCount, &poi, sizeof(ShaderMeshInstancePointer)); + + instancedBatch.instanceCount++; // next instance in current InstancedBatch + instanceCount++; + } + } - GetRenderFrameAllocator(cmd).free(sizeof(InstancedBatch) * instancedBatchCount); + batch_flush(); device->EventEnd(cmd); } @@ -3152,9 +2661,18 @@ void RenderImpostors( CommandList cmd ) { - const PipelineState* impostorRequest = GetImpostorPSO(renderPass); + const PipelineState* pso = &PSO_impostor[renderPass]; + if (IsWireRender()) + { + switch (renderPass) + { + case RENDERPASS_MAIN: + pso = &PSO_impostor_wire; + } + return; + } - if (vis.scene->impostors.GetCount() > 0 && impostorRequest != nullptr) + if (vis.scene->impostors.GetCount() > 0 && pso != nullptr) { uint32_t instanceCount = 0; for (size_t impostorID = 0; impostorID < vis.scene->impostors.GetCount(); ++impostorID) @@ -3162,7 +2680,7 @@ void RenderImpostors( const ImpostorComponent& impostor = vis.scene->impostors[impostorID]; if (vis.camera->frustum.CheckBoxFast(impostor.aabb)) { - instanceCount += (uint32_t)impostor.instanceMatrices.size(); + instanceCount += (uint32_t)impostor.instances.size(); } } @@ -3174,7 +2692,7 @@ void RenderImpostors( device->EventBegin("RenderImpostors", cmd); // Pre-allocate space for all the instances in GPU-buffer: - const uint32_t instanceDataSize = sizeof(Instance); + const uint32_t instanceDataSize = sizeof(ShaderMeshInstancePointer); const size_t alloc_size = instanceCount * instanceDataSize; GraphicsDevice::GPUAllocation instances = device->AllocateGPU(alloc_size, cmd); @@ -3187,9 +2705,16 @@ void RenderImpostors( continue; } - for (auto& mat : impostor.instanceMatrices) + for (auto& instanceIndex : impostor.instances) { - const XMFLOAT3 center = *((XMFLOAT3*)&mat._41); + const ShaderMeshInstance& instance = vis.scene->instanceData[instanceIndex]; + const AABB& aabb = vis.scene->aabb_objects[instanceIndex]; + if (!vis.camera->frustum.CheckBoxFast(aabb)) + { + continue; + } + + const XMFLOAT3 center = aabb.getCenter(); float distance = wiMath::Distance(vis.camera->Eye, center); if (distance < impostor.swapInDistance - impostor.fadeThresholdRadius) @@ -3199,22 +2724,22 @@ void RenderImpostors( float dither = std::max(0.0f, impostor.swapInDistance - distance) / impostor.fadeThresholdRadius; - ((volatile Instance*)instances.data)[drawableInstanceCount].Create(mat, impostor.color, dither, uint32_t(impostorID * impostorCaptureAngles * 3)); + // Write into actual GPU-buffer: + ShaderMeshInstancePointer poi; + poi.Create(instanceIndex, uint32_t(impostorID * impostorCaptureAngles * 3), dither); + std::memcpy((ShaderMeshInstancePointer*)instances.data + drawableInstanceCount, &poi, sizeof(ShaderMeshInstancePointer)); drawableInstanceCount++; } } device->BindStencilRef(STENCILREF_DEFAULT, cmd); - device->BindPipelineState(impostorRequest, cmd); + device->BindPipelineState(pso, cmd); - MiscCB cb; - cb.g_xColor.x = (float)instances.offset; - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &cb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->PushConstants(&instances.offset, sizeof(uint), cmd); - device->BindResource(VS, instances.buffer, TEXSLOT_ONDEMAND21, cmd); - device->BindResource(PS, &vis.scene->impostorArray, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&instances.buffer, TEXSLOT_ONDEMAND21, cmd); + device->BindResource(&vis.scene->impostorArray, TEXSLOT_ONDEMAND0, cmd); device->Draw(drawableInstanceCount * 6, 0, cmd); @@ -3542,81 +3067,81 @@ void UpdatePerFrameData( wiJobSystem::Wait(ctx); - if (!device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) && !device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE) && scene.IsAccelerationStructureUpdateRequested()) + if (!device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING) && scene.IsAccelerationStructureUpdateRequested()) { scene.BVH.Update(scene); } // Update CPU-side frame constant buffer: - frameCB.g_xFrame_ConstantOne = 1; - frameCB.g_xFrame_CanvasSize = float2(canvas.GetLogicalWidth(), canvas.GetLogicalHeight()); - frameCB.g_xFrame_CanvasSize_rcp = float2(1.0f / frameCB.g_xFrame_CanvasSize.x, 1.0f / frameCB.g_xFrame_CanvasSize.y); - frameCB.g_xFrame_InternalResolution = float2((float)internalResolution.x, (float)internalResolution.y); - frameCB.g_xFrame_InternalResolution_rcp = float2(1.0f / frameCB.g_xFrame_InternalResolution.x, 1.0f / frameCB.g_xFrame_InternalResolution.y); - frameCB.g_xFrame_Gamma = GetGamma(); - frameCB.g_xFrame_SunColor = vis.scene->weather.sunColor; - frameCB.g_xFrame_SunDirection = vis.scene->weather.sunDirection; - frameCB.g_xFrame_SunEnergy = vis.scene->weather.sunEnergy; - frameCB.g_xFrame_ShadowCascadeCount = CASCADE_COUNT; - frameCB.g_xFrame_Ambient = vis.scene->weather.ambient; - frameCB.g_xFrame_Cloudiness = vis.scene->weather.cloudiness; - frameCB.g_xFrame_CloudScale = vis.scene->weather.cloudScale; - frameCB.g_xFrame_CloudSpeed = vis.scene->weather.cloudSpeed; - frameCB.g_xFrame_Fog = float4(vis.scene->weather.fogStart, vis.scene->weather.fogEnd, vis.scene->weather.fogHeightStart, vis.scene->weather.fogHeightEnd); - frameCB.g_xFrame_FogHeightSky = vis.scene->weather.fogHeightSky; - frameCB.g_xFrame_Horizon = vis.scene->weather.horizon; - frameCB.g_xFrame_Zenith = vis.scene->weather.zenith; - frameCB.g_xFrame_SkyExposure = vis.scene->weather.skyExposure; - frameCB.g_xFrame_VoxelRadianceMaxDistance = voxelSceneData.maxDistance; - frameCB.g_xFrame_VoxelRadianceDataSize = voxelSceneData.voxelsize; - frameCB.g_xFrame_VoxelRadianceDataSize_rcp = 1.0f / (float)frameCB.g_xFrame_VoxelRadianceDataSize; - frameCB.g_xFrame_VoxelRadianceDataRes = GetVoxelRadianceEnabled() ? (uint)voxelSceneData.res : 0; - frameCB.g_xFrame_VoxelRadianceDataRes_rcp = 1.0f / (float)frameCB.g_xFrame_VoxelRadianceDataRes; - frameCB.g_xFrame_VoxelRadianceDataMIPs = voxelSceneData.mips; - frameCB.g_xFrame_VoxelRadianceNumCones = std::max(std::min(voxelSceneData.numCones, 16u), 1u); - frameCB.g_xFrame_VoxelRadianceNumCones_rcp = 1.0f / (float)frameCB.g_xFrame_VoxelRadianceNumCones; - frameCB.g_xFrame_VoxelRadianceRayStepSize = voxelSceneData.rayStepSize; - frameCB.g_xFrame_VoxelRadianceDataCenter = voxelSceneData.center; - frameCB.g_xFrame_EntityCullingTileCount = GetEntityCullingTileCount(internalResolution); - frameCB.g_xFrame_ObjectShaderSamplerIndex = device->GetDescriptorIndex(&samplers[SSLOT_OBJECTSHADER]); + frameCB.ConstantOne = 1; + frameCB.CanvasSize = float2(canvas.GetLogicalWidth(), canvas.GetLogicalHeight()); + frameCB.CanvasSize_rcp = float2(1.0f / frameCB.CanvasSize.x, 1.0f / frameCB.CanvasSize.y); + frameCB.InternalResolution = float2((float)internalResolution.x, (float)internalResolution.y); + frameCB.InternalResolution_rcp = float2(1.0f / frameCB.InternalResolution.x, 1.0f / frameCB.InternalResolution.y); + frameCB.Gamma = GetGamma(); + frameCB.SunColor = vis.scene->weather.sunColor; + frameCB.SunDirection = vis.scene->weather.sunDirection; + frameCB.SunEnergy = vis.scene->weather.sunEnergy; + frameCB.ShadowCascadeCount = CASCADE_COUNT; + frameCB.Ambient = vis.scene->weather.ambient; + frameCB.Cloudiness = vis.scene->weather.cloudiness; + frameCB.CloudScale = vis.scene->weather.cloudScale; + frameCB.CloudSpeed = vis.scene->weather.cloudSpeed; + frameCB.Fog = float4(vis.scene->weather.fogStart, vis.scene->weather.fogEnd, vis.scene->weather.fogHeightStart, vis.scene->weather.fogHeightEnd); + frameCB.FogHeightSky = vis.scene->weather.fogHeightSky; + frameCB.Horizon = vis.scene->weather.horizon; + frameCB.Zenith = vis.scene->weather.zenith; + frameCB.SkyExposure = vis.scene->weather.skyExposure; + frameCB.VoxelRadianceMaxDistance = voxelSceneData.maxDistance; + frameCB.VoxelRadianceDataSize = voxelSceneData.voxelsize; + frameCB.VoxelRadianceDataSize_rcp = 1.0f / (float)frameCB.VoxelRadianceDataSize; + frameCB.VoxelRadianceDataRes = GetVoxelRadianceEnabled() ? (uint)voxelSceneData.res : 0; + frameCB.VoxelRadianceDataRes_rcp = 1.0f / (float)frameCB.VoxelRadianceDataRes; + frameCB.VoxelRadianceDataMIPs = voxelSceneData.mips; + frameCB.VoxelRadianceNumCones = std::max(std::min(voxelSceneData.numCones, 16u), 1u); + frameCB.VoxelRadianceNumCones_rcp = 1.0f / (float)frameCB.VoxelRadianceNumCones; + frameCB.VoxelRadianceRayStepSize = voxelSceneData.rayStepSize; + frameCB.VoxelRadianceDataCenter = voxelSceneData.center; + frameCB.EntityCullingTileCount = GetEntityCullingTileCount(internalResolution); + frameCB.ObjectShaderSamplerIndex = device->GetDescriptorIndex(&samplers[SSLOT_OBJECTSHADER]); // The order is very important here: - frameCB.g_xFrame_DecalArrayOffset = 0; - frameCB.g_xFrame_DecalArrayCount = (uint)vis.visibleDecals.size(); - frameCB.g_xFrame_EnvProbeArrayOffset = frameCB.g_xFrame_DecalArrayCount; - frameCB.g_xFrame_EnvProbeArrayCount = std::min(vis.scene->envmapCount, (uint)vis.visibleEnvProbes.size()); - frameCB.g_xFrame_LightArrayOffset = frameCB.g_xFrame_EnvProbeArrayOffset + frameCB.g_xFrame_EnvProbeArrayCount; - frameCB.g_xFrame_LightArrayCount = (uint)vis.visibleLights.size(); - frameCB.g_xFrame_ForceFieldArrayOffset = frameCB.g_xFrame_LightArrayOffset + frameCB.g_xFrame_LightArrayCount; - frameCB.g_xFrame_ForceFieldArrayCount = (uint)vis.scene->forces.GetCount(); + frameCB.DecalArrayOffset = 0; + frameCB.DecalArrayCount = (uint)vis.visibleDecals.size(); + frameCB.EnvProbeArrayOffset = frameCB.DecalArrayCount; + frameCB.EnvProbeArrayCount = std::min(vis.scene->envmapCount, (uint)vis.visibleEnvProbes.size()); + frameCB.LightArrayOffset = frameCB.EnvProbeArrayOffset + frameCB.EnvProbeArrayCount; + frameCB.LightArrayCount = (uint)vis.visibleLights.size(); + frameCB.ForceFieldArrayOffset = frameCB.LightArrayOffset + frameCB.LightArrayCount; + frameCB.ForceFieldArrayCount = (uint)vis.scene->forces.GetCount(); - frameCB.g_xFrame_GlobalEnvProbeIndex = 0; - frameCB.g_xFrame_EnvProbeMipCount = 0; - frameCB.g_xFrame_EnvProbeMipCount_rcp = 1.0f; + frameCB.GlobalEnvProbeIndex = 0; + frameCB.EnvProbeMipCount = 0; + frameCB.EnvProbeMipCount_rcp = 1.0f; if (vis.scene->envmapArray.IsValid()) { - frameCB.g_xFrame_EnvProbeMipCount = vis.scene->envmapArray.GetDesc().MipLevels; - frameCB.g_xFrame_EnvProbeMipCount_rcp = 1.0f / (float)frameCB.g_xFrame_EnvProbeMipCount; + frameCB.EnvProbeMipCount = vis.scene->envmapArray.GetDesc().MipLevels; + frameCB.EnvProbeMipCount_rcp = 1.0f / (float)frameCB.EnvProbeMipCount; } - frameCB.g_xFrame_DeltaTime = dt * GetGameSpeed(); - frameCB.g_xFrame_TimePrev = frameCB.g_xFrame_Time; - frameCB.g_xFrame_Time += frameCB.g_xFrame_DeltaTime; - frameCB.g_xFrame_WindSpeed = vis.scene->weather.windSpeed; - frameCB.g_xFrame_WindRandomness = vis.scene->weather.windRandomness; - frameCB.g_xFrame_WindWaveSize = vis.scene->weather.windWaveSize; - frameCB.g_xFrame_WindDirection = vis.scene->weather.windDirection; - frameCB.g_xFrame_StaticSkyGamma = 0.0f; + frameCB.DeltaTime = dt * GetGameSpeed(); + frameCB.TimePrev = frameCB.Time; + frameCB.Time += frameCB.DeltaTime; + frameCB.WindSpeed = vis.scene->weather.windSpeed; + frameCB.WindRandomness = vis.scene->weather.windRandomness; + frameCB.WindWaveSize = vis.scene->weather.windWaveSize; + frameCB.WindDirection = vis.scene->weather.windDirection; + frameCB.StaticSkyGamma = 0.0f; if (vis.scene->weather.skyMap != nullptr) { bool hdr = !device->IsFormatUnorm(vis.scene->weather.skyMap->texture.desc.Format); - frameCB.g_xFrame_StaticSkyGamma = hdr ? 1.0f : frameCB.g_xFrame_Gamma; + frameCB.StaticSkyGamma = hdr ? 1.0f : frameCB.Gamma; } - frameCB.g_xFrame_FrameCount = (uint)device->GetFrameCount(); - frameCB.g_xFrame_TemporalAASampleRotation = 0; + frameCB.FrameCount = (uint)device->GetFrameCount(); + frameCB.TemporalAASampleRotation = 0; if (GetTemporalAAEnabled()) { - uint id = frameCB.g_xFrame_FrameCount % 4; + uint id = frameCB.FrameCount % 4; uint x = 0; uint y = 0; switch (id) @@ -3634,72 +3159,80 @@ void UpdatePerFrameData( default: break; } - frameCB.g_xFrame_TemporalAASampleRotation = (x & 0x000000FF) | ((y & 0x000000FF) << 8); + frameCB.TemporalAASampleRotation = (x & 0x000000FF) | ((y & 0x000000FF) << 8); } - frameCB.g_xFrame_ShadowKernel2D = 1.0f / SHADOWRES_2D; - frameCB.g_xFrame_ShadowKernelCube = 1.0f / SHADOWRES_CUBE; + frameCB.ShadowKernel2D = 1.0f / SHADOWRES_2D; + frameCB.ShadowKernelCube = 1.0f / SHADOWRES_CUBE; - frameCB.g_xFrame_WorldBoundsMin = vis.scene->bounds.getMin(); - frameCB.g_xFrame_WorldBoundsMax = vis.scene->bounds.getMax(); - frameCB.g_xFrame_WorldBoundsExtents.x = abs(frameCB.g_xFrame_WorldBoundsMax.x - frameCB.g_xFrame_WorldBoundsMin.x); - frameCB.g_xFrame_WorldBoundsExtents.y = abs(frameCB.g_xFrame_WorldBoundsMax.y - frameCB.g_xFrame_WorldBoundsMin.y); - frameCB.g_xFrame_WorldBoundsExtents.z = abs(frameCB.g_xFrame_WorldBoundsMax.z - frameCB.g_xFrame_WorldBoundsMin.z); - frameCB.g_xFrame_WorldBoundsExtents_rcp.x = 1.0f / frameCB.g_xFrame_WorldBoundsExtents.x; - frameCB.g_xFrame_WorldBoundsExtents_rcp.y = 1.0f / frameCB.g_xFrame_WorldBoundsExtents.y; - frameCB.g_xFrame_WorldBoundsExtents_rcp.z = 1.0f / frameCB.g_xFrame_WorldBoundsExtents.z; + frameCB.WorldBoundsMin = vis.scene->bounds.getMin(); + frameCB.WorldBoundsMax = vis.scene->bounds.getMax(); + frameCB.WorldBoundsExtents.x = abs(frameCB.WorldBoundsMax.x - frameCB.WorldBoundsMin.x); + frameCB.WorldBoundsExtents.y = abs(frameCB.WorldBoundsMax.y - frameCB.WorldBoundsMin.y); + frameCB.WorldBoundsExtents.z = abs(frameCB.WorldBoundsMax.z - frameCB.WorldBoundsMin.z); + frameCB.WorldBoundsExtents_rcp.x = 1.0f / frameCB.WorldBoundsExtents.x; + frameCB.WorldBoundsExtents_rcp.y = 1.0f / frameCB.WorldBoundsExtents.y; + frameCB.WorldBoundsExtents_rcp.z = 1.0f / frameCB.WorldBoundsExtents.z; - frameCB.g_xFrame_BlueNoisePhase = (frameCB.g_xFrame_FrameCount & 0xFF) * 1.6180339887f; + frameCB.BlueNoisePhase = (frameCB.FrameCount & 0xFF) * 1.6180339887f; - frameCB.g_xFrame_Options = 0; + frameCB.Options = 0; if (GetTemporalAAEnabled()) { - frameCB.g_xFrame_Options |= OPTION_BIT_TEMPORALAA_ENABLED; + frameCB.Options |= OPTION_BIT_TEMPORALAA_ENABLED; } if (GetTransparentShadowsEnabled()) { - frameCB.g_xFrame_Options |= OPTION_BIT_TRANSPARENTSHADOWS_ENABLED; + frameCB.Options |= OPTION_BIT_TRANSPARENTSHADOWS_ENABLED; } if (GetVoxelRadianceEnabled()) { - frameCB.g_xFrame_Options |= OPTION_BIT_VOXELGI_ENABLED; + frameCB.Options |= OPTION_BIT_VOXELGI_ENABLED; } if (GetVoxelRadianceReflectionsEnabled()) { - frameCB.g_xFrame_Options |= OPTION_BIT_VOXELGI_REFLECTIONS_ENABLED; + frameCB.Options |= OPTION_BIT_VOXELGI_REFLECTIONS_ENABLED; } if (voxelSceneData.centerChangedThisFrame) { - frameCB.g_xFrame_Options |= OPTION_BIT_VOXELGI_RETARGETTED; + frameCB.Options |= OPTION_BIT_VOXELGI_RETARGETTED; } if (vis.scene->weather.IsSimpleSky()) { - frameCB.g_xFrame_Options |= OPTION_BIT_SIMPLE_SKY; + frameCB.Options |= OPTION_BIT_SIMPLE_SKY; } if (vis.scene->weather.IsRealisticSky()) { - frameCB.g_xFrame_Options |= OPTION_BIT_REALISTIC_SKY; + frameCB.Options |= OPTION_BIT_REALISTIC_SKY; } if (vis.scene->weather.IsHeightFog()) { - frameCB.g_xFrame_Options |= OPTION_BIT_HEIGHT_FOG; + frameCB.Options |= OPTION_BIT_HEIGHT_FOG; } - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE) && GetRaytracedShadowsEnabled()) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING) && GetRaytracedShadowsEnabled()) { - frameCB.g_xFrame_Options |= OPTION_BIT_RAYTRACED_SHADOWS; - frameCB.g_xFrame_Options |= OPTION_BIT_SHADOW_MASK; - } - if (IsDisableAlbedoMaps()) - { - frameCB.g_xFrame_Options |= OPTION_BIT_DISABLE_ALBEDO_MAPS; + frameCB.Options |= OPTION_BIT_RAYTRACED_SHADOWS; + frameCB.Options |= OPTION_BIT_SHADOW_MASK; } if (GetScreenSpaceShadowsEnabled()) { - frameCB.g_xFrame_Options |= OPTION_BIT_SHADOW_MASK; + frameCB.Options |= OPTION_BIT_SHADOW_MASK; + } + if (GetSurfelGIEnabled()) + { + frameCB.Options |= OPTION_BIT_SURFELGI_ENABLED; + } + if (IsDisableAlbedoMaps()) + { + frameCB.Options |= OPTION_BIT_DISABLE_ALBEDO_MAPS; + } + if (IsForceDiffuseLighting()) + { + frameCB.Options |= OPTION_BIT_FORCE_DIFFUSE_LIGHTING; } - frameCB.g_xFrame_Atmosphere = vis.scene->weather.atmosphereParameters; - frameCB.g_xFrame_VolumetricClouds = vis.scene->weather.volumetricCloudParameters; - + frameCB.Atmosphere = vis.scene->weather.atmosphereParameters; + frameCB.VolumetricClouds = vis.scene->weather.volumetricCloudParameters; + frameCB.scene = vis.scene->shaderscene; // Create volumetric cloud static resources if needed: @@ -3713,7 +3246,7 @@ void UpdatePerFrameData( shape_desc.MipLevels = 6; shape_desc.Format = FORMAT_R8G8B8A8_UNORM; shape_desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - shape_desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE; + shape_desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; device->CreateTexture(&shape_desc, nullptr, &texture_shapeNoise); device->SetName(&texture_shapeNoise, "texture_shapeNoise"); @@ -3734,7 +3267,7 @@ void UpdatePerFrameData( detail_desc.MipLevels = 6; detail_desc.Format = FORMAT_R8G8B8A8_UNORM; detail_desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - detail_desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE; + detail_desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; device->CreateTexture(&detail_desc, nullptr, &texture_detailNoise); device->SetName(&texture_detailNoise, "texture_detailNoise"); @@ -3753,7 +3286,7 @@ void UpdatePerFrameData( texture_desc.Height = 128; texture_desc.Format = FORMAT_R8G8B8A8_UNORM; texture_desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - texture_desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE; + texture_desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; device->CreateTexture(&texture_desc, nullptr, &texture_curlNoise); device->SetName(&texture_curlNoise, "texture_curlNoise"); @@ -3770,30 +3303,26 @@ void UpdateRenderData( CommandList cmd ) { - device->UpdateBuffer(&constantBuffers[CBTYPE_FRAME], &frameCB, cmd); - UpdateCameraCB( - *vis.camera, - *vis.camera, - *vis.camera, - cmd - ); + device->EventBegin("UpdateRenderData", cmd); - BindCommonResources(cmd); - - // Update dirty material constant buffers: - for (size_t i = 0; i < vis.scene->materials.GetCount(); ++i) + // Begin copy barriers: { - const MaterialComponent& material = vis.scene->materials[i]; - if (material.dirty_buffer) - { - material.dirty_buffer = false; - - ShaderMaterial shadermaterial; - material.WriteShaderMaterial(&shadermaterial); - device->UpdateBuffer(&material.constantBuffer, &shadermaterial, cmd); - } + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&constantBuffers[CBTYPE_FRAME], RESOURCE_STATE_CONSTANT_BUFFER, RESOURCE_STATE_COPY_DST), + GPUBarrier::Buffer(&vis.scene->instanceBuffer, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_COPY_DST), + GPUBarrier::Buffer(&vis.scene->meshBuffer, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_COPY_DST), + GPUBarrier::Buffer(&vis.scene->materialBuffer, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_COPY_DST), + GPUBarrier::Buffer(&resourceBuffers[RBTYPE_ENTITYARRAY], RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_COPY_DST), + GPUBarrier::Buffer(&resourceBuffers[RBTYPE_MATRIXARRAY], RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_COPY_DST), + }; + device->Barrier(barriers, arraysize(barriers), cmd); } + device->UpdateBuffer(&constantBuffers[CBTYPE_FRAME], &frameCB, cmd); + device->UpdateBuffer(&vis.scene->instanceBuffer, vis.scene->instanceData.data(), cmd); + device->UpdateBuffer(&vis.scene->meshBuffer, vis.scene->meshData.data(), cmd); + device->UpdateBuffer(&vis.scene->materialBuffer, vis.scene->materialData.data(), cmd); + // Fill Entity Array with decals + envprobes + lights in the frustum: { // Reserve temporary entity array for GPU data upload: @@ -3842,34 +3371,19 @@ void UpdateRenderData( entityArray[entityCounter].SetIndices(matrixCounter, 0); matrixArray[matrixCounter] = XMMatrixInverse(nullptr, XMLoadFloat4x4(&decal.world)); - XMFLOAT4 atlasMulAdd; + int texture = -1; if (decal.texture != nullptr) { - const TextureDesc& desc = vis.scene->decalAtlas.GetDesc(); - - wiRectPacker::rect_xywh rect = vis.scene->packedDecals.at(decal.texture); - - // eliminate border expansion: - rect.x += Scene::atlasClampBorder; - rect.y += Scene::atlasClampBorder; - rect.w -= Scene::atlasClampBorder * 2; - rect.h -= Scene::atlasClampBorder * 2; - - atlasMulAdd = XMFLOAT4( - (float)rect.w / (float)desc.Width, - (float)rect.h / (float)desc.Height, - (float)rect.x / (float)desc.Width, - (float)rect.y / (float)desc.Height - ); + texture = device->GetDescriptorIndex(&decal.texture->texture, SRV); } - else + int normal = -1; + if (decal.normal != nullptr) { - atlasMulAdd = XMFLOAT4(0, 0, 0, 0); + normal = device->GetDescriptorIndex(&decal.normal->texture, SRV); } - matrixArray[matrixCounter].r[0] = XMVectorSetW(matrixArray[matrixCounter].r[0], atlasMulAdd.x); - matrixArray[matrixCounter].r[1] = XMVectorSetW(matrixArray[matrixCounter].r[1], atlasMulAdd.y); - matrixArray[matrixCounter].r[2] = XMVectorSetW(matrixArray[matrixCounter].r[2], atlasMulAdd.z); - matrixArray[matrixCounter].r[3] = XMVectorSetW(matrixArray[matrixCounter].r[3], atlasMulAdd.w); + matrixArray[matrixCounter].r[0] = XMVectorSetW(matrixArray[matrixCounter].r[0], *(float*)&texture); + matrixArray[matrixCounter].r[1] = XMVectorSetW(matrixArray[matrixCounter].r[1], *(float*)&normal); + matrixCounter++; entityCounter++; @@ -4077,32 +3591,54 @@ void UpdateRenderData( device->UpdateBuffer(&resourceBuffers[RBTYPE_ENTITYARRAY], entityArray, cmd, sizeof(ShaderEntity)*entityCounter); device->UpdateBuffer(&resourceBuffers[RBTYPE_MATRIXARRAY], matrixArray, cmd, sizeof(XMMATRIX)*matrixCounter); + // Temporary array for GPU entities can be freed now: GetRenderFrameAllocator(cmd).free(sizeof(ShaderEntity)*SHADER_ENTITY_COUNT); GetRenderFrameAllocator(cmd).free(sizeof(XMMATRIX)*MATRIXARRAY_COUNT); } + // End copy barriers: + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&constantBuffers[CBTYPE_FRAME], RESOURCE_STATE_COPY_DST, RESOURCE_STATE_CONSTANT_BUFFER), + GPUBarrier::Buffer(&vis.scene->instanceBuffer, RESOURCE_STATE_COPY_DST, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&vis.scene->meshBuffer, RESOURCE_STATE_COPY_DST, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&vis.scene->materialBuffer, RESOURCE_STATE_COPY_DST, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&resourceBuffers[RBTYPE_ENTITYARRAY], RESOURCE_STATE_COPY_DST, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&resourceBuffers[RBTYPE_MATRIXARRAY], RESOURCE_STATE_COPY_DST, RESOURCE_STATE_SHADER_RESOURCE), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + BindCommonResources(cmd); + UpdateCameraCB( + *vis.camera, + *vis.camera, + *vis.camera, + cmd + ); + auto range = wiProfiler::BeginRangeGPU("Skinning", cmd); device->EventBegin("Skinning", cmd); { - bool streamOutSetUp = false; - SHADERTYPE lastCS = CSTYPE_SKINNING_LDS; - GPUBarrier* barriers_start = (GPUBarrier*)GetRenderFrameAllocator(cmd).top(); - uint32_t numBarriers = 0; + for (size_t i = 0; i < vis.scene->armatures.GetCount(); ++i) + { + const ArmatureComponent& armature = vis.scene->armatures[i]; + // Upload bones for skinning to shader + device->UpdateBuffer(&armature.boneBuffer, armature.boneData.data(), cmd); + + barrier_stack[cmd].push_back(GPUBarrier::Buffer(&armature.boneBuffer, RESOURCE_STATE_COPY_DST, RESOURCE_STATE_SHADER_RESOURCE)); + } + barrier_stack_flush(cmd); for (size_t i = 0; i < vis.scene->meshes.GetCount(); ++i) { Entity entity = vis.scene->meshes.GetEntity(i); const MeshComponent& mesh = vis.scene->meshes[i]; - if (mesh.dirty_bindless && device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS)) + if (mesh.dirty_subsets) { - mesh.dirty_bindless = false; - - ShaderMesh shadermesh; - mesh.WriteShaderMesh(&shadermesh); - - int mesh_descriptor = device->GetDescriptorIndex(&mesh.descriptor, SRV); + mesh.dirty_subsets = false; size_t tmp_alloc = sizeof(ShaderMeshSubset) * mesh.subsets.size(); ShaderMeshSubset* subsetarray = (ShaderMeshSubset*)GetRenderFrameAllocator(cmd).allocate(tmp_alloc); @@ -4111,25 +3647,19 @@ void UpdateRenderData( { ShaderMeshSubset& shadersubset = subsetarray[j++]; shadersubset.indexOffset = x.indexOffset; - shadersubset.indexCount = x.indexCount; - shadersubset.mesh = mesh_descriptor; - - const MaterialComponent* material = vis.scene->materials.GetComponent(x.materialID); - if (material != nullptr) - { - shadersubset.material = device->GetDescriptorIndex(&material->constantBuffer, SRV); - } + shadersubset.materialIndex = (uint)vis.scene->materials.GetIndex(x.materialID); } - - device->UpdateBuffer(&mesh.descriptor, &shadermesh, cmd); - device->UpdateBuffer(&mesh.subsetBuffer, subsetarray, cmd); GetRenderFrameAllocator(cmd).free(tmp_alloc); + + device->UpdateBuffer(&mesh.subsetBuffer, subsetarray, cmd); + barrier_stack[cmd].push_back(GPUBarrier::Buffer(&mesh.subsetBuffer, RESOURCE_STATE_COPY_DST, RESOURCE_STATE_SHADER_RESOURCE)); } if (mesh.dirty_morph) { mesh.dirty_morph = false; wiRenderer::GetDevice()->UpdateBuffer(&mesh.vertexBuffer_POS, mesh.vertex_positions_morphed.data(), cmd); + barrier_stack[cmd].push_back(GPUBarrier::Buffer(&mesh.vertexBuffer_POS, RESOURCE_STATE_COPY_DST, RESOURCE_STATE_SHADER_RESOURCE)); } if (mesh.IsSkinned() && vis.scene->armatures.Contains(mesh.armatureID)) @@ -4144,36 +3674,7 @@ void UpdateRenderData( const ArmatureComponent& armature = *vis.scene->armatures.GetComponent(mesh.armatureID); - if (!streamOutSetUp) - { - // Set up skinning shader - streamOutSetUp = true; - GPUBuffer* vbs[] = { - nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr,nullptr - }; - const uint32_t strides[] = { - 0,0,0,0,0,0,0,0 - }; - device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, nullptr, cmd); - device->BindComputeShader(&shaders[CSTYPE_SKINNING_LDS], cmd); - } - - SHADERTYPE targetCS = CSTYPE_SKINNING_LDS; - - if (!GetLDSSkinningEnabled() || armature.boneData.size() > SKINNING_COMPUTE_THREADCOUNT) - { - // If we have more bones that can fit into LDS, we switch to a skinning shader which loads from device memory: - targetCS = CSTYPE_SKINNING; - } - - if (targetCS != lastCS) - { - lastCS = targetCS; - device->BindComputeShader(&shaders[targetCS], cmd); - } - - // Upload bones for skinning to shader - device->UpdateBuffer(&armature.boneBuffer, armature.boneData.data(), cmd, (int)(sizeof(ArmatureComponent::ShaderBoneType) * armature.boneData.size())); + device->BindComputeShader(&shaders[CSTYPE_SKINNING], cmd); // Do the skinning const GPUResource* vbs[] = { @@ -4187,50 +3688,41 @@ void UpdateRenderData( &mesh.streamoutBuffer_TAN, }; - numBarriers += arraysize(uavs); - GPUBarrier* barriers = (GPUBarrier*)GetRenderFrameAllocator(cmd).allocate(sizeof(GPUBarrier) * arraysize(uavs)); - barriers[0] = GPUBarrier::Buffer(&mesh.streamoutBuffer_POS, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE); - barriers[1] = GPUBarrier::Buffer(&mesh.streamoutBuffer_TAN, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE); - // Barriers will be issued later... + device->BindResources(vbs, SKINNINGSLOT_IN_VERTEX_POS, arraysize(vbs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); - device->BindResources(CS, vbs, SKINNINGSLOT_IN_VERTEX_POS, arraysize(vbs), cmd); - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->Dispatch(((uint32_t)mesh.vertex_positions.size() + 63) / 64, 1, 1, cmd); + + barrier_stack[cmd].push_back(GPUBarrier::Buffer(&mesh.streamoutBuffer_POS, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE)); + barrier_stack[cmd].push_back(GPUBarrier::Buffer(&mesh.streamoutBuffer_TAN, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE)); - device->Dispatch(((uint32_t)mesh.vertex_positions.size() + SKINNING_COMPUTE_THREADCOUNT - 1) / SKINNING_COMPUTE_THREADCOUNT, 1, 1, cmd); } } - if (streamOutSetUp) + // Soft body updates: + for (size_t i = 0; i < vis.scene->softbodies.GetCount(); ++i) { - numBarriers++; - GPUBarrier* barriers = (GPUBarrier*)GetRenderFrameAllocator(cmd).allocate(sizeof(GPUBarrier)); - barriers[0] = GPUBarrier::Memory(); - device->Barrier(barriers_start, numBarriers, cmd); - GetRenderFrameAllocator(cmd).free(sizeof(GPUBarrier) * numBarriers); + Entity entity = vis.scene->softbodies.GetEntity(i); + const SoftBodyPhysicsComponent& softbody = vis.scene->softbodies[i]; - device->UnbindUAVs(0, 2, cmd); - device->UnbindResources(SKINNINGSLOT_IN_VERTEX_POS, 4, cmd); + const MeshComponent* mesh = vis.scene->meshes.GetComponent(entity); + if (mesh != nullptr) + { + device->UpdateBuffer(&mesh->streamoutBuffer_POS, softbody.vertex_positions_simulation.data(), cmd); + device->UpdateBuffer(&mesh->streamoutBuffer_TAN, softbody.vertex_tangents_simulation.data(), cmd); + + barrier_stack[cmd].push_back(GPUBarrier::Buffer(&mesh->streamoutBuffer_POS, RESOURCE_STATE_COPY_DST, RESOURCE_STATE_SHADER_RESOURCE)); + barrier_stack[cmd].push_back(GPUBarrier::Buffer(&mesh->streamoutBuffer_TAN, RESOURCE_STATE_COPY_DST, RESOURCE_STATE_SHADER_RESOURCE)); + } } + barrier_stack_flush(cmd); + } device->EventEnd(cmd); wiProfiler::EndRange(range); // skinning - // Soft body updates: - for (size_t i = 0; i < vis.scene->softbodies.GetCount(); ++i) - { - Entity entity = vis.scene->softbodies.GetEntity(i); - const SoftBodyPhysicsComponent& softbody = vis.scene->softbodies[i]; - - const MeshComponent* mesh = vis.scene->meshes.GetComponent(entity); - if (mesh != nullptr) - { - device->UpdateBuffer(&mesh->streamoutBuffer_POS, softbody.vertex_positions_simulation.data(), cmd); - device->UpdateBuffer(&mesh->streamoutBuffer_TAN, softbody.vertex_tangents_simulation.data(), cmd); - } - } - // GPU Particle systems simulation/sorting/culling: if (!vis.visibleEmitters.empty()) { @@ -4243,7 +3735,7 @@ void UpdateRenderData( const MaterialComponent& material = *vis.scene->materials.GetComponent(entity); const MeshComponent* mesh = vis.scene->meshes.GetComponent(emitter.meshID); - emitter.UpdateGPU(transform, material, mesh, cmd); + emitter.UpdateGPU((uint32_t)vis.scene->materials.GetIndex(entity), transform, mesh, cmd); } wiProfiler::EndRange(range); } @@ -4260,9 +3752,10 @@ void UpdateRenderData( if (mesh != nullptr) { Entity entity = vis.scene->hairs.GetEntity(hairIndex); - const MaterialComponent& material = *vis.scene->materials.GetComponent(entity); + size_t materialIndex = vis.scene->materials.GetIndex(entity); + const MaterialComponent& material = vis.scene->materials[materialIndex]; - hair.UpdateGPU(*mesh, material, cmd); + hair.UpdateGPU((uint32_t)vis.scene->objects.GetCount() + hairIndex, (uint32_t)materialIndex, *mesh, material, cmd); } } wiProfiler::EndRange(range); @@ -4294,11 +3787,11 @@ void UpdateRenderData( const GPUResource* uavs[] = { &texture_shapeNoise, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&texture_shapeNoise, texture_shapeNoise.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&texture_shapeNoise, texture_shapeNoise.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -4309,7 +3802,6 @@ void UpdateRenderData( device->Dispatch(noiseThreadXY, noiseThreadXY, noiseThreadZ, cmd); - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -4321,11 +3813,11 @@ void UpdateRenderData( const GPUResource* uavs[] = { &texture_detailNoise, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&texture_detailNoise, texture_detailNoise.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&texture_detailNoise, texture_detailNoise.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -4335,14 +3827,13 @@ void UpdateRenderData( device->Dispatch(noiseThreadXYZ, noiseThreadXYZ, noiseThreadXYZ, cmd); - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } { GPUBarrier barriers[] = { - GPUBarrier::Image(&texture_shapeNoise, IMAGE_LAYOUT_UNORDERED_ACCESS, texture_shapeNoise.desc.layout), - GPUBarrier::Image(&texture_detailNoise, IMAGE_LAYOUT_UNORDERED_ACCESS, texture_detailNoise.desc.layout), + GPUBarrier::Image(&texture_shapeNoise, RESOURCE_STATE_UNORDERED_ACCESS, texture_shapeNoise.desc.layout), + GPUBarrier::Image(&texture_detailNoise, RESOURCE_STATE_UNORDERED_ACCESS, texture_detailNoise.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -4359,11 +3850,11 @@ void UpdateRenderData( const GPUResource* uavs[] = { &texture_curlNoise, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&texture_curlNoise, texture_curlNoise.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&texture_curlNoise, texture_curlNoise.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -4374,7 +3865,13 @@ void UpdateRenderData( device->Dispatch(curlThread, curlThread, 1, cmd); - device->UnbindUAVs(0, arraysize(uavs), cmd); + { + GPUBarrier barriers[] = { + GPUBarrier::Image(&texture_curlNoise, RESOURCE_STATE_UNORDERED_ACCESS, texture_curlNoise.desc.layout), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + device->EventEnd(cmd); } @@ -4386,11 +3883,11 @@ void UpdateRenderData( const GPUResource* uavs[] = { &texture_weatherMap, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&texture_weatherMap, texture_weatherMap.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&texture_weatherMap, texture_weatherMap.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -4403,20 +3900,21 @@ void UpdateRenderData( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&texture_weatherMap, IMAGE_LAYOUT_UNORDERED_ACCESS, texture_weatherMap.desc.layout), + GPUBarrier::Image(&texture_weatherMap, RESOURCE_STATE_UNORDERED_ACCESS, texture_weatherMap.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } volumetric_clouds_precomputed = true; } + + device->EventEnd(cmd); } void UpdateRaytracingAccelerationStructures(const Scene& scene, CommandList cmd) { - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) || device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { if (!scene.TLAS.IsValid()) @@ -4449,6 +3947,16 @@ void UpdateRaytracingAccelerationStructures(const Scene& scene, CommandList cmd) } } + for (size_t i = 0; i < scene.hairs.GetCount(); ++i) + { + const wiHairParticle& hair = scene.hairs[i]; + + if (hair.meshID != INVALID_ENTITY && hair.BLAS.IsValid()) + { + device->BuildRaytracingAccelerationStructure(&hair.BLAS, cmd, nullptr); + } + } + { GPUBarrier barriers[] = { GPUBarrier::Memory(), @@ -4467,7 +3975,20 @@ void UpdateRaytracingAccelerationStructures(const Scene& scene, CommandList cmd) auto range = wiProfiler::BeginRangeGPU("TLAS Update (GPU)", cmd); device->EventBegin("TLAS Update", cmd); + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&scene.TLAS.desc.toplevel.instanceBuffer, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_COPY_DST), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } device->UpdateBuffer(&scene.TLAS.desc.toplevel.instanceBuffer, scene.TLAS_instances.data(), cmd); + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&scene.TLAS.desc.toplevel.instanceBuffer, RESOURCE_STATE_COPY_DST, RESOURCE_STATE_SHADER_RESOURCE), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + device->BuildRaytracingAccelerationStructure(&scene.TLAS, cmd, nullptr); { @@ -4484,11 +4005,31 @@ void UpdateRaytracingAccelerationStructures(const Scene& scene, CommandList cmd) } else { + BindCommonResources(cmd); scene.BVH.Build(scene, cmd); } scene.acceleration_structure_update_requested = false; } + + +void OcclusionCulling_Reset(const Visibility& vis, wiGraphics::CommandList cmd) +{ + if (!GetOcclusionCullingEnabled() || GetFreezeCullingCameraEnabled()) + { + return; + } + + int query_write = vis.scene->queryheap_idx; + const GPUQueryHeap& queryHeap = vis.scene->queryHeap[query_write]; + + device->QueryReset( + &queryHeap, + 0, + queryHeap.desc.queryCount, + cmd + ); +} void OcclusionCulling_Render(const CameraComponent& camera_previous, const Visibility& vis, CommandList cmd) { if (!GetOcclusionCullingEnabled() || GetFreezeCullingCameraEnabled()) @@ -4506,7 +4047,6 @@ void OcclusionCulling_Render(const CameraComponent& camera_previous, const Visib const GPUQueryHeap& queryHeap = vis.scene->queryHeap[query_write]; device->BindPipelineState(&PSO_occlusionquery, cmd); - const bool bindless = device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS); XMMATRIX VP = camera_previous.GetViewProjection(); @@ -4525,18 +4065,7 @@ void OcclusionCulling_Render(const CameraComponent& camera_previous, const Visib const XMMATRIX transform = aabb.getAsBoxMatrix() * VP; - if (bindless) - { - device->PushConstants(&transform, sizeof(transform), cmd); - } - else - { - MiscCB cb; - XMStoreFloat4x4(&cb.g_xTransform, transform); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &cb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - - } + device->PushConstants(&transform, sizeof(transform), cmd); // render bounding box to later read the occlusion status device->QueryBegin(&queryHeap, queryIndex, cmd); @@ -4545,18 +4074,33 @@ void OcclusionCulling_Render(const CameraComponent& camera_previous, const Visib } } - device->QueryResolve( - &queryHeap, - 0, - vis.scene->writtenQueries[query_write], - cmd - ); - device->EventEnd(cmd); } wiProfiler::EndRange(range); // Occlusion Culling Render } +void OcclusionCulling_Resolve(const Visibility& vis, wiGraphics::CommandList cmd) +{ + if (!GetOcclusionCullingEnabled() || GetFreezeCullingCameraEnabled()) + { + return; + } + + if (!vis.visibleObjects.empty()) + { + int query_write = vis.scene->queryheap_idx; + const GPUQueryHeap& queryHeap = vis.scene->queryHeap[query_write]; + + device->QueryResolve( + &queryHeap, + 0, + vis.scene->writtenQueries[query_write], + &vis.scene->queryResultBuffer[query_write], + 0ull, + cmd + ); + } +} void DrawWaterRipples(const Visibility& vis, CommandList cmd) { @@ -4598,7 +4142,7 @@ void DrawSoftParticles( wiProfiler::BeginRangeGPU("EmittedParticles - Render (Distortion)", cmd) : wiProfiler::BeginRangeGPU("EmittedParticles - Render", cmd); - device->BindResource(PS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); // Sort emitters based on distance: assert(emitterCount < 0x0000FFFF); // watch out for sorting hash truncation! @@ -4623,11 +4167,11 @@ void DrawSoftParticles( if (distortion && emitter.shaderType == wiEmittedParticle::SOFT_DISTORTION) { - emitter.Draw(*vis.camera, material, cmd); + emitter.Draw(material, cmd); } else if (!distortion && (emitter.shaderType == wiEmittedParticle::SOFT || emitter.shaderType == wiEmittedParticle::SOFT_LIGHTING || emitter.shaderType == wiEmittedParticle::SIMPLE || IsWireRender())) { - emitter.Draw(*vis.camera, material, cmd); + emitter.Draw(material, cmd); } } @@ -4644,9 +4188,6 @@ void DrawLightVisualizers( { device->EventBegin("Light Visualizer Render", cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_VOLUMELIGHT], CB_GETBINDSLOT(VolumeLightCB), cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_VOLUMELIGHT], CB_GETBINDSLOT(VolumeLightCB), cmd); - XMMATRIX camrot = XMLoadFloat3x3(&vis.camera->rotationMatrix); XMMATRIX VP = vis.camera->GetViewProjection(); @@ -4675,7 +4216,7 @@ void DrawLightVisualizers( XMMatrixTranslationFromVector(XMLoadFloat3(&light.position)) ); - device->UpdateBuffer(&constantBuffers[CBTYPE_VOLUMELIGHT], &lcb, cmd); + device->BindDynamicConstantBuffer(lcb, CB_GETBINDSLOT(VolumeLightCB), cmd); device->Draw(108, 0, cmd); // circle } @@ -4689,7 +4230,7 @@ void DrawLightVisualizers( XMMatrixTranslationFromVector(XMLoadFloat3(&light.position)) ); - device->UpdateBuffer(&constantBuffers[CBTYPE_VOLUMELIGHT], &lcb, cmd); + device->BindDynamicConstantBuffer(lcb, CB_GETBINDSLOT(VolumeLightCB), cmd); device->Draw(192, 0, cmd); // cone } @@ -4713,13 +4254,9 @@ void DrawVolumeLights( { device->EventBegin("Volumetric Light Render", cmd); - BindShadowmaps(PS, cmd); + BindCommonResources(cmd); - device->BindResource(PS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], TEXSLOT_SKYVIEWLUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_TRANSMITTANCELUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_MULTISCATTERINGLUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], TEXSLOT_SKYLUMINANCELUT, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); XMMATRIX VP = vis.camera->GetViewProjection(); @@ -4747,9 +4284,7 @@ void DrawVolumeLights( { MiscCB miscCb; miscCb.g_xColor.x = float(i); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &miscCb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(miscCb, CB_GETBINDSLOT(MiscCB), cmd); device->Draw(3, 0, cmd); // full screen triangle } @@ -4760,9 +4295,7 @@ void DrawVolumeLights( miscCb.g_xColor.x = float(i); float sca = light.GetRange() + 1; XMStoreFloat4x4(&miscCb.g_xTransform, XMMatrixScaling(sca, sca, sca)*XMMatrixTranslationFromVector(XMLoadFloat3(&light.position)) * VP); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &miscCb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(miscCb, CB_GETBINDSLOT(MiscCB), cmd); device->Draw(240, 0, cmd); // icosphere } @@ -4778,9 +4311,7 @@ void DrawVolumeLights( XMMatrixTranslationFromVector(XMLoadFloat3(&light.position)) * VP ); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &miscCb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(miscCb, CB_GETBINDSLOT(MiscCB), cmd); device->Draw(192, 0, cmd); // cone } @@ -4809,7 +4340,7 @@ void DrawLensFlares( device->EventBegin("Lens Flares", cmd); - device->BindResource(VS, &depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); for (auto visibleLight : vis.visibleLights) { @@ -4831,11 +4362,11 @@ void DrawLensFlares( // Directional light can use occlusion texture (eg. clouds): if (texture_directional_occlusion == nullptr) { - device->BindResource(VS, wiTextureHelper::getWhite(), TEXSLOT_ONDEMAND0, cmd); + device->BindResource(wiTextureHelper::getWhite(), TEXSLOT_ONDEMAND0, cmd); } else { - device->BindResource(VS, texture_directional_occlusion, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(texture_directional_occlusion, TEXSLOT_ONDEMAND0, cmd); } } else @@ -4844,18 +4375,17 @@ void DrawLensFlares( POS = XMLoadFloat3(&light.position); // not using occlusion texture - device->BindResource(VS, wiTextureHelper::getWhite(), TEXSLOT_ONDEMAND0, cmd); + device->BindResource(wiTextureHelper::getWhite(), TEXSLOT_ONDEMAND0, cmd); } if (XMVectorGetX(XMVector3Dot(XMVectorSubtract(POS, vis.camera->GetEye()), vis.camera->GetAt())) > 0) // check if the camera is facing towards the flare or not { device->BindPipelineState(&PSO_lensflare, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_LENSFLARE], CB_GETBINDSLOT(LensFlareCB), cmd); // Get the screen position of the flare: XMVECTOR flarePos = XMVector3Project(POS, 0, 0, 1, 1, 1, 0, vis.camera->GetProjection(), vis.camera->GetView(), XMMatrixIdentity()); - LensFlareCB cb; + LensFlarePush cb; XMStoreFloat3(&cb.xLensFlarePos, flarePos); uint32_t i = 0; @@ -4873,9 +4403,9 @@ void DrawLensFlares( cb.xLensFlareSize.x = (float)x->texture.desc.Width; cb.xLensFlareSize.y = (float)x->texture.desc.Height; - device->UpdateBuffer(&constantBuffers[CBTYPE_LENSFLARE], &cb, cmd); + device->PushConstants(&cb, sizeof(cb), cmd); - device->BindResource(PS, &x->texture, TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&x->texture, TEXSLOT_ONDEMAND1, cmd); device->Draw(4, 0, cmd); i++; } @@ -4910,17 +4440,15 @@ void SetShadowProps2D(int resolution, int count) desc.ArraySize = SHADOWCOUNT_2D; desc.SampleCount = 1; desc.Usage = USAGE_DEFAULT; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; desc.BindFlags = BIND_DEPTH_STENCIL | BIND_SHADER_RESOURCE; desc.Format = FORMAT_R16_TYPELESS; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE; device->CreateTexture(&desc, nullptr, &shadowMapArray_2D); desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE; desc.Format = FORMAT_R16G16B16A16_FLOAT; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE; desc.clear.color[0] = 1; desc.clear.color[1] = 1; desc.clear.color[2] = 1; @@ -4944,9 +4472,9 @@ void SetShadowProps2D(int resolution, int count) &shadowMapArray_2D, RenderPassAttachment::LOADOP_CLEAR, RenderPassAttachment::STOREOP_STORE, - IMAGE_LAYOUT_SHADER_RESOURCE, - IMAGE_LAYOUT_DEPTHSTENCIL, - IMAGE_LAYOUT_SHADER_RESOURCE + RESOURCE_STATE_SHADER_RESOURCE, + RESOURCE_STATE_DEPTHSTENCIL, + RESOURCE_STATE_SHADER_RESOURCE ) ); renderpassdesc.attachments.back().subresource = subresource_index; @@ -4956,9 +4484,9 @@ void SetShadowProps2D(int resolution, int count) &shadowMapArray_Transparent_2D, RenderPassAttachment::LOADOP_CLEAR, RenderPassAttachment::STOREOP_STORE, - IMAGE_LAYOUT_SHADER_RESOURCE, - IMAGE_LAYOUT_RENDERTARGET, - IMAGE_LAYOUT_SHADER_RESOURCE + RESOURCE_STATE_SHADER_RESOURCE, + RESOURCE_STATE_RENDERTARGET, + RESOURCE_STATE_SHADER_RESOURCE ) ); renderpassdesc.attachments.back().subresource = subresource_index; @@ -4988,17 +4516,16 @@ void SetShadowPropsCube(int resolution, int count) desc.ArraySize = 6 * SHADOWCOUNT_CUBE; desc.SampleCount = 1; desc.Usage = USAGE_DEFAULT; - desc.CPUAccessFlags = 0; desc.MiscFlags = RESOURCE_MISC_TEXTURECUBE; desc.BindFlags = BIND_DEPTH_STENCIL | BIND_SHADER_RESOURCE; desc.Format = FORMAT_R16_TYPELESS; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE; device->CreateTexture(&desc, nullptr, &shadowMapArray_Cube); desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE; desc.Format = FORMAT_R16G16B16A16_FLOAT; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE; desc.clear.color[0] = 1; desc.clear.color[1] = 1; desc.clear.color[2] = 1; @@ -5021,9 +4548,9 @@ void SetShadowPropsCube(int resolution, int count) &shadowMapArray_Cube, RenderPassAttachment::LOADOP_CLEAR, RenderPassAttachment::STOREOP_STORE, - IMAGE_LAYOUT_SHADER_RESOURCE, - IMAGE_LAYOUT_DEPTHSTENCIL, - IMAGE_LAYOUT_SHADER_RESOURCE + RESOURCE_STATE_SHADER_RESOURCE, + RESOURCE_STATE_DEPTHSTENCIL, + RESOURCE_STATE_SHADER_RESOURCE ) ); renderpassdesc.attachments.back().subresource = subresource_index; @@ -5033,9 +4560,9 @@ void SetShadowPropsCube(int resolution, int count) &shadowMapArray_Transparent_Cube, RenderPassAttachment::LOADOP_CLEAR, RenderPassAttachment::STOREOP_STORE, - IMAGE_LAYOUT_SHADER_RESOURCE, - IMAGE_LAYOUT_RENDERTARGET, - IMAGE_LAYOUT_SHADER_RESOURCE + RESOURCE_STATE_SHADER_RESOURCE, + RESOURCE_STATE_RENDERTARGET, + RESOURCE_STATE_SHADER_RESOURCE ) ); renderpassdesc.attachments.back().subresource = subresource_index; @@ -5059,8 +4586,7 @@ void DrawShadowmaps( auto range = wiProfiler::BeginRangeGPU("Shadow Rendering", cmd); BindCommonResources(cmd); - BindConstantBuffers(VS, cmd); - BindConstantBuffers(PS, cmd); + BoundingFrustum cam_frustum; BoundingFrustum::CreateFromMatrix(cam_frustum, vis.camera->GetProjection()); @@ -5068,7 +4594,6 @@ void DrawShadowmaps( cam_frustum.Transform(cam_frustum, vis.camera->GetInvView()); XMStoreFloat4(&cam_frustum.Orientation, XMQuaternionNormalize(XMLoadFloat4(&cam_frustum.Orientation))); - device->UnbindResources(TEXSLOT_SHADOWARRAY_2D, 2, cmd); uint32_t shadowCounter_2D = SHADOWRES_2D > 0 ? 0 : SHADOWCOUNT_2D; uint32_t shadowCounter_Cube = SHADOWRES_CUBE > 0 ? 0 : SHADOWCOUNT_CUBE; @@ -5132,8 +4657,8 @@ void DrawShadowmaps( if (!renderQueue.empty()) { CameraCB cb; - XMStoreFloat4x4(&cb.g_xCamera_VP, shcams[cascade].VP); - device->UpdateBuffer(&constantBuffers[CBTYPE_CAMERA], &cb, cmd); + XMStoreFloat4x4(&cb.VP, shcams[cascade].VP); + device->BindDynamicConstantBuffer(cb, CBSLOT_RENDERER_CAMERA, cmd); Viewport vp; vp.TopLeftX = 0; @@ -5196,8 +4721,8 @@ void DrawShadowmaps( if (!renderQueue.empty()) { CameraCB cb; - XMStoreFloat4x4(&cb.g_xCamera_VP, shcam.VP); - device->UpdateBuffer(&constantBuffers[CBTYPE_CAMERA], &cb, cmd); + XMStoreFloat4x4(&cb.VP, shcam.VP); + device->BindDynamicConstantBuffer(cb, CBSLOT_RENDERER_CAMERA, cmd); Viewport vp; vp.TopLeftX = 0; @@ -5258,9 +4783,7 @@ void DrawShadowmaps( { MiscCB miscCb; miscCb.g_xColor = float4(light.position.x, light.position.y, light.position.z, 0); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &miscCb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(miscCb, CB_GETBINDSLOT(MiscCB), cmd); const float zNearP = 0.1f; const float zFarP = std::max(1.0f, light.GetRange()); @@ -5286,8 +4809,7 @@ void DrawShadowmaps( frustum_count++; } } - device->UpdateBuffer(&constantBuffers[CBTYPE_CUBEMAPRENDER], &cb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_CUBEMAPRENDER], CB_GETBINDSLOT(CubemapRenderCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(CubemapRenderCB), cmd); Viewport vp; vp.TopLeftX = 0; @@ -5336,32 +4858,10 @@ void DrawScene( device->BindShadingRate(SHADING_RATE_1X1, cmd); BindCommonResources(cmd); - BindShadowmaps(PS, cmd); - BindConstantBuffers(VS, cmd); - BindConstantBuffers(PS, cmd); - device->BindResource(PS, &vis.scene->envmapArray, TEXSLOT_ENVMAPARRAY, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], TEXSLOT_SKYVIEWLUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_TRANSMITTANCELUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_MULTISCATTERINGLUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], TEXSLOT_SKYLUMINANCELUT, cmd); - device->BindResource(PS, GetVoxelRadianceSecondaryBounceEnabled() ? &textures[TEXTYPE_3D_VOXELRADIANCE_HELPER] : &textures[TEXTYPE_3D_VOXELRADIANCE], TEXSLOT_VOXELRADIANCE, cmd); - - if (vis.scene->weather.skyMap != nullptr) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { - device->BindResource(PS, &vis.scene->weather.skyMap->texture, TEXSLOT_GLOBALENVMAP, cmd); - } - - device->BindResource(PS, &vis.scene->lightmap, TEXSLOT_GLOBALLIGHTMAP, cmd); - if (vis.scene->decalAtlas.IsValid()) - { - device->BindResource(PS, &vis.scene->decalAtlas, TEXSLOT_DECALATLAS, cmd); - } - - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) || device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) - { - device->BindResource(PS, &vis.scene->TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); - device->BindResource(CS, &vis.scene->TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); + device->BindResource(&vis.scene->TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); } if (transparent && vis.scene->weather.IsOceanEnabled()) @@ -5379,7 +4879,7 @@ void DrawScene( Entity entity = vis.scene->hairs.GetEntity(hairIndex); const MaterialComponent& material = *vis.scene->materials.GetComponent(entity); - hair.Draw(*vis.camera, material, renderPass, cmd); + hair.Draw(material, renderPass, cmd); } } } @@ -5468,7 +4968,6 @@ void DrawDebugWorld( bd.Usage = USAGE_DEFAULT; bd.ByteWidth = sizeof(verts); bd.BindFlags = BIND_VERTEX_BUFFER; - bd.CPUAccessFlags = 0; SubresourceData InitData; InitData.pSysMem = verts; device->CreateBuffer(&bd, &InitData, &wirecubeVB); @@ -5481,7 +4980,6 @@ void DrawDebugWorld( bd.Usage = USAGE_DEFAULT; bd.ByteWidth = sizeof(indices); bd.BindFlags = BIND_INDEX_BUFFER; - bd.CPUAccessFlags = 0; InitData.pSysMem = indices; device->CreateBuffer(&bd, &InitData, &wirecubeIB); } @@ -5489,8 +4987,6 @@ void DrawDebugWorld( device->EventBegin("DrawDebugWorld", cmd); BindCommonResources(cmd); - BindConstantBuffers(VS, cmd); - BindConstantBuffers(PS, cmd); if (debugPartitionTree) { @@ -5517,9 +5013,7 @@ void DrawDebugWorld( XMStoreFloat4x4(&sb.g_xTransform, aabb.getAsBoxMatrix()*camera.GetViewProjection()); sb.g_xColor = XMFLOAT4(1, 0, 0, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); device->DrawIndexed(24, 0, 0, cmd); } @@ -5531,9 +5025,7 @@ void DrawDebugWorld( XMStoreFloat4x4(&sb.g_xTransform, aabb.getAsBoxMatrix()*camera.GetViewProjection()); sb.g_xColor = XMFLOAT4(1, 1, 0, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); device->DrawIndexed(24, 0, 0, cmd); } @@ -5545,9 +5037,7 @@ void DrawDebugWorld( XMStoreFloat4x4(&sb.g_xTransform, aabb.getAsBoxMatrix()*camera.GetViewProjection()); sb.g_xColor = XMFLOAT4(1, 0, 1, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); device->DrawIndexed(24, 0, 0, cmd); } @@ -5559,9 +5049,7 @@ void DrawDebugWorld( XMStoreFloat4x4(&sb.g_xTransform, aabb.getAsBoxMatrix()*camera.GetViewProjection()); sb.g_xColor = XMFLOAT4(0, 1, 1, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); device->DrawIndexed(24, 0, 0, cmd); } @@ -5578,9 +5066,7 @@ void DrawDebugWorld( MiscCB sb; XMStoreFloat4x4(&sb.g_xTransform, camera.GetViewProjection()); sb.g_xColor = XMFLOAT4(1, 1, 1, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); for (size_t i = 0; i < scene.armatures.GetCount(); ++i) { @@ -5625,7 +5111,7 @@ void DrawDebugWorld( } const GPUBuffer* vbs[] = { - mem.buffer + &mem.buffer }; const uint32_t strides[] = { sizeof(XMFLOAT4) + sizeof(XMFLOAT4), @@ -5651,9 +5137,7 @@ void DrawDebugWorld( MiscCB sb; XMStoreFloat4x4(&sb.g_xTransform, camera.GetViewProjection()); sb.g_xColor = XMFLOAT4(1, 1, 1, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); struct Vertex { @@ -5678,7 +5162,7 @@ void DrawDebugWorld( } const GPUBuffer* vbs[] = { - mem.buffer, + &mem.buffer, }; const uint32_t strides[] = { sizeof(Vertex), @@ -5704,9 +5188,7 @@ void DrawDebugWorld( MiscCB sb; XMStoreFloat4x4(&sb.g_xTransform, camera.GetViewProjection()); sb.g_xColor = XMFLOAT4(1, 1, 1, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); struct Vertex { @@ -5731,7 +5213,7 @@ void DrawDebugWorld( } const GPUBuffer* vbs[] = { - mem.buffer, + &mem.buffer, }; const uint32_t strides[] = { sizeof(Vertex), @@ -5757,9 +5239,7 @@ void DrawDebugWorld( MiscCB sb; XMStoreFloat4x4(&sb.g_xTransform, camera.GetViewProjection()); sb.g_xColor = XMFLOAT4(1, 1, 1, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); struct LineSegment { @@ -5781,7 +5261,7 @@ void DrawDebugWorld( } const GPUBuffer* vbs[] = { - mem.buffer, + &mem.buffer, }; const uint32_t strides[] = { sizeof(XMFLOAT4) + sizeof(XMFLOAT4), @@ -5807,9 +5287,7 @@ void DrawDebugWorld( MiscCB sb; XMStoreFloat4x4(&sb.g_xTransform, canvas.GetProjection()); sb.g_xColor = XMFLOAT4(1, 1, 1, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); struct LineSegment { @@ -5831,7 +5309,7 @@ void DrawDebugWorld( } const GPUBuffer* vbs[] = { - mem.buffer, + &mem.buffer, }; const uint32_t strides[] = { sizeof(XMFLOAT4) + sizeof(XMFLOAT4), @@ -5857,9 +5335,7 @@ void DrawDebugWorld( MiscCB sb; XMStoreFloat4x4(&sb.g_xTransform, camera.GetProjection()); // only projection, we will expand in view space on CPU below to be camera facing! sb.g_xColor = XMFLOAT4(1, 1, 1, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); // Will generate 2 line segments for each point forming a cross section: struct LineSegment @@ -5896,7 +5372,7 @@ void DrawDebugWorld( } const GPUBuffer* vbs[] = { - mem.buffer, + &mem.buffer, }; const uint32_t strides[] = { sizeof(XMFLOAT4) + sizeof(XMFLOAT4), @@ -5935,9 +5411,7 @@ void DrawDebugWorld( XMStoreFloat4x4(&sb.g_xTransform, XMLoadFloat4x4(&x.first)*camera.GetViewProjection()); sb.g_xColor = x.second; - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); device->DrawIndexed(24, 0, 0, cmd); } @@ -5991,7 +5465,6 @@ void DrawDebugWorld( bd.Usage = USAGE_DEFAULT; bd.ByteWidth = uint32_t(vertices.size() * sizeof(Vertex)); bd.BindFlags = BIND_VERTEX_BUFFER; - bd.CPUAccessFlags = 0; SubresourceData InitData; InitData.pSysMem = vertices.data(); device->CreateBuffer(&bd, &InitData, &wiresphereVB); @@ -6016,7 +5489,6 @@ void DrawDebugWorld( bd.Usage = USAGE_DEFAULT; bd.ByteWidth = uint32_t(indices.size() * sizeof(uint16_t)); bd.BindFlags = BIND_INDEX_BUFFER; - bd.CPUAccessFlags = 0; InitData.pSysMem = indices.data(); device->CreateBuffer(&bd, &InitData, &wiresphereIB); } @@ -6044,9 +5516,7 @@ void DrawDebugWorld( ); sb.g_xColor = x.second; - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); device->DrawIndexed(wiresphereIB.GetDesc().ByteWidth / sizeof(uint16_t), 0, 0, cmd); } @@ -6064,9 +5534,7 @@ void DrawDebugWorld( MiscCB sb; XMStoreFloat4x4(&sb.g_xTransform, camera.GetViewProjection()); sb.g_xColor = XMFLOAT4(1, 1, 1, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); const int segmentcount = 18 + 1 + 18 + 1; const int linecount = (int)renderableCapsules.size() * segmentcount; @@ -6136,7 +5604,7 @@ void DrawDebugWorld( } const GPUBuffer* vbs[] = { - mem.buffer, + &mem.buffer, }; const uint32_t strides[] = { sizeof(XMFLOAT4) + sizeof(XMFLOAT4), @@ -6167,17 +5635,15 @@ void DrawDebugWorld( const EnvironmentProbeComponent& probe = scene.probes[i]; XMStoreFloat4x4(&sb.g_xTransform, XMMatrixTranslationFromVector(XMLoadFloat3(&probe.position))); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); if (probe.textureIndex < 0) { - device->BindResource(PS, wiTextureHelper::getBlackCubeMap(), TEXSLOT_ONDEMAND0, cmd); + device->BindResource(wiTextureHelper::getBlackCubeMap(), TEXSLOT_ONDEMAND0, cmd); } else { - device->BindResource(PS, &scene.envmapArray, TEXSLOT_ONDEMAND0, cmd, scene.envmapArray.GetDesc().MipLevels + probe.textureIndex); + device->BindResource(&scene.envmapArray, TEXSLOT_ONDEMAND0, cmd, scene.envmapArray.GetDesc().MipLevels + probe.textureIndex); } device->Draw(2880, 0, cmd); // uv-sphere @@ -6212,9 +5678,7 @@ void DrawDebugWorld( XMStoreFloat4x4(&sb.g_xTransform, XMLoadFloat4x4(&transform.world)*camera.GetViewProjection()); sb.g_xColor = float4(0, 1, 1, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); device->DrawIndexed(24, 0, 0, cmd); } @@ -6259,10 +5723,8 @@ void DrawDebugWorld( gridVertexCount = arraysize(verts) / 2; GPUBufferDesc bd; - bd.Usage = USAGE_IMMUTABLE; bd.ByteWidth = sizeof(verts); bd.BindFlags = BIND_VERTEX_BUFFER; - bd.CPUAccessFlags = 0; SubresourceData InitData; InitData.pSysMem = verts; device->CreateBuffer(&bd, &InitData, &grid); @@ -6272,9 +5734,7 @@ void DrawDebugWorld( XMStoreFloat4x4(&sb.g_xTransform, camera.GetViewProjection()); sb.g_xColor = float4(1, 1, 1, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); const GPUBuffer* vbs[] = { &grid, @@ -6294,17 +5754,14 @@ void DrawDebugWorld( device->BindPipelineState(&PSO_debug[DEBUGRENDERING_VOXEL], cmd); - device->BindResource(VS, GetVoxelRadianceSecondaryBounceEnabled() ? &textures[TEXTYPE_3D_VOXELRADIANCE_HELPER] : &textures[TEXTYPE_3D_VOXELRADIANCE], TEXSLOT_VOXELRADIANCE, cmd); + device->BindResource(GetVoxelRadianceSecondaryBounceEnabled() ? &textures[TEXTYPE_3D_VOXELRADIANCE_HELPER] : &textures[TEXTYPE_3D_VOXELRADIANCE], TEXSLOT_VOXELGI, cmd); MiscCB sb; XMStoreFloat4x4(&sb.g_xTransform, XMMatrixTranslationFromVector(XMLoadFloat3(&voxelSceneData.center)) * camera.GetViewProjection()); sb.g_xColor = float4(1, 1, 1, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(GS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); device->Draw(voxelSceneData.res * voxelSceneData.res * voxelSceneData.res, 0, cmd); @@ -6325,9 +5782,8 @@ void DrawDebugWorld( XMStoreFloat4x4(&sb.g_xTransform, XMLoadFloat4x4(&transform.world)*camera.GetViewProjection()); sb.g_xColor = float4(0, 1, 0, 1); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); if (mesh == nullptr) { @@ -6377,56 +5833,10 @@ void DrawDebugWorld( const MeshComponent::MeshSubset& subset = mesh.subsets[x.subset]; const MaterialComponent& material = *scene.materials.GetComponent(subset.materialID); - GraphicsDevice::GPUAllocation mem = device->AllocateGPU(sizeof(Instance), cmd); - volatile Instance* buff = (volatile Instance*)mem.data; - buff->Create(transform.world); - - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS)) - { - ObjectPushConstants push; - push.material = device->GetDescriptorIndex(&material.constantBuffer, SRV); - push.mesh = device->GetDescriptorIndex(&mesh.descriptor, SRV); - push.instances = device->GetDescriptorIndex(mem.buffer, SRV); - push.instance_offset = mem.offset; - device->PushConstants(&push, sizeof(push), cmd); - } - else - { - const GPUBuffer* vbs[] = { - mesh.streamoutBuffer_POS.IsValid() ? &mesh.streamoutBuffer_POS : &mesh.vertexBuffer_POS, - nullptr, - &mesh.vertexBuffer_UV0, - &mesh.vertexBuffer_UV1, - nullptr, - nullptr, - nullptr, - mem.buffer - }; - uint32_t strides[] = { - sizeof(MeshComponent::Vertex_POS), - sizeof(MeshComponent::Vertex_POS), - sizeof(MeshComponent::Vertex_TEX), - sizeof(MeshComponent::Vertex_TEX), - sizeof(MeshComponent::Vertex_TEX), - sizeof(MeshComponent::Vertex_COL), - sizeof(MeshComponent::Vertex_TAN), - sizeof(Instance) - }; - uint32_t offsets[] = { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - mem.offset - }; - device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); - - device->BindConstantBuffer(VS, &material.constantBuffer, CB_GETBINDSLOT(MaterialCB), cmd); - device->BindConstantBuffer(PS, &material.constantBuffer, CB_GETBINDSLOT(MaterialCB), cmd); - } + GraphicsDevice::GPUAllocation mem = device->AllocateGPU(sizeof(ShaderMeshInstancePointer), cmd); + volatile ShaderMeshInstancePointer* buff = (volatile ShaderMeshInstancePointer*)mem.data; + buff->instanceID = (uint)scene.objects.GetIndex(x.objectEntity); + buff->userdata = 0; device->BindIndexBuffer(&mesh.indexBuffer, mesh.GetIndexFormat(), 0, cmd); @@ -6435,8 +5845,17 @@ void DrawDebugWorld( cb.xPaintRadCenter = x.center; cb.xPaintRadRadius = x.radius; cb.xPaintRadUVSET = x.uvset; - device->UpdateBuffer(&constantBuffers[CBTYPE_PAINTRADIUS], &cb, cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_PAINTRADIUS], CB_GETBINDSLOT(PaintRadiusCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PaintRadiusCB), cmd); + + ObjectPushConstants push; + push.init( + (uint)scene.meshes.GetIndex(object.meshID), + x.subset, + subset.materialIndex, + device->GetDescriptorIndex(&mem.buffer, SRV), + mem.offset + ); + device->PushConstants(&push, sizeof(push), cmd); device->DrawIndexedInstanced(subset.indexCount, 1, subset.indexOffset, 0, 0, cmd); } @@ -6458,9 +5877,8 @@ void DrawDebugWorld( XMStoreFloat4x4(&sb.g_xTransform, camera.GetViewProjection()); sb.g_xColor = XMFLOAT4(camera.Eye.x, camera.Eye.y, camera.Eye.z, (float)i); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); switch (force.type) { @@ -6506,7 +5924,6 @@ void DrawDebugWorld( bd.Usage = USAGE_DEFAULT; bd.ByteWidth = sizeof(verts); bd.BindFlags = BIND_VERTEX_BUFFER; - bd.CPUAccessFlags = 0; SubresourceData InitData; InitData.pSysMem = verts; device->CreateBuffer(&bd, &InitData, &wirecamVB); @@ -6521,7 +5938,6 @@ void DrawDebugWorld( bd.Usage = USAGE_DEFAULT; bd.ByteWidth = sizeof(indices); bd.BindFlags = BIND_INDEX_BUFFER; - bd.CPUAccessFlags = 0; InitData.pSysMem = indices; device->CreateBuffer(&bd, &InitData, &wirecamIB); } @@ -6548,9 +5964,7 @@ void DrawDebugWorld( const float aspect = cam.width / cam.height; XMStoreFloat4x4(&sb.g_xTransform, XMMatrixScaling(aspect * 0.5f, 0.5f, 0.5f) * cam.GetInvView()*camera.GetViewProjection()); - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &sb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); + device->BindDynamicConstantBuffer(sb, CB_GETBINDSLOT(MiscCB), cmd); device->DrawIndexed(32, 0, 0, cmd); } @@ -6577,17 +5991,17 @@ void RenderAtmosphericScatteringTextures(CommandList cmd) device->EventBegin("TransmittanceLut", cmd); device->BindComputeShader(&shaders[CSTYPE_SKYATMOSPHERE_TRANSMITTANCELUT], cmd); - device->BindResource(CS, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_ONDEMAND0, cmd); // empty - device->BindResource(CS, &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_ONDEMAND1, cmd); // empty + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_ONDEMAND0, cmd); // empty + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_ONDEMAND1, cmd); // empty const GPUResource* uavs[] = { &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS) + GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS) }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -6603,12 +6017,11 @@ void RenderAtmosphericScatteringTextures(CommandList cmd) { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], IMAGE_LAYOUT_UNORDERED_ACCESS, textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT].desc.layout) + GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], RESOURCE_STATE_UNORDERED_ACCESS, textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT].desc.layout) }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -6618,17 +6031,17 @@ void RenderAtmosphericScatteringTextures(CommandList cmd) device->BindComputeShader(&shaders[CSTYPE_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], cmd); // Use transmittance from previous pass - device->BindResource(CS, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_ONDEMAND1, cmd); const GPUResource* uavs[] = { &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS) + GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS) }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -6641,12 +6054,11 @@ void RenderAtmosphericScatteringTextures(CommandList cmd) { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], IMAGE_LAYOUT_UNORDERED_ACCESS, textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT].desc.layout) + GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], RESOURCE_STATE_UNORDERED_ACCESS, textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT].desc.layout) }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -6655,17 +6067,17 @@ void RenderAtmosphericScatteringTextures(CommandList cmd) device->EventBegin("EnvironmentLuminanceLut", cmd); device->BindComputeShader(&shaders[CSTYPE_SKYATMOSPHERE_SKYLUMINANCELUT], cmd); - device->BindResource(CS, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_ONDEMAND1, cmd); const GPUResource* uavs[] = { &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS) + GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS) }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -6678,12 +6090,11 @@ void RenderAtmosphericScatteringTextures(CommandList cmd) { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], IMAGE_LAYOUT_UNORDERED_ACCESS, textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT].desc.layout) + GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], RESOURCE_STATE_UNORDERED_ACCESS, textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT].desc.layout) }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -6702,17 +6113,17 @@ void RefreshAtmosphericScatteringTextures(CommandList cmd) device->EventBegin("SkyViewLut", cmd); device->BindComputeShader(&shaders[CSTYPE_SKYATMOSPHERE_SKYVIEWLUT], cmd); - device->BindResource(CS, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_ONDEMAND1, cmd); const GPUResource* uavs[] = { &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS) + GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS) }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -6728,12 +6139,11 @@ void RefreshAtmosphericScatteringTextures(CommandList cmd) { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], IMAGE_LAYOUT_UNORDERED_ACCESS, textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT].desc.layout) + GPUBarrier::Image(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], RESOURCE_STATE_UNORDERED_ACCESS, textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT].desc.layout) }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -6746,31 +6156,13 @@ void DrawSky(const Scene& scene, CommandList cmd) if (scene.weather.skyMap != nullptr) { device->BindPipelineState(&PSO_sky[SKYRENDERING_STATIC], cmd); - device->BindResource(PS, &scene.weather.skyMap->texture, TEXSLOT_GLOBALENVMAP, cmd); } else { device->BindPipelineState(&PSO_sky[SKYRENDERING_DYNAMIC], cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], TEXSLOT_SKYVIEWLUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_TRANSMITTANCELUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_MULTISCATTERINGLUT, cmd); } - BindConstantBuffers(VS, cmd); - BindConstantBuffers(PS, cmd); - - device->Draw(3, 0, cmd); - - device->EventEnd(cmd); -} -void DrawSkyVelocity(CommandList cmd) -{ - device->EventBegin("DrawSkyVelocity", cmd); - - device->BindPipelineState(&PSO_sky[SKYRENDERING_VELOCITY], cmd); - - BindConstantBuffers(VS, cmd); - BindConstantBuffers(PS, cmd); + BindCommonResources(cmd); device->Draw(3, 0, cmd); @@ -6782,12 +6174,7 @@ void DrawSun(CommandList cmd) device->BindPipelineState(&PSO_sky[SKYRENDERING_SUN], cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], TEXSLOT_SKYVIEWLUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_TRANSMITTANCELUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_MULTISCATTERINGLUT, cmd); - - BindConstantBuffers(VS, cmd); - BindConstantBuffers(PS, cmd); + BindCommonResources(cmd); device->Draw(3, 0, cmd); @@ -6814,6 +6201,7 @@ void RefreshEnvProbes(const Visibility& vis, CommandList cmd) auto render_probe = [&](const EnvironmentProbeComponent& probe, const AABB& probe_aabb) { + const SHCAM cameras[] = { SHCAM(probe.position, XMFLOAT4(0.5f, -0.5f, -0.5f, -0.5f), zNearP, zFarP, XM_PIDIV2), //+x SHCAM(probe.position, XMFLOAT4(0.5f, 0.5f, 0.5f, -0.5f), zNearP, zFarP, XM_PIDIV2), //-x @@ -6831,27 +6219,19 @@ void RefreshEnvProbes(const Visibility& vis, CommandList cmd) XMStoreFloat4x4(&cb.xCubemapRenderCams[i].VP, cameras[i].VP); cb.xCubemapRenderCams[i].properties = uint4(i, 0, 0, 0); } - - device->UpdateBuffer(&constantBuffers[CBTYPE_CUBEMAPRENDER], &cb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_CUBEMAPRENDER], CB_GETBINDSLOT(CubemapRenderCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(CubemapRenderCB), cmd); CameraCB camcb; - camcb.g_xCamera_CamPos = probe.position; // only this will be used by envprobe rendering shaders the rest is read from cubemaprenderCB - device->UpdateBuffer(&constantBuffers[CBTYPE_CAMERA], &camcb, cmd); + camcb.CamPos = probe.position; // only this will be used by envprobe rendering shaders the rest is read from cubemaprenderCB + device->BindDynamicConstantBuffer(camcb, CBSLOT_RENDERER_CAMERA, cmd); if (vis.scene->weather.IsRealisticSky()) { // Refresh atmospheric textures, since each probe has different positions RefreshAtmosphericScatteringTextures(cmd); + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], TEXSLOT_SKYLUMINANCELUT, cmd); } - // Bind the atmospheric textures, as lighting and sky needs them - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], TEXSLOT_SKYVIEWLUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_TRANSMITTANCELUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_MULTISCATTERINGLUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], TEXSLOT_SKYLUMINANCELUT, cmd); - - device->RenderPassBegin(&vis.scene->renderpasses_envmap[probe.textureIndex], cmd); // Scene will only be rendered if this is a real probe entity: @@ -6878,9 +6258,6 @@ void RefreshEnvProbes(const Visibility& vis, CommandList cmd) if (!renderQueue.empty()) { - BindShadowmaps(PS, cmd); - device->BindResource(PS, &vis.scene->lightmap, TEXSLOT_GLOBALLIGHTMAP, cmd); - RenderMeshes(vis, renderQueue, RENDERPASS_ENVMAPCAPTURE, RENDERTYPE_ALL, cmd, false, frusta, arraysize(frusta)); GetRenderFrameAllocator(cmd).free(sizeof(RenderBatch) * renderQueue.batchCount); @@ -6892,7 +6269,7 @@ void RefreshEnvProbes(const Visibility& vis, CommandList cmd) if (vis.scene->weather.skyMap != nullptr) { device->BindPipelineState(&PSO_sky[SKYRENDERING_ENVMAPCAPTURE_STATIC], cmd); - device->BindResource(PS, &vis.scene->weather.skyMap->texture, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&vis.scene->weather.skyMap->texture, TEXSLOT_ONDEMAND0, cmd); } else { @@ -6924,18 +6301,18 @@ void RefreshEnvProbes(const Visibility& vis, CommandList cmd) { { GPUBarrier barriers[] = { - GPUBarrier::Image(&vis.scene->envmapArray, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_UNORDERED_ACCESS, i, arrayIndex * 6 + 0), - GPUBarrier::Image(&vis.scene->envmapArray, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_UNORDERED_ACCESS, i, arrayIndex * 6 + 1), - GPUBarrier::Image(&vis.scene->envmapArray, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_UNORDERED_ACCESS, i, arrayIndex * 6 + 2), - GPUBarrier::Image(&vis.scene->envmapArray, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_UNORDERED_ACCESS, i, arrayIndex * 6 + 3), - GPUBarrier::Image(&vis.scene->envmapArray, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_UNORDERED_ACCESS, i, arrayIndex * 6 + 4), - GPUBarrier::Image(&vis.scene->envmapArray, IMAGE_LAYOUT_SHADER_RESOURCE, IMAGE_LAYOUT_UNORDERED_ACCESS, i, arrayIndex * 6 + 5), + GPUBarrier::Image(&vis.scene->envmapArray, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS, i, arrayIndex * 6 + 0), + GPUBarrier::Image(&vis.scene->envmapArray, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS, i, arrayIndex * 6 + 1), + GPUBarrier::Image(&vis.scene->envmapArray, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS, i, arrayIndex * 6 + 2), + GPUBarrier::Image(&vis.scene->envmapArray, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS, i, arrayIndex * 6 + 3), + GPUBarrier::Image(&vis.scene->envmapArray, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS, i, arrayIndex * 6 + 4), + GPUBarrier::Image(&vis.scene->envmapArray, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS, i, arrayIndex * 6 + 5), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->BindUAV(CS, &vis.scene->envmapArray, 0, cmd, i); - device->BindResource(CS, &vis.scene->envmapArray, TEXSLOT_ONDEMAND0, cmd, std::max(0, (int)i - 2)); + device->BindUAV(&vis.scene->envmapArray, 0, cmd, i); + device->BindResource(&vis.scene->envmapArray, TEXSLOT_ONDEMAND0, cmd, std::max(0, (int)i - 2)); FilterEnvmapCB cb; cb.filterResolution.x = desc.Width; @@ -6945,8 +6322,7 @@ void RefreshEnvProbes(const Visibility& vis, CommandList cmd) cb.filterArrayIndex = arrayIndex; cb.filterRoughness = (float)i / (float)desc.MipLevels; cb.filterRayCount = 128; - device->UpdateBuffer(&constantBuffers[CBTYPE_FILTERENVMAP], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_FILTERENVMAP], CB_GETBINDSLOT(FilterEnvmapCB), cmd); + device->PushConstants(&cb, sizeof(cb), cmd); device->Dispatch( std::max(1u, (uint32_t)ceilf((float)desc.Width / GENERATEMIPCHAIN_2D_BLOCK_SIZE)), @@ -6957,12 +6333,12 @@ void RefreshEnvProbes(const Visibility& vis, CommandList cmd) { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&vis.scene->envmapArray, IMAGE_LAYOUT_UNORDERED_ACCESS, IMAGE_LAYOUT_SHADER_RESOURCE, i, arrayIndex * 6 + 0), - GPUBarrier::Image(&vis.scene->envmapArray, IMAGE_LAYOUT_UNORDERED_ACCESS, IMAGE_LAYOUT_SHADER_RESOURCE, i, arrayIndex * 6 + 1), - GPUBarrier::Image(&vis.scene->envmapArray, IMAGE_LAYOUT_UNORDERED_ACCESS, IMAGE_LAYOUT_SHADER_RESOURCE, i, arrayIndex * 6 + 2), - GPUBarrier::Image(&vis.scene->envmapArray, IMAGE_LAYOUT_UNORDERED_ACCESS, IMAGE_LAYOUT_SHADER_RESOURCE, i, arrayIndex * 6 + 3), - GPUBarrier::Image(&vis.scene->envmapArray, IMAGE_LAYOUT_UNORDERED_ACCESS, IMAGE_LAYOUT_SHADER_RESOURCE, i, arrayIndex * 6 + 4), - GPUBarrier::Image(&vis.scene->envmapArray, IMAGE_LAYOUT_UNORDERED_ACCESS, IMAGE_LAYOUT_SHADER_RESOURCE, i, arrayIndex * 6 + 5), + GPUBarrier::Image(&vis.scene->envmapArray, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE, i, arrayIndex * 6 + 0), + GPUBarrier::Image(&vis.scene->envmapArray, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE, i, arrayIndex * 6 + 1), + GPUBarrier::Image(&vis.scene->envmapArray, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE, i, arrayIndex * 6 + 2), + GPUBarrier::Image(&vis.scene->envmapArray, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE, i, arrayIndex * 6 + 3), + GPUBarrier::Image(&vis.scene->envmapArray, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE, i, arrayIndex * 6 + 4), + GPUBarrier::Image(&vis.scene->envmapArray, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE, i, arrayIndex * 6 + 5), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -6970,7 +6346,6 @@ void RefreshEnvProbes(const Visibility& vis, CommandList cmd) desc.Width *= 2; desc.Height *= 2; } - device->UnbindUAVs(0, 1, cmd); } device->EventEnd(cmd); }; @@ -7014,18 +6389,6 @@ void RefreshImpostors(const Scene& scene, CommandList cmd) BindCommonResources(cmd); - struct InstBuf - { - Instance instance; - InstancePrev instancePrev; - InstanceAtlas instanceAtlas; - }; - GraphicsDevice::GPUAllocation mem = device->AllocateGPU(sizeof(InstBuf), cmd); - volatile InstBuf* buff = (volatile InstBuf*)mem.data; - buff->instance.Create(IDENTITYMATRIX); - buff->instancePrev.Create(IDENTITYMATRIX); - buff->instanceAtlas.Create(XMFLOAT4(1, 1, 0, 0)); - for (uint32_t impostorIndex = 0; impostorIndex < scene.impostors.GetCount(); ++impostorIndex) { const ImpostorComponent& impostor = scene.impostors[impostorIndex]; @@ -7039,50 +6402,6 @@ void RefreshImpostors(const Scene& scene, CommandList cmd) // impostor camera will fit around mesh bounding sphere: const SPHERE boundingsphere = mesh.GetBoundingSphere(); - ObjectPushConstants push; // used with bindless model only - - const bool bindless = device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS); - if (bindless) - { - push.mesh = device->GetDescriptorIndex(&mesh.descriptor, SRV); - push.instances = device->GetDescriptorIndex(mem.buffer, SRV); - push.instance_offset = mem.offset; - } - else - { - const GPUBuffer* vbs[] = { - mesh.streamoutBuffer_POS.IsValid() ? &mesh.streamoutBuffer_POS : &mesh.vertexBuffer_POS, - mesh.vertexBuffer_PRE.IsValid() ? &mesh.vertexBuffer_PRE : &mesh.vertexBuffer_POS, - &mesh.vertexBuffer_UV0, - &mesh.vertexBuffer_UV1, - &mesh.vertexBuffer_ATL, - &mesh.vertexBuffer_COL, - mesh.streamoutBuffer_TAN.IsValid() ? &mesh.streamoutBuffer_TAN : &mesh.vertexBuffer_TAN, - mem.buffer - }; - uint32_t strides[] = { - sizeof(MeshComponent::Vertex_POS), - sizeof(MeshComponent::Vertex_POS), - sizeof(MeshComponent::Vertex_TEX), - sizeof(MeshComponent::Vertex_TEX), - sizeof(MeshComponent::Vertex_TEX), - sizeof(MeshComponent::Vertex_COL), - sizeof(MeshComponent::Vertex_TAN), - sizeof(InstBuf) - }; - uint32_t offsets[] = { - 0, - 0, - 0, - 0, - 0, - 0, - 0, - mem.offset - }; - device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); - } - device->BindIndexBuffer(&mesh.indexBuffer, mesh.GetIndexFormat(), 0, cmd); for (int prop = 0; prop < 3; ++prop) @@ -7129,28 +6448,23 @@ void RefreshImpostors(const Scene& scene, CommandList cmd) viewport.Width = (float)scene.impostorTextureDim; device->BindViewports(1, &viewport, cmd); - for (auto& subset : mesh.subsets) + for (size_t subsetIndex = 0; subsetIndex < mesh.subsets.size(); ++subsetIndex) { + const MeshComponent::MeshSubset& subset = mesh.subsets[subsetIndex]; if (subset.indexCount == 0) { continue; } const MaterialComponent& material = *scene.materials.GetComponent(subset.materialID); - if (bindless) - { - push.material = device->GetDescriptorIndex(&material.constantBuffer, SRV); - device->PushConstants(&push, sizeof(push), cmd); - } - else - { - device->BindConstantBuffer(VS, &material.constantBuffer, CB_GETBINDSLOT(MaterialCB), cmd); - device->BindConstantBuffer(PS, &material.constantBuffer, CB_GETBINDSLOT(MaterialCB), cmd); - - const GPUResource* res[4]; - material.WriteTextures(res, arraysize(res)); - device->BindResources(PS, res, TEXSLOT_ONDEMAND0, arraysize(res), cmd); - } + ObjectPushConstants push; + push.init( + (uint)scene.meshes.GetIndex(entity), + (uint)subsetIndex, + subset.materialIndex, + -1, 0 + ); + device->PushConstants(&push, sizeof(push), cmd); device->DrawIndexedInstanced(subset.indexCount, 1, subset.indexOffset, 0, 0, cmd); } @@ -7216,10 +6530,10 @@ void VoxelRadiance(const Visibility& vis, CommandList cmd) device->BindViewports(1, &vp, cmd); GPUResource* UAVs[] = { &resourceBuffers[RBTYPE_VOXELSCENE] }; - device->BindUAVs(PS, UAVs, 0, 1, cmd); + device->BindUAVs(UAVs, 0, 1, cmd); BindCommonResources(cmd); - BindShadowmaps(PS, cmd); + device->RenderPassBegin(&renderpass_voxelize, cmd); RenderMeshes(vis, renderQueue, RENDERPASS_VOXELIZE, RENDERTYPE_OPAQUE, cmd, false, nullptr, 1); @@ -7236,8 +6550,8 @@ void VoxelRadiance(const Visibility& vis, CommandList cmd) // Copy the packed voxel scene data to a 3D texture, then delete the voxel scene emission data. The cone tracing will operate on the 3D texture device->EventBegin("Voxel Scene Copy - Clear", cmd); - device->BindUAV(CS, &resourceBuffers[RBTYPE_VOXELSCENE], 0, cmd); - device->BindUAV(CS, &textures[TEXTYPE_3D_VOXELRADIANCE], 1, cmd); + device->BindUAV(&resourceBuffers[RBTYPE_VOXELSCENE], 0, cmd); + device->BindUAV(&textures[TEXTYPE_3D_VOXELRADIANCE], 1, cmd); static bool smooth_copy = true; if (smooth_copy) @@ -7261,13 +6575,12 @@ void VoxelRadiance(const Visibility& vis, CommandList cmd) if (voxelSceneData.secondaryBounceEnabled) { device->EventBegin("Voxel Radiance Secondary Bounce", cmd); - device->UnbindUAVs(1, 1, cmd); // Pre-integrate the voxel texture by creating blurred mip levels: GenerateMipChain(textures[TEXTYPE_3D_VOXELRADIANCE], MIPGENFILTER_LINEAR, cmd); - device->BindResource(CS, &textures[TEXTYPE_3D_VOXELRADIANCE], 0, cmd); - device->BindResource(CS, &resourceBuffers[RBTYPE_VOXELSCENE], 1, cmd); - device->BindUAV(CS, &textures[TEXTYPE_3D_VOXELRADIANCE_HELPER], 0, cmd); + device->BindResource(&textures[TEXTYPE_3D_VOXELRADIANCE], 0, cmd); + device->BindResource(&resourceBuffers[RBTYPE_VOXELSCENE], 1, cmd); + device->BindUAV(&textures[TEXTYPE_3D_VOXELRADIANCE_HELPER], 0, cmd); device->BindComputeShader(&shaders[CSTYPE_VOXELRADIANCESECONDARYBOUNCE], cmd); device->Dispatch(voxelSceneData.res / 8, voxelSceneData.res / 8, voxelSceneData.res / 8, cmd); device->EventEnd(cmd); @@ -7280,8 +6593,7 @@ void VoxelRadiance(const Visibility& vis, CommandList cmd) } device->EventBegin("Voxel Scene Clear Normals", cmd); - device->UnbindResources(1, 1, cmd); - device->BindUAV(CS, &resourceBuffers[RBTYPE_VOXELSCENE], 0, cmd); + device->BindUAV(&resourceBuffers[RBTYPE_VOXELSCENE], 0, cmd); device->BindComputeShader(&shaders[CSTYPE_VOXELCLEARONLYNORMAL], cmd); device->Dispatch((uint32_t)(voxelSceneData.res * voxelSceneData.res * voxelSceneData.res / 256), 1, 1, cmd); device->EventEnd(cmd); @@ -7296,7 +6608,6 @@ void VoxelRadiance(const Visibility& vis, CommandList cmd) result = &textures[TEXTYPE_3D_VOXELRADIANCE_HELPER]; } - device->UnbindUAVs(0, 2, cmd); // Pre-integrate the voxel texture by creating blurred mip levels: @@ -7321,7 +6632,6 @@ void CreateTiledLightResources(TiledLightResources& res, XMUINT2 resolution) bd.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; bd.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; bd.Usage = USAGE_DEFAULT; - bd.CPUAccessFlags = 0; device->CreateBuffer(&bd, nullptr, &res.tileFrustums); device->SetName(&res.tileFrustums, "tileFrustums"); @@ -7332,7 +6642,6 @@ void CreateTiledLightResources(TiledLightResources& res, XMUINT2 resolution) bd.ByteWidth = tileCount.x * tileCount.y * bd.StructureByteStride * SHADER_ENTITY_TILE_BUCKET_COUNT; bd.Usage = USAGE_DEFAULT; bd.BindFlags = BIND_UNORDERED_ACCESS | BIND_SHADER_RESOURCE; - bd.CPUAccessFlags = 0; bd.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; device->CreateBuffer(&bd, nullptr, &res.entityTiles_Opaque); device->CreateBuffer(&bd, nullptr, &res.entityTiles_Transparent); @@ -7352,7 +6661,7 @@ void ComputeTiledLightCulling( BindCommonResources(cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); // Frustum computation { @@ -7362,12 +6671,12 @@ void ComputeTiledLightCulling( const GPUResource* uavs[] = { &res.tileFrustums }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { GPUBarrier::Memory(&res.tileFrustums), - GPUBarrier::Buffer(&res.tileFrustums, BUFFER_STATE_SHADER_RESOURCE, BUFFER_STATE_UNORDERED_ACCESS) + GPUBarrier::Buffer(&res.tileFrustums, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS) }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -7378,7 +6687,6 @@ void ComputeTiledLightCulling( 1, cmd ); - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -7387,12 +6695,12 @@ void ComputeTiledLightCulling( { device->EventBegin("Entity Culling", cmd); - device->BindResource(CS, &res.tileFrustums, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.tileFrustums, TEXSLOT_ONDEMAND0, cmd); if (GetDebugLightCulling() && debugUAV.IsValid()) { device->BindComputeShader(&shaders[GetAdvancedLightCulling() ? CSTYPE_LIGHTCULLING_ADVANCED_DEBUG : CSTYPE_LIGHTCULLING_DEBUG], cmd); - device->BindUAV(CS, &debugUAV, 3, cmd); + device->BindUAV(&debugUAV, 3, cmd); } else { @@ -7403,14 +6711,14 @@ void ComputeTiledLightCulling( &res.entityTiles_Transparent, &res.entityTiles_Opaque, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { GPUBarrier::Memory(&res.tileFrustums), - GPUBarrier::Buffer(&res.tileFrustums, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), - GPUBarrier::Buffer(&res.entityTiles_Transparent, BUFFER_STATE_SHADER_RESOURCE, BUFFER_STATE_UNORDERED_ACCESS), - GPUBarrier::Buffer(&res.entityTiles_Opaque, BUFFER_STATE_SHADER_RESOURCE, BUFFER_STATE_UNORDERED_ACCESS), + GPUBarrier::Buffer(&res.tileFrustums, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&res.entityTiles_Transparent, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Buffer(&res.entityTiles_Opaque, RESOURCE_STATE_SHADER_RESOURCE, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -7421,13 +6729,12 @@ void ComputeTiledLightCulling( GPUBarrier barriers[] = { GPUBarrier::Memory(&res.entityTiles_Opaque), GPUBarrier::Memory(&res.entityTiles_Transparent), - GPUBarrier::Buffer(&res.entityTiles_Opaque, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), - GPUBarrier::Buffer(&res.entityTiles_Transparent, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&res.entityTiles_Opaque, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&res.entityTiles_Transparent, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -7438,8 +6745,8 @@ void ResolveMSAADepthBuffer(const Texture& dst, const Texture& src, CommandList { device->EventBegin("ResolveMSAADepthBuffer", cmd); - device->BindResource(CS, &src, TEXSLOT_ONDEMAND0, cmd); - device->BindUAV(CS, &dst, 0, cmd); + device->BindResource(&src, TEXSLOT_ONDEMAND0, cmd); + device->BindUAV(&dst, 0, cmd); const TextureDesc& desc = src.GetDesc(); @@ -7447,8 +6754,6 @@ void ResolveMSAADepthBuffer(const Texture& dst, const Texture& src, CommandList device->Dispatch((desc.Width + 7) / 8, (desc.Height + 7) / 8, 1, cmd); - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); - device->UnbindUAVs(0, 1, cmd); device->EventEnd(cmd); } @@ -7458,11 +6763,10 @@ void DownsampleDepthBuffer(const wiGraphics::Texture& src, wiGraphics::CommandLi device->BindPipelineState(&PSO_downsampledepthbuffer, cmd); - device->BindResource(PS, &src, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&src, TEXSLOT_ONDEMAND0, cmd); device->Draw(3, 0, cmd); - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); device->EventEnd(cmd); } @@ -7500,12 +6804,12 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c case MIPGENFILTER_POINT: device->EventBegin("GenerateMipChain CubeArray - PointFilter", cmd); device->BindComputeShader(&shaders[hdr ? CSTYPE_GENERATEMIPCHAINCUBEARRAY_FLOAT4 : CSTYPE_GENERATEMIPCHAINCUBEARRAY_UNORM4], cmd); - device->BindSampler(CS, &samplers[SSLOT_POINT_CLAMP], SSLOT_ONDEMAND0, cmd); + device->BindSampler(&samplers[SSLOT_POINT_CLAMP], SSLOT_ONDEMAND0, cmd); break; case MIPGENFILTER_LINEAR: device->EventBegin("GenerateMipChain CubeArray - LinearFilter", cmd); device->BindComputeShader(&shaders[hdr ? CSTYPE_GENERATEMIPCHAINCUBEARRAY_FLOAT4 : CSTYPE_GENERATEMIPCHAINCUBEARRAY_UNORM4], cmd); - device->BindSampler(CS, &samplers[SSLOT_LINEAR_CLAMP], SSLOT_ONDEMAND0, cmd); + device->BindSampler(&samplers[SSLOT_LINEAR_CLAMP], SSLOT_ONDEMAND0, cmd); break; default: assert(0); @@ -7516,18 +6820,18 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c { { GPUBarrier barriers[] = { - GPUBarrier::Image(&texture, texture.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS, i + 1, options.arrayIndex * 6 + 0), - GPUBarrier::Image(&texture, texture.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS, i + 1, options.arrayIndex * 6 + 1), - GPUBarrier::Image(&texture, texture.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS, i + 1, options.arrayIndex * 6 + 2), - GPUBarrier::Image(&texture, texture.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS, i + 1, options.arrayIndex * 6 + 3), - GPUBarrier::Image(&texture, texture.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS, i + 1, options.arrayIndex * 6 + 4), - GPUBarrier::Image(&texture, texture.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS, i + 1, options.arrayIndex * 6 + 5), + GPUBarrier::Image(&texture, texture.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS, i + 1, options.arrayIndex * 6 + 0), + GPUBarrier::Image(&texture, texture.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS, i + 1, options.arrayIndex * 6 + 1), + GPUBarrier::Image(&texture, texture.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS, i + 1, options.arrayIndex * 6 + 2), + GPUBarrier::Image(&texture, texture.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS, i + 1, options.arrayIndex * 6 + 3), + GPUBarrier::Image(&texture, texture.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS, i + 1, options.arrayIndex * 6 + 4), + GPUBarrier::Image(&texture, texture.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS, i + 1, options.arrayIndex * 6 + 5), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->BindUAV(CS, &texture, 0, cmd, i + 1); - device->BindResource(CS, &texture, TEXSLOT_ONDEMAND0, cmd, i); + device->BindUAV(&texture, 0, cmd, i + 1); + device->BindResource(&texture, TEXSLOT_ONDEMAND0, cmd, i); desc.Width = std::max(1u, desc.Width / 2); desc.Height = std::max(1u, desc.Height / 2); @@ -7538,8 +6842,7 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c cb.outputResolution_rcp.y = 1.0f / cb.outputResolution.y; cb.arrayIndex = options.arrayIndex; cb.mipgen_options = 0; - device->UpdateBuffer(&constantBuffers[CBTYPE_MIPGEN], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_MIPGEN], CB_GETBINDSLOT(GenerateMIPChainCB), cmd); + device->PushConstants(&cb, sizeof(cb), cmd); device->Dispatch( std::max(1u, (desc.Width + GENERATEMIPCHAIN_2D_BLOCK_SIZE - 1) / GENERATEMIPCHAIN_2D_BLOCK_SIZE), @@ -7550,12 +6853,12 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&texture, IMAGE_LAYOUT_UNORDERED_ACCESS, texture.desc.layout, i + 1, options.arrayIndex * 6 + 0), - GPUBarrier::Image(&texture, IMAGE_LAYOUT_UNORDERED_ACCESS, texture.desc.layout, i + 1, options.arrayIndex * 6 + 1), - GPUBarrier::Image(&texture, IMAGE_LAYOUT_UNORDERED_ACCESS, texture.desc.layout, i + 1, options.arrayIndex * 6 + 2), - GPUBarrier::Image(&texture, IMAGE_LAYOUT_UNORDERED_ACCESS, texture.desc.layout, i + 1, options.arrayIndex * 6 + 3), - GPUBarrier::Image(&texture, IMAGE_LAYOUT_UNORDERED_ACCESS, texture.desc.layout, i + 1, options.arrayIndex * 6 + 4), - GPUBarrier::Image(&texture, IMAGE_LAYOUT_UNORDERED_ACCESS, texture.desc.layout, i + 1, options.arrayIndex * 6 + 5), + GPUBarrier::Image(&texture, RESOURCE_STATE_UNORDERED_ACCESS, texture.desc.layout, i + 1, options.arrayIndex * 6 + 0), + GPUBarrier::Image(&texture, RESOURCE_STATE_UNORDERED_ACCESS, texture.desc.layout, i + 1, options.arrayIndex * 6 + 1), + GPUBarrier::Image(&texture, RESOURCE_STATE_UNORDERED_ACCESS, texture.desc.layout, i + 1, options.arrayIndex * 6 + 2), + GPUBarrier::Image(&texture, RESOURCE_STATE_UNORDERED_ACCESS, texture.desc.layout, i + 1, options.arrayIndex * 6 + 3), + GPUBarrier::Image(&texture, RESOURCE_STATE_UNORDERED_ACCESS, texture.desc.layout, i + 1, options.arrayIndex * 6 + 4), + GPUBarrier::Image(&texture, RESOURCE_STATE_UNORDERED_ACCESS, texture.desc.layout, i + 1, options.arrayIndex * 6 + 5), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -7569,12 +6872,12 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c case MIPGENFILTER_POINT: device->EventBegin("GenerateMipChain Cube - PointFilter", cmd); device->BindComputeShader(&shaders[hdr ? CSTYPE_GENERATEMIPCHAINCUBE_FLOAT4 : CSTYPE_GENERATEMIPCHAINCUBE_UNORM4], cmd); - device->BindSampler(CS, &samplers[SSLOT_POINT_CLAMP], SSLOT_ONDEMAND0, cmd); + device->BindSampler(&samplers[SSLOT_POINT_CLAMP], SSLOT_ONDEMAND0, cmd); break; case MIPGENFILTER_LINEAR: device->EventBegin("GenerateMipChain Cube - LinearFilter", cmd); device->BindComputeShader(&shaders[hdr ? CSTYPE_GENERATEMIPCHAINCUBE_FLOAT4 : CSTYPE_GENERATEMIPCHAINCUBE_UNORM4], cmd); - device->BindSampler(CS, &samplers[SSLOT_LINEAR_CLAMP], SSLOT_ONDEMAND0, cmd); + device->BindSampler(&samplers[SSLOT_LINEAR_CLAMP], SSLOT_ONDEMAND0, cmd); break; default: assert(0); // not implemented @@ -7583,8 +6886,8 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c for (uint32_t i = 0; i < desc.MipLevels - 1; ++i) { - device->BindUAV(CS, &texture, 0, cmd, i + 1); - device->BindResource(CS, &texture, TEXSLOT_ONDEMAND0, cmd, i); + device->BindUAV(&texture, 0, cmd, i + 1); + device->BindResource(&texture, TEXSLOT_ONDEMAND0, cmd, i); desc.Width = std::max(1u, desc.Width / 2); desc.Height = std::max(1u, desc.Height / 2); @@ -7595,8 +6898,7 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c cb.outputResolution_rcp.y = 1.0f / cb.outputResolution.y; cb.arrayIndex = 0; cb.mipgen_options = 0; - device->UpdateBuffer(&constantBuffers[CBTYPE_MIPGEN], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_MIPGEN], CB_GETBINDSLOT(GenerateMIPChainCB), cmd); + device->PushConstants(&cb, sizeof(cb), cmd); device->Dispatch( std::max(1u, (desc.Width + GENERATEMIPCHAIN_2D_BLOCK_SIZE - 1) / GENERATEMIPCHAIN_2D_BLOCK_SIZE), @@ -7620,12 +6922,12 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c case MIPGENFILTER_POINT: device->EventBegin("GenerateMipChain 2D - PointFilter", cmd); device->BindComputeShader(&shaders[hdr ? CSTYPE_GENERATEMIPCHAIN2D_FLOAT4 : CSTYPE_GENERATEMIPCHAIN2D_UNORM4], cmd); - device->BindSampler(CS, &samplers[SSLOT_POINT_CLAMP], SSLOT_ONDEMAND0, cmd); + device->BindSampler(&samplers[SSLOT_POINT_CLAMP], SSLOT_ONDEMAND0, cmd); break; case MIPGENFILTER_LINEAR: device->EventBegin("GenerateMipChain 2D - LinearFilter", cmd); device->BindComputeShader(&shaders[hdr ? CSTYPE_GENERATEMIPCHAIN2D_FLOAT4 : CSTYPE_GENERATEMIPCHAIN2D_UNORM4], cmd); - device->BindSampler(CS, &samplers[SSLOT_LINEAR_CLAMP], SSLOT_ONDEMAND0, cmd); + device->BindSampler(&samplers[SSLOT_LINEAR_CLAMP], SSLOT_ONDEMAND0, cmd); break; case MIPGENFILTER_GAUSSIAN: { @@ -7649,13 +6951,13 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c { { GPUBarrier barriers[] = { - GPUBarrier::Image(&texture,texture.desc.layout,IMAGE_LAYOUT_UNORDERED_ACCESS,i + 1), + GPUBarrier::Image(&texture,texture.desc.layout,RESOURCE_STATE_UNORDERED_ACCESS,i + 1), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->BindUAV(CS, &texture, 0, cmd, i + 1); - device->BindResource(CS, &texture, TEXSLOT_ONDEMAND0, cmd, i); + device->BindUAV(&texture, 0, cmd, i + 1); + device->BindResource(&texture, TEXSLOT_ONDEMAND0, cmd, i); desc.Width = std::max(1u, desc.Width / 2); desc.Height = std::max(1u, desc.Height / 2); @@ -7670,8 +6972,7 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c { cb.mipgen_options |= MIPGEN_OPTION_BIT_PRESERVE_COVERAGE; } - device->UpdateBuffer(&constantBuffers[CBTYPE_MIPGEN], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_MIPGEN], CB_GETBINDSLOT(GenerateMIPChainCB), cmd); + device->PushConstants(&cb, sizeof(cb), cmd); device->Dispatch( std::max(1u, (desc.Width + GENERATEMIPCHAIN_2D_BLOCK_SIZE - 1) / GENERATEMIPCHAIN_2D_BLOCK_SIZE), @@ -7682,15 +6983,13 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&texture,IMAGE_LAYOUT_UNORDERED_ACCESS,texture.desc.layout,i + 1), + GPUBarrier::Image(&texture,RESOURCE_STATE_UNORDERED_ACCESS,texture.desc.layout,i + 1), }; device->Barrier(barriers, arraysize(barriers), cmd); } } } - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); - device->UnbindUAVs(0, 1, cmd); device->EventEnd(cmd); } @@ -7701,12 +7000,12 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c case MIPGENFILTER_POINT: device->EventBegin("GenerateMipChain 3D - PointFilter", cmd); device->BindComputeShader(&shaders[hdr ? CSTYPE_GENERATEMIPCHAIN3D_FLOAT4 : CSTYPE_GENERATEMIPCHAIN3D_UNORM4], cmd); - device->BindSampler(CS, &samplers[SSLOT_POINT_CLAMP], SSLOT_ONDEMAND0, cmd); + device->BindSampler(&samplers[SSLOT_POINT_CLAMP], SSLOT_ONDEMAND0, cmd); break; case MIPGENFILTER_LINEAR: device->EventBegin("GenerateMipChain 3D - LinearFilter", cmd); device->BindComputeShader(&shaders[hdr ? CSTYPE_GENERATEMIPCHAIN3D_FLOAT4 : CSTYPE_GENERATEMIPCHAIN3D_UNORM4], cmd); - device->BindSampler(CS, &samplers[SSLOT_LINEAR_CLAMP], SSLOT_ONDEMAND0, cmd); + device->BindSampler(&samplers[SSLOT_LINEAR_CLAMP], SSLOT_ONDEMAND0, cmd); break; default: assert(0); // not implemented @@ -7715,8 +7014,8 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c for (uint32_t i = 0; i < desc.MipLevels - 1; ++i) { - device->BindUAV(CS, &texture, 0, cmd, i + 1); - device->BindResource(CS, &texture, TEXSLOT_ONDEMAND0, cmd, i); + device->BindUAV(&texture, 0, cmd, i + 1); + device->BindResource(&texture, TEXSLOT_ONDEMAND0, cmd, i); desc.Width = std::max(1u, desc.Width / 2); desc.Height = std::max(1u, desc.Height / 2); desc.Depth = std::max(1u, desc.Depth / 2); @@ -7730,8 +7029,7 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c cb.outputResolution_rcp.z = 1.0f / cb.outputResolution.z; cb.arrayIndex = options.arrayIndex >= 0 ? (uint)options.arrayIndex : 0; cb.mipgen_options = 0; - device->UpdateBuffer(&constantBuffers[CBTYPE_MIPGEN], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_MIPGEN], CB_GETBINDSLOT(GenerateMIPChainCB), cmd); + device->PushConstants(&cb, sizeof(cb), cmd); device->Dispatch( std::max(1u, (desc.Width + GENERATEMIPCHAIN_3D_BLOCK_SIZE - 1) / GENERATEMIPCHAIN_3D_BLOCK_SIZE), @@ -7745,8 +7043,6 @@ void GenerateMipChain(const Texture& texture, MIPGENFILTER filter, CommandList c device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindResources(TEXSLOT_ONDEMAND0, 1, cmd); - device->UnbindUAVs(0, 1, cmd); device->EventEnd(cmd); } @@ -7800,29 +7096,26 @@ void CopyTexture2D(const Texture& dst, int DstMIP, int DstX, int DstY, const Tex cb.xCopySrcSize.y = desc_src.Height >> SrcMIP; cb.xCopySrcMIP = SrcMIP; cb.xCopyBorderExpandStyle = (uint)borderExpand; - device->UpdateBuffer(&constantBuffers[CBTYPE_COPYTEXTURE], &cb, cmd); + device->PushConstants(&cb, sizeof(cb), cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_COPYTEXTURE], CB_GETBINDSLOT(CopyTextureCB), cmd); + device->BindResource(&src, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &src, TEXSLOT_ONDEMAND0, cmd); - - device->BindUAV(CS, &dst, 0, cmd, DstMIP); + device->BindUAV(&dst, 0, cmd, DstMIP); { GPUBarrier barriers[] = { - GPUBarrier::Image(&dst,dst.desc.layout,IMAGE_LAYOUT_UNORDERED_ACCESS, DstMIP), + GPUBarrier::Image(&dst,dst.desc.layout,RESOURCE_STATE_UNORDERED_ACCESS, DstMIP), }; device->Barrier(barriers, arraysize(barriers), cmd); } device->Dispatch((cb.xCopySrcSize.x + 7) / 8, (cb.xCopySrcSize.y + 7) / 8, 1, cmd); - device->UnbindUAVs(0, 1, cmd); { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&dst,IMAGE_LAYOUT_UNORDERED_ACCESS,dst.desc.layout, DstMIP), + GPUBarrier::Image(&dst,RESOURCE_STATE_UNORDERED_ACCESS,dst.desc.layout, DstMIP), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -7841,17 +7134,17 @@ void RayTraceScene( ) { // Set up tracing resources: - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { if (!scene.TLAS.IsValid()) { return; } - device->BindResource(CS, &scene.TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); + device->BindResource(&scene.TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); } else { - scene.BVH.Bind(CS, cmd); + scene.BVH.Bind(cmd); } device->EventBegin("RayTraceScene", cmd); @@ -7859,16 +7152,8 @@ void RayTraceScene( const TextureDesc& desc = output.GetDesc(); - if (scene.weather.skyMap != nullptr) - { - device->BindResource(CS, &scene.weather.skyMap->texture, TEXSLOT_GLOBALENVMAP, cmd); - } - else - { - device->BindResource(CS, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], TEXSLOT_SKYVIEWLUT, cmd); - device->BindResource(CS, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_TRANSMITTANCELUT, cmd); - device->BindResource(CS, &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_MULTISCATTERINGLUT, cmd); - } + BindCommonResources(cmd); + const XMFLOAT4& halton = wiMath::GetHaltonSequence(accumulation_sample); RaytracingCB cb; @@ -7880,30 +7165,29 @@ void RayTraceScene( cb.xTraceResolution_rcp.y = 1.0f / cb.xTraceResolution.y; cb.xTraceUserData.x = raytraceBounceCount; cb.xTraceSampleIndex = (uint32_t)accumulation_sample; - device->UpdateBuffer(&constantBuffers[CBTYPE_RAYTRACE], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_RAYTRACE], CB_GETBINDSLOT(RaytracingCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(RaytracingCB), cmd); device->BindComputeShader(&shaders[CSTYPE_RAYTRACE], cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } if (output_albedo != nullptr) { - device->BindUAV(CS, output_albedo, 1, cmd); + device->BindUAV(output_albedo, 1, cmd); } if (output_normal != nullptr) { - device->BindUAV(CS, output_normal, 2, cmd); + device->BindUAV(output_normal, 2, cmd); } device->Dispatch( @@ -7915,12 +7199,11 @@ void RayTraceScene( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, 3, cmd); wiProfiler::EndRange(range); device->EventEnd(cmd); // RayTraceScene @@ -7929,130 +7212,28 @@ void RayTraceSceneBVH(const Scene& scene, CommandList cmd) { device->EventBegin("RayTraceSceneBVH", cmd); device->BindPipelineState(&PSO_debug[DEBUGRENDERING_RAYTRACE_BVH], cmd); - scene.BVH.Bind(PS, cmd); + scene.BVH.Bind(cmd); device->Draw(3, 0, cmd); device->EventEnd(cmd); } - -void RefreshDecalAtlas(const Scene& scene, CommandList cmd) +void RefreshLightmaps(const Scene& scene, CommandList cmd) { - using namespace wiRectPacker; - - if (scene.decal_repack_needed) - { - for (uint32_t mip = 0; mip < scene.decalAtlas.GetDesc().MipLevels; ++mip) - { - for (auto& it : scene.packedDecals) - { - if (mip < it.first->texture.desc.MipLevels) - { - CopyTexture2D(scene.decalAtlas, mip, (it.second.x >> mip) + Scene::atlasClampBorder, (it.second.y >> mip) + Scene::atlasClampBorder, it.first->texture, mip, cmd, BORDEREXPAND_CLAMP); - } - } - } - scene.decal_repack_needed = false; - } -} - -void RenderObjectLightMap(const Scene& scene, const ObjectComponent& object, CommandList cmd) -{ - device->EventBegin("RenderObjectLightMap", cmd); - - const MeshComponent& mesh = *scene.meshes.GetComponent(object.meshID); - assert(!mesh.vertex_atlas.empty()); - assert(mesh.vertexBuffer_ATL.IsValid()); - - const TextureDesc& desc = object.lightmap.GetDesc(); - - if (object.lightmapIterationCount == 0) - { - device->RenderPassBegin(&object.renderpass_lightmap_clear, cmd); - } - else - { - device->RenderPassBegin(&object.renderpass_lightmap_accumulate, cmd); - } - - Viewport vp; - vp.Width = (float)desc.Width; - vp.Height = (float)desc.Height; - device->BindViewports(1, &vp, cmd); - - const TransformComponent& transform = scene.transforms[object.transform_index]; - - MiscCB misccb; - misccb.g_xTransform = transform.world; - device->UpdateBuffer(&constantBuffers[CBTYPE_MISC], &misccb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_MISC], CB_GETBINDSLOT(MiscCB), cmd); - - const GPUBuffer* vbs[] = { - &mesh.vertexBuffer_POS, - &mesh.vertexBuffer_ATL, - }; - uint32_t strides[] = { - sizeof(MeshComponent::Vertex_POS), - sizeof(MeshComponent::Vertex_TEX), - }; - uint32_t offsets[] = { - 0, - 0, - }; - device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); - device->BindIndexBuffer(&mesh.indexBuffer, mesh.GetIndexFormat(), 0, cmd); - - RaytracingCB cb; - cb.xTraceResolution.x = desc.Width; - cb.xTraceResolution.y = desc.Height; - cb.xTraceResolution_rcp.x = 1.0f / cb.xTraceResolution.x; - cb.xTraceResolution_rcp.y = 1.0f / cb.xTraceResolution.y; - XMFLOAT4 halton = wiMath::GetHaltonSequence(object.lightmapIterationCount); // for jittering the rasterization (good for eliminating atlas border artifacts) - cb.xTracePixelOffset.x = (halton.x * 2 - 1) * cb.xTraceResolution_rcp.x; - cb.xTracePixelOffset.y = (halton.y * 2 - 1) * cb.xTraceResolution_rcp.y; - cb.xTracePixelOffset.x *= 1.4f; // boost the jitter by a bit - cb.xTracePixelOffset.y *= 1.4f; // boost the jitter by a bit - cb.xTraceAccumulationFactor = 1.0f / (object.lightmapIterationCount + 1.0f); // accumulation factor (alpha) - cb.xTraceUserData.x = raytraceBounceCount; - cb.xTraceSampleIndex = object.lightmapIterationCount; - device->UpdateBuffer(&constantBuffers[CBTYPE_RAYTRACE], &cb, cmd); - device->BindConstantBuffer(VS, &constantBuffers[CBTYPE_RAYTRACE], CB_GETBINDSLOT(RaytracingCB), cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_RAYTRACE], CB_GETBINDSLOT(RaytracingCB), cmd); - - device->BindPipelineState(&PSO_renderlightmap, cmd); - - if (scene.weather.skyMap != nullptr) - { - device->BindResource(PS, &scene.weather.skyMap->texture, TEXSLOT_GLOBALENVMAP, cmd); - } - else - { - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], TEXSLOT_SKYVIEWLUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_TRANSMITTANCELUT, cmd); - device->BindResource(PS, &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_MULTISCATTERINGLUT, cmd); - } - - device->DrawIndexedInstanced((uint32_t)mesh.indices.size(), 1, 0, 0, 0, cmd); - object.lightmapIterationCount++; - - device->RenderPassEnd(cmd); - - device->EventEnd(cmd); -} -void RefreshLightmapAtlas(const Scene& scene, CommandList cmd) -{ - if (scene.lightmap_refresh_needed.load() || scene.lightmap_repack_needed.load()) + if (scene.lightmap_refresh_needed.load()) { auto range = wiProfiler::BeginRangeGPU("Lightmap Processing", cmd); - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { - device->BindResource(PS, &scene.TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); + device->BindResource(&scene.TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); } else { - scene.BVH.Bind(PS, cmd); + scene.BVH.Bind(cmd); } + BindCommonResources(cmd); + // Render lightmaps for each object: for (uint32_t i = 0; i < scene.objects.GetCount(); ++i) { @@ -8062,17 +7243,76 @@ void RefreshLightmapAtlas(const Scene& scene, CommandList cmd) if (object.IsLightmapRenderRequested()) { - RenderObjectLightMap(scene, object, cmd); - } + device->EventBegin("RenderObjectLightMap", cmd); - if (object.IsLightmapRenderRequested() || scene.lightmap_repack_needed) - { - // copy object' lightmap into scene's lightmap atlas - CopyTexture2D(scene.lightmap, -1, object.lightmap_rect.x + Scene::atlasClampBorder, object.lightmap_rect.y + Scene::atlasClampBorder, object.lightmap, 0, cmd); + const MeshComponent& mesh = *scene.meshes.GetComponent(object.meshID); + assert(!mesh.vertex_atlas.empty()); + assert(mesh.vertexBuffer_ATL.IsValid()); + + const TextureDesc& desc = object.lightmap.GetDesc(); + + if (object.lightmapIterationCount == 0) + { + device->RenderPassBegin(&object.renderpass_lightmap_clear, cmd); + } + else + { + device->RenderPassBegin(&object.renderpass_lightmap_accumulate, cmd); + } + + Viewport vp; + vp.Width = (float)desc.Width; + vp.Height = (float)desc.Height; + device->BindViewports(1, &vp, cmd); + + const TransformComponent& transform = scene.transforms[object.transform_index]; + + MiscCB misccb; + misccb.g_xTransform = transform.world; + + device->BindDynamicConstantBuffer(misccb, CB_GETBINDSLOT(MiscCB), cmd); + + const GPUBuffer* vbs[] = { + &mesh.vertexBuffer_POS, + &mesh.vertexBuffer_ATL, + }; + uint32_t strides[] = { + sizeof(MeshComponent::Vertex_POS), + sizeof(MeshComponent::Vertex_TEX), + }; + uint32_t offsets[] = { + 0, + 0, + }; + device->BindVertexBuffers(vbs, 0, arraysize(vbs), strides, offsets, cmd); + device->BindIndexBuffer(&mesh.indexBuffer, mesh.GetIndexFormat(), 0, cmd); + + RaytracingCB cb; + cb.xTraceResolution.x = desc.Width; + cb.xTraceResolution.y = desc.Height; + cb.xTraceResolution_rcp.x = 1.0f / cb.xTraceResolution.x; + cb.xTraceResolution_rcp.y = 1.0f / cb.xTraceResolution.y; + XMFLOAT4 halton = wiMath::GetHaltonSequence(object.lightmapIterationCount); // for jittering the rasterization (good for eliminating atlas border artifacts) + cb.xTracePixelOffset.x = (halton.x * 2 - 1) * cb.xTraceResolution_rcp.x; + cb.xTracePixelOffset.y = (halton.y * 2 - 1) * cb.xTraceResolution_rcp.y; + cb.xTracePixelOffset.x *= 1.4f; // boost the jitter by a bit + cb.xTracePixelOffset.y *= 1.4f; // boost the jitter by a bit + cb.xTraceAccumulationFactor = 1.0f / (object.lightmapIterationCount + 1.0f); // accumulation factor (alpha) + cb.xTraceUserData.x = raytraceBounceCount; + cb.xTraceSampleIndex = object.lightmapIterationCount; + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(RaytracingCB), cmd); + + device->BindPipelineState(&PSO_renderlightmap, cmd); + + device->DrawIndexedInstanced((uint32_t)mesh.indices.size(), 1, 0, 0, 0, cmd); + object.lightmapIterationCount++; + + device->RenderPassEnd(cmd); + + device->EventEnd(cmd); } } - scene.lightmap_repack_needed.store(false); scene.lightmap_refresh_needed.store(false); wiProfiler::EndRange(range); } @@ -8080,29 +7320,40 @@ void RefreshLightmapAtlas(const Scene& scene, CommandList cmd) void BindCommonResources(CommandList cmd) { - for (int i = 0; i < SHADERSTAGE_COUNT; ++i) - { - SHADERSTAGE stage = (SHADERSTAGE)i; + device->BindConstantBuffer(&constantBuffers[CBTYPE_FRAME], CBSLOT_RENDERER_FRAME, cmd); - device->BindSampler(stage, &samplers[SSLOT_OBJECTSHADER], SSLOT_OBJECTSHADER, cmd); + device->BindSampler(&samplers[SSLOT_OBJECTSHADER], SSLOT_OBJECTSHADER, cmd); - BindConstantBuffers(stage, cmd); + device->BindResource(wiTextureHelper::getRandom64x64(), TEXSLOT_RANDOM64X64, cmd); + device->BindResource(wiTextureHelper::getBlueNoise(), TEXSLOT_BLUENOISE, cmd); - device->BindResource(stage, wiTextureHelper::getRandom64x64(), TEXSLOT_RANDOM64X64, cmd); - device->BindResource(stage, wiTextureHelper::getBlueNoise(), TEXSLOT_BLUENOISE, cmd); - } - - device->BindResource(PS, &textures[TEXTYPE_2D_SHEENLUT], TEXSLOT_SHEENLUT, cmd); - device->BindResource(CS, &textures[TEXTYPE_2D_SHEENLUT], TEXSLOT_SHEENLUT, cmd); + device->BindResource(&textures[TEXTYPE_2D_SHEENLUT], TEXSLOT_SHEENLUT, cmd); // Bind the GPU entity array for all shaders that need it here: GPUResource* resources[] = { &resourceBuffers[RBTYPE_ENTITYARRAY], &resourceBuffers[RBTYPE_MATRIXARRAY], }; - device->BindResources(VS, resources, SBSLOT_ENTITYARRAY, arraysize(resources), cmd); - device->BindResources(PS, resources, SBSLOT_ENTITYARRAY, arraysize(resources), cmd); - device->BindResources(CS, resources, SBSLOT_ENTITYARRAY, arraysize(resources), cmd); + device->BindResources(resources, SBSLOT_ENTITYARRAY, arraysize(resources), cmd); + device->BindResources(resources, SBSLOT_ENTITYARRAY, arraysize(resources), cmd); + device->BindResources(resources, SBSLOT_ENTITYARRAY, arraysize(resources), cmd); + + device->BindResource(&shadowMapArray_2D, TEXSLOT_SHADOWARRAY_2D, cmd); + device->BindResource(&shadowMapArray_Cube, TEXSLOT_SHADOWARRAY_CUBE, cmd); + if (GetTransparentShadowsEnabled()) + { + device->BindResource(&shadowMapArray_Transparent_2D, TEXSLOT_SHADOWARRAY_TRANSPARENT_2D, cmd); + device->BindResource(&shadowMapArray_Transparent_Cube, TEXSLOT_SHADOWARRAY_TRANSPARENT_CUBE, cmd); + } + + // Bind the atmospheric textures, as lighting and sky needs them + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], TEXSLOT_SKYVIEWLUT, cmd); + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_TRANSMITTANCELUT, cmd); + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_MULTISCATTERINGLUT, cmd); + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], TEXSLOT_SKYLUMINANCELUT, cmd); + + device->BindResource(GetVoxelRadianceSecondaryBounceEnabled() ? &textures[TEXTYPE_3D_VOXELRADIANCE_HELPER] : &textures[TEXTYPE_3D_VOXELRADIANCE], TEXSLOT_VOXELGI, cmd); + } void UpdateCameraCB( @@ -8114,45 +7365,45 @@ void UpdateCameraCB( { CameraCB cb; - XMStoreFloat4x4(&cb.g_xCamera_VP, camera.GetViewProjection()); - XMStoreFloat4x4(&cb.g_xCamera_View, camera.GetView()); - XMStoreFloat4x4(&cb.g_xCamera_Proj, camera.GetProjection()); - cb.g_xCamera_CamPos = camera.Eye; - cb.g_xCamera_DistanceFromOrigin = XMVectorGetX(XMVector3Length(XMLoadFloat3(&cb.g_xCamera_CamPos))); - XMStoreFloat4x4(&cb.g_xCamera_InvV, camera.GetInvView()); - XMStoreFloat4x4(&cb.g_xCamera_InvP, camera.GetInvProjection()); - XMStoreFloat4x4(&cb.g_xCamera_InvVP, camera.GetInvViewProjection()); - cb.g_xCamera_At = camera.At; - cb.g_xCamera_Up = camera.Up; - cb.g_xCamera_ZNearP = camera.zNearP; - cb.g_xCamera_ZFarP = camera.zFarP; - cb.g_xCamera_ZNearP_rcp = 1.0f / std::max(0.0001f, cb.g_xCamera_ZNearP); - cb.g_xCamera_ZFarP_rcp = 1.0f / std::max(0.0001f, cb.g_xCamera_ZFarP); - cb.g_xCamera_ZRange = abs(cb.g_xCamera_ZFarP - cb.g_xCamera_ZNearP); - cb.g_xCamera_ZRange_rcp = 1.0f / std::max(0.0001f, cb.g_xCamera_ZRange); - cb.g_xCamera_ClipPlane = camera.clipPlane; + XMStoreFloat4x4(&cb.VP, camera.GetViewProjection()); + XMStoreFloat4x4(&cb.View, camera.GetView()); + XMStoreFloat4x4(&cb.Proj, camera.GetProjection()); + cb.CamPos = camera.Eye; + cb.DistanceFromOrigin = XMVectorGetX(XMVector3Length(XMLoadFloat3(&cb.CamPos))); + XMStoreFloat4x4(&cb.InvV, camera.GetInvView()); + XMStoreFloat4x4(&cb.InvP, camera.GetInvProjection()); + XMStoreFloat4x4(&cb.InvVP, camera.GetInvViewProjection()); + cb.At = camera.At; + cb.Up = camera.Up; + cb.ZNearP = camera.zNearP; + cb.ZFarP = camera.zFarP; + cb.ZNearP_rcp = 1.0f / std::max(0.0001f, cb.ZNearP); + cb.ZFarP_rcp = 1.0f / std::max(0.0001f, cb.ZFarP); + cb.ZRange = abs(cb.ZFarP - cb.ZNearP); + cb.ZRange_rcp = 1.0f / std::max(0.0001f, cb.ZRange); + cb.ClipPlane = camera.clipPlane; - static_assert(arraysize(camera.frustum.planes) == arraysize(cb.g_xCamera_FrustumPlanes), "Mismatch!"); + static_assert(arraysize(camera.frustum.planes) == arraysize(cb.FrustumPlanes), "Mismatch!"); for (int i = 0; i < arraysize(camera.frustum.planes); ++i) { - cb.g_xCamera_FrustumPlanes[i] = camera.frustum.planes[i]; + cb.FrustumPlanes[i] = camera.frustum.planes[i]; } - cb.g_xFrame_TemporalAAJitter = camera.jitter; - cb.g_xFrame_TemporalAAJitterPrev = camera_previous.jitter; + cb.TemporalAAJitter = camera.jitter; + cb.TemporalAAJitterPrev = camera_previous.jitter; - XMStoreFloat4x4(&cb.g_xCamera_PrevV, camera_previous.GetView()); - XMStoreFloat4x4(&cb.g_xCamera_PrevP, camera_previous.GetProjection()); - XMStoreFloat4x4(&cb.g_xCamera_PrevVP, camera_previous.GetViewProjection()); - XMStoreFloat4x4(&cb.g_xCamera_PrevInvVP, camera_previous.GetInvViewProjection()); - XMStoreFloat4x4(&cb.g_xCamera_ReflVP, camera_reflection.GetViewProjection()); - XMStoreFloat4x4(&cb.g_xCamera_Reprojection, camera.GetInvViewProjection() * camera_previous.GetViewProjection()); + XMStoreFloat4x4(&cb.PrevV, camera_previous.GetView()); + XMStoreFloat4x4(&cb.PrevP, camera_previous.GetProjection()); + XMStoreFloat4x4(&cb.PrevVP, camera_previous.GetViewProjection()); + XMStoreFloat4x4(&cb.PrevInvVP, camera_previous.GetInvViewProjection()); + XMStoreFloat4x4(&cb.ReflVP, camera_reflection.GetViewProjection()); + XMStoreFloat4x4(&cb.Reprojection, camera.GetInvViewProjection() * camera_previous.GetViewProjection()); - cb.g_xCamera_FocalLength = camera.focal_length; - cb.g_xCamera_ApertureSize = camera.aperture_size; - cb.g_xCamera_ApertureShape = camera.aperture_shape; + cb.FocalLength = camera.focal_length; + cb.ApertureSize = camera.aperture_size; + cb.ApertureShape = camera.aperture_shape; - device->UpdateBuffer(&constantBuffers[CBTYPE_CAMERA], &cb, cmd); + device->BindDynamicConstantBuffer(cb, CBSLOT_RENDERER_CAMERA, cmd); } void CreateLuminanceResources(LuminanceResources& res, XMUINT2 resolution) @@ -8180,18 +7431,17 @@ const Texture* ComputeLuminance( PostProcessCB cb; cb.luminance_adaptionrate = adaption_rate; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); // Pass 1 : Compute log luminance and reduction { device->BindComputeShader(&shaders[CSTYPE_LUMINANCE_PASS1], cmd); - device->BindResource(CS, &sourceImage, TEXSLOT_ONDEMAND0, cmd); - device->BindUAV(CS, &res.reductiontex, 0, cmd); + device->BindResource(&sourceImage, TEXSLOT_ONDEMAND0, cmd); + device->BindUAV(&res.reductiontex, 0, cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.reductiontex, res.reductiontex.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.reductiontex, res.reductiontex.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8201,7 +7451,7 @@ const Texture* ComputeLuminance( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.reductiontex, IMAGE_LAYOUT_UNORDERED_ACCESS, res.reductiontex.desc.layout), + GPUBarrier::Image(&res.reductiontex, RESOURCE_STATE_UNORDERED_ACCESS, res.reductiontex.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8211,12 +7461,12 @@ const Texture* ComputeLuminance( { device->BindComputeShader(&shaders[CSTYPE_LUMINANCE_PASS2], cmd); - device->BindUAV(CS, &res.luminance, 0, cmd); - device->BindResource(CS, &res.reductiontex, TEXSLOT_ONDEMAND0, cmd); + device->BindUAV(&res.luminance, 0, cmd); + device->BindResource(&res.reductiontex, TEXSLOT_ONDEMAND0, cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.luminance, res.luminance.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.luminance, res.luminance.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8226,12 +7476,11 @@ const Texture* ComputeLuminance( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.luminance, IMAGE_LAYOUT_UNORDERED_ACCESS, res.luminance.desc.layout), + GPUBarrier::Image(&res.luminance, RESOURCE_STATE_UNORDERED_ACCESS, res.luminance.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, 1, cmd); } wiProfiler::EndRange(range); @@ -8253,11 +7502,11 @@ void ComputeShadingRateClassification( if (GetVariableRateShadingClassificationDebug()) { - device->BindUAV(CS, &debugUAV, 1, cmd); + device->BindUAV(&debugUAV, 1, cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&debugUAV, debugUAV.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&debugUAV, debugUAV.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8269,8 +7518,8 @@ void ComputeShadingRateClassification( device->BindComputeShader(&shaders[CSTYPE_SHADINGRATECLASSIFICATION], cmd); } - device->BindResource(CS, &gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER2, cmd); - device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER1, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); const TextureDesc& desc = output.GetDesc(); @@ -8283,17 +7532,16 @@ void ComputeShadingRateClassification( device->WriteShadingRateValue(SHADING_RATE_2X4, &cb.SHADING_RATE_2X4); device->WriteShadingRateValue(SHADING_RATE_4X2, &cb.SHADING_RATE_4X2); device->WriteShadingRateValue(SHADING_RATE_4X4, &cb.SHADING_RATE_4X4); - device->UpdateBuffer(&constantBuffers[CBTYPE_SHADINGRATECLASSIFICATION], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_SHADINGRATECLASSIFICATION], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8304,7 +7552,7 @@ void ComputeShadingRateClassification( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8313,18 +7561,430 @@ void ComputeShadingRateClassification( { { GPUBarrier barriers[] = { - GPUBarrier::Image(&debugUAV, IMAGE_LAYOUT_UNORDERED_ACCESS, debugUAV.desc.layout), + GPUBarrier::Image(&debugUAV, RESOURCE_STATE_UNORDERED_ACCESS, debugUAV.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } } - device->UnbindUAVs(0, arraysize(uavs), cmd); wiProfiler::EndRange(range); device->EventEnd(cmd); } +void VisibilityResolve( + const Texture& depthbuffer, + const Texture& texture_primitiveID, // can be MSAA + const Texture gbuffer[GBUFFER_COUNT], + const Texture& depthbuffer_resolved, + const Texture& lineardepth, + CommandList cmd +) +{ + device->EventBegin("VisibilityResolve", cmd); + auto range = wiProfiler::BeginRangeGPU("VisibilityResolve", cmd); + + BindCommonResources(cmd); + + const bool msaa = texture_primitiveID.desc.SampleCount > 1; + + device->BindComputeShader(&shaders[msaa ? CSTYPE_VISIBILITY_RESOLVE_MSAA : CSTYPE_VISIBILITY_RESOLVE], cmd); + + + device->BindResource(&texture_primitiveID, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&depthbuffer, TEXSLOT_ONDEMAND1, cmd); + + device->BindUAV(&gbuffer[GBUFFER_VELOCITY], 0, cmd); + device->BindUAV(&depthbuffer_resolved, 1, cmd, 0); + device->BindUAV(&depthbuffer_resolved, 2, cmd, 1); + device->BindUAV(&depthbuffer_resolved, 3, cmd, 2); + device->BindUAV(&depthbuffer_resolved, 4, cmd, 3); + device->BindUAV(&depthbuffer_resolved, 5, cmd, 4); + device->BindUAV(&lineardepth, 6, cmd, 0); + device->BindUAV(&lineardepth, 7, cmd, 1); + device->BindUAV(&lineardepth, 8, cmd, 2); + device->BindUAV(&lineardepth, 9, cmd, 3); + device->BindUAV(&lineardepth, 10, cmd, 4); + + { + GPUBarrier barriers[] = { + GPUBarrier::Image(&gbuffer[GBUFFER_VELOCITY], gbuffer[GBUFFER_VELOCITY].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&depthbuffer_resolved, depthbuffer_resolved.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&lineardepth, lineardepth.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + if (msaa) + { + device->BindUAV(&gbuffer[GBUFFER_PRIMITIVEID], 11, cmd); + { + GPUBarrier barriers[] = { + GPUBarrier::Image(&gbuffer[GBUFFER_PRIMITIVEID], gbuffer[GBUFFER_PRIMITIVEID].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + } + + device->Dispatch( + (depthbuffer.desc.Width + 15) / 16, + (depthbuffer.desc.Height + 15) / 16, + 1, + cmd + ); + + { + GPUBarrier barriers[] = { + GPUBarrier::Memory(), + GPUBarrier::Image(&gbuffer[GBUFFER_VELOCITY], RESOURCE_STATE_UNORDERED_ACCESS, gbuffer[GBUFFER_VELOCITY].desc.layout), + GPUBarrier::Image(&depthbuffer_resolved, RESOURCE_STATE_UNORDERED_ACCESS, depthbuffer_resolved.desc.layout), + GPUBarrier::Image(&lineardepth, RESOURCE_STATE_UNORDERED_ACCESS, lineardepth.desc.layout), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + if (msaa) + { + { + GPUBarrier barriers[] = { + GPUBarrier::Image(&gbuffer[GBUFFER_PRIMITIVEID], RESOURCE_STATE_UNORDERED_ACCESS, gbuffer[GBUFFER_PRIMITIVEID].desc.layout), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + } + + + wiProfiler::EndRange(range); + device->EventEnd(cmd); +} + +void CreateSurfelGIResources(SurfelGIResources& res, XMUINT2 resolution) +{ + TextureDesc desc; + desc.Width = resolution.x; + desc.Height = resolution.y; + desc.Format = FORMAT_R11G11B10_FLOAT; + desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; + device->CreateTexture(&desc, nullptr, &res.result); + device->SetName(&res.result, "surfelGI.result"); +} +void SurfelGI_Coverage( + const SurfelGIResources& res, + const Scene& scene, + const Texture& depthbuffer, + const Texture gbuffer[GBUFFER_COUNT], + const Texture& debugUAV, + CommandList cmd +) +{ + device->EventBegin("SurfelGI - Coverage", cmd); + auto prof_range = wiProfiler::BeginRangeGPU("SurfelGI - Coverage", cmd); + + + // Coverage: + { + device->EventBegin("Coverage", cmd); + device->BindComputeShader(&shaders[CSTYPE_SURFEL_COVERAGE], cmd); + + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&gbuffer[GBUFFER_PRIMITIVEID], TEXSLOT_GBUFFER0, cmd); + device->BindResource(&gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER1, cmd); + + device->BindResource(&scene.surfelBuffer, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&scene.surfelStatsBuffer, TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&scene.surfelGridBuffer, TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&scene.surfelCellBuffer, TEXSLOT_ONDEMAND3, cmd); + device->BindResource(&scene.surfelMomentsTexture, TEXSLOT_ONDEMAND4, cmd); + + const GPUResource* uavs[] = { + &scene.surfelDataBuffer, + &scene.surfelStatsBuffer, + &res.result, + &debugUAV + }; + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); + + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&scene.surfelStatsBuffer, RESOURCE_STATE_INDIRECT_ARGUMENT, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.result, res.result.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&debugUAV, debugUAV.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + +#ifdef SURFEL_COVERAGE_HALFRES + device->Dispatch( + (res.result.desc.Width / 2 + 15) / 16, + (res.result.desc.Height / 2 + 15) / 16, + 1, + cmd + ); +#else + device->Dispatch( + (res.result.desc.Width + 15) / 16, + (res.result.desc.Height + 15) / 16, + 1, + cmd + ); +#endif // SURFEL_COVERAGE_HALFRES + + { + GPUBarrier barriers[] = { + GPUBarrier::Memory(), + GPUBarrier::Image(&res.result, RESOURCE_STATE_UNORDERED_ACCESS, res.result.desc.layout), + GPUBarrier::Image(&debugUAV, RESOURCE_STATE_UNORDERED_ACCESS, debugUAV.desc.layout), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->EventEnd(cmd); + } + + // surfel count -> indirect args (for next frame): + { + device->EventBegin("Indirect args", cmd); + const GPUResource* uavs[] = { + &scene.surfelStatsBuffer, + }; + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); + + device->BindComputeShader(&shaders[CSTYPE_SURFEL_INDIRECTPREPARE], cmd); + device->Dispatch(1, 1, 1, cmd); + + device->EventEnd(cmd); + } + + + wiProfiler::EndRange(prof_range); + device->EventEnd(cmd); +} +void SurfelGI( + const SurfelGIResources& res, + const wiScene::Scene& scene, + wiGraphics::CommandList cmd +) +{ + auto prof_range = wiProfiler::BeginRangeGPU("SurfelGI", cmd); + device->EventBegin("SurfelGI", cmd); + + BindCommonResources(cmd); + + + // Grid reset: + { + device->EventBegin("Grid Reset", cmd); + device->BindComputeShader(&shaders[CSTYPE_SURFEL_GRIDRESET], cmd); + + const GPUResource* uavs[] = { + &scene.surfelGridBuffer, + }; + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); + + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&scene.surfelGridBuffer, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE, RESOURCE_STATE_UNORDERED_ACCESS), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->Dispatch( + (SURFEL_TABLE_SIZE + 63) / 64, + 1, + 1, + cmd + ); + + device->EventEnd(cmd); + } + + // Update: + { + device->EventBegin("Update", cmd); + device->BindComputeShader(&shaders[CSTYPE_SURFEL_UPDATE], cmd); + + device->BindResource(&scene.surfelStatsBuffer, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&scene.surfelDataBuffer, TEXSLOT_ONDEMAND1, cmd); + + const GPUResource* uavs[] = { + &scene.surfelBuffer, + &scene.surfelGridBuffer, + }; + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); + + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&scene.surfelBuffer, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE, RESOURCE_STATE_UNORDERED_ACCESS), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->DispatchIndirect(&scene.surfelStatsBuffer, SURFEL_STATS_OFFSET_INDIRECT, cmd); + + { + GPUBarrier barriers[] = { + GPUBarrier::Memory(), + GPUBarrier::Buffer(&scene.surfelBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->EventEnd(cmd); + } + + // Grid offsets: + { + device->EventBegin("Grid Offsets", cmd); + device->BindComputeShader(&shaders[CSTYPE_SURFEL_GRIDOFFSETS], cmd); + + const GPUResource* uavs[] = { + &scene.surfelGridBuffer, + &scene.surfelCellBuffer, + &scene.surfelStatsBuffer, + }; + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); + + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&scene.surfelCellBuffer, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Buffer(&scene.surfelStatsBuffer, RESOURCE_STATE_INDIRECT_ARGUMENT, RESOURCE_STATE_UNORDERED_ACCESS), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->Dispatch( + (SURFEL_TABLE_SIZE + 63) / 64, + 1, + 1, + cmd + ); + + { + GPUBarrier barriers[] = { + GPUBarrier::Memory(), + GPUBarrier::Buffer(&scene.surfelStatsBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_INDIRECT_ARGUMENT), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->EventEnd(cmd); + } + + // Binning: + { + device->EventBegin("Binning", cmd); + device->BindComputeShader(&shaders[CSTYPE_SURFEL_BINNING], cmd); + + device->BindResource(&scene.surfelBuffer, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&scene.surfelStatsBuffer, TEXSLOT_ONDEMAND1, cmd); + + const GPUResource* uavs[] = { + &scene.surfelGridBuffer, + &scene.surfelCellBuffer, + }; + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); + + device->DispatchIndirect(&scene.surfelStatsBuffer, SURFEL_STATS_OFFSET_INDIRECT, cmd); + + { + GPUBarrier barriers[] = { + GPUBarrier::Memory(), + GPUBarrier::Buffer(&scene.surfelGridBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE), + GPUBarrier::Buffer(&scene.surfelCellBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->EventEnd(cmd); + } + + + + // Raytracing: + { + device->EventBegin("Raytrace", cmd); + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) + { + if (!scene.TLAS.IsValid()) + { + return; + } + device->BindResource(&scene.TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); + } + else + { + scene.BVH.Bind(cmd); + } + + device->BindComputeShader(&shaders[CSTYPE_SURFEL_RAYTRACE], cmd); + + device->BindResource(&scene.surfelBuffer, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&scene.surfelStatsBuffer, TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&scene.surfelGridBuffer, TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&scene.surfelCellBuffer, TEXSLOT_ONDEMAND3, cmd); + + const GPUResource* uavs[] = { + &scene.surfelDataBuffer, + &scene.surfelMomentsTexture, + }; + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); + + { + GPUBarrier barriers[] = { + GPUBarrier::Buffer(&scene.surfelDataBuffer, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&scene.surfelMomentsTexture, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE, RESOURCE_STATE_UNORDERED_ACCESS), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->DispatchIndirect(&scene.surfelStatsBuffer, SURFEL_STATS_OFFSET_INDIRECT, cmd); + + { + GPUBarrier barriers[] = { + GPUBarrier::Memory(), + GPUBarrier::Image(&scene.surfelMomentsTexture, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->EventEnd(cmd); + } + + // Shading: + { + device->EventBegin("Shade", cmd); + + device->BindComputeShader(&shaders[CSTYPE_SURFEL_SHADE], cmd); + + device->BindResource(&scene.surfelBuffer, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&scene.surfelStatsBuffer, TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&scene.surfelGridBuffer, TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&scene.surfelCellBuffer, TEXSLOT_ONDEMAND3, cmd); + device->BindResource(&scene.surfelMomentsTexture, TEXSLOT_ONDEMAND4, cmd); + + const GPUResource* uavs[] = { + &scene.surfelDataBuffer, + }; + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); + + device->DispatchIndirect(&scene.surfelStatsBuffer, SURFEL_STATS_OFFSET_INDIRECT, cmd); + + { + GPUBarrier barriers[] = { + GPUBarrier::Memory(), + GPUBarrier::Buffer(&scene.surfelDataBuffer, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE), + }; + device->Barrier(barriers, arraysize(barriers), cmd); + } + + device->EventEnd(cmd); + } + + wiProfiler::EndRange(prof_range); + device->EventEnd(cmd); +} + void Postprocess_Blur_Gaussian( const Texture& input, const Texture& temp, @@ -8366,7 +8026,6 @@ void Postprocess_Blur_Gaussian( break; } device->BindComputeShader(&shaders[cs], cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); // Horizontal: { @@ -8384,14 +8043,14 @@ void Postprocess_Blur_Gaussian( cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; cb.xPPParams0.x = 1; cb.xPPParams0.y = 0; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); - device->BindResource(CS, &input, TEXSLOT_ONDEMAND0, cmd, mip_src); - device->BindUAV(CS, &temp, 0, cmd, mip_dst); + device->BindResource(&input, TEXSLOT_ONDEMAND0, cmd, mip_src); + device->BindUAV(&temp, 0, cmd, mip_dst); { GPUBarrier barriers[] = { - GPUBarrier::Image(&temp, temp.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS, mip_dst), + GPUBarrier::Image(&temp, temp.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS, mip_dst), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8406,12 +8065,11 @@ void Postprocess_Blur_Gaussian( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&temp, IMAGE_LAYOUT_UNORDERED_ACCESS, temp.desc.layout, mip_dst), + GPUBarrier::Image(&temp, RESOURCE_STATE_UNORDERED_ACCESS, temp.desc.layout, mip_dst), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, 1, cmd); } // Vertical: @@ -8430,14 +8088,14 @@ void Postprocess_Blur_Gaussian( cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; cb.xPPParams0.x = 0; cb.xPPParams0.y = 1; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); - device->BindResource(CS, &temp, TEXSLOT_ONDEMAND0, cmd, mip_dst); // <- also mip_dst because it's second pass! - device->BindUAV(CS, &output, 0, cmd, mip_dst); + device->BindResource(&temp, TEXSLOT_ONDEMAND0, cmd, mip_dst); // <- also mip_dst because it's second pass! + device->BindUAV(&output, 0, cmd, mip_dst); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS, mip_dst), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS, mip_dst), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8452,12 +8110,11 @@ void Postprocess_Blur_Gaussian( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout, mip_dst), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout, mip_dst), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, 1, cmd); } device->EventEnd(cmd); @@ -8505,9 +8162,8 @@ void Postprocess_Blur_Bilateral( break; } device->BindComputeShader(&shaders[cs], cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); - device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); // Horizontal: { @@ -8526,14 +8182,14 @@ void Postprocess_Blur_Bilateral( cb.xPPParams0.x = 1; cb.xPPParams0.y = 0; cb.xPPParams0.w = depth_threshold; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); - device->BindResource(CS, &input, TEXSLOT_ONDEMAND0, cmd, mip_src); - device->BindUAV(CS, &temp, 0, cmd, mip_dst); + device->BindResource(&input, TEXSLOT_ONDEMAND0, cmd, mip_src); + device->BindUAV(&temp, 0, cmd, mip_dst); { GPUBarrier barriers[] = { - GPUBarrier::Image(&temp, temp.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS, mip_dst), + GPUBarrier::Image(&temp, temp.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS, mip_dst), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8548,12 +8204,11 @@ void Postprocess_Blur_Bilateral( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&temp, IMAGE_LAYOUT_UNORDERED_ACCESS, temp.desc.layout, mip_dst), + GPUBarrier::Image(&temp, RESOURCE_STATE_UNORDERED_ACCESS, temp.desc.layout, mip_dst), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, 1, cmd); } // Vertical: @@ -8573,14 +8228,14 @@ void Postprocess_Blur_Bilateral( cb.xPPParams0.x = 0; cb.xPPParams0.y = 1; cb.xPPParams0.w = depth_threshold; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); - device->BindResource(CS, &temp, TEXSLOT_ONDEMAND0, cmd, mip_dst); // <- also mip_dst because it's second pass! - device->BindUAV(CS, &output, 0, cmd, mip_dst); + device->BindResource(&temp, TEXSLOT_ONDEMAND0, cmd, mip_dst); // <- also mip_dst because it's second pass! + device->BindUAV(&output, 0, cmd, mip_dst); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS, mip_dst), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS, mip_dst), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8595,12 +8250,11 @@ void Postprocess_Blur_Bilateral( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout, mip_dst), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout, mip_dst), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, 1, cmd); } device->EventEnd(cmd); @@ -8612,7 +8266,7 @@ void CreateSSAOResources(SSAOResources& res, XMUINT2 resolution) desc.Width = resolution.x / 2; desc.Height = resolution.y / 2; desc.BindFlags = BIND_UNORDERED_ACCESS | BIND_SHADER_RESOURCE; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; device->CreateTexture(&desc, nullptr, &res.temp); } void Postprocess_SSAO( @@ -8631,8 +8285,8 @@ void Postprocess_SSAO( device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_SSAO], cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); const TextureDesc& desc = output.GetDesc(); @@ -8644,17 +8298,16 @@ void Postprocess_SSAO( cb.ssao_range = range; cb.ssao_samplecount = (float)samplecount; cb.ssao_power = power; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8669,12 +8322,11 @@ void Postprocess_SSAO( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); Postprocess_Blur_Bilateral(output, lineardepth, res.temp, output, cmd, 1.2f, -1, -1, true); @@ -8695,7 +8347,7 @@ void Postprocess_HBAO( device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_HBAO], cmd); - device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); const TextureDesc& desc = output.GetDesc(); @@ -8723,20 +8375,19 @@ void Postprocess_HBAO( cb.xPPParams1.z = UVToViewBX; cb.xPPParams1.w = UVToViewBY; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); // horizontal pass: { - device->BindResource(CS, wiTextureHelper::getWhite(), TEXSLOT_ONDEMAND0, cmd); + device->BindResource(wiTextureHelper::getWhite(), TEXSLOT_ONDEMAND0, cmd); const GPUResource* uavs[] = { &res.temp, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.temp, res.temp.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.temp, res.temp.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8751,30 +8402,28 @@ void Postprocess_HBAO( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.temp, IMAGE_LAYOUT_UNORDERED_ACCESS, res.temp.desc.layout), + GPUBarrier::Image(&res.temp, RESOURCE_STATE_UNORDERED_ACCESS, res.temp.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); } // vertical pass: { cb.xPPParams0.x = 0; cb.xPPParams0.y = 1; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); - device->BindResource(CS, &res.temp, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.temp, TEXSLOT_ONDEMAND0, cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8789,13 +8438,11 @@ void Postprocess_HBAO( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); - device->UnbindResources(TEXSLOT_ONDEMAND1, 1, cmd); } Postprocess_Blur_Bilateral(output, lineardepth, res.temp, output, cmd, 1.2f, -1, -1, true); @@ -8810,7 +8457,7 @@ void CreateMSAOResources(MSAOResources& res, XMUINT2 resolution) saved_desc.Width = resolution.x; saved_desc.Height = resolution.y; saved_desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - saved_desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE; + saved_desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; const uint32_t bufferWidth = saved_desc.Width; const uint32_t bufferWidth1 = (bufferWidth + 1) / 2; @@ -8905,7 +8552,7 @@ void Postprocess_MSAO( { device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_MSAO_PREPAREDEPTHBUFFERS1], cmd); - device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); const GPUResource* uavs[] = { &res.texture_lineardepth_downsize1, @@ -8913,14 +8560,14 @@ void Postprocess_MSAO( &res.texture_lineardepth_downsize2, &res.texture_lineardepth_tiled2, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_lineardepth_downsize1, res.texture_lineardepth_downsize1.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_lineardepth_tiled1, res.texture_lineardepth_tiled1.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_lineardepth_downsize2, res.texture_lineardepth_downsize2.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_lineardepth_tiled2, res.texture_lineardepth_tiled2.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_lineardepth_downsize1, res.texture_lineardepth_downsize1.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_lineardepth_tiled1, res.texture_lineardepth_tiled1.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_lineardepth_downsize2, res.texture_lineardepth_downsize2.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_lineardepth_tiled2, res.texture_lineardepth_tiled2.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8931,22 +8578,21 @@ void Postprocess_MSAO( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_lineardepth_downsize1, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_lineardepth_downsize1.desc.layout), - GPUBarrier::Image(&res.texture_lineardepth_tiled1, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_lineardepth_tiled1.desc.layout), - GPUBarrier::Image(&res.texture_lineardepth_downsize2, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_lineardepth_downsize2.desc.layout), - GPUBarrier::Image(&res.texture_lineardepth_tiled2, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_lineardepth_tiled2.desc.layout), + GPUBarrier::Image(&res.texture_lineardepth_downsize1, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_lineardepth_downsize1.desc.layout), + GPUBarrier::Image(&res.texture_lineardepth_tiled1, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_lineardepth_tiled1.desc.layout), + GPUBarrier::Image(&res.texture_lineardepth_downsize2, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_lineardepth_downsize2.desc.layout), + GPUBarrier::Image(&res.texture_lineardepth_tiled2, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_lineardepth_tiled2.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); } // Depth downsampling + deinterleaving pass2: { device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_MSAO_PREPAREDEPTHBUFFERS2], cmd); - device->BindResource(CS, &res.texture_lineardepth_downsize2, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.texture_lineardepth_downsize2, TEXSLOT_ONDEMAND0, cmd); const GPUResource* uavs[] = { &res.texture_lineardepth_downsize3, @@ -8954,14 +8600,14 @@ void Postprocess_MSAO( &res.texture_lineardepth_downsize4, &res.texture_lineardepth_tiled4, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_lineardepth_downsize3, res.texture_lineardepth_downsize3.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_lineardepth_tiled3, res.texture_lineardepth_tiled3.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_lineardepth_downsize4, res.texture_lineardepth_downsize4.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_lineardepth_tiled4, res.texture_lineardepth_tiled4.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_lineardepth_downsize3, res.texture_lineardepth_downsize3.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_lineardepth_tiled3, res.texture_lineardepth_tiled3.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_lineardepth_downsize4, res.texture_lineardepth_downsize4.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_lineardepth_tiled4, res.texture_lineardepth_tiled4.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -8972,15 +8618,14 @@ void Postprocess_MSAO( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_lineardepth_downsize3, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_lineardepth_downsize3.desc.layout), - GPUBarrier::Image(&res.texture_lineardepth_tiled3, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_lineardepth_tiled3.desc.layout), - GPUBarrier::Image(&res.texture_lineardepth_downsize4, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_lineardepth_downsize4.desc.layout), - GPUBarrier::Image(&res.texture_lineardepth_tiled4, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_lineardepth_tiled4.desc.layout), + GPUBarrier::Image(&res.texture_lineardepth_downsize3, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_lineardepth_downsize3.desc.layout), + GPUBarrier::Image(&res.texture_lineardepth_tiled3, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_lineardepth_tiled3.desc.layout), + GPUBarrier::Image(&res.texture_lineardepth_downsize4, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_lineardepth_downsize4.desc.layout), + GPUBarrier::Image(&res.texture_lineardepth_tiled4, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_lineardepth_tiled4.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); } @@ -9110,19 +8755,18 @@ void Postprocess_MSAO( cb.xRejectFadeoff = 1.0f / -RejectionFalloff; cb.xRcpAccentuation = 1.0f / (1.0f + Accentuation); - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS_MSAO], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS_MSAO], CB_GETBINDSLOT(MSAOCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(MSAOCB), cmd); - device->BindResource(CS, &read_depth, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&read_depth, TEXSLOT_ONDEMAND0, cmd); const GPUResource* uavs[] = { &write_result, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&write_result, write_result.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&write_result, write_result.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -9141,12 +8785,11 @@ void Postprocess_MSAO( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&write_result, IMAGE_LAYOUT_UNORDERED_ACCESS, write_result.desc.layout), + GPUBarrier::Image(&write_result, RESOURCE_STATE_UNORDERED_ACCESS, write_result.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); }; // end of lambda: msao_compute msao_compute(res.texture_ao_merged4, res.texture_lineardepth_tiled4); @@ -9209,28 +8852,27 @@ void Postprocess_MSAO( cb.kBlurTolerance = kBlurTolerance; cb.kUpsampleTolerance = kUpsampleTolerance; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS_MSAO_UPSAMPLE], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS_MSAO_UPSAMPLE], CB_GETBINDSLOT(MSAO_UPSAMPLECB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(MSAO_UPSAMPLECB), cmd); - device->BindUAV(CS, &Destination, 0, cmd); - device->BindResource(CS, &LoResDepth, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &HiResDepth, TEXSLOT_ONDEMAND1, cmd); + device->BindUAV(&Destination, 0, cmd); + device->BindResource(&LoResDepth, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&HiResDepth, TEXSLOT_ONDEMAND1, cmd); if (InterleavedAO != nullptr) { - device->BindResource(CS, InterleavedAO, TEXSLOT_ONDEMAND2, cmd); + device->BindResource(InterleavedAO, TEXSLOT_ONDEMAND2, cmd); } if (HighQualityAO != nullptr) { - device->BindResource(CS, HighQualityAO, TEXSLOT_ONDEMAND3, cmd); + device->BindResource(HighQualityAO, TEXSLOT_ONDEMAND3, cmd); } if (HiResAO != nullptr) { - device->BindResource(CS, HiResAO, TEXSLOT_ONDEMAND4, cmd); + device->BindResource(HiResAO, TEXSLOT_ONDEMAND4, cmd); } { GPUBarrier barriers[] = { - GPUBarrier::Image(&Destination, Destination.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&Destination, Destination.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -9240,7 +8882,7 @@ void Postprocess_MSAO( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&Destination, IMAGE_LAYOUT_UNORDERED_ACCESS, Destination.desc.layout), + GPUBarrier::Image(&Destination, RESOURCE_STATE_UNORDERED_ACCESS, Destination.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -9291,7 +8933,7 @@ void CreateRTAOResources(RTAOResources& res, XMUINT2 resolution) desc.Width = resolution.x / 2; desc.Height = resolution.y / 2; desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; desc.Format = FORMAT_R11G11B10_FLOAT; device->CreateTexture(&desc, nullptr, &res.normals); @@ -9334,7 +8976,7 @@ void Postprocess_RTAO( float power ) { - if (!wiRenderer::device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (!device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) return; if (scene.objects.GetCount() <= 0) @@ -9353,20 +8995,19 @@ void Postprocess_RTAO( device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_RTAO], cmd); - device->BindResource(CS, &scene.TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&scene.TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); - device->BindResource(CS, &gbuffer[GBUFFER_COLOR], TEXSLOT_GBUFFER0, cmd); - device->BindResource(CS, &gbuffer[GBUFFER_NORMAL_ROUGHNESS], TEXSLOT_GBUFFER1, cmd); - device->BindResource(CS, &gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER2, cmd); + device->BindResource(&gbuffer[GBUFFER_PRIMITIVEID], TEXSLOT_GBUFFER0, cmd); + device->BindResource(&gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER1, cmd); const GPUResource* uavs[] = { &output, &res.normals, &res.tiles }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); PostProcessCB cb; cb.xPPResolution.x = desc.Width; @@ -9376,14 +9017,13 @@ void Postprocess_RTAO( cb.rtao_range = range; cb.rtao_power = power; cb.xPPParams0.w = (float)res.frame; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.normals, res.normals.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Buffer(&res.tiles, BUFFER_STATE_SHADER_RESOURCE_COMPUTE, BUFFER_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.normals, res.normals.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Buffer(&res.tiles, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -9398,16 +9038,15 @@ void Postprocess_RTAO( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.normals, IMAGE_LAYOUT_UNORDERED_ACCESS, res.normals.desc.layout), - GPUBarrier::Buffer(&res.tiles, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE_COMPUTE), + GPUBarrier::Image(&res.normals, RESOURCE_STATE_UNORDERED_ACCESS, res.normals.desc.layout), + GPUBarrier::Buffer(&res.tiles, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE), }; device->Barrier(barriers, arraysize(barriers), cmd); } device->EventEnd(cmd); - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); int temporal_output = res.frame % 2; int temporal_history = 1 - temporal_output; @@ -9417,25 +9056,25 @@ void Postprocess_RTAO( device->EventBegin("Denoise - Tile Classification", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_RTAO_DENOISE_TILECLASSIFICATION], cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &res.normals, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &res.tiles, TEXSLOT_ONDEMAND1, cmd); - device->BindResource(CS, &res.moments[temporal_history], TEXSLOT_ONDEMAND2, cmd); - device->BindResource(CS, &res.scratch[1], TEXSLOT_ONDEMAND3, cmd); - device->BindResource(CS, &depth_history, TEXSLOT_ONDEMAND4, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&res.normals, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.tiles, TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&res.moments[temporal_history], TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.scratch[1], TEXSLOT_ONDEMAND3, cmd); + device->BindResource(&depth_history, TEXSLOT_ONDEMAND4, cmd); const GPUResource* uavs[] = { &res.scratch[0], &res.moments[temporal_output], &res.metadata }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.scratch[0], res.scratch[0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.moments[temporal_output], res.moments[temporal_output].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Buffer(&res.metadata, BUFFER_STATE_SHADER_RESOURCE_COMPUTE, BUFFER_STATE_UNORDERED_ACCESS) + GPUBarrier::Image(&res.scratch[0], res.scratch[0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.moments[temporal_output], res.moments[temporal_output].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Buffer(&res.metadata, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE, RESOURCE_STATE_UNORDERED_ACCESS) }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -9450,9 +9089,9 @@ void Postprocess_RTAO( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.scratch[0], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[0].desc.layout), - GPUBarrier::Image(&res.moments[temporal_output], IMAGE_LAYOUT_UNORDERED_ACCESS, res.moments[temporal_output].desc.layout), - GPUBarrier::Buffer(&res.metadata, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE_COMPUTE) + GPUBarrier::Image(&res.scratch[0], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[0].desc.layout), + GPUBarrier::Image(&res.moments[temporal_output], RESOURCE_STATE_UNORDERED_ACCESS, res.moments[temporal_output].desc.layout), + GPUBarrier::Buffer(&res.metadata, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE) }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -9465,29 +9104,28 @@ void Postprocess_RTAO( device->EventBegin("Denoise - Filter", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_RTAO_DENOISE_FILTER], cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &res.normals, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &res.metadata, TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&res.normals, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.metadata, TEXSLOT_ONDEMAND1, cmd); // pass0: { - device->BindResource(CS, &res.scratch[0], TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.scratch[0], TEXSLOT_ONDEMAND2, cmd); const GPUResource* uavs[] = { &res.scratch[1], &output }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.scratch[1], res.scratch[1].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[1], res.scratch[1].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } cb.xPPParams1.x = 0; cb.xPPParams1.y = 1; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); device->Dispatch( (desc.Width + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, @@ -9499,25 +9137,24 @@ void Postprocess_RTAO( // pass1: { - device->BindResource(CS, &res.scratch[1], TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.scratch[1], TEXSLOT_ONDEMAND2, cmd); const GPUResource* uavs[] = { &res.scratch[0], &output }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.scratch[1], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[1].desc.layout), - GPUBarrier::Image(&res.scratch[0], res.scratch[0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[1], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[1].desc.layout), + GPUBarrier::Image(&res.scratch[0], res.scratch[0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } cb.xPPParams1.x = 1; cb.xPPParams1.y = 2; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); device->Dispatch( (desc.Width + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, @@ -9529,25 +9166,24 @@ void Postprocess_RTAO( // pass2: { - device->BindResource(CS, &res.scratch[0], TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.scratch[0], TEXSLOT_ONDEMAND2, cmd); const GPUResource* uavs[] = { &res.scratch[1], &output }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.scratch[0], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[0].desc.layout), - GPUBarrier::Image(&res.scratch[1], res.scratch[0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[0], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[0].desc.layout), + GPUBarrier::Image(&res.scratch[1], res.scratch[0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } cb.xPPParams1.x = 2; cb.xPPParams1.y = 4; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); device->Dispatch( (desc.Width + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, @@ -9560,8 +9196,8 @@ void Postprocess_RTAO( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.scratch[1], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[1].desc.layout), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&res.scratch[1], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[1].desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -9579,7 +9215,7 @@ void CreateRTReflectionResources(RTReflectionResources& res, XMUINT2 resolution) desc.Width = resolution.x / 2; desc.Height = resolution.y / 2; desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; desc.Format = FORMAT_R11G11B10_FLOAT; device->CreateTexture(&desc, nullptr, &res.temporal[0]); @@ -9602,9 +9238,7 @@ void Postprocess_RTReflection( float range ) { - if (!wiRenderer::device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE)) - return; - if (!wiRenderer::device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_GEOMETRYINDEX)) + if (!device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) return; if (scene.objects.GetCount() <= 0) @@ -9620,29 +9254,13 @@ void Postprocess_RTReflection( device->BindRaytracingPipelineState(&RTPSO_reflection, cmd); BindCommonResources(cmd); - BindShadowmaps(LIB, cmd); - device->BindResource(LIB, &scene.TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); - device->BindResource(LIB, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(LIB, &gbuffer[GBUFFER_NORMAL_ROUGHNESS], TEXSLOT_GBUFFER1, cmd); - device->BindResource(LIB, &gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER2, cmd); + device->BindResource(&scene.TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&gbuffer[GBUFFER_PRIMITIVEID], TEXSLOT_GBUFFER0, cmd); + device->BindResource(&gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER1, cmd); - device->BindResource(LIB, &depth_history, TEXSLOT_ONDEMAND2, cmd); - - device->BindResource(LIB, &resourceBuffers[RBTYPE_ENTITYARRAY], SBSLOT_ENTITYARRAY, cmd); - device->BindResource(LIB, &resourceBuffers[RBTYPE_MATRIXARRAY], SBSLOT_MATRIXARRAY, cmd); - device->BindResource(LIB, GetVoxelRadianceSecondaryBounceEnabled() ? &textures[TEXTYPE_3D_VOXELRADIANCE_HELPER] : &textures[TEXTYPE_3D_VOXELRADIANCE], TEXSLOT_VOXELRADIANCE, cmd); - device->BindResource(LIB, &scene.envmapArray, TEXSLOT_ENVMAPARRAY, cmd); - device->BindResource(LIB, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_TRANSMITTANCELUT, cmd); - device->BindResource(LIB, &textures[TEXTYPE_2D_SKYATMOSPHERE_MULTISCATTEREDLUMINANCELUT], TEXSLOT_MULTISCATTERINGLUT, cmd); - device->BindResource(LIB, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYVIEWLUT], TEXSLOT_SKYVIEWLUT, cmd); - device->BindResource(LIB, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], TEXSLOT_SKYLUMINANCELUT, cmd); - - device->BindResource(LIB, &scene.lightmap, TEXSLOT_GLOBALLIGHTMAP, cmd); - if (scene.decalAtlas.IsValid()) - { - device->BindResource(LIB, &scene.decalAtlas, TEXSLOT_DECALATLAS, cmd); - } + device->BindResource(&depth_history, TEXSLOT_ONDEMAND2, cmd); PostProcessCB cb; cb.xPPResolution.x = desc.Width; @@ -9650,8 +9268,7 @@ void Postprocess_RTReflection( cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; cb.rtreflection_range = range; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(LIB, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); size_t shaderIdentifierSize = device->GetShaderIdentifierSize(); GraphicsDevice::GPUAllocation shadertable_raygen = device->AllocateGPU(shaderIdentifierSize, cmd); @@ -9663,16 +9280,16 @@ void Postprocess_RTReflection( device->WriteShaderIdentifier(&RTPSO_reflection, 2, shadertable_hitgroup.data); DispatchRaysDesc dispatchraysdesc; - dispatchraysdesc.raygeneration.buffer = shadertable_raygen.buffer; + dispatchraysdesc.raygeneration.buffer = &shadertable_raygen.buffer; dispatchraysdesc.raygeneration.offset = shadertable_raygen.offset; dispatchraysdesc.raygeneration.size = shaderIdentifierSize; - dispatchraysdesc.miss.buffer = shadertable_miss.buffer; + dispatchraysdesc.miss.buffer = &shadertable_miss.buffer; dispatchraysdesc.miss.offset = shadertable_miss.offset; dispatchraysdesc.miss.size = shaderIdentifierSize; dispatchraysdesc.miss.stride = shaderIdentifierSize; - dispatchraysdesc.hitgroup.buffer = shadertable_hitgroup.buffer; + dispatchraysdesc.hitgroup.buffer = &shadertable_hitgroup.buffer; dispatchraysdesc.hitgroup.offset = shadertable_hitgroup.offset; dispatchraysdesc.hitgroup.size = shaderIdentifierSize; dispatchraysdesc.hitgroup.stride = shaderIdentifierSize; @@ -9684,12 +9301,12 @@ void Postprocess_RTReflection( &output, &res.rayLengths }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.rayLengths, res.rayLengths.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.rayLengths, res.rayLengths.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -9699,18 +9316,16 @@ void Postprocess_RTReflection( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), - GPUBarrier::Image(&res.rayLengths, IMAGE_LAYOUT_UNORDERED_ACCESS, res.rayLengths.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&res.rayLengths, RESOURCE_STATE_UNORDERED_ACCESS, res.rayLengths.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); - device->BindResource(CS, &gbuffer[GBUFFER_COLOR], TEXSLOT_GBUFFER0, cmd); - device->BindResource(CS, &gbuffer[GBUFFER_NORMAL_ROUGHNESS], TEXSLOT_GBUFFER1, cmd); - device->BindResource(CS, &gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER2, cmd); + device->BindResource(&gbuffer[GBUFFER_PRIMITIVEID], TEXSLOT_GBUFFER0, cmd); + device->BindResource(&gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER1, cmd); int temporal_output = device->GetFrameCount() % 2; int temporal_history = 1 - temporal_output; @@ -9720,20 +9335,20 @@ void Postprocess_RTReflection( device->EventBegin("Temporal pass", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_SSR_TEMPORAL], cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &output, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &res.temporal[temporal_history], TEXSLOT_ONDEMAND1, cmd); - device->BindResource(CS, &depth_history, TEXSLOT_ONDEMAND2, cmd); - device->BindResource(CS, &res.rayLengths, TEXSLOT_ONDEMAND3, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&output, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.temporal[temporal_history], TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&depth_history, TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.rayLengths, TEXSLOT_ONDEMAND3, cmd); const GPUResource* uavs[] = { &res.temporal[temporal_output], }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.temporal[temporal_output], res.temporal[temporal_output].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.temporal[temporal_output], res.temporal[temporal_output].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -9748,12 +9363,11 @@ void Postprocess_RTReflection( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.temporal[temporal_output], IMAGE_LAYOUT_UNORDERED_ACCESS, res.temporal[temporal_output].desc.layout), + GPUBarrier::Image(&res.temporal[temporal_output], RESOURCE_STATE_UNORDERED_ACCESS, res.temporal[temporal_output].desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -9762,17 +9376,17 @@ void Postprocess_RTReflection( device->EventBegin("Median blur pass", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_SSR_MEDIAN], cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &res.temporal[temporal_output], TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&res.temporal[temporal_output], TEXSLOT_ONDEMAND0, cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -9787,12 +9401,11 @@ void Postprocess_RTReflection( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -9807,7 +9420,7 @@ void CreateSSRResources(SSRResources& res, XMUINT2 resolution) desc.Height = resolution.y / 2; desc.Format = FORMAT_R16G16B16A16_FLOAT; desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; device->CreateTexture(&desc, nullptr, &res.texture_raytrace); device->CreateTexture(&desc, nullptr, &res.texture_temporal[0]); device->CreateTexture(&desc, nullptr, &res.texture_temporal[1]); @@ -9830,18 +9443,16 @@ void Postprocess_SSR( device->EventBegin("Postprocess_SSR", cmd); auto range = wiProfiler::BeginRangeGPU("SSR", cmd); - device->UnbindResources(TEXSLOT_RENDERPATH_SSR, 1, cmd); BindCommonResources(cmd); const TextureDesc& input_desc = input.GetDesc(); const TextureDesc& desc = output.GetDesc(); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); - device->BindResource(CS, &gbuffer[GBUFFER_COLOR], TEXSLOT_GBUFFER0, cmd); - device->BindResource(CS, &gbuffer[GBUFFER_NORMAL_ROUGHNESS], TEXSLOT_GBUFFER1, cmd); - device->BindResource(CS, &gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER2, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&gbuffer[GBUFFER_PRIMITIVEID], TEXSLOT_GBUFFER0, cmd); + device->BindResource(&gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER1, cmd); PostProcessCB cb; cb.xPPResolution.x = desc.Width; @@ -9850,25 +9461,24 @@ void Postprocess_SSR( cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; cb.ssr_input_maxmip = float(input_desc.MipLevels - 1); cb.ssr_input_resolution_max = (float)std::max(input_desc.Width, input_desc.Height); - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); // Raytrace pass: { device->EventBegin("Stochastic Raytrace pass", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_SSR_RAYTRACE], cmd); - device->BindResource(CS, &input, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&input, TEXSLOT_ONDEMAND0, cmd); const GPUResource* uavs[] = { &res.texture_raytrace, &res.rayLengths }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_raytrace, res.texture_raytrace.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_raytrace, res.texture_raytrace.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -9883,12 +9493,11 @@ void Postprocess_SSR( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_raytrace, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_raytrace.desc.layout), + GPUBarrier::Image(&res.texture_raytrace, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_raytrace.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -9897,18 +9506,18 @@ void Postprocess_SSR( device->EventBegin("Resolve pass", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_SSR_RESOLVE], cmd); - device->BindResource(CS, &res.texture_raytrace, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &input, TEXSLOT_ONDEMAND1, cmd); - device->BindResource(CS, &depth_history, TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.texture_raytrace, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&input, TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&depth_history, TEXSLOT_ONDEMAND2, cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -9923,12 +9532,11 @@ void Postprocess_SSR( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -9940,19 +9548,19 @@ void Postprocess_SSR( device->EventBegin("Temporal pass", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_SSR_TEMPORAL], cmd); - device->BindResource(CS, &output, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &res.texture_temporal[temporal_history], TEXSLOT_ONDEMAND1, cmd); - device->BindResource(CS, &depth_history, TEXSLOT_ONDEMAND2, cmd); - device->BindResource(CS, &res.rayLengths, TEXSLOT_ONDEMAND3, cmd); + device->BindResource(&output, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.texture_temporal[temporal_history], TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&depth_history, TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.rayLengths, TEXSLOT_ONDEMAND3, cmd); const GPUResource* uavs[] = { &res.texture_temporal[temporal_output], }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_temporal[temporal_output], res.texture_temporal[temporal_output].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_temporal[temporal_output], res.texture_temporal[temporal_output].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -9967,12 +9575,11 @@ void Postprocess_SSR( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_temporal[temporal_output], IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_temporal[temporal_output].desc.layout), + GPUBarrier::Image(&res.texture_temporal[temporal_output], RESOURCE_STATE_UNORDERED_ACCESS, res.texture_temporal[temporal_output].desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -9981,16 +9588,16 @@ void Postprocess_SSR( device->EventBegin("Median blur pass", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_SSR_MEDIAN], cmd); - device->BindResource(CS, &res.texture_temporal[temporal_output], TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.texture_temporal[temporal_output], TEXSLOT_ONDEMAND0, cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -10005,12 +9612,11 @@ void Postprocess_SSR( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -10023,7 +9629,7 @@ void CreateRTShadowResources(RTShadowResources& res, XMUINT2 resolution) desc.Width = resolution.x / 2; desc.Height = resolution.y / 2; desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; desc.Format = FORMAT_R32G32B32A32_UINT; device->CreateTexture(&desc, nullptr, &res.temp); @@ -10080,7 +9686,7 @@ void Postprocess_RTShadow( CommandList cmd ) { - if (!wiRenderer::device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (!device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) return; if (scene.objects.GetCount() <= 0) @@ -10097,7 +9703,7 @@ void Postprocess_RTShadow( device->EventBegin("Raytrace", cmd); - device->BindResource(CS, &scene.TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); + device->BindResource(&scene.TLAS, TEXSLOT_ACCELERATION_STRUCTURE, cmd); PostProcessCB cb; cb.xPPResolution.x = desc.Width; @@ -10105,32 +9711,30 @@ void Postprocess_RTShadow( cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; cb.xPPParams0.w = (float)res.frame; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_RTSHADOW], cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); - device->BindResource(CS, &entityTiles_Opaque, TEXSLOT_RENDERPATH_ENTITYTILES, cmd); + device->BindResource(&entityTiles_Opaque, TEXSLOT_RENDERPATH_ENTITYTILES, cmd); - device->BindResource(CS, &gbuffer[GBUFFER_COLOR], TEXSLOT_GBUFFER0, cmd); - device->BindResource(CS, &gbuffer[GBUFFER_NORMAL_ROUGHNESS], TEXSLOT_GBUFFER1, cmd); - device->BindResource(CS, &gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER2, cmd); + device->BindResource(&gbuffer[GBUFFER_PRIMITIVEID], TEXSLOT_GBUFFER0, cmd); + device->BindResource(&gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER1, cmd); const GPUResource* uavs[] = { &res.temp, &res.normals, &res.tiles }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.temp, res.temp.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.normals, res.normals.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Buffer(&res.tiles, BUFFER_STATE_SHADER_RESOURCE_COMPUTE, BUFFER_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.temp, res.temp.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.normals, res.normals.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Buffer(&res.tiles, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -10145,13 +9749,12 @@ void Postprocess_RTShadow( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.normals, IMAGE_LAYOUT_UNORDERED_ACCESS, res.normals.desc.layout), - GPUBarrier::Buffer(&res.tiles, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE_COMPUTE), + GPUBarrier::Image(&res.normals, RESOURCE_STATE_UNORDERED_ACCESS, res.normals.desc.layout), + GPUBarrier::Buffer(&res.tiles, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); int temporal_output = res.frame % 2; @@ -10162,18 +9765,18 @@ void Postprocess_RTShadow( device->EventBegin("Denoise - Tile Classification", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_RTSHADOW_DENOISE_TILECLASSIFICATION], cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &res.normals, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &depth_history, TEXSLOT_ONDEMAND1, cmd); - device->BindResource(CS, &res.tiles, TEXSLOT_ONDEMAND2, cmd); - device->BindResource(CS, &res.moments[0][temporal_history], TEXSLOT_ONDEMAND3, cmd); - device->BindResource(CS, &res.moments[1][temporal_history], TEXSLOT_ONDEMAND4, cmd); - device->BindResource(CS, &res.moments[2][temporal_history], TEXSLOT_ONDEMAND5, cmd); - device->BindResource(CS, &res.moments[3][temporal_history], TEXSLOT_ONDEMAND6, cmd); - device->BindResource(CS, &res.scratch[0][1], TEXSLOT_ONDEMAND7, cmd); - device->BindResource(CS, &res.scratch[1][1], TEXSLOT_ONDEMAND8, cmd); - device->BindResource(CS, &res.scratch[2][1], TEXSLOT_ONDEMAND9, cmd); - device->BindResource(CS, &res.scratch[3][1], TEXSLOT_ONDEMAND10, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&res.normals, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&depth_history, TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&res.tiles, TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.moments[0][temporal_history], TEXSLOT_ONDEMAND3, cmd); + device->BindResource(&res.moments[1][temporal_history], TEXSLOT_ONDEMAND4, cmd); + device->BindResource(&res.moments[2][temporal_history], TEXSLOT_ONDEMAND5, cmd); + device->BindResource(&res.moments[3][temporal_history], TEXSLOT_ONDEMAND6, cmd); + device->BindResource(&res.scratch[0][1], TEXSLOT_ONDEMAND7, cmd); + device->BindResource(&res.scratch[1][1], TEXSLOT_ONDEMAND8, cmd); + device->BindResource(&res.scratch[2][1], TEXSLOT_ONDEMAND9, cmd); + device->BindResource(&res.scratch[3][1], TEXSLOT_ONDEMAND10, cmd); const GPUResource* uavs[] = { &res.metadata, @@ -10186,19 +9789,19 @@ void Postprocess_RTShadow( &res.moments[2][temporal_output], &res.moments[3][temporal_output], }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Buffer(&res.metadata, BUFFER_STATE_SHADER_RESOURCE_COMPUTE, BUFFER_STATE_UNORDERED_ACCESS), - GPUBarrier::Image(&res.scratch[0][0], res.scratch[0][0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.scratch[1][0], res.scratch[1][0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.scratch[2][0], res.scratch[2][0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.scratch[3][0], res.scratch[3][0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.moments[0][temporal_output], res.moments[0][temporal_output].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.moments[1][temporal_output], res.moments[1][temporal_output].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.moments[2][temporal_output], res.moments[2][temporal_output].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.moments[3][temporal_output], res.moments[3][temporal_output].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Buffer(&res.metadata, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[0][0], res.scratch[0][0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[1][0], res.scratch[1][0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[2][0], res.scratch[2][0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[3][0], res.scratch[3][0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.moments[0][temporal_output], res.moments[0][temporal_output].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.moments[1][temporal_output], res.moments[1][temporal_output].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.moments[2][temporal_output], res.moments[2][temporal_output].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.moments[3][temporal_output], res.moments[3][temporal_output].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -10213,20 +9816,19 @@ void Postprocess_RTShadow( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Buffer(&res.metadata, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE_COMPUTE), - GPUBarrier::Image(&res.scratch[0][0], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[0][0].desc.layout), - GPUBarrier::Image(&res.scratch[1][0], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[1][0].desc.layout), - GPUBarrier::Image(&res.scratch[2][0], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[2][0].desc.layout), - GPUBarrier::Image(&res.scratch[3][0], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[3][0].desc.layout), - GPUBarrier::Image(&res.moments[0][temporal_output], IMAGE_LAYOUT_UNORDERED_ACCESS, res.moments[0][temporal_output].desc.layout), - GPUBarrier::Image(&res.moments[1][temporal_output], IMAGE_LAYOUT_UNORDERED_ACCESS, res.moments[1][temporal_output].desc.layout), - GPUBarrier::Image(&res.moments[2][temporal_output], IMAGE_LAYOUT_UNORDERED_ACCESS, res.moments[2][temporal_output].desc.layout), - GPUBarrier::Image(&res.moments[3][temporal_output], IMAGE_LAYOUT_UNORDERED_ACCESS, res.moments[3][temporal_output].desc.layout), + GPUBarrier::Buffer(&res.metadata, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE_COMPUTE), + GPUBarrier::Image(&res.scratch[0][0], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[0][0].desc.layout), + GPUBarrier::Image(&res.scratch[1][0], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[1][0].desc.layout), + GPUBarrier::Image(&res.scratch[2][0], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[2][0].desc.layout), + GPUBarrier::Image(&res.scratch[3][0], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[3][0].desc.layout), + GPUBarrier::Image(&res.moments[0][temporal_output], RESOURCE_STATE_UNORDERED_ACCESS, res.moments[0][temporal_output].desc.layout), + GPUBarrier::Image(&res.moments[1][temporal_output], RESOURCE_STATE_UNORDERED_ACCESS, res.moments[1][temporal_output].desc.layout), + GPUBarrier::Image(&res.moments[2][temporal_output], RESOURCE_STATE_UNORDERED_ACCESS, res.moments[2][temporal_output].desc.layout), + GPUBarrier::Image(&res.moments[3][temporal_output], RESOURCE_STATE_UNORDERED_ACCESS, res.moments[3][temporal_output].desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -10235,16 +9837,16 @@ void Postprocess_RTShadow( device->EventBegin("Denoise - Filter", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_RTSHADOW_DENOISE_FILTER], cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &res.normals, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &res.metadata, TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&res.normals, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.metadata, TEXSLOT_ONDEMAND1, cmd); // pass0: { - device->BindResource(CS, &res.scratch[0][0], TEXSLOT_ONDEMAND2, cmd); - device->BindResource(CS, &res.scratch[1][0], TEXSLOT_ONDEMAND3, cmd); - device->BindResource(CS, &res.scratch[2][0], TEXSLOT_ONDEMAND4, cmd); - device->BindResource(CS, &res.scratch[3][0], TEXSLOT_ONDEMAND5, cmd); + device->BindResource(&res.scratch[0][0], TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.scratch[1][0], TEXSLOT_ONDEMAND3, cmd); + device->BindResource(&res.scratch[2][0], TEXSLOT_ONDEMAND4, cmd); + device->BindResource(&res.scratch[3][0], TEXSLOT_ONDEMAND5, cmd); const GPUResource* uavs[] = { &res.scratch[0][1], &res.scratch[1][1], @@ -10252,22 +9854,21 @@ void Postprocess_RTShadow( &res.scratch[3][1], &res.denoised }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.scratch[0][1], res.scratch[0][1].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.scratch[1][1], res.scratch[1][1].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.scratch[2][1], res.scratch[2][1].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.scratch[3][1], res.scratch[3][1].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.denoised, res.denoised.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[0][1], res.scratch[0][1].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[1][1], res.scratch[1][1].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[2][1], res.scratch[2][1].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[3][1], res.scratch[3][1].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.denoised, res.denoised.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } cb.xPPParams1.x = 0; cb.xPPParams1.y = 1; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); device->Dispatch( (desc.Width + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, @@ -10279,10 +9880,10 @@ void Postprocess_RTShadow( // pass1: { - device->BindResource(CS, &res.scratch[0][1], TEXSLOT_ONDEMAND2, cmd); - device->BindResource(CS, &res.scratch[1][1], TEXSLOT_ONDEMAND3, cmd); - device->BindResource(CS, &res.scratch[2][1], TEXSLOT_ONDEMAND4, cmd); - device->BindResource(CS, &res.scratch[3][1], TEXSLOT_ONDEMAND5, cmd); + device->BindResource(&res.scratch[0][1], TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.scratch[1][1], TEXSLOT_ONDEMAND3, cmd); + device->BindResource(&res.scratch[2][1], TEXSLOT_ONDEMAND4, cmd); + device->BindResource(&res.scratch[3][1], TEXSLOT_ONDEMAND5, cmd); const GPUResource* uavs[] = { &res.scratch[0][0], &res.scratch[1][0], @@ -10290,26 +9891,25 @@ void Postprocess_RTShadow( &res.scratch[3][0], &res.denoised }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.scratch[0][1], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[0][1].desc.layout), - GPUBarrier::Image(&res.scratch[1][1], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[1][1].desc.layout), - GPUBarrier::Image(&res.scratch[2][1], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[2][1].desc.layout), - GPUBarrier::Image(&res.scratch[3][1], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[3][1].desc.layout), - GPUBarrier::Image(&res.scratch[0][0], res.scratch[0][0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.scratch[1][0], res.scratch[1][0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.scratch[2][0], res.scratch[2][0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.scratch[3][0], res.scratch[3][0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[0][1], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[0][1].desc.layout), + GPUBarrier::Image(&res.scratch[1][1], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[1][1].desc.layout), + GPUBarrier::Image(&res.scratch[2][1], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[2][1].desc.layout), + GPUBarrier::Image(&res.scratch[3][1], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[3][1].desc.layout), + GPUBarrier::Image(&res.scratch[0][0], res.scratch[0][0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[1][0], res.scratch[1][0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[2][0], res.scratch[2][0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[3][0], res.scratch[3][0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } cb.xPPParams1.x = 1; cb.xPPParams1.y = 2; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); device->Dispatch( (desc.Width + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, @@ -10321,10 +9921,10 @@ void Postprocess_RTShadow( // pass2: { - device->BindResource(CS, &res.scratch[0][0], TEXSLOT_ONDEMAND2, cmd); - device->BindResource(CS, &res.scratch[1][0], TEXSLOT_ONDEMAND3, cmd); - device->BindResource(CS, &res.scratch[2][0], TEXSLOT_ONDEMAND4, cmd); - device->BindResource(CS, &res.scratch[3][0], TEXSLOT_ONDEMAND5, cmd); + device->BindResource(&res.scratch[0][0], TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.scratch[1][0], TEXSLOT_ONDEMAND3, cmd); + device->BindResource(&res.scratch[2][0], TEXSLOT_ONDEMAND4, cmd); + device->BindResource(&res.scratch[3][0], TEXSLOT_ONDEMAND5, cmd); const GPUResource* uavs[] = { &res.scratch[0][1], &res.scratch[1][1], @@ -10332,26 +9932,25 @@ void Postprocess_RTShadow( &res.scratch[3][1], &res.denoised }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.scratch[0][0], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[0][0].desc.layout), - GPUBarrier::Image(&res.scratch[1][0], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[1][0].desc.layout), - GPUBarrier::Image(&res.scratch[2][0], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[2][0].desc.layout), - GPUBarrier::Image(&res.scratch[3][0], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[3][0].desc.layout), - GPUBarrier::Image(&res.scratch[0][1], res.scratch[0][0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.scratch[1][1], res.scratch[1][0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.scratch[2][1], res.scratch[2][0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.scratch[3][1], res.scratch[3][0].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[0][0], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[0][0].desc.layout), + GPUBarrier::Image(&res.scratch[1][0], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[1][0].desc.layout), + GPUBarrier::Image(&res.scratch[2][0], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[2][0].desc.layout), + GPUBarrier::Image(&res.scratch[3][0], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[3][0].desc.layout), + GPUBarrier::Image(&res.scratch[0][1], res.scratch[0][0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[1][1], res.scratch[1][0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[2][1], res.scratch[2][0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.scratch[3][1], res.scratch[3][0].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } cb.xPPParams1.x = 2; cb.xPPParams1.y = 4; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); device->Dispatch( (desc.Width + POSTPROCESS_BLOCKSIZE - 1) / POSTPROCESS_BLOCKSIZE, @@ -10364,16 +9963,15 @@ void Postprocess_RTShadow( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.scratch[0][1], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[0][1].desc.layout), - GPUBarrier::Image(&res.scratch[1][1], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[1][1].desc.layout), - GPUBarrier::Image(&res.scratch[2][1], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[2][1].desc.layout), - GPUBarrier::Image(&res.scratch[3][1], IMAGE_LAYOUT_UNORDERED_ACCESS, res.scratch[3][1].desc.layout), - GPUBarrier::Image(&res.denoised, IMAGE_LAYOUT_UNORDERED_ACCESS, res.denoised.desc.layout), + GPUBarrier::Image(&res.scratch[0][1], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[0][1].desc.layout), + GPUBarrier::Image(&res.scratch[1][1], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[1][1].desc.layout), + GPUBarrier::Image(&res.scratch[2][1], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[2][1].desc.layout), + GPUBarrier::Image(&res.scratch[3][1], RESOURCE_STATE_UNORDERED_ACCESS, res.scratch[3][1].desc.layout), + GPUBarrier::Image(&res.denoised, RESOURCE_STATE_UNORDERED_ACCESS, res.denoised.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } res.frame++; @@ -10383,23 +9981,23 @@ void Postprocess_RTShadow( device->EventBegin("Temporal Denoise", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_RTSHADOW_DENOISE_TEMPORAL], cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &res.temp, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &res.temporal[temporal_history], TEXSLOT_ONDEMAND1, cmd); - device->BindResource(CS, &depth_history, TEXSLOT_ONDEMAND2, cmd); - device->BindResource(CS, &res.denoised, TEXSLOT_ONDEMAND3, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&res.temp, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.temporal[temporal_history], TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&depth_history, TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.denoised, TEXSLOT_ONDEMAND3, cmd); const GPUResource* uavs[] = { &res.temporal[temporal_output], &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.temp, IMAGE_LAYOUT_UNORDERED_ACCESS, res.temp.desc.layout), - GPUBarrier::Image(&res.temporal[temporal_output], res.temporal[temporal_output].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.temp, RESOURCE_STATE_UNORDERED_ACCESS, res.temp.desc.layout), + GPUBarrier::Image(&res.temporal[temporal_output], res.temporal[temporal_output].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -10414,13 +10012,12 @@ void Postprocess_RTShadow( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.temporal[temporal_output], IMAGE_LAYOUT_UNORDERED_ACCESS, res.temporal[temporal_output].desc.layout), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&res.temporal[temporal_output], RESOURCE_STATE_UNORDERED_ACCESS, res.temporal[temporal_output].desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -10435,6 +10032,7 @@ void Postprocess_ScreenSpaceShadow( const Texture& depthbuffer, const Texture& lineardepth, const GPUBuffer& entityTiles_Opaque, + const Texture gbuffer[GBUFFER_COUNT], const Texture& output, CommandList cmd, float range, @@ -10453,24 +10051,26 @@ void Postprocess_ScreenSpaceShadow( cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; cb.xPPParams0.x = range; cb.xPPParams0.y = (float)samplecount; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_SCREENSPACESHADOW], cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); - device->BindResource(CS, &entityTiles_Opaque, TEXSLOT_RENDERPATH_ENTITYTILES, cmd); + device->BindResource(&entityTiles_Opaque, TEXSLOT_RENDERPATH_ENTITYTILES, cmd); + + device->BindResource(&gbuffer[GBUFFER_PRIMITIVEID], TEXSLOT_GBUFFER0, cmd); + device->BindResource(&gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER1, cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -10485,12 +10085,11 @@ void Postprocess_ScreenSpaceShadow( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); wiProfiler::EndRange(prof_range); device->EventEnd(cmd); @@ -10507,7 +10106,7 @@ void Postprocess_LightShafts( device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_LIGHTSHAFTS], cmd); - device->BindResource(CS, &input, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&input, TEXSLOT_ONDEMAND0, cmd); const TextureDesc& desc = output.GetDesc(); @@ -10522,17 +10121,16 @@ void Postprocess_LightShafts( cb.xPPParams0.w = 0.2f; // exposure cb.xPPParams1.x = center.x; cb.xPPParams1.y = center.y; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -10547,12 +10145,11 @@ void Postprocess_LightShafts( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); wiProfiler::EndRange(range); device->EventEnd(cmd); @@ -10595,7 +10192,7 @@ void CreateDepthOfFieldResources(DepthOfFieldResources& res, XMUINT2 resolution) bufferdesc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; bufferdesc.ByteWidth = TILE_STATISTICS_CAPACITY * sizeof(uint); - bufferdesc.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS | RESOURCE_MISC_INDIRECT_ARGS; + bufferdesc.MiscFlags = RESOURCE_MISC_BUFFER_RAW | RESOURCE_MISC_INDIRECT_ARGS; device->CreateBuffer(&bufferdesc, nullptr, &res.buffer_tile_statistics); bufferdesc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; @@ -10618,7 +10215,7 @@ void Postprocess_DepthOfField( device->EventBegin("Postprocess_DepthOfField", cmd); auto range = wiProfiler::BeginRangeGPU("Depth of Field", cmd); - device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); const TextureDesc& desc = output.GetDesc(); @@ -10629,8 +10226,7 @@ void Postprocess_DepthOfField( cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; cb.dof_cocscale = coc_scale; cb.dof_maxcoc = max_coc; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); // Compute tile max COC (horizontal): { @@ -10641,12 +10237,12 @@ void Postprocess_DepthOfField( &res.texture_tilemax_horizontal, &res.texture_tilemin_horizontal, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_tilemax_horizontal, res.texture_tilemax_horizontal.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_tilemin_horizontal, res.texture_tilemin_horizontal.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_tilemax_horizontal, res.texture_tilemax_horizontal.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_tilemin_horizontal, res.texture_tilemin_horizontal.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -10661,13 +10257,12 @@ void Postprocess_DepthOfField( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_tilemax_horizontal, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_tilemax_horizontal.desc.layout), - GPUBarrier::Image(&res.texture_tilemin_horizontal, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_tilemin_horizontal.desc.layout), + GPUBarrier::Image(&res.texture_tilemax_horizontal, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_tilemax_horizontal.desc.layout), + GPUBarrier::Image(&res.texture_tilemin_horizontal, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_tilemin_horizontal.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -10680,18 +10275,18 @@ void Postprocess_DepthOfField( &res.texture_tilemax_horizontal, &res.texture_tilemin_horizontal }; - device->BindResources(CS, resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); + device->BindResources(resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); const GPUResource* uavs[] = { &res.texture_tilemax, &res.texture_tilemin, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_tilemax, res.texture_tilemax.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_tilemin, res.texture_tilemin.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_tilemax, res.texture_tilemax.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_tilemin, res.texture_tilemin.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -10706,13 +10301,12 @@ void Postprocess_DepthOfField( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_tilemax, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_tilemax.desc.layout), - GPUBarrier::Image(&res.texture_tilemin, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_tilemin.desc.layout), + GPUBarrier::Image(&res.texture_tilemax, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_tilemax.desc.layout), + GPUBarrier::Image(&res.texture_tilemin, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_tilemin.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -10725,7 +10319,7 @@ void Postprocess_DepthOfField( &res.texture_tilemax, &res.texture_tilemin }; - device->BindResources(CS, resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); + device->BindResources(resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); const GPUResource* uavs[] = { &res.buffer_tile_statistics, @@ -10734,11 +10328,11 @@ void Postprocess_DepthOfField( &res.buffer_tiles_expensive, &res.texture_neighborhoodmax }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_neighborhoodmax, res.texture_neighborhoodmax.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_neighborhoodmax, res.texture_neighborhoodmax.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -10753,12 +10347,11 @@ void Postprocess_DepthOfField( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_neighborhoodmax, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_neighborhoodmax.desc.layout), + GPUBarrier::Image(&res.texture_neighborhoodmax, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_neighborhoodmax.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -10767,7 +10360,7 @@ void Postprocess_DepthOfField( device->EventBegin("Kickjobs", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_KICKJOBS], cmd); - device->BindResource(CS, &res.texture_tilemax, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.texture_tilemax, TEXSLOT_ONDEMAND0, cmd); const GPUResource* uavs[] = { &res.buffer_tile_statistics, @@ -10775,17 +10368,16 @@ void Postprocess_DepthOfField( &res.buffer_tiles_cheap, &res.buffer_tiles_expensive }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); device->Dispatch(1, 1, 1, cmd); GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Buffer(&res.buffer_tile_statistics, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_INDIRECT_ARGUMENT), + GPUBarrier::Buffer(&res.buffer_tile_statistics, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_INDIRECT_ARGUMENT), }; device->Barrier(barriers, arraysize(barriers), cmd); - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -10794,8 +10386,7 @@ void Postprocess_DepthOfField( cb.xPPResolution.y = desc.Height / 2; cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); // Prepass: { @@ -10805,47 +10396,46 @@ void Postprocess_DepthOfField( &input, &res.texture_neighborhoodmax, }; - device->BindResources(CS, resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); + device->BindResources(resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); const GPUResource* uavs[] = { &res.texture_presort, &res.texture_prefilter }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Buffer(&res.buffer_tiles_earlyexit, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), - GPUBarrier::Buffer(&res.buffer_tiles_cheap, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), - GPUBarrier::Buffer(&res.buffer_tiles_expensive, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), - GPUBarrier::Image(&res.texture_presort, res.texture_presort.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_prefilter, res.texture_prefilter.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Buffer(&res.buffer_tiles_earlyexit, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&res.buffer_tiles_cheap, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&res.buffer_tiles_expensive, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Image(&res.texture_presort, res.texture_presort.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_prefilter, res.texture_prefilter.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->BindResource(CS, &res.buffer_tiles_earlyexit, TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.buffer_tiles_earlyexit, TEXSLOT_ONDEMAND2, cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_PREPASS_EARLYEXIT], cmd); device->DispatchIndirect(&res.buffer_tile_statistics, INDIRECT_OFFSET_EARLYEXIT, cmd); - device->BindResource(CS, &res.buffer_tiles_cheap, TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.buffer_tiles_cheap, TEXSLOT_ONDEMAND2, cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_PREPASS], cmd); device->DispatchIndirect(&res.buffer_tile_statistics, INDIRECT_OFFSET_CHEAP, cmd); - device->BindResource(CS, &res.buffer_tiles_expensive, TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.buffer_tiles_expensive, TEXSLOT_ONDEMAND2, cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_DEPTHOFFIELD_PREPASS], cmd); device->DispatchIndirect(&res.buffer_tile_statistics, INDIRECT_OFFSET_EXPENSIVE, cmd); { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_presort, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_presort.desc.layout), - GPUBarrier::Image(&res.texture_prefilter, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_prefilter.desc.layout), + GPUBarrier::Image(&res.texture_presort, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_presort.desc.layout), + GPUBarrier::Image(&res.texture_prefilter, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_prefilter.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -10861,18 +10451,18 @@ void Postprocess_DepthOfField( &res.buffer_tiles_cheap, &res.buffer_tiles_expensive }; - device->BindResources(CS, resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); + device->BindResources(resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); const GPUResource* uavs[] = { &res.texture_main, &res.texture_alpha1 }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_main, res.texture_main.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_alpha1, res.texture_alpha1.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_main, res.texture_main.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_alpha1, res.texture_alpha1.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -10889,13 +10479,12 @@ void Postprocess_DepthOfField( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_main, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_main.desc.layout), - GPUBarrier::Image(&res.texture_alpha1, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_alpha1.desc.layout), + GPUBarrier::Image(&res.texture_main, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_main.desc.layout), + GPUBarrier::Image(&res.texture_alpha1, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_alpha1.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -10908,18 +10497,18 @@ void Postprocess_DepthOfField( &res.texture_main, &res.texture_alpha1 }; - device->BindResources(CS, resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); + device->BindResources(resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); const GPUResource* uavs[] = { &res.texture_postfilter, &res.texture_alpha2 }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_postfilter, res.texture_postfilter.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_alpha2, res.texture_alpha2.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_postfilter, res.texture_postfilter.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_alpha2, res.texture_alpha2.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -10934,13 +10523,12 @@ void Postprocess_DepthOfField( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_postfilter, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_postfilter.desc.layout), - GPUBarrier::Image(&res.texture_alpha2, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_alpha2.desc.layout), + GPUBarrier::Image(&res.texture_postfilter, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_postfilter.desc.layout), + GPUBarrier::Image(&res.texture_alpha2, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_alpha2.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -10949,8 +10537,7 @@ void Postprocess_DepthOfField( cb.xPPResolution.y = desc.Height; cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); // Upsample pass: { @@ -10963,16 +10550,16 @@ void Postprocess_DepthOfField( &res.texture_alpha2, &res.texture_neighborhoodmax }; - device->BindResources(CS, resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); + device->BindResources(resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -10987,12 +10574,11 @@ void Postprocess_DepthOfField( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -11012,7 +10598,7 @@ void Postprocess_Outline( device->BindPipelineState(&PSO_outline, cmd); - device->BindResource(PS, &input, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&input, TEXSLOT_ONDEMAND0, cmd); PostProcessCB cb; cb.xPPResolution.x = (uint)input.GetDesc().Width; @@ -11025,8 +10611,7 @@ void Postprocess_Outline( cb.xPPParams1.y = color.y; cb.xPPParams1.z = color.z; cb.xPPParams1.w = color.w; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); device->Draw(3, 0, cmd); @@ -11054,7 +10639,7 @@ void CreateMotionBlurResources(MotionBlurResources& res, XMUINT2 resolution) bufferdesc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; bufferdesc.ByteWidth = TILE_STATISTICS_CAPACITY * sizeof(uint); - bufferdesc.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS | RESOURCE_MISC_INDIRECT_ARGS; + bufferdesc.MiscFlags = RESOURCE_MISC_BUFFER_RAW | RESOURCE_MISC_INDIRECT_ARGS; device->CreateBuffer(&bufferdesc, nullptr, &res.buffer_tile_statistics); bufferdesc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; @@ -11077,8 +10662,8 @@ void Postprocess_MotionBlur( device->EventBegin("Postprocess_MotionBlur", cmd); auto range = wiProfiler::BeginRangeGPU("MotionBlur", cmd); - device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); - device->BindResource(CS, &gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER2, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER1, cmd); const TextureDesc& desc = output.GetDesc(); @@ -11088,8 +10673,7 @@ void Postprocess_MotionBlur( cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; cb.motionblur_strength = strength; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); // Compute tile max velocities (horizontal): { @@ -11100,12 +10684,12 @@ void Postprocess_MotionBlur( &res.texture_tilemax_horizontal, &res.texture_tilemin_horizontal, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_tilemax_horizontal, res.texture_tilemax_horizontal.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_tilemin_horizontal, res.texture_tilemin_horizontal.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_tilemax_horizontal, res.texture_tilemax_horizontal.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_tilemin_horizontal, res.texture_tilemin_horizontal.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -11120,13 +10704,12 @@ void Postprocess_MotionBlur( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_tilemax_horizontal, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_tilemax_horizontal.desc.layout), - GPUBarrier::Image(&res.texture_tilemin_horizontal, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_tilemin_horizontal.desc.layout), + GPUBarrier::Image(&res.texture_tilemax_horizontal, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_tilemax_horizontal.desc.layout), + GPUBarrier::Image(&res.texture_tilemin_horizontal, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_tilemin_horizontal.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -11135,18 +10718,18 @@ void Postprocess_MotionBlur( device->EventBegin("TileMax - Vertical", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_MOTIONBLUR_TILEMAXVELOCITY_VERTICAL], cmd); - device->BindResource(CS, &res.texture_tilemax_horizontal, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.texture_tilemax_horizontal, TEXSLOT_ONDEMAND0, cmd); const GPUResource* uavs[] = { &res.texture_tilemax, &res.texture_tilemin, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_tilemax, res.texture_tilemax.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_tilemin, res.texture_tilemin.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_tilemax, res.texture_tilemax.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_tilemin, res.texture_tilemin.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -11161,13 +10744,12 @@ void Postprocess_MotionBlur( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_tilemax, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_tilemax.desc.layout), - GPUBarrier::Image(&res.texture_tilemin, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_tilemin.desc.layout), + GPUBarrier::Image(&res.texture_tilemax, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_tilemax.desc.layout), + GPUBarrier::Image(&res.texture_tilemin, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_tilemin.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -11180,7 +10762,7 @@ void Postprocess_MotionBlur( &res.texture_tilemax, &res.texture_tilemin }; - device->BindResources(CS, resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); + device->BindResources(resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); const GPUResource* uavs[] = { &res.buffer_tile_statistics, @@ -11189,11 +10771,11 @@ void Postprocess_MotionBlur( &res.buffer_tiles_expensive, &res.texture_neighborhoodmax }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_neighborhoodmax, res.texture_neighborhoodmax.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_neighborhoodmax, res.texture_neighborhoodmax.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -11208,12 +10790,11 @@ void Postprocess_MotionBlur( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_neighborhoodmax, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_neighborhoodmax.desc.layout), + GPUBarrier::Image(&res.texture_neighborhoodmax, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_neighborhoodmax.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -11222,7 +10803,7 @@ void Postprocess_MotionBlur( device->EventBegin("Kickjobs", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_MOTIONBLUR_KICKJOBS], cmd); - device->BindResource(CS, &res.texture_tilemax, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.texture_tilemax, TEXSLOT_ONDEMAND0, cmd); const GPUResource* uavs[] = { &res.buffer_tile_statistics, @@ -11230,17 +10811,16 @@ void Postprocess_MotionBlur( &res.buffer_tiles_cheap, &res.buffer_tiles_expensive }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); device->Dispatch(1, 1, 1, cmd); GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Buffer(&res.buffer_tile_statistics, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_INDIRECT_ARGUMENT), + GPUBarrier::Buffer(&res.buffer_tile_statistics, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_INDIRECT_ARGUMENT), }; device->Barrier(barriers, arraysize(barriers), cmd); - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -11255,19 +10835,19 @@ void Postprocess_MotionBlur( &res.buffer_tiles_cheap, &res.buffer_tiles_expensive, }; - device->BindResources(CS, resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); + device->BindResources(resarray, TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Buffer(&res.buffer_tiles_earlyexit, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), - GPUBarrier::Buffer(&res.buffer_tiles_cheap, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), - GPUBarrier::Buffer(&res.buffer_tiles_expensive, BUFFER_STATE_UNORDERED_ACCESS, BUFFER_STATE_SHADER_RESOURCE), - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Buffer(&res.buffer_tiles_earlyexit, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&res.buffer_tiles_cheap, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Buffer(&res.buffer_tiles_expensive, RESOURCE_STATE_UNORDERED_ACCESS, RESOURCE_STATE_SHADER_RESOURCE), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -11284,13 +10864,11 @@ void Postprocess_MotionBlur( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); - device->UnbindResources(TEXSLOT_ONDEMAND0, arraysize(resarray), cmd); device->EventEnd(cmd); } @@ -11346,21 +10924,20 @@ void Postprocess_Bloom( cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; cb.xPPParams0.x = threshold; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_BLOOMSEPARATE], cmd); - device->BindResource(CS, &input, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&input, TEXSLOT_ONDEMAND0, cmd); const GPUResource* uavs[] = { &res.texture_bloom, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_bloom, res.texture_bloom.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_bloom, res.texture_bloom.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -11375,12 +10952,11 @@ void Postprocess_Bloom( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_bloom, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_bloom.desc.layout), + GPUBarrier::Image(&res.texture_bloom, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_bloom.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -11402,22 +10978,21 @@ void Postprocess_Bloom( cb.xPPResolution.y = desc.Height; cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_BLOOMCOMBINE], cmd); - device->BindResource(CS, &input, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &res.texture_bloom, TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&input, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.texture_bloom, TEXSLOT_ONDEMAND1, cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -11432,12 +11007,11 @@ void Postprocess_Bloom( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -11455,7 +11029,7 @@ void CreateVolumetricCloudResources(VolumetricCloudResources& res, XMUINT2 resol desc.Width = renderResolution.x; desc.Height = renderResolution.y; desc.Format = FORMAT_R16G16B16A16_FLOAT; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE_COMPUTE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE_COMPUTE; device->CreateTexture(&desc, nullptr, &res.texture_cloudRender); device->SetName(&res.texture_cloudRender, "texture_cloudRender"); desc.Format = FORMAT_R16G16_FLOAT; @@ -11508,32 +11082,31 @@ void Postprocess_VolumetricClouds( cb.xPPParams0.y = (float)res.texture_reproject[0].GetDesc().Height; cb.xPPParams0.z = 1.0f / cb.xPPParams0.x; cb.xPPParams0.w = 1.0f / cb.xPPParams0.y; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); // Cloud pass: { device->EventBegin("Volumetric Cloud Rendering", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_VOLUMETRICCLOUDS_RENDER], cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &texture_shapeNoise, TEXSLOT_ONDEMAND1, cmd); - device->BindResource(CS, &texture_detailNoise, TEXSLOT_ONDEMAND2, cmd); - device->BindResource(CS, &texture_curlNoise, TEXSLOT_ONDEMAND3, cmd); - device->BindResource(CS, &texture_weatherMap, TEXSLOT_ONDEMAND4, cmd); - device->BindResource(CS, &textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_TRANSMITTANCELUT, cmd); - device->BindResource(CS, &textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], TEXSLOT_SKYLUMINANCELUT, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&texture_shapeNoise, TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&texture_detailNoise, TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&texture_curlNoise, TEXSLOT_ONDEMAND3, cmd); + device->BindResource(&texture_weatherMap, TEXSLOT_ONDEMAND4, cmd); + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_TRANSMITTANCELUT], TEXSLOT_TRANSMITTANCELUT, cmd); + device->BindResource(&textures[TEXTYPE_2D_SKYATMOSPHERE_SKYLUMINANCELUT], TEXSLOT_SKYLUMINANCELUT, cmd); const GPUResource* uavs[] = { &res.texture_cloudRender, &res.texture_cloudDepth, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_cloudRender, res.texture_cloudRender.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_cloudDepth, res.texture_cloudDepth.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_cloudRender, res.texture_cloudRender.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_cloudDepth, res.texture_cloudDepth.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -11548,13 +11121,12 @@ void Postprocess_VolumetricClouds( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_cloudRender, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_cloudRender.desc.layout), - GPUBarrier::Image(&res.texture_cloudDepth, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_cloudDepth.desc.layout), + GPUBarrier::Image(&res.texture_cloudRender, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_cloudRender.desc.layout), + GPUBarrier::Image(&res.texture_cloudDepth, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_cloudDepth.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -11563,8 +11135,7 @@ void Postprocess_VolumetricClouds( cb.xPPResolution.y = reprojection_desc.Height; cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); int temporal_output = device->GetFrameCount() % 2; int temporal_history = 1 - temporal_output; @@ -11574,22 +11145,22 @@ void Postprocess_VolumetricClouds( device->EventBegin("Volumetric Cloud Reproject", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_VOLUMETRICCLOUDS_REPROJECT], cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &res.texture_cloudRender, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &res.texture_cloudDepth, TEXSLOT_ONDEMAND1, cmd); - device->BindResource(CS, &res.texture_reproject[temporal_history], TEXSLOT_ONDEMAND2, cmd); - device->BindResource(CS, &res.texture_reproject_depth[temporal_history], TEXSLOT_ONDEMAND3, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&res.texture_cloudRender, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.texture_cloudDepth, TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&res.texture_reproject[temporal_history], TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&res.texture_reproject_depth[temporal_history], TEXSLOT_ONDEMAND3, cmd); const GPUResource* uavs[] = { &res.texture_reproject[temporal_output], &res.texture_reproject_depth[temporal_output], }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_reproject[temporal_output], res.texture_reproject[temporal_output].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_reproject_depth[temporal_output], res.texture_reproject_depth[temporal_output].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_reproject[temporal_output], res.texture_reproject[temporal_output].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_reproject_depth[temporal_output], res.texture_reproject_depth[temporal_output].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -11604,13 +11175,12 @@ void Postprocess_VolumetricClouds( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_reproject[temporal_output], IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_reproject[temporal_output].desc.layout), - GPUBarrier::Image(&res.texture_reproject_depth[temporal_output], IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_reproject_depth[temporal_output].desc.layout), + GPUBarrier::Image(&res.texture_reproject[temporal_output], RESOURCE_STATE_UNORDERED_ACCESS, res.texture_reproject[temporal_output].desc.layout), + GPUBarrier::Image(&res.texture_reproject_depth[temporal_output], RESOURCE_STATE_UNORDERED_ACCESS, res.texture_reproject_depth[temporal_output].desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -11619,21 +11189,21 @@ void Postprocess_VolumetricClouds( device->EventBegin("Volumetric Cloud Temporal", cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_VOLUMETRICCLOUDS_TEMPORAL], cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); - device->BindResource(CS, &res.texture_reproject[temporal_output], TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &res.texture_reproject_depth[temporal_output], TEXSLOT_ONDEMAND1, cmd); - device->BindResource(CS, &res.texture_temporal[temporal_history], TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&res.texture_reproject[temporal_output], TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&res.texture_reproject_depth[temporal_output], TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&res.texture_temporal[temporal_history], TEXSLOT_ONDEMAND2, cmd); const GPUResource* uavs[] = { &res.texture_temporal[temporal_output], &res.texture_cloudMask, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&res.texture_temporal[temporal_output], res.texture_temporal[temporal_output].desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&res.texture_cloudMask, res.texture_cloudMask.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_temporal[temporal_output], res.texture_temporal[temporal_output].desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), + GPUBarrier::Image(&res.texture_cloudMask, res.texture_cloudMask.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -11648,13 +11218,12 @@ void Postprocess_VolumetricClouds( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&res.texture_temporal[temporal_output], IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_temporal[temporal_output].desc.layout), - GPUBarrier::Image(&res.texture_cloudMask, IMAGE_LAYOUT_UNORDERED_ACCESS, res.texture_cloudMask.desc.layout), + GPUBarrier::Image(&res.texture_temporal[temporal_output], RESOURCE_STATE_UNORDERED_ACCESS, res.texture_temporal[temporal_output].desc.layout), + GPUBarrier::Image(&res.texture_cloudMask, RESOURCE_STATE_UNORDERED_ACCESS, res.texture_cloudMask.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -11672,7 +11241,7 @@ void Postprocess_FXAA( device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_FXAA], cmd); - device->BindResource(CS, &input, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&input, TEXSLOT_ONDEMAND0, cmd); const TextureDesc& desc = output.GetDesc(); @@ -11681,17 +11250,16 @@ void Postprocess_FXAA( cb.xPPResolution.y = desc.Height; cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -11706,12 +11274,11 @@ void Postprocess_FXAA( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); wiProfiler::EndRange(range); device->EventEnd(cmd); @@ -11731,11 +11298,11 @@ void Postprocess_TemporalAA( device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_TEMPORALAA], cmd); - device->BindResource(CS, &input_current, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &input_history, TEXSLOT_ONDEMAND1, cmd); - device->BindResource(CS, &depth_history, TEXSLOT_ONDEMAND2, cmd); - device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); - device->BindResource(CS, &gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER2, cmd); + device->BindResource(&input_current, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&input_history, TEXSLOT_ONDEMAND1, cmd); + device->BindResource(&depth_history, TEXSLOT_ONDEMAND2, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&gbuffer[GBUFFER_VELOCITY], TEXSLOT_GBUFFER1, cmd); const TextureDesc& desc = output.GetDesc(); @@ -11744,17 +11311,16 @@ void Postprocess_TemporalAA( cb.xPPResolution.y = desc.Height; cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -11769,81 +11335,11 @@ void Postprocess_TemporalAA( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); - - wiProfiler::EndRange(range); - device->EventEnd(cmd); -} -void Postprocess_DepthPyramid( - const Texture& depthbuffer, - const Texture& lineardepth, - CommandList cmd -) -{ - device->EventBegin("Postprocess_DepthPyramid", cmd); - auto range = wiProfiler::BeginRangeGPU("Depth Pyramid", cmd); - - BindCommonResources(cmd); - - const TextureDesc& desc = lineardepth.GetDesc(); - - PostProcessCB cb; - cb.xPPResolution.x = desc.Width / 2; // downsample res - cb.xPPResolution.y = desc.Height / 2; // downsample res - cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; - cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; - cb.xPPParams0.x = (float)depthbuffer.GetDesc().Width; - cb.xPPParams0.y = (float)depthbuffer.GetDesc().Height; - cb.xPPParams0.z = 1.0f / cb.xPPParams0.x; - cb.xPPParams0.w = 1.0f / cb.xPPParams0.y; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); - - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd, 0); // full res native depth - - device->BindUAV(CS, &lineardepth, 0, cmd, 0); // full res linear depth - device->BindUAV(CS, &lineardepth, 1, cmd, 1); // 2x downsample linear depth - device->BindUAV(CS, &lineardepth, 2, cmd, 2); // 4x downsample linear depth - device->BindUAV(CS, &lineardepth, 3, cmd, 3); // 8x downsample linear depth - device->BindUAV(CS, &lineardepth, 4, cmd, 4); // 16x downsample linear depth - device->BindUAV(CS, &lineardepth, 5, cmd, 5); // 32x downsample linear depth - - device->BindUAV(CS, &depthbuffer, 6, cmd, 1); // 2x downsample native depth - device->BindUAV(CS, &depthbuffer, 7, cmd, 2); // 4x downsample native depth - - { - GPUBarrier barriers[] = { - GPUBarrier::Image(&lineardepth, lineardepth.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), - GPUBarrier::Image(&depthbuffer, depthbuffer.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS, 1), - GPUBarrier::Image(&depthbuffer, depthbuffer.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS, 2), - }; - device->Barrier(barriers, arraysize(barriers), cmd); - } - - device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_LINEARDEPTH], cmd); - device->Dispatch( - (desc.Width + POSTPROCESS_LINEARDEPTH_BLOCKSIZE - 1) / POSTPROCESS_LINEARDEPTH_BLOCKSIZE, - (desc.Height + POSTPROCESS_LINEARDEPTH_BLOCKSIZE - 1) / POSTPROCESS_LINEARDEPTH_BLOCKSIZE, - 1, - cmd - ); - - { - GPUBarrier barriers[] = { - GPUBarrier::Memory(), - GPUBarrier::Image(&lineardepth, IMAGE_LAYOUT_UNORDERED_ACCESS, lineardepth.desc.layout), - GPUBarrier::Image(&depthbuffer, IMAGE_LAYOUT_UNORDERED_ACCESS, depthbuffer.desc.layout, 1), - GPUBarrier::Image(&depthbuffer, IMAGE_LAYOUT_UNORDERED_ACCESS, depthbuffer.desc.layout, 2), - }; - device->Barrier(barriers, arraysize(barriers), cmd); - } - - device->UnbindUAVs(0, 8, cmd); wiProfiler::EndRange(range); device->EventEnd(cmd); @@ -11859,7 +11355,7 @@ void Postprocess_Sharpen( device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_SHARPEN], cmd); - device->BindResource(CS, &input, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&input, TEXSLOT_ONDEMAND0, cmd); const TextureDesc& desc = output.GetDesc(); @@ -11869,17 +11365,16 @@ void Postprocess_Sharpen( cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; cb.xPPParams0.x = amount; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -11894,12 +11389,11 @@ void Postprocess_Sharpen( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -11935,44 +11429,21 @@ void Postprocess_Tonemap( assert(texture_colorgradinglut == nullptr || texture_colorgradinglut->desc.type == TextureDesc::TEXTURE_3D); // This must be a 3D lut - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS)) - { - PushConstantsTonemap push = {}; - push.xPPResolution_rcp = cb.xPPResolution_rcp; - push.exposure = cb.tonemap_exposure; - push.dither = cb.tonemap_dither; - push.eyeadaptionkey = cb.tonemap_eyeadaptionkey; - push.texture_input = device->GetDescriptorIndex(&input, SRV); - push.texture_input_luminance = device->GetDescriptorIndex(texture_luminance, SRV); - push.texture_input_distortion = device->GetDescriptorIndex(texture_distortion, SRV); - push.texture_colorgrade_lookuptable = device->GetDescriptorIndex(texture_colorgradinglut, SRV); - push.texture_output = device->GetDescriptorIndex(&output, UAV); - device->PushConstants(&push, sizeof(push), cmd); - } - else - { - device->UnbindResources(TEXSLOT_ONDEMAND0, 4, cmd); - - device->BindResource(CS, &input, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, texture_luminance, TEXSLOT_ONDEMAND1, cmd); - device->BindResource(CS, texture_distortion, TEXSLOT_ONDEMAND2, cmd); - - if (texture_colorgradinglut != nullptr) - { - device->BindResource(CS, texture_colorgradinglut, TEXSLOT_ONDEMAND3, cmd); - } - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); - - const GPUResource* uavs[] = { - &output, - }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); - } + PushConstantsTonemap push = {}; + push.xPPResolution_rcp = cb.xPPResolution_rcp; + push.exposure = cb.tonemap_exposure; + push.dither = cb.tonemap_dither; + push.eyeadaptionkey = cb.tonemap_eyeadaptionkey; + push.texture_input = device->GetDescriptorIndex(&input, SRV); + push.texture_input_luminance = device->GetDescriptorIndex(texture_luminance, SRV); + push.texture_input_distortion = device->GetDescriptorIndex(texture_distortion, SRV); + push.texture_colorgrade_lookuptable = device->GetDescriptorIndex(texture_colorgradinglut, SRV); + push.texture_output = device->GetDescriptorIndex(&output, UAV); + device->PushConstants(&push, sizeof(push), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -11987,12 +11458,11 @@ void Postprocess_Tonemap( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, 1, cmd); device->EventEnd(cmd); } @@ -12044,19 +11514,18 @@ void Postprocess_FSR( static_cast(temp.desc.Height) ); - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS_FSR], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS_FSR], CB_GETBINDSLOT(FSRCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(FSRCB), cmd); - device->BindResource(CS, &input, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&input, TEXSLOT_ONDEMAND0, cmd); const GPUResource* uavs[] = { &temp, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&temp, temp.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&temp, temp.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -12066,12 +11535,11 @@ void Postprocess_FSR( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&temp, IMAGE_LAYOUT_UNORDERED_ACCESS, temp.desc.layout), + GPUBarrier::Image(&temp, RESOURCE_STATE_UNORDERED_ACCESS, temp.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); } // Sharpen: @@ -12079,19 +11547,18 @@ void Postprocess_FSR( device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_FSR_SHARPEN], cmd); FsrRcasCon(cb.const0, sharpness); - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS_FSR], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS_FSR], CB_GETBINDSLOT(FSRCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(FSRCB), cmd); - device->BindResource(CS, &temp, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&temp, TEXSLOT_ONDEMAND0, cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -12101,12 +11568,11 @@ void Postprocess_FSR( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); } wiProfiler::EndRange(range); @@ -12123,7 +11589,7 @@ void Postprocess_Chromatic_Aberration( device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_CHROMATIC_ABERRATION], cmd); - device->BindResource(CS, &input, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&input, TEXSLOT_ONDEMAND0, cmd); const TextureDesc& desc = output.GetDesc(); @@ -12133,17 +11599,16 @@ void Postprocess_Chromatic_Aberration( cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; cb.xPPParams0.x = amount; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -12158,12 +11623,11 @@ void Postprocess_Chromatic_Aberration( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -12194,16 +11658,14 @@ void Postprocess_Upsample_Bilateral( cb.xPPParams1.y = (float)input.GetDesc().Height; cb.xPPParams1.z = 1.0f / cb.xPPParams1.x; cb.xPPParams1.w = 1.0f / cb.xPPParams1.y; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); if (pixelshader) { device->BindPipelineState(&PSO_upsample_bilateral, cmd); - device->BindConstantBuffer(PS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); - - device->BindResource(PS, &input, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(PS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&input, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); device->Draw(3, 0, cmd); } @@ -12240,19 +11702,17 @@ void Postprocess_Upsample_Bilateral( } device->BindComputeShader(&shaders[cs], cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); - - device->BindResource(CS, &input, TEXSLOT_ONDEMAND0, cmd); - device->BindResource(CS, &lineardepth, TEXSLOT_LINEARDEPTH, cmd); + device->BindResource(&input, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&lineardepth, TEXSLOT_LINEARDEPTH, cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -12267,12 +11727,11 @@ void Postprocess_Upsample_Bilateral( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); } device->EventEnd(cmd); @@ -12292,21 +11751,20 @@ void Postprocess_Downsample4x( cb.xPPResolution.y = desc.Height; cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_DOWNSAMPLE4X], cmd); - device->BindResource(CS, &input, TEXSLOT_ONDEMAND0, cmd); + device->BindResource(&input, TEXSLOT_ONDEMAND0, cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -12321,12 +11779,11 @@ void Postprocess_Downsample4x( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } void Postprocess_NormalsFromDepth( @@ -12345,21 +11802,20 @@ void Postprocess_NormalsFromDepth( cb.xPPResolution_rcp.x = 1.0f / cb.xPPResolution.x; cb.xPPResolution_rcp.y = 1.0f / cb.xPPResolution.y; cb.xPPParams0.x = floorf(std::max(1.0f, log2f(std::max((float)desc.Width / (float)depthbuffer.GetDesc().Width, (float)desc.Height / (float)depthbuffer.GetDesc().Height)))); - device->UpdateBuffer(&constantBuffers[CBTYPE_POSTPROCESS], &cb, cmd); - device->BindConstantBuffer(CS, &constantBuffers[CBTYPE_POSTPROCESS], CB_GETBINDSLOT(PostProcessCB), cmd); + device->BindDynamicConstantBuffer(cb, CB_GETBINDSLOT(PostProcessCB), cmd); device->BindComputeShader(&shaders[CSTYPE_POSTPROCESS_NORMALSFROMDEPTH], cmd); - device->BindResource(CS, &depthbuffer, TEXSLOT_DEPTH, cmd); + device->BindResource(&depthbuffer, TEXSLOT_DEPTH, cmd); const GPUResource* uavs[] = { &output, }; - device->BindUAVs(CS, uavs, 0, arraysize(uavs), cmd); + device->BindUAVs(uavs, 0, arraysize(uavs), cmd); { GPUBarrier barriers[] = { - GPUBarrier::Image(&output, output.desc.layout, IMAGE_LAYOUT_UNORDERED_ACCESS), + GPUBarrier::Image(&output, output.desc.layout, RESOURCE_STATE_UNORDERED_ACCESS), }; device->Barrier(barriers, arraysize(barriers), cmd); } @@ -12374,12 +11830,11 @@ void Postprocess_NormalsFromDepth( { GPUBarrier barriers[] = { GPUBarrier::Memory(), - GPUBarrier::Image(&output, IMAGE_LAYOUT_UNORDERED_ACCESS, output.desc.layout), + GPUBarrier::Image(&output, RESOURCE_STATE_UNORDERED_ACCESS, output.desc.layout), }; device->Barrier(barriers, arraysize(barriers), cmd); } - device->UnbindUAVs(0, arraysize(uavs), cmd); device->EventEnd(cmd); } @@ -12484,8 +11939,6 @@ void SetOcclusionCullingEnabled(bool value) occlusionCulling = value; } bool GetOcclusionCullingEnabled() { return occlusionCulling; } -void SetLDSSkinningEnabled(bool enabled) { ldsSkinningEnabled = enabled; } -bool GetLDSSkinningEnabled() { return ldsSkinningEnabled; } void SetTemporalAAEnabled(bool enabled) { temporalAA = enabled; } bool GetTemporalAAEnabled() { return temporalAA; } void SetTemporalAADebugEnabled(bool enabled) { temporalAADEBUG = enabled; } @@ -12506,8 +11959,6 @@ void SetVoxelRadianceEnabled(bool enabled) desc.Format = FORMAT_R16G16B16A16_FLOAT; desc.BindFlags = BIND_UNORDERED_ACCESS | BIND_SHADER_RESOURCE; desc.Usage = USAGE_DEFAULT; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; device->CreateTexture(&desc, nullptr, &textures[TEXTYPE_3D_VOXELRADIANCE]); @@ -12540,7 +11991,6 @@ void SetVoxelRadianceEnabled(bool enabled) desc.StructureByteStride = sizeof(uint32_t) * 2; desc.ByteWidth = desc.StructureByteStride * voxelSceneData.res * voxelSceneData.res * voxelSceneData.res; desc.BindFlags = BIND_UNORDERED_ACCESS | BIND_SHADER_RESOURCE; - desc.CPUAccessFlags = 0; desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; desc.Usage = USAGE_DEFAULT; @@ -12603,6 +12053,14 @@ bool IsDisableAlbedoMaps() { return disableAlbedoMaps; } +void SetForceDiffuseLighting(bool value) +{ + forceDiffuseLighting = value; +} +bool IsForceDiffuseLighting() +{ + return forceDiffuseLighting; +} void SetScreenSpaceShadowsEnabled(bool value) { SCREENSPACESHADOWS = value; @@ -12611,5 +12069,21 @@ bool GetScreenSpaceShadowsEnabled() { return SCREENSPACESHADOWS; } +void SetSurfelGIEnabled(bool value) +{ + SURFELGI = value; +} +bool GetSurfelGIEnabled() +{ + return SURFELGI; +} +void SetSurfelGIDebugEnabled(bool value) +{ + SURFELGI_DEBUG = value; +} +bool GetSurfelGIDebugEnabled() +{ + return SURFELGI_DEBUG; +} } diff --git a/WickedEngine/wiRenderer.h b/WickedEngine/wiRenderer.h index 99ac15a6f..012f9f12b 100644 --- a/WickedEngine/wiRenderer.h +++ b/WickedEngine/wiRenderer.h @@ -69,7 +69,7 @@ namespace wiRenderer wiGraphics::SHADERSTAGE stage, wiGraphics::Shader& shader, const std::string& filename, - wiGraphics::SHADERMODEL minshadermodel = wiGraphics::SHADERMODEL_5_0 + wiGraphics::SHADERMODEL minshadermodel = wiGraphics::SHADERMODEL_6_0 ); @@ -209,8 +209,6 @@ namespace wiRenderer void RefreshAtmosphericScatteringTextures(wiGraphics::CommandList cmd); // Draw skydome centered to camera. void DrawSky(const wiScene::Scene& scene, wiGraphics::CommandList cmd); - // Draw sky velocity buffer - void DrawSkyVelocity(wiGraphics::CommandList cmd); // Draw shadow maps for each visible light that has associated shadow maps void DrawSun(wiGraphics::CommandList cmd); // Draw shadow maps for each visible light that has associated shadow maps @@ -254,10 +252,8 @@ namespace wiRenderer void RefreshEnvProbes(const Visibility& vis, wiGraphics::CommandList cmd); // Call once per frame to re-render out of date impostors void RefreshImpostors(const wiScene::Scene& scene, wiGraphics::CommandList cmd); - // Call once per frame to repack out of date decals in the atlas - void RefreshDecalAtlas(const wiScene::Scene& scene, wiGraphics::CommandList cmd); // Call once per frame to repack out of date lightmaps in the atlas - void RefreshLightmapAtlas(const wiScene::Scene& scene, wiGraphics::CommandList cmd); + void RefreshLightmaps(const wiScene::Scene& scene, wiGraphics::CommandList cmd); // Voxelize the scene into a voxel grid 3D texture void VoxelRadiance(const Visibility& vis, wiGraphics::CommandList cmd); // Run a compute shader that will resolve a MSAA depth buffer to a single-sample texture @@ -301,6 +297,34 @@ namespace wiRenderer wiGraphics::CommandList cmd ); + void VisibilityResolve( + const wiGraphics::Texture& depthbuffer, + const wiGraphics::Texture& texture_primitiveID, // can be MSAA + const wiGraphics::Texture gbuffer[GBUFFER_COUNT], + const wiGraphics::Texture& depthbuffer_resolved, + const wiGraphics::Texture& lineardepth, + wiGraphics::CommandList cmd + ); + + struct SurfelGIResources + { + wiGraphics::Texture result; + }; + void CreateSurfelGIResources(SurfelGIResources& res, XMUINT2 resolution); + void SurfelGI_Coverage( + const SurfelGIResources& res, + const wiScene::Scene& scene, + const wiGraphics::Texture& depthbuffer, + const wiGraphics::Texture gbuffer[GBUFFER_COUNT], + const wiGraphics::Texture& debugUAV, + wiGraphics::CommandList cmd + ); + void SurfelGI( + const SurfelGIResources& res, + const wiScene::Scene& scene, + wiGraphics::CommandList cmd + ); + void Postprocess_Blur_Gaussian( const wiGraphics::Texture& input, const wiGraphics::Texture& temp, @@ -466,6 +490,7 @@ namespace wiRenderer const wiGraphics::Texture& depthbuffer, const wiGraphics::Texture& lineardepth, const wiGraphics::GPUBuffer& entityTiles_Opaque, + const wiGraphics::Texture gbuffer[GBUFFER_COUNT], const wiGraphics::Texture& output, wiGraphics::CommandList cmd, float range = 1, @@ -576,11 +601,6 @@ namespace wiRenderer const wiGraphics::Texture& output, wiGraphics::CommandList cmd ); - void Postprocess_DepthPyramid( - const wiGraphics::Texture& depthbuffer, - const wiGraphics::Texture& lineardepth, - wiGraphics::CommandList cmd - ); void Postprocess_Sharpen( const wiGraphics::Texture& input, const wiGraphics::Texture& output, @@ -643,7 +663,9 @@ namespace wiRenderer void RayTraceSceneBVH(const wiScene::Scene& scene, wiGraphics::CommandList cmd); // Render occluders against a depth buffer + void OcclusionCulling_Reset(const Visibility& vis, wiGraphics::CommandList cmd); void OcclusionCulling_Render(const wiScene::CameraComponent& camera_previous, const Visibility& vis, wiGraphics::CommandList cmd); + void OcclusionCulling_Resolve(const Visibility& vis, wiGraphics::CommandList cmd); enum MIPGENFILTER @@ -725,8 +747,6 @@ namespace wiRenderer bool GetVariableRateShadingClassificationDebug(); void SetOcclusionCullingEnabled(bool enabled); bool GetOcclusionCullingEnabled(); - void SetLDSSkinningEnabled(bool enabled); - bool GetLDSSkinningEnabled(); void SetTemporalAAEnabled(bool enabled); bool GetTemporalAAEnabled(); void SetTemporalAADebugEnabled(bool enabled); @@ -760,8 +780,14 @@ namespace wiRenderer bool GetTessellationEnabled(); void SetDisableAlbedoMaps(bool value); bool IsDisableAlbedoMaps(); + void SetForceDiffuseLighting(bool value); + bool IsForceDiffuseLighting(); void SetScreenSpaceShadowsEnabled(bool value); bool GetScreenSpaceShadowsEnabled(); + void SetSurfelGIEnabled(bool value); + bool GetSurfelGIEnabled(); + void SetSurfelGIDebugEnabled(bool value); + bool GetSurfelGIDebugEnabled(); // Gets pick ray according to the current screen resolution and pointer coordinates. Can be used as input into RayIntersectWorld() RAY GetPickRay(long cursorX, long cursorY, const wiCanvas& canvas, const wiScene::CameraComponent& camera = wiScene::GetCamera()); diff --git a/WickedEngine/wiResourceManager.cpp b/WickedEngine/wiResourceManager.cpp index 65d3552f4..23328d7cf 100644 --- a/WickedEngine/wiResourceManager.cpp +++ b/WickedEngine/wiResourceManager.cpp @@ -105,16 +105,13 @@ namespace wiResourceManager TextureDesc desc; desc.ArraySize = 1; desc.BindFlags = BIND_SHADER_RESOURCE; - desc.CPUAccessFlags = 0; desc.Width = dds.GetWidth(); desc.Height = dds.GetHeight(); desc.Depth = dds.GetDepth(); desc.MipLevels = dds.GetMipCount(); desc.ArraySize = dds.GetArraySize(); - desc.MiscFlags = 0; - desc.Usage = USAGE_IMMUTABLE; desc.Format = FORMAT_R8G8B8A8_UNORM; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE; if (dds.IsCubemap()) { @@ -251,7 +248,7 @@ namespace wiResourceManager TextureDesc desc; desc.Height = uint32_t(height); desc.Width = uint32_t(width); - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE; if (flags & IMPORT_COLORGRADINGLUT) { @@ -294,12 +291,10 @@ namespace wiResourceManager else { desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - desc.CPUAccessFlags = 0; desc.Format = FORMAT_R8G8B8A8_UNORM; desc.MipLevels = (uint32_t)log2(std::max(width, height)) + 1; - desc.MiscFlags = 0; desc.Usage = USAGE_DEFAULT; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE; uint32_t mipwidth = width; std::vector InitData(desc.MipLevels); diff --git a/WickedEngine/wiScene.cpp b/WickedEngine/wiScene.cpp index 2e5c081d3..abae826f3 100644 --- a/WickedEngine/wiScene.cpp +++ b/WickedEngine/wiScene.cpp @@ -11,6 +11,8 @@ #include "wiRenderer.h" #include "wiBackLog.h" +#include "shaders/ShaderInterop_SurfelGI.h" + #include #include @@ -263,7 +265,7 @@ namespace wiScene dest->sheenRoughness = sheenRoughness; dest->clearcoat = clearcoat; dest->clearcoatRoughness = clearcoatRoughness; - dest->alphaTest = 1 - alphaRef + 1.0f / 256.0f; // 256 so that it is just about smaller than 1 unorm unit (1.0/255.0) + dest->alphaTest = 1 - alphaRef; dest->layerMask = layerMask; dest->transmission = transmission; dest->options = 0; @@ -295,6 +297,14 @@ namespace wiScene { dest->options |= SHADERMATERIAL_OPTION_BIT_CAST_SHADOW; } + if (IsDoubleSided()) + { + dest->options |= SHADERMATERIAL_OPTION_BIT_DOUBLE_SIDED; + } + if (GetRenderTypes() & RENDERTYPE_TRANSPARENT) + { + dest->options |= SHADERMATERIAL_OPTION_BIT_TRANSPARENT; + } GraphicsDevice* device = wiRenderer::GetDevice(); dest->texture_basecolormap_index = device->GetDescriptorIndex(textures[BASECOLORMAP].GetGPUResource(), SRV); @@ -354,24 +364,6 @@ namespace wiScene x.resource = wiResourceManager::Load(x.name, wiResourceManager::IMPORT_RETAIN_FILEDATA); } } - - ShaderMaterial shadermat; - WriteShaderMaterial(&shadermat); - - SubresourceData data; - data.pSysMem = &shadermat; - - GraphicsDevice* device = wiRenderer::GetDevice(); - GPUBufferDesc desc; - desc.Usage = USAGE_DEFAULT; - desc.BindFlags = BIND_CONSTANT_BUFFER; - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS)) - { - desc.BindFlags |= BIND_SHADER_RESOURCE; - desc.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; - } - desc.ByteWidth = sizeof(MaterialCB); - device->CreateBuffer(&desc, &data, &constantBuffer); } uint32_t MaterialComponent::GetStencilRef() const { @@ -382,14 +374,23 @@ namespace wiScene { GraphicsDevice* device = wiRenderer::GetDevice(); + vertex_subsets.resize(vertex_positions.size()); + uint32_t subsetCounter = 0; + for (auto& subset : subsets) + { + for (uint32_t i = 0; i < subset.indexCount; ++i) + { + uint32_t index = indices[subset.indexOffset + i]; + vertex_subsets[index] = subsetCounter; + } + subsetCounter++; + } + // Create index buffer GPU data: { GPUBufferDesc bd; - bd.Usage = USAGE_IMMUTABLE; - bd.CPUAccessFlags = 0; bd.BindFlags = BIND_INDEX_BUFFER | BIND_SHADER_RESOURCE; - bd.MiscFlags = 0; - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) || device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { bd.MiscFlags |= RESOURCE_MISC_RAY_TRACING; } @@ -451,10 +452,9 @@ namespace wiScene GPUBufferDesc bd; bd.Usage = USAGE_DEFAULT; - bd.CPUAccessFlags = 0; bd.BindFlags = BIND_VERTEX_BUFFER | BIND_SHADER_RESOURCE; - bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) || device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + bd.MiscFlags = RESOURCE_MISC_BUFFER_RAW; + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { bd.MiscFlags |= RESOURCE_MISC_RAY_TRACING; } @@ -549,9 +549,8 @@ namespace wiScene GPUBufferDesc bd; bd.Usage = USAGE_DEFAULT; - bd.CPUAccessFlags = 0; bd.BindFlags = BIND_VERTEX_BUFFER | BIND_SHADER_RESOURCE; - bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + bd.MiscFlags = RESOURCE_MISC_BUFFER_RAW; bd.StructureByteStride = sizeof(Vertex_TAN); bd.ByteWidth = (uint32_t)(bd.StructureByteStride * vertices.size()); @@ -583,10 +582,8 @@ namespace wiScene } GPUBufferDesc bd; - bd.Usage = USAGE_IMMUTABLE; bd.BindFlags = BIND_SHADER_RESOURCE; - bd.CPUAccessFlags = 0; - bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + bd.MiscFlags = RESOURCE_MISC_BUFFER_RAW; bd.ByteWidth = (uint32_t)(sizeof(Vertex_BON) * vertices.size()); SubresourceData InitData; @@ -595,8 +592,7 @@ namespace wiScene bd.Usage = USAGE_DEFAULT; bd.BindFlags = BIND_VERTEX_BUFFER | BIND_UNORDERED_ACCESS | BIND_SHADER_RESOURCE; - bd.CPUAccessFlags = 0; - bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + bd.MiscFlags = RESOURCE_MISC_BUFFER_RAW; if (!vertex_tangents.empty()) { @@ -606,7 +602,7 @@ namespace wiScene } bd.ByteWidth = (uint32_t)(sizeof(Vertex_POS) * vertex_positions.size()); - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) || device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { bd.MiscFlags |= RESOURCE_MISC_RAY_TRACING; } @@ -624,10 +620,8 @@ namespace wiScene } GPUBufferDesc bd; - bd.Usage = USAGE_IMMUTABLE; - bd.CPUAccessFlags = 0; bd.BindFlags = BIND_VERTEX_BUFFER | BIND_SHADER_RESOURCE; - bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + bd.MiscFlags = RESOURCE_MISC_BUFFER_RAW; bd.StructureByteStride = sizeof(Vertex_TEX); bd.ByteWidth = (uint32_t)(bd.StructureByteStride * vertices.size()); @@ -647,10 +641,8 @@ namespace wiScene } GPUBufferDesc bd; - bd.Usage = USAGE_IMMUTABLE; - bd.CPUAccessFlags = 0; bd.BindFlags = BIND_VERTEX_BUFFER | BIND_SHADER_RESOURCE; - bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + bd.MiscFlags = RESOURCE_MISC_BUFFER_RAW; bd.StructureByteStride = sizeof(Vertex_TEX); bd.ByteWidth = (uint32_t)(bd.StructureByteStride * vertices.size()); @@ -664,10 +656,8 @@ namespace wiScene if (!vertex_colors.empty()) { GPUBufferDesc bd; - bd.Usage = USAGE_IMMUTABLE; - bd.CPUAccessFlags = 0; bd.BindFlags = BIND_VERTEX_BUFFER | BIND_SHADER_RESOURCE; - bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + bd.MiscFlags = RESOURCE_MISC_BUFFER_RAW; bd.StructureByteStride = sizeof(Vertex_COL); bd.ByteWidth = (uint32_t)(bd.StructureByteStride * vertex_colors.size()); @@ -687,10 +677,8 @@ namespace wiScene } GPUBufferDesc bd; - bd.Usage = USAGE_IMMUTABLE; - bd.CPUAccessFlags = 0; bd.BindFlags = BIND_VERTEX_BUFFER | BIND_SHADER_RESOURCE; - bd.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; + bd.MiscFlags = RESOURCE_MISC_BUFFER_RAW; bd.StructureByteStride = sizeof(Vertex_TEX); bd.ByteWidth = (uint32_t)(bd.StructureByteStride * vertices.size()); @@ -700,43 +688,22 @@ namespace wiScene device->SetName(&vertexBuffer_ATL, "vertexBuffer_ATL"); } - // vertexBuffer - SUBSETS - { - vertex_subsets.resize(vertex_positions.size()); - - uint32_t subsetCounter = 0; - for (auto& subset : subsets) - { - for (uint32_t i = 0; i < subset.indexCount; ++i) - { - uint32_t index = indices[subset.indexOffset + i]; - vertex_subsets[index] = subsetCounter; - } - subsetCounter++; - } - - GPUBufferDesc bd; - bd.Usage = USAGE_IMMUTABLE; - bd.CPUAccessFlags = 0; - bd.BindFlags = BIND_VERTEX_BUFFER | BIND_SHADER_RESOURCE; - bd.MiscFlags = 0; - bd.StructureByteStride = sizeof(uint8_t); - bd.ByteWidth = (uint32_t)(bd.StructureByteStride * vertex_subsets.size()); - bd.Format = FORMAT_R8_UINT; - - SubresourceData InitData; - InitData.pSysMem = vertex_subsets.data(); - device->CreateBuffer(&bd, &InitData, &vertexBuffer_SUB); - device->SetName(&vertexBuffer_SUB, "vertexBuffer_SUB"); - } - // vertexBuffer_PRE will be created on demand later! vertexBuffer_PRE = GPUBuffer(); + GPUBufferDesc desc; + desc.BindFlags = BIND_SHADER_RESOURCE; + desc.MiscFlags = RESOURCE_MISC_BUFFER_RAW; + desc.StructureByteStride = sizeof(ShaderMeshSubset); + desc.ByteWidth = desc.StructureByteStride * (uint32_t)subsets.size(); + bool success = device->CreateBuffer(&desc, nullptr, &subsetBuffer); + assert(success); + dirty_subsets = true; - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) || device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { - BLAS_state = BLAS_STATE_NEEDS_REBUILD; + BLAS_state = MeshComponent::BLAS_STATE_NEEDS_REBUILD; RaytracingAccelerationStructureDesc desc; desc.type = RaytracingAccelerationStructureDesc::BOTTOMLEVEL; @@ -770,25 +737,6 @@ namespace wiScene assert(success); device->SetName(&BLAS, "BLAS"); } - - if(device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS)) - { - dirty_bindless = true; - - GPUBufferDesc desc; - desc.BindFlags = BIND_SHADER_RESOURCE; - desc.MiscFlags = RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS; - desc.ByteWidth = sizeof(ShaderMesh); - bool success = device->CreateBuffer(&desc, nullptr, &descriptor); - assert(success); - - desc.BindFlags = BIND_SHADER_RESOURCE; - desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; - desc.StructureByteStride = sizeof(ShaderMeshSubset); - desc.ByteWidth = desc.StructureByteStride * (uint32_t)subsets.size(); - success = device->CreateBuffer(&desc, nullptr, &subsetBuffer); - assert(success); - } } void MeshComponent::WriteShaderMesh(ShaderMesh* dest) const { @@ -819,6 +767,16 @@ namespace wiScene dest->blendmaterial2 = terrain_material2_index; dest->blendmaterial3 = terrain_material3_index; dest->subsetbuffer = device->GetDescriptorIndex(&subsetBuffer, SRV); + dest->aabb_min = aabb._min; + dest->aabb_max = aabb._max; + dest->tessellation_factor = tessellationFactor; + + dest->flags = 0; + if (IsDoubleSided()) + { + dest->flags |= SHADERMESH_FLAG_DOUBLE_SIDED; + } + } void MeshComponent::ComputeNormals(COMPUTE_NORMALS compute) { @@ -1291,13 +1249,10 @@ namespace wiScene GraphicsDevice* device = wiRenderer::GetDevice(); GPUBufferDesc bd; - bd.Usage = USAGE_DYNAMIC; - bd.CPUAccessFlags = CPU_ACCESS_WRITE; - - bd.ByteWidth = sizeof(ArmatureComponent::ShaderBoneType) * (uint32_t)boneCollection.size(); + bd.ByteWidth = sizeof(ShaderTransform) * (uint32_t)boneCollection.size(); bd.BindFlags = BIND_SHADER_RESOURCE; bd.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; - bd.StructureByteStride = sizeof(ArmatureComponent::ShaderBoneType); + bd.StructureByteStride = sizeof(ShaderTransform); device->CreateBuffer(&bd, nullptr, &boneBuffer); } @@ -1456,9 +1411,45 @@ namespace wiScene GraphicsDevice* device = wiRenderer::GetDevice(); - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) || device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + instanceData.resize(objects.GetCount() + hairs.GetCount()); + if (instanceBuffer.desc.ByteWidth < (instanceData.size() * sizeof(ShaderMeshInstance))) { - TLAS_instances.resize(objects.GetCount() * device->GetTopLevelAccelerationStructureInstanceSize()); + GPUBufferDesc desc; + desc.StructureByteStride = sizeof(ShaderMeshInstance); + desc.ByteWidth = desc.StructureByteStride * (uint32_t)instanceData.size(); + desc.BindFlags = BIND_SHADER_RESOURCE; + desc.MiscFlags = RESOURCE_MISC_BUFFER_RAW; + device->CreateBuffer(&desc, nullptr, &instanceBuffer); + device->SetName(&instanceBuffer, "instanceBuffer"); + } + + meshData.resize(meshes.GetCount() + hairs.GetCount()); + if (meshBuffer.desc.ByteWidth < (meshData.size() * sizeof(ShaderMesh))) + { + GPUBufferDesc desc; + desc.StructureByteStride = sizeof(ShaderMesh); + desc.ByteWidth = desc.StructureByteStride * (uint32_t)meshData.size(); + desc.BindFlags = BIND_SHADER_RESOURCE; + desc.MiscFlags = RESOURCE_MISC_BUFFER_RAW; + device->CreateBuffer(&desc, nullptr, &meshBuffer); + device->SetName(&meshBuffer, "meshBuffer"); + } + + materialData.resize(materials.GetCount()); + if (materialBuffer.desc.ByteWidth < (materialData.size() * sizeof(ShaderMaterial))) + { + GPUBufferDesc desc; + desc.StructureByteStride = sizeof(ShaderMaterial); + desc.ByteWidth = desc.StructureByteStride * (uint32_t)materialData.size(); + desc.BindFlags = BIND_SHADER_RESOURCE; + desc.MiscFlags = RESOURCE_MISC_BUFFER_RAW; + device->CreateBuffer(&desc, nullptr, &materialBuffer); + device->SetName(&materialBuffer, "materialBuffer"); + } + + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) + { + TLAS_instances.resize(instanceData.size() * device->GetTopLevelAccelerationStructureInstanceSize()); } // Occlusion culling read: @@ -1468,13 +1459,20 @@ namespace wiScene { GPUQueryHeapDesc desc; desc.type = GPU_QUERY_TYPE_OCCLUSION_BINARY; - desc.queryCount = 2048; + desc.queryCount = 8192; + + GPUBufferDesc bd; + bd.Usage = USAGE_READBACK; + bd.ByteWidth = desc.queryCount * sizeof(uint64_t); + for (int i = 0; i < arraysize(queryHeap); ++i) { - bool success = wiRenderer::GetDevice()->CreateQueryHeap(&desc, &queryHeap[i]); + bool success = device->CreateQueryHeap(&desc, &queryHeap[i]); + assert(success); + + success = device->CreateBuffer(&bd, nullptr, &queryResultBuffer[i]); assert(success); } - queryResults.resize(desc.queryCount); } // Previously allocated and written query count (newest one) is saved: @@ -1483,17 +1481,6 @@ namespace wiScene // Advance to next query heap to use (this will be the oldest one that was written) queryheap_idx = (queryheap_idx + 1) % arraysize(queryHeap); - - // Read back data from the oldest query heap: - if (writtenQueries[queryheap_idx] > 0) - { - device->QueryRead( - &queryHeap[queryheap_idx], - 0, - writtenQueries[queryheap_idx], - queryResults.data() - ); - } } wiJobSystem::context ctx; @@ -1522,10 +1509,10 @@ namespace wiScene RunWeatherUpdateSystem(ctx); - wiPhysicsEngine::RunPhysicsUpdateSystem(ctx, *this, dt); - wiJobSystem::Wait(ctx); // dependencies + wiPhysicsEngine::RunPhysicsUpdateSystem(ctx, *this, dt); + RunObjectUpdateSystem(ctx); RunCameraUpdateSystem(ctx); @@ -1551,15 +1538,20 @@ namespace wiScene bounds = AABB::Merge(bounds, group_bound); } - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_PIPELINE) || device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING_INLINE)) + if (lightmap_refresh_needed.load()) + { + SetAccelerationStructureUpdateRequested(true); + } + + if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_RAYTRACING)) { // Recreate top level acceleration structure if the object count changed: - if (objects.GetCount() > 0 && objects.GetCount() != TLAS.desc.toplevel.count) + if ((uint32_t)instanceData.size() != TLAS.desc.toplevel.count) { RaytracingAccelerationStructureDesc desc; desc._flags = RaytracingAccelerationStructureDesc::FLAG_PREFER_FAST_BUILD; desc.type = RaytracingAccelerationStructureDesc::TOPLEVEL; - desc.toplevel.count = (uint32_t)objects.GetCount(); + desc.toplevel.count = (uint32_t)instanceData.size(); GPUBufferDesc bufdesc; bufdesc.MiscFlags |= RESOURCE_MISC_RAY_TRACING; bufdesc.ByteWidth = desc.toplevel.count * (uint32_t)device->GetTopLevelAccelerationStructureInstanceSize(); @@ -1572,92 +1564,6 @@ namespace wiScene } } - if (lightmap_refresh_needed.load()) - { - SetAccelerationStructureUpdateRequested(true); - } - if (lightmap_repack_needed.load()) - { - std::vector bins; - if (wiRectPacker::pack(lightmap_rects.data(), (int)lightmap_rect_allocator.load(), 16384, bins)) - { - assert(bins.size() == 1 && "The regions won't fit into the texture!"); - - TextureDesc desc; - desc.Width = (uint32_t)bins[0].size.w; - desc.Height = (uint32_t)bins[0].size.h; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = FORMAT_R11G11B10_FLOAT; - desc.SampleCount = 1; - desc.Usage = USAGE_DEFAULT; - desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - device->CreateTexture(&desc, nullptr, &lightmap); - device->SetName(&lightmap, "Scene::lightmap"); - } - else - { - wiBackLog::post("Global Lightmap atlas packing failed!"); - } - } - if (!lightmap.IsValid()) - { - // In case no lightmaps, still create a dummy texture - TextureDesc desc; - desc.Width = 1; - desc.Height = 1; - desc.Format = FORMAT_R11G11B10_FLOAT; - desc.BindFlags = BIND_SHADER_RESOURCE; - device->CreateTexture(&desc, nullptr, &lightmap); - } - - // Update atlas texture if it is invalidated: - if (decal_repack_needed) - { - std::vector out_rects(packedDecals.size()); - int i = 0; - for (auto& it : packedDecals) - { - out_rects[i] = &it.second; - i++; - } - - std::vector bins; - if (wiRectPacker::pack(out_rects.data(), (int)packedDecals.size(), 16384, bins)) - { - assert(bins.size() == 1 && "The regions won't fit into the texture!"); - - TextureDesc desc; - desc.Width = (uint32_t)bins[0].size.w; - desc.Height = (uint32_t)bins[0].size.h; - desc.MipLevels = 0; - desc.ArraySize = 1; - desc.Format = FORMAT_R8G8B8A8_UNORM; - desc.SampleCount = 1; - desc.Usage = USAGE_DEFAULT; - desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - device->CreateTexture(&desc, nullptr, &decalAtlas); - device->SetName(&decalAtlas, "Scene::decalAtlas"); - - for (uint32_t i = 0; i < decalAtlas.GetDesc().MipLevels; ++i) - { - int subresource_index; - subresource_index = device->CreateSubresource(&decalAtlas, UAV, 0, 1, i, 1); - assert(subresource_index == i); - } - } - else - { - wiBackLog::post("Decal atlas packing failed!"); - } - } - // Update water ripples: for (size_t i = 0; i < waterRipples.size(); ++i) { @@ -1673,6 +1579,64 @@ namespace wiScene } } + if (wiRenderer::GetSurfelGIEnabled() && !surfelBuffer.IsValid()) + { + GPUBufferDesc desc; + desc.StructureByteStride = sizeof(Surfel); + desc.ByteWidth = desc.StructureByteStride * SURFEL_CAPACITY; + desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; + desc.BindFlags = BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; + device->CreateBuffer(&desc, nullptr, &surfelBuffer); + device->SetName(&surfelBuffer, "surfelBuffer"); + + desc.StructureByteStride = sizeof(SurfelData); + desc.ByteWidth = desc.StructureByteStride * SURFEL_CAPACITY; + desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; + device->CreateBuffer(&desc, nullptr, &surfelDataBuffer); + device->SetName(&surfelDataBuffer, "surfelDataBuffer"); + + desc.StructureByteStride = sizeof(uint); + desc.ByteWidth = desc.StructureByteStride * 5; + desc.MiscFlags = RESOURCE_MISC_BUFFER_RAW | RESOURCE_MISC_INDIRECT_ARGS; + device->CreateBuffer(&desc, nullptr, &surfelStatsBuffer); + device->SetName(&surfelStatsBuffer, "surfelStatsBuffer"); + + desc.StructureByteStride = sizeof(SurfelGridCell); + desc.ByteWidth = desc.StructureByteStride * SURFEL_TABLE_SIZE; + desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; + device->CreateBuffer(&desc, nullptr, &surfelGridBuffer); + device->SetName(&surfelGridBuffer, "surfelGridBuffer"); + + desc.StructureByteStride = sizeof(uint); + desc.ByteWidth = desc.StructureByteStride * SURFEL_CAPACITY * 27; // each surfel can be in 3x3x3=27 cells + desc.MiscFlags = RESOURCE_MISC_BUFFER_STRUCTURED; + device->CreateBuffer(&desc, nullptr, &surfelCellBuffer); + device->SetName(&surfelCellBuffer, "surfelCellBuffer"); + + TextureDesc tex; + tex.Width = SURFEL_MOMENT_ATLAS_TEXELS; + tex.Height = SURFEL_MOMENT_ATLAS_TEXELS; + tex.Format = FORMAT_R16G16_FLOAT; + tex.BindFlags = BIND_UNORDERED_ACCESS | BIND_SHADER_RESOURCE; + device->CreateTexture(&tex, nullptr, &surfelMomentsTexture); + device->SetName(&surfelMomentsTexture, "surfelMomentsTexture"); + } + + // Bindless scene resources: + shaderscene.instancebuffer = device->GetDescriptorIndex(&instanceBuffer, SRV); + shaderscene.meshbuffer = device->GetDescriptorIndex(&meshBuffer, SRV); + shaderscene.materialbuffer = device->GetDescriptorIndex(&materialBuffer, SRV); + shaderscene.TLAS = device->GetDescriptorIndex(&TLAS, SRV); + shaderscene.envmaparray = device->GetDescriptorIndex(&envmapArray, SRV); + + if (weather.skyMap == nullptr) + { + shaderscene.globalenvmap = -1; + } + else + { + shaderscene.globalenvmap = device->GetDescriptorIndex(&weather.skyMap->texture, SRV); + } } void Scene::Clear() { @@ -1708,8 +1672,13 @@ namespace wiScene TLAS = RaytracingAccelerationStructure(); BVH.Clear(); - packedDecals.clear(); waterRipples.clear(); + + surfelBuffer = {}; + surfelDataBuffer = {}; + surfelStatsBuffer = {}; + surfelGridBuffer = {}; + surfelCellBuffer = {}; } void Scene::Merge(Scene& other) { @@ -2700,7 +2669,9 @@ namespace wiScene XMMATRIX W = XMLoadFloat4x4(&bone.world); XMMATRIX M = B * W * R; - armature.boneData[boneIndex++].Store(M); + XMFLOAT4X4 mat; + XMStoreFloat4x4(&mat, M); + armature.boneData[boneIndex++].Create(mat); const float bone_radius = 1; XMFLOAT3 bonepos = bone.GetPosition(); @@ -2712,7 +2683,7 @@ namespace wiScene armature.aabb = AABB(_min, _max); - if (!armature.boneBuffer.IsValid()) + if (!armature.boneBuffer.IsValid() || armature.boneBuffer.desc.ByteWidth != armature.boneData.size() * sizeof(ShaderTransform)) { armature.CreateRenderData(); } @@ -2726,12 +2697,18 @@ namespace wiScene MeshComponent& mesh = meshes[args.jobIndex]; GraphicsDevice* device = wiRenderer::GetDevice(); - if (mesh.IsSkinned() && armatures.Contains(mesh.armatureID)) + if (!mesh.vertexBuffer_PRE.IsValid()) { const SoftBodyPhysicsComponent* softbody = softbodies.GetComponent(entity); - if (softbody == nullptr || softbody->vertex_positions_simulation.empty()) + if (softbody != nullptr && wiPhysicsEngine::IsSimulationEnabled()) { - if (!mesh.vertexBuffer_PRE.IsValid()) + device->CreateBuffer(&mesh.vertexBuffer_POS.desc, nullptr, &mesh.streamoutBuffer_POS); + device->CreateBuffer(&mesh.vertexBuffer_POS.desc, nullptr, &mesh.vertexBuffer_PRE); + device->CreateBuffer(&mesh.vertexBuffer_TAN.desc, nullptr, &mesh.streamoutBuffer_TAN); + } + else if (mesh.IsSkinned() && armatures.Contains(mesh.armatureID)) + { + if (softbody == nullptr || softbody->vertex_positions_simulation.empty()) { device->CreateBuffer(&mesh.streamoutBuffer_POS.GetDesc(), nullptr, &mesh.vertexBuffer_PRE); } @@ -2740,7 +2717,6 @@ namespace wiScene if (mesh.streamoutBuffer_POS.IsValid() && mesh.vertexBuffer_PRE.IsValid()) { - mesh.dirty_bindless = true; std::swap(mesh.streamoutBuffer_POS, mesh.vertexBuffer_PRE); } @@ -2772,6 +2748,10 @@ namespace wiScene mesh.BLAS_state = MeshComponent::BLAS_STATE_NEEDS_REBUILD; geometry.triangles.vertexBuffer = mesh.streamoutBuffer_POS; } + if (material->IsDoubleSided()) + { + mesh._flags |= MeshComponent::TLAS_FORCE_DOUBLE_SIDED; + } } } else @@ -2789,48 +2769,9 @@ namespace wiScene } } - if (device->CheckCapability(GRAPHICSDEVICE_CAPABILITY_BINDLESS_DESCRIPTORS)) - { - if (mesh.terrain_material1 != INVALID_ENTITY) - { - const MaterialComponent* mat = materials.GetComponent(mesh.terrain_material1); - if (mat != nullptr) - { - int index = device->GetDescriptorIndex(&mat->constantBuffer, SRV); - if (mesh.terrain_material1_index != index) - { - mesh.dirty_bindless = true; - mesh.terrain_material1_index = index; - } - } - } - if (mesh.terrain_material2 != INVALID_ENTITY) - { - const MaterialComponent* mat = materials.GetComponent(mesh.terrain_material2); - if (mat != nullptr) - { - int index = device->GetDescriptorIndex(&mat->constantBuffer, SRV); - if (mesh.terrain_material2_index != index) - { - mesh.dirty_bindless = true; - mesh.terrain_material2_index = index; - } - } - } - if (mesh.terrain_material3 != INVALID_ENTITY) - { - const MaterialComponent* mat = materials.GetComponent(mesh.terrain_material3); - if (mat != nullptr) - { - int index = device->GetDescriptorIndex(&mat->constantBuffer, SRV); - if (mesh.terrain_material3_index != index) - { - mesh.dirty_bindless = true; - mesh.terrain_material3_index = index; - } - } - } - } + mesh.terrain_material1_index = (uint32_t)materials.GetIndex(mesh.terrain_material1); + mesh.terrain_material2_index = (uint32_t)materials.GetIndex(mesh.terrain_material2); + mesh.terrain_material3_index = (uint32_t)materials.GetIndex(mesh.terrain_material3); // Update morph targets if needed: if (mesh.dirty_morph && !mesh.targets.empty()) @@ -2868,6 +2809,9 @@ namespace wiScene mesh.aabb = AABB(_min, _max); } + ShaderMesh& shadermesh = meshData[args.jobIndex]; + mesh.WriteShaderMesh(&shadermesh); + }); } void Scene::RunMaterialUpdateSystem(wiJobSystem::context& ctx) @@ -2882,11 +2826,6 @@ namespace wiScene material.layerMask = layer->layerMask; } - if (!material.constantBuffer.IsValid()) - { - material.CreateRenderData(); - } - material.texAnimElapsedTime += dt * material.texAnimFrameRate; if (material.texAnimElapsedTime >= 1.0f) { @@ -2906,9 +2845,11 @@ namespace wiScene if (material.IsDirty()) { material.SetDirty(false); - material.dirty_buffer = true; } + ShaderMaterial& shadermat = materialData[args.jobIndex]; + material.WriteShaderMaterial(&shadermat); + }); } void Scene::RunImpostorUpdateSystem(wiJobSystem::context& ctx) @@ -2924,14 +2865,14 @@ namespace wiScene desc.BindFlags = BIND_DEPTH_STENCIL; desc.ArraySize = 1; desc.Format = FORMAT_D16_UNORM; - desc.layout = IMAGE_LAYOUT_DEPTHSTENCIL; + desc.layout = RESOURCE_STATE_DEPTHSTENCIL; device->CreateTexture(&desc, nullptr, &impostorDepthStencil); device->SetName(&impostorDepthStencil, "impostorDepthStencil"); desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE | BIND_UNORDERED_ACCESS; desc.ArraySize = maxImpostorCount * impostorCaptureAngles * 3; desc.Format = FORMAT_R8G8B8A8_UNORM; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE; device->CreateTexture(&desc, nullptr, &impostorArray); device->SetName(&impostorArray, "impostorArray"); @@ -2969,7 +2910,7 @@ namespace wiScene ImpostorComponent& impostor = impostors[args.jobIndex]; impostor.aabb = AABB(); - impostor.instanceMatrices.clear(); + impostor.instances.clear(); if (impostor.IsDirty()) { @@ -2982,9 +2923,6 @@ namespace wiScene { assert(objects.GetCount() == aabb_objects.GetCount()); - lightmap_rects.resize(objects.GetCount()); - lightmap_rect_allocator.store(0); - parallel_bounds.clear(); parallel_bounds.resize((size_t)wiJobSystem::DispatchGroupCount((uint32_t)objects.GetCount(), small_subtask_groupsize)); @@ -2998,9 +2936,9 @@ namespace wiScene { object.occlusionHistory <<= 1; // advance history by 1 frame int query_id = object.occlusionQueries[queryheap_idx]; - if (query_id >= 0 && (int)writtenQueries[queryheap_idx] > query_id) + if (queryResultBuffer[queryheap_idx].mapped_data != nullptr && query_id >= 0 && (int)writtenQueries[queryheap_idx] > query_id) { - uint64_t visible = queryResults[query_id]; + uint64_t visible = ((uint64_t*)queryResultBuffer[queryheap_idx].mapped_data)[query_id]; if (visible) { object.occlusionHistory |= 1; // visible @@ -3082,12 +3020,7 @@ namespace wiScene const SPHERE boundingsphere = mesh->GetBoundingSphere(); locker.lock(); - impostor->instanceMatrices.emplace_back(); - XMStoreFloat4x4(&impostor->instanceMatrices.back(), - XMMatrixScaling(boundingsphere.radius, boundingsphere.radius, boundingsphere.radius) * - XMMatrixTranslation(boundingsphere.center.x, boundingsphere.center.y, boundingsphere.center.z) * - W - ); + impostor->instances.push_back(args.jobIndex); locker.unlock(); } @@ -3113,26 +3046,55 @@ namespace wiScene object.prev_transform_index = -1; } - if (TLAS.IsValid()) + // Create GPU instance data: + const XMFLOAT4X4& worldMatrix = object.transform_index >= 0 ? transforms[object.transform_index].world : IDENTITYMATRIX; + const XMFLOAT4X4& worldMatrixPrev = object.prev_transform_index >= 0 ? prev_transforms[object.prev_transform_index].world_prev : IDENTITYMATRIX; + + XMMATRIX worldMatrixInverseTranspose = XMLoadFloat4x4(&worldMatrix); + worldMatrixInverseTranspose = XMMatrixInverse(nullptr, worldMatrixInverseTranspose); + worldMatrixInverseTranspose = XMMatrixTranspose(worldMatrixInverseTranspose); + XMFLOAT4X4 transformIT; + XMStoreFloat4x4(&transformIT, worldMatrixInverseTranspose); + + GraphicsDevice* device = wiRenderer::GetDevice(); + ShaderMeshInstance& inst = instanceData[args.jobIndex]; + inst.init(); + inst.transform.Create(worldMatrix); + inst.transformInverseTranspose.Create(transformIT); + inst.transformPrev.Create(worldMatrixPrev); + if (object.lightmap.IsValid()) { - GraphicsDevice* device = wiRenderer::GetDevice(); + inst.lightmap = device->GetDescriptorIndex(&object.lightmap, SRV); + } + inst.uid = entity; + inst.color = wiMath::CompressColor(object.color); + inst.emissive = wiMath::CompressColor(object.emissiveColor); + inst.meshIndex = (uint)meshes.GetIndex(object.meshID); + + if (!TLAS_instances.empty()) + { + // TLAS instance data: RaytracingAccelerationStructureDesc::TopLevel::Instance instance = {}; - const XMFLOAT4X4& worldMatrix = object.transform_index >= 0 ? transforms[object.transform_index].world : IDENTITYMATRIX; instance = {}; instance.transform = XMFLOAT3X4( worldMatrix._11, worldMatrix._21, worldMatrix._31, worldMatrix._41, worldMatrix._12, worldMatrix._22, worldMatrix._32, worldMatrix._42, worldMatrix._13, worldMatrix._23, worldMatrix._33, worldMatrix._43 ); - instance.InstanceID = (uint32_t)device->GetDescriptorIndex(&mesh->descriptor, SRV); + instance.InstanceID = args.jobIndex; instance.InstanceMask = 1; instance.bottomlevel = mesh->BLAS; + if (mesh->IsDoubleSided() || mesh->_flags & MeshComponent::TLAS_FORCE_DOUBLE_SIDED) + { + instance.Flags |= RaytracingAccelerationStructureDesc::TopLevel::Instance::FLAG_TRIANGLE_CULL_DISABLE; + } + if (XMVectorGetX(XMMatrixDeterminant(W)) > 0) { // There is a mismatch between object space winding and BLAS winding: // https://docs.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_raytracing_instance_flags - instance.Flags = RaytracingAccelerationStructureDesc::TopLevel::Instance::FLAG_TRIANGLE_FRONT_COUNTERCLOCKWISE; + instance.Flags |= RaytracingAccelerationStructureDesc::TopLevel::Instance::FLAG_TRIANGLE_FRONT_COUNTERCLOCKWISE; } void* dest = (void*)((size_t)TLAS_instances.data() + (size_t)args.jobIndex * device->GetTopLevelAccelerationStructureInstanceSize()); @@ -3140,60 +3102,44 @@ namespace wiScene } // lightmap things: - if (dt > 0) + if (object.IsLightmapRenderRequested() && dt > 0) { - if (object.IsLightmapRenderRequested() && dt > 0) + if (!object.lightmap.IsValid()) { - if (!object.lightmap.IsValid()) { - { - // Unfortunately, fp128 format only correctly downloads from GPU if it is pow2 size: - object.lightmapWidth = wiMath::GetNextPowerOfTwo(object.lightmapWidth + 1) / 2; - object.lightmapHeight = wiMath::GetNextPowerOfTwo(object.lightmapHeight + 1) / 2; - } - - TextureDesc desc; - desc.Width = object.lightmapWidth; - desc.Height = object.lightmapHeight; - desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE; - // Note: we need the full precision format to achieve correct accumulative blending! - // But the global atlas will have less precision for good bandwidth for sampling - desc.Format = FORMAT_R32G32B32A32_FLOAT; - - GraphicsDevice* device = wiRenderer::GetDevice(); - device->CreateTexture(&desc, nullptr, &object.lightmap); - device->SetName(&object.lightmap, "object.lightmap"); - - RenderPassDesc renderpassdesc; - - renderpassdesc.attachments.push_back(RenderPassAttachment::RenderTarget(&object.lightmap, RenderPassAttachment::LOADOP_CLEAR)); - - device->CreateRenderPass(&renderpassdesc, &object.renderpass_lightmap_clear); - - renderpassdesc.attachments.back().loadop = RenderPassAttachment::LOADOP_LOAD; - device->CreateRenderPass(&renderpassdesc, &object.renderpass_lightmap_accumulate); + // Unfortunately, fp128 format only correctly downloads from GPU if it is pow2 size: + object.lightmapWidth = wiMath::GetNextPowerOfTwo(object.lightmapWidth + 1) / 2; + object.lightmapHeight = wiMath::GetNextPowerOfTwo(object.lightmapHeight + 1) / 2; } - lightmap_refresh_needed.store(true); - } - if (!object.lightmapTextureData.empty() && !object.lightmap.IsValid()) - { - // Create a GPU-side per object lighmap if there is none yet, so that copying into atlas can be done efficiently: - wiTextureHelper::CreateTexture(object.lightmap, object.lightmapTextureData.data(), object.lightmapWidth, object.lightmapHeight, object.GetLightmapFormat()); - } + TextureDesc desc; + desc.Width = object.lightmapWidth; + desc.Height = object.lightmapHeight; + desc.BindFlags = BIND_RENDER_TARGET | BIND_SHADER_RESOURCE; + // Note: we need the full precision format to achieve correct accumulative blending! + // But the global atlas will have less precision for good bandwidth for sampling + desc.Format = FORMAT_R32G32B32A32_FLOAT; - if (object.lightmap.IsValid()) - { - if (object.lightmap_rect.w == 0) - { - // we need to pack this lightmap texture into the atlas - object.lightmap_rect = wiRectPacker::rect_xywh(0, 0, object.lightmap.GetDesc().Width + atlasClampBorder * 2, object.lightmap.GetDesc().Height + atlasClampBorder * 2); - lightmap_repack_needed.store(true); // will need to repack all in this case! - } - // lightmap rects' state is always updated, in case one needs repacking - uint32_t alloc = lightmap_rect_allocator.fetch_add(1); - lightmap_rects[alloc] = &object.lightmap_rect; + GraphicsDevice* device = wiRenderer::GetDevice(); + device->CreateTexture(&desc, nullptr, &object.lightmap); + device->SetName(&object.lightmap, "object.lightmap"); + + RenderPassDesc renderpassdesc; + + renderpassdesc.attachments.push_back(RenderPassAttachment::RenderTarget(&object.lightmap, RenderPassAttachment::LOADOP_CLEAR)); + + device->CreateRenderPass(&renderpassdesc, &object.renderpass_lightmap_clear); + + renderpassdesc.attachments.back().loadop = RenderPassAttachment::LOADOP_LOAD; + device->CreateRenderPass(&renderpassdesc, &object.renderpass_lightmap_accumulate); } + lightmap_refresh_needed.store(true); + } + + if (!object.lightmapTextureData.empty() && !object.lightmap.IsValid()) + { + // Create a GPU-side per object lighmap if there is none yet, so that copying into atlas can be done efficiently: + wiTextureHelper::CreateTexture(object.lightmap, object.lightmapTextureData.data(), object.lightmapWidth, object.lightmapHeight, object.GetLightmapFormat()); } } @@ -3281,18 +3227,6 @@ namespace wiScene decal.emissive = material.GetEmissiveStrength(); decal.texture = material.textures[MaterialComponent::BASECOLORMAP].resource; decal.normal = material.textures[MaterialComponent::NORMALMAP].resource; - - // atlas part is not thread safe: - if (decal.texture != nullptr && decal.texture->texture.IsValid()) - { - if (packedDecals.find(decal.texture) == packedDecals.end()) - { - // we need to pack this decal texture into the atlas - wiRectPacker::rect_xywh newRect = wiRectPacker::rect_xywh(0, 0, decal.texture->texture.desc.Width + atlasClampBorder * 2, decal.texture->texture.desc.Height + atlasClampBorder * 2); - packedDecals[decal.texture] = newRect; - decal_repack_needed = true; - } - } } } void Scene::RunProbeUpdateSystem(wiJobSystem::context& ctx) @@ -3306,28 +3240,26 @@ namespace wiScene TextureDesc desc; desc.ArraySize = 6; desc.BindFlags = BIND_DEPTH_STENCIL; - desc.CPUAccessFlags = 0; desc.Format = FORMAT_D16_UNORM; desc.Height = envmapRes; desc.Width = envmapRes; desc.MipLevels = 1; desc.MiscFlags = RESOURCE_MISC_TEXTURECUBE; desc.Usage = USAGE_DEFAULT; - desc.layout = IMAGE_LAYOUT_DEPTHSTENCIL; + desc.layout = RESOURCE_STATE_DEPTHSTENCIL; device->CreateTexture(&desc, nullptr, &envrenderingDepthBuffer); device->SetName(&envrenderingDepthBuffer, "envrenderingDepthBuffer"); desc.ArraySize = envmapCount * 6; desc.BindFlags = BIND_SHADER_RESOURCE | BIND_RENDER_TARGET | BIND_UNORDERED_ACCESS; - desc.CPUAccessFlags = 0; desc.Format = FORMAT_R11G11B10_FLOAT; desc.Height = envmapRes; desc.Width = envmapRes; desc.MipLevels = envmapMIPs; desc.MiscFlags = RESOURCE_MISC_TEXTURECUBE; desc.Usage = USAGE_DEFAULT; - desc.layout = IMAGE_LAYOUT_SHADER_RESOURCE; + desc.layout = RESOURCE_STATE_SHADER_RESOURCE; device->CreateTexture(&desc, nullptr, &envmapArray); device->SetName(&envmapArray, "envmapArray"); @@ -3557,6 +3489,45 @@ namespace wiScene const TransformComponent& transform = *transforms.GetComponent(entity); hair.UpdateCPU(transform, *mesh, dt); + + GraphicsDevice* device = wiRenderer::GetDevice(); + + size_t meshIndex = meshes.GetCount() + args.jobIndex; + ShaderMesh& mesh = meshData[meshIndex]; + mesh.ib = device->GetDescriptorIndex(&hair.primitiveBuffer, SRV); + mesh.vb_pos_nor_wind = device->GetDescriptorIndex(&hair.vertexBuffer_POS[0], SRV); + mesh.vb_pre = device->GetDescriptorIndex(&hair.vertexBuffer_POS[1], SRV); + mesh.vb_uv0 = device->GetDescriptorIndex(&hair.vertexBuffer_TEX, SRV); + mesh.subsetbuffer = device->GetDescriptorIndex(&hair.subsetBuffer, SRV); + mesh.flags |= SHADERMESH_FLAG_DOUBLE_SIDED; + + size_t instanceIndex = objects.GetCount() + args.jobIndex; + ShaderMeshInstance& inst = instanceData[instanceIndex]; + inst.init(); + inst.uid = entity; + // every vertex is pretransformed and simulated in worldspace for hair particle: + inst.transform.Create(IDENTITYMATRIX); + inst.transformPrev.Create(IDENTITYMATRIX); + inst.meshIndex = (uint)meshIndex; + + if (!TLAS_instances.empty()) + { + // TLAS instance data: + RaytracingAccelerationStructureDesc::TopLevel::Instance instance = {}; + instance = {}; + instance.transform = XMFLOAT3X4( + IDENTITYMATRIX._11, IDENTITYMATRIX._21, IDENTITYMATRIX._31, IDENTITYMATRIX._41, + IDENTITYMATRIX._12, IDENTITYMATRIX._22, IDENTITYMATRIX._32, IDENTITYMATRIX._42, + IDENTITYMATRIX._13, IDENTITYMATRIX._23, IDENTITYMATRIX._33, IDENTITYMATRIX._43 + ); + instance.InstanceID = (uint32_t)instanceIndex; + instance.InstanceMask = 1; + instance.bottomlevel = hair.BLAS; + instance.Flags = RaytracingAccelerationStructureDesc::TopLevel::Instance::FLAG_TRIANGLE_CULL_DISABLE; + + void* dest = (void*)((size_t)TLAS_instances.data() + instanceIndex * device->GetTopLevelAccelerationStructureInstanceSize()); + device->WriteTopLevelAccelerationStructureInstance(&instance, dest); + } } } @@ -3643,11 +3614,17 @@ namespace wiScene const XMUINT4& ind = mesh.vertex_boneindices[index]; const XMFLOAT4& wei = mesh.vertex_boneweights[index]; + const XMFLOAT4X4 mat[] = { + armature.boneData[ind.x].GetMatrix(), + armature.boneData[ind.y].GetMatrix(), + armature.boneData[ind.z].GetMatrix(), + armature.boneData[ind.w].GetMatrix(), + }; const XMMATRIX M[] = { - armature.boneData[ind.x].Load(), - armature.boneData[ind.y].Load(), - armature.boneData[ind.z].Load(), - armature.boneData[ind.w].Load(), + XMMatrixTranspose(XMLoadFloat4x4(&mat[0])), + XMMatrixTranspose(XMLoadFloat4x4(&mat[1])), + XMMatrixTranspose(XMLoadFloat4x4(&mat[2])), + XMMatrixTranspose(XMLoadFloat4x4(&mat[3])), }; XMVECTOR skinned; diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index 6e1d31278..66d307cc2 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -223,9 +223,7 @@ namespace wiScene int customShaderID = -1; // Non-serialized attributes: - wiGraphics::GPUBuffer constantBuffer; uint32_t layerMask = ~0u; - mutable bool dirty_buffer = false; // User stencil value can be in range [0, 15] inline void SetUserStencilRef(uint8_t value) @@ -324,6 +322,7 @@ namespace wiScene TERRAIN = 1 << 3, _DEPRECATED_DIRTY_MORPH = 1 << 4, _DEPRECATED_DIRTY_BINDLESS = 1 << 5, + TLAS_FORCE_DOUBLE_SIDED = 1 << 6, }; uint32_t _flags = RENDERABLE; @@ -384,9 +383,7 @@ namespace wiScene wiGraphics::GPUBuffer vertexBuffer_PRE; wiGraphics::GPUBuffer streamoutBuffer_POS; wiGraphics::GPUBuffer streamoutBuffer_TAN; - wiGraphics::GPUBuffer vertexBuffer_SUB; std::vector vertex_subsets; - wiGraphics::GPUBuffer descriptor; wiGraphics::GPUBuffer subsetBuffer; wiGraphics::RaytracingAccelerationStructure BLAS; @@ -399,12 +396,12 @@ namespace wiScene mutable BLAS_STATE BLAS_state = BLAS_STATE_NEEDS_REBUILD; // Only valid for 1 frame material component indices: - int terrain_material1_index = -1; - int terrain_material2_index = -1; - int terrain_material3_index = -1; + uint32_t terrain_material1_index = ~0u; + uint32_t terrain_material2_index = ~0u; + uint32_t terrain_material3_index = ~0u; mutable bool dirty_morph = false; - mutable bool dirty_bindless = true; + mutable bool dirty_subsets = true; inline void SetRenderable(bool value) { if (value) { _flags |= RENDERABLE; } else { _flags &= ~RENDERABLE; } } inline void SetDoubleSided(bool value) { if (value) { _flags |= DOUBLE_SIDED; } else { _flags &= ~DOUBLE_SIDED; } } @@ -596,7 +593,7 @@ namespace wiScene AABB aabb; XMFLOAT4 color; float fadeThresholdRadius; - std::vector instanceMatrices; + std::vector instances; mutable bool render_dirty = false; inline void SetDirty(bool value = true) { if (value) { _flags |= DIRTY; } else { _flags &= ~DIRTY; } } @@ -794,31 +791,7 @@ namespace wiScene // Non-serialized attributes: AABB aabb; - struct ShaderBoneType - { - XMFLOAT4 pose0; - XMFLOAT4 pose1; - XMFLOAT4 pose2; - - inline void Store(const XMMATRIX& M) - { - XMFLOAT4X4 mat; - XMStoreFloat4x4(&mat, M); - pose0 = XMFLOAT4(mat._11, mat._21, mat._31, mat._41); - pose1 = XMFLOAT4(mat._12, mat._22, mat._32, mat._42); - pose2 = XMFLOAT4(mat._13, mat._23, mat._33, mat._43); - } - inline XMMATRIX Load() const - { - return XMMATRIX( - pose0.x, pose1.x, pose2.x, 0, - pose0.y, pose1.y, pose2.y, 0, - pose0.z, pose1.z, pose2.z, 0, - pose0.w, pose1.w, pose2.w, 1 - ); - } - }; - std::vector boneData; + std::vector boneData; wiGraphics::GPUBuffer boneBuffer; void CreateRenderData(); @@ -1297,13 +1270,42 @@ namespace wiScene void SetAccelerationStructureUpdateRequested(bool value = true) { acceleration_structure_update_requested = value; } bool IsAccelerationStructureUpdateRequested() const { return acceleration_structure_update_requested; } + // Shader visible scene parameters: + ShaderScene shaderscene; + + // Instances for bindless visiblity indexing: + // contains in order: + // 1) objects + // 2) hair particles + std::vector instanceData; + wiGraphics::GPUBuffer instanceBuffer; + + // Meshes for bindless visiblity indexing: + // contains in order: + // 1) meshes + // 2) hair particles + std::vector meshData; + wiGraphics::GPUBuffer meshBuffer; + + std::vector materialData; + wiGraphics::GPUBuffer materialBuffer; + // Occlusion query state: wiGraphics::GPUQueryHeap queryHeap[arraysize(ObjectComponent::occlusionQueries)]; - std::vector queryResults; + wiGraphics::GPUBuffer queryResultBuffer[arraysize(queryHeap)]; uint32_t writtenQueries[arraysize(queryHeap)] = {}; int queryheap_idx = 0; std::atomic queryAllocator{ 0 }; + // Surfel GI resources: + wiGraphics::GPUBuffer surfelBuffer; + wiGraphics::GPUBuffer surfelDataBuffer; + wiGraphics::GPUBuffer surfelStatsBuffer; + wiGraphics::GPUBuffer surfelGridBuffer; + wiGraphics::GPUBuffer surfelCellBuffer; + wiGraphics::Texture surfelMomentsTexture; + + // Environment probe cubemap array state: static constexpr uint32_t envmapCount = 16; static constexpr uint32_t envmapRes = 128; @@ -1319,21 +1321,8 @@ namespace wiScene wiGraphics::Texture impostorArray; std::vector renderpasses_impostor; - // Atlas packing border size in pixels: - static constexpr int atlasClampBorder = 1; - - // Lightmap atlas state: - wiGraphics::Texture lightmap; - std::vector lightmap_rects; - std::atomic lightmap_rect_allocator{ 0 }; - mutable std::atomic_bool lightmap_repack_needed{ false }; mutable std::atomic_bool lightmap_refresh_needed{ false }; - // Decal atlas state: - wiGraphics::Texture decalAtlas; - mutable bool decal_repack_needed{ false }; - std::unordered_map, wiRectPacker::rect_xywh> packedDecals; - // Ocean GPU state: wiOcean ocean; void OceanRegenerate() { ocean.Create(weather.oceanParameters); } diff --git a/WickedEngine/wiShaderCompiler.cpp b/WickedEngine/wiShaderCompiler.cpp index 31a238aa7..8b36e3812 100644 --- a/WickedEngine/wiShaderCompiler.cpp +++ b/WickedEngine/wiShaderCompiler.cpp @@ -12,7 +12,7 @@ #ifdef PLATFORM_WINDOWS_DESKTOP #define SHADERCOMPILER_ENABLED #define SHADERCOMPILER_ENABLED_DXCOMPILER -#define SHADERCOMPILER_ENABLED_D3DCOMPILER +//#define SHADERCOMPILER_ENABLED_D3DCOMPILER #include // ComPtr #endif // _WIN32 @@ -57,6 +57,10 @@ namespace wiShaderCompiler //L"-no-legacy-cbuf-layout", //L"-pack-optimized", //L"-all-resources-bound", + //L"-Gis", // Force IEEE strictness + //L"-Gec", // Enable backward compatibility mode + //L"-Ges", // Enable strict mode + //L"-O0", // Optimization Level 0 }; if (input.flags & FLAG_DISABLE_OPTIMIZATION) diff --git a/WickedEngine/wiTextureHelper.cpp b/WickedEngine/wiTextureHelper.cpp index 2c71017cd..261c493e7 100644 --- a/WickedEngine/wiTextureHelper.cpp +++ b/WickedEngine/wiTextureHelper.cpp @@ -95,11 +95,9 @@ namespace wiTextureHelper texDesc.MipLevels = 1; texDesc.ArraySize = 6; texDesc.Format = FORMAT_R8G8B8A8_UNORM; - texDesc.CPUAccessFlags = 0; texDesc.SampleCount = 1; texDesc.Usage = USAGE_DEFAULT; texDesc.BindFlags = BIND_SHADER_RESOURCE; - texDesc.CPUAccessFlags = 0; texDesc.MiscFlags = RESOURCE_MISC_TEXTURECUBE; SubresourceData pData[6]; @@ -256,10 +254,7 @@ namespace wiTextureHelper textureDesc.ArraySize = 1; textureDesc.Format = format; textureDesc.SampleCount = 1; - textureDesc.Usage = USAGE_IMMUTABLE; textureDesc.BindFlags = BIND_SHADER_RESOURCE; - textureDesc.CPUAccessFlags = 0; - textureDesc.MiscFlags = 0; SubresourceData InitData; InitData.pSysMem = data; diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 0c1724b08..45c3ee405 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -7,9 +7,9 @@ namespace wiVersion // main engine core const int major = 0; // minor features, major updates, breaking compatibility changes - const int minor = 56; + const int minor = 57; // minor bug fixes, alterations, refactors, updates - const int revision = 85; + const int revision = 0; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision); diff --git a/WickedEngine/wiWidget.cpp b/WickedEngine/wiWidget.cpp index 424d3c598..c90cc018e 100644 --- a/WickedEngine/wiWidget.cpp +++ b/WickedEngine/wiWidget.cpp @@ -1326,8 +1326,7 @@ void wiComboBox::Render(const wiCanvas& canvas, CommandList cmd) const XMMatrixTranslation(translation.x + scale.x + 1 + scale.y * 0.5f, translation.y + scale.y * 0.5f, 0) * Projection ); - device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); - device->BindConstantBuffer(VS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CBSLOT_RENDERER_MISC, cmd); + device->BindDynamicConstantBuffer(cb, CBSLOT_RENDERER_MISC, cmd); const GPUBuffer* vbs[] = { &vb_triangle, }; @@ -2337,10 +2336,7 @@ void wiColorPicker::Render(const wiCanvas& canvas, CommandList cmd) const GPUBufferDesc desc; desc.BindFlags = BIND_VERTEX_BUFFER; desc.ByteWidth = (uint32_t)(vertices.size() * sizeof(Vertex)); - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; desc.StructureByteStride = 0; - desc.Usage = USAGE_IMMUTABLE; SubresourceData data; data.pSysMem = vertices.data(); device->CreateBuffer(&desc, &data, &vb_hue); @@ -2364,10 +2360,7 @@ void wiColorPicker::Render(const wiCanvas& canvas, CommandList cmd) const GPUBufferDesc desc; desc.BindFlags = BIND_VERTEX_BUFFER; desc.ByteWidth = (uint32_t)(vertices.size() * sizeof(Vertex)); - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; desc.StructureByteStride = 0; - desc.Usage = USAGE_IMMUTABLE; SubresourceData data; data.pSysMem = vertices.data(); device->CreateBuffer(&desc, &data, &vb_picker_saturation); @@ -2405,10 +2398,7 @@ void wiColorPicker::Render(const wiCanvas& canvas, CommandList cmd) const GPUBufferDesc desc; desc.BindFlags = BIND_VERTEX_BUFFER; desc.ByteWidth = (uint32_t)sizeof(vertices); - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; desc.StructureByteStride = 0; - desc.Usage = USAGE_IMMUTABLE; SubresourceData data; data.pSysMem = vertices; device->CreateBuffer(&desc, &data, &vb_picker_hue); @@ -2426,10 +2416,6 @@ void wiColorPicker::Render(const wiCanvas& canvas, CommandList cmd) const GPUBufferDesc desc; desc.BindFlags = BIND_VERTEX_BUFFER; desc.ByteWidth = (uint32_t)sizeof(vertices); - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - desc.StructureByteStride = 0; - desc.Usage = USAGE_IMMUTABLE; SubresourceData data; data.pSysMem = vertices; device->CreateBuffer(&desc, &data, &vb_preview); @@ -2442,7 +2428,6 @@ void wiColorPicker::Render(const wiCanvas& canvas, CommandList cmd) const const XMMATRIX Projection = canvas.GetProjection(); - device->BindConstantBuffer(VS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CBSLOT_RENDERER_MISC, cmd); device->BindPipelineState(&PSO_colored, cmd); ApplyScissor(canvas, scissorRect, cmd); @@ -2484,9 +2469,9 @@ void wiColorPicker::Render(const wiCanvas& canvas, CommandList cmd) const Projection ); cb.g_xColor = IsEnabled() ? float4(1, 1, 1, 1) : float4(0.5f, 0.5f, 0.5f, 1); - device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); + device->BindDynamicConstantBuffer(cb, CBSLOT_RENDERER_MISC, cmd); const GPUBuffer* vbs[] = { - vb_saturation.buffer, + &vb_saturation.buffer, }; const uint32_t strides[] = { sizeof(Vertex), @@ -2505,7 +2490,7 @@ void wiColorPicker::Render(const wiCanvas& canvas, CommandList cmd) const Projection ); cb.g_xColor = IsEnabled() ? float4(1, 1, 1, 1) : float4(0.5f, 0.5f, 0.5f, 1); - device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); + device->BindDynamicConstantBuffer(cb, CBSLOT_RENDERER_MISC, cmd); const GPUBuffer* vbs[] = { &vb_hue, }; @@ -2532,7 +2517,7 @@ void wiColorPicker::Render(const wiCanvas& canvas, CommandList cmd) const rgb result = hsv2rgb(source); cb.g_xColor = float4(1 - result.r, 1 - result.g, 1 - result.b, 1); - device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); + device->BindDynamicConstantBuffer(cb, CBSLOT_RENDERER_MISC, cmd); const GPUBuffer* vbs[] = { &vb_picker_hue, }; @@ -2583,7 +2568,7 @@ void wiColorPicker::Render(const wiCanvas& canvas, CommandList cmd) const Projection ); cb.g_xColor = float4(1 - final_color.toFloat3().x, 1 - final_color.toFloat3().y, 1 - final_color.toFloat3().z, 1); - device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); + device->BindDynamicConstantBuffer(cb, CBSLOT_RENDERER_MISC, cmd); const GPUBuffer* vbs[] = { &vb_picker_saturation, }; @@ -2602,7 +2587,7 @@ void wiColorPicker::Render(const wiCanvas& canvas, CommandList cmd) const Projection ); cb.g_xColor = final_color.toFloat4(); - device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); + device->BindDynamicConstantBuffer(cb, CBSLOT_RENDERER_MISC, cmd); const GPUBuffer* vbs[] = { &vb_preview, }; @@ -2990,8 +2975,7 @@ void wiTreeList::Render(const wiCanvas& canvas, CommandList cmd) const XMMatrixTranslation(open_box.pos.x + open_box.siz.x * 0.5f, open_box.pos.y + open_box.siz.y * 0.25f, 0) * Projection ); - device->UpdateBuffer(wiRenderer::GetConstantBuffer(CBTYPE_MISC), &cb, cmd); - device->BindConstantBuffer(VS, wiRenderer::GetConstantBuffer(CBTYPE_MISC), CBSLOT_RENDERER_MISC, cmd); + device->BindDynamicConstantBuffer(cb, CBSLOT_RENDERER_MISC, cmd); const GPUBuffer* vbs[] = { &vb_triangle, }; diff --git a/appveyor.yml b/appveyor.yml index 378cdfaa2..ecc6a78a7 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -12,7 +12,7 @@ before_build: build_script: - msbuild "C:\projects\wickedengine\WickedEngine.sln" /t:OfflineShaderCompiler /m /verbosity:minimal /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - cd "C:\projects\wickedengine\WickedEngine" - - call "../BUILD/x64/Release/OfflineShaderCompiler/OfflineShaderCompiler.exe" hlsl5 hlsl6 spirv shaderdump + - call "../BUILD/x64/Release/OfflineShaderCompiler/OfflineShaderCompiler.exe" hlsl6 spirv shaderdump - cd .. - msbuild "C:\projects\wickedengine\WickedEngine.sln" /t:rebuild /m /verbosity:minimal /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" diff --git a/credits.txt b/credits.txt index 0922cc00d..95050361e 100644 --- a/credits.txt +++ b/credits.txt @@ -37,4 +37,5 @@ Patreon supporters: - Quifeng Jin - TheGameCreators - Joseph Goldin +- Yuri
    2K&wO!E>b;o(E!&{0C+aS=kcg>kZld}Zs?2Rz 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%0AdCz7@F6l|9 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 GO8$4;(eWk# delta 10724 zcmeHNdt8iJAD`x#sVSvN_nI;(Dwk9uR5Ry{mQwCEB2rknY(;8g@sw=XNQ9@bySZPA zRV2HpIYX^WONm^@{gRNjtXoL$b58H$w(YyU;q(6S>hqbt=X}ra{Lb%Oe$Vfm=R7-~ z8y{e_Ogr=5{flYLGD>sGmKiLiy5|L$Q$afP;`L6pxTw9$f%X{Zz*Slp6X%{8g7J%k zR{j{l?Sepzse>}dV~i^fbiue<%h?cPS;Lt=7=1PyyJCzr=<0~^YjJ&djQ$HM#Te_> zrgy{mr^^UzBF!6quhJ9~$y9VNjQ$>BJuq%`>1=^9VYQhJMv=~}b{I`Y9@WM8;^0he zjE26ET`>-uMH4*>H`N>A{P=Cxy)cIG0xb4WP-;OzUzl~ooz1kyICWnUg>iFyD#-^_Q0};Wp63pU2p1$eyAsQvKkrF~&fr158|IG>8fJyD ze%>Z2#-zDXq+z!aw(dA@wc$81h!?t+^iY&JNfYy%Uo0h43BO7uBP9upZ-eH zIm|5)Zl8B~!zwWQ(OPIshOE@AmyON?7JG)T`33ronzteoUZ zdc^-GiZozuliCW)+1MwOHF7>_J{b{3?+Ii|ou~ZV8BOa?o%-4 zFRUYrD2ksj0_U?=yqtjXh;~>A#_{>yF&JfgFV4i6@Z6?9M$cc$!Z1#7&L&fr9B>NY ze78P43C1hk`*~ozC9Lg)acKs9&j}|&FT@fjHVrrbGUzYG{w7~#(5a$S)4=tM@OpYLOtSZfIPJ`CD+g{YoO(9 zV3U{S*}75%y7X-}U*oX1r(OJ!L;D>j^jcp!Pkz^>m-3NfJxG_#gyadqPJ$a-M~D5{ zv%h2BX8BQ%o#mYyoaNCXGuht$PD=4&1<2Kpel3snR>r=;_N6*X{Cb