From c0c0271c7b94a2317093468401163c2a803c1b97 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 3 Sep 2023 05:03:57 +0200 Subject: [PATCH] Perform the copy from the atlas resolve image to the lightmap texture on the GPU --- .../rendering/hwrenderer/data/hw_levelmesh.h | 2 +- .../vulkan/accelstructs/vk_lightmap.cpp | 83 +++++++------------ .../vulkan/accelstructs/vk_lightmap.h | 3 - .../rendering/vulkan/vk_renderdevice.cpp | 44 ---------- 4 files changed, 32 insertions(+), 100 deletions(-) diff --git a/src/common/rendering/hwrenderer/data/hw_levelmesh.h b/src/common/rendering/hwrenderer/data/hw_levelmesh.h index 9ac563f7a..65be52a9e 100644 --- a/src/common/rendering/hwrenderer/data/hw_levelmesh.h +++ b/src/common/rendering/hwrenderer/data/hw_levelmesh.h @@ -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); diff --git a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp index 018f98ec3..c43f1d7ff 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp +++ b/src/common/rendering/vulkan/accelstructs/vk_lightmap.cpp @@ -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" @@ -48,13 +49,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) @@ -214,9 +208,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(); @@ -269,51 +263,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 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; + 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); + } - 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(); - } - } + 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; } diff --git a/src/common/rendering/vulkan/accelstructs/vk_lightmap.h b/src/common/rendering/vulkan/accelstructs/vk_lightmap.h index c9ad6d225..77c734b8e 100644 --- a/src/common/rendering/vulkan/accelstructs/vk_lightmap.h +++ b/src/common/rendering/vulkan/accelstructs/vk_lightmap.h @@ -46,8 +46,6 @@ struct LightmapImage std::unique_ptr View; std::unique_ptr Framebuffer; } resolve; - - std::unique_ptr 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); diff --git a/src/common/rendering/vulkan/vk_renderdevice.cpp b/src/common/rendering/vulkan/vk_renderdevice.cpp index 34388651f..54df71ca6 100644 --- a/src/common/rendering/vulkan/vk_renderdevice.cpp +++ b/src/common/rendering/vulkan/vk_renderdevice.cpp @@ -62,7 +62,6 @@ #include #include "engineerrors.h" #include "c_dispatch.h" -#include "accelstructs/halffloat.h" FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames, int maxFrames = -1); @@ -539,51 +538,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 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 } }