diff --git a/src/rendering/gl/system/gl_framebuffer.cpp b/src/rendering/gl/system/gl_framebuffer.cpp index 8ad6e60c02..88faa2ff2a 100644 --- a/src/rendering/gl/system/gl_framebuffer.cpp +++ b/src/rendering/gl/system/gl_framebuffer.cpp @@ -91,6 +91,7 @@ OpenGLFrameBuffer::~OpenGLFrameBuffer() if (mSkyData != nullptr) delete mSkyData; if (mViewpoints != nullptr) delete mViewpoints; if (mLights != nullptr) delete mLights; + mShadowMap.Reset(); if (GLRenderer) { diff --git a/src/rendering/hwrenderer/data/shaderuniforms.h b/src/rendering/hwrenderer/data/shaderuniforms.h index db593b8cbf..8937b6fb78 100644 --- a/src/rendering/hwrenderer/data/shaderuniforms.h +++ b/src/rendering/hwrenderer/data/shaderuniforms.h @@ -8,7 +8,10 @@ enum { LIGHTBUF_BINDINGPOINT = 1, POSTPROCESS_BINDINGPOINT = 2, - VIEWPOINT_BINDINGPOINT = 3 + VIEWPOINT_BINDINGPOINT = 3, + LIGHTNODES_BINDINGPOINT = 4, + LIGHTLINES_BINDINGPOINT = 5, + LIGHTLIST_BINDINGPOINT = 6 }; enum class UniformType diff --git a/src/rendering/hwrenderer/dynlights/hw_shadowmap.cpp b/src/rendering/hwrenderer/dynlights/hw_shadowmap.cpp index e563814e1a..2ae3cb092a 100644 --- a/src/rendering/hwrenderer/dynlights/hw_shadowmap.cpp +++ b/src/rendering/hwrenderer/dynlights/hw_shadowmap.cpp @@ -24,6 +24,7 @@ #include "hwrenderer/utility/hw_cvars.h" #include "hwrenderer/dynlights/hw_dynlightdata.h" #include "hwrenderer/data/buffers.h" +#include "hwrenderer/data/shaderuniforms.h" #include "stats.h" #include "g_levellocals.h" #include "v_video.h" @@ -188,7 +189,7 @@ void IShadowMap::UploadLights() CollectLights(); if (mLightList == nullptr) - mLightList = screen->CreateDataBuffer(4, true); + mLightList = screen->CreateDataBuffer(LIGHTLIST_BINDINGPOINT, true); mLightList->SetData(sizeof(float) * mLights.Size(), &mLights[0]); } @@ -199,11 +200,11 @@ void IShadowMap::UploadAABBTree() if (!ValidateAABBTree(&level)) { if (!mNodesBuffer) - mNodesBuffer = screen->CreateDataBuffer(2, true); + mNodesBuffer = screen->CreateDataBuffer(LIGHTNODES_BINDINGPOINT, true); mNodesBuffer->SetData(mAABBTree->NodesSize(), mAABBTree->Nodes()); if (!mLinesBuffer) - mLinesBuffer = screen->CreateDataBuffer(3, true); + mLinesBuffer = screen->CreateDataBuffer(LIGHTLINES_BINDINGPOINT, true); mLinesBuffer->SetData(mAABBTree->LinesSize(), mAABBTree->Lines()); } else if (mAABBTree->Update()) @@ -213,10 +214,15 @@ void IShadowMap::UploadAABBTree() } } -IShadowMap::~IShadowMap() +void IShadowMap::Reset() { - if (mLightList) delete mLightList; - if (mNodesBuffer) delete mNodesBuffer; - if (mLinesBuffer) delete mLinesBuffer; + delete mLightList; mLightList = nullptr; + delete mNodesBuffer; mNodesBuffer = nullptr; + delete mLinesBuffer; mLinesBuffer = nullptr; +} + +IShadowMap::~IShadowMap() +{ + Reset(); } diff --git a/src/rendering/hwrenderer/dynlights/hw_shadowmap.h b/src/rendering/hwrenderer/dynlights/hw_shadowmap.h index dc0cf40c7d..bf30dbd8a9 100644 --- a/src/rendering/hwrenderer/dynlights/hw_shadowmap.h +++ b/src/rendering/hwrenderer/dynlights/hw_shadowmap.h @@ -16,6 +16,8 @@ public: IShadowMap() { } virtual ~IShadowMap(); + void Reset(); + // Test if a world position is in shadow relative to the specified light and returns false if it is bool ShadowTest(FDynamicLight *light, const DVector3 &pos); diff --git a/src/rendering/hwrenderer/postprocessing/hw_postprocess.cpp b/src/rendering/hwrenderer/postprocessing/hw_postprocess.cpp index 8d6f9361a5..294cece47c 100644 --- a/src/rendering/hwrenderer/postprocessing/hw_postprocess.cpp +++ b/src/rendering/hwrenderer/postprocessing/hw_postprocess.cpp @@ -17,6 +17,7 @@ Postprocess::Postprocess() Managers.Push(new PPTonemap()); Managers.Push(new PPAmbientOcclusion()); Managers.Push(new PPPresent()); + Managers.Push(new PPShadowMap()); } Postprocess::~Postprocess() @@ -892,3 +893,32 @@ void PPPresent::UpdateTextures() void PPPresent::UpdateSteps() { } + +///////////////////////////////////////////////////////////////////////////// + +void PPShadowMap::DeclareShaders() +{ + hw_postprocess.Shaders["ShadowMap"] = { "shaders/glsl/shadowmap.fp", "", ShadowMapUniforms::Desc() }; +} + +void PPShadowMap::UpdateTextures() +{ +} + +void PPShadowMap::UpdateSteps() +{ + ShadowMapUniforms uniforms; + uniforms.ShadowmapQuality = (float)gl_shadowmap_quality; + + PPStep step; + step.ShaderName = "ShadowMap"; + step.Uniforms.Set(uniforms); + step.Viewport = { 0, 0, gl_shadowmap_quality, 1024 }; + step.SetShadowMapBuffers(true); + step.SetOutputShadowMap(); + step.SetNoBlend(); + + TArray steps; + steps.Push(step); + hw_postprocess.Effects["UpdateShadowMap"] = steps; +} diff --git a/src/rendering/hwrenderer/postprocessing/hw_postprocess.h b/src/rendering/hwrenderer/postprocessing/hw_postprocess.h index c35fb0c562..1e2dd28c39 100644 --- a/src/rendering/hwrenderer/postprocessing/hw_postprocess.h +++ b/src/rendering/hwrenderer/postprocessing/hw_postprocess.h @@ -11,7 +11,7 @@ typedef IntRect PPViewport; enum class PPFilterMode { Nearest, Linear }; enum class PPWrapMode { Clamp, Repeat }; -enum class PPTextureType { CurrentPipelineTexture, NextPipelineTexture, PPTexture, SceneColor, SceneFog, SceneNormal, SceneDepth, SwapChain }; +enum class PPTextureType { CurrentPipelineTexture, NextPipelineTexture, PPTexture, SceneColor, SceneFog, SceneNormal, SceneDepth, SwapChain, ShadowMap }; class PPTextureInput { @@ -120,6 +120,11 @@ public: tex.Texture = ""; } + void SetShadowMapBuffers(bool enable) + { + ShadowMapBuffers = enable; + } + void SetOutputTexture(PPTextureName texture) { Output.Type = PPTextureType::PPTexture; @@ -150,6 +155,12 @@ public: Output.Texture = ""; } + void SetOutputShadowMap() + { + Output.Type = PPTextureType::ShadowMap; + Output.Texture = ""; + } + void SetNoBlend() { BlendMode.BlendOp = STYLEOP_Add; @@ -180,6 +191,7 @@ public: PPViewport Viewport; PPBlendMode BlendMode; PPOutput Output; + bool ShadowMapBuffers = false; }; enum class PixelFormat @@ -658,3 +670,11 @@ struct ShadowMapUniforms }; } }; + +class PPShadowMap : public PPEffectManager +{ +public: + void DeclareShaders() override; + void UpdateTextures() override; + void UpdateSteps() override; +}; diff --git a/src/rendering/vulkan/renderer/vk_postprocess.cpp b/src/rendering/vulkan/renderer/vk_postprocess.cpp index 7c061a95c7..8cba3793fb 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.cpp +++ b/src/rendering/vulkan/renderer/vk_postprocess.cpp @@ -225,6 +225,23 @@ void VkPostprocess::ClearTonemapPalette() hw_postprocess.Textures.Remove("Tonemap.Palette"); } +void VkPostprocess::UpdateShadowMap() +{ + if (screen->mShadowMap.PerformUpdate()) + { + RenderEffect("UpdateShadowMap"); + + auto fb = GetVulkanFrameBuffer(); + auto buffers = fb->GetBuffers(); + + VkPPImageTransition imageTransition; + imageTransition.addImage(buffers->Shadowmap.get(), &buffers->ShadowmapLayout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false); + imageTransition.execute(fb->GetDrawCommands()); + + screen->mShadowMap.FinishUpdate(); + } +} + void VkPostprocess::BeginFrame() { mFrameDescriptorSets.clear(); @@ -233,6 +250,7 @@ void VkPostprocess::BeginFrame() { DescriptorPoolBuilder builder; builder.addPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 100); + builder.addPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 4); builder.setMaxSets(100); mDescriptorPool = builder.create(GetVulkanFrameBuffer()->device); mDescriptorPool->SetDebugName("VkPostprocess.mDescriptorPool"); @@ -405,10 +423,13 @@ void VkPostprocess::RenderEffect(const FString &name) key.Uniforms = step.Uniforms.Data.Size(); key.Shader = mShaders[step.ShaderName].get(); key.SwapChain = (step.Output.Type == PPTextureType::SwapChain); + key.ShadowMapBuffers = step.ShadowMapBuffers; if (step.Output.Type == PPTextureType::PPTexture) key.OutputFormat = mTextures[step.Output.Texture]->Format; else if (step.Output.Type == PPTextureType::SwapChain) key.OutputFormat = GetVulkanFrameBuffer()->swapChain->swapChainFormat.format; + else if (step.Output.Type == PPTextureType::ShadowMap) + key.OutputFormat = VK_FORMAT_R32_SFLOAT; else key.OutputFormat = VK_FORMAT_R16G16B16A16_SFLOAT; @@ -417,7 +438,7 @@ void VkPostprocess::RenderEffect(const FString &name) passSetup.reset(new VkPPRenderPassSetup(key)); int framebufferWidth = 0, framebufferHeight = 0; - VulkanDescriptorSet *input = GetInput(passSetup.get(), step.Textures); + VulkanDescriptorSet *input = GetInput(passSetup.get(), step.Textures, step.ShadowMapBuffers); VulkanFramebuffer *output = GetOutput(passSetup.get(), step.Output, framebufferWidth, framebufferHeight); RenderScreenQuad(passSetup.get(), input, output, framebufferWidth, framebufferHeight, step.Viewport.left, step.Viewport.top, step.Viewport.width, step.Viewport.height, step.Uniforms.Data.Data(), step.Uniforms.Data.Size()); @@ -470,7 +491,7 @@ void VkPostprocess::RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescr cmdbuffer->endRenderPass(); } -VulkanDescriptorSet *VkPostprocess::GetInput(VkPPRenderPassSetup *passSetup, const TArray &textures) +VulkanDescriptorSet *VkPostprocess::GetInput(VkPPRenderPassSetup *passSetup, const TArray &textures, bool bindShadowMapBuffers) { auto fb = GetVulkanFrameBuffer(); auto descriptors = mDescriptorPool->allocate(passSetup->DescriptorLayout.get()); @@ -489,6 +510,13 @@ VulkanDescriptorSet *VkPostprocess::GetInput(VkPPRenderPassSetup *passSetup, con imageTransition.addImage(tex.image, tex.layout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); } + if (bindShadowMapBuffers) + { + write.addBuffer(descriptors.get(), LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightNodes->mBuffer.get()); + write.addBuffer(descriptors.get(), LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightLines->mBuffer.get()); + write.addBuffer(descriptors.get(), LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->LightList->mBuffer.get()); + } + write.updateSets(fb->device); imageTransition.execute(fb->GetDrawCommands()); @@ -588,6 +616,13 @@ VkPostprocess::TextureImage VkPostprocess::GetTexture(const PPTextureType &type, tex.layout = &fb->GetBuffers()->SceneDepthStencilLayout; tex.debugname = "SceneDepth"; } + else if (type == PPTextureType::ShadowMap) + { + tex.image = fb->GetBuffers()->Shadowmap.get(); + tex.view = fb->GetBuffers()->ShadowmapView.get(); + tex.layout = &fb->GetBuffers()->ShadowmapLayout; + tex.debugname = "Shadowmap"; + } else if (type == PPTextureType::SwapChain) { tex.image = nullptr; @@ -639,6 +674,12 @@ void VkPPRenderPassSetup::CreateDescriptorLayout(const VkPPRenderPassKey &key) DescriptorSetLayoutBuilder builder; for (int i = 0; i < key.InputTextures; i++) builder.addBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + if (key.ShadowMapBuffers) + { + builder.addBinding(LIGHTNODES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.addBinding(LIGHTLINES_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + builder.addBinding(LIGHTLIST_BINDINGPOINT, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); + } DescriptorLayout = builder.create(GetVulkanFrameBuffer()->device); DescriptorLayout->SetDebugName("VkPPRenderPassSetup.DescriptorLayout"); } diff --git a/src/rendering/vulkan/renderer/vk_postprocess.h b/src/rendering/vulkan/renderer/vk_postprocess.h index 23a408b054..7cb009e583 100644 --- a/src/rendering/vulkan/renderer/vk_postprocess.h +++ b/src/rendering/vulkan/renderer/vk_postprocess.h @@ -25,6 +25,7 @@ public: PPBlendMode BlendMode; VkFormat OutputFormat; int SwapChain; + int ShadowMapBuffers; bool operator<(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) < 0; } bool operator==(const VkPPRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) == 0; } @@ -60,6 +61,8 @@ public: void BlurScene(float gameinfobluramount); void ClearTonemapPalette(); + void UpdateShadowMap(); + void BlitSceneToTexture(); void BlitCurrentToImage(VulkanImage *image, VkImageLayout *layout, VkImageLayout finallayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); void DrawPresentTexture(const IntRect &box, bool applyGamma, bool clearBorders); @@ -72,7 +75,7 @@ private: void NextEye(int eyeCount); void RenderScreenQuad(VkPPRenderPassSetup *passSetup, VulkanDescriptorSet *descriptorSet, VulkanFramebuffer *framebuffer, int framebufferWidth, int framebufferHeight, int x, int y, int width, int height, const void *pushConstants, uint32_t pushConstantsSize); - VulkanDescriptorSet *GetInput(VkPPRenderPassSetup *passSetup, const TArray &textures); + VulkanDescriptorSet *GetInput(VkPPRenderPassSetup *passSetup, const TArray &textures, bool bindShadowMapBuffers); VulkanFramebuffer *GetOutput(VkPPRenderPassSetup *passSetup, const PPOutput &output, int &framebufferWidth, int &framebufferHeight); VulkanSampler *GetSampler(PPFilterMode filter, PPWrapMode wrap); diff --git a/src/rendering/vulkan/renderer/vk_renderbuffers.cpp b/src/rendering/vulkan/renderer/vk_renderbuffers.cpp index 19f2dcc37b..2e8c0d7a52 100644 --- a/src/rendering/vulkan/renderer/vk_renderbuffers.cpp +++ b/src/rendering/vulkan/renderer/vk_renderbuffers.cpp @@ -55,6 +55,8 @@ void VkRenderBuffers::BeginFrame(int width, int height, int sceneWidth, int scen if (width != mWidth || height != mHeight || mSamples != samples) CreateScene(width, height, samples); + CreateShadowmap(); + mWidth = width; mHeight = height; mSamples = samples; @@ -206,3 +208,41 @@ void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlag SceneNormalView = viewbuilder.create(fb->device); SceneNormalView->SetDebugName("VkRenderBuffers.SceneNormalView"); } + +void VkRenderBuffers::CreateShadowmap() +{ + if (Shadowmap && Shadowmap->width == gl_shadowmap_quality) + return; + + Shadowmap.reset(); + ShadowmapView.reset(); + + auto fb = GetVulkanFrameBuffer(); + + ImageBuilder builder; + builder.setSize(gl_shadowmap_quality, 1024); + builder.setFormat(VK_FORMAT_R32_SFLOAT); + builder.setUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT); + Shadowmap = builder.create(fb->device); + Shadowmap->SetDebugName("VkRenderBuffers.Shadowmap"); + + ImageViewBuilder viewbuilder; + viewbuilder.setImage(Shadowmap.get(), VK_FORMAT_R32_SFLOAT); + ShadowmapView = viewbuilder.create(fb->device); + ShadowmapView->SetDebugName("VkRenderBuffers.ShadowmapView"); + + PipelineBarrier barrier; + barrier.addImage(Shadowmap.get(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 0, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT); + barrier.execute(fb->GetDrawCommands(), VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + + if (!ShadowmapSampler) + { + SamplerBuilder builder; + builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_NEAREST); + builder.setMinFilter(VK_FILTER_NEAREST); + builder.setMagFilter(VK_FILTER_NEAREST); + builder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE); + ShadowmapSampler = builder.create(fb->device); + ShadowmapSampler->SetDebugName("VkRenderBuffers.ShadowmapSampler"); + } +} diff --git a/src/rendering/vulkan/renderer/vk_renderbuffers.h b/src/rendering/vulkan/renderer/vk_renderbuffers.h index 8f425c1f78..2041852f0e 100644 --- a/src/rendering/vulkan/renderer/vk_renderbuffers.h +++ b/src/rendering/vulkan/renderer/vk_renderbuffers.h @@ -37,6 +37,11 @@ public: std::unique_ptr PipelineView[NumPipelineImages]; VkImageLayout PipelineLayout[NumPipelineImages]; + std::unique_ptr Shadowmap; + std::unique_ptr ShadowmapView; + std::unique_ptr ShadowmapSampler; + VkImageLayout ShadowmapLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + private: void CreatePipeline(int width, int height); void CreateScene(int width, int height, VkSampleCountFlagBits samples); @@ -44,6 +49,7 @@ private: void CreateSceneDepthStencil(int width, int height, VkSampleCountFlagBits samples); void CreateSceneFog(int width, int height, VkSampleCountFlagBits samples); void CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples); + void CreateShadowmap(); VkSampleCountFlagBits GetBestSampleCount(); int mWidth = 0; diff --git a/src/rendering/vulkan/renderer/vk_renderpass.cpp b/src/rendering/vulkan/renderer/vk_renderpass.cpp index 50b40e0c4c..18dfb99624 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.cpp +++ b/src/rendering/vulkan/renderer/vk_renderpass.cpp @@ -79,6 +79,7 @@ void VkRenderPassManager::CreateDynamicSetLayout() builder.addBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_FRAGMENT_BIT); builder.addBinding(2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); builder.addBinding(3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); + builder.addBinding(4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); DynamicSetLayout = builder.create(GetVulkanFrameBuffer()->device); DynamicSetLayout->SetDebugName("VkRenderPassManager.DynamicSetLayout"); } @@ -90,7 +91,6 @@ void VkRenderPassManager::CreateTextureSetLayout() { builder.addBinding(i, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); } - builder.addBinding(16, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT); TextureSetLayout = builder.create(GetVulkanFrameBuffer()->device); TextureSetLayout->SetDebugName("VkRenderPassManager.TextureSetLayout"); } @@ -119,13 +119,18 @@ void VkRenderPassManager::CreateDescriptorPool() void VkRenderPassManager::CreateDynamicSet() { DynamicSet = DescriptorPool->allocate(DynamicSetLayout.get()); +} +void VkRenderPassManager::UpdateDynamicSet() +{ auto fb = GetVulkanFrameBuffer(); + WriteDescriptors update; update.addBuffer(DynamicSet.get(), 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->ViewpointUBO->mBuffer.get(), 0, sizeof(HWViewpointUniforms)); update.addBuffer(DynamicSet.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, fb->LightBufferSSO->mBuffer.get(), 0, fb->GetLightBufferBlockSize()); update.addBuffer(DynamicSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->MatricesUBO->mBuffer.get(), 0, sizeof(MatricesUBO)); update.addBuffer(DynamicSet.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->StreamUBO->mBuffer.get(), 0, sizeof(StreamUBO)); + update.addCombinedImageSampler(DynamicSet.get(), 4, fb->GetBuffers()->ShadowmapView.get(), fb->GetBuffers()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); update.updateSets(fb->device); } diff --git a/src/rendering/vulkan/renderer/vk_renderpass.h b/src/rendering/vulkan/renderer/vk_renderpass.h index 9d94761c2f..195d940332 100644 --- a/src/rendering/vulkan/renderer/vk_renderpass.h +++ b/src/rendering/vulkan/renderer/vk_renderpass.h @@ -68,6 +68,7 @@ public: void Init(); void RenderBuffersReset(); + void UpdateDynamicSet(); VkRenderPassSetup *GetRenderPass(const VkRenderPassKey &key); int GetVertexFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs); diff --git a/src/rendering/vulkan/shaders/vk_shader.cpp b/src/rendering/vulkan/shaders/vk_shader.cpp index 67e5f82490..af3ba3740a 100644 --- a/src/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/rendering/vulkan/shaders/vk_shader.cpp @@ -139,6 +139,8 @@ static const char *shaderBindings = R"( StreamData data[256]; }; + layout(set = 0, binding = 4) uniform sampler2D ShadowMap; + // textures layout(set = 1, binding = 0) uniform sampler2D tex; layout(set = 1, binding = 1) uniform sampler2D texture2; @@ -146,7 +148,6 @@ static const char *shaderBindings = R"( layout(set = 1, binding = 3) uniform sampler2D texture4; layout(set = 1, binding = 4) uniform sampler2D texture5; layout(set = 1, binding = 5) uniform sampler2D texture6; - layout(set = 1, binding = 16) uniform sampler2D ShadowMap; // This must match the PushConstants struct layout(push_constant) uniform PushConstants @@ -207,7 +208,7 @@ static const char *shaderBindings = R"( #define uSplitTopPlane data[uDataIndex].uSplitTopPlane #define uSplitBottomPlane data[uDataIndex].uSplitBottomPlane - // #define SUPPORTS_SHADOWMAPS + #define SUPPORTS_SHADOWMAPS #define VULKAN_COORDINATE_SYSTEM #define HAS_UNIFORM_VERTEX_DATA )"; diff --git a/src/rendering/vulkan/system/vk_framebuffer.cpp b/src/rendering/vulkan/system/vk_framebuffer.cpp index a876cec1e4..b1eb24fdcc 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.cpp +++ b/src/rendering/vulkan/system/vk_framebuffer.cpp @@ -95,6 +95,7 @@ VulkanFrameBuffer::~VulkanFrameBuffer() delete mSkyData; delete mViewpoints; delete mLights; + mShadowMap.Reset(); } void VulkanFrameBuffer::InitializeState() @@ -390,10 +391,8 @@ sector_t *VulkanFrameBuffer::RenderViewpoint(FRenderViewpoint &mainvp, AActor * R_SetupFrame(mainvp, r_viewwindow, camera); -#if 0 if (mainview && toscreen) UpdateShadowMap(); -#endif // Update the attenuation flag of all light defaults for each viewpoint. // This function will only do something if the setting differs. @@ -629,14 +628,19 @@ IIndexBuffer *VulkanFrameBuffer::CreateIndexBuffer() IDataBuffer *VulkanFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo) { auto buffer = new VKDataBuffer(bindingpoint, ssbo); - if (bindingpoint == VIEWPOINT_BINDINGPOINT) + + auto fb = GetVulkanFrameBuffer(); + switch (bindingpoint) { - ViewpointUBO = buffer; - } - else if (bindingpoint == LIGHTBUF_BINDINGPOINT) - { - LightBufferSSO = buffer; + case LIGHTBUF_BINDINGPOINT: LightBufferSSO = buffer; break; + case VIEWPOINT_BINDINGPOINT: ViewpointUBO = buffer; break; + case LIGHTNODES_BINDINGPOINT: LightNodes = buffer; break; + case LIGHTLINES_BINDINGPOINT: LightLines = buffer; break; + case LIGHTLIST_BINDINGPOINT: LightList = buffer; break; + case POSTPROCESS_BINDINGPOINT: break; + default: break; } + return buffer; } @@ -758,6 +762,7 @@ void VulkanFrameBuffer::BeginFrame() mScreenBuffers->BeginFrame(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height); mSaveBuffers->BeginFrame(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT); mPostprocess->BeginFrame(); + mRenderPassManager->UpdateDynamicSet(); } void VulkanFrameBuffer::Draw2D() @@ -841,3 +846,8 @@ void VulkanFrameBuffer::CreateFanToTrisIndexBuffer() FanToTrisIndexBuffer.reset(CreateIndexBuffer()); FanToTrisIndexBuffer->SetData(sizeof(uint32_t) * data.Size(), data.Data()); } + +void VulkanFrameBuffer::UpdateShadowMap() +{ + mPostprocess->UpdateShadowMap(); +} diff --git a/src/rendering/vulkan/system/vk_framebuffer.h b/src/rendering/vulkan/system/vk_framebuffer.h index 68ea006ee0..fde969d2e5 100644 --- a/src/rendering/vulkan/system/vk_framebuffer.h +++ b/src/rendering/vulkan/system/vk_framebuffer.h @@ -44,6 +44,10 @@ public: VKDataBuffer *MatricesUBO = nullptr; VKDataBuffer *StreamUBO = nullptr; + VKDataBuffer *LightNodes = nullptr; + VKDataBuffer *LightLines = nullptr; + VKDataBuffer *LightList = nullptr; + std::unique_ptr FanToTrisIndexBuffer; std::vector> mFrameDeleteList; @@ -90,6 +94,7 @@ private: void CreateFanToTrisIndexBuffer(); void SubmitCommands(bool finish); void CopyScreenToBuffer(int w, int h, void *data); + void UpdateShadowMap(); std::unique_ptr mShaderManager; std::unique_ptr mSamplerManager; diff --git a/wadsrc/static/shaders/glsl/shadowmap.fp b/wadsrc/static/shaders/glsl/shadowmap.fp index 6333341246..e632929be0 100644 --- a/wadsrc/static/shaders/glsl/shadowmap.fp +++ b/wadsrc/static/shaders/glsl/shadowmap.fp @@ -20,17 +20,17 @@ struct GPULine vec2 delta; // Line end position - line start position }; -layout(std430, binding = 2) buffer LightNodes +layout(std430, binding = 4) buffer LightNodes { GPUNode nodes[]; }; -layout(std430, binding = 3) buffer LightLines +layout(std430, binding = 5) buffer LightLines { GPULine lines[]; }; -layout(std430, binding = 4) buffer LightList +layout(std430, binding = 6) buffer LightList { vec4 lights[]; };