Move DrawLevelMesh to RenderState

This commit is contained in:
Magnus Norddahl 2023-12-02 16:26:51 +01:00
commit 47f17b1c03
10 changed files with 136 additions and 256 deletions

View file

@ -727,192 +727,7 @@ int VulkanRenderDevice::GetLevelMeshPipelineID(const MeshApplyData& applyData, c
return levelMeshPipelineKeys.Size() - 1;
}
void VulkanRenderDevice::DrawLevelMesh(const HWViewpointUniforms& viewpoint)
const VkPipelineKey& VulkanRenderDevice::GetLevelMeshPipelineKey(int id) const
{
auto cmdbuffer = GetCommands()->GetDrawCommands();
auto buffers = GetBuffers();
auto descriptors = GetDescriptorSetManager();
descriptors->UpdateLevelMeshSet();
VkRenderPassKey key = {};
key.DrawBufferFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
key.Samples = buffers->GetSceneSamples();
key.DrawBuffers = 1; // 3 if ssao is enabled
key.DepthStencil = true;
auto passSetup = GetRenderPassManager()->GetRenderPass(key);
RenderPassBegin beginInfo;
beginInfo.RenderPass(passSetup->GetRenderPass(CT_Color | CT_Depth | CT_Stencil));
beginInfo.RenderArea(0, 0, buffers->GetWidth(), buffers->GetHeight());
beginInfo.Framebuffer(buffers->GetFramebuffer(key));
beginInfo.AddClearColor(screen->mSceneClearColor[0], screen->mSceneClearColor[1], screen->mSceneClearColor[2], screen->mSceneClearColor[3]);
if (key.DrawBuffers > 1)
beginInfo.AddClearColor(0.0f, 0.0f, 0.0f, 0.0f);
if (key.DrawBuffers > 2)
beginInfo.AddClearColor(0.0f, 0.0f, 0.0f, 0.0f);
beginInfo.AddClearDepthStencil(1.0f, 0);
beginInfo.Execute(cmdbuffer);
VkViewport viewport = {};
viewport.x = (float)mSceneViewport.left;
viewport.y = (float)mSceneViewport.top;
viewport.width = (float)mSceneViewport.width;
viewport.height = (float)mSceneViewport.height;
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
cmdbuffer->setViewport(0, 1, &viewport);
VkRect2D scissor = {};
scissor.offset.x = 0;
scissor.offset.y = 0;
scissor.extent.width = mSceneViewport.width;
scissor.extent.height = mSceneViewport.height;
cmdbuffer->setScissor(0, 1, &scissor);
cmdbuffer->setStencilReference(VK_STENCIL_FRONT_AND_BACK, 0);
cmdbuffer->setDepthBias(0.0f, 0.0f, 0.0f);
VkBuffer vertexBuffers[2] = { GetRaytrace()->GetVertexBuffer()->buffer, GetRaytrace()->GetUniformIndexBuffer()->buffer };
VkDeviceSize vertexBufferOffsets[] = { 0, 0 };
cmdbuffer->bindVertexBuffers(0, 2, vertexBuffers, vertexBufferOffsets);
cmdbuffer->bindIndexBuffer(GetRaytrace()->GetIndexBuffer()->buffer, 0, VK_INDEX_TYPE_UINT32);
auto rsbuffers = GetBufferManager()->GetRSBuffers();
memcpy(((char*)rsbuffers->Viewpoint.Data) + rsbuffers->Viewpoint.UploadIndex * rsbuffers->Viewpoint.BlockAlign, &viewpoint, sizeof(HWViewpointUniforms));
int viewpointIndex = rsbuffers->Viewpoint.UploadIndex++;
MatricesUBO matrices = {};
matrices.ModelMatrix.loadIdentity();
matrices.NormalModelMatrix.loadIdentity();
matrices.TextureMatrix.loadIdentity();
rsbuffers->MatrixBuffer->Write(matrices);
auto submesh = GetRaytrace()->GetMesh()->StaticMesh.get();
// Draw opaque scene into the depth buffer
for (LevelSubmeshDrawRange& range : submesh->DrawList)
{
VkPipelineKey pipelineKey = levelMeshPipelineKeys[range.PipelineID];
if (pipelineKey.ShaderKey.AlphaTest) continue;
pipelineKey.ShaderKey.NoFragmentShader = true;
DrawLevelMeshRange(cmdbuffer, passSetup, pipelineKey, viewpointIndex, range.Start, range.Count, 0);
}
for (LevelSubmeshDrawRange& range : submesh->PortalList)
{
VkPipelineKey pipelineKey = levelMeshPipelineKeys[range.PipelineID];
pipelineKey.ShaderKey.NoFragmentShader = true;
DrawLevelMeshRange(cmdbuffer, passSetup, pipelineKey, viewpointIndex, range.Start, range.Count, 0);
}
// Draw portal surface occlusion queries
//int portalIndex = 0;
//cmdbuffer->beginQuery(queryPool, portalIndex, 0);
for (LevelSubmeshDrawRange& range : submesh->PortalList)
{
VkPipelineKey pipelineKey = levelMeshPipelineKeys[range.PipelineID];
pipelineKey.ShaderKey.NoFragmentShader = true;
DrawLevelMeshRange(cmdbuffer, passSetup, pipelineKey, viewpointIndex, range.Start, range.Count, 0);
}
//cmdbuffer->endQuery(queryPool, portalIndex);
//portalIndex++;
// Draw opaque scene
for (LevelSubmeshDrawRange& range : submesh->DrawList)
{
DrawLevelMeshRange(cmdbuffer, passSetup, levelMeshPipelineKeys[range.PipelineID], viewpointIndex, range.Start, range.Count, 0);
}
cmdbuffer->endRenderPass();
GetCommands()->FlushCommands(false);
//VkResult result = vkGetQueryPoolResults(GetDevice()->device, queryPool->pool, 0, portalIndex, ...);
cmdbuffer = GetCommands()->GetDrawCommands();
// Create stencil
for (LevelSubmeshDrawRange& range : submesh->PortalList)
{
VkPipelineKey pipelineKey = levelMeshPipelineKeys[range.PipelineID];
pipelineKey.ShaderKey.NoFragmentShader = true;
pipelineKey.StencilTest = true;
pipelineKey.StencilPassOp = SOP_Increment;
DrawLevelMeshRange(cmdbuffer, passSetup, pipelineKey, viewpointIndex, range.Start, range.Count, 0);
}
// Clear zbuffer
viewport.minDepth = 1.0f;
viewport.maxDepth = 1.0f;
cmdbuffer->setViewport(0, 1, &viewport);
for (LevelSubmeshDrawRange& range : submesh->PortalList)
{
VkPipelineKey pipelineKey = levelMeshPipelineKeys[range.PipelineID];
pipelineKey.ShaderKey.NoFragmentShader = true;
pipelineKey.StencilTest = true;
pipelineKey.StencilPassOp = SOP_Keep;
pipelineKey.DepthFunc = DF_Always;
DrawLevelMeshRange(cmdbuffer, passSetup, pipelineKey, viewpointIndex, range.Start, range.Count, 1);
}
// Portal scene
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;
cmdbuffer->setViewport(0, 1, &viewport);
/*
auto& state = *mRenderState.get();
state.SetTextureMode(TM_OPAQUE);
mSkyData->RenderDome(state, origin->texture[0], origin->x_offset[0], origin->y_offset, origin->mirrored, FSkyVertexBuffer::SKYMODE_MAINLAYER, !!(di->Level->flags & LEVEL_FORCETILEDSKY));
state.SetTextureMode(TM_NORMAL);
*/
// Clear zbuffer
viewport.minDepth = 1.0f;
viewport.maxDepth = 1.0f;
cmdbuffer->setViewport(0, 1, &viewport);
for (LevelSubmeshDrawRange& range : submesh->PortalList)
{
VkPipelineKey pipelineKey = levelMeshPipelineKeys[range.PipelineID];
pipelineKey.ShaderKey.NoFragmentShader = true;
pipelineKey.StencilTest = true;
pipelineKey.StencilPassOp = SOP_Keep;
pipelineKey.DepthFunc = DF_Always;
DrawLevelMeshRange(cmdbuffer, passSetup, pipelineKey, viewpointIndex, range.Start, range.Count, 1);
}
// Restore zbuffer
for (LevelSubmeshDrawRange& range : submesh->PortalList)
{
VkPipelineKey pipelineKey = levelMeshPipelineKeys[range.PipelineID];
pipelineKey.ShaderKey.NoFragmentShader = true;
pipelineKey.StencilTest = true;
pipelineKey.StencilPassOp = SOP_Decrement;
DrawLevelMeshRange(cmdbuffer, passSetup, pipelineKey, viewpointIndex, range.Start, range.Count, 1);
}
}
void VulkanRenderDevice::DrawLevelMeshRange(VulkanCommandBuffer* cmdbuffer, VkRenderPassSetup* passSetup, const VkPipelineKey& pipelineKey, int viewpointIndex, int start, int count, int stencilRef)
{
auto rsbuffers = GetBufferManager()->GetRSBuffers();
auto descriptors = GetDescriptorSetManager();
PushConstants pushConstants = {};
pushConstants.uDataIndex = 0;
pushConstants.uLightIndex = -1;
pushConstants.uBoneIndexBase = -1;
VulkanPipelineLayout* layout = GetRenderPassManager()->GetPipelineLayout(pipelineKey.NumTextureLayers, pipelineKey.ShaderKey.UseLevelMesh);
uint32_t viewpointOffset = viewpointIndex * rsbuffers->Viewpoint.BlockAlign;
uint32_t matrixOffset = rsbuffers->MatrixBuffer->Offset();
uint32_t lightsOffset = 0;
uint32_t offsets[] = { viewpointOffset, matrixOffset, lightsOffset };
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->GetPipeline(pipelineKey));
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedSet());
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 1, descriptors->GetLevelMeshSet(), 3, offsets);
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 2, descriptors->GetBindlessSet());
cmdbuffer->pushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &pushConstants);
cmdbuffer->setStencilReference(VK_STENCIL_FACE_FRONT_AND_BACK, stencilRef);
cmdbuffer->drawIndexed(count, 1, start, 0, 0);
return levelMeshPipelineKeys[id];
}