mirror of
https://github.com/ZDoom/gzdoom.git
synced 2025-02-21 19:41:11 +00:00
Perform the copy from the atlas resolve image to the lightmap texture on the GPU
This commit is contained in:
parent
3b0f19a57f
commit
ab370c7a91
4 changed files with 33 additions and 101 deletions
|
@ -188,7 +188,7 @@ public:
|
|||
|
||||
void BuildSmoothingGroups()
|
||||
{
|
||||
for (size_t i = 0, count = GetSurfaceCount(); i < count; i++)
|
||||
for (int i = 0, count = GetSurfaceCount(); i < count; i++)
|
||||
{
|
||||
auto surface = GetSurface(i);
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
#include "vk_lightmap.h"
|
||||
#include "vulkan/vk_renderdevice.h"
|
||||
#include "vulkan/textures/vk_texture.h"
|
||||
#include "vulkan/commands/vk_commandbuffer.h"
|
||||
#include "vk_raytrace.h"
|
||||
#include "zvulkan/vulkanbuilders.h"
|
||||
|
@ -49,13 +50,6 @@ void VkLightmap::Raytrace(LevelMesh* level)
|
|||
{
|
||||
ResolveAtlasImage(pageIndex);
|
||||
}
|
||||
|
||||
fb->GetCommands()->WaitForCommands(false);
|
||||
|
||||
for (size_t pageIndex = 0; pageIndex < atlasImages.size(); pageIndex++)
|
||||
{
|
||||
DownloadAtlasImage(pageIndex);
|
||||
}
|
||||
}
|
||||
|
||||
void VkLightmap::RenderAtlasImage(size_t pageIndex)
|
||||
|
@ -215,9 +209,9 @@ void VkLightmap::UploadUniforms()
|
|||
.Execute(cmdbuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
void VkLightmap::ResolveAtlasImage(size_t i)
|
||||
void VkLightmap::ResolveAtlasImage(size_t pageIndex)
|
||||
{
|
||||
LightmapImage& img = atlasImages[i];
|
||||
LightmapImage& img = atlasImages[pageIndex];
|
||||
|
||||
auto cmdbuffer = fb->GetCommands()->GetTransferCommands();
|
||||
|
||||
|
@ -270,51 +264,42 @@ void VkLightmap::ResolveAtlasImage(size_t i)
|
|||
|
||||
cmdbuffer->endRenderPass();
|
||||
|
||||
PipelineBarrier()
|
||||
.AddImage(img.resolve.Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT)
|
||||
.Execute(cmdbuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
VkBufferImageCopy region = {};
|
||||
region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.imageSubresource.layerCount = 1;
|
||||
region.imageExtent.width = atlasImageSize;
|
||||
region.imageExtent.height = atlasImageSize;
|
||||
region.imageExtent.depth = 1;
|
||||
cmdbuffer->copyImageToBuffer(img.resolve.Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, img.Transfer->buffer, 1, ®ion);
|
||||
}
|
||||
|
||||
void VkLightmap::DownloadAtlasImage(size_t pageIndex)
|
||||
{
|
||||
struct hvec4
|
||||
{
|
||||
unsigned short x, y, z, w;
|
||||
FVector3 xyz() { return FVector3(halfToFloat(x), halfToFloat(y), halfToFloat(z)); }
|
||||
};
|
||||
|
||||
hvec4* pixels = (hvec4*)atlasImages[pageIndex].Transfer->Map(0, atlasImageSize * atlasImageSize * sizeof(hvec4));
|
||||
|
||||
std::vector<VkImageCopy> regions;
|
||||
for (int i = 0, count = mesh->GetSurfaceCount(); i < count; i++)
|
||||
{
|
||||
LevelMeshSurface* surface = mesh->GetSurface(i);
|
||||
if (surface->lightmapperAtlasPage != pageIndex)
|
||||
continue;
|
||||
|
||||
int lightmapperAtlasX = surface->lightmapperAtlasX;
|
||||
int lightmapperAtlasY = surface->lightmapperAtlasY;
|
||||
int sampleWidth = surface->texWidth;
|
||||
int sampleHeight = surface->texHeight;
|
||||
|
||||
for (int y = 0; y < sampleHeight; y++)
|
||||
{
|
||||
FVector3* dest = &surface->texPixels[y * sampleWidth];
|
||||
hvec4* src = &pixels[lightmapperAtlasX + (lightmapperAtlasY + y) * atlasImageSize];
|
||||
for (int x = 0; x < sampleWidth; x++)
|
||||
{
|
||||
dest[x] = src[x].xyz();
|
||||
}
|
||||
}
|
||||
VkImageCopy region = {};
|
||||
region.srcOffset.x = surface->lightmapperAtlasX;
|
||||
region.srcOffset.y = surface->lightmapperAtlasY;
|
||||
region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.srcSubresource.layerCount = 1;
|
||||
region.dstOffset.x = surface->atlasX;
|
||||
region.dstOffset.y = surface->atlasY;
|
||||
region.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
region.dstSubresource.layerCount = 1;
|
||||
region.dstSubresource.baseArrayLayer = surface->atlasPageIndex;
|
||||
region.extent.width = surface->texWidth;
|
||||
region.extent.height = surface->texHeight;
|
||||
region.extent.depth = 1;
|
||||
regions.push_back(region);
|
||||
}
|
||||
|
||||
if (!regions.empty())
|
||||
{
|
||||
PipelineBarrier()
|
||||
.AddImage(img.resolve.Image.get(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT)
|
||||
.AddImage(fb->GetTextureManager()->Lightmap.Image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, (int)pageIndex, 1)
|
||||
.Execute(cmdbuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
cmdbuffer->copyImage(img.resolve.Image->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, fb->GetTextureManager()->Lightmap.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, (uint32_t)regions.size(), regions.data());
|
||||
|
||||
PipelineBarrier()
|
||||
.AddImage(fb->GetTextureManager()->Lightmap.Image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT, VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, (int)pageIndex, 1)
|
||||
.Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
atlasImages[pageIndex].Transfer->Unmap();
|
||||
}
|
||||
|
||||
FVector2 VkLightmap::ToUV(const FVector3& vert, const LevelMeshSurface* targetSurface)
|
||||
|
@ -589,12 +574,6 @@ LightmapImage VkLightmap::CreateImage(int width, int height)
|
|||
.DebugName("LightmapImage.resolve.Framebuffer")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
img.Transfer = BufferBuilder()
|
||||
.Size(width * height * sizeof(FVector4))
|
||||
.Usage(VK_IMAGE_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_CPU_ONLY)
|
||||
.DebugName("LightmapImage.Transfer")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
return img;
|
||||
}
|
||||
|
||||
|
|
|
@ -46,8 +46,6 @@ struct LightmapImage
|
|||
std::unique_ptr<VulkanImageView> View;
|
||||
std::unique_ptr<VulkanFramebuffer> Framebuffer;
|
||||
} resolve;
|
||||
|
||||
std::unique_ptr<VulkanBuffer> Transfer;
|
||||
};
|
||||
|
||||
struct SceneVertex
|
||||
|
@ -88,7 +86,6 @@ private:
|
|||
void CreateAtlasImages();
|
||||
void RenderAtlasImage(size_t pageIndex);
|
||||
void ResolveAtlasImage(size_t pageIndex);
|
||||
void DownloadAtlasImage(size_t pageIndex);
|
||||
|
||||
LightmapImage CreateImage(int width, int height);
|
||||
|
||||
|
|
|
@ -62,7 +62,6 @@
|
|||
#include <zvulkan/vulkancompatibledevice.h>
|
||||
#include "engineerrors.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "accelstructs/halffloat.h"
|
||||
|
||||
FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames, int maxFrames = -1);
|
||||
|
||||
|
@ -541,51 +540,8 @@ void VulkanRenderDevice::SetLevelMesh(LevelMesh* mesh)
|
|||
{
|
||||
lastMesh = mesh;
|
||||
|
||||
#if 0 // To do: GetLightmap()->Raytrace should output directly to the lightmap texture instead of forcing us to download it to the CPU first
|
||||
|
||||
GetTextureManager()->CreateLightmap(mesh->LMTextureSize, mesh->LMTextureCount);
|
||||
GetCommands()->WaitForCommands(false);
|
||||
GetLightmap()->Raytrace(mesh);
|
||||
|
||||
#else // Temporary version using the old zdray Raytracer code as-is
|
||||
|
||||
Printf("Running VkLightmap.\n");
|
||||
|
||||
GetLightmap()->Raytrace(mesh);
|
||||
|
||||
Printf("Copying data.\n");
|
||||
|
||||
// TODO refactor
|
||||
auto clamp = [](float a, float min, float max) -> float { return a < min ? min : a > max ? max : a; };
|
||||
|
||||
TArray<uint16_t> LMTextureData;
|
||||
LMTextureData.Resize(mesh->LMTextureSize * mesh->LMTextureSize * mesh->LMTextureCount * 3);
|
||||
|
||||
for (int i = 0, count = mesh->GetSurfaceCount(); i < count; i++)
|
||||
{
|
||||
LevelMeshSurface* surface = mesh->GetSurface(i);
|
||||
|
||||
uint16_t* currentTexture = LMTextureData.Data() + (mesh->LMTextureSize * mesh->LMTextureSize * 3) * surface->atlasPageIndex;
|
||||
|
||||
FVector3* colorSamples = surface->texPixels.data();
|
||||
// store results to lightmap texture
|
||||
for (int i = 0; i < surface->texHeight; i++)
|
||||
{
|
||||
for (int j = 0; j < surface->texWidth; j++)
|
||||
{
|
||||
// get texture offset
|
||||
int offs = ((mesh->LMTextureSize * (i + surface->atlasY)) + surface->atlasX) * 3;
|
||||
|
||||
// convert RGB to bytes
|
||||
currentTexture[offs + j * 3 + 0] = floatToHalf(clamp(colorSamples[i * surface->texWidth + j].X, 0.0f, 65000.0f));
|
||||
currentTexture[offs + j * 3 + 1] = floatToHalf(clamp(colorSamples[i * surface->texWidth + j].Y, 0.0f, 65000.0f));
|
||||
currentTexture[offs + j * 3 + 2] = floatToHalf(clamp(colorSamples[i * surface->texWidth + j].Z, 0.0f, 65000.0f));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GetTextureManager()->SetLightmap(mesh->LMTextureSize, mesh->LMTextureCount, LMTextureData);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue