Refactor to reduce reallocations and copying
This commit is contained in:
parent
04195e8331
commit
7dc050edb0
10 changed files with 91 additions and 51 deletions
|
|
@ -1,6 +1,6 @@
|
|||
#include "hw_lightprobe.h"
|
||||
|
||||
void LightProbeIncrementalBuilder::Step(const TArray<LightProbe>& probes, std::function<void(const LightProbe&, TArray<uint16_t>&, TArray<uint16_t>&)> renderScene, std::function<void(TArray<uint16_t>&&, TArray<uint16_t>&&)> uploadEnv)
|
||||
void LightProbeIncrementalBuilder::Step(const TArray<LightProbe>& probes, std::function<void(const LightProbe&, TArrayView<uint16_t>&, TArrayView<uint16_t>&)> renderScene, std::function<void(const TArray<uint16_t>&, const TArray<uint16_t>&)> uploadEnv)
|
||||
{
|
||||
if (lastIndex >= probes.size())
|
||||
{
|
||||
|
|
@ -12,28 +12,44 @@ void LightProbeIncrementalBuilder::Step(const TArray<LightProbe>& probes, std::f
|
|||
}
|
||||
}
|
||||
|
||||
TArray<uint16_t> irradianceMap;
|
||||
TArray<uint16_t> prefilterMap;
|
||||
if (cubemapsAllocated != probes.size())
|
||||
{
|
||||
int newSegments = probes.size();
|
||||
int lastSegments = cubemapsAllocated;
|
||||
|
||||
renderScene(probes[lastIndex++], irradianceMap, prefilterMap);
|
||||
irradianceMaps.resize(probes.size() * irradianceBytes);
|
||||
prefilterMaps.resize(probes.size() * prefilterBytes);
|
||||
cubemapsAllocated = probes.size();
|
||||
|
||||
lastIndex = 0;
|
||||
collected = 0;
|
||||
|
||||
// needed because otherwise it somehow gets corrupted
|
||||
memset(irradianceMaps.Data(), 0, irradianceMaps.Size() * sizeof(uint16_t));
|
||||
memset(prefilterMaps.Data(), 0, prefilterMaps.Size() * sizeof(uint16_t));
|
||||
|
||||
// workaround for lack of boundary checking in GPU
|
||||
uploadEnv(this->irradianceMaps, this->prefilterMaps);
|
||||
return;
|
||||
}
|
||||
|
||||
auto irradianceBuffer = TArrayView<uint16_t>(irradianceMaps.data() + lastIndex * irradianceBytes, irradianceBytes);
|
||||
auto prefilterBuffer = TArrayView<uint16_t>(prefilterMaps.data() + lastIndex * prefilterBytes, prefilterBytes);
|
||||
|
||||
renderScene(probes[lastIndex++], irradianceBuffer, prefilterBuffer);
|
||||
++collected;
|
||||
|
||||
this->irradianceMaps.Append(irradianceMap);
|
||||
this->prefilterMaps.Append(prefilterMap);
|
||||
|
||||
if (lastIndex >= probes.size())
|
||||
{
|
||||
if (collected == probes.size())
|
||||
{
|
||||
uploadEnv(std::move(this->irradianceMaps), std::move(this->prefilterMaps));
|
||||
uploadEnv(this->irradianceMaps, this->prefilterMaps);
|
||||
}
|
||||
this->irradianceMaps.Clear();
|
||||
this->prefilterMaps.Clear();
|
||||
collected = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void LightProbeIncrementalBuilder::Full(const TArray<LightProbe>& probes, std::function<void(const LightProbe&, TArray<uint16_t>&, TArray<uint16_t>&)> renderScene, std::function<void(TArray<uint16_t>&&, TArray<uint16_t>&&)> uploadEnv)
|
||||
void LightProbeIncrementalBuilder::Full(const TArray<LightProbe>& probes, std::function<void(const LightProbe&, TArrayView<uint16_t>&, TArrayView<uint16_t>&)> renderScene, std::function<void(const TArray<uint16_t>&, const TArray<uint16_t>&)> uploadEnv)
|
||||
{
|
||||
if (lastIndex >= probes.size())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -16,16 +16,25 @@ struct LightProbeTarget
|
|||
class LightProbeIncrementalBuilder
|
||||
{
|
||||
int lastIndex = 0;
|
||||
int collected = 0;
|
||||
|
||||
int cubemapsAllocated = 0;
|
||||
|
||||
int collected;
|
||||
|
||||
TArray<uint16_t> irradianceMaps;
|
||||
TArray<uint16_t> prefilterMaps;
|
||||
|
||||
size_t irradianceBytes;
|
||||
size_t prefilterBytes;
|
||||
public:
|
||||
LightProbeIncrementalBuilder(size_t irradianceTexels, size_t prefilterTexels, size_t irradianceChannels, size_t prefilterChannels) :
|
||||
irradianceBytes(irradianceTexels * irradianceChannels),
|
||||
prefilterBytes(prefilterTexels * prefilterChannels)
|
||||
{
|
||||
}
|
||||
|
||||
void Step(const TArray<LightProbe>& probes, std::function<void(const LightProbe&, TArray<uint16_t>&, TArray<uint16_t>&)> renderScene, std::function<void(TArray<uint16_t>&&, TArray<uint16_t>&&)> uploadEnv);
|
||||
void Full(const TArray<LightProbe>& probes, std::function<void(const LightProbe&, TArray<uint16_t>&, TArray<uint16_t>&)> renderScene, std::function<void(TArray<uint16_t>&&, TArray<uint16_t>&&)> uploadEnv);
|
||||
void Step(const TArray<LightProbe>& probes, std::function<void(const LightProbe&, TArrayView<uint16_t>&, TArrayView<uint16_t>&)> renderScene, std::function<void(const TArray<uint16_t>&, const TArray<uint16_t>&)> uploadEnv);
|
||||
void Full(const TArray<LightProbe>& probes, std::function<void(const LightProbe&, TArrayView<uint16_t>&, TArrayView<uint16_t>&)> renderScene, std::function<void(const TArray<uint16_t>&, const TArray<uint16_t>&)> uploadEnv);
|
||||
|
||||
auto GetStep() const { return lastIndex; }
|
||||
auto GetBufferSize() const { return irradianceMaps.size() && prefilterMaps.size(); }
|
||||
};
|
||||
|
|
@ -221,8 +221,8 @@ public:
|
|||
// Get the array index for the material in the textures array accessible from shaders
|
||||
virtual int GetBindlessTextureIndex(FMaterial* material, int clampmode, int translation) { return -1; }
|
||||
|
||||
virtual void RenderEnvironmentMap(std::function<void(IntRect& bounds, int side)> renderFunc, TArray<uint16_t>& irradianceMap, TArray<uint16_t>& prefilterMap) {}
|
||||
virtual void UploadEnvironmentMaps(int cubemapCount, TArray<uint16_t>&& irradianceMaps, TArray<uint16_t>&& prefilterMaps) {}
|
||||
virtual void RenderEnvironmentMap(std::function<void(IntRect& bounds, int side)> renderFunc, TArrayView<uint16_t>& irradianceMap, TArrayView<uint16_t>& prefilterMap) {}
|
||||
virtual void UploadEnvironmentMaps(int cubemapCount, const TArray<uint16_t>& irradianceMaps, const TArray<uint16_t>& prefilterMaps) {}
|
||||
|
||||
// Screen wiping
|
||||
virtual FTexture *WipeStartScreen();
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ void VkTextureManager::CreatePrefiltermap()
|
|||
CreatePrefiltermap(size, 6, std::move(data));
|
||||
}
|
||||
|
||||
void VkTextureManager::CreateIrradiancemap(int size, int count, TArray<uint16_t>&& newPixelData)
|
||||
void VkTextureManager::CreateIrradiancemap(int size, int count, const TArray<uint16_t>& newPixelData)
|
||||
{
|
||||
if (Irradiancemap.Size == size && Irradiancemap.Count == count && newPixelData.Size() == 0)
|
||||
return;
|
||||
|
|
@ -346,8 +346,6 @@ void VkTextureManager::CreateIrradiancemap(int size, int count, TArray<uint16_t>
|
|||
cmdbuffer->copyBufferToImage(stagingBuffer->buffer, Irradiancemap.Image.Image->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
|
||||
fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer));
|
||||
|
||||
newPixelData.Clear();
|
||||
}
|
||||
|
||||
VkImageTransition()
|
||||
|
|
@ -355,7 +353,7 @@ void VkTextureManager::CreateIrradiancemap(int size, int count, TArray<uint16_t>
|
|||
.Execute(cmdbuffer);
|
||||
}
|
||||
|
||||
void VkTextureManager::CreatePrefiltermap(int size, int count, TArray<uint16_t>&& newPixelData)
|
||||
void VkTextureManager::CreatePrefiltermap(int size, int count, const TArray<uint16_t>& newPixelData)
|
||||
{
|
||||
if (Prefiltermap.Size == size && Prefiltermap.Count == count && newPixelData.Size() == 0)
|
||||
return;
|
||||
|
|
@ -443,8 +441,6 @@ void VkTextureManager::CreatePrefiltermap(int size, int count, TArray<uint16_t>&
|
|||
}
|
||||
|
||||
fb->GetCommands()->TransferDeleteList->Add(std::move(stagingBuffer));
|
||||
|
||||
newPixelData.Clear();
|
||||
}
|
||||
|
||||
VkImageTransition()
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ public:
|
|||
void BeginFrame();
|
||||
|
||||
void CreateLightmap(int size, int count, TArray<uint16_t>&& data);
|
||||
void CreateIrradiancemap(int size, int count, TArray<uint16_t>&& data);
|
||||
void CreatePrefiltermap(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 DownloadLightmap(int arrayIndex, uint16_t* buffer);
|
||||
|
||||
VkTextureImage* GetTexture(const PPTextureType& type, PPTexture* tex);
|
||||
|
|
|
|||
|
|
@ -256,8 +256,15 @@ void VkLightprober::CreateIrradianceMap()
|
|||
}
|
||||
}
|
||||
|
||||
TArray<uint16_t> VkLightprober::GenerateIrradianceMap()
|
||||
bool VkLightprober::GenerateIrradianceMap(TArrayView<uint16_t>& databuffer)
|
||||
{
|
||||
const int texelCount = irrandiaceMapTexelCount;
|
||||
|
||||
if (databuffer.Size() < texelCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto staging = BufferBuilder()
|
||||
.Size(32 * 32 * 8 * 6)
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_TO_CPU)
|
||||
|
|
@ -334,9 +341,7 @@ TArray<uint16_t> VkLightprober::GenerateIrradianceMap()
|
|||
fb->GetCommands()->WaitForCommands(false);
|
||||
|
||||
// Copy while dropping the alpha channel
|
||||
int texelCount = 32 * 32 * 6;
|
||||
TArray<uint16_t> databuffer(texelCount * 3, true);
|
||||
auto dst = databuffer.data();
|
||||
auto dst = databuffer.Data();
|
||||
auto src = (uint16_t*)staging->Map(0, texelCount * 8);
|
||||
for (int i = 0; i < texelCount; i++)
|
||||
{
|
||||
|
|
@ -346,7 +351,7 @@ TArray<uint16_t> VkLightprober::GenerateIrradianceMap()
|
|||
src++;
|
||||
}
|
||||
staging->Unmap();
|
||||
return databuffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
void VkLightprober::CreatePrefilterMap()
|
||||
|
|
@ -398,8 +403,15 @@ void VkLightprober::CreatePrefilterMap()
|
|||
}
|
||||
}
|
||||
|
||||
TArray<uint16_t> VkLightprober::GeneratePrefilterMap()
|
||||
bool VkLightprober::GeneratePrefilterMap(TArrayView<uint16_t>& databuffer)
|
||||
{
|
||||
const int texelCount = prefilterMapTexelCount;
|
||||
|
||||
if (databuffer.Size() < texelCount)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
auto staging = BufferBuilder()
|
||||
.Size(prefilterMap.levelsSize * 6 * 8)
|
||||
.Usage(VK_BUFFER_USAGE_TRANSFER_DST_BIT, VMA_MEMORY_USAGE_GPU_TO_CPU)
|
||||
|
|
@ -484,9 +496,7 @@ TArray<uint16_t> VkLightprober::GeneratePrefilterMap()
|
|||
fb->GetCommands()->WaitForCommands(false);
|
||||
|
||||
// Copy while dropping the alpha channel
|
||||
int texelCount = prefilterMap.levelsSize * 6;
|
||||
TArray<uint16_t> databuffer(texelCount * 3, true);
|
||||
auto dst = databuffer.data();
|
||||
auto dst = databuffer.Data();
|
||||
auto src = (uint16_t*)staging->Map(0, texelCount * 8);
|
||||
for (int i = 0; i < texelCount; i++)
|
||||
{
|
||||
|
|
@ -496,7 +506,7 @@ TArray<uint16_t> VkLightprober::GeneratePrefilterMap()
|
|||
src++;
|
||||
}
|
||||
staging->Unmap();
|
||||
return databuffer;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<VulkanShader> VkLightprober::CompileShader(const std::string& name, const std::string& filename, const char* debugName)
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ public:
|
|||
~VkLightprober();
|
||||
|
||||
void RenderEnvironmentMap(std::function<void(IntRect& bounds, int side)> renderFunc);
|
||||
TArray<uint16_t> GenerateIrradianceMap();
|
||||
TArray<uint16_t> GeneratePrefilterMap();
|
||||
bool GenerateIrradianceMap(TArrayView<uint16_t>& databuffer);
|
||||
bool GeneratePrefilterMap(TArrayView<uint16_t>& databuffer);
|
||||
|
||||
private:
|
||||
void CreateBrdfLutResources();
|
||||
|
|
@ -89,7 +89,7 @@ private:
|
|||
std::unique_ptr<VulkanImageView> views[6];
|
||||
} irradianceMap;
|
||||
|
||||
struct
|
||||
struct PrefilterMap
|
||||
{
|
||||
enum
|
||||
{
|
||||
|
|
@ -108,4 +108,12 @@ private:
|
|||
} prefilterMap;
|
||||
|
||||
VulkanRenderDevice* fb = nullptr;
|
||||
|
||||
public:
|
||||
// Used to pass buffer sizes
|
||||
constexpr static const int irrandiaceMapTexelCount = 32 * 32 * 6;
|
||||
constexpr static const int prefilterMapTexelCount = PrefilterMap::levelsSize * 6;
|
||||
|
||||
constexpr static const int irradianceMapChannelCount = 3;
|
||||
constexpr static const int prefilterMapChannelCount = 3;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -321,18 +321,17 @@ void VulkanRenderDevice::RenderTextureView(FCanvasTexture* tex, std::function<vo
|
|||
tex->SetUpdated(true);
|
||||
}
|
||||
|
||||
void VulkanRenderDevice::RenderEnvironmentMap(std::function<void(IntRect& bounds, int side)> renderFunc, TArray<uint16_t>& irradianceMap, TArray<uint16_t>& prefilterMap)
|
||||
void VulkanRenderDevice::RenderEnvironmentMap(std::function<void(IntRect& bounds, int side)> renderFunc, TArrayView<uint16_t>& irradianceMap, TArrayView<uint16_t>& prefilterMap)
|
||||
{
|
||||
mLightprober->RenderEnvironmentMap(std::move(renderFunc));
|
||||
irradianceMap = mLightprober->GenerateIrradianceMap();
|
||||
prefilterMap = mLightprober->GeneratePrefilterMap();
|
||||
|
||||
mLightprober->GenerateIrradianceMap(irradianceMap);
|
||||
mLightprober->GeneratePrefilterMap(prefilterMap);
|
||||
}
|
||||
|
||||
void VulkanRenderDevice::UploadEnvironmentMaps(int cubemapCount, TArray<uint16_t>&& irradianceMaps, TArray<uint16_t>&& prefilterMaps)
|
||||
void VulkanRenderDevice::UploadEnvironmentMaps(int cubemapCount, const TArray<uint16_t>& irradianceMaps, const TArray<uint16_t>& prefilterMaps)
|
||||
{
|
||||
mTextureManager->CreateIrradiancemap(32, 6 * cubemapCount, std::move(irradianceMaps));
|
||||
mTextureManager->CreatePrefiltermap(128, 6 * cubemapCount, std::move(prefilterMaps));
|
||||
mTextureManager->CreateIrradiancemap(32, 6 * cubemapCount, irradianceMaps);
|
||||
mTextureManager->CreatePrefiltermap(128, 6 * cubemapCount, prefilterMaps);
|
||||
}
|
||||
|
||||
void VulkanRenderDevice::PostProcessScene(bool swscene, int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D)
|
||||
|
|
|
|||
|
|
@ -104,8 +104,8 @@ public:
|
|||
|
||||
private:
|
||||
void RenderTextureView(FCanvasTexture* tex, std::function<void(IntRect &)> renderFunc) override;
|
||||
void RenderEnvironmentMap(std::function<void(IntRect& bounds, int side)> renderFunc, TArray<uint16_t>& irradianceMap, TArray<uint16_t>& prefilterMap) override;
|
||||
void UploadEnvironmentMaps(int cubemapCount, TArray<uint16_t>&& irradianceMaps, TArray<uint16_t>&& prefilterMaps) override;
|
||||
void RenderEnvironmentMap(std::function<void(IntRect& bounds, int side)> renderFunc, TArrayView<uint16_t>& irradianceMap, TArrayView<uint16_t>& prefilterMap) override;
|
||||
void UploadEnvironmentMaps(int cubemapCount, const TArray<uint16_t>& irradianceMaps, const TArray<uint16_t>& prefilterMaps) override;
|
||||
void PrintStartupLog();
|
||||
void CopyScreenToBuffer(int w, int h, uint8_t *data) override;
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@
|
|||
#include "hwrenderer/scene/hw_drawcontext.h"
|
||||
#include "hw_vrmodes.h"
|
||||
|
||||
#include "common/rendering/vulkan/vk_lightprober.h" // to fetch irradiance and prefilter map texel counts
|
||||
|
||||
EXTERN_CVAR(Bool, cl_capfps)
|
||||
EXTERN_CVAR(Float, r_visibility)
|
||||
EXTERN_CVAR(Bool, gl_bandedswlight)
|
||||
|
|
@ -333,7 +335,7 @@ static void CheckTimer(FRenderState &state, uint64_t ShaderStartTime)
|
|||
state.firstFrame = screen->FrameTime - 1;
|
||||
}
|
||||
|
||||
LightProbeIncrementalBuilder lightProbeBuilder;
|
||||
LightProbeIncrementalBuilder lightProbeBuilder(VkLightprober::irrandiaceMapTexelCount, VkLightprober::prefilterMapTexelCount, VkLightprober::irradianceMapChannelCount, VkLightprober::prefilterMapChannelCount);
|
||||
|
||||
sector_t* RenderView(player_t* player)
|
||||
{
|
||||
|
|
@ -410,7 +412,7 @@ sector_t* RenderView(player_t* player)
|
|||
AActor* lightprobe = level.GetThinkerIterator<AActor>(NAME_LightProbe, STAT_INFO).Next();
|
||||
if (lightprobe)
|
||||
{
|
||||
auto renderEnvMap = [&](const LightProbe& probe, TArray<uint16_t>& irradianceMap, TArray<uint16_t>& prefilteredMap) {
|
||||
auto renderEnvMap = [&](const LightProbe& probe, TArrayView<uint16_t>& irradianceMap, TArrayView<uint16_t>& prefilteredMap) {
|
||||
lightprobe->SetOrigin(DVector3(probe.position), false); // crime against nature
|
||||
|
||||
// The renderer interpolates camera in its own mechanism that has to be disabled when moving around the single probe
|
||||
|
|
@ -425,8 +427,8 @@ sector_t* RenderView(player_t* player)
|
|||
r_NoInterpolate = noInterpolate;
|
||||
};
|
||||
|
||||
auto renderEnvScreen = [&](TArray<uint16_t>&& irradianceMaps, TArray<uint16_t>&& prefilteredMaps) {
|
||||
screen->UploadEnvironmentMaps(level.lightProbes.size(), std::move(irradianceMaps), std::move(prefilteredMaps));
|
||||
auto renderEnvScreen = [&](const TArray<uint16_t>& irradianceMaps, const TArray<uint16_t>& prefilteredMaps) {
|
||||
screen->UploadEnvironmentMaps(level.lightProbes.size(), irradianceMaps, prefilteredMaps);
|
||||
};
|
||||
|
||||
lightProbeBuilder.Step(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue