mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-02-03 06:11:03 +00:00
Add lightmap texture support to vulkan backend
Also fix a warning in SetFlatVertex
This commit is contained in:
parent
24070cba2d
commit
63ecb36889
9 changed files with 137 additions and 9 deletions
|
@ -78,6 +78,7 @@ void VkRenderBuffers::BeginFrame(int width, int height, int sceneWidth, int scen
|
|||
CreateScene(width, height, samples);
|
||||
|
||||
CreateShadowmap();
|
||||
CreateLightmapSampler();
|
||||
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
|
@ -269,3 +270,41 @@ void VkRenderBuffers::CreateShadowmap()
|
|||
ShadowmapSampler->SetDebugName("VkRenderBuffers.ShadowmapSampler");
|
||||
}
|
||||
}
|
||||
|
||||
void VkRenderBuffers::CreateLightmapSampler()
|
||||
{
|
||||
if (!Lightmap.Image)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
ImageBuilder builder;
|
||||
builder.setSize(1, 1);
|
||||
builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
builder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
Lightmap.Image = builder.create(fb->device);
|
||||
Lightmap.Image->SetDebugName("VkRenderBuffers.Lightmap");
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setType(VK_IMAGE_VIEW_TYPE_2D_ARRAY);
|
||||
viewbuilder.setImage(Lightmap.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
Lightmap.View = viewbuilder.create(fb->device);
|
||||
Lightmap.View->SetDebugName("VkRenderBuffers.LightmapView");
|
||||
|
||||
VkImageTransition barrier;
|
||||
barrier.addImage(&Lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true);
|
||||
barrier.execute(fb->GetDrawCommands());
|
||||
}
|
||||
|
||||
if (!LightmapSampler)
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
|
||||
SamplerBuilder builder;
|
||||
builder.setMipmapMode(VK_SAMPLER_MIPMAP_MODE_LINEAR);
|
||||
builder.setMinFilter(VK_FILTER_LINEAR);
|
||||
builder.setMagFilter(VK_FILTER_LINEAR);
|
||||
builder.setAddressMode(VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
|
||||
LightmapSampler = builder.create(fb->device);
|
||||
LightmapSampler->SetDebugName("VkRenderBuffers.LightmapSampler");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,9 @@ public:
|
|||
VkTextureImage Shadowmap;
|
||||
std::unique_ptr<VulkanSampler> ShadowmapSampler;
|
||||
|
||||
VkTextureImage Lightmap;
|
||||
std::unique_ptr<VulkanSampler> LightmapSampler;
|
||||
|
||||
private:
|
||||
void CreatePipeline(int width, int height);
|
||||
void CreateScene(int width, int height, VkSampleCountFlagBits samples);
|
||||
|
@ -40,6 +43,7 @@ private:
|
|||
void CreateSceneFog(int width, int height, VkSampleCountFlagBits samples);
|
||||
void CreateSceneNormal(int width, int height, VkSampleCountFlagBits samples);
|
||||
void CreateShadowmap();
|
||||
void CreateLightmapSampler();
|
||||
VkSampleCountFlagBits GetBestSampleCount();
|
||||
|
||||
int mWidth = 0;
|
||||
|
|
|
@ -130,6 +130,7 @@ void VkRenderPassManager::CreateDynamicSetLayout()
|
|||
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);
|
||||
builder.addBinding(5, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1, VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
DynamicSetLayout = builder.create(GetVulkanFrameBuffer()->device);
|
||||
DynamicSetLayout->SetDebugName("VkRenderPassManager.DynamicSetLayout");
|
||||
}
|
||||
|
@ -249,6 +250,7 @@ void VkRenderPassManager::UpdateDynamicSet()
|
|||
update.addBuffer(DynamicSet.get(), 2, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->MatrixBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(MatricesUBO));
|
||||
update.addBuffer(DynamicSet.get(), 3, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, fb->StreamBuffer->UniformBuffer->mBuffer.get(), 0, sizeof(StreamUBO));
|
||||
update.addCombinedImageSampler(DynamicSet.get(), 4, fb->GetBuffers()->Shadowmap.View.get(), fb->GetBuffers()->ShadowmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
update.addCombinedImageSampler(DynamicSet.get(), 5, fb->GetBuffers()->Lightmap.View.get(), fb->GetBuffers()->LightmapSampler.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
update.updateSets(fb->device);
|
||||
}
|
||||
|
||||
|
@ -376,7 +378,7 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
|
|||
VK_FORMAT_A2B10G10R10_SNORM_PACK32
|
||||
};
|
||||
|
||||
bool inputLocations[6] = { false, false, false, false, false, false };
|
||||
bool inputLocations[7] = { false, false, false, false, false, false, false };
|
||||
|
||||
for (size_t i = 0; i < vfmt.Attrs.size(); i++)
|
||||
{
|
||||
|
@ -386,7 +388,7 @@ std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipeli
|
|||
}
|
||||
|
||||
// Vulkan requires an attribute binding for each location specified in the shader
|
||||
for (int i = 0; i < 6; i++)
|
||||
for (int i = 0; i < 7; i++)
|
||||
{
|
||||
if (!inputLocations[i])
|
||||
builder.addVertexAttribute(i, 0, VK_FORMAT_R32G32B32_SFLOAT, 0);
|
||||
|
|
|
@ -38,7 +38,7 @@ class ImageBuilder
|
|||
public:
|
||||
ImageBuilder();
|
||||
|
||||
void setSize(int width, int height, int miplevels = 1);
|
||||
void setSize(int width, int height, int miplevels = 1, int arrayLayers = 1);
|
||||
void setSamples(VkSampleCountFlagBits samples);
|
||||
void setFormat(VkFormat format);
|
||||
void setUsage(VkImageUsageFlags imageUsage, VmaMemoryUsage memoryUsage = VMA_MEMORY_USAGE_GPU_ONLY, VmaAllocationCreateFlags allocFlags = 0);
|
||||
|
@ -60,6 +60,7 @@ class ImageViewBuilder
|
|||
public:
|
||||
ImageViewBuilder();
|
||||
|
||||
void setType(VkImageViewType type);
|
||||
void setImage(VulkanImage *image, VkFormat format, VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_COLOR_BIT);
|
||||
|
||||
std::unique_ptr<VulkanImageView> create(VulkanDevice *device);
|
||||
|
@ -374,11 +375,12 @@ inline ImageBuilder::ImageBuilder()
|
|||
imageInfo.flags = 0;
|
||||
}
|
||||
|
||||
inline void ImageBuilder::setSize(int width, int height, int mipLevels)
|
||||
inline void ImageBuilder::setSize(int width, int height, int mipLevels, int arrayLayers)
|
||||
{
|
||||
imageInfo.extent.width = width;
|
||||
imageInfo.extent.height = height;
|
||||
imageInfo.mipLevels = mipLevels;
|
||||
imageInfo.arrayLayers = arrayLayers;
|
||||
}
|
||||
|
||||
inline void ImageBuilder::setSamples(VkSampleCountFlagBits samples)
|
||||
|
@ -474,6 +476,11 @@ inline ImageViewBuilder::ImageViewBuilder()
|
|||
viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
}
|
||||
|
||||
inline void ImageViewBuilder::setType(VkImageViewType type)
|
||||
{
|
||||
viewInfo.viewType = type;
|
||||
}
|
||||
|
||||
inline void ImageViewBuilder::setImage(VulkanImage *image, VkFormat format, VkImageAspectFlags aspectMask)
|
||||
{
|
||||
viewInfo.image = image->image;
|
||||
|
|
|
@ -582,6 +582,81 @@ void VulkanFrameBuffer::BeginFrame()
|
|||
}
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::InitLightmap(FLevelLocals* Level)
|
||||
{
|
||||
if (Level->LMTextureData.Size() > 0)
|
||||
{
|
||||
int w = Level->LMTextureSize;
|
||||
int h = Level->LMTextureSize;
|
||||
int count = Level->LMTextureCount;
|
||||
int pixelsize = 8;
|
||||
auto& lightmap = mActiveRenderBuffers->Lightmap;
|
||||
|
||||
if (lightmap.Image)
|
||||
{
|
||||
FrameDeleteList.Images.push_back(std::move(lightmap.Image));
|
||||
FrameDeleteList.ImageViews.push_back(std::move(lightmap.View));
|
||||
lightmap.reset();
|
||||
}
|
||||
|
||||
ImageBuilder builder;
|
||||
builder.setSize(w, h, 1, count);
|
||||
builder.setFormat(VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
builder.setUsage(VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT);
|
||||
lightmap.Image = builder.create(device);
|
||||
lightmap.Image->SetDebugName("VkRenderBuffers.Lightmap");
|
||||
|
||||
ImageViewBuilder viewbuilder;
|
||||
viewbuilder.setType(VK_IMAGE_VIEW_TYPE_2D_ARRAY);
|
||||
viewbuilder.setImage(lightmap.Image.get(), VK_FORMAT_R16G16B16A16_SFLOAT);
|
||||
lightmap.View = viewbuilder.create(device);
|
||||
lightmap.View->SetDebugName("VkRenderBuffers.LightmapView");
|
||||
|
||||
auto cmdbuffer = GetTransferCommands();
|
||||
|
||||
int totalSize = w * h * count * pixelsize;
|
||||
|
||||
BufferBuilder bufbuilder;
|
||||
bufbuilder.setSize(totalSize);
|
||||
bufbuilder.setUsage(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY);
|
||||
std::unique_ptr<VulkanBuffer> stagingBuffer = bufbuilder.create(device);
|
||||
stagingBuffer->SetDebugName("VkHardwareTexture.mStagingBuffer");
|
||||
|
||||
uint16_t one = 0x3c00; // half-float 1.0
|
||||
uint16_t* src = &Level->LMTextureData[0];
|
||||
uint16_t* data = (uint16_t*)stagingBuffer->Map(0, totalSize);
|
||||
for (int i = w * h * count; i > 0; i--)
|
||||
{
|
||||
*(data++) = *(src++);
|
||||
*(data++) = *(src++);
|
||||
*(data++) = *(src++);
|
||||
*(data++) = one;
|
||||
}
|
||||
stagingBuffer->Unmap();
|
||||
|
||||
VkImageTransition imageTransition;
|
||||
imageTransition.addImage(&lightmap, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, true);
|
||||
imageTransition.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, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
VkImageTransition barrier;
|
||||
barrier.addImage(&lightmap, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, true);
|
||||
barrier.execute(cmdbuffer);
|
||||
|
||||
FrameTextureUpload.Buffers.push_back(std::move(stagingBuffer));
|
||||
FrameTextureUpload.TotalSize += totalSize;
|
||||
|
||||
Level->LMTextureData.Reset(); // We no longer need this, release the memory
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanFrameBuffer::PushGroup(const FString &name)
|
||||
{
|
||||
if (!gpuStatActive)
|
||||
|
|
|
@ -85,6 +85,7 @@ public:
|
|||
void SetTextureFilterMode() override;
|
||||
void StartPrecaching() override;
|
||||
void BeginFrame() override;
|
||||
void InitLightmap(FLevelLocals* Level) override;
|
||||
void BlurScene(float amount) override;
|
||||
void PostProcessScene(bool swscene, int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D) override;
|
||||
void AmbientOccludeScene(float m5) override;
|
||||
|
|
|
@ -456,7 +456,7 @@ public:
|
|||
TArray<float> LMTexCoords;
|
||||
int LMTextureCount = 0;
|
||||
int LMTextureSize = 0;
|
||||
TArray<uint8_t> LMTextureData;
|
||||
TArray<uint16_t> LMTextureData;
|
||||
|
||||
// Portal information.
|
||||
FDisplacementTable Displacements;
|
||||
|
|
|
@ -3423,8 +3423,8 @@ void MapLoader::LoadLightmap(MapData *map)
|
|||
|
||||
Level->LMTextureCount = numTextures;
|
||||
Level->LMTextureSize = textureSize;
|
||||
Level->LMTextureData.Resize(numTexBytes);
|
||||
uint8_t* data = &Level->LMTextureData[0];
|
||||
Level->LMTextureData.Resize((numTexBytes + 1) / 2);
|
||||
uint8_t* data = (uint8_t*)&Level->LMTextureData[0];
|
||||
fr.Read(data, numTexBytes);
|
||||
#if 0
|
||||
// Apply compression predictor
|
||||
|
|
|
@ -191,7 +191,7 @@ 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)
|
||||
static void SetFlatVertex(FFlatVertex& ffv, vertex_t* vt, const secplane_t& plane, float llu, float llv, int llindex)
|
||||
{
|
||||
ffv.x = (float)vt->fX();
|
||||
ffv.y = (float)vt->fY();
|
||||
|
@ -200,7 +200,7 @@ static void SetFlatVertex(FFlatVertex& ffv, vertex_t* vt, const secplane_t& plan
|
|||
ffv.v = -(float)vt->fY() / 64.f;
|
||||
ffv.lu = llu;
|
||||
ffv.lv = llv;
|
||||
ffv.lindex = llindex;
|
||||
ffv.lindex = (float)llindex;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
Loading…
Reference in a new issue