mirror of
https://github.com/ZDoom/gzdoom-gles.git
synced 2024-11-14 00:20:38 +00:00
- avoid creating a new render pass if a pipeline bind will suffice
This commit is contained in:
parent
9ab19d057d
commit
7e37d640dc
4 changed files with 99 additions and 50 deletions
|
@ -203,7 +203,6 @@ std::unique_ptr<VulkanDescriptorSet> VkRenderPassManager::AllocateTextureDescrip
|
||||||
VkRenderPassSetup::VkRenderPassSetup(const VkRenderPassKey &key)
|
VkRenderPassSetup::VkRenderPassSetup(const VkRenderPassKey &key)
|
||||||
{
|
{
|
||||||
CreateRenderPass(key);
|
CreateRenderPass(key);
|
||||||
CreatePipeline(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkRenderPassSetup::CreateRenderPass(const VkRenderPassKey &key)
|
void VkRenderPassSetup::CreateRenderPass(const VkRenderPassKey &key)
|
||||||
|
@ -258,7 +257,15 @@ void VkRenderPassSetup::CreateRenderPass(const VkRenderPassKey &key)
|
||||||
RenderPass->SetDebugName("VkRenderPassSetup.RenderPass");
|
RenderPass->SetDebugName("VkRenderPassSetup.RenderPass");
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkRenderPassSetup::CreatePipeline(const VkRenderPassKey &key)
|
VulkanPipeline *VkRenderPassSetup::GetPipeline(const VkPipelineKey &key)
|
||||||
|
{
|
||||||
|
auto &item = Pipelines[key];
|
||||||
|
if (!item)
|
||||||
|
item = CreatePipeline(key);
|
||||||
|
return item.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<VulkanPipeline> VkRenderPassSetup::CreatePipeline(const VkPipelineKey &key)
|
||||||
{
|
{
|
||||||
auto fb = GetVulkanFrameBuffer();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
GraphicsPipelineBuilder builder;
|
GraphicsPipelineBuilder builder;
|
||||||
|
@ -348,6 +355,7 @@ void VkRenderPassSetup::CreatePipeline(const VkRenderPassKey &key)
|
||||||
|
|
||||||
builder.setLayout(fb->GetRenderPassManager()->GetPipelineLayout(key.NumTextureLayers));
|
builder.setLayout(fb->GetRenderPassManager()->GetPipelineLayout(key.NumTextureLayers));
|
||||||
builder.setRenderPass(RenderPass.get());
|
builder.setRenderPass(RenderPass.get());
|
||||||
Pipeline = builder.create(fb->device);
|
auto pipeline = builder.create(fb->device);
|
||||||
Pipeline->SetDebugName("VkRenderPassSetup.Pipeline");
|
pipeline->SetDebugName("VkRenderPassSetup.Pipeline");
|
||||||
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
class VKDataBuffer;
|
class VKDataBuffer;
|
||||||
|
|
||||||
class VkRenderPassKey
|
class VkPipelineKey
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FRenderStyle RenderStyle;
|
FRenderStyle RenderStyle;
|
||||||
|
@ -36,6 +36,36 @@ public:
|
||||||
|
|
||||||
bool UsesDepthStencil() const { return DepthTest || DepthWrite || StencilTest || (ClearTargets & (CT_Depth | CT_Stencil)); }
|
bool UsesDepthStencil() const { return DepthTest || DepthWrite || StencilTest || (ClearTargets & (CT_Depth | CT_Stencil)); }
|
||||||
|
|
||||||
|
bool operator<(const VkPipelineKey &other) const { return memcmp(this, &other, sizeof(VkPipelineKey)) < 0; }
|
||||||
|
bool operator==(const VkPipelineKey &other) const { return memcmp(this, &other, sizeof(VkPipelineKey)) == 0; }
|
||||||
|
bool operator!=(const VkPipelineKey &other) const { return memcmp(this, &other, sizeof(VkPipelineKey)) != 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class VkRenderPassKey
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VkRenderPassKey() = default;
|
||||||
|
VkRenderPassKey(const VkPipelineKey &key)
|
||||||
|
{
|
||||||
|
DepthWrite = key.DepthWrite;
|
||||||
|
DepthTest = key.DepthTest;
|
||||||
|
StencilTest = key.StencilTest;
|
||||||
|
Samples = key.Samples;
|
||||||
|
ClearTargets = key.ClearTargets;
|
||||||
|
DrawBuffers = key.DrawBuffers;
|
||||||
|
DrawBufferFormat = key.DrawBufferFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DepthWrite;
|
||||||
|
int DepthTest;
|
||||||
|
int StencilTest;
|
||||||
|
int Samples;
|
||||||
|
int ClearTargets;
|
||||||
|
int DrawBuffers;
|
||||||
|
VkFormat DrawBufferFormat;
|
||||||
|
|
||||||
|
bool UsesDepthStencil() const { return DepthTest || DepthWrite || StencilTest || (ClearTargets & (CT_Depth | CT_Stencil)); }
|
||||||
|
|
||||||
bool operator<(const VkRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkRenderPassKey)) < 0; }
|
bool operator<(const VkRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkRenderPassKey)) < 0; }
|
||||||
bool operator==(const VkRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkRenderPassKey)) == 0; }
|
bool operator==(const VkRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkRenderPassKey)) == 0; }
|
||||||
bool operator!=(const VkRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkRenderPassKey)) != 0; }
|
bool operator!=(const VkRenderPassKey &other) const { return memcmp(this, &other, sizeof(VkRenderPassKey)) != 0; }
|
||||||
|
@ -46,13 +76,15 @@ class VkRenderPassSetup
|
||||||
public:
|
public:
|
||||||
VkRenderPassSetup(const VkRenderPassKey &key);
|
VkRenderPassSetup(const VkRenderPassKey &key);
|
||||||
|
|
||||||
|
VulkanPipeline *GetPipeline(const VkPipelineKey &key);
|
||||||
|
|
||||||
std::unique_ptr<VulkanRenderPass> RenderPass;
|
std::unique_ptr<VulkanRenderPass> RenderPass;
|
||||||
std::unique_ptr<VulkanPipeline> Pipeline;
|
std::map<VkPipelineKey, std::unique_ptr<VulkanPipeline>> Pipelines;
|
||||||
std::map<VkImageView, std::unique_ptr<VulkanFramebuffer>> Framebuffer;
|
std::map<VkImageView, std::unique_ptr<VulkanFramebuffer>> Framebuffer;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CreatePipeline(const VkRenderPassKey &key);
|
|
||||||
void CreateRenderPass(const VkRenderPassKey &key);
|
void CreateRenderPass(const VkRenderPassKey &key);
|
||||||
|
std::unique_ptr<VulkanPipeline> CreatePipeline(const VkPipelineKey &key);
|
||||||
};
|
};
|
||||||
|
|
||||||
class VkVertexFormat
|
class VkVertexFormat
|
||||||
|
|
|
@ -196,65 +196,75 @@ void VkRenderState::ApplyDepthBias()
|
||||||
void VkRenderState::ApplyRenderPass(int dt)
|
void VkRenderState::ApplyRenderPass(int dt)
|
||||||
{
|
{
|
||||||
// Find a render pass that matches our state
|
// Find a render pass that matches our state
|
||||||
VkRenderPassKey passKey;
|
VkPipelineKey pipelineKey;
|
||||||
passKey.ClearTargets = mRenderPassKey.ClearTargets | mClearTargets;
|
pipelineKey.ClearTargets = mPipelineKey.ClearTargets | mClearTargets;
|
||||||
passKey.DrawType = dt;
|
pipelineKey.DrawType = dt;
|
||||||
passKey.VertexFormat = static_cast<VKVertexBuffer*>(mVertexBuffer)->VertexFormat;
|
pipelineKey.VertexFormat = static_cast<VKVertexBuffer*>(mVertexBuffer)->VertexFormat;
|
||||||
passKey.RenderStyle = mRenderStyle;
|
pipelineKey.RenderStyle = mRenderStyle;
|
||||||
passKey.DepthTest = mDepthTest;
|
pipelineKey.DepthTest = mDepthTest;
|
||||||
passKey.DepthWrite = mDepthTest && mDepthWrite;
|
pipelineKey.DepthWrite = mDepthTest && mDepthWrite;
|
||||||
passKey.DepthFunc = mDepthFunc;
|
pipelineKey.DepthFunc = mDepthFunc;
|
||||||
passKey.DepthClamp = mDepthClamp;
|
pipelineKey.DepthClamp = mDepthClamp;
|
||||||
passKey.DepthBias = !(mBias.mFactor == 0 && mBias.mUnits == 0);
|
pipelineKey.DepthBias = !(mBias.mFactor == 0 && mBias.mUnits == 0);
|
||||||
passKey.StencilTest = mStencilTest;
|
pipelineKey.StencilTest = mStencilTest;
|
||||||
passKey.StencilPassOp = mStencilOp;
|
pipelineKey.StencilPassOp = mStencilOp;
|
||||||
passKey.ColorMask = mColorMask;
|
pipelineKey.ColorMask = mColorMask;
|
||||||
passKey.CullMode = mCullMode;
|
pipelineKey.CullMode = mCullMode;
|
||||||
passKey.DrawBufferFormat = mRenderTarget.Format;
|
pipelineKey.DrawBufferFormat = mRenderTarget.Format;
|
||||||
passKey.Samples = mRenderTarget.Samples;
|
pipelineKey.Samples = mRenderTarget.Samples;
|
||||||
passKey.DrawBuffers = mRenderTarget.DrawBuffers;
|
pipelineKey.DrawBuffers = mRenderTarget.DrawBuffers;
|
||||||
passKey.NumTextureLayers = mMaterial.mMaterial ? mMaterial.mMaterial->GetLayers() : 0;
|
pipelineKey.NumTextureLayers = mMaterial.mMaterial ? mMaterial.mMaterial->GetLayers() : 0;
|
||||||
if (mSpecialEffect > EFF_NONE)
|
if (mSpecialEffect > EFF_NONE)
|
||||||
{
|
{
|
||||||
passKey.SpecialEffect = mSpecialEffect;
|
pipelineKey.SpecialEffect = mSpecialEffect;
|
||||||
passKey.EffectState = 0;
|
pipelineKey.EffectState = 0;
|
||||||
passKey.AlphaTest = false;
|
pipelineKey.AlphaTest = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int effectState = mMaterial.mOverrideShader >= 0 ? mMaterial.mOverrideShader : (mMaterial.mMaterial ? mMaterial.mMaterial->GetShaderIndex() : 0);
|
int effectState = mMaterial.mOverrideShader >= 0 ? mMaterial.mOverrideShader : (mMaterial.mMaterial ? mMaterial.mMaterial->GetShaderIndex() : 0);
|
||||||
passKey.SpecialEffect = EFF_NONE;
|
pipelineKey.SpecialEffect = EFF_NONE;
|
||||||
passKey.EffectState = mTextureEnabled ? effectState : SHADER_NoTexture;
|
pipelineKey.EffectState = mTextureEnabled ? effectState : SHADER_NoTexture;
|
||||||
passKey.AlphaTest = mAlphaThreshold >= 0.f;
|
pipelineKey.AlphaTest = mAlphaThreshold >= 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is this the one we already have or do we need to change render pass?
|
// Is this the one we already have or do we need to change pipeline?
|
||||||
bool changingRenderPass = (passKey != mRenderPassKey);
|
bool changingPipeline = (pipelineKey != mPipelineKey);
|
||||||
|
bool inRenderPass = mCommandBuffer;
|
||||||
|
|
||||||
if (!mCommandBuffer)
|
if (!inRenderPass)
|
||||||
{
|
{
|
||||||
mCommandBuffer = GetVulkanFrameBuffer()->GetDrawCommands();
|
mCommandBuffer = GetVulkanFrameBuffer()->GetDrawCommands();
|
||||||
changingRenderPass = true;
|
changingPipeline = true;
|
||||||
mScissorChanged = true;
|
mScissorChanged = true;
|
||||||
mViewportChanged = true;
|
mViewportChanged = true;
|
||||||
mStencilRefChanged = true;
|
mStencilRefChanged = true;
|
||||||
mBias.mChanged = true;
|
mBias.mChanged = true;
|
||||||
}
|
}
|
||||||
else if (changingRenderPass)
|
|
||||||
{
|
|
||||||
mCommandBuffer->endRenderPass();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changingRenderPass)
|
if (changingPipeline)
|
||||||
{
|
{
|
||||||
passKey.ClearTargets = mClearTargets;
|
pipelineKey.ClearTargets = mClearTargets;
|
||||||
|
|
||||||
// Only clear depth+stencil if the render target actually has that
|
// Only clear depth+stencil if the render target actually has that
|
||||||
if (!mRenderTarget.DepthStencil)
|
if (!mRenderTarget.DepthStencil)
|
||||||
passKey.ClearTargets &= ~(CT_Depth | CT_Stencil);
|
pipelineKey.ClearTargets &= ~(CT_Depth | CT_Stencil);
|
||||||
|
|
||||||
BeginRenderPass(passKey, mCommandBuffer);
|
// Begin new render pass if needed
|
||||||
mRenderPassKey = passKey;
|
VkRenderPassKey passKey = pipelineKey;
|
||||||
|
if (!inRenderPass || passKey != VkRenderPassKey(mPipelineKey))
|
||||||
|
{
|
||||||
|
if (inRenderPass)
|
||||||
|
mCommandBuffer->endRenderPass();
|
||||||
|
|
||||||
|
BeginRenderPass(passKey, mCommandBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bind the pipeline
|
||||||
|
VkRenderPassSetup *passSetup = GetVulkanFrameBuffer()->GetRenderPassManager()->GetRenderPass(passKey);
|
||||||
|
mCommandBuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->GetPipeline(pipelineKey));
|
||||||
|
|
||||||
|
mPipelineKey = pipelineKey;
|
||||||
mClearTargets = 0;
|
mClearTargets = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -385,7 +395,7 @@ void VkRenderState::ApplyPushConstants()
|
||||||
|
|
||||||
auto fb = GetVulkanFrameBuffer();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
auto passManager = fb->GetRenderPassManager();
|
auto passManager = fb->GetRenderPassManager();
|
||||||
mCommandBuffer->pushConstants(passManager->GetPipelineLayout(mRenderPassKey.NumTextureLayers), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &mPushConstants);
|
mCommandBuffer->pushConstants(passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &mPushConstants);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -471,7 +481,7 @@ void VkRenderState::ApplyMaterial()
|
||||||
{
|
{
|
||||||
auto fb = GetVulkanFrameBuffer();
|
auto fb = GetVulkanFrameBuffer();
|
||||||
auto passManager = fb->GetRenderPassManager();
|
auto passManager = fb->GetRenderPassManager();
|
||||||
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mRenderPassKey.NumTextureLayers), 1, base->GetDescriptorSet(mMaterial));
|
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 1, base->GetDescriptorSet(mMaterial));
|
||||||
}
|
}
|
||||||
|
|
||||||
mMaterial.mChanged = false;
|
mMaterial.mChanged = false;
|
||||||
|
@ -486,7 +496,7 @@ void VkRenderState::ApplyDynamicSet()
|
||||||
auto passManager = fb->GetRenderPassManager();
|
auto passManager = fb->GetRenderPassManager();
|
||||||
|
|
||||||
uint32_t offsets[3] = { mViewpointOffset, mMatricesOffset, mStreamDataOffset };
|
uint32_t offsets[3] = { mViewpointOffset, mMatricesOffset, mStreamDataOffset };
|
||||||
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mRenderPassKey.NumTextureLayers), 0, passManager->DynamicSet.get(), 3, offsets);
|
mCommandBuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, passManager->GetPipelineLayout(mPipelineKey.NumTextureLayers), 0, passManager->DynamicSet.get(), 3, offsets);
|
||||||
|
|
||||||
mLastViewpointOffset = mViewpointOffset;
|
mLastViewpointOffset = mViewpointOffset;
|
||||||
mLastMatricesOffset = mMatricesOffset;
|
mLastMatricesOffset = mMatricesOffset;
|
||||||
|
@ -515,7 +525,7 @@ void VkRenderState::EndRenderPass()
|
||||||
{
|
{
|
||||||
mCommandBuffer->endRenderPass();
|
mCommandBuffer->endRenderPass();
|
||||||
mCommandBuffer = nullptr;
|
mCommandBuffer = nullptr;
|
||||||
mRenderPassKey = {};
|
mPipelineKey = {};
|
||||||
|
|
||||||
mLastViewpointOffset = 0xffffffff;
|
mLastViewpointOffset = 0xffffffff;
|
||||||
mLastVertexBuffer = nullptr;
|
mLastVertexBuffer = nullptr;
|
||||||
|
@ -588,7 +598,6 @@ void VkRenderState::BeginRenderPass(const VkRenderPassKey &key, VulkanCommandBuf
|
||||||
beginInfo.addClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
beginInfo.addClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
beginInfo.addClearDepthStencil(1.0f, 0);
|
beginInfo.addClearDepthStencil(1.0f, 0);
|
||||||
cmdbuffer->beginRenderPass(beginInfo);
|
cmdbuffer->beginRenderPass(beginInfo);
|
||||||
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->Pipeline.get());
|
|
||||||
|
|
||||||
mMaterial.mChanged = true;
|
mMaterial.mChanged = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ protected:
|
||||||
|
|
||||||
bool mDepthClamp = true;
|
bool mDepthClamp = true;
|
||||||
VulkanCommandBuffer *mCommandBuffer = nullptr;
|
VulkanCommandBuffer *mCommandBuffer = nullptr;
|
||||||
VkRenderPassKey mRenderPassKey = {};
|
VkPipelineKey mPipelineKey = {};
|
||||||
int mClearTargets = 0;
|
int mClearTargets = 0;
|
||||||
bool mNeedApply = true;
|
bool mNeedApply = true;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue