From af6ec929cc774821322c668decb302c2e57fdca2 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Tue, 8 Jul 2025 02:59:10 +0200 Subject: [PATCH] Move lightmap atlas textures and light probes to the bindless textures array as its impossible to predict up front how many we need --- .../rendering/hwrenderer/data/hw_levelmesh.h | 2 +- .../hwrenderer/data/hw_renderstate.h | 5 +- .../descriptorsets/vk_descriptorset.cpp | 61 ++- .../vulkan/descriptorsets/vk_descriptorset.h | 11 + .../rendering/vulkan/shaders/vk_shader.cpp | 7 +- .../vulkan/textures/vk_imagetransition.h | 12 +- .../rendering/vulkan/textures/vk_texture.cpp | 364 ++++++++++-------- .../rendering/vulkan/textures/vk_texture.h | 21 +- .../rendering/vulkan/vk_lightmapper.cpp | 21 +- .../rendering/vulkan/vk_renderdevice.cpp | 6 +- .../rendering/vulkan/vk_renderstate.cpp | 2 + src/rendering/hwrenderer/hw_vertexbuilder.cpp | 16 +- .../shaders/lightmap/binding_textures.glsl | 1 + .../static/shaders/scene/binding_fixed.glsl | 19 +- .../shaders/scene/binding_textures.glsl | 1 + .../static/shaders/scene/layout_shared.glsl | 1 + wadsrc/static/shaders/scene/lightmode.glsl | 8 +- .../static/shaders/scene/lightmodel_pbr.glsl | 4 +- wadsrc/static/shaders/scene/vert_main.glsl | 6 +- 19 files changed, 318 insertions(+), 250 deletions(-) diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index dc482a9b9..85041ed1e 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -200,7 +200,7 @@ public: // Lightmap tiles and their locations in the texture atlas struct { - int TextureCount = 10; // To do: remove all the limits and instead resize GPU resources if they are exhausted. Too difficult to calculate it all up front. + int TextureCount = 1; int TextureSize = 1024; TArray TextureData; uint16_t SampleDistance = 8; diff --git a/src/common/rendering/hwrenderer/data/hw_renderstate.h b/src/common/rendering/hwrenderer/data/hw_renderstate.h index 89a2d13d8..c24816fe1 100644 --- a/src/common/rendering/hwrenderer/data/hw_renderstate.h +++ b/src/common/rendering/hwrenderer/data/hw_renderstate.h @@ -150,6 +150,7 @@ protected: int mLightIndex; int mBoneIndexBase; int mFogballIndex; + int mLightProbeIndex; int mSpecialEffect; int mTextureMode; int mTextureClamp; @@ -217,7 +218,7 @@ public: mSurfaceUniforms.uFogDensity = 0.0f; mSurfaceUniforms.uLightLevel = -1.0f; mSurfaceUniforms.uDepthFadeThreshold = 0.0f; - mSurfaceUniforms.uLightProbeIndex = 0; + mLightProbeIndex = 0; mSpecialEffect = EFF_NONE; mLightIndex = -1; mBoneIndexBase = -1; @@ -569,7 +570,7 @@ public: void SetLightProbeIndex(int index) { - mSurfaceUniforms.uLightProbeIndex = index; + mLightProbeIndex = index; } void SetRenderStyle(FRenderStyle rs) diff --git a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp index 51de680be..168346534 100644 --- a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp +++ b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.cpp @@ -144,24 +144,21 @@ void VkDescriptorSetManager::UpdateFixedSet() WriteDescriptors update; update.AddCombinedImageSampler(Fixed.Set.get(), 0, fb->GetTextureManager()->Shadowmap.View.get(), fb->GetSamplerManager()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - update.AddCombinedImageSampler(Fixed.Set.get(), 1, fb->GetTextureManager()->Lightmap.Image.View.get(), fb->GetSamplerManager()->LightmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - update.AddCombinedImageSampler(Fixed.Set.get(), 2, fb->GetBuffers()->SceneLinearDepth.View.get(), fb->GetSamplerManager()->Get(PPFilterMode::Nearest, PPWrapMode::Clamp), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - update.AddCombinedImageSampler(Fixed.Set.get(), 3, fb->GetTextureManager()->Irradiancemap.Image.View.get(), fb->GetSamplerManager()->IrradiancemapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - update.AddCombinedImageSampler(Fixed.Set.get(), 4, fb->GetTextureManager()->Prefiltermap.Image.View.get(), fb->GetSamplerManager()->PrefiltermapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + update.AddCombinedImageSampler(Fixed.Set.get(), 1, fb->GetBuffers()->SceneLinearDepth.View.get(), fb->GetSamplerManager()->Get(PPFilterMode::Nearest, PPWrapMode::Clamp), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); if (fb->IsRayQueryEnabled()) { - update.AddAccelerationStructure(Fixed.Set.get(), 5, fb->GetLevelMesh()->GetAccelStruct()); + update.AddAccelerationStructure(Fixed.Set.get(), 2, fb->GetLevelMesh()->GetAccelStruct()); } else { - update.AddBuffer(Fixed.Set.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetNodeBuffer()); + update.AddBuffer(Fixed.Set.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetNodeBuffer()); } - update.AddBuffer(Fixed.Set.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetVertexBuffer()); - update.AddBuffer(Fixed.Set.get(), 7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetIndexBuffer()); - update.AddBuffer(Fixed.Set.get(), 8, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceIndexBuffer()); - update.AddBuffer(Fixed.Set.get(), 9, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceBuffer()); - update.AddBuffer(Fixed.Set.get(), 10, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetPortalBuffer()); + update.AddBuffer(Fixed.Set.get(), 3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetVertexBuffer()); + update.AddBuffer(Fixed.Set.get(), 4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetIndexBuffer()); + update.AddBuffer(Fixed.Set.get(), 5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceIndexBuffer()); + update.AddBuffer(Fixed.Set.get(), 6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetSurfaceBuffer()); + update.AddBuffer(Fixed.Set.get(), 7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetPortalBuffer()); update.Execute(fb->GetDevice()); } @@ -175,6 +172,8 @@ void VkDescriptorSetManager::ResetHWTextureSets() colormap->Renderdev.bindIndex = -1; Colormaps.clear(); + LightProbes.clear(); + Bindless.Writer = WriteDescriptors(); Bindless.NextIndex = 0; @@ -186,6 +185,9 @@ void VkDescriptorSetManager::ResetHWTextureSets() // Slot 2 is always our game palette texture AddBindlessTextureIndex(fb->GetTextureManager()->GetGamePaletteView(), fb->GetSamplerManager()->Get(CLAMP_XY_NOMIP)); + + // Lightmap textures follow + Bindless.NextIndex = LightmapsStart + MaxLightmaps; } void VkDescriptorSetManager::AddMaterial(VkMaterial* texture) @@ -286,22 +288,19 @@ void VkDescriptorSetManager::CreateFixedLayout() DescriptorSetLayoutBuilder builder; builder.AddBinding(0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); builder.AddBinding(1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); - builder.AddBinding(2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); - builder.AddBinding(3, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); - builder.AddBinding(4, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); if (fb->IsRayQueryEnabled()) { - builder.AddBinding(5, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(2, VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); } else { - builder.AddBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); } + builder.AddBinding(3, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(4, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); + builder.AddBinding(5, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); builder.AddBinding(6, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); builder.AddBinding(7, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); - builder.AddBinding(8, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); - builder.AddBinding(9, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); - builder.AddBinding(10, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT); builder.DebugName("VkDescriptorSetManager.Fixed.SetLayout"); Fixed.Layout = builder.Create(fb->GetDevice()); } @@ -367,7 +366,7 @@ void VkDescriptorSetManager::CreateRSBufferPool() void VkDescriptorSetManager::CreateFixedPool() { DescriptorPoolBuilder poolbuilder; - poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 5 * MaxFixedSets); + poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 2 * MaxFixedSets); if (fb->IsRayQueryEnabled()) { poolbuilder.AddPoolSize(VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR, 1 * MaxFixedSets); @@ -406,6 +405,14 @@ void VkDescriptorSetManager::CreateBindlessSet() void VkDescriptorSetManager::UpdateBindlessDescriptorSet() { + auto sampler = fb->GetSamplerManager()->LightmapSampler.get(); + int index = LightmapsStart; + for (auto& lightmap : fb->GetTextureManager()->Lightmaps) + { + Bindless.Writer.AddCombinedImageSampler(Bindless.Set.get(), 0, index, lightmap.View.get(), sampler, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); + index++; + } + Bindless.Writer.Execute(fb->GetDevice()); Bindless.Writer = WriteDescriptors(); } @@ -426,3 +433,17 @@ int VkDescriptorSetManager::GetSWColormapTextureIndex(FSWColormap* colormap) Colormaps.push_back(colormap); return colormap->Renderdev.bindIndex; } + +int VkDescriptorSetManager::GetLightProbeTextureIndex(int probeIndex) +{ + if ((size_t)probeIndex >= LightProbes.size()) + LightProbes.resize(probeIndex + 1, -1); + + if (LightProbes[probeIndex] == -1) + { + LightProbes[probeIndex] = AddBindlessTextureIndex(fb->GetTextureManager()->Irradiancemaps[probeIndex].View.get(), fb->GetSamplerManager()->IrradiancemapSampler.get()); + AddBindlessTextureIndex(fb->GetTextureManager()->Prefiltermaps[probeIndex].View.get(), fb->GetSamplerManager()->PrefiltermapSampler.get()); + } + + return LightProbes[probeIndex]; +} diff --git a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h index 8f227c55f..76a7ea912 100644 --- a/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h +++ b/src/common/rendering/vulkan/descriptorsets/vk_descriptorset.h @@ -46,6 +46,7 @@ public: int AddBindlessTextureIndex(VulkanImageView* imageview, VulkanSampler* sampler); int GetSWColormapTextureIndex(FSWColormap* colormap); + int GetLightProbeTextureIndex(int probeIndex); private: void CreateLevelMeshLayout(); @@ -98,6 +99,13 @@ private: int NextIndex = 0; } Bindless; + struct + { + std::unique_ptr Pool; + std::unique_ptr Set; + std::unique_ptr Layout; + } Lightmap; + struct { std::unique_ptr Pool; @@ -119,7 +127,10 @@ private: std::list Materials; std::vector Colormaps; + std::vector LightProbes; static const int MaxFixedSets = 100; static const int MaxBindlessTextures = 16536; + static const int LightmapsStart = 3; + static const int MaxLightmaps = 128; }; diff --git a/src/common/rendering/vulkan/shaders/vk_shader.cpp b/src/common/rendering/vulkan/shaders/vk_shader.cpp index 5bfafea4e..e9a4a6710 100644 --- a/src/common/rendering/vulkan/shaders/vk_shader.cpp +++ b/src/common/rendering/vulkan/shaders/vk_shader.cpp @@ -247,9 +247,10 @@ static std::vector vertexShaderOutputs {"vEyeNormal", "", UniformType::Vec4, FieldCondition::ALWAYS}, //6 {"ClipDistanceA", "", UniformType::Vec4, FieldCondition::HAS_CLIPDISTANCE}, //7 {"ClipDistanceB", "", UniformType::Vec4, FieldCondition::HAS_CLIPDISTANCE}, //8 - {"vLightmap", "", UniformType::Vec3, FieldCondition::ALWAYS}, //9 - {"uDataIndex", "flat", UniformType::Int, FieldCondition::USELEVELMESH}, //10 - {"vLightColor", "", UniformType::Vec3, FieldCondition::SHADE_VERTEX}, //11 + {"vLightmap", "", UniformType::Vec2, FieldCondition::ALWAYS}, //9 + {"vLightmapIndex", "flat", UniformType::Int, FieldCondition::ALWAYS}, //10 + {"uDataIndex", "flat", UniformType::Int, FieldCondition::USELEVELMESH}, //11 + {"vLightColor", "", UniformType::Vec3, FieldCondition::SHADE_VERTEX}, //12 }; static std::vector fragShaderOutputs diff --git a/src/common/rendering/vulkan/textures/vk_imagetransition.h b/src/common/rendering/vulkan/textures/vk_imagetransition.h index 2cd181878..03d4bfbac 100644 --- a/src/common/rendering/vulkan/textures/vk_imagetransition.h +++ b/src/common/rendering/vulkan/textures/vk_imagetransition.h @@ -19,12 +19,8 @@ public: for (auto &it : RSFramebuffers) deletelist->Add(std::move(it.second)); RSFramebuffers.clear(); - for (auto& framebuffer : LMFramebuffers) - deletelist->Add(std::move(framebuffer)); - LMFramebuffers.clear(); - for (auto& view : LMViews) - deletelist->Add(std::move(view)); - LMViews.clear(); + deletelist->Add(std::move(LMFramebuffer)); + deletelist->Add(std::move(LMView)); deletelist->Add(std::move(ZMinMaxFramebuffer)); deletelist->Add(std::move(DepthOnlyView)); deletelist->Add(std::move(View)); @@ -41,8 +37,8 @@ public: std::unique_ptr PPFramebuffer; std::unique_ptr ZMinMaxFramebuffer; std::map> RSFramebuffers; - std::vector> LMViews; - std::vector> LMFramebuffers; + std::unique_ptr LMView; + std::unique_ptr LMFramebuffer; }; class VkImageTransition diff --git a/src/common/rendering/vulkan/textures/vk_texture.cpp b/src/common/rendering/vulkan/textures/vk_texture.cpp index 6d74abc5a..f5386c1ae 100644 --- a/src/common/rendering/vulkan/textures/vk_texture.cpp +++ b/src/common/rendering/vulkan/textures/vk_texture.cpp @@ -57,13 +57,15 @@ void VkTextureManager::Deinit() RemovePPTexture(PPTextures.back()); } -void VkTextureManager::BeginFrame() +void VkTextureManager::BeginFrame(int lightmapTextureSize, int lightmapCount) { if (!Shadowmap.Image || Shadowmap.Image->width != gl_shadowmap_quality) { Shadowmap.Reset(fb); CreateShadowmap(); } + + SetLightmapCount(lightmapTextureSize, lightmapCount); } void VkTextureManager::AddTexture(VkHardwareTexture* texture) @@ -400,7 +402,7 @@ void VkTextureManager::CreateIrradiancemap() data.Push(0); data.Push(0); } - CreateIrradiancemap(1, 6, std::move(data)); + CreateIrradiancemap(1, 1, std::move(data)); } void VkTextureManager::CreatePrefiltermap() @@ -420,55 +422,55 @@ void VkTextureManager::CreatePrefiltermap() } } } - CreatePrefiltermap(size, 6, std::move(data)); + CreatePrefiltermap(size, 1, std::move(data)); } -void VkTextureManager::CreateIrradiancemap(int size, int count, const TArray& newPixelData) +void VkTextureManager::CreateIrradiancemap(int size, int cubeCount, const TArray& srcPixels) { - if (Irradiancemap.Size == size && Irradiancemap.Count == count && newPixelData.Size() == 0) - return; - - Irradiancemap.Size = size; - Irradiancemap.Count = count; + for (auto& tex : Irradiancemaps) + tex.Reset(fb); + Irradiancemaps.clear(); + Irradiancemaps.resize(cubeCount); int w = size; int h = size; int pixelsize = 8; - Irradiancemap.Image.Reset(fb); + for (int i = 0; i < cubeCount; i++) + { + Irradiancemaps[i].Image = ImageBuilder() + .Size(w, h, 1, 6) + .Format(VK_FORMAT_R16G16B16A16_SFLOAT) + .Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT) + .Flags(VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) + .DebugName("VkTextureManager.Irradiancemap") + .Create(fb->GetDevice()); - Irradiancemap.Image.Image = ImageBuilder() - .Size(w, h, 1, count) - .Format(VK_FORMAT_R16G16B16A16_SFLOAT) - .Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT) - .Flags(VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) - .DebugName("VkTextureManager.Irradiancemap") - .Create(fb->GetDevice()); - - Irradiancemap.Image.View = ImageViewBuilder() - .Type(VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) - .Image(Irradiancemap.Image.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT) - .DebugName("VkTextureManager.IrradiancemapView") - .Create(fb->GetDevice()); + Irradiancemaps[i].View = ImageViewBuilder() + .Type(VK_IMAGE_VIEW_TYPE_CUBE) + .Image(Irradiancemaps[i].Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT) + .DebugName("VkTextureManager.IrradiancemapView") + .Create(fb->GetDevice()); + } auto cmdbuffer = fb->GetCommands()->GetTransferCommands(); - assert(newPixelData.Size() == (size_t)w * h * count * 3); - - if (count > 0 && newPixelData.Size() == (size_t)w * h * count * 3) + if (srcPixels.size() != 0) { - int totalSize = w * h * count * pixelsize; + if (srcPixels.size() != w * h * 3 * 6 * cubeCount) + I_FatalError("Invalid pixels array passed to VkTextureManager.CreateIrradiancemap"); + int totalSize = w * h * pixelsize * 6 * cubeCount; auto stagingBuffer = BufferBuilder() .Size(totalSize) .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) - .DebugName("VkRenderBuffers.IrradiancemapStagingBuffer") + .DebugName("VkTextureManager.CubeTextureListStagingBuffer") .Create(fb->GetDevice()); uint16_t one = 0x3c00; // half-float 1.0 - const uint16_t* src = newPixelData.Data(); + const uint16_t* src = srcPixels.data(); uint16_t* data = (uint16_t*)stagingBuffer->Map(0, totalSize); - for (int i = w * h * count; i > 0; i--) + for (int i = w * h * 6 * cubeCount; i > 0; i--) { *(data++) = *(src++); *(data++) = *(src++); @@ -477,77 +479,85 @@ void VkTextureManager::CreateIrradiancemap(int size, int count, const TArrayUnmap(); - VkImageTransition() - .AddImage(&Irradiancemap.Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, 1, 0, count) - .Execute(cmdbuffer); + VkImageTransition barrier0; + for (int i = 0; i < cubeCount; i++) + barrier0.AddImage(&Irradiancemaps[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, 1, 0, 6); + barrier0.Execute(cmdbuffer); - VkBufferImageCopy region = {}; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = count; - region.imageExtent.depth = 1; - region.imageExtent.width = w; - region.imageExtent.height = h; - cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Irradiancemap.Image.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + for (int i = 0; i < cubeCount; i++) + { + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 6; + region.imageExtent.depth = 1; + region.imageExtent.width = w; + region.imageExtent.height = h; + region.bufferOffset = w * h * pixelsize * 6 * i; + cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Irradiancemaps[i].Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + } fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer)); } - VkImageTransition() - .AddImage(&Irradiancemap.Image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, 1, 0, count) - .Execute(cmdbuffer); + VkImageTransition barrier1; + for (int i = 0; i < cubeCount; i++) + barrier1.AddImage(&Irradiancemaps[i], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, 1, 0, 6); + barrier1.Execute(cmdbuffer); } -void VkTextureManager::CreatePrefiltermap(int size, int count, const TArray& newPixelData) +void VkTextureManager::CreatePrefiltermap(int size, int cubeCount, const TArray& srcPixels) { - if (Prefiltermap.Size == size && Prefiltermap.Count == count && newPixelData.Size() == 0) - return; - - Prefiltermap.Size = size; - Prefiltermap.Count = count; + for (auto& tex : Prefiltermaps) + tex.Reset(fb); + Prefiltermaps.clear(); + Prefiltermaps.resize(cubeCount); int w = size; int h = size; int pixelsize = 8; int miplevels = MAX_REFLECTION_LOD + 1; - Prefiltermap.Image.Reset(fb); + for (int i = 0; i < cubeCount; i++) + { + Prefiltermaps[i].Image = ImageBuilder() + .Size(w, h, miplevels, 6) + .Format(VK_FORMAT_R16G16B16A16_SFLOAT) + .Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT) + .Flags(VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) + .DebugName("VkTextureManager.Prefiltermap") + .Create(fb->GetDevice()); - Prefiltermap.Image.Image = ImageBuilder() - .Size(w, h, miplevels, count) - .Format(VK_FORMAT_R16G16B16A16_SFLOAT) - .Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT) - .Flags(VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) - .DebugName("VkTextureManager.Prefiltermap") - .Create(fb->GetDevice()); - - Prefiltermap.Image.View = ImageViewBuilder() - .Type(VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) - .Image(Prefiltermap.Image.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT) - .DebugName("VkTextureManager.PrefiltermapView") - .Create(fb->GetDevice()); + Prefiltermaps[i].View = ImageViewBuilder() + .Type(VK_IMAGE_VIEW_TYPE_CUBE) + .Image(Prefiltermaps[i].Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT) + .DebugName("VkTextureManager.PrefiltermapView") + .Create(fb->GetDevice()); + } auto cmdbuffer = fb->GetCommands()->GetTransferCommands(); - int totalSize = 0; - for (int level = 0; level < miplevels; level++) + if (srcPixels.size() != 0) { - int mipwidth = std::max(w >> level, 1); - int mipheight = std::max(h >> level, 1); - totalSize += mipwidth * mipheight * count; - } - assert(newPixelData.Size() == (size_t)totalSize * 3); + int totalSize = 0; + for (int level = 0; level < miplevels; level++) + { + int mipwidth = std::max(w >> level, 1); + int mipheight = std::max(h >> level, 1); + totalSize += mipwidth * mipheight * 6 * cubeCount; + } + + if (srcPixels.size() != totalSize * 3) + I_FatalError("Invalid pixels array passed to VkTextureManager.CreatePrefiltermap"); - if (count > 0 && newPixelData.Size() == (size_t)totalSize * 3) - { auto stagingBuffer = BufferBuilder() .Size(totalSize * pixelsize) .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) - .DebugName("VkTextureManager.PrefiltermapStagingBuffer") + .DebugName("VkTextureManager.CreatePrefiltermap") .Create(fb->GetDevice()); uint16_t one = 0x3c00; // half-float 1.0 - const uint16_t* src = newPixelData.Data(); - uint16_t* data = (uint16_t*)stagingBuffer->Map(0, totalSize * pixelsize); + const uint16_t* src = srcPixels.data(); + uint16_t* data = (uint16_t*)stagingBuffer->Map(0, totalSize); for (int i = 0; i < totalSize; i++) { *(data++) = *(src++); @@ -557,95 +567,121 @@ void VkTextureManager::CreatePrefiltermap(int size, int count, const TArrayUnmap(); - VkImageTransition() - .AddImage(&Prefiltermap.Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, miplevels, 0, count) - .Execute(cmdbuffer); + VkImageTransition barrier0; + for (int i = 0; i < cubeCount; i++) + barrier0.AddImage(&Prefiltermaps[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, miplevels, 0, 6); + barrier0.Execute(cmdbuffer); int offset = 0; - for (int i = 0; i < count; ++i) + for (int i = 0; i < cubeCount; i++) { - for (int level = 0; level < miplevels; level++) + for (int side = 0; side < 6; side++) { - int mipwidth = std::max(w >> level, 1); - int mipheight = std::max(h >> level, 1); + for (int level = 0; level < miplevels; level++) + { + int mipwidth = std::max(w >> level, 1); + int mipheight = std::max(h >> level, 1); - VkBufferImageCopy region = {}; - region.bufferOffset = offset; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = 1; - region.imageSubresource.baseArrayLayer = i; - region.imageSubresource.mipLevel = level; - region.imageExtent.depth = 1; - region.imageExtent.width = mipwidth; - region.imageExtent.height = mipheight; - cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Prefiltermap.Image.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.baseArrayLayer = side; + region.imageSubresource.layerCount = 1; + region.imageSubresource.mipLevel = level; + region.imageExtent.depth = 1; + region.imageExtent.width = mipwidth; + region.imageExtent.height = mipheight; + region.bufferOffset = offset; + cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Prefiltermaps[i].Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); - offset += mipwidth * mipheight * pixelsize; + offset += mipwidth * mipheight * pixelsize; + } } } fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer)); } - VkImageTransition() - .AddImage(&Prefiltermap.Image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, miplevels, 0, count) - .Execute(cmdbuffer); + VkImageTransition barrier1; + for (int i = 0; i < cubeCount; i++) + barrier1.AddImage(&Prefiltermaps[i], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, miplevels, 0, 6); + barrier1.Execute(cmdbuffer); } -void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCount, TArray&& newPixelData) +void VkTextureManager::SetLightmapCount(int size, int count) { - if (newLMTextureCount == 0) // If there is no lightmap we create a dummy texture to simplify code elsewhere - { - newLMTextureSize = 1; - newLMTextureCount = 1; - newPixelData = {}; - } - - if (Lightmap.Size == newLMTextureSize && Lightmap.Count == newLMTextureCount + 1 && newPixelData.Size() == 0) + int startIndex = Lightmaps.size(); + if (startIndex >= count) return; - Lightmap.Size = newLMTextureSize; + Lightmaps.resize(count); - // Always create minimum 16 textures with 4 additional than the initial watermark - // To do: add support for expanding the texture dynamically instead - Lightmap.Count = std::max(newLMTextureCount, 12) + 4; - - int w = newLMTextureSize; - int h = newLMTextureSize; - int count = newLMTextureCount; - int pixelsize = 8; + for (int i = startIndex; i < count; i++) + { + Lightmaps[i].Image = ImageBuilder() + .Size(size, size) + .Format(VK_FORMAT_R16G16B16A16_SFLOAT) + .Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) + .DebugName("VkTextureManager.Lightmap") + .Create(fb->GetDevice()); - Lightmap.Image.Reset(fb); - - Lightmap.Image.Image = ImageBuilder() - .Size(w, h, 1, Lightmap.Count) - .Format(VK_FORMAT_R16G16B16A16_SFLOAT) - .Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) - .DebugName("VkTextureManager.Lightmap") - .Create(fb->GetDevice()); - - Lightmap.Image.View = ImageViewBuilder() - .Type(VK_IMAGE_VIEW_TYPE_2D_ARRAY) - .Image(Lightmap.Image.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT) - .DebugName("VkTextureManager.LightmapView") - .Create(fb->GetDevice()); + Lightmaps[i].View = ImageViewBuilder() + .Type(VK_IMAGE_VIEW_TYPE_2D) + .Image(Lightmaps[i].Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT) + .DebugName("VkTextureManager.LightmapView") + .Create(fb->GetDevice()); + } auto cmdbuffer = fb->GetCommands()->GetTransferCommands(); - if (count > 0 && newPixelData.Size() >= (size_t)w * h * count * 3) + VkImageTransition barrier; + for (int i = startIndex; i < count; i++) + barrier.AddImage(&Lightmaps[i], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); + barrier.Execute(cmdbuffer); +} + +void VkTextureManager::CreateLightmap(int size, int count, const TArray& srcPixels) +{ + for (auto& tex : Lightmaps) + tex.Reset(fb); + Lightmaps.clear(); + Lightmaps.resize(count); + + int w = size; + int h = size; + int pixelsize = 8; + + for (int i = 0; i < count; i++) { - assert(newPixelData.Size() == (size_t)w * h * count * 3); + Lightmaps[i].Image = ImageBuilder() + .Size(w, h) + .Format(VK_FORMAT_R16G16B16A16_SFLOAT) + .Usage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) + .DebugName("VkTextureManager.Lightmap") + .Create(fb->GetDevice()); - int totalSize = w * h * count * pixelsize; + Lightmaps[i].View = ImageViewBuilder() + .Type(VK_IMAGE_VIEW_TYPE_2D) + .Image(Lightmaps[i].Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT) + .DebugName("VkTextureManager.LightmapView") + .Create(fb->GetDevice()); + } + auto cmdbuffer = fb->GetCommands()->GetTransferCommands(); + + if (srcPixels.size() != 0) + { + if (srcPixels.size() != w * h * 3 * count) + I_FatalError("Invalid pixels array passed to VkTextureManager.CreateLightmap"); + + int totalSize = w * h * pixelsize * count; auto stagingBuffer = BufferBuilder() .Size(totalSize) .Usage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY) - .DebugName("VkTextureManager.LightmapStagingBuffer") + .DebugName("VkTextureManager.TextureListStagingBuffer") .Create(fb->GetDevice()); uint16_t one = 0x3c00; // half-float 1.0 - const uint16_t* src = newPixelData.Data(); + const uint16_t* src = srcPixels.data(); uint16_t* data = (uint16_t*)stagingBuffer->Map(0, totalSize); for (int i = w * h * count; i > 0; i--) { @@ -656,31 +692,42 @@ void VkTextureManager::CreateLightmap(int newLMTextureSize, int newLMTextureCoun } stagingBuffer->Unmap(); - VkImageTransition() - .AddImage(&Lightmap.Image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true, 0, 1, 0, Lightmap.Count) - .Execute(cmdbuffer); + VkImageTransition barrier0; + for (int i = 0; i < count; i++) + barrier0.AddImage(&Lightmaps[i], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true); + barrier0.Execute(cmdbuffer); - VkBufferImageCopy region = {}; - region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.layerCount = count; - region.imageExtent.depth = 1; - region.imageExtent.width = w; - region.imageExtent.height = h; - cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Lightmap.Image.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + for (int i = 0; i < count; i++) + { + VkBufferImageCopy region = {}; + region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + region.imageSubresource.layerCount = 1; + region.imageExtent.depth = 1; + region.imageExtent.width = w; + region.imageExtent.height = h; + region.bufferOffset = w * h * pixelsize * i; + cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Lightmaps[i].Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion); + } fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer)); - - newPixelData.Clear(); } - VkImageTransition() - .AddImage(&Lightmap.Image, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false, 0, 1, 0, Lightmap.Count) - .Execute(cmdbuffer); + VkImageTransition barrier1; + for (int i = 0; i < count; i++) + barrier1.AddImage(&Lightmaps[i], VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false); + barrier1.Execute(cmdbuffer); } void VkTextureManager::DownloadLightmap(int arrayIndex, uint16_t* buffer) { - unsigned int totalSize = Lightmap.Size * Lightmap.Size * 4; + DownloadTexture(&Lightmaps[arrayIndex], buffer); +} + +void VkTextureManager::DownloadTexture(VkTextureImage* texture, uint16_t* buffer) +{ + int width = texture->Image->width; + int height = texture->Image->height; + int totalSize = width * height * 4; auto stagingBuffer = BufferBuilder() .Size(totalSize * sizeof(uint16_t)) @@ -690,23 +737,22 @@ void VkTextureManager::DownloadLightmap(int arrayIndex, uint16_t* buffer) auto cmdbuffer = fb->GetCommands()->GetTransferCommands(); - PipelineBarrier() - .AddImage(Lightmap.Image.Image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, arrayIndex, 1) - .Execute(cmdbuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT); + VkImageTransition() + .AddImage(texture, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, false) + .Execute(cmdbuffer); VkBufferImageCopy region = {}; region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - region.imageSubresource.baseArrayLayer = arrayIndex; region.imageSubresource.layerCount = 1; region.imageSubresource.mipLevel = 0; - region.imageExtent.width = Lightmap.Size; - region.imageExtent.height = Lightmap.Size; + region.imageExtent.width = width; + region.imageExtent.height = height; region.imageExtent.depth = 1; - cmdbuffer->copyImageToBuffer(Lightmap.Image.Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer->buffer, 1, ®ion); + cmdbuffer->copyImageToBuffer(texture->Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer->buffer, 1, ®ion); - PipelineBarrier() - .AddImage(Lightmap.Image.Image.get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, arrayIndex, 1) - .Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + VkImageTransition() + .AddImage(texture, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false) + .Execute(cmdbuffer); fb->GetCommands()->WaitForCommands(false); diff --git a/src/common/rendering/vulkan/textures/vk_texture.h b/src/common/rendering/vulkan/textures/vk_texture.h index 25ac45529..fafbb582e 100644 --- a/src/common/rendering/vulkan/textures/vk_texture.h +++ b/src/common/rendering/vulkan/textures/vk_texture.h @@ -26,11 +26,13 @@ public: void Deinit(); - void BeginFrame(); + void BeginFrame(int lightmapTextureSize, int lightmapCount); - void CreateLightmap(int size, int count, TArray&& data); - void CreateIrradiancemap(int size, int count, const TArray& data); - void CreatePrefiltermap(int size, int count, const TArray& data); + void SetLightmapCount(int size, int count); + + void CreateLightmap(int size, int count, const TArray& data); + void CreateIrradiancemap(int size, int cubeCount, const TArray& data); + void CreatePrefiltermap(int size, int cubeCount, const TArray& data); void DownloadLightmap(int arrayIndex, uint16_t* buffer); void SetGamePalette(); @@ -58,13 +60,9 @@ public: int GetHWTextureCount() { return (int)Textures.size(); } VkTextureImage Shadowmap; - - struct - { - VkTextureImage Image; - int Size = 0; - int Count = 0; - } Lightmap, Irradiancemap, Prefiltermap; + std::vector Lightmaps; + std::vector Irradiancemaps; + std::vector Prefiltermaps; static const int MAX_REFLECTION_LOD = 4; // Note: must match what lightmodel_pbr.glsl expects @@ -83,6 +81,7 @@ private: void CreateLightmap(); void CreateIrradiancemap(); void CreatePrefiltermap(); + void DownloadTexture(VkTextureImage* texture, uint16_t* buffer); void StartWorkerThread(); void StopWorkerThread(); diff --git a/src/common/rendering/vulkan/vk_lightmapper.cpp b/src/common/rendering/vulkan/vk_lightmapper.cpp index cd364af99..f79ee354b 100644 --- a/src/common/rendering/vulkan/vk_lightmapper.cpp +++ b/src/common/rendering/vulkan/vk_lightmapper.cpp @@ -402,8 +402,7 @@ void VkLightmapper::CopyResult() if (pixels == 0) return; - VkTextureImage* destTexture = &fb->GetTextureManager()->Lightmap.Image; - int destSize = fb->GetTextureManager()->Lightmap.Size; + std::vector& destTexture = fb->GetTextureManager()->Lightmaps; auto cmdbuffer = fb->GetCommands()->GetTransferCommands(); @@ -415,7 +414,7 @@ void VkLightmapper::CopyResult() for (unsigned int i = 0, count = copylists.Size(); i < count; i++) { if (copylists[i].Size() > 0) - barrier0.AddImage(destTexture->Image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, i, 1); + barrier0.AddImage(destTexture[i].Image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1); } barrier0.Execute(cmdbuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); @@ -428,22 +427,18 @@ void VkLightmapper::CopyResult() if (list.Size() == 0) continue; - // Create framebuffer object if it doesn't exist - if (i >= destTexture->LMFramebuffers.size()) - { - destTexture->LMViews.resize(i + 1); - destTexture->LMFramebuffers.resize(i + 1); - } + int destSize = destTexture[i].Image->width; - auto& framebuffer = destTexture->LMFramebuffers[i]; + // Create framebuffer object if it doesn't exist + auto& framebuffer = destTexture[i].LMFramebuffer; if (!framebuffer) { - auto& view = destTexture->LMViews[i]; + auto& view = destTexture[i].LMView; if (!view) { view = ImageViewBuilder() .Type(VK_IMAGE_VIEW_TYPE_2D) - .Image(destTexture->Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_ASPECT_COLOR_BIT, 0, i, 1, 1) + .Image(destTexture[i].Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1, 1) .DebugName("LMView") .Create(fb->GetDevice()); } @@ -504,7 +499,7 @@ void VkLightmapper::CopyResult() for (unsigned int i = 0, count = copylists.Size(); i < count; i++) { if (copylists[i].Size() > 0) - barrier1.AddImage(destTexture->Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, i, 1); + barrier1.AddImage(destTexture[i].Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1); } barrier1.Execute(cmdbuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); diff --git a/src/common/rendering/vulkan/vk_renderdevice.cpp b/src/common/rendering/vulkan/vk_renderdevice.cpp index 4484c44ef..727cc51d3 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.cpp +++ b/src/common/rendering/vulkan/vk_renderdevice.cpp @@ -415,8 +415,8 @@ void VulkanRenderDevice::RenderEnvironmentMap(std::function& irradianceMaps, const TArray& prefilterMaps) { - mTextureManager->CreateIrradiancemap(32, 6 * cubemapCount, irradianceMaps); - mTextureManager->CreatePrefiltermap(128, 6 * cubemapCount, prefilterMaps); + mTextureManager->CreateIrradiancemap(32, cubemapCount, irradianceMaps); + mTextureManager->CreatePrefiltermap(128, cubemapCount, prefilterMaps); } void VulkanRenderDevice::PostProcessScene(bool swscene, int fixedcm, float flash, bool palettePostprocess, const std::function &afterBloomDrawEndScene2D) @@ -638,7 +638,7 @@ void VulkanRenderDevice::BeginFrame() SetViewportRects(nullptr); mCommands->BeginFrame(); mLevelMesh->BeginFrame(); - mTextureManager->BeginFrame(); + mTextureManager->BeginFrame(levelMesh->Lightmap.TextureSize, levelMesh->Lightmap.TextureCount); mScreenBuffers->BeginFrame(screen->mScreenViewport.width, screen->mScreenViewport.height, screen->mSceneViewport.width, screen->mSceneViewport.height); mSaveBuffers->BeginFrame(SAVEPICWIDTH, SAVEPICHEIGHT, SAVEPICWIDTH, SAVEPICHEIGHT); mRenderState->BeginFrame(); diff --git a/src/common/rendering/vulkan/vk_renderstate.cpp b/src/common/rendering/vulkan/vk_renderstate.cpp index 1ad2601a4..118384b3c 100644 --- a/src/common/rendering/vulkan/vk_renderstate.cpp +++ b/src/common/rendering/vulkan/vk_renderstate.cpp @@ -458,6 +458,8 @@ void VkRenderState::ApplySurfaceUniforms() mSurfaceUniforms.uColormapIndex = 0; } + mSurfaceUniforms.uLightProbeIndex = fb->GetDescriptorSetManager()->GetLightProbeTextureIndex(mLightProbeIndex); + if (mMaterial.mChanged) { if (mMaterial.mMaterial) diff --git a/src/rendering/hwrenderer/hw_vertexbuilder.cpp b/src/rendering/hwrenderer/hw_vertexbuilder.cpp index 1bb7e111e..7549a3749 100644 --- a/src/rendering/hwrenderer/hw_vertexbuilder.cpp +++ b/src/rendering/hwrenderer/hw_vertexbuilder.cpp @@ -205,18 +205,6 @@ static void SetFlatVertex(FFlatVertex& ffv, vertex_t* vt, const secplane_t& plan ffv.lindex = -1.0f; } -static void SetFlatVertex(FFlatVertex& ffv, vertex_t* vt, const secplane_t& plane, float llu, float llv, float llindex) -{ - ffv.x = (float)vt->fX(); - ffv.y = (float)vt->fY(); - ffv.z = (float)plane.ZatPoint(vt); - ffv.u = (float)vt->fX() / 64.f; - ffv.v = -(float)vt->fY() / 64.f; - ffv.lu = llu; - ffv.lv = llv; - ffv.lindex = llindex; -} - //========================================================================== // // Creates the vertices for one plane in one subsector w/lightmap support. @@ -470,6 +458,10 @@ static void UpdatePlaneLightmap(FRenderState& renderstate, sector_t* sec, int pl vt->lv = luv.Y; vt->lindex = lindex; } + else + { + vt->lindex = -1; + } } } renderstate.UpdateShadowData(startvt, §or_vertices[startvt], countvt); diff --git a/wadsrc/static/shaders/lightmap/binding_textures.glsl b/wadsrc/static/shaders/lightmap/binding_textures.glsl index 3bc436ef6..e06cc3d08 100644 --- a/wadsrc/static/shaders/lightmap/binding_textures.glsl +++ b/wadsrc/static/shaders/lightmap/binding_textures.glsl @@ -1,2 +1,3 @@ layout(set = 2, binding = 0) uniform sampler2D textures[]; +layout(set = 2, binding = 0) uniform samplerCube cubeTextures[]; diff --git a/wadsrc/static/shaders/scene/binding_fixed.glsl b/wadsrc/static/shaders/scene/binding_fixed.glsl index a684efb88..a23979bd5 100644 --- a/wadsrc/static/shaders/scene/binding_fixed.glsl +++ b/wadsrc/static/shaders/scene/binding_fixed.glsl @@ -1,18 +1,15 @@ #include layout(set = 0, binding = 0) uniform sampler2D ShadowMap; -layout(set = 0, binding = 1) uniform sampler2DArray LightMap; -layout(set = 0, binding = 2) uniform sampler2D LinearDepth; -layout(set = 0, binding = 3) uniform samplerCubeArray IrradianceMap; -layout(set = 0, binding = 4) uniform samplerCubeArray PrefilterMap; +layout(set = 0, binding = 1) uniform sampler2D LinearDepth; #if defined(SUPPORTS_RAYQUERY) -layout(set = 0, binding = 5) uniform accelerationStructureEXT acc; +layout(set = 0, binding = 2) uniform accelerationStructureEXT acc; #else -layout(set = 0, binding = 5, std430) buffer readonly NodeBuffer +layout(set = 0, binding = 2, std430) buffer readonly NodeBuffer { int nodesRoot; int nodebufferPadding1; @@ -23,9 +20,9 @@ layout(set = 0, binding = 5, std430) buffer readonly NodeBuffer #endif -layout(set = 0, binding = 6, std430) buffer readonly VertexBuffer { SurfaceVertex vertices[]; }; -layout(set = 0, binding = 7, std430) buffer readonly ElementBuffer { int elements[]; }; -layout(set = 0, binding = 8, std430) buffer readonly SurfaceIndexBuffer { uint surfaceIndices[]; }; -layout(set = 0, binding = 9, std430) buffer readonly SurfaceBuffer { SurfaceInfo surfaces[]; }; -layout(set = 0, binding = 10, std430) buffer readonly PortalBuffer { PortalInfo portals[]; }; +layout(set = 0, binding = 3, std430) buffer readonly VertexBuffer { SurfaceVertex vertices[]; }; +layout(set = 0, binding = 4, std430) buffer readonly ElementBuffer { int elements[]; }; +layout(set = 0, binding = 5, std430) buffer readonly SurfaceIndexBuffer { uint surfaceIndices[]; }; +layout(set = 0, binding = 6, std430) buffer readonly SurfaceBuffer { SurfaceInfo surfaces[]; }; +layout(set = 0, binding = 7, std430) buffer readonly PortalBuffer { PortalInfo portals[]; }; diff --git a/wadsrc/static/shaders/scene/binding_textures.glsl b/wadsrc/static/shaders/scene/binding_textures.glsl index 5f013d45d..4f89e3609 100644 --- a/wadsrc/static/shaders/scene/binding_textures.glsl +++ b/wadsrc/static/shaders/scene/binding_textures.glsl @@ -1,5 +1,6 @@ layout(set = 2, binding = 0) uniform sampler2D textures[]; +layout(set = 2, binding = 0) uniform samplerCube cubeTextures[]; const int tex = 0; const int texture2 = 1; diff --git a/wadsrc/static/shaders/scene/layout_shared.glsl b/wadsrc/static/shaders/scene/layout_shared.glsl index 53202a183..6404e567d 100644 --- a/wadsrc/static/shaders/scene/layout_shared.glsl +++ b/wadsrc/static/shaders/scene/layout_shared.glsl @@ -26,6 +26,7 @@ #define BrdfLUT 1 // the BRDF convoluted texture is always in this texture slot #define PaletteLUT 2 // the RGB666 lookup table from a color to the game palette is always in this texture slot +#define LightmapsStart 3 // the lightmaps start at this texture slot #define uObjectColor data[uDataIndex].uObjectColor #define uObjectColor2 data[uDataIndex].uObjectColor2 diff --git a/wadsrc/static/shaders/scene/lightmode.glsl b/wadsrc/static/shaders/scene/lightmode.glsl index cae0fda37..a078d0a83 100644 --- a/wadsrc/static/shaders/scene/lightmode.glsl +++ b/wadsrc/static/shaders/scene/lightmode.glsl @@ -52,9 +52,9 @@ vec4 getLightColor(Material material) vec4 dynlight = uDynLightColor; - if (vLightmap.z >= 0.0) + if (vLightmapIndex != -1) { - dynlight.rgb += texture(LightMap, vLightmap).rgb; + dynlight.rgb += texture(textures[nonuniformEXT(vLightmapIndex)], vLightmap.xy).rgb; } dynlight.rgb += ProcessSWLight(material); @@ -103,9 +103,9 @@ vec4 getLightColor(Material material) // // apply lightmaps // - if (vLightmap.z >= 0.0) + if (vLightmapIndex != -1) { - color.rgb += texture(LightMap, vLightmap).rgb; + color.rgb += texture(textures[nonuniformEXT(vLightmapIndex)], vLightmap.xy).rgb; } // diff --git a/wadsrc/static/shaders/scene/lightmodel_pbr.glsl b/wadsrc/static/shaders/scene/lightmodel_pbr.glsl index 29f54b2ce..3c39f9961 100644 --- a/wadsrc/static/shaders/scene/lightmodel_pbr.glsl +++ b/wadsrc/static/shaders/scene/lightmodel_pbr.glsl @@ -151,13 +151,13 @@ vec3 ProcessMaterialLight(Material material, vec3 ambientLight) const float environmentScaleFactor = 1.0; - vec3 irradiance = texture(IrradianceMap, vec4(N, uLightProbeIndex)).rgb * environmentScaleFactor; + vec3 irradiance = texture(cubeTextures[uLightProbeIndex], N).rgb * environmentScaleFactor; vec3 diffuse = irradiance * albedo; kD *= 1.0 - metallic; const float MAX_REFLECTION_LOD = 4.0; vec3 R = reflect(-V, N); - vec3 prefilteredColor = textureLod(PrefilterMap, vec4(R, uLightProbeIndex), roughness * MAX_REFLECTION_LOD).rgb * environmentScaleFactor; + vec3 prefilteredColor = textureLod(cubeTextures[uLightProbeIndex + 1], R, roughness * MAX_REFLECTION_LOD).rgb * environmentScaleFactor; vec2 envBRDF = texture(textures[BrdfLUT], vec2(clamp(dot(N, V), 0.0, 1.0), roughness)).rg; vec3 specular = prefilteredColor * (F * envBRDF.x + envBRDF.y); diff --git a/wadsrc/static/shaders/scene/vert_main.glsl b/wadsrc/static/shaders/scene/vert_main.glsl index de0de71c6..365fb5d6e 100644 --- a/wadsrc/static/shaders/scene/vert_main.glsl +++ b/wadsrc/static/shaders/scene/vert_main.glsl @@ -135,7 +135,11 @@ void main() #endif #if !defined(SIMPLE) || defined(SIMPLE3D) - vLightmap = vec3(aLightmap, aPosition.w); + vLightmap = aLightmap; + if (aPosition.w >= 0.0) + vLightmapIndex = LightmapsStart + int(aPosition.w); + else + vLightmapIndex = -1; pixelpos.xyz = worldcoord.xyz; pixelpos.w = -eyeCoordPos.z/eyeCoordPos.w;