Run the light tiles compute shader
This commit is contained in:
parent
2ba2c24f6b
commit
521e2ed39c
16 changed files with 162 additions and 11 deletions
|
|
@ -699,6 +699,7 @@ public:
|
|||
}
|
||||
|
||||
// Draw level mesh
|
||||
virtual void DispatchLightTiles() { }
|
||||
virtual void DrawLevelMesh(LevelMeshDrawType drawType, bool noFragmentShader) { }
|
||||
virtual int GetNextQueryIndex() { return 0; }
|
||||
virtual void BeginQuery() { }
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ struct HWViewpointUniforms
|
|||
|
||||
int mLightBlendMode = 0;
|
||||
|
||||
int mLightTilesWidth = 0;
|
||||
|
||||
void CalcDependencies()
|
||||
{
|
||||
mNormalViewMatrix.computeNormalMatrix(mViewMatrix);
|
||||
|
|
|
|||
|
|
@ -43,9 +43,11 @@ VkDescriptorSetManager::VkDescriptorSetManager(VulkanRenderDevice* fb) : fb(fb)
|
|||
CreateLevelMeshLayout();
|
||||
CreateRSBufferLayout();
|
||||
CreateFixedLayout();
|
||||
CreateLightTilesLayout();
|
||||
CreateLevelMeshPool();
|
||||
CreateRSBufferPool();
|
||||
CreateFixedPool();
|
||||
CreateLightTilesPool();
|
||||
CreateBindlessSet();
|
||||
}
|
||||
|
||||
|
|
@ -59,6 +61,7 @@ void VkDescriptorSetManager::Init()
|
|||
{
|
||||
RSBuffer.Set = RSBuffer.Pool->allocate(RSBuffer.Layout.get());
|
||||
LevelMesh.Set = LevelMesh.Pool->allocate(LevelMesh.Layout.get());
|
||||
LightTiles.Set = LightTiles.Pool->allocate(LightTiles.Layout.get());
|
||||
|
||||
auto rsbuffers = fb->GetBufferManager()->GetRSBuffers();
|
||||
WriteDescriptors()
|
||||
|
|
@ -81,6 +84,7 @@ void VkDescriptorSetManager::BeginFrame()
|
|||
{
|
||||
UpdateFixedSet();
|
||||
UpdateLevelMeshSet();
|
||||
UpdateLightTilesSet();
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::UpdateLevelMeshSet()
|
||||
|
|
@ -97,6 +101,15 @@ void VkDescriptorSetManager::UpdateLevelMeshSet()
|
|||
.Execute(fb->GetDevice());
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::UpdateLightTilesSet()
|
||||
{
|
||||
WriteDescriptors()
|
||||
.AddStorageImage(LightTiles.Set.get(), 0, fb->GetBuffers()->SceneZMinMax[4].View.get(), VK_IMAGE_LAYOUT_GENERAL)
|
||||
.AddBuffer(LightTiles.Set.get(), 1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetLevelMesh()->GetUniformsBuffer())
|
||||
.AddBuffer(LightTiles.Set.get(), 2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, fb->GetBuffers()->SceneLightTiles.get())
|
||||
.Execute(fb->GetDevice());
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::UpdateFixedSet()
|
||||
{
|
||||
fb->GetCommands()->DrawDeleteList->Add(std::move(Fixed.Set));
|
||||
|
|
@ -250,6 +263,26 @@ void VkDescriptorSetManager::CreateFixedLayout()
|
|||
Fixed.Layout = builder.Create(fb->GetDevice());
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::CreateLightTilesLayout()
|
||||
{
|
||||
LightTiles.Layout = DescriptorSetLayoutBuilder()
|
||||
.AddBinding(0, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1, VK_SHADER_STAGE_COMPUTE_BIT)
|
||||
.AddBinding(1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT)
|
||||
.AddBinding(2, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT)
|
||||
.DebugName("VkDescriptorSetManager.LightTiles.Layout")
|
||||
.Create(fb->GetDevice());
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::CreateLightTilesPool()
|
||||
{
|
||||
LightTiles.Pool = DescriptorPoolBuilder()
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
|
||||
.AddPoolSize(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 2)
|
||||
.MaxSets(1)
|
||||
.DebugName("VkDescriptorSetManager.LightTiles.Pool")
|
||||
.Create(fb->GetDevice());
|
||||
}
|
||||
|
||||
void VkDescriptorSetManager::CreateLevelMeshPool()
|
||||
{
|
||||
LevelMesh.Pool = DescriptorPoolBuilder()
|
||||
|
|
|
|||
|
|
@ -21,17 +21,18 @@ public:
|
|||
void Deinit();
|
||||
void BeginFrame();
|
||||
void ResetHWTextureSets();
|
||||
void UpdateLevelMeshSet();
|
||||
|
||||
VulkanDescriptorSetLayout* GetLevelMeshLayout() { return LevelMesh.Layout.get(); }
|
||||
VulkanDescriptorSetLayout* GetRSBufferLayout() { return RSBuffer.Layout.get(); }
|
||||
VulkanDescriptorSetLayout* GetFixedLayout() { return Fixed.Layout.get(); }
|
||||
VulkanDescriptorSetLayout* GetBindlessLayout() { return Bindless.Layout.get(); }
|
||||
VulkanDescriptorSetLayout* GetLightTilesLayout() { return LightTiles.Layout.get(); }
|
||||
|
||||
VulkanDescriptorSet* GetLevelMeshSet() { return LevelMesh.Set.get(); }
|
||||
VulkanDescriptorSet* GetRSBufferSet() { return RSBuffer.Set.get(); }
|
||||
VulkanDescriptorSet* GetFixedSet() { return Fixed.Set.get(); }
|
||||
VulkanDescriptorSet* GetBindlessSet() { return Bindless.Set.get(); }
|
||||
VulkanDescriptorSet* GetLightTilesSet() { return LightTiles.Set.get(); }
|
||||
|
||||
VulkanDescriptorSet* GetInput(VkPPRenderPassSetup* passSetup, const TArray<PPTextureInput>& textures, bool bindShadowMapBuffers);
|
||||
|
||||
|
|
@ -45,11 +46,15 @@ private:
|
|||
void CreateLevelMeshLayout();
|
||||
void CreateRSBufferLayout();
|
||||
void CreateFixedLayout();
|
||||
void CreateLightTilesLayout();
|
||||
void CreateLevelMeshPool();
|
||||
void CreateRSBufferPool();
|
||||
void CreateFixedPool();
|
||||
void CreateLightTilesPool();
|
||||
void CreateBindlessSet();
|
||||
void UpdateFixedSet();
|
||||
void UpdateLevelMeshSet();
|
||||
void UpdateLightTilesSet();
|
||||
|
||||
std::unique_ptr<VulkanDescriptorSet> AllocatePPSet(VulkanDescriptorSetLayout* layout);
|
||||
|
||||
|
|
@ -90,6 +95,13 @@ private:
|
|||
std::unique_ptr<VulkanDescriptorPool> Pool;
|
||||
} Postprocess;
|
||||
|
||||
struct
|
||||
{
|
||||
std::unique_ptr<VulkanDescriptorPool> Pool;
|
||||
std::unique_ptr<VulkanDescriptorSet> Set;
|
||||
std::unique_ptr<VulkanDescriptorSetLayout> Layout;
|
||||
} LightTiles;
|
||||
|
||||
std::list<VkMaterial*> Materials;
|
||||
|
||||
static const int MaxFixedSets = 100;
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ VkRenderPassManager::VkRenderPassManager(VulkanRenderDevice* fb) : fb(fb)
|
|||
}
|
||||
|
||||
PipelineCache = builder.Create(fb->GetDevice());
|
||||
|
||||
CreateLightTilesPipeline();
|
||||
}
|
||||
|
||||
VkRenderPassManager::~VkRenderPassManager()
|
||||
|
|
@ -154,6 +156,22 @@ VkPPRenderPassSetup* VkRenderPassManager::GetPPRenderPass(const VkPPRenderPassKe
|
|||
return passSetup.get();
|
||||
}
|
||||
|
||||
void VkRenderPassManager::CreateLightTilesPipeline()
|
||||
{
|
||||
LightTiles.Layout = PipelineLayoutBuilder()
|
||||
.AddSetLayout(fb->GetDescriptorSetManager()->GetLightTilesLayout())
|
||||
.AddPushConstantRange(VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(LightTilesPushConstants))
|
||||
.DebugName("VkRenderPassManager.LightTiles.Layout")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
LightTiles.Pipeline = ComputePipelineBuilder()
|
||||
.Cache(PipelineCache.get())
|
||||
.Layout(LightTiles.Layout.get())
|
||||
.ComputeShader(fb->GetShaderManager()->GetLightTilesShader())
|
||||
.DebugName("VkRenderPassManager.LightTiles.Pipeline")
|
||||
.Create(fb->GetDevice());
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
VkRenderPassSetup::VkRenderPassSetup(VulkanRenderDevice* fb, const VkRenderPassKey &key) : PassKey(key), fb(fb)
|
||||
|
|
|
|||
|
|
@ -115,7 +115,12 @@ public:
|
|||
|
||||
VulkanPipelineCache* GetCache() { return PipelineCache.get(); }
|
||||
|
||||
VulkanPipelineLayout* GetLightTilesLayout() { return LightTiles.Layout.get(); }
|
||||
VulkanPipeline* GetLightTilesPipeline() { return LightTiles.Pipeline.get(); }
|
||||
|
||||
private:
|
||||
void CreateLightTilesPipeline();
|
||||
|
||||
VulkanRenderDevice* fb = nullptr;
|
||||
|
||||
std::map<VkRenderPassKey, std::unique_ptr<VkRenderPassSetup>> RenderPassSetup;
|
||||
|
|
@ -124,6 +129,12 @@ private:
|
|||
|
||||
std::map<VkPPRenderPassKey, std::unique_ptr<VkPPRenderPassSetup>> PPRenderPassSetup;
|
||||
|
||||
struct
|
||||
{
|
||||
std::unique_ptr<VulkanPipelineLayout> Layout;
|
||||
std::unique_ptr<VulkanPipeline> Pipeline;
|
||||
} LightTiles;
|
||||
|
||||
FString CacheFilename;
|
||||
std::unique_ptr<VulkanPipelineCache> PipelineCache;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -53,6 +53,13 @@ struct PushConstants
|
|||
int uFogballIndex; // fog balls
|
||||
};
|
||||
|
||||
struct LightTilesPushConstants
|
||||
{
|
||||
int normalLightCount;
|
||||
int modulatedLightCount;
|
||||
int subtractiveLightCount;
|
||||
};
|
||||
|
||||
class VkShaderKey
|
||||
{
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -292,7 +292,7 @@ void VkRenderBuffers::CreateSceneZMinMax(int width, int height)
|
|||
SceneZMinMax[i].Image = ImageBuilder()
|
||||
.Size(width, height)
|
||||
.Format(VK_FORMAT_R32G32_SFLOAT)
|
||||
.Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
|
||||
.Usage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT)
|
||||
.DebugName("VkRenderBuffers.SceneZMinMax")
|
||||
.Create(fb->GetDevice());
|
||||
|
||||
|
|
@ -309,7 +309,7 @@ void VkRenderBuffers::CreateSceneLightTiles(int width, int height)
|
|||
height = (height + 63) / 64;
|
||||
|
||||
// Make room for 16 lights plus the lightdata header
|
||||
size_t blockSize = (1 + 3 * 16) * sizeof(FVector4);
|
||||
size_t blockSize = (1 + 4 * 16) * sizeof(FVector4);
|
||||
|
||||
SceneLightTiles = BufferBuilder()
|
||||
.Usage(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)
|
||||
|
|
|
|||
|
|
@ -236,6 +236,7 @@ void VulkanRenderDevice::InitializeState()
|
|||
|
||||
mPostprocess.reset(new VkPostprocess(this));
|
||||
mDescriptorSetManager.reset(new VkDescriptorSetManager(this));
|
||||
mShaderManager.reset(new VkShaderManager(this));
|
||||
mRenderPassManager.reset(new VkRenderPassManager(this));
|
||||
mLevelMesh.reset(new VkLevelMesh(this));
|
||||
mLightmapper.reset(new VkLightmapper(this));
|
||||
|
|
@ -245,7 +246,6 @@ void VulkanRenderDevice::InitializeState()
|
|||
mSkyData = new FSkyVertexBuffer(this);
|
||||
mShadowMap = new ShadowMap(this);
|
||||
|
||||
mShaderManager.reset(new VkShaderManager(this));
|
||||
mDescriptorSetManager->Init();
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
|
|
|||
|
|
@ -867,6 +867,43 @@ void VkRenderState::ApplyLevelMesh()
|
|||
mCommandBuffer->bindIndexBuffer(fb->GetLevelMesh()->GetDrawIndexBuffer()->buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
}
|
||||
|
||||
void VkRenderState::DispatchLightTiles()
|
||||
{
|
||||
EndRenderPass();
|
||||
|
||||
auto cmdbuffer = fb->GetCommands()->GetDrawCommands();
|
||||
|
||||
// To do: run the zminmax pass
|
||||
VkImageTransition()
|
||||
.AddImage(&fb->GetBuffers()->SceneZMinMax[4], VK_IMAGE_LAYOUT_GENERAL, true /* false */)
|
||||
.Execute(cmdbuffer);
|
||||
|
||||
PipelineBarrier()
|
||||
.AddBuffer(fb->GetBuffers()->SceneLightTiles.get(), VK_ACCESS_SHADER_READ_BIT, VK_ACCESS_SHADER_WRITE_BIT)
|
||||
.Execute(cmdbuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||
|
||||
LightTilesPushConstants pushConstants = {};
|
||||
//auto mesh = fb->GetLevelMesh()->GetMesh();
|
||||
//pushConstants.normalLightCount = mesh->Mesh.NormalLightCount;
|
||||
//pushConstants.modulatedLightCount = mesh->Mesh.ModulatedLightCount;
|
||||
//pushConstants.subtractiveLightCount = mesh->Mesh.SubtractiveLightCount;
|
||||
|
||||
auto pipelines = fb->GetRenderPassManager();
|
||||
auto descriptors = fb->GetDescriptorSetManager();
|
||||
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, pipelines->GetLightTilesPipeline());
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_COMPUTE, pipelines->GetLightTilesLayout(), 0, descriptors->GetLightTilesSet());
|
||||
cmdbuffer->pushConstants(pipelines->GetLightTilesLayout(), VK_SHADER_STAGE_COMPUTE_BIT, 0, (uint32_t)sizeof(LightTilesPushConstants), &pushConstants);
|
||||
|
||||
cmdbuffer->dispatch(
|
||||
(fb->GetBuffers()->GetWidth() + 63) / 64,
|
||||
(fb->GetBuffers()->GetHeight() + 63) / 64,
|
||||
1);
|
||||
|
||||
PipelineBarrier()
|
||||
.AddBuffer(fb->GetBuffers()->SceneLightTiles.get(), VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT)
|
||||
.Execute(cmdbuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
|
||||
}
|
||||
|
||||
void VkRenderState::DrawLevelMesh(LevelMeshDrawType drawType, bool noFragmentShader)
|
||||
{
|
||||
ApplyLevelMesh();
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ public:
|
|||
void ResetVertices() override;
|
||||
|
||||
// Draw level mesh
|
||||
void DispatchLightTiles() override;
|
||||
void DrawLevelMesh(LevelMeshDrawType drawType, bool noFragmentShader) override;
|
||||
int GetNextQueryIndex() override;
|
||||
void BeginQuery() override;
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ void HWDrawInfo::StartScene(FRenderViewpoint &parentvp, HWViewpointUniforms *uni
|
|||
VPUniforms.mViewOffsetX = -screen->mSceneViewport.left;
|
||||
VPUniforms.mViewOffsetY = -screen->mSceneViewport.top;
|
||||
VPUniforms.mViewHeight = viewheight;
|
||||
VPUniforms.mLightTilesWidth = (screen->mScreenViewport.width + 63) / 64;
|
||||
if (lightmode == ELightMode::Build)
|
||||
{
|
||||
VPUniforms.mGlobVis = 1 / 64.f;
|
||||
|
|
@ -442,6 +443,7 @@ void HWDrawInfo::CreateScene(bool drawpsprites, FRenderState& state)
|
|||
state.SetColorMask(false);
|
||||
state.SetCulling(Cull_CW);
|
||||
state.DrawLevelMesh(LevelMeshDrawType::Opaque, true);
|
||||
state.DispatchLightTiles();
|
||||
state.DrawLevelMesh(LevelMeshDrawType::Masked, false); // To do: properly mark wall top/bottom as opaque so we don't need this
|
||||
if (gl_portals)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ layout(set = 1, binding = 0, std140) uniform ViewpointUBO
|
|||
int uShadowmapFilter;
|
||||
|
||||
int uLightBlendMode;
|
||||
|
||||
int uLightTilesWidth; // Levelmesh light tiles
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 1, std140) uniform MatricesUBO
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
layout(local_size_x = 32, local_size_y = 32) in;
|
||||
layout(binding = 0, rg32f) readonly uniform image2D zminmax;
|
||||
layout(set = 0, binding = 0, rg32f) readonly uniform image2D zminmax;
|
||||
|
||||
layout(binding = 1) readonly buffer Lights
|
||||
layout(set = 0, binding = 1) readonly buffer Lights
|
||||
{
|
||||
vec4 lights[];
|
||||
};
|
||||
|
||||
layout(binding = 1) buffer Tiles
|
||||
layout(set = 0, binding = 2) buffer Tiles
|
||||
{
|
||||
vec4 tiles[];
|
||||
};
|
||||
|
|
@ -26,18 +26,37 @@ void main()
|
|||
return;
|
||||
|
||||
const int maxLights = 16;
|
||||
const int lightSize = 3;
|
||||
const int lightSize = 4;
|
||||
int tileOffset = (tilePos.x + tilePos.y * zminmaxSize.x) * (1 + maxLights * lightSize);
|
||||
|
||||
vec2 minmax = imageLoad(zminmax, tilePos).xy;
|
||||
float zmin = minmax.x;
|
||||
float zmax = minmax.y;
|
||||
|
||||
int tileNormalCount = 0;
|
||||
int tileNormalCount = 1;
|
||||
int tileModulatedCount = 0;
|
||||
int tileSubtractiveCount = 0;
|
||||
|
||||
// To do: cull and add lights
|
||||
|
||||
tiles[tileOffset] = vec4(ivec4(tileNormalCount, tileModulatedCount, tileSubtractiveCount, 0));
|
||||
tiles[tileOffset] = vec4(ivec4(
|
||||
0,
|
||||
tileNormalCount,
|
||||
tileNormalCount + tileModulatedCount,
|
||||
tileNormalCount + tileModulatedCount + tileSubtractiveCount));
|
||||
|
||||
vec3 pos = vec3(-316.0, 64.0, 621.0);
|
||||
float radius = 200.0;
|
||||
vec3 color = vec3(1.0, 1.0, 1.0);
|
||||
float shadowIndex = -1025.0;
|
||||
vec3 spotDir = vec3(0.0);
|
||||
float lightType = 0.0;
|
||||
float spotInnerAngle = 0.0;
|
||||
float spotOuterAngle = 0.0;
|
||||
float softShadowRadius = 0.0;
|
||||
|
||||
tiles[tileOffset + 1] = vec4(pos, radius);
|
||||
tiles[tileOffset + 2] = vec4(color, shadowIndex);
|
||||
tiles[tileOffset + 3] = vec4(spotDir, lightType);
|
||||
tiles[tileOffset + 4] = vec4(spotInnerAngle, spotOuterAngle, softShadowRadius, 0.0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@ void main()
|
|||
if (ClipDistanceA.x < 0 || ClipDistanceA.y < 0 || ClipDistanceA.z < 0 || ClipDistanceA.w < 0 || ClipDistanceB.x < 0) discard;
|
||||
#endif
|
||||
|
||||
#if defined(USE_LEVELMESH)
|
||||
const int lightTileSize = 1 + 16 * 4;
|
||||
uLightIndex = int(uint(gl_FragCoord.x) / 64 + uint(gl_FragCoord.y) / 64 * uLightTilesWidth) * lightTileSize;
|
||||
#endif
|
||||
|
||||
Material material = CreateMaterial();
|
||||
|
||||
#ifndef NO_ALPHATEST
|
||||
|
|
|
|||
|
|
@ -73,7 +73,8 @@ layout(push_constant) uniform PushConstants
|
|||
#define uVertexColor lightdata[uDataIndex].uVertexColor
|
||||
#define uDesaturationFactor lightdata[uDataIndex].uDesaturationFactor
|
||||
#define uLightLevel lightdata[uDataIndex].uLightLevel
|
||||
#define uLightIndex lightdata[uDataIndex].uLightIndex
|
||||
//#define uLightIndex lightdata[uDataIndex].uLightIndex
|
||||
int uLightIndex;
|
||||
#else
|
||||
#define uVertexColor data[uDataIndex].uVertexColor
|
||||
#define uDesaturationFactor data[uDataIndex].uDesaturationFactor
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue