1
0
forked from 0ad/0ad

Adds framebuffer attachment load and store operations.

Comments By: phosit, Stan
Differential Revision: https://code.wildfiregames.com/D4830
This was SVN commit r27256.
This commit is contained in:
Vladislav Belov 2022-11-26 21:55:17 +00:00
parent e9979c62b3
commit 29368cf776
25 changed files with 555 additions and 190 deletions

View File

@ -281,10 +281,16 @@ void CLOSTexture::ConstructTexture(Renderer::Backend::IDeviceCommandContext* dev
m_SmoothTextures[1] = backendDevice->CreateTexture2D("LOSSmoothTexture1",
usage, m_TextureFormat, textureSize, textureSize, defaultSamplerDesc);
Renderer::Backend::SColorAttachment colorAttachment{};
colorAttachment.texture = m_SmoothTextures[0].get();
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::DONT_CARE;
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
colorAttachment.clearColor = CColor{0.0f, 0.0f, 0.0f, 0.0f};
m_SmoothFramebuffers[0] = backendDevice->CreateFramebuffer(
"LOSSmoothFramebuffer0", m_SmoothTextures[0].get(), nullptr);
"LOSSmoothFramebuffer0", &colorAttachment, nullptr);
colorAttachment.texture = m_SmoothTextures[1].get();
m_SmoothFramebuffers[1] = backendDevice->CreateFramebuffer(
"LOSSmoothFramebuffer1", m_SmoothTextures[1].get(), nullptr);
"LOSSmoothFramebuffer1", &colorAttachment, nullptr);
if (!m_SmoothFramebuffers[0] || !m_SmoothFramebuffers[1])
{
LOGERROR("Failed to create LOS framebuffers");

View File

@ -355,8 +355,13 @@ void CMiniMapTexture::CreateTextures(
Renderer::Backend::Format::R8G8B8A8_UNORM,
FINAL_TEXTURE_SIZE, FINAL_TEXTURE_SIZE, defaultSamplerDesc));
m_FinalTextureFramebuffer = backendDevice->CreateFramebuffer("MiniMapFinalFramebuffer",
m_FinalTexture->GetBackendTexture(), nullptr);
Renderer::Backend::SColorAttachment colorAttachment{};
colorAttachment.texture = m_FinalTexture->GetBackendTexture();
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::DONT_CARE;
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
colorAttachment.clearColor = CColor{0.0f, 0.0f, 0.0f, 0.0f};
m_FinalTextureFramebuffer = backendDevice->CreateFramebuffer(
"MiniMapFinalFramebuffer", &colorAttachment, nullptr);
ENSURE(m_FinalTextureFramebuffer);
}

View File

@ -148,8 +148,13 @@ void CPostprocManager::RecreateBuffers()
for (BlurScale::Step& step : scale.steps)
{
GEN_BUFFER_RGBA(step.texture, width, height);
step.framebuffer = backendDevice->CreateFramebuffer("BlurScaleSteoFramebuffer",
step.texture.get(), nullptr);
Renderer::Backend::SColorAttachment colorAttachment{};
colorAttachment.texture = step.texture.get();
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::LOAD;
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
colorAttachment.clearColor = CColor{0.0f, 0.0f, 0.0f, 0.0f};
step.framebuffer = backendDevice->CreateFramebuffer(
"BlurScaleSteoFramebuffer", &colorAttachment, nullptr);
}
width /= 2;
height /= 2;
@ -167,13 +172,29 @@ void CPostprocManager::RecreateBuffers()
Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE));
// Set up the framebuffers with some initial textures.
m_CaptureFramebuffer = backendDevice->CreateFramebuffer("PostprocCaptureFramebuffer",
m_ColorTex1.get(), m_DepthTex.get(), CColor(0.0f, 0.0f, 0.0f, 0.0f));
Renderer::Backend::SColorAttachment colorAttachment{};
colorAttachment.texture = m_ColorTex1.get();
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::DONT_CARE;
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
colorAttachment.clearColor = CColor{0.0f, 0.0f, 0.0f, 0.0f};
Renderer::Backend::SDepthStencilAttachment depthStencilAttachment{};
depthStencilAttachment.texture = m_DepthTex.get();
depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR;
depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
m_CaptureFramebuffer = backendDevice->CreateFramebuffer("PostprocCaptureFramebuffer",
&colorAttachment, &depthStencilAttachment);
colorAttachment.texture = m_ColorTex1.get();
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::LOAD;
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
m_PingFramebuffer = backendDevice->CreateFramebuffer("PostprocPingFramebuffer",
m_ColorTex1.get(), nullptr);
&colorAttachment, nullptr);
colorAttachment.texture = m_ColorTex2.get();
m_PongFramebuffer = backendDevice->CreateFramebuffer("PostprocPongFramebuffer",
m_ColorTex2.get(), nullptr);
&colorAttachment, nullptr);
if (!m_CaptureFramebuffer || !m_PingFramebuffer || !m_PongFramebuffer)
{
@ -403,7 +424,8 @@ void CPostprocManager::CaptureRenderOutput(
void CPostprocManager::ReleaseRenderOutput(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IFramebuffer* destination)
{
ENSURE(m_IsInitialized);
@ -411,8 +433,7 @@ void CPostprocManager::ReleaseRenderOutput(
// We blit to the backbuffer from the previous active buffer.
deviceCommandContext->BlitFramebuffer(
deviceCommandContext->GetDevice()->GetCurrentBackbuffer(),
(m_WhichBuffer ? m_PingFramebuffer : m_PongFramebuffer).get());
destination, (m_WhichBuffer ? m_PingFramebuffer : m_PongFramebuffer).get());
}
void CPostprocManager::ApplyEffect(
@ -675,8 +696,19 @@ void CPostprocManager::CreateMultisampleBuffer()
Renderer::Backend::Sampler::AddressMode::CLAMP_TO_EDGE), 1, m_MultisampleCount);
// Set up the framebuffers with some initial textures.
m_MultisampleFramebuffer = backendDevice->CreateFramebuffer("PostprocMultisampleFramebuffer",
m_MultisampleColorTex.get(), m_MultisampleDepthTex.get(), CColor(0.0f, 0.0f, 0.0f, 0.0f));
Renderer::Backend::SColorAttachment colorAttachment{};
colorAttachment.texture = m_MultisampleColorTex.get();
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::DONT_CARE;
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
colorAttachment.clearColor = CColor{0.0f, 0.0f, 0.0f, 0.0f};
Renderer::Backend::SDepthStencilAttachment depthStencilAttachment{};
depthStencilAttachment.texture = m_MultisampleDepthTex.get();
depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR;
depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
m_MultisampleFramebuffer = backendDevice->CreateFramebuffer(
"PostprocMultisampleFramebuffer", &colorAttachment, &depthStencilAttachment);
if (!m_MultisampleFramebuffer)
{

View File

@ -74,10 +74,13 @@ public:
void ApplyPostproc(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
// Blits the final postprocessed texture to the system framebuffer. The system framebuffer
// is selected as the output buffer. Should be called before silhouette rendering.
// Blits the final postprocessed texture to the system framebuffer. The system
// framebuffer is selected as the output buffer. Should be called before
// silhouette rendering.
// @note CPostprocManager must be initialized first
void ReleaseRenderOutput(Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
void ReleaseRenderOutput(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
Renderer::Backend::IFramebuffer* destination);
// Returns true if we render main scene in the MSAA framebuffer.
bool IsMultisampleEnabled() const;

View File

@ -482,8 +482,14 @@ void CRenderer::RenderFrameImpl(const bool renderGUI, const bool renderLogger)
}
else
{
// We don't need to clear the color attachment of the framebuffer as the sky
// is going to be rendered anyway.
m->deviceCommandContext->BeginFramebufferPass(
m->deviceCommandContext->GetDevice()->GetCurrentBackbuffer());
m->deviceCommandContext->GetDevice()->GetCurrentBackbuffer(
Renderer::Backend::AttachmentLoadOp::DONT_CARE,
Renderer::Backend::AttachmentStoreOp::STORE,
Renderer::Backend::AttachmentLoadOp::CLEAR,
Renderer::Backend::AttachmentStoreOp::DONT_CARE));
}
g_Game->GetView()->Render(m->deviceCommandContext.get());
@ -496,18 +502,35 @@ void CRenderer::RenderFrameImpl(const bool renderGUI, const bool renderLogger)
postprocManager.ResolveMultisampleFramebuffer(m->deviceCommandContext.get());
postprocManager.ApplyPostproc(m->deviceCommandContext.get());
postprocManager.ReleaseRenderOutput(m->deviceCommandContext.get());
m->deviceCommandContext->BeginFramebufferPass(
m->deviceCommandContext->GetDevice()->GetCurrentBackbuffer());
Renderer::Backend::IFramebuffer* backbuffer =
m->deviceCommandContext->GetDevice()->GetCurrentBackbuffer(
Renderer::Backend::AttachmentLoadOp::LOAD,
Renderer::Backend::AttachmentStoreOp::STORE,
Renderer::Backend::AttachmentLoadOp::LOAD,
Renderer::Backend::AttachmentStoreOp::DONT_CARE);
postprocManager.ReleaseRenderOutput(
m->deviceCommandContext.get(), backbuffer);
m->deviceCommandContext->BeginFramebufferPass(backbuffer);
}
g_Game->GetView()->RenderOverlays(m->deviceCommandContext.get());
g_Game->GetView()->GetCinema()->Render();
}
else
{
// We have a fullscreen background in our UI so we don't need
// to clear the color attachment.
// We don't need a depth test to render so we don't care about the
// depth-stencil attachment content.
m->deviceCommandContext->BeginFramebufferPass(
m->deviceCommandContext->GetDevice()->GetCurrentBackbuffer());
m->deviceCommandContext->GetDevice()->GetCurrentBackbuffer(
Renderer::Backend::AttachmentLoadOp::DONT_CARE,
Renderer::Backend::AttachmentStoreOp::STORE,
Renderer::Backend::AttachmentLoadOp::DONT_CARE,
Renderer::Backend::AttachmentStoreOp::DONT_CARE));
}
// If we're in Atlas game view, render special tools
@ -516,11 +539,6 @@ void CRenderer::RenderFrameImpl(const bool renderGUI, const bool renderLogger)
g_AtlasGameLoop->view->DrawCinemaPathTool();
}
if (g_Game && g_Game->IsGameStarted())
{
g_Game->GetView()->GetCinema()->Render();
}
RenderFrame2D(renderGUI, renderLogger);
m->deviceCommandContext->EndFramebufferPass();

