Skip to content

Commit

Permalink
Vsm optimizations (#692)
Browse files Browse the repository at this point in the history
* split page listing and page alocation

#681

* fixup

* 8k vsm pool

* build

* new fog pages

#681

* fixup vms cluster culling

#681

* some tuning for vsm fog

#681

* Update vsm_cluster_task.comp

* epipolar fog initial

* vsm: epipolar fog in progress

#681

* fixup

* fixup

* fixup

* epipolar fog

* CI

* CI
  • Loading branch information
Try authored Nov 10, 2024
1 parent 0db60b0 commit 2f7f9ab
Show file tree
Hide file tree
Showing 30 changed files with 952 additions and 380 deletions.
5 changes: 3 additions & 2 deletions game/gothic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,10 @@ Gothic::Gothic() {
opts.doBindless = CommandLine::inst().isBindless();
}

if(hasBindless() && gpu.compute.maxInvocations>=1024) {
//TODO: productize
if(gpu.compute.maxInvocations>=1024 && gpu.render.maxClipCullDistances>=4 &&
gpu.render.maxViewportSize.w>=8192 && gpu.render.maxViewportSize.h>=8192) {
opts.doVirtualShadow = CommandLine::inst().isVirtualShadow();
opts.doVirtualFog = opts.doVirtualShadow;
}

opts.aaPreset = CommandLine::inst().aaPreset();
Expand Down
1 change: 1 addition & 0 deletions game/gothic.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class Gothic final {
bool doMeshShading = false;
bool doBindless = false;
bool doVirtualShadow = false;
bool doVirtualFog = false;
uint32_t swRenderingPreset = 0;

uint32_t aaPreset = 0;
Expand Down
9 changes: 4 additions & 5 deletions game/graphics/drawcommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,15 +238,14 @@ void DrawCommands::updateTasksUniforms() {
i.desc.set(T_Clusters, clusters.ssbo());
i.desc.set(T_Indirect, views[i.viewport].indirectCmd);
i.desc.set(T_Payload, views[i.viewport].visClusters);
i.desc.set(T_Scene, scene.uboGlobal[i.viewport]);
i.desc.set(T_Instance, owner.instanceSsbo());
i.desc.set(T_Bucket, buckets.ssbo());

if(i.viewport!=SceneGlobals::V_Vsm) {
i.desc.set(T_Scene, scene.uboGlobal[i.viewport]);
i.desc.set(T_Instance, owner.instanceSsbo());
i.desc.set(T_Bucket, buckets.ssbo());
i.desc.set(T_HiZ, *scene.hiZ);
} else {
i.desc.set(T_Scene, scene.uboGlobal[i.viewport]);
i.desc.set(T_Payload, views[i.viewport].vsmClusters);
i.desc.set(T_Payload, views[i.viewport].vsmClusters); //unsorted clusters
i.desc.set(T_HiZ, *scene.vsmPageHiZ);
i.desc.set(T_VsmPages, *scene.vsmPageList);
i.desc.set(8, scene.vsmDbg);
Expand Down
1 change: 1 addition & 0 deletions game/graphics/instancestorage.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <condition_variable>
#include <vector>
#include <thread>

#include "resources.h"

Expand Down
1 change: 0 additions & 1 deletion game/graphics/lightsource.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#pragma once

#include <Tempest/Point>
#include <array>
#include <vector>

#include <glm/vec4.hpp>
Expand Down
86 changes: 64 additions & 22 deletions game/graphics/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,10 @@ void Renderer::resetSwapchain() {

if(smSize>0) {
for(int i=0; i<Resources::ShadowLayers; ++i) {
if(settings.vsmEnabled && (i+1)!=Resources::ShadowLayers)
if(settings.vsmEnabled)
continue;
if(settings.vsmEnabled && !settings.giEnabled)
;//continue; //TODO: support vsm in gi code
shadowMap[i] = device.zbuffer(shadowFormat,smSize,smSize);
}
}
Expand Down Expand Up @@ -195,23 +197,32 @@ void Renderer::resetSwapchain() {
if(!vsm.pageDataCs.isEmpty())
vsm.uboClearPages = device.descriptors(Shaders::inst().vsmClearPages);

vsm.uboPages = device.descriptors(Shaders::inst().vsmMarkPages );
vsm.uboPages = device.descriptors(Shaders::inst().vsmMarkPages);
vsm.uboEpipole = device.descriptors(Shaders::inst().vsmFogEpipolar);
vsm.uboFogShadow = device.descriptors(Shaders::inst().vsmFogShadow);
vsm.uboFogSample = device.descriptors(Shaders::inst().vsmFogSample);
vsm.uboClump = device.descriptors(Shaders::inst().vsmClumpPages);
vsm.uboAlloc = device.descriptors(Shaders::inst().vsmAllocPages);
vsm.uboReproj = device.descriptors(Shaders::inst().vsmReprojectSm);

vsm.directLightPso = &Shaders::inst().vsmDirectLight;
vsm.pagesDbgPso = &Shaders::inst().vsmDbg;
vsm.uboLight = device.descriptors(*vsm.directLightPso);

vsm.pageTbl = device.image3d(TextureFormat::R32U, 32, 32, 16);
vsm.pageHiZ = device.image3d(TextureFormat::R32U, 32, 32, 16);
vsm.pageData = device.zbuffer(shadowFormat, 4096, 4096);
vsm.pageData = device.zbuffer(shadowFormat, 8192, 8192);
// vsm.pageDataCs = device.image2d(TextureFormat::R32U, 4096, 4096);

// vsm.ssTrace = device.image2d(TextureFormat::RGBA8, w, h);
vsm.ssTrace = device.image2d(TextureFormat::R32U, w, h);
vsm.epTrace = device.image2d(TextureFormat::R16, 2048, 2*1024);
vsm.epipoles = device.ssbo(nullptr, uint32_t(vsm.epTrace.h())*6*sizeof(float));

const int32_t VSM_PAGE_SIZE = 128;
auto pageCount = uint32_t((vsm.pageData.w()+VSM_PAGE_SIZE-1)/VSM_PAGE_SIZE) * uint32_t((vsm.pageData.h()+VSM_PAGE_SIZE-1)/VSM_PAGE_SIZE);
vsm.pageList = device.ssbo(nullptr, (pageCount + 4 + 16*4)*sizeof(uint32_t));
auto pageCount = uint32_t(vsm.pageData.w()/VSM_PAGE_SIZE) * uint32_t(vsm.pageData.h()/VSM_PAGE_SIZE);
auto pageSsboSize = Shaders::inst().vsmClear.sizeOfBuffer(0, pageCount);

vsm.pageList = device.ssbo(nullptr, pageSsboSize);
}

if(settings.swrEnabled) {
Expand Down Expand Up @@ -466,6 +477,26 @@ void Renderer::prepareUniforms() {
vsm.uboPages.set(5, vsm.pageHiZ);
//vsm.uboPages.set(7, vsm.pageList);

vsm.uboEpipole.set(0, vsm.ssTrace);
vsm.uboEpipole.set(1, vsm.epTrace);
vsm.uboEpipole.set(2, wview->sceneGlobals().uboGlobal[SceneGlobals::V_Main]);
vsm.uboEpipole.set(3, vsm.epipoles);
vsm.uboEpipole.set(4, zbuffer);
vsm.uboEpipole.set(5, vsm.pageTbl);
vsm.uboEpipole.set(6, vsm.pageData);

vsm.uboFogShadow.set(0, vsm.epTrace);
vsm.uboFogShadow.set(1, wview->sceneGlobals().uboGlobal[SceneGlobals::V_Main]);
vsm.uboFogShadow.set(2, vsm.epipoles);
vsm.uboFogShadow.set(3, vsm.pageTbl);
vsm.uboFogShadow.set(4, vsm.pageData);

vsm.uboFogSample.set(0, vsm.ssTrace);
vsm.uboFogSample.set(1, vsm.epTrace);
vsm.uboFogSample.set(2, wview->sceneGlobals().uboGlobal[SceneGlobals::V_Main]);
vsm.uboFogSample.set(3, vsm.epipoles);
vsm.uboFogSample.set(4, zbuffer);

vsm.uboClump.set(0, vsm.pageList);
vsm.uboClump.set(1, vsm.pageTbl);

Expand All @@ -482,13 +513,7 @@ void Renderer::prepareUniforms() {
if(!vsm.pageDataCs.isEmpty())
vsm.uboLight.set(6, vsm.pageDataCs); else
vsm.uboLight.set(6, vsm.pageData);

vsm.uboReproj.set(0, wview->sceneGlobals().uboGlobal[SceneGlobals::V_Main]);
vsm.uboReproj.set(1, vsm.pageTbl);
vsm.uboReproj.set(2, vsm.pageList);
if(!vsm.pageDataCs.isEmpty())
vsm.uboReproj.set(3, vsm.pageDataCs); else
vsm.uboReproj.set(3, vsm.pageData);
vsm.uboLight.set(8, wview->sceneGlobals().vsmDbg);
}

if(settings.swrEnabled) {
Expand All @@ -506,6 +531,7 @@ void Renderer::prepareUniforms() {
}
wview->setShadowMaps(sh);
wview->setVirtualShadowMap(vsm.pageData, vsm.pageDataCs, vsm.pageTbl, vsm.pageHiZ, vsm.pageList);
wview->setVsmSkyShadows(vsm.ssTrace);
wview->setSwRenderingImage(swr.outputImage);

wview->setHiZ(textureCast<const Texture2d&>(hiz.hiZ));
Expand Down Expand Up @@ -584,7 +610,8 @@ void Renderer::dbgDraw(Tempest::Painter& p) {
//tex.push_back(&textureCast(hiz.hiZSm1));
//tex.push_back(&textureCast(shadowMap[1]));
//tex.push_back(&textureCast<const Texture2d&>(shadowMap[0]));
tex.push_back(&textureCast<const Texture2d&>(vsm.pageData));
//tex.push_back(&textureCast<const Texture2d&>(vsm.pageData));
tex.push_back(&textureCast<const Texture2d&>(vsm.ssTrace));

static int size = 400;
int left = 10;
Expand Down Expand Up @@ -873,7 +900,12 @@ void Renderer::drawVsm(Tempest::Encoder<Tempest::CommandBuffer>& cmd, uint8_t fI
cmd.setUniforms(shaders.vsmMarkPages, vsm.uboPages, &settings.vsmMipBias, sizeof(settings.vsmMipBias));
cmd.dispatchThreads(zbuffer.size());

wview.vsmMarkSkyPages(cmd, fId);
// sky&fog
if(true && wview.sky().isVolumetric()) {
cmd.setUniforms(shaders.vsmMarkFogPages, vsm.uboPages);
cmd.dispatchThreads(zbuffer.size());
// wview.vsmMarkSkyPages(cmd, fId);
}

if(vsm.pageDataCs.isEmpty()) {
// trimming
Expand All @@ -890,6 +922,10 @@ void Renderer::drawVsm(Tempest::Encoder<Tempest::CommandBuffer>& cmd, uint8_t fI
cmd.dispatchThreads(size_t(vsm.pageDataCs.w()), size_t(vsm.pageDataCs.h()));
}

// list?
cmd.setUniforms(shaders.vsmListPages, vsm.uboAlloc);
cmd.dispatch(size_t(vsm.pageTbl.d()));

// alloc
cmd.setUniforms(shaders.vsmAllocPages, vsm.uboAlloc);
cmd.dispatch(1);
Expand All @@ -904,13 +940,19 @@ void Renderer::drawVsm(Tempest::Encoder<Tempest::CommandBuffer>& cmd, uint8_t fI
cmd.setFramebuffer({}, {vsm.pageData, 0.f, Tempest::Preserve});
wview.drawVsm(cmd,fId);

if(false) {
cmd.setDebugMarker("VSM-reproject");
cmd.setFramebuffer({}, {shadowMap[1], 0.f, Tempest::Preserve});
auto viewShadowLwcInv = shadowMatrix[1];
viewShadowLwcInv.inverse();
cmd.setUniforms(shaders.vsmReprojectSm, vsm.uboReproj, &viewShadowLwcInv, sizeof(viewShadowLwcInv));
cmd.draw(Resources::fsqVbo());
if(Gothic::inst().options().doVirtualFog) {
cmd.setFramebuffer({});
cmd.setDebugMarker("VSM-epipolar");
cmd.setUniforms(shaders.vsmFogEpipolar, vsm.uboEpipole);
cmd.dispatch(uint32_t(vsm.epTrace.h()));

cmd.setDebugMarker("VSM-epipolar-fog");
cmd.setUniforms(shaders.vsmFogShadow, vsm.uboFogShadow);
cmd.dispatchThreads(vsm.epTrace.size());

cmd.setDebugMarker("VSM-epipolar-fog");
cmd.setUniforms(shaders.vsmFogSample, vsm.uboFogSample);
cmd.dispatchThreads(zbuffer.size());
}
}

Expand Down
7 changes: 6 additions & 1 deletion game/graphics/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class Renderer final {

float vidResIndex = 0;

float vsmMipBias = -0.25;
float vsmMipBias = 0.25; //TODO: set to lower, eventually
} settings;

Frustrum frustrum[SceneGlobals::V_Count];
Expand Down Expand Up @@ -217,6 +217,7 @@ class Renderer final {
Tempest::DescriptorSet uboClearPages;
Tempest::DescriptorSet uboPages;
Tempest::DescriptorSet uboReproj;
Tempest::DescriptorSet uboEpipole, uboFogSample, uboFogShadow;

Tempest::DescriptorSet uboClump, uboAlloc;

Expand All @@ -229,6 +230,10 @@ class Renderer final {
Tempest::StorageImage pageDataCs;
Tempest::ZBuffer pageData;
Tempest::StorageBuffer pageList;

Tempest::StorageImage ssTrace;
Tempest::StorageImage epTrace;
Tempest::StorageBuffer epipoles;
} vsm;

struct {
Expand Down
8 changes: 7 additions & 1 deletion game/graphics/sceneglobals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ SceneGlobals::SceneGlobals() {
vsmPageData = &Resources::fallbackBlack();
vsmPageTbl = &Resources::fallbackImage3d();
vsmPageHiZ = &Resources::fallbackImage3d();
vsmDbg = device.image2d(Tempest::TextureFormat::R32U, 32, 32);
vsmDbg = device.image2d(Tempest::TextureFormat::R32U, 64, 64);

skyShadows = &Resources::fallbackImage();

for(uint8_t lay=0; lay<V_Count; ++lay) {
uboGlobal[lay] = device.ssbo(nullptr,sizeof(UboGlobal));
Expand Down Expand Up @@ -228,6 +230,10 @@ void SceneGlobals::setVirtualShadowMap(const Tempest::ZBuffer& pageData,
vsmPageList = &pageList;
}

void SceneGlobals::setVsmSkyShadows(const Tempest::StorageImage& sh) {
skyShadows = &sh;
}

void SceneGlobals::setSwRenderingImage(const Tempest::StorageImage& mainView) {
swMainImage = &mainView;
}
Expand Down
7 changes: 5 additions & 2 deletions game/graphics/sceneglobals.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class SceneGlobals final {
const Tempest::StorageImage& pageTbl,
const Tempest::StorageImage& pageHiZ,
const Tempest::StorageBuffer& vsmPageList);
void setVsmSkyShadows(const Tempest::StorageImage& skyShadows);
void setSwRenderingImage(const Tempest::StorageImage& mainView);

const Tempest::Matrix4x4& viewProject() const;
Expand Down Expand Up @@ -82,9 +83,11 @@ class SceneGlobals final {
const Tempest::StorageImage* vsmPageTbl = nullptr;
const Tempest::StorageImage* vsmPageHiZ = nullptr;
const Tempest::StorageBuffer* vsmPageList = nullptr;
Tempest::StorageImage vsmDbg;
Tempest::StorageImage vsmDbg;

const Tempest::StorageImage* swMainImage = nullptr;
const Tempest::StorageImage* skyShadows = nullptr;

const Tempest::StorageImage* swMainImage = nullptr;

struct UboGlobal final {
Tempest::Matrix4x4 viewProject;
Expand Down
44 changes: 18 additions & 26 deletions game/graphics/shaders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,32 +197,24 @@ Shaders::Shaders() {
if(Gothic::options().doVirtualShadow) {
vsmClusterTask = computeShader("vsm_cluster_task.comp.sprv");
// vsmClusterTask = computeShader("vsm_cluster_task2.comp.sprv");
vsmClear = computeShader("vsm_clear.comp.sprv");
vsmClearPages = computeShader("vsm_clear_pages.comp.sprv");
vsmMarkPages = computeShader("vsm_mark_pages.comp.sprv");
vsmMarkSky = computeShader("fog3d_vsm_mark_pages.comp.sprv");
vsmTrimPages = computeShader("vsm_trim_pages.comp.sprv");
vsmClumpPages = computeShader("vsm_clump_pages.comp.sprv");
vsmAllocPages = computeShader("vsm_alloc_pages.comp.sprv");
vsmMergePages = computeShader("vsm_merge_pages.comp.sprv");
vsmPackDraw0 = computeShader("vsm_pack_draws0.comp.sprv");
vsmPackDraw1 = computeShader("vsm_pack_draws1.comp.sprv");
vsmDirectLight = postEffect("copy", "direct_light_vsm", RenderState::ZTestMode::NoEqual);
// vsmReprojectSm = postEffect("copy", "vsm_reproject_sm", RenderState::ZTestMode::Always);
vsmDbg = postEffect("copy", "vsm_dbg", RenderState::ZTestMode::Always);
vsmRendering = computeShader("vsm_rendering.comp.sprv");
{
RenderState state;
state.setZWriteEnabled(true);
state.setZTestMode (RenderState::ZTestMode::Always);
state.setCullFaceMode (RenderState::CullMode::Front);

auto sh = GothicShader::get("copy.vert.sprv");
auto vs = device.shader(sh.data,sh.len);
sh = GothicShader::get("vsm_reproject_sm.frag.sprv");
auto fs = device.shader(sh.data,sh.len);
vsmReprojectSm = device.pipeline(Triangles,state,vs,fs);
}
vsmClear = computeShader("vsm_clear.comp.sprv");
vsmClearPages = computeShader("vsm_clear_pages.comp.sprv");
vsmMarkPages = computeShader("vsm_mark_pages.comp.sprv");
vsmMarkFogPages = computeShader("vsm_mark_fog_pages.comp.sprv");
vsmTrimPages = computeShader("vsm_trim_pages.comp.sprv");
vsmClumpPages = computeShader("vsm_clump_pages.comp.sprv");
vsmListPages = computeShader("vsm_list_pages.comp.sprv");
vsmAllocPages = computeShader("vsm_alloc_pages.comp.sprv");
vsmMergePages = computeShader("vsm_merge_pages.comp.sprv");
vsmPackDraw0 = computeShader("vsm_pack_draws0.comp.sprv");
vsmPackDraw1 = computeShader("vsm_pack_draws1.comp.sprv");
vsmFogEpipolar = computeShader("vsm_fog_epipolar.comp.sprv");
vsmFogShadow = computeShader("vsm_fog_shadow.comp.sprv");
vsmFogSample = computeShader("vsm_fog_sample.comp.sprv");

vsmDirectLight = postEffect("copy", "direct_light_vsm", RenderState::ZTestMode::NoEqual);
vsmDbg = postEffect("copy", "vsm_dbg", RenderState::ZTestMode::Always);
vsmRendering = computeShader("vsm_rendering.comp.sprv");
}

if(Gothic::options().swRenderingPreset>0) {
Expand Down
6 changes: 3 additions & 3 deletions game/graphics/shaders.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ class Shaders {

// Virtual shadow
Tempest::ComputePipeline vsmClusterTask;
Tempest::ComputePipeline vsmClear, vsmClearPages, vsmMarkPages, vsmMarkSky;
Tempest::ComputePipeline vsmTrimPages, vsmClumpPages, vsmAllocPages, vsmMergePages;
Tempest::ComputePipeline vsmClear, vsmClearPages, vsmMarkPages, vsmMarkFogPages;
Tempest::ComputePipeline vsmTrimPages, vsmListPages, vsmClumpPages, vsmAllocPages, vsmMergePages;
Tempest::ComputePipeline vsmPackDraw0, vsmPackDraw1;
Tempest::ComputePipeline vsmFogEpipolar, vsmFogShadow, vsmFogSample;
Tempest::RenderPipeline vsmDirectLight;
Tempest::RenderPipeline vsmReprojectSm;
Tempest::RenderPipeline vsmDbg;

Tempest::ComputePipeline vsmRendering;
Expand Down
Loading

0 comments on commit 2f7f9ab

Please sign in to comment.