diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 7137d7043..b1ed326b5 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -16,7 +16,7 @@ jobs: steps: - uses: actions/checkout@v3 with: - submodules: 'true' + submodules: recursive - uses: ilammy/msvc-dev-cmd@v1.10.0 @@ -28,7 +28,7 @@ jobs: run: cmake -S . --preset=ALL --check-stamp-file "build\CMakeFiles\generate.stamp" - name: cmake build - run: cmake --build build --config Release + run: cmake --build build/ALL --config Release - name: create a tagged release and upload the archive uses: ncipollo/release-action@v1 diff --git a/BuildRelease.bat b/BuildRelease.bat index 0a34cbe54..e283cc910 100644 --- a/BuildRelease.bat +++ b/BuildRelease.bat @@ -7,9 +7,9 @@ if NOT "%1" == "" ( echo Running preset %preset% -cmake -S . --preset=%preset% --check-stamp-file "build\CMakeFiles\generate.stamp" +cmake -S . --preset=%preset% --check-stamp-file "build\%preset%\CMakeFiles\generate.stamp" if %ERRORLEVEL% NEQ 0 exit 1 -cmake --build build --config Release +cmake --build build/%preset% --config Release if %ERRORLEVEL% NEQ 0 exit 1 pause \ No newline at end of file diff --git a/CMakePresets.json b/CMakePresets.json index 27998958b..c10f1e97d 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -12,20 +12,14 @@ "cacheVariables": { "SKSE_SUPPORT_XBYAK": "ON" }, - "binaryDir": "${sourceDir}/build" + "binaryDir": "${sourceDir}/build/${presetName}" }, { "name": "vcpkg", "hidden": true, "cacheVariables": { - "CMAKE_TOOLCHAIN_FILE": { - "type": "STRING", - "value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" - }, - "VCPKG_OVERLAY_PORTS": { - "type": "STRING", - "value": "${sourceDir}/cmake/ports/" - }, + "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake", + "VCPKG_OVERLAY_PORTS": "${sourceDir}/cmake/ports/", "VCPKG_TARGET_TRIPLET": "x64-windows-static-md" } }, @@ -53,7 +47,8 @@ } }, { - "name": "AE", + "name": "skyrim", + "hidden": true, "cacheVariables": { "BUILD_SKYRIM": true, "ENABLE_SKYRIM_AE": "ON", @@ -68,85 +63,64 @@ "msvc" ] }, + { + "name": "AE", + "cacheVariables": { + "ENABLE_SKYRIM_AE": "ON", + "ENABLE_SKYRIM_SE": "OFF", + "ENABLE_SKYRIM_VR": "OFF" + }, + "inherits": "skyrim" + }, { "name": "SE", "cacheVariables": { - "BUILD_SKYRIM": true, "ENABLE_SKYRIM_AE": "OFF", "ENABLE_SKYRIM_SE": "ON", "ENABLE_SKYRIM_VR": "OFF", "BUILD_TESTS": "OFF" }, - "inherits": [ - "common", - "vcpkg", - "win64", - "msvc" - ] + "inherits": "skyrim" }, { "name": "VR", "cacheVariables": { - "BUILD_SKYRIM": true, "ENABLE_SKYRIM_AE": "OFF", "ENABLE_SKYRIM_SE": "OFF", "ENABLE_SKYRIM_VR": "ON", "BUILD_TESTS": "OFF" }, - "inherits": [ - "common", - "vcpkg", - "win64", - "msvc" - ] + "inherits": "skyrim" }, { "name": "ALL", "cacheVariables": { - "BUILD_SKYRIM": true, "ENABLE_SKYRIM_AE": "ON", "ENABLE_SKYRIM_SE": "ON", "ENABLE_SKYRIM_VR": "ON", "BUILD_TESTS": "OFF" }, - "inherits": [ - "common", - "vcpkg", - "win64", - "msvc" - ] + "inherits": "skyrim" }, { "name": "PRE-AE", "cacheVariables": { - "BUILD_SKYRIM": true, "ENABLE_SKYRIM_AE": "OFF", "ENABLE_SKYRIM_SE": "ON", "ENABLE_SKYRIM_VR": "ON", "BUILD_TESTS": "OFF" }, - "inherits": [ - "common", - "vcpkg", - "win64", - "msvc" - ] + "inherits": "skyrim" }, { "name": "FLATRIM", "cacheVariables": { - "BUILD_SKYRIM": true, "ENABLE_SKYRIM_AE": "ON", "ENABLE_SKYRIM_SE": "ON", "ENABLE_SKYRIM_VR": "OFF", "BUILD_TESTS": "OFF" }, - "inherits": [ - "common", - "vcpkg", - "win64", - "msvc" - ] + "inherits": "skyrim" } ] } \ No newline at end of file diff --git a/extern/CommonLibSSE-NG b/extern/CommonLibSSE-NG index 4fba153e7..ebbfbb957 160000 --- a/extern/CommonLibSSE-NG +++ b/extern/CommonLibSSE-NG @@ -1 +1 @@ -Subproject commit 4fba153e75fa2941ab72b5e6da9f280494f52cbd +Subproject commit ebbfbb957a6a8d74e901eb1b40ed567f04b46994 diff --git a/features/Light Limit Fix/Shaders/LightLimitFix/ClusterCullingCS.hlsl b/features/Light Limit Fix/Shaders/LightLimitFix/ClusterCullingCS.hlsl index 59d52c5f6..7d5fc3567 100644 --- a/features/Light Limit Fix/Shaders/LightLimitFix/ClusterCullingCS.hlsl +++ b/features/Light Limit Fix/Shaders/LightLimitFix/ClusterCullingCS.hlsl @@ -11,9 +11,9 @@ cbuffer PerFrame : register(b0) StructuredBuffer clusters : register(t0); StructuredBuffer lights : register(t1); -RWStructuredBuffer lightIndexCounter : register(u0); //1 -RWStructuredBuffer lightIndexList : register(u1); //MAX_CLUSTER_LIGHTS * 16^3 -RWStructuredBuffer lightGrid : register(u2); //16^3 +RWStructuredBuffer lightIndexCounter : register(u0); +RWStructuredBuffer lightIndexList : register(u1); +RWStructuredBuffer lightGrid : register(u2); groupshared StructuredLight sharedLights[GROUP_SIZE]; @@ -25,14 +25,15 @@ bool LightIntersectsCluster(StructuredLight light, ClusterAABB cluster, int eyeI return dot(dist, dist) <= (light.radius * light.radius); } -[numthreads(16, 8, 8)] void main(uint3 groupId - : SV_GroupID, - uint3 dispatchThreadId - : SV_DispatchThreadID, - uint3 groupThreadId - : SV_GroupThreadID, - uint groupIndex - : SV_GroupIndex) { +[numthreads(NUMTHREAD_X, NUMTHREAD_Y, NUMTHREAD_Z)] void main( + uint3 groupId + : SV_GroupID, uint3 dispatchThreadId + : SV_DispatchThreadID, uint3 groupThreadId + : SV_GroupThreadID, uint groupIndex + : SV_GroupIndex) { + if (any(dispatchThreadId >= uint3(CLUSTER_BUILDING_DISPATCH_SIZE_X, CLUSTER_BUILDING_DISPATCH_SIZE_Y, CLUSTER_BUILDING_DISPATCH_SIZE_Z))) + return; + if (all(dispatchThreadId == 0)) { lightIndexCounter[0] = 0; } @@ -40,7 +41,9 @@ bool LightIntersectsCluster(StructuredLight light, ClusterAABB cluster, int eyeI uint visibleLightCount = 0; uint visibleLightIndices[MAX_CLUSTER_LIGHTS]; - uint clusterIndex = groupIndex + GROUP_SIZE * groupId.z; + uint clusterIndex = dispatchThreadId.x + + dispatchThreadId.y * CLUSTER_BUILDING_DISPATCH_SIZE_X + + dispatchThreadId.z * (CLUSTER_BUILDING_DISPATCH_SIZE_X * CLUSTER_BUILDING_DISPATCH_SIZE_Y); ClusterAABB cluster = clusters[clusterIndex]; @@ -61,11 +64,13 @@ bool LightIntersectsCluster(StructuredLight light, ClusterAABB cluster, int eyeI for (uint i = 0; i < batchSize; i++) { StructuredLight light = lights[i]; - if (visibleLightCount < MAX_CLUSTER_LIGHTS && (LightIntersectsCluster(light, cluster) + bool updateCluster = LightIntersectsCluster(light, cluster); #ifdef VR - || LightIntersectsCluster(light, cluster, 1) + updateCluster = updateCluster || LightIntersectsCluster(light, cluster, 1); #endif // VR - )) { + updateCluster = updateCluster && (visibleLightCount < MAX_CLUSTER_LIGHTS); + + if (updateCluster) { visibleLightIndices[visibleLightCount] = lightOffset + i; visibleLightCount++; } @@ -83,8 +88,11 @@ bool LightIntersectsCluster(StructuredLight light, ClusterAABB cluster, int eyeI lightIndexList[offset + i] = visibleLightIndices[i]; } - lightGrid[clusterIndex].offset = offset; - lightGrid[clusterIndex].lightCount = visibleLightCount; + LightGrid output = { + offset, visibleLightCount, 0, 0 + }; + + lightGrid[clusterIndex] = output; } //https://www.3dgep.com/forward-plus/#Grid_Frustums_Compute_Shader diff --git a/features/Light Limit Fix/Shaders/LightLimitFix/Common.hlsli b/features/Light Limit Fix/Shaders/LightLimitFix/Common.hlsli index df0c52f61..7e84f1df7 100644 --- a/features/Light Limit Fix/Shaders/LightLimitFix/Common.hlsli +++ b/features/Light Limit Fix/Shaders/LightLimitFix/Common.hlsli @@ -1,11 +1,10 @@ -#define GROUP_SIZE (16 * 16 * 4) +#define NUMTHREAD_X 16 +#define NUMTHREAD_Y 16 +#define NUMTHREAD_Z 4 +#define GROUP_SIZE (NUMTHREAD_X * NUMTHREAD_Y * NUMTHREAD_Z) #define MAX_CLUSTER_LIGHTS 128 -#define CLUSTER_BUILDING_DISPATCH_SIZE_X 16 -#define CLUSTER_BUILDING_DISPATCH_SIZE_Y 16 -#define CLUSTER_BUILDING_DISPATCH_SIZE_Z 16 - struct ClusterAABB { float4 minPoint; diff --git a/features/Light Limit Fix/Shaders/LightLimitFix/LightLimitFix.hlsli b/features/Light Limit Fix/Shaders/LightLimitFix/LightLimitFix.hlsli index d48fb9574..66576d0e9 100644 --- a/features/Light Limit Fix/Shaders/LightLimitFix/LightLimitFix.hlsli +++ b/features/Light Limit Fix/Shaders/LightLimitFix/LightLimitFix.hlsli @@ -31,15 +31,16 @@ StructuredBuffer strictLights : register(t53); bool GetClusterIndex(in float2 uv, in float z, out uint clusterIndex) { + const uint3 clusterSize = lightLimitFixSettings.ClusterSize.xyz; + if (z < strictLights[0].LightsNear || z > strictLights[0].LightsFar) return false; float clampedZ = clamp(z, strictLights[0].LightsNear, strictLights[0].LightsFar); - uint clusterZ = uint(max((log2(z) - log2(strictLights[0].LightsNear)) * 16.0 / log2(strictLights[0].LightsFar / strictLights[0].LightsNear), 0.0)); - uint2 clusterDim = ceil(BufferDim / float2(16, 16)); - uint3 cluster = uint3(uint2((uv * BufferDim) / clusterDim), clusterZ); + uint clusterZ = uint(max((log2(z) - log2(strictLights[0].LightsNear)) * clusterSize.z / log2(strictLights[0].LightsFar / strictLights[0].LightsNear), 0.0)); + uint3 cluster = uint3(uint2(uv * clusterSize.xy), clusterZ); - clusterIndex = cluster.x + (16 * cluster.y) + (16 * 16 * cluster.z); + clusterIndex = cluster.x + (clusterSize.x * cluster.y) + (clusterSize.x * clusterSize.y * cluster.z); return true; } diff --git a/features/Skylighting/Shaders/Skylighting/Skylighting.hlsli b/features/Skylighting/Shaders/Skylighting/Skylighting.hlsli index 42a369a8b..6f4df8251 100644 --- a/features/Skylighting/Shaders/Skylighting/Skylighting.hlsli +++ b/features/Skylighting/Shaders/Skylighting/Skylighting.hlsli @@ -132,29 +132,6 @@ namespace Skylighting return vl * step; } - // http://torust.me/ZH3.pdf - // ZH hallucination that makes skylighting more directional - // skipped luminance because it's single channel - float hallucinateZH3(sh2 sh, float3 normal) - { - const static float factor = sqrt(5.0f / (16.0f * 3.1415926f)); - - float result = shFuncProductIntegral(sh, shEvaluateCosineLobe(normal)) / shPI; // cosine lobe integral -> pi - if (all(abs(sh.yzw) < 1e-10)) - return result; - - float3 zonalAxis = normalize(sh.wyz); - float ratio = abs(dot(sh.wyz * float3(-1, -1, 0), zonalAxis)) / sh.x; - float zonalL2Coeff = sh.x * (0.08f * ratio + 0.6f * ratio * ratio); - - float fZ = dot(zonalAxis, normal); - float zhDir = factor * (3.0f * fZ * fZ - 1.0f); - - result += 0.25f * zonalL2Coeff * zhDir; - - return saturate(result); - } - sh2 fauxSpecularLobeSH(float3 N, float3 V, float roughness) { // https://www.gdcvault.com/play/1026701/Fast-Denoising-With-Self-Stabilizing diff --git a/package/Shaders/AmbientCompositeCS.hlsl b/package/Shaders/AmbientCompositeCS.hlsl index 88b2e8d71..59c17193f 100644 --- a/package/Shaders/AmbientCompositeCS.hlsl +++ b/package/Shaders/AmbientCompositeCS.hlsl @@ -68,7 +68,7 @@ RWTexture2D DiffuseAmbientRW : register(u1); # endif sh2 skylighting = Skylighting::sample(skylightingSettings, SkylightingProbeArray, positionMS.xyz, normalWS); - half skylightingDiffuse = Skylighting::hallucinateZH3(skylighting, skylightingSettings.DirectionalDiffuse ? normalWS : float3(0, 0, 1)); + half skylightingDiffuse = shFuncProductIntegral(skylighting, shEvaluateCosineLobe(skylightingSettings.DirectionalDiffuse ? normalWS : float3(0, 0, 1))); skylightingDiffuse = Skylighting::mixDiffuse(skylightingSettings, skylightingDiffuse); visibility = skylightingDiffuse; diff --git a/package/Shaders/Common/SharedData.hlsli b/package/Shaders/Common/SharedData.hlsli index 0830ed5c0..6d68c1772 100644 --- a/package/Shaders/Common/SharedData.hlsli +++ b/package/Shaders/Common/SharedData.hlsli @@ -112,6 +112,8 @@ struct LightLimitFixSettings uint EnableLightsVisualisation; uint LightsVisualisationMode; uint pad0; + + uint4 ClusterSize; }; # define SL_INCL_STRUCT diff --git a/package/Shaders/Lighting.hlsl b/package/Shaders/Lighting.hlsl index 8ffe667b7..4bca84323 100644 --- a/package/Shaders/Lighting.hlsl +++ b/package/Shaders/Lighting.hlsl @@ -327,7 +327,7 @@ VS_OUTPUT main(VS_INPUT input) vsout.ScreenNormalTransform1.xyz = ScreenNormalTransform[1]; vsout.ScreenNormalTransform2.xyz = ScreenNormalTransform[2]; # else - float3x4 transMat = mul((float4x3)(ScreenProj[eyeIndex]), World[eyeIndex]); + float3x4 transMat = mul(ScreenProj[eyeIndex], World[eyeIndex]); # if defined(MODELSPACENORMALS) vsout.ScreenNormalTransform0.xyz = transMat[0].xyz; @@ -2207,7 +2207,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace float3 reflectionDiffuseColor = diffuseColor + directionalAmbientColor; # if defined(SKYLIGHTING) - float skylightingDiffuse = Skylighting::hallucinateZH3(skylightingSH, skylightingSettings.DirectionalDiffuse ? worldSpaceNormal : float3(0, 0, 1)); + float skylightingDiffuse = shFuncProductIntegral(skylightingSH, shEvaluateCosineLobe(skylightingSettings.DirectionalDiffuse ? worldSpaceNormal : float3(0, 0, 1))); skylightingDiffuse = Skylighting::mixDiffuse(skylightingSettings, skylightingDiffuse); directionalAmbientColor = sRGB2Lin(directionalAmbientColor); directionalAmbientColor *= skylightingDiffuse; diff --git a/package/Shaders/RunGrass.hlsl b/package/Shaders/RunGrass.hlsl index 47c11c327..3c36c37f2 100644 --- a/package/Shaders/RunGrass.hlsl +++ b/package/Shaders/RunGrass.hlsl @@ -653,7 +653,7 @@ PS_OUTPUT main(PS_INPUT input, bool frontFace # endif sh2 skylightingSH = Skylighting::sample(skylightingSettings, SkylightingProbeArray, positionMSSkylight, normal); - float skylighting = Skylighting::hallucinateZH3(skylightingSH, skylightingSettings.DirectionalDiffuse ? normal : float3(0, 0, 1)); + float skylighting = shFuncProductIntegral(skylightingSH, shEvaluateCosineLobe(skylightingSettings.DirectionalDiffuse ? normal : float3(0, 0, 1))); skylighting = Skylighting::mixDiffuse(skylightingSettings, skylighting); directionalAmbientColor = sRGB2Lin(directionalAmbientColor); diff --git a/src/Buffer.h b/src/Buffer.h index baefca215..c2d2557f8 100644 --- a/src/Buffer.h +++ b/src/Buffer.h @@ -83,12 +83,14 @@ class ConstantBuffer }; template -D3D11_BUFFER_DESC StructuredBufferDesc(UINT a_count = 1) +D3D11_BUFFER_DESC StructuredBufferDesc(UINT a_count = 1, bool cpu_access = true) { D3D11_BUFFER_DESC desc{}; ZeroMemory(&desc, sizeof(desc)); - desc.Usage = D3D11_USAGE_DYNAMIC; + desc.Usage = cpu_access ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + if (!cpu_access) + desc.BindFlags = desc.BindFlags | D3D11_BIND_UNORDERED_ACCESS; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; desc.StructureByteStride = sizeof(T); diff --git a/src/Features/CloudShadows.cpp b/src/Features/CloudShadows.cpp index fc978f649..b228f92fb 100644 --- a/src/Features/CloudShadows.cpp +++ b/src/Features/CloudShadows.cpp @@ -17,31 +17,6 @@ void CloudShadows::CheckResourcesSide(int side) context->ClearRenderTargetView(cubemapCloudOccRTVs[side], black); } -class BSSkyShaderProperty : public RE::BSShaderProperty -{ -public: - enum SkyObject - { - SO_SUN = 0x0, - SO_SUN_GLARE = 0x1, - SO_ATMOSPHERE = 0x2, - SO_CLOUDS = 0x3, - SO_SKYQUAD = 0x4, - SO_STARS = 0x5, - SO_MOON = 0x6, - SO_MOON_SHADOW = 0x7, - }; - - RE::NiColorA kBlendColor; - RE::NiSourceTexture* pBaseTexture; - RE::NiSourceTexture* pBlendTexture; - char _pad0[0x10]; - float fBlendValue; - uint16_t usCloudLayer; - bool bFadeSecondTexture; - uint32_t uiSkyObjectType; -}; - void CloudShadows::ModifySky(RE::BSRenderPass* Pass) { auto shadowState = RE::BSGraphics::RendererShadowState::GetSingleton(); @@ -51,9 +26,9 @@ void CloudShadows::ModifySky(RE::BSRenderPass* Pass) if (cubeMapRenderTarget != RE::RENDER_TARGETS_CUBEMAP::kREFLECTIONS) return; - auto skyProperty = static_cast(Pass->shaderProperty); + auto skyProperty = static_cast(Pass->shaderProperty); - if (skyProperty->uiSkyObjectType == BSSkyShaderProperty::SkyObject::SO_CLOUDS) { + if (skyProperty->uiSkyObjectType == RE::BSSkyShaderProperty::SkyObject::SO_CLOUDS) { auto renderer = RE::BSGraphics::Renderer::GetSingleton(); auto& context = State::GetSingleton()->context; diff --git a/src/Features/LightLimitFix.cpp b/src/Features/LightLimitFix.cpp index a5ed12417..76e6608af 100644 --- a/src/Features/LightLimitFix.cpp +++ b/src/Features/LightLimitFix.cpp @@ -5,13 +5,8 @@ #include "State.h" #include "Util.h" -static constexpr uint CLUSTER_SIZE_X = 16; -static constexpr uint CLUSTER_SIZE_Y = 16; -static constexpr uint CLUSTER_SIZE_Z = 16; constexpr uint CLUSTER_MAX_LIGHTS = 128; -constexpr std::uint32_t CLUSTER_COUNT = CLUSTER_SIZE_X * CLUSTER_SIZE_Y * CLUSTER_SIZE_Z; - static constexpr uint MAX_LIGHTS = 2048; NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT( @@ -125,14 +120,33 @@ LightLimitFix::PerFrame LightLimitFix::GetCommonBufferData() perFrame.EnableContactShadows = settings.EnableContactShadows; perFrame.EnableLightsVisualisation = settings.EnableLightsVisualisation; perFrame.LightsVisualisationMode = settings.LightsVisualisationMode; + std::copy(clusterSize, clusterSize + 3, perFrame.ClusterSize); return perFrame; } void LightLimitFix::SetupResources() { + auto screenSize = Util::ConvertToDynamic(State::GetSingleton()->screenSize); + if (REL::Module::IsVR()) + screenSize.x *= .5; + clusterSize[0] = ((uint)screenSize.x + 63) / 64; + clusterSize[1] = ((uint)screenSize.y + 63) / 64; + clusterSize[2] = 16; + uint clusterCount = clusterSize[0] * clusterSize[1] * clusterSize[2]; + { - clusterBuildingCS = (ID3D11ComputeShader*)Util::CompileShader(L"Data\\Shaders\\LightLimitFix\\ClusterBuildingCS.hlsl", {}, "cs_5_0"); - clusterCullingCS = (ID3D11ComputeShader*)Util::CompileShader(L"Data\\Shaders\\LightLimitFix\\ClusterCullingCS.hlsl", {}, "cs_5_0"); + std::string clusterSizeStrs[3]; + for (int i = 0; i < 3; ++i) + clusterSizeStrs[i] = std::format("{}", clusterSize[i]); + + std::vector> defines = { + { "CLUSTER_BUILDING_DISPATCH_SIZE_X", clusterSizeStrs[0].c_str() }, + { "CLUSTER_BUILDING_DISPATCH_SIZE_Y", clusterSizeStrs[1].c_str() }, + { "CLUSTER_BUILDING_DISPATCH_SIZE_Z", clusterSizeStrs[2].c_str() } + }; + + clusterBuildingCS = (ID3D11ComputeShader*)Util::CompileShader(L"Data\\Shaders\\LightLimitFix\\ClusterBuildingCS.hlsl", defines, "cs_5_0"); + clusterCullingCS = (ID3D11ComputeShader*)Util::CompileShader(L"Data\\Shaders\\LightLimitFix\\ClusterCullingCS.hlsl", defines, "cs_5_0"); lightBuildingCB = new ConstantBuffer(ConstantBufferDesc()); lightCullingCB = new ConstantBuffer(ConstantBufferDesc()); @@ -156,7 +170,7 @@ void LightLimitFix::SetupResources() uavDesc.Buffer.FirstElement = 0; uavDesc.Buffer.Flags = 0; - std::uint32_t numElements = CLUSTER_COUNT; + std::uint32_t numElements = clusterCount; sbDesc.StructureByteStride = sizeof(ClusterAABB); sbDesc.ByteWidth = sizeof(ClusterAABB) * numElements; @@ -175,7 +189,7 @@ void LightLimitFix::SetupResources() uavDesc.Buffer.NumElements = numElements; lightCounter->CreateUAV(uavDesc); - numElements = CLUSTER_COUNT * CLUSTER_MAX_LIGHTS; + numElements = clusterCount * CLUSTER_MAX_LIGHTS; sbDesc.StructureByteStride = sizeof(uint32_t); sbDesc.ByteWidth = sizeof(uint32_t) * numElements; lightList = eastl::make_unique(sbDesc); @@ -184,7 +198,7 @@ void LightLimitFix::SetupResources() uavDesc.Buffer.NumElements = numElements; lightList->CreateUAV(uavDesc); - numElements = CLUSTER_COUNT; + numElements = clusterCount; sbDesc.StructureByteStride = sizeof(LightGrid); sbDesc.ByteWidth = sizeof(LightGrid) * numElements; lightGrid = eastl::make_unique(sbDesc); @@ -872,7 +886,7 @@ void LightLimitFix::UpdateLights() context->CSSetUnorderedAccessViews(0, 1, &clusters_uav, nullptr); context->CSSetShader(clusterBuildingCS, nullptr, 0); - context->Dispatch(CLUSTER_SIZE_X, CLUSTER_SIZE_Y, CLUSTER_SIZE_Z); + context->Dispatch(clusterSize[0], clusterSize[1], clusterSize[2]); ID3D11UnorderedAccessView* null_uav = nullptr; context->CSSetUnorderedAccessViews(0, 1, &null_uav, nullptr); @@ -908,7 +922,7 @@ void LightLimitFix::UpdateLights() context->CSSetUnorderedAccessViews(0, 3, uavs, nullptr); context->CSSetShader(clusterCullingCS, nullptr, 0); - context->Dispatch(CLUSTER_SIZE_X / 16, CLUSTER_SIZE_Y / 16, CLUSTER_SIZE_Z / 4); + context->Dispatch((clusterSize[0] + 15) / 16, (clusterSize[1] + 15) / 16, (clusterSize[2] + 3) / 4); } context->CSSetShader(nullptr, nullptr, 0); diff --git a/src/Features/LightLimitFix.h b/src/Features/LightLimitFix.h index 6bc3b3560..7d0acef10 100644 --- a/src/Features/LightLimitFix.h +++ b/src/Features/LightLimitFix.h @@ -74,6 +74,8 @@ struct LightLimitFix : Feature uint EnableLightsVisualisation; uint LightsVisualisationMode; uint pad0; + + uint ClusterSize[4]; }; PerFrame GetCommonBufferData(); @@ -171,6 +173,8 @@ struct LightLimitFix : Feature float lightsNear = 0.0f; float lightsFar = 16384.0f; + uint clusterSize[3] = { 16 }; + Settings settings; using ConfigPair = std::pair; diff --git a/src/Features/Skylighting.cpp b/src/Features/Skylighting.cpp index a1d88f24c..6f4273ac8 100644 --- a/src/Features/Skylighting.cpp +++ b/src/Features/Skylighting.cpp @@ -360,177 +360,21 @@ enum class ShaderTechnique BloodSplaterSplatter = 0x5C006074, }; -class BSUtilityShader : public RE::BSShader -{ -public: - enum class Flags - { - None = 0, - Vc = 1 << 0, - Texture = 1 << 1, - Skinned = 1 << 2, - Normals = 1 << 3, - BinormalTangent = 1 << 4, - AlphaTest = 1 << 7, - LodLandscape = 1 << 8, - RenderNormal = 1 << 9, - RenderNormalFalloff = 1 << 10, - RenderNormalClamp = 1 << 11, - RenderNormalClear = 1 << 12, - RenderDepth = 1 << 13, - RenderShadowmap = 1 << 14, - RenderShadowmapClamped = 1 << 15, - GrayscaleToAlpha = 1 << 15, - RenderShadowmapPb = 1 << 16, - AdditionalAlphaMask = 1 << 16, - DepthWriteDecals = 1 << 17, - DebugShadowSplit = 1 << 18, - DebugColor = 1 << 19, - GrayscaleMask = 1 << 20, - RenderShadowmask = 1 << 21, - RenderShadowmaskSpot = 1 << 22, - RenderShadowmaskPb = 1 << 23, - RenderShadowmaskDpb = 1 << 24, - RenderBaseTexture = 1 << 25, - TreeAnim = 1 << 26, - LodObject = 1 << 27, - LocalMapFogOfWar = 1 << 28, - OpaqueEffect = 1 << 29, - }; - - static BSUtilityShader* GetSingleton() - { - static REL::Relocation singleton{ RELOCATION_ID(528354, 415300) }; - return *singleton; - } - ~BSUtilityShader() override; // 00 - - // override (BSShader) - bool SetupTechnique(std::uint32_t globalTechnique) override; // 02 - void RestoreTechnique(std::uint32_t globalTechnique) override; // 03 - void SetupGeometry(RE::BSRenderPass* pass, uint32_t flags) override; // 06 - void RestoreGeometry(RE::BSRenderPass* pass, uint32_t flags) override; // 07 -}; - -struct RenderPassArray -{ - static RE::BSRenderPass* MakeRenderPass(RE::BSShader* shader, RE::BSShaderProperty* property, RE::BSGeometry* geometry, - uint32_t technique, uint8_t numLights, RE::BSLight** lights) - { - using func_t = decltype(&RenderPassArray::MakeRenderPass); - static REL::Relocation func{ RELOCATION_ID(100717, 107497) }; - return func(shader, property, geometry, technique, numLights, lights); - } - - static void ClearRenderPass(RE::BSRenderPass* pass) - { - using func_t = decltype(&RenderPassArray::ClearRenderPass); - static REL::Relocation func{ RELOCATION_ID(100718, 107498) }; - func(pass); - } - - void Clear() - { - while (head != nullptr) { - RE::BSRenderPass* next = head->next; - ClearRenderPass(head); - head = next; - } - head = nullptr; - } - - RE::BSRenderPass* EmplacePass(RE::BSShader* shader, RE::BSShaderProperty* property, RE::BSGeometry* geometry, - uint32_t technique, uint8_t numLights = 0, RE::BSLight* light0 = nullptr, RE::BSLight* light1 = nullptr, - RE::BSLight* light2 = nullptr, RE::BSLight* light3 = nullptr) - { - RE::BSLight* lights[4]; - lights[0] = light0; - lights[1] = light1; - lights[2] = light2; - lights[3] = light3; - auto* newPass = MakeRenderPass(shader, property, geometry, technique, numLights, lights); - if (head != nullptr) { - RE::BSRenderPass* lastPass = head; - while (lastPass->next != nullptr) { - lastPass = lastPass->next; - } - lastPass->next = newPass; - } else { - head = newPass; - } - return newPass; - } - - RE::BSRenderPass* head; // 00 - uint64_t unk08; // 08 -}; - -class BSBatchRenderer -{ -public: - struct PersistentPassList - { - RE::BSRenderPass* m_Head; - RE::BSRenderPass* m_Tail; - }; - - struct GeometryGroup - { - BSBatchRenderer* m_BatchRenderer; - PersistentPassList m_PassList; - uintptr_t UnkPtr4; - float m_Depth; // Distance from geometry to camera location - uint16_t m_Count; - uint8_t m_Flags; // Flags - }; - - struct PassGroup - { - RE::BSRenderPass* m_Passes[5]; - uint32_t m_ValidPassBits; // OR'd with (1 << PassIndex) - }; - - RE::BSTArray unk008; // 008 - RE::BSTHashMap unk020; // 020 - std::uint64_t unk050; // 050 - std::uint64_t unk058; // 058 - std::uint64_t unk060; // 060 - std::uint64_t unk068; // 068 - GeometryGroup* m_GeometryGroups[16]; - GeometryGroup* m_AlphaGroup; - void* unk1; - void* unk2; -}; - ////////////////////////////////////////////////////////////// -static void Precipitation_SetupMask(RE::Precipitation* a_This) -{ - using func_t = decltype(&Precipitation_SetupMask); - static REL::Relocation func{ REL::RelocationID(25641, 26183) }; - func(a_This); -} - -static void Precipitation_RenderMask(RE::Precipitation* a_This, BSParticleShaderRainEmitter* a_emitter) -{ - using func_t = decltype(&Precipitation_RenderMask); - static REL::Relocation func{ REL::RelocationID(25642, 26184) }; - func(a_This, a_emitter); -} - -void* Skylighting::BSLightingShaderProperty_GetPrecipitationOcclusionMapRenderPassesImpl::thunk( +RE::BSLightingShaderProperty::Data* Skylighting::BSLightingShaderProperty_GetPrecipitationOcclusionMapRenderPassesImpl::thunk( RE::BSLightingShaderProperty* property, RE::BSGeometry* geometry, [[maybe_unused]] uint32_t renderMode, [[maybe_unused]] RE::BSGraphics::BSShaderAccumulator* accumulator) { - auto batch = (BSBatchRenderer*)accumulator->GetRuntimeData().batchRenderer; - batch->m_GeometryGroups[14]->m_Flags &= ~1; + auto batch = accumulator->GetRuntimeData().batchRenderer; + batch->geometryGroups[14]->flags &= ~1; using enum RE::BSShaderProperty::EShaderPropertyFlag; - using enum BSUtilityShader::Flags; + using enum RE::BSUtilityShader::Flags; - auto* precipitationOcclusionMapRenderPassList = reinterpret_cast(&property->unk0C8); + auto* precipitationOcclusionMapRenderPassList = &property->unk0C8; precipitationOcclusionMapRenderPassList->Clear(); if (GetSingleton()->inOcclusion && !GetSingleton()->renderTrees) { @@ -543,11 +387,11 @@ void* Skylighting::BSLightingShaderProperty_GetPrecipitationOcclusionMapRenderPa if (property->flags.any(kZBufferWrite) && property->flags.none(kRefraction, kTempRefraction, kMultiTextureLandscape, kNoLODLandBlend, kLODLandscape, kEyeReflect, kDecal, kDynamicDecal, kAnisotropicLighting) && !(property->flags.any(kSkinned) && property->flags.none(kTreeAnim))) { if (geometry->worldBound.radius > GetSingleton()->boundSize) { - stl::enumeration technique; + stl::enumeration technique; technique.set(RenderDepth); auto pass = precipitationOcclusionMapRenderPassList->EmplacePass( - BSUtilityShader::GetSingleton(), + RE::BSUtilityShader::GetSingleton(), property, geometry, technique.underlying() + static_cast(ShaderTechnique::UtilityGeneralStart)); @@ -579,14 +423,14 @@ void Skylighting::Main_Precipitation_RenderOcclusion::thunk() precipObject = precip->lastPrecip; } if (precipObject) { - Precipitation_SetupMask(precip); - Precipitation_SetupMask(precip); // Calling setup twice fixes an issue when it is raining + precip->SetupMask(); + precip->SetupMask(); // Calling setup twice fixes an issue when it is raining auto effect = precipObject->GetGeometryRuntimeData().properties[RE::BSGeometry::States::kEffect]; auto shaderProp = netimmerse_cast(effect.get()); auto particleShaderProperty = netimmerse_cast(shaderProp); - auto rain = (BSParticleShaderRainEmitter*)(particleShaderProperty->particleEmitter); + auto rain = (RE::BSParticleShaderRainEmitter*)(particleShaderProperty->particleEmitter); - Precipitation_RenderMask(precip, rain); + precip->RenderMask(rain); } } @@ -648,21 +492,19 @@ void Skylighting::Main_Precipitation_RenderOcclusion::thunk() PrecipitationShaderDirection = { PrecipitationShaderDirectionF.x, PrecipitationShaderDirectionF.y, PrecipitationShaderDirectionF.z }; - Precipitation_SetupMask(precip); - Precipitation_SetupMask(precip); // Calling setup twice fixes an issue when it is raining + precip->SetupMask(); + precip->SetupMask(); // Calling setup twice fixes an issue when it is raining BSParticleShaderRainEmitter* rain = new BSParticleShaderRainEmitter; { TracyD3D11Zone(State::GetSingleton()->tracyCtx, "Skylighting - Render Height Map"); - Precipitation_RenderMask(precip, rain); + precip->RenderMask((RE::BSParticleShaderRainEmitter*)rain); } singleton->inOcclusion = false; - RE::BSParticleShaderCubeEmitter* cube = (RE::BSParticleShaderCubeEmitter*)rain; singleton->OcclusionDir = -float4{ PrecipitationShaderDirectionF.x, PrecipitationShaderDirectionF.y, PrecipitationShaderDirectionF.z, 0 }; - singleton->OcclusionTransform = cube->occlusionProjection; + singleton->OcclusionTransform = ((RE::BSParticleShaderRainEmitter*)rain)->occlusionProjection; - cube = nullptr; delete rain; PrecipitationShaderCubeSize = originalPrecipitationShaderCubeSize; diff --git a/src/Features/Skylighting.h b/src/Features/Skylighting.h index 64b7e76e2..1093b0871 100644 --- a/src/Features/Skylighting.h +++ b/src/Features/Skylighting.h @@ -98,7 +98,7 @@ struct Skylighting : Feature // Hooks struct BSLightingShaderProperty_GetPrecipitationOcclusionMapRenderPassesImpl { - static void* thunk(RE::BSLightingShaderProperty* property, RE::BSGeometry* geometry, uint32_t renderMode, RE::BSGraphics::BSShaderAccumulator* accumulator); + static RE::BSLightingShaderProperty::Data* thunk(RE::BSLightingShaderProperty* property, RE::BSGeometry* geometry, uint32_t renderMode, RE::BSGraphics::BSShaderAccumulator* accumulator); static inline REL::Relocation func; };