View File

@ -589,7 +589,6 @@ void CSceneRenderer::RenderReflections(
deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc());
deviceCommandContext->BeginFramebufferPass(wm.m_ReflectionFramebuffer.get());
deviceCommandContext->ClearFramebuffer();
CShaderDefines reflectionsContext = context;
reflectionsContext.Add(str_PASS_REFLECTIONS, str_1);
@ -665,7 +664,6 @@ void CSceneRenderer::RenderRefractions(
deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc());
deviceCommandContext->BeginFramebufferPass(wm.m_RefractionFramebuffer.get());
deviceCommandContext->ClearFramebuffer();
// Render terrain and models
RenderPatches(deviceCommandContext, context, CULL_REFRACTIONS);
@ -841,13 +839,6 @@ void CSceneRenderer::RenderSubmissions(
constexpr int cullGroup = CULL_DEFAULT;
{
PROFILE3_GPU("clear buffers");
// We don't need to clear the color attachment of the framebuffer if the sky
// is going to be rendered. Because it covers the whole view.
deviceCommandContext->ClearFramebuffer(!m->skyManager.IsSkyVisible(), true, true);
}
m->skyManager.RenderSky(deviceCommandContext);
// render submitted patches and models

View File

@ -510,7 +510,7 @@ void ShadowMapInternals::CreateTexture()
const char* formatName;
Renderer::Backend::Format backendFormat = Renderer::Backend::Format::UNDEFINED;
#if CONFIG2_GLES
formatName = "DEPTH_COMPONENT";
formatName = "Format::D24";
backendFormat = Renderer::Backend::Format::D24;
#else
switch (DepthTextureBits)
@ -556,9 +556,24 @@ void ShadowMapInternals::CreateTexture()
Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT,
backendFormat, Width, Height, samplerDesc);
Framebuffer = backendDevice->CreateFramebuffer("ShadowMapFramebuffer",
g_RenderingOptions.GetShadowAlphaFix() ? DummyTexture.get() : nullptr, Texture.get());
const bool useDummyTexture = g_RenderingOptions.GetShadowAlphaFix();
// In case we used ShadowAlphaFix, we ought to clear the unused
// color buffer too, else Mali 400 drivers get confused.
// Might as well clear stencil too for completeness.
Renderer::Backend::SColorAttachment colorAttachment{};
colorAttachment.texture = DummyTexture.get();
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR;
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::DONT_CARE;
colorAttachment.clearColor = CColor{0.0f, 0.0f, 0.0f, 0.0f};
Renderer::Backend::SDepthStencilAttachment depthStencilAttachment{};
depthStencilAttachment.texture = Texture.get();
depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR;
depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
Framebuffer = backendDevice->CreateFramebuffer("ShadowMapFramebuffer",
useDummyTexture ? &colorAttachment : nullptr, &depthStencilAttachment);
if (!Framebuffer)
{
LOGERROR("Failed to create shadows framebuffer");
@ -574,20 +589,8 @@ void ShadowMap::BeginRender(
deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc());
{
PROFILE("bind framebuffer");
ENSURE(m->Framebuffer);
deviceCommandContext->BeginFramebufferPass(m->Framebuffer.get());
}
// clear buffers
{
PROFILE("clear depth texture");
// In case we used m_ShadowAlphaFix, we ought to clear the unused
// color buffer too, else Mali 400 drivers get confused.
// Might as well clear stencil too for completeness.
deviceCommandContext->ClearFramebuffer();
}
ENSURE(m->Framebuffer);
deviceCommandContext->BeginFramebufferPass(m->Framebuffer.get());
m->SavedViewCamera = g_Renderer.GetSceneRenderer().GetViewCamera();
}

View File

