Move lightmap atlas textures and light probes to the bindless textures array as its impossible to predict up front how many we need

This commit is contained in:
Magnus Norddahl 2025-07-08 02:59:10 +02:00
commit af6ec929cc
19 changed files with 317 additions and 249 deletions

View file

@ -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<uint16_t> TextureData;
uint16_t SampleDistance = 8;

View file

@ -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)

View file

@ -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];
}

View file

@ -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<VulkanDescriptorPool> Pool;
std::unique_ptr<VulkanDescriptorSet> Set;
std::unique_ptr<VulkanDescriptorSetLayout> Layout;
} Lightmap;
struct
{
std::unique_ptr<VulkanDescriptorPool> Pool;
@ -119,7 +127,10 @@ private:
std::list<VkMaterial*> Materials;
std::vector<FSWColormap*> Colormaps;
std::vector<int> LightProbes;
static const int MaxFixedSets = 100;
static const int MaxBindlessTextures = 16536;
static const int LightmapsStart = 3;
static const int MaxLightmaps = 128;
};

View file

@ -247,9 +247,10 @@ static std::vector<BuiltinFieldDesc> 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<BuiltinFieldDesc> fragShaderOutputs

View file

@ -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<VulkanFramebuffer> PPFramebuffer;
std::unique_ptr<VulkanFramebuffer> ZMinMaxFramebuffer;
std::map<VkRenderPassKey, std::unique_ptr<VulkanFramebuffer>> RSFramebuffers;
std::vector<std::unique_ptr<VulkanImageView>> LMViews;
std::vector<std::unique_ptr<VulkanFramebuffer>> LMFramebuffers;
std::unique_ptr<VulkanImageView> LMView;
std::unique_ptr<VulkanFramebuffer> LMFramebuffer;
};
class VkImageTransition

View file

@ -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<uint16_t>& newPixelData)
void VkTextureManager::CreateIrradiancemap(int size, int cubeCount, const TArray<uint16_t>& 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 TArray<uin
}
stagingBuffer->Unmap();
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, &region);
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, &region);
}
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<uint16_t>& newPixelData)
void VkTextureManager::CreatePrefiltermap(int size, int cubeCount, const TArray<uint16_t>& 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 TArray<uint
}
stagingBuffer->Unmap();
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, &region);
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, &region);
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<uint16_t>&& 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<uint16_t>& 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, &region);
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, &region);
}
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, &region);
cmdbuffer->copyImageToBuffer(texture->Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, stagingBuffer->buffer, 1, &region);
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);

View file

@ -26,11 +26,13 @@ public:
void Deinit();
void BeginFrame();
void BeginFrame(int lightmapTextureSize, int lightmapCount);
void CreateLightmap(int size, int count, TArray<uint16_t>&& data);
void CreateIrradiancemap(int size, int count, const TArray<uint16_t>& data);
void CreatePrefiltermap(int size, int count, const TArray<uint16_t>& data);
void SetLightmapCount(int size, int count);
void CreateLightmap(int size, int count, const TArray<uint16_t>& data);
void CreateIrradiancemap(int size, int cubeCount, const TArray<uint16_t>& data);
void CreatePrefiltermap(int size, int cubeCount, const TArray<uint16_t>& 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<VkTextureImage> Lightmaps;
std::vector<VkTextureImage> Irradiancemaps;
std::vector<VkTextureImage> 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();

View file

@ -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<VkTextureImage>& 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);

View file

@ -415,8 +415,8 @@ void VulkanRenderDevice::RenderEnvironmentMap(std::function<void(IntRect& bounds
void VulkanRenderDevice::UploadEnvironmentMaps(int cubemapCount, const TArray<uint16_t>& irradianceMaps, const TArray<uint16_t>& 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<void()> &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();

View file

@ -458,6 +458,8 @@ void VkRenderState::ApplySurfaceUniforms()
mSurfaceUniforms.uColormapIndex = 0;
}
mSurfaceUniforms.uLightProbeIndex = fb->GetDescriptorSetManager()->GetLightProbeTextureIndex(mLightProbeIndex);
if (mMaterial.mChanged)
{
if (mMaterial.mMaterial)

View file

@ -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, &sector_vertices[startvt], countvt);

View file

@ -1,2 +1,3 @@
layout(set = 2, binding = 0) uniform sampler2D textures[];
layout(set = 2, binding = 0) uniform samplerCube cubeTextures[];

View file

@ -1,18 +1,15 @@
#include <shaders/binding_struct_definitions.glsl>
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[]; };

View file

@ -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;

View file

@ -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

View file

@ -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;
}
//

View file

@ -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);

View file

@ -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;