summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineOpenGL
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-08-25 01:07:40 +0000
committerazhirnov <zh1dron@gmail.com>2020-08-25 01:30:09 +0000
commit142c7880f92c3517a8897d2601336f6dba319c17 (patch)
tree55fd757db90d80fe2a72b54970e95764f181bbfb /Graphics/GraphicsEngineOpenGL
parentUpdated description of DrawMeshIndirect command (diff)
parentFixed test crash in d3d11 mode on Intel GPU (diff)
downloadDiligentCore-142c7880f92c3517a8897d2601336f6dba319c17.tar.gz
DiligentCore-142c7880f92c3517a8897d2601336f6dba319c17.zip
Merge branch 'master' into mesh_shader
# Conflicts: # Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp # Graphics/GraphicsEngineD3D12/include/CommandContext.hpp # Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.hpp
Diffstat (limited to 'Graphics/GraphicsEngineOpenGL')
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp3
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp11
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp92
3 files changed, 99 insertions, 7 deletions
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp b/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp
index 332fc304..a93528ec 100644
--- a/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp
+++ b/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp
@@ -71,6 +71,8 @@ inline GLenum TypeToGLType(VALUE_TYPE Value)
inline GLenum UsageToGLUsage(const BufferDesc& Desc)
{
+ static_assert(USAGE_NUM_USAGES == 5, "Please update this function to handle the new usage type");
+
// http://www.informit.com/articles/article.aspx?p=2033340&seqNum=2
// https://www.khronos.org/registry/OpenGL-Refpages/gl2.1/xhtml/glBufferData.xml
switch (Desc.Usage)
@@ -82,6 +84,7 @@ inline GLenum UsageToGLUsage(const BufferDesc& Desc)
// clang-format off
case USAGE_STATIC: return GL_STATIC_DRAW;
case USAGE_DEFAULT: return GL_STATIC_DRAW;
+ case USAGE_UNIFIED: return GL_STATIC_DRAW;
case USAGE_DYNAMIC: return GL_DYNAMIC_DRAW;
case USAGE_STAGING:
if(Desc.CPUAccessFlags & CPU_ACCESS_READ)
diff --git a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp
index 70df3725..e05d72ff 100644
--- a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp
@@ -89,8 +89,15 @@ BufferGLImpl::BufferGLImpl(IReferenceCounters* pRefCounters,
m_GLUsageHint {UsageToGLUsage(BuffDesc)}
// clang-format on
{
- if (BuffDesc.Usage == USAGE_STATIC && (pBuffData == nullptr || pBuffData->pData == nullptr))
- LOG_ERROR_AND_THROW("Static buffer must be initialized with data at creation time");
+ ValidateBufferInitData(BuffDesc, pBuffData);
+
+ if (m_Desc.Usage == USAGE_UNIFIED)
+ {
+ DecayUnifiedBuffer();
+ }
+
+ if (m_Desc.Usage == USAGE_STATIC)
+ VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for static buffers");
// TODO: find out if it affects performance if the buffer is originally bound to one target
// and then bound to another (such as first to GL_ARRAY_BUFFER and then to GL_UNIFORM_BUFFER)
diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
index d7a95033..96c93e7a 100644
--- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
@@ -29,6 +29,7 @@
#include <iostream>
#include <fstream>
#include <string>
+#include <array>
#include "SwapChainGL.h"
#include "DeviceContextGLImpl.hpp"
@@ -143,6 +144,11 @@ void DeviceContextGLImpl::SetPipelineState(IPipelineState* pPipelineState)
}
m_ContextState.InvalidateVAO();
}
+
+ // Note that the program may change if a shader is created after the call
+ // (GLProgramResources needs to bind a program to load uniforms), but before
+ // the draw command.
+ m_pPipelineState->CommitProgram(m_ContextState);
}
void DeviceContextGLImpl::TransitionShaderResources(IPipelineState* pPipelineState, IShaderResourceBinding* pShaderResourceBinding)
@@ -498,13 +504,20 @@ void DeviceContextGLImpl::EndSubpass()
const auto& RPDesc = m_pActiveRenderPass->GetDesc();
VERIFY_EXPR(m_SubpassIndex < RPDesc.SubpassCount);
const auto& SubpassDesc = RPDesc.pSubpasses[m_SubpassIndex];
- if (SubpassDesc.pResolveAttachments != nullptr)
- {
- const auto& SubpassFBOs = m_pBoundFramebuffer->GetSubpassFramebuffer(m_SubpassIndex);
- glBindFramebuffer(GL_READ_FRAMEBUFFER, SubpassFBOs.RenderTarget);
- DEV_CHECK_GL_ERROR("Failed to bind subpass render target FBO as read framebuffer");
+ const auto& SubpassFBOs = m_pBoundFramebuffer->GetSubpassFramebuffer(m_SubpassIndex);
+#ifdef DILIGENT_DEBUG
+ {
+ GLint glCurrReadFB = 0;
+ glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &glCurrReadFB);
+ CHECK_GL_ERROR("Failed to get current read framebuffer");
+ GLuint glExpectedReadFB = SubpassFBOs.RenderTarget != 0 ? static_cast<GLuint>(SubpassFBOs.RenderTarget) : m_pSwapChain->GetDefaultFBO();
+ VERIFY(static_cast<GLuint>(glCurrReadFB) == glExpectedReadFB, "Unexpected read framebuffer");
+ }
+#endif
+ if (SubpassDesc.pResolveAttachments != nullptr)
+ {
GLuint ResolveDstFBO = SubpassFBOs.Resolve;
if (ResolveDstFBO == 0)
{
@@ -521,6 +534,68 @@ void DeviceContextGLImpl::EndSubpass()
);
DEV_CHECK_GL_ERROR("glBlitFramebuffer() failed when resolving multi-sampled attachments");
}
+
+ if (glInvalidateFramebuffer != nullptr)
+ {
+ // It is crucially important to invalidate the framebuffer while it is bound
+ // https://community.arm.com/developer/tools-software/graphics/b/blog/posts/mali-performance-2-how-to-correctly-handle-framebuffers
+ GLsizei InvalidateAttachmentsCount = 0;
+
+ std::array<GLenum, MAX_RENDER_TARGETS + 1> InvalidateAttachments;
+ for (Uint32 rt = 0; rt < SubpassDesc.RenderTargetAttachmentCount; ++rt)
+ {
+ const auto RTAttachmentIdx = SubpassDesc.pRenderTargetAttachments[rt].AttachmentIndex;
+ if (RTAttachmentIdx != ATTACHMENT_UNUSED)
+ {
+ auto AttachmentLastUse = m_pActiveRenderPass->GetAttachmentFirstLastUse(RTAttachmentIdx).second;
+ if (AttachmentLastUse == m_SubpassIndex && RPDesc.pAttachments[RTAttachmentIdx].StoreOp == ATTACHMENT_STORE_OP_DISCARD)
+ {
+ if (SubpassFBOs.RenderTarget == 0)
+ {
+ VERIFY(rt == 0, "Default framebuffer can only have single color attachment");
+ InvalidateAttachments[InvalidateAttachmentsCount++] = GL_COLOR;
+ }
+ else
+ {
+ InvalidateAttachments[InvalidateAttachmentsCount++] = GL_COLOR_ATTACHMENT0 + rt;
+ }
+ }
+ }
+ }
+
+ if (SubpassDesc.pDepthStencilAttachment != nullptr)
+ {
+ const auto DSAttachmentIdx = SubpassDesc.pDepthStencilAttachment->AttachmentIndex;
+ if (DSAttachmentIdx != ATTACHMENT_UNUSED)
+ {
+ auto AttachmentLastUse = m_pActiveRenderPass->GetAttachmentFirstLastUse(DSAttachmentIdx).second;
+ if (AttachmentLastUse == m_SubpassIndex && RPDesc.pAttachments[DSAttachmentIdx].StoreOp == ATTACHMENT_STORE_OP_DISCARD)
+ {
+ const auto& FmtAttribs = GetTextureFormatAttribs(RPDesc.pAttachments[DSAttachmentIdx].Format);
+ VERIFY_EXPR(FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH || FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL);
+ if (SubpassFBOs.RenderTarget == 0)
+ {
+ InvalidateAttachments[InvalidateAttachmentsCount++] = GL_DEPTH;
+ if (FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH_STENCIL)
+ InvalidateAttachments[InvalidateAttachmentsCount++] = GL_STENCIL;
+ }
+ else
+ {
+ InvalidateAttachments[InvalidateAttachmentsCount++] = FmtAttribs.ComponentType == COMPONENT_TYPE_DEPTH ? GL_DEPTH_ATTACHMENT : GL_DEPTH_STENCIL_ATTACHMENT;
+ }
+ }
+ }
+ }
+
+ if (InvalidateAttachmentsCount > 0)
+ {
+ glInvalidateFramebuffer(GL_READ_FRAMEBUFFER, InvalidateAttachmentsCount, InvalidateAttachments.data());
+ DEV_CHECK_GL_ERROR("glInvalidateFramebuffer() failed");
+ }
+ }
+
+ // TODO: invalidate input attachments using glInvalidateTexImage
+
m_ContextState.InvalidateFBO();
}
@@ -544,6 +619,7 @@ void DeviceContextGLImpl::NextSubpass()
EndSubpass();
TDeviceContextBase::NextSubpass();
BeginSubpass();
+ m_AttachmentClearValues.clear();
}
void DeviceContextGLImpl::EndRenderPass()
@@ -810,6 +886,8 @@ void DeviceContextGLImpl::PrepareForDraw(DRAW_FLAGS Flags, bool IsIndexed, GLenu
DvpVerifyRenderTargets();
#endif
+ // The program might have changed since the last SetPipelineState call if a shader was
+ // created after the call (GLProgramResources needs to bind a program to load uniforms).
m_pPipelineState->CommitProgram(m_ContextState);
auto CurrNativeGLContext = m_pDevice->m_GLContext.GetCurrentNativeGLContext();
@@ -1040,6 +1118,8 @@ void DeviceContextGLImpl::DispatchCompute(const DispatchComputeAttribs& Attribs)
return;
#if GL_ARB_compute_shader
+ // The program might have changed since the last SetPipelineState call if a shader was
+ // created after the call (GLProgramResources needs to bind a program to load uniforms).
m_pPipelineState->CommitProgram(m_ContextState);
glDispatchCompute(Attribs.ThreadGroupCountX, Attribs.ThreadGroupCountY, Attribs.ThreadGroupCountZ);
DEV_CHECK_GL_ERROR("glDispatchCompute() failed");
@@ -1056,6 +1136,8 @@ void DeviceContextGLImpl::DispatchComputeIndirect(const DispatchComputeIndirectA
return;
#if GL_ARB_compute_shader
+ // The program might have changed since the last SetPipelineState call if a shader was
+ // created after the call (GLProgramResources needs to bind a program to load uniforms).
m_pPipelineState->CommitProgram(m_ContextState);
auto* pBufferGL = ValidatedCast<BufferGLImpl>(pAttribsBuffer);