@ -212,12 +212,10 @@ void SkyManager::RenderSky(
{
GPU_SCOPED_LABEL(deviceCommandContext, "Render sky");
if (!m_SkyVisible)
return;
// Do nothing unless SetSkySet was called
if (m_SkySet.empty() || !m_SkyTextureCube)
return;
const CTexturePtr& skyTextureCube =
!m_SkyVisible || m_SkySet.empty() || !m_SkyTextureCube
? g_Renderer.GetTextureManager().GetBlackTextureCube()
: m_SkyTextureCube;
const CCamera& camera = g_Renderer.GetSceneRenderer().GetViewCamera();
@ -228,7 +226,7 @@ void SkyManager::RenderSky(
deviceCommandContext->BeginPass();
Renderer::Backend::IShaderProgram* shader = skytech->GetShader();
deviceCommandContext->SetTexture(
shader->GetBindingSlot(str_baseTex), m_SkyTextureCube->GetBackendTexture());
shader->GetBindingSlot(str_baseTex), skyTextureCube->GetBackendTexture());
// Translate so the sky center is at the camera space origin.
CMatrix3D translate;

View File

@ -218,13 +218,24 @@ void WaterManager::RecreateOrLoadTexturesIfNeeded()
m_ReflFboDepthTexture = backendDevice->CreateTexture2D("WaterReflectionDepthTexture",
Renderer::Backend::ITexture::Usage::SAMPLED |
Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT,
Renderer::Backend::Format::D32, m_RefTextureSize, m_RefTextureSize,
Renderer::Backend::Format::D24, m_RefTextureSize, m_RefTextureSize,
Renderer::Backend::Sampler::MakeDefaultSampler(
Renderer::Backend::Sampler::Filter::NEAREST,
Renderer::Backend::Sampler::AddressMode::REPEAT));
Renderer::Backend::SColorAttachment colorAttachment{};
colorAttachment.texture = m_ReflectionTexture.get();
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR;
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
colorAttachment.clearColor = CColor{0.5f, 0.5f, 1.0f, 0.0f};
Renderer::Backend::SDepthStencilAttachment depthStencilAttachment{};
depthStencilAttachment.texture = m_ReflFboDepthTexture.get();
depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR;
depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
m_ReflectionFramebuffer = backendDevice->CreateFramebuffer("ReflectionFramebuffer",
m_ReflectionTexture.get(), m_ReflFboDepthTexture.get(), CColor(0.5f, 0.5f, 1.0f, 0.0f));
&colorAttachment, &depthStencilAttachment);
if (!m_ReflectionFramebuffer)
{
g_RenderingOptions.SetWaterReflection(false);
@ -249,13 +260,24 @@ void WaterManager::RecreateOrLoadTexturesIfNeeded()
m_RefrFboDepthTexture = backendDevice->CreateTexture2D("WaterRefractionDepthTexture",
Renderer::Backend::ITexture::Usage::SAMPLED |
Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT,
Renderer::Backend::Format::D32, m_RefTextureSize, m_RefTextureSize,
Renderer::Backend::Format::D24, m_RefTextureSize, m_RefTextureSize,
Renderer::Backend::Sampler::MakeDefaultSampler(
Renderer::Backend::Sampler::Filter::NEAREST,
Renderer::Backend::Sampler::AddressMode::REPEAT));
Renderer::Backend::SColorAttachment colorAttachment{};
colorAttachment.texture = m_RefractionTexture.get();
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR;
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
colorAttachment.clearColor = CColor{1.0f, 0.0f, 0.0f, 0.0f};
Renderer::Backend::SDepthStencilAttachment depthStencilAttachment{};
depthStencilAttachment.texture = m_RefrFboDepthTexture.get();
depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR;
depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
m_RefractionFramebuffer = backendDevice->CreateFramebuffer("RefractionFramebuffer",
m_RefractionTexture.get(), m_RefrFboDepthTexture.get(), CColor(1.0f, 0.0f, 0.0f, 0.0f));
&colorAttachment, &depthStencilAttachment);
if (!m_RefractionFramebuffer)
{
g_RenderingOptions.SetWaterRefraction(false);
@ -288,13 +310,24 @@ void WaterManager::RecreateOrLoadTexturesIfNeeded()
m_FancyTextureDepth = backendDevice->CreateTexture2D("WaterFancyDepthTexture",
Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT,
Renderer::Backend::Format::D32, g_Renderer.GetWidth(), g_Renderer.GetHeight(),
Renderer::Backend::Format::D24, g_Renderer.GetWidth(), g_Renderer.GetHeight(),
Renderer::Backend::Sampler::MakeDefaultSampler(
Renderer::Backend::Sampler::Filter::LINEAR,
Renderer::Backend::Sampler::AddressMode::REPEAT));
Renderer::Backend::SColorAttachment colorAttachment{};
colorAttachment.texture = m_FancyTexture.get();
colorAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR;
colorAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::STORE;
colorAttachment.clearColor = CColor{0.0f, 0.0f, 0.0f, 0.0f};
Renderer::Backend::SDepthStencilAttachment depthStencilAttachment{};
depthStencilAttachment.texture = m_FancyTextureDepth.get();
depthStencilAttachment.loadOp = Renderer::Backend::AttachmentLoadOp::CLEAR;
depthStencilAttachment.storeOp = Renderer::Backend::AttachmentStoreOp::DONT_CARE;
m_FancyEffectsFramebuffer = backendDevice->CreateFramebuffer("FancyEffectsFramebuffer",
m_FancyTexture.get(), m_FancyTextureDepth.get());
&colorAttachment, &depthStencilAttachment);
if (!m_FancyEffectsFramebuffer)
{
g_RenderingOptions.SetWaterRefraction(false);
@ -810,7 +843,6 @@ void WaterManager::RenderWaves(
deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc());
deviceCommandContext->BeginFramebufferPass(m_FancyEffectsFramebuffer.get());
deviceCommandContext->ClearFramebuffer();
CShaderTechniquePtr tech = g_Renderer.GetShaderManager().LoadEffect(str_water_waves);
deviceCommandContext->SetGraphicsPipelineState(

View File

@ -72,8 +72,6 @@ public:
virtual void Report(const ScriptRequest& rq, JS::HandleValue settings) = 0;
virtual IFramebuffer* GetCurrentBackbuffer() = 0;
virtual std::unique_ptr<IDeviceCommandContext> CreateCommandContext() = 0;
virtual std::unique_ptr<ITexture> CreateTexture(
@ -86,13 +84,19 @@ public:
const Format format, const uint32_t width, const uint32_t height,
const Sampler::Desc& defaultSamplerDesc, const uint32_t MIPLevelCount = 1, const uint32_t sampleCount = 1) = 0;
/**
* @see IFramebuffer
*
* The color attachment and the depth-stencil attachment should not be
* nullptr at the same time. There should not be many different clear
* colors along all color attachments for all framebuffers created for
* the device.
*
* @return A valid framebuffer if it was created successfully else nullptr.
*/
virtual std::unique_ptr<IFramebuffer> CreateFramebuffer(
const char* name, ITexture* colorAttachment,
ITexture* depthStencilAttachment) = 0;
virtual std::unique_ptr<IFramebuffer> CreateFramebuffer(
const char* name, ITexture* colorAttachment,
ITexture* depthStencilAttachment, const CColor& clearColor) = 0;
const char* name, SColorAttachment* colorAttachment,
SDepthStencilAttachment* depthStencilAttachment) = 0;
virtual std::unique_ptr<IBuffer> CreateBuffer(
const char* name, const IBuffer::Type type, const uint32_t size, const bool dynamic) = 0;
@ -100,7 +104,36 @@ public:
virtual std::unique_ptr<IShaderProgram> CreateShaderProgram(
const CStr& name, const CShaderDefines& defines) = 0;
/**
* Acquires a backbuffer for rendering a frame.
*
* @return True if it was successfully acquired and we can render to it.
*/
virtual bool AcquireNextBackbuffer() = 0;
/**
* Returns a framebuffer for the current backbuffer with the required
* attachment operations. It should not be called if the last
* AcquireNextBackbuffer call returned false.
*
* It's guaranteed that for the same acquired backbuffer this function returns
* a framebuffer with the same attachments and properties except load and
* store operations.
*
* @return The last successfully acquired framebuffer that wasn't
* presented.
*/
virtual IFramebuffer* GetCurrentBackbuffer(
const AttachmentLoadOp colorAttachmentLoadOp,
const AttachmentStoreOp colorAttachmentStoreOp,
const AttachmentLoadOp depthStencilAttachmentLoadOp,
const AttachmentStoreOp depthStencilAttachmentStoreOp) = 0;
/**
* Presents the backbuffer to the swapchain queue to be flipped on a
* screen. Should be called only if the last AcquireNextBackbuffer call
* returned true.
*/
virtual void Present() = 0;
virtual bool IsTextureFormatSupported(const Format format) const = 0;

View File

@ -45,10 +45,25 @@ public:
virtual void BlitFramebuffer(
IFramebuffer* destinationFramebuffer, IFramebuffer* sourceFramebuffer) = 0;
virtual void ClearFramebuffer() = 0;
virtual void ClearFramebuffer(const bool color, const bool depth, const bool stencil) = 0;
/**
* Starts a framebuffer pass, performs attachment load operations.
* It should be called as rarely as possible.
*
* @see IFramebuffer
*/
virtual void BeginFramebufferPass(IFramebuffer* framebuffer) = 0;
/**
* Finishes a framebuffer pass, performs attachment store operations.
*/
virtual void EndFramebufferPass() = 0;
/**
* Clears all mentioned attachments. Prefer to use attachment load operations over
* this function. It should be called only inside a framebuffer pass.
*/
virtual void ClearFramebuffer(const bool color, const bool depth, const bool stencil) = 0;
virtual void ReadbackFramebufferSync(
const uint32_t x, const uint32_t y, const uint32_t width, const uint32_t height,
void* data) = 0;

View File

@ -27,9 +27,67 @@ namespace Renderer
namespace Backend
{
class ITexture;
/**
* Load operation is set for each attachment, what should be done with its
* content on BeginFramebufferPass.
*/
enum class AttachmentLoadOp
{
// Loads the attachment content.
LOAD,
// Clears the attachment content without loading. Prefer to use that
// operation over manual ClearFramebuffer.
CLEAR,
// After BeginFramebufferPass the attachment content is undefined.
DONT_CARE
};
/**
* Store operation is set for each attachment, what should be done with its
* content on EndFramebufferPass.
*/
enum class AttachmentStoreOp
{
// Stores the attachment content.
STORE,
// After EndFramebufferPass the attachment content is undefined.
DONT_CARE
};
struct SColorAttachment
{
ITexture* texture = nullptr;
AttachmentLoadOp loadOp = AttachmentLoadOp::DONT_CARE;
AttachmentStoreOp storeOp = AttachmentStoreOp::DONT_CARE;
CColor clearColor;
};
struct SDepthStencilAttachment
{
ITexture* texture = nullptr;
AttachmentLoadOp loadOp = AttachmentLoadOp::DONT_CARE;
AttachmentStoreOp storeOp = AttachmentStoreOp::DONT_CARE;
};
/**
* IFramebuffer stores attachments which should be used by backend as rendering
* destinations. That combining allows to set these destinations at once.
* IFramebuffer doesn't own its attachments so clients must keep them alive.
* The number of framebuffers ever created for a device during its lifetime
* should be as small as possible.
*
* Framebuffer is a term from OpenGL/Vulkan worlds (D3D synonym is a render
* target).
*/
class IFramebuffer : public IDeviceObject<IFramebuffer>
{
public:
/**
* Returns a clear color for all color attachments of the framebuffer.
* @see IDevice::CreateFramebuffer()
*/
virtual const CColor& GetClearColor() const = 0;
};

View File

@ -91,13 +91,7 @@ std::unique_ptr<ITexture> CDevice::CreateTexture2D(
}
std::unique_ptr<IFramebuffer> CDevice::CreateFramebuffer(
const char*, ITexture*, ITexture*)
{
return CFramebuffer::Create(this);
}
std::unique_ptr<IFramebuffer> CDevice::CreateFramebuffer(
const char*, ITexture*, ITexture*, const CColor&)
const char*, SColorAttachment*, SDepthStencilAttachment*)
{
return CFramebuffer::Create(this);
}
@ -120,6 +114,13 @@ bool CDevice::AcquireNextBackbuffer()
return true;
}
IFramebuffer* CDevice::GetCurrentBackbuffer(
const AttachmentLoadOp, const AttachmentStoreOp,
const AttachmentLoadOp, const AttachmentStoreOp)
{
return m_Backbuffer.get();
}
void CDevice::Present()
{
// We have nothing to present.

View File

@ -49,8 +49,6 @@ public:
void Report(const ScriptRequest& rq, JS::HandleValue settings) override;
IFramebuffer* GetCurrentBackbuffer() override { return m_Backbuffer.get(); }
std::unique_ptr<IDeviceCommandContext> CreateCommandContext() override;
std::unique_ptr<ITexture> CreateTexture(
@ -64,12 +62,8 @@ public:
const Sampler::Desc& defaultSamplerDesc, const uint32_t MIPLevelCount = 1, const uint32_t sampleCount = 1) override;
std::unique_ptr<IFramebuffer> CreateFramebuffer(
const char* name, ITexture* colorAttachment,
ITexture* depthStencilAttachment) override;
std::unique_ptr<IFramebuffer> CreateFramebuffer(
const char* name, ITexture* colorAttachment,
ITexture* depthStencilAttachment, const CColor& clearColor) override;
const char* name, SColorAttachment* colorAttachment,
SDepthStencilAttachment* depthStencilAttachment) override;
std::unique_ptr<IBuffer> CreateBuffer(
const char* name, const IBuffer::Type type, const uint32_t size, const bool dynamic) override;
@ -78,6 +72,11 @@ public:
const CStr& name, const CShaderDefines& defines) override;
bool AcquireNextBackbuffer() override;
IFramebuffer* GetCurrentBackbuffer(
const AttachmentLoadOp, const AttachmentStoreOp,
const AttachmentLoadOp, const AttachmentStoreOp) override;
void Present() override;
bool IsTextureFormatSupported(const Format format) const override;

View File

@ -103,10 +103,6 @@ void CDeviceCommandContext::BlitFramebuffer(IFramebuffer*, IFramebuffer*)
{
}
void CDeviceCommandContext::ClearFramebuffer()
{
}
void CDeviceCommandContext::ClearFramebuffer(const bool, const bool, const bool)
{
}

View File

@ -50,7 +50,6 @@ public:
void BlitFramebuffer(IFramebuffer* destinationFramebuffer, IFramebuffer* sourceFramebuffer) override;
void ClearFramebuffer() override;
void ClearFramebuffer(const bool color, const bool depth, const bool stencil) override;
void BeginFramebufferPass(IFramebuffer* framebuffer) override;
void EndFramebufferPass() override;

View File

@ -20,6 +20,7 @@
#include "Device.h"
#include "lib/external_libraries/libsdl.h"
#include "lib/hash.h"
#include "lib/ogl.h"
#include "ps/CLogger.h"
#include "ps/ConfigDB.h"
@ -358,7 +359,11 @@ std::unique_ptr<IDevice> CDevice::Create(SDL_Window* window, const bool arb)
#endif
}
device->m_Backbuffer = CFramebuffer::CreateBackbuffer(device.get());
#if CONFIG2_GLES
device->m_UseFramebufferInvalidating = ogl_HaveExtension("GL_EXT_discard_framebuffer");
#else
device->m_UseFramebufferInvalidating = !arb && ogl_HaveExtension("GL_ARB_invalidate_subdata");
#endif
Capabilities& capabilities = device->m_Capabilities;
capabilities.ARBShaders = !ogl_HaveExtensions(0, "GL_ARB_vertex_program", "GL_ARB_fragment_program", nullptr);
@ -880,18 +885,11 @@ std::unique_ptr<ITexture> CDevice::CreateTexture2D(
}
std::unique_ptr<IFramebuffer> CDevice::CreateFramebuffer(
const char* name, ITexture* colorAttachment,
ITexture* depthStencilAttachment)
{
return CreateFramebuffer(name, colorAttachment, depthStencilAttachment, CColor(0.0f, 0.0f, 0.0f, 0.0f));
}
std::unique_ptr<IFramebuffer> CDevice::CreateFramebuffer(
const char* name, ITexture* colorAttachment,
ITexture* depthStencilAttachment, const CColor& clearColor)
const char* name, SColorAttachment* colorAttachment,
SDepthStencilAttachment* depthStencilAttachment)
{
return CFramebuffer::Create(
this, name, colorAttachment->As<CTexture>(), depthStencilAttachment->As<CTexture>(), clearColor);
this, name, colorAttachment, depthStencilAttachment);
}
std::unique_ptr<IBuffer> CDevice::CreateBuffer(
@ -913,6 +911,35 @@ bool CDevice::AcquireNextBackbuffer()
return true;
}
size_t CDevice::BackbufferKeyHash::operator()(const BackbufferKey& key) const
{
size_t seed = 0;
hash_combine(seed, std::get<0>(key));
hash_combine(seed, std::get<1>(key));
hash_combine(seed, std::get<2>(key));
hash_combine(seed, std::get<3>(key));
return seed;
}
IFramebuffer* CDevice::GetCurrentBackbuffer(
const AttachmentLoadOp colorAttachmentLoadOp,
const AttachmentStoreOp colorAttachmentStoreOp,
const AttachmentLoadOp depthStencilAttachmentLoadOp,
const AttachmentStoreOp depthStencilAttachmentStoreOp)
{
const BackbufferKey key{
colorAttachmentLoadOp, colorAttachmentStoreOp,
depthStencilAttachmentLoadOp, depthStencilAttachmentStoreOp};
auto it = m_Backbuffers.find(key);
if (it == m_Backbuffers.end())
{
it = m_Backbuffers.emplace(key, CFramebuffer::CreateBackbuffer(
this, colorAttachmentLoadOp, colorAttachmentStoreOp,
depthStencilAttachmentLoadOp, depthStencilAttachmentStoreOp)).first;
}
return it->second.get();
}
void CDevice::Present()
{
ENSURE(m_BackbufferAcquired);

View File

@ -29,6 +29,8 @@
#include <memory>
#include <string>
#include <tuple>
#include <unordered_map>
#include <vector>
typedef struct SDL_Window SDL_Window;
@ -64,8 +66,6 @@ public:
void Report(const ScriptRequest& rq, JS::HandleValue settings) override;
IFramebuffer* GetCurrentBackbuffer() override { return m_Backbuffer.get(); }
std::unique_ptr<IDeviceCommandContext> CreateCommandContext() override;
CDeviceCommandContext* GetActiveCommandContext() { return m_ActiveCommandContext; }
@ -81,12 +81,8 @@ public:
const Sampler::Desc& defaultSamplerDesc, const uint32_t MIPLevelCount = 1, const uint32_t sampleCount = 1) override;
std::unique_ptr<IFramebuffer> CreateFramebuffer(
const char* name, ITexture* colorAttachment,
ITexture* depthStencilAttachment) override;
std::unique_ptr<IFramebuffer> CreateFramebuffer(
const char* name, ITexture* colorAttachment,
ITexture* depthStencilAttachment, const CColor& clearColor) override;
const char* name, SColorAttachment* colorAttachment,
SDepthStencilAttachment* depthStencilAttachment) override;
std::unique_ptr<IBuffer> CreateBuffer(
const char* name, const IBuffer::Type type, const uint32_t size, const bool dynamic) override;
@ -95,8 +91,17 @@ public:
const CStr& name, const CShaderDefines& defines) override;
bool AcquireNextBackbuffer() override;
IFramebuffer* GetCurrentBackbuffer(
const AttachmentLoadOp colorAttachmentLoadOp,
const AttachmentStoreOp colorAttachmentStoreOp,
const AttachmentLoadOp depthStencilAttachmentLoadOp,
const AttachmentStoreOp depthStencilAttachmentStoreOp) override;
void Present() override;
bool UseFramebufferInvalidating() const { return m_UseFramebufferInvalidating; }
bool IsTextureFormatSupported(const Format format) const override;
bool IsFramebufferFormatSupported(const Format format) const override;
@ -121,8 +126,20 @@ private:
// it's used only as a helper for transition.
CDeviceCommandContext* m_ActiveCommandContext = nullptr;
std::unique_ptr<CFramebuffer> m_Backbuffer;
using BackbufferKey = std::tuple<
AttachmentLoadOp, AttachmentStoreOp,
AttachmentLoadOp, AttachmentStoreOp>;
struct BackbufferKeyHash
{
size_t operator()(const BackbufferKey& key) const;
};
// We use std::unordered_map to avoid storing sizes of Attachment*Op
// enumerations. If it becomes a performance issue we'll replace it
// by an array.
std::unordered_map<
BackbufferKey, std::unique_ptr<CFramebuffer>, BackbufferKeyHash> m_Backbuffers;
bool m_BackbufferAcquired = false;
bool m_UseFramebufferInvalidating = false;
Capabilities m_Capabilities{};
};

View File

@ -150,13 +150,76 @@ void UploadDynamicBufferRegionImpl(
}
}
/**
* In case we don't need a framebuffer content (because of the following clear
* or overwriting by a shader) we might give a hint to a driver via
* glInvalidateFramebuffer.
*/
void InvalidateFramebuffer(
CFramebuffer* framebuffer, const bool color, const bool depthStencil)
{
GLsizei numberOfAttachments = 0;
GLenum attachments[8];
const bool isBackbuffer = framebuffer->GetHandle() == 0;
if (color && (framebuffer->GetAttachmentMask() & GL_COLOR_BUFFER_BIT))
{
if (isBackbuffer)
#if CONFIG2_GLES
attachments[numberOfAttachments++] = GL_COLOR_EXT;
#else
attachments[numberOfAttachments++] = GL_COLOR;
#endif
else
attachments[numberOfAttachments++] = GL_COLOR_ATTACHMENT0;
}
if (depthStencil)
{
if (isBackbuffer)
{
if (framebuffer->GetAttachmentMask() & GL_DEPTH_BUFFER_BIT)
#if CONFIG2_GLES
attachments[numberOfAttachments++] = GL_DEPTH_EXT;
#else
attachments[numberOfAttachments++] = GL_DEPTH;
#endif
if (framebuffer->GetAttachmentMask() & GL_STENCIL_BUFFER_BIT)
#if CONFIG2_GLES
attachments[numberOfAttachments++] = GL_STENCIL_EXT;
#else
attachments[numberOfAttachments++] = GL_STENCIL;
#endif
}
else
{
if (framebuffer->GetAttachmentMask() & GL_DEPTH_BUFFER_BIT)
attachments[numberOfAttachments++] = GL_DEPTH_ATTACHMENT;
if (framebuffer->GetAttachmentMask() & GL_STENCIL_BUFFER_BIT)
attachments[numberOfAttachments++] = GL_STENCIL_ATTACHMENT;
}
}
if (numberOfAttachments > 0)
{
#if CONFIG2_GLES
glDiscardFramebufferEXT(GL_FRAMEBUFFER_EXT, numberOfAttachments, attachments);
#else
glInvalidateFramebuffer(GL_FRAMEBUFFER_EXT, numberOfAttachments, attachments);
#endif
ogl_WarnIfError();
}
}
} // anonymous namespace
// static
std::unique_ptr<CDeviceCommandContext> CDeviceCommandContext::Create(CDevice* device)
{
std::unique_ptr<CDeviceCommandContext> deviceCommandContext(new CDeviceCommandContext(device));
deviceCommandContext->m_Framebuffer = static_cast<CFramebuffer*>(device->GetCurrentBackbuffer());
deviceCommandContext->m_Framebuffer = device->GetCurrentBackbuffer(
Renderer::Backend::AttachmentLoadOp::DONT_CARE,
Renderer::Backend::AttachmentStoreOp::DONT_CARE,
Renderer::Backend::AttachmentLoadOp::DONT_CARE,
Renderer::Backend::AttachmentStoreOp::DONT_CARE)->As<CFramebuffer>();
deviceCommandContext->ResetStates();
return deviceCommandContext;
}
@ -483,7 +546,11 @@ void CDeviceCommandContext::ResetStates()
{
SetGraphicsPipelineStateImpl(MakeDefaultGraphicsPipelineStateDesc(), true);
SetScissors(0, nullptr);
m_Framebuffer = static_cast<CFramebuffer*>(m_Device->GetCurrentBackbuffer());
m_Framebuffer = m_Device->GetCurrentBackbuffer(
Renderer::Backend::AttachmentLoadOp::DONT_CARE,
Renderer::Backend::AttachmentStoreOp::DONT_CARE,
Renderer::Backend::AttachmentLoadOp::DONT_CARE,
Renderer::Backend::AttachmentStoreOp::DONT_CARE)->As<CFramebuffer>();
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_Framebuffer->GetHandle());
ogl_WarnIfError();
}
@ -761,13 +828,9 @@ void CDeviceCommandContext::BlitFramebuffer(
#endif
}
void CDeviceCommandContext::ClearFramebuffer()
{
ClearFramebuffer(true, true, true);
}
void CDeviceCommandContext::ClearFramebuffer(const bool color, const bool depth, const bool stencil)
{
ENSURE(m_InsideFramebufferPass);
const bool needsColor = color && (m_Framebuffer->GetAttachmentMask() & GL_COLOR_BUFFER_BIT) != 0;
const bool needsDepth = depth && (m_Framebuffer->GetAttachmentMask() & GL_DEPTH_BUFFER_BIT) != 0;
const bool needsStencil = stencil && (m_Framebuffer->GetAttachmentMask() & GL_STENCIL_BUFFER_BIT) != 0;
@ -811,15 +874,46 @@ void CDeviceCommandContext::BeginFramebufferPass(IFramebuffer* framebuffer)
ENSURE(m_Framebuffer->GetHandle() == 0 || (m_Framebuffer->GetWidth() > 0 && m_Framebuffer->GetHeight() > 0));
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_Framebuffer->GetHandle());
ogl_WarnIfError();
if (m_Device->UseFramebufferInvalidating())
{
InvalidateFramebuffer(
m_Framebuffer,
m_Framebuffer->GetColorAttachmentLoadOp() != AttachmentLoadOp::LOAD,
m_Framebuffer->GetDepthStencilAttachmentLoadOp() != AttachmentLoadOp::LOAD);
}
const bool needsClearColor =
m_Framebuffer->GetColorAttachmentLoadOp() == AttachmentLoadOp::CLEAR;
const bool needsClearDepthStencil =
m_Framebuffer->GetDepthStencilAttachmentLoadOp() == AttachmentLoadOp::CLEAR;
if (needsClearColor || needsClearDepthStencil)
{
ClearFramebuffer(
needsClearColor, needsClearDepthStencil, needsClearDepthStencil);
}
}
void CDeviceCommandContext::EndFramebufferPass()
{
if (m_Device->UseFramebufferInvalidating())
{
InvalidateFramebuffer(
m_Framebuffer,
m_Framebuffer->GetColorAttachmentStoreOp() != AttachmentStoreOp::STORE,
m_Framebuffer->GetDepthStencilAttachmentStoreOp() != AttachmentStoreOp::STORE);
}
ENSURE(m_InsideFramebufferPass);
m_InsideFramebufferPass = false;
m_Framebuffer = static_cast<CFramebuffer*>(m_Device->GetCurrentBackbuffer());
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_Framebuffer->GetHandle());
ogl_WarnIfError();
CFramebuffer* framebuffer = m_Device->GetCurrentBackbuffer(
Renderer::Backend::AttachmentLoadOp::DONT_CARE,
Renderer::Backend::AttachmentStoreOp::DONT_CARE,
Renderer::Backend::AttachmentLoadOp::DONT_CARE,
Renderer::Backend::AttachmentStoreOp::DONT_CARE)->As<CFramebuffer>();
if (framebuffer->GetHandle() != m_Framebuffer->GetHandle())
{
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framebuffer->GetHandle());
ogl_WarnIfError();
}
m_Framebuffer = framebuffer;
}
void CDeviceCommandContext::ReadbackFramebufferSync(

View File

@ -57,10 +57,9 @@ public:
void BlitFramebuffer(IFramebuffer* destinationFramebuffer, IFramebuffer* sourceFramebuffer) override;
void ClearFramebuffer() override;
void ClearFramebuffer(const bool color, const bool depth, const bool stencil) override;
void BeginFramebufferPass(IFramebuffer* framebuffer) override;
void EndFramebufferPass() override;
void ClearFramebuffer(const bool color, const bool depth, const bool stencil) override;
void ReadbackFramebufferSync(
const uint32_t x, const uint32_t y, const uint32_t width, const uint32_t height,
void* data) override;

View File

@ -36,15 +36,24 @@ namespace GL
// static
std::unique_ptr<CFramebuffer> CFramebuffer::Create(
CDevice* device, const char* name,
CTexture* colorAttachment, CTexture* depthStencilAttachment,
const CColor& clearColor)
CDevice* device, const char* name, SColorAttachment* colorAttachment,
SDepthStencilAttachment* depthStencilAttachment)
{
ENSURE(colorAttachment || depthStencilAttachment);
std::unique_ptr<CFramebuffer> framebuffer(new CFramebuffer());
framebuffer->m_Device = device;
framebuffer->m_ClearColor = clearColor;
if (colorAttachment)
{
framebuffer->m_ClearColor = colorAttachment->clearColor;
framebuffer->m_ColorAttachmentLoadOp = colorAttachment->loadOp;
framebuffer->m_ColorAttachmentStoreOp = colorAttachment->storeOp;
}
if (depthStencilAttachment)
{
framebuffer->m_DepthStencilAttachmentLoadOp = depthStencilAttachment->loadOp;
framebuffer->m_DepthStencilAttachmentStoreOp = depthStencilAttachment->storeOp;
}
glGenFramebuffersEXT(1, &framebuffer->m_Handle);
if (!framebuffer->m_Handle)
@ -56,59 +65,62 @@ std::unique_ptr<CFramebuffer> CFramebuffer::Create(
if (colorAttachment)
{
ENSURE(device->IsFramebufferFormatSupported(colorAttachment->GetFormat()));
ENSURE(colorAttachment->GetUsage() & Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT);
CTexture* colorAttachmentTexture = colorAttachment->texture->As<CTexture>();
ENSURE(device->IsFramebufferFormatSupported(colorAttachmentTexture->GetFormat()));
ENSURE(colorAttachmentTexture->GetUsage() & Renderer::Backend::ITexture::Usage::COLOR_ATTACHMENT);
framebuffer->m_AttachmentMask |= GL_COLOR_BUFFER_BIT;
#if CONFIG2_GLES
ENSURE(colorAttachment->GetType() == CTexture::Type::TEXTURE_2D);
ENSURE(colorAttachmentTexture->GetType() == CTexture::Type::TEXTURE_2D);
const GLenum textureTarget = GL_TEXTURE_2D;
#else
const GLenum textureTarget = colorAttachment->GetType() == CTexture::Type::TEXTURE_2D_MULTISAMPLE ?
const GLenum textureTarget = colorAttachmentTexture->GetType() == CTexture::Type::TEXTURE_2D_MULTISAMPLE ?
GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
#endif
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
textureTarget, colorAttachment->GetHandle(), 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0,
textureTarget, colorAttachmentTexture->GetHandle(), 0);
}
if (depthStencilAttachment)
{
ENSURE(depthStencilAttachment->GetUsage() & Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT);
CTexture* depthStencilAttachmentTexture = depthStencilAttachment->texture->As<CTexture>();
ENSURE(depthStencilAttachmentTexture->GetUsage() & Renderer::Backend::ITexture::Usage::DEPTH_STENCIL_ATTACHMENT);
framebuffer->m_Width = depthStencilAttachment->GetWidth();
framebuffer->m_Height = depthStencilAttachment->GetHeight();
framebuffer->m_Width = depthStencilAttachmentTexture->GetWidth();
framebuffer->m_Height = depthStencilAttachmentTexture->GetHeight();
framebuffer->m_AttachmentMask |= GL_DEPTH_BUFFER_BIT;
if (depthStencilAttachment->GetFormat() == Format::D24_S8)
if (depthStencilAttachmentTexture->GetFormat() == Format::D24_S8)
framebuffer->m_AttachmentMask |= GL_STENCIL_BUFFER_BIT;
if (colorAttachment)
{
ENSURE(colorAttachment->GetWidth() == depthStencilAttachment->GetWidth());
ENSURE(colorAttachment->GetHeight() == depthStencilAttachment->GetHeight());
ENSURE(colorAttachment->GetType() == depthStencilAttachment->GetType());
ENSURE(colorAttachment->texture->GetWidth() == depthStencilAttachmentTexture->GetWidth());
ENSURE(colorAttachment->texture->GetHeight() == depthStencilAttachmentTexture->GetHeight());
ENSURE(colorAttachment->texture->GetType() == depthStencilAttachmentTexture->GetType());
}
ENSURE(
depthStencilAttachment->GetFormat() == Format::D16 ||
depthStencilAttachment->GetFormat() == Format::D24 ||
depthStencilAttachment->GetFormat() == Format::D32 ||
depthStencilAttachment->GetFormat() == Format::D24_S8);
depthStencilAttachmentTexture->GetFormat() == Format::D16 ||
depthStencilAttachmentTexture->GetFormat() == Format::D24 ||
depthStencilAttachmentTexture->GetFormat() == Format::D32 ||
depthStencilAttachmentTexture->GetFormat() == Format::D24_S8);
#if CONFIG2_GLES
ENSURE(depthStencilAttachment->GetFormat() != Format::D24_S8);
ENSURE(depthStencilAttachmentTexture->GetFormat() != Format::D24_S8);
const GLenum attachment = GL_DEPTH_ATTACHMENT;
ENSURE(depthStencilAttachment->GetType() == CTexture::Type::TEXTURE_2D);
ENSURE(depthStencilAttachmentTexture->GetType() == CTexture::Type::TEXTURE_2D);
const GLenum textureTarget = GL_TEXTURE_2D;
#else
const GLenum attachment = depthStencilAttachment->GetFormat() == Format::D24_S8 ?
const GLenum attachment = depthStencilAttachmentTexture->GetFormat() == Format::D24_S8 ?
GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT;
const GLenum textureTarget = depthStencilAttachment->GetType() == CTexture::Type::TEXTURE_2D_MULTISAMPLE ?
const GLenum textureTarget = depthStencilAttachmentTexture->GetType() == CTexture::Type::TEXTURE_2D_MULTISAMPLE ?
GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
#endif
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attachment,
textureTarget, depthStencilAttachment->GetHandle(), 0);
textureTarget, depthStencilAttachmentTexture->GetHandle(), 0);
}
else
{
framebuffer->m_Width = colorAttachment->GetWidth();
framebuffer->m_Height = colorAttachment->GetHeight();
framebuffer->m_Width = colorAttachment->texture->GetWidth();
framebuffer->m_Height = colorAttachment->texture->GetHeight();
}
ogl_WarnIfError();
@ -120,7 +132,7 @@ std::unique_ptr<CFramebuffer> CFramebuffer::Create(
glDrawBuffer(GL_NONE);
}
else
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glDrawBuffer(GL_COLOR_ATTACHMENT0);
#endif
ogl_WarnIfError();
@ -151,13 +163,21 @@ std::unique_ptr<CFramebuffer> CFramebuffer::Create(
// static
std::unique_ptr<CFramebuffer> CFramebuffer::CreateBackbuffer(
CDevice* device)
CDevice* device,
const AttachmentLoadOp colorAttachmentLoadOp,
const AttachmentStoreOp colorAttachmentStoreOp,
const AttachmentLoadOp depthStencilAttachmentLoadOp,
const AttachmentStoreOp depthStencilAttachmentStoreOp)
{
// Backbuffer for GL is a special case with a zero framebuffer.
std::unique_ptr<CFramebuffer> framebuffer(new CFramebuffer());
framebuffer->m_Device = device;
framebuffer->m_AttachmentMask = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
framebuffer->m_ClearColor = CColor(0.0f, 0.0f, 0.0f, 0.0f);
framebuffer->m_ColorAttachmentLoadOp = colorAttachmentLoadOp;
framebuffer->m_ColorAttachmentStoreOp = colorAttachmentStoreOp;
framebuffer->m_DepthStencilAttachmentLoadOp = depthStencilAttachmentLoadOp;
framebuffer->m_DepthStencilAttachmentStoreOp = depthStencilAttachmentStoreOp;
return framebuffer;
}

View File

@ -49,6 +49,11 @@ public:
GLuint GetHandle() const { return m_Handle; }
GLbitfield GetAttachmentMask() const { return m_AttachmentMask; }
AttachmentLoadOp GetColorAttachmentLoadOp() const { return m_ColorAttachmentLoadOp; }
AttachmentStoreOp GetColorAttachmentStoreOp() const { return m_ColorAttachmentStoreOp; }
AttachmentLoadOp GetDepthStencilAttachmentLoadOp() const { return m_DepthStencilAttachmentLoadOp; }
AttachmentStoreOp GetDepthStencilAttachmentStoreOp() const { return m_DepthStencilAttachmentStoreOp; }
uint32_t GetWidth() const { return m_Width; }
uint32_t GetHeight() const { return m_Height; }
@ -56,17 +61,29 @@ private:
friend class CDevice;
static std::unique_ptr<CFramebuffer> Create(
CDevice* device, const char* name,
CTexture* colorAttachment, CTexture* depthStencilAttachment, const CColor& clearColor);
static std::unique_ptr<CFramebuffer> CreateBackbuffer(CDevice* device);
CDevice* device, const char* name, SColorAttachment* colorAttachment,
SDepthStencilAttachment* depthStencilAttachment);
static std::unique_ptr<CFramebuffer> CreateBackbuffer(
CDevice* device,
const AttachmentLoadOp colorAttachmentLoadOp,
const AttachmentStoreOp colorAttachmentStoreOp,
const AttachmentLoadOp depthStencilAttachmentLoadOp,
const AttachmentStoreOp depthStencilAttachmentStoreOp);
CFramebuffer();
CDevice* m_Device = nullptr;
GLuint m_Handle = 0;
uint32_t m_Width = 0, m_Height = 0;
GLbitfield m_AttachmentMask = 0;
CColor m_ClearColor;
AttachmentLoadOp m_ColorAttachmentLoadOp = AttachmentLoadOp::DONT_CARE;
AttachmentStoreOp m_ColorAttachmentStoreOp = AttachmentStoreOp::DONT_CARE;
AttachmentLoadOp m_DepthStencilAttachmentLoadOp = AttachmentLoadOp::DONT_CARE;
AttachmentStoreOp m_DepthStencilAttachmentStoreOp = AttachmentStoreOp::DONT_CARE;
};
} // namespace GL

View File

@ -74,11 +74,6 @@ void CDevice::Report(const ScriptRequest& rq, JS::HandleValue settings)
Script::SetProperty(rq, settings, "status", vulkanSupport);
}
IFramebuffer* CDevice::GetCurrentBackbuffer()
{
return nullptr;
}
std::unique_ptr<IDeviceCommandContext> CDevice::CreateCommandContext()
{
return nullptr;
@ -112,8 +107,8 @@ std::unique_ptr<ITexture> CDevice::CreateTexture2D(
}
std::unique_ptr<IFramebuffer> CDevice::CreateFramebuffer(
const char* name, ITexture* colorAttachment,
ITexture* depthStencilAttachment)
const char* name, SColorAttachment* colorAttachment,
SDepthStencilAttachment* depthStencilAttachment)
{
UNUSED2(name);
UNUSED2(colorAttachment);
@ -121,17 +116,6 @@ std::unique_ptr<IFramebuffer> CDevice::CreateFramebuffer(
return nullptr;
}
std::unique_ptr<IFramebuffer> CDevice::CreateFramebuffer(
const char* name, ITexture* colorAttachment,
ITexture* depthStencilAttachment, const CColor& clearColor)
{
UNUSED2(name);
UNUSED2(colorAttachment);
UNUSED2(depthStencilAttachment);
UNUSED2(clearColor);
return nullptr;
}
std::unique_ptr<IBuffer> CDevice::CreateBuffer(
const char* name, const IBuffer::Type type, const uint32_t size, const bool dynamic)
{
@ -155,6 +139,19 @@ bool CDevice::AcquireNextBackbuffer()
return false;
}
IFramebuffer* CDevice::GetCurrentBackbuffer(
const AttachmentLoadOp colorAttachmentLoadOp,
const AttachmentStoreOp colorAttachmentStoreOp,
const AttachmentLoadOp depthStencilAttachmentLoadOp,
const AttachmentStoreOp depthStencilAttachmentStoreOp)
{
UNUSED2(colorAttachmentLoadOp);
UNUSED2(colorAttachmentStoreOp);
UNUSED2(depthStencilAttachmentLoadOp);
UNUSED2(depthStencilAttachmentStoreOp);
return nullptr;
}
void CDevice::Present()
{
}

View File

@ -54,8 +54,6 @@ public:
void Report(const ScriptRequest& rq, JS::HandleValue settings) override;
IFramebuffer* GetCurrentBackbuffer() override;
std::unique_ptr<IDeviceCommandContext> CreateCommandContext() override;
std::unique_ptr<ITexture> CreateTexture(
@ -69,12 +67,8 @@ public:
const Sampler::Desc& defaultSamplerDesc, const uint32_t MIPLevelCount = 1, const uint32_t sampleCount = 1) override;
std::unique_ptr<IFramebuffer> CreateFramebuffer(
const char* name, ITexture* colorAttachment,
ITexture* depthStencilAttachment) override;
std::unique_ptr<IFramebuffer> CreateFramebuffer(
const char* name, ITexture* colorAttachment,
ITexture* depthStencilAttachment, const CColor& clearColor) override;
const char* name, SColorAttachment* colorAttachment,
SDepthStencilAttachment* depthStencilAttachment) override;
std::unique_ptr<IBuffer> CreateBuffer(
const char* name, const IBuffer::Type type, const uint32_t size, const bool dynamic) override;
@ -83,6 +77,13 @@ public:
const CStr& name, const CShaderDefines& defines) override;
bool AcquireNextBackbuffer() override;
IFramebuffer* GetCurrentBackbuffer(
const AttachmentLoadOp colorAttachmentLoadOp,
const AttachmentStoreOp colorAttachmentStoreOp,
const AttachmentLoadOp depthStencilAttachmentLoadOp,
const AttachmentStoreOp depthStencilAttachmentStoreOp) override;
void Present() override;
bool IsTextureFormatSupported(const Format format) const override;

View File

@ -540,7 +540,11 @@ void ActorViewer::Render()
sceneRenderer.PrepareScene(deviceCommandContext, m);
deviceCommandContext->BeginFramebufferPass(
deviceCommandContext->GetDevice()->GetCurrentBackbuffer());
deviceCommandContext->GetDevice()->GetCurrentBackbuffer(
Renderer::Backend::AttachmentLoadOp::DONT_CARE,
Renderer::Backend::AttachmentStoreOp::STORE,
Renderer::Backend::AttachmentLoadOp::DONT_CARE,
Renderer::Backend::AttachmentStoreOp::DONT_CARE));
sceneRenderer.RenderScene(deviceCommandContext);
sceneRenderer.RenderSceneOverlays(deviceCommandContext);