OpenGLRenderer/CommandBuffer: Replace std::visit by a switch (to improve performance)
This commit is contained in:
parent
97f1c2c56c
commit
3957687a31
|
|
@ -8,6 +8,7 @@
|
||||||
#define NAZARA_OPENGLRENDERER_OPENGLCOMMANDBUFFER_HPP
|
#define NAZARA_OPENGLRENDERER_OPENGLCOMMANDBUFFER_HPP
|
||||||
|
|
||||||
#include <NazaraUtils/Prerequisites.hpp>
|
#include <NazaraUtils/Prerequisites.hpp>
|
||||||
|
#include <NazaraUtils/TypeList.hpp>
|
||||||
#include <Nazara/Core/Color.hpp>
|
#include <Nazara/Core/Color.hpp>
|
||||||
#include <Nazara/Math/Rect.hpp>
|
#include <Nazara/Math/Rect.hpp>
|
||||||
#include <Nazara/OpenGLRenderer/Config.hpp>
|
#include <Nazara/OpenGLRenderer/Config.hpp>
|
||||||
|
|
@ -79,17 +80,57 @@ namespace Nz
|
||||||
struct DrawStates;
|
struct DrawStates;
|
||||||
struct ShaderBindings;
|
struct ShaderBindings;
|
||||||
|
|
||||||
|
#define NAZARA_OPENGL_FOREACH_COMMANDS(cb, lastCb) \
|
||||||
|
cb(BeginDebugRegionCommand) \
|
||||||
|
cb(BlitTextureCommand) \
|
||||||
|
cb(CopyBufferCommand) \
|
||||||
|
cb(CopyBufferFromMemoryCommand) \
|
||||||
|
cb(CopyTextureCommand) \
|
||||||
|
cb(DispatchCommand) \
|
||||||
|
cb(DrawCommand) \
|
||||||
|
cb(DrawIndexedCommand) \
|
||||||
|
cb(EndDebugRegionCommand) \
|
||||||
|
cb(MemoryBarrier) \
|
||||||
|
lastCb(SetFrameBufferCommand) \
|
||||||
|
|
||||||
|
#define NAZARA_OPENGL_COMMAND_CALLBACK(Command) struct Command;
|
||||||
|
NAZARA_OPENGL_FOREACH_COMMANDS(NAZARA_OPENGL_COMMAND_CALLBACK, NAZARA_OPENGL_COMMAND_CALLBACK)
|
||||||
|
#undef NAZARA_OPENGL_COMMAND_CALLBACK
|
||||||
|
|
||||||
|
using CommandList = TypeList<
|
||||||
|
|
||||||
|
#define NAZARA_OPENGL_COMMAND_CALLBACK(Command) Command,
|
||||||
|
#define NAZARA_OPENGL_COMMAND_CALLBACK_LAST(Command) Command
|
||||||
|
NAZARA_OPENGL_FOREACH_COMMANDS(NAZARA_OPENGL_COMMAND_CALLBACK, NAZARA_OPENGL_COMMAND_CALLBACK_LAST)
|
||||||
|
#undef NAZARA_OPENGL_COMMAND_CALLBACK_LAST
|
||||||
|
#undef NAZARA_OPENGL_COMMAND_CALLBACK
|
||||||
|
|
||||||
|
>;
|
||||||
|
|
||||||
void ApplyBindings(const GL::Context& context, const ShaderBindings& bindings);
|
void ApplyBindings(const GL::Context& context, const ShaderBindings& bindings);
|
||||||
void ApplyStates(const GL::Context& context, const DrawStates& states);
|
void ApplyStates(const GL::Context& context, const DrawStates& states);
|
||||||
|
|
||||||
|
inline void Execute(const GL::Context* context, const BeginDebugRegionCommand& command);
|
||||||
|
inline void Execute(const GL::Context* context, const BlitTextureCommand& command);
|
||||||
|
inline void Execute(const GL::Context* context, const CopyBufferCommand& command);
|
||||||
|
inline void Execute(const GL::Context* context, const CopyBufferFromMemoryCommand& command);
|
||||||
|
inline void Execute(const GL::Context* context, const CopyTextureCommand& command);
|
||||||
|
inline void Execute(const GL::Context* context, const DispatchCommand& command);
|
||||||
|
inline void Execute(const GL::Context* context, const DrawCommand& command);
|
||||||
|
inline void Execute(const GL::Context* context, const DrawIndexedCommand& command);
|
||||||
|
inline void Execute(const GL::Context* context, const EndDebugRegionCommand& command);
|
||||||
|
inline void Execute(const GL::Context* context, const MemoryBarrier& command);
|
||||||
|
inline void Execute(const GL::Context*& context, const SetFrameBufferCommand& command);
|
||||||
|
|
||||||
void Release() override;
|
void Release() override;
|
||||||
|
|
||||||
struct BeginDebugRegionData
|
struct BeginDebugRegionCommand
|
||||||
{
|
{
|
||||||
std::string regionName;
|
std::string regionName;
|
||||||
Color color;
|
Color color;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BlitTextureData
|
struct BlitTextureCommand
|
||||||
{
|
{
|
||||||
const OpenGLTexture* source;
|
const OpenGLTexture* source;
|
||||||
const OpenGLTexture* target;
|
const OpenGLTexture* target;
|
||||||
|
|
@ -103,7 +144,7 @@ namespace Nz
|
||||||
const OpenGLComputePipeline* pipeline = nullptr;
|
const OpenGLComputePipeline* pipeline = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CopyBufferData
|
struct CopyBufferCommand
|
||||||
{
|
{
|
||||||
GLuint source;
|
GLuint source;
|
||||||
GLuint target;
|
GLuint target;
|
||||||
|
|
@ -112,7 +153,7 @@ namespace Nz
|
||||||
UInt64 targetOffset;
|
UInt64 targetOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CopyTextureData
|
struct CopyTextureCommand
|
||||||
{
|
{
|
||||||
const OpenGLTexture* source;
|
const OpenGLTexture* source;
|
||||||
const OpenGLTexture* target;
|
const OpenGLTexture* target;
|
||||||
|
|
@ -120,7 +161,7 @@ namespace Nz
|
||||||
Vector3ui targetPoint;
|
Vector3ui targetPoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CopyBufferFromMemoryData
|
struct CopyBufferFromMemoryCommand
|
||||||
{
|
{
|
||||||
const void* memory;
|
const void* memory;
|
||||||
GLuint target;
|
GLuint target;
|
||||||
|
|
@ -133,7 +174,7 @@ namespace Nz
|
||||||
std::vector<std::pair<const OpenGLRenderPipelineLayout*, const OpenGLShaderBinding*>> shaderBindings;
|
std::vector<std::pair<const OpenGLRenderPipelineLayout*, const OpenGLShaderBinding*>> shaderBindings;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DispatchData
|
struct DispatchCommand
|
||||||
{
|
{
|
||||||
ComputeStates states;
|
ComputeStates states;
|
||||||
ShaderBindings bindings;
|
ShaderBindings bindings;
|
||||||
|
|
@ -160,7 +201,7 @@ namespace Nz
|
||||||
bool shouldFlipY = false;
|
bool shouldFlipY = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DrawData
|
struct DrawCommand
|
||||||
{
|
{
|
||||||
DrawStates states;
|
DrawStates states;
|
||||||
ShaderBindings bindings;
|
ShaderBindings bindings;
|
||||||
|
|
@ -170,7 +211,7 @@ namespace Nz
|
||||||
UInt32 vertexCount;
|
UInt32 vertexCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DrawIndexedData
|
struct DrawIndexedCommand
|
||||||
{
|
{
|
||||||
DrawStates states;
|
DrawStates states;
|
||||||
ShaderBindings bindings;
|
ShaderBindings bindings;
|
||||||
|
|
@ -180,7 +221,7 @@ namespace Nz
|
||||||
UInt32 instanceCount;
|
UInt32 instanceCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EndDebugRegionData
|
struct EndDebugRegionCommand
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -189,26 +230,14 @@ namespace Nz
|
||||||
GLbitfield barriers;
|
GLbitfield barriers;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SetFrameBufferData
|
struct SetFrameBufferCommand
|
||||||
{
|
{
|
||||||
std::array<CommandBufferBuilder::ClearValues, 16> clearValues; //< TODO: Remove hard limit?
|
std::array<CommandBufferBuilder::ClearValues, 16> clearValues; //< TODO: Remove hard limit?
|
||||||
const OpenGLFramebuffer* framebuffer;
|
const OpenGLFramebuffer* framebuffer;
|
||||||
const OpenGLRenderPass* renderpass;
|
const OpenGLRenderPass* renderpass;
|
||||||
};
|
};
|
||||||
|
|
||||||
using CommandData = std::variant<
|
using CommandData = TypeListInstantiate<CommandList, std::variant>;
|
||||||
BeginDebugRegionData,
|
|
||||||
BlitTextureData,
|
|
||||||
CopyBufferData,
|
|
||||||
CopyBufferFromMemoryData,
|
|
||||||
CopyTextureData,
|
|
||||||
DispatchData,
|
|
||||||
DrawData,
|
|
||||||
DrawIndexedData,
|
|
||||||
EndDebugRegionData,
|
|
||||||
MemoryBarrier,
|
|
||||||
SetFrameBufferData
|
|
||||||
>;
|
|
||||||
|
|
||||||
ComputeStates m_currentComputeStates;
|
ComputeStates m_currentComputeStates;
|
||||||
DrawStates m_currentDrawStates;
|
DrawStates m_currentDrawStates;
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ namespace Nz
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::BeginDebugRegion(const std::string_view& regionName, const Color& color)
|
inline void OpenGLCommandBuffer::BeginDebugRegion(const std::string_view& regionName, const Color& color)
|
||||||
{
|
{
|
||||||
BeginDebugRegionData beginDebugRegion;
|
BeginDebugRegionCommand beginDebugRegion;
|
||||||
beginDebugRegion.color = color;
|
beginDebugRegion.color = color;
|
||||||
beginDebugRegion.regionName = regionName;
|
beginDebugRegion.regionName = regionName;
|
||||||
|
|
||||||
|
|
@ -77,7 +77,7 @@ namespace Nz
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::BlitTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Boxui& targetBox, SamplerFilter filter)
|
inline void OpenGLCommandBuffer::BlitTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Boxui& targetBox, SamplerFilter filter)
|
||||||
{
|
{
|
||||||
BlitTextureData blitTexture = {
|
BlitTextureCommand blitTexture = {
|
||||||
&source,
|
&source,
|
||||||
&target,
|
&target,
|
||||||
sourceBox,
|
sourceBox,
|
||||||
|
|
@ -90,7 +90,7 @@ namespace Nz
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::CopyBuffer(GLuint source, GLuint target, UInt64 size, UInt64 sourceOffset, UInt64 targetOffset)
|
inline void OpenGLCommandBuffer::CopyBuffer(GLuint source, GLuint target, UInt64 size, UInt64 sourceOffset, UInt64 targetOffset)
|
||||||
{
|
{
|
||||||
CopyBufferData copyBuffer = {
|
CopyBufferCommand copyBuffer = {
|
||||||
source,
|
source,
|
||||||
target,
|
target,
|
||||||
size,
|
size,
|
||||||
|
|
@ -103,7 +103,7 @@ namespace Nz
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::CopyBuffer(const UploadPool::Allocation& allocation, GLuint target, UInt64 size, UInt64 sourceOffset, UInt64 targetOffset)
|
inline void OpenGLCommandBuffer::CopyBuffer(const UploadPool::Allocation& allocation, GLuint target, UInt64 size, UInt64 sourceOffset, UInt64 targetOffset)
|
||||||
{
|
{
|
||||||
CopyBufferFromMemoryData copyBuffer = {
|
CopyBufferFromMemoryCommand copyBuffer = {
|
||||||
static_cast<const UInt8*>(allocation.mappedPtr) + sourceOffset,
|
static_cast<const UInt8*>(allocation.mappedPtr) + sourceOffset,
|
||||||
target,
|
target,
|
||||||
size,
|
size,
|
||||||
|
|
@ -115,7 +115,7 @@ namespace Nz
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::CopyTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Vector3ui& targetPoint)
|
inline void OpenGLCommandBuffer::CopyTexture(const OpenGLTexture& source, const Boxui& sourceBox, const OpenGLTexture& target, const Vector3ui& targetPoint)
|
||||||
{
|
{
|
||||||
CopyTextureData copyTexture = {
|
CopyTextureCommand copyTexture = {
|
||||||
&source,
|
&source,
|
||||||
&target,
|
&target,
|
||||||
sourceBox,
|
sourceBox,
|
||||||
|
|
@ -130,7 +130,7 @@ namespace Nz
|
||||||
if (!m_currentComputeStates.pipeline)
|
if (!m_currentComputeStates.pipeline)
|
||||||
throw std::runtime_error("no pipeline bound");
|
throw std::runtime_error("no pipeline bound");
|
||||||
|
|
||||||
DispatchData dispatch;
|
DispatchCommand dispatch;
|
||||||
dispatch.bindings = m_currentComputeShaderBindings;
|
dispatch.bindings = m_currentComputeShaderBindings;
|
||||||
dispatch.states = m_currentComputeStates;
|
dispatch.states = m_currentComputeStates;
|
||||||
dispatch.numGroupsX = numGroupsX;
|
dispatch.numGroupsX = numGroupsX;
|
||||||
|
|
@ -145,7 +145,7 @@ namespace Nz
|
||||||
if (!m_currentDrawStates.pipeline)
|
if (!m_currentDrawStates.pipeline)
|
||||||
throw std::runtime_error("no pipeline bound");
|
throw std::runtime_error("no pipeline bound");
|
||||||
|
|
||||||
DrawData draw;
|
DrawCommand draw;
|
||||||
draw.bindings = m_currentGraphicsShaderBindings;
|
draw.bindings = m_currentGraphicsShaderBindings;
|
||||||
draw.states = m_currentDrawStates;
|
draw.states = m_currentDrawStates;
|
||||||
draw.firstInstance = firstInstance;
|
draw.firstInstance = firstInstance;
|
||||||
|
|
@ -161,7 +161,7 @@ namespace Nz
|
||||||
if (!m_currentDrawStates.pipeline)
|
if (!m_currentDrawStates.pipeline)
|
||||||
throw std::runtime_error("no pipeline bound");
|
throw std::runtime_error("no pipeline bound");
|
||||||
|
|
||||||
DrawIndexedData draw;
|
DrawIndexedCommand draw;
|
||||||
draw.bindings = m_currentGraphicsShaderBindings;
|
draw.bindings = m_currentGraphicsShaderBindings;
|
||||||
draw.states = m_currentDrawStates;
|
draw.states = m_currentDrawStates;
|
||||||
draw.firstIndex = firstIndex;
|
draw.firstIndex = firstIndex;
|
||||||
|
|
@ -174,7 +174,7 @@ namespace Nz
|
||||||
|
|
||||||
inline void OpenGLCommandBuffer::EndDebugRegion()
|
inline void OpenGLCommandBuffer::EndDebugRegion()
|
||||||
{
|
{
|
||||||
m_commands.emplace_back(EndDebugRegionData{});
|
m_commands.emplace_back(EndDebugRegionCommand{});
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::size_t OpenGLCommandBuffer::GetBindingIndex() const
|
inline std::size_t OpenGLCommandBuffer::GetBindingIndex() const
|
||||||
|
|
@ -214,7 +214,7 @@ namespace Nz
|
||||||
{
|
{
|
||||||
m_maxColorBufferCount = std::max(m_maxColorBufferCount, framebuffer.GetColorBufferCount());
|
m_maxColorBufferCount = std::max(m_maxColorBufferCount, framebuffer.GetColorBufferCount());
|
||||||
|
|
||||||
SetFrameBufferData setFramebuffer;
|
SetFrameBufferCommand setFramebuffer;
|
||||||
setFramebuffer.framebuffer = &framebuffer;
|
setFramebuffer.framebuffer = &framebuffer;
|
||||||
setFramebuffer.renderpass = &renderPass;
|
setFramebuffer.renderpass = &renderPass;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -62,273 +62,18 @@ namespace Nz
|
||||||
{
|
{
|
||||||
const GL::Context* context = GL::Context::GetCurrentContext();
|
const GL::Context* context = GL::Context::GetCurrentContext();
|
||||||
|
|
||||||
StackArray<std::size_t> colorIndexes = NazaraStackArrayNoInit(std::size_t, m_maxColorBufferCount);
|
|
||||||
|
|
||||||
for (const auto& commandVariant : m_commands)
|
for (const auto& commandVariant : m_commands)
|
||||||
{
|
{
|
||||||
std::visit([&](auto&& command)
|
switch (commandVariant.index())
|
||||||
{
|
{
|
||||||
using T = std::decay_t<decltype(command)>;
|
#define NAZARA_OPENGL_COMMAND_CALLBACK(Command) \
|
||||||
|
case TypeListFind<CommandList, Command>: \
|
||||||
|
Execute(context, std::get<TypeListFind<CommandList, Command>>(commandVariant)); \
|
||||||
|
break;
|
||||||
|
|
||||||
if constexpr (std::is_same_v<T, BeginDebugRegionData>)
|
NAZARA_OPENGL_FOREACH_COMMANDS(NAZARA_OPENGL_COMMAND_CALLBACK, NAZARA_OPENGL_COMMAND_CALLBACK)
|
||||||
{
|
#undef NAZARA_OPENGL_COMMAND_CALLBACK
|
||||||
if (context->glPushDebugGroup)
|
}
|
||||||
context->glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, GLsizei(command.regionName.size()), command.regionName.data());
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, BlitTextureData>)
|
|
||||||
{
|
|
||||||
context->BlitTexture(*command.source, *command.target, command.sourceBox, command.targetBox, command.filter);
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, CopyBufferData>)
|
|
||||||
{
|
|
||||||
context->BindBuffer(GL::BufferTarget::CopyRead, command.source);
|
|
||||||
context->BindBuffer(GL::BufferTarget::CopyWrite, command.target);
|
|
||||||
context->glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, command.sourceOffset, command.targetOffset, command.size);
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, CopyBufferFromMemoryData>)
|
|
||||||
{
|
|
||||||
context->BindBuffer(GL::BufferTarget::CopyWrite, command.target);
|
|
||||||
context->glBufferSubData(GL_COPY_WRITE_BUFFER, command.targetOffset, command.size, command.memory);
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, CopyTextureData>)
|
|
||||||
{
|
|
||||||
context->CopyTexture(*command.source, *command.target, command.sourceBox, command.targetPoint);
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, DispatchData>)
|
|
||||||
{
|
|
||||||
if (!context->glDispatchCompute)
|
|
||||||
throw std::runtime_error("compute shaders are not supported on this device");
|
|
||||||
|
|
||||||
command.states.pipeline->Apply(*context);
|
|
||||||
ApplyBindings(*context, command.bindings);
|
|
||||||
context->glDispatchCompute(command.numGroupsX, command.numGroupsY, command.numGroupsZ);
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, DrawData>)
|
|
||||||
{
|
|
||||||
ApplyStates(*context, command.states);
|
|
||||||
ApplyBindings(*context, command.bindings);
|
|
||||||
context->glDrawArraysInstanced(ToOpenGL(command.states.pipeline->GetPipelineInfo().primitiveMode), command.firstVertex, command.vertexCount, command.instanceCount);
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, DrawIndexedData>)
|
|
||||||
{
|
|
||||||
const UInt8* origin = 0; //< For an easy way to cast an integer to a pointer
|
|
||||||
origin += command.states.indexBufferOffset;
|
|
||||||
|
|
||||||
switch (command.states.indexBufferType)
|
|
||||||
{
|
|
||||||
case IndexType::U8: origin += command.firstIndex * sizeof(UInt8); break;
|
|
||||||
case IndexType::U16: origin += command.firstIndex * sizeof(UInt16); break;
|
|
||||||
case IndexType::U32: origin += command.firstIndex * sizeof(UInt32); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ApplyStates(*context, command.states);
|
|
||||||
ApplyBindings(*context, command.bindings);
|
|
||||||
context->glDrawElementsInstanced(ToOpenGL(command.states.pipeline->GetPipelineInfo().primitiveMode), command.indexCount, ToOpenGL(command.states.indexBufferType), origin, command.instanceCount);
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, EndDebugRegionData>)
|
|
||||||
{
|
|
||||||
if (context->glPopDebugGroup)
|
|
||||||
context->glPopDebugGroup();
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, MemoryBarrier>)
|
|
||||||
{
|
|
||||||
if (context->glMemoryBarrier)
|
|
||||||
context->glMemoryBarrier(command.barriers);
|
|
||||||
}
|
|
||||||
else if constexpr (std::is_same_v<T, SetFrameBufferData>)
|
|
||||||
{
|
|
||||||
command.framebuffer->Activate();
|
|
||||||
|
|
||||||
context = GL::Context::GetCurrentContext();
|
|
||||||
|
|
||||||
std::size_t colorBufferCount = command.framebuffer->GetColorBufferCount();
|
|
||||||
assert(colorBufferCount <= colorIndexes.size());
|
|
||||||
|
|
||||||
colorIndexes.fill(0);
|
|
||||||
std::size_t colorIndex = 0;
|
|
||||||
|
|
||||||
GLbitfield clearFields = 0;
|
|
||||||
std::optional<std::size_t> depthStencilIndex;
|
|
||||||
|
|
||||||
std::size_t attachmentCount = command.renderpass->GetAttachmentCount();
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < attachmentCount; ++i)
|
|
||||||
{
|
|
||||||
const auto& attachmentInfo = command.renderpass->GetAttachment(i);
|
|
||||||
switch (PixelFormatInfo::GetContent(attachmentInfo.format))
|
|
||||||
{
|
|
||||||
case PixelFormatContent::Undefined:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PixelFormatContent::ColorRGBA:
|
|
||||||
colorIndexes[colorIndex++] = i;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PixelFormatContent::Depth:
|
|
||||||
if (!depthStencilIndex)
|
|
||||||
depthStencilIndex = i;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PixelFormatContent::DepthStencil:
|
|
||||||
if (!depthStencilIndex)
|
|
||||||
depthStencilIndex = i;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case PixelFormatContent::Stencil:
|
|
||||||
//FIXME: I'm not sure stencil is properly handled here
|
|
||||||
if (!depthStencilIndex)
|
|
||||||
depthStencilIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StackVector<GLenum> invalidateAttachments;
|
|
||||||
|
|
||||||
if (command.framebuffer->GetType() == FramebufferType::Texture)
|
|
||||||
{
|
|
||||||
const OpenGLFboFramebuffer& fboFramebuffer = static_cast<const OpenGLFboFramebuffer&>(*command.framebuffer);
|
|
||||||
|
|
||||||
invalidateAttachments = NazaraStackVector(GLenum, colorBufferCount + 1);
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < colorBufferCount; ++i)
|
|
||||||
{
|
|
||||||
std::size_t attachmentIndex = colorIndexes[i];
|
|
||||||
|
|
||||||
Color color = command.clearValues[attachmentIndex].color;
|
|
||||||
std::array<GLfloat, 4> clearColor = { color.r, color.g, color.b, color.a };
|
|
||||||
|
|
||||||
const auto& attachmentInfo = command.renderpass->GetAttachment(attachmentIndex);
|
|
||||||
if (attachmentInfo.loadOp == AttachmentLoadOp::Clear)
|
|
||||||
{
|
|
||||||
context->ResetColorWriteMasks();
|
|
||||||
|
|
||||||
// Reset scissor as it affects clear commands if enabled (disabling it would work too but it seems more expansive)
|
|
||||||
const Vector2ui& attachmentSize = fboFramebuffer.GetAttachmentSize(i);
|
|
||||||
context->SetScissorBox(0, 0, attachmentSize.x, attachmentSize.y);
|
|
||||||
|
|
||||||
context->glClearBufferfv(GL_COLOR, GLint(i), clearColor.data());
|
|
||||||
}
|
|
||||||
else if (attachmentInfo.loadOp == AttachmentLoadOp::Discard)
|
|
||||||
invalidateAttachments.push_back(static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depthStencilIndex)
|
|
||||||
{
|
|
||||||
std::size_t attachmentIndex = *depthStencilIndex;
|
|
||||||
const auto& clearValues = command.clearValues[attachmentIndex];
|
|
||||||
|
|
||||||
const auto& depthStencilAttachment = command.renderpass->GetAttachment(attachmentIndex);
|
|
||||||
|
|
||||||
// Reset scissor as it affects clear commands if enabled (disabling it would work too but it seems more expansive)
|
|
||||||
if (depthStencilAttachment.loadOp == AttachmentLoadOp::Clear || depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Clear)
|
|
||||||
{
|
|
||||||
const Vector2ui& attachmentSize = fboFramebuffer.GetAttachmentSize(attachmentIndex);
|
|
||||||
context->SetScissorBox(0, 0, attachmentSize.x, attachmentSize.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depthStencilAttachment.loadOp == AttachmentLoadOp::Clear && depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Clear)
|
|
||||||
{
|
|
||||||
context->ResetDepthWriteMasks();
|
|
||||||
context->ResetStencilWriteMasks();
|
|
||||||
context->glClearBufferfi(GL_DEPTH_STENCIL, 0, clearValues.depth, clearValues.stencil);
|
|
||||||
}
|
|
||||||
else if (depthStencilAttachment.loadOp == AttachmentLoadOp::Clear)
|
|
||||||
{
|
|
||||||
context->ResetDepthWriteMasks();
|
|
||||||
context->glClearBufferfv(GL_DEPTH, 0, &clearValues.depth);
|
|
||||||
|
|
||||||
if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Discard)
|
|
||||||
invalidateAttachments.push_back(GL_STENCIL_ATTACHMENT);
|
|
||||||
}
|
|
||||||
else if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Clear)
|
|
||||||
{
|
|
||||||
context->ResetStencilWriteMasks();
|
|
||||||
context->glClearBufferuiv(GL_STENCIL, 0, &clearValues.stencil);
|
|
||||||
|
|
||||||
if (depthStencilAttachment.loadOp == AttachmentLoadOp::Discard)
|
|
||||||
invalidateAttachments.push_back(GL_DEPTH_ATTACHMENT);
|
|
||||||
}
|
|
||||||
else if (depthStencilAttachment.loadOp == AttachmentLoadOp::Discard && depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Discard)
|
|
||||||
invalidateAttachments.push_back(GL_DEPTH_STENCIL_ATTACHMENT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert(command.framebuffer->GetType() == FramebufferType::Window);
|
|
||||||
|
|
||||||
// glDrawBuffers doesn't accept GL_BACK on OpenGL non-ES, and glDrawBuffer must be used instead
|
|
||||||
if (context->GetParams().type != GL::ContextType::OpenGL_ES && context->glDrawBuffer)
|
|
||||||
context->glDrawBuffer(GL_BACK);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GLenum buffer = GL_BACK;
|
|
||||||
context->glDrawBuffers(1, &buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidateAttachments = NazaraStackVector(GLenum, 3); //< color + depth + stencil
|
|
||||||
|
|
||||||
if (colorIndex > 0)
|
|
||||||
{
|
|
||||||
assert(colorBufferCount <= 1);
|
|
||||||
|
|
||||||
std::size_t colorAttachmentIndex = colorIndexes.front();
|
|
||||||
|
|
||||||
const auto& colorAttachment = command.renderpass->GetAttachment(colorAttachmentIndex);
|
|
||||||
if (colorAttachment.loadOp == AttachmentLoadOp::Clear)
|
|
||||||
{
|
|
||||||
context->ResetColorWriteMasks();
|
|
||||||
|
|
||||||
const Color& color = command.clearValues[colorAttachmentIndex].color;
|
|
||||||
context->glClearColor(color.r, color.g, color.b, color.a);
|
|
||||||
|
|
||||||
clearFields |= GL_COLOR_BUFFER_BIT;
|
|
||||||
}
|
|
||||||
else if (colorAttachment.loadOp == AttachmentLoadOp::Discard)
|
|
||||||
invalidateAttachments.push_back(GL_COLOR);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (depthStencilIndex)
|
|
||||||
{
|
|
||||||
std::size_t attachmentIndex = *depthStencilIndex;
|
|
||||||
const auto& clearValues = command.clearValues[attachmentIndex];
|
|
||||||
|
|
||||||
const auto& depthStencilAttachment = command.renderpass->GetAttachment(attachmentIndex);
|
|
||||||
if (depthStencilAttachment.loadOp == AttachmentLoadOp::Clear)
|
|
||||||
{
|
|
||||||
context->ResetDepthWriteMasks();
|
|
||||||
context->glClearDepthf(clearValues.depth);
|
|
||||||
clearFields |= GL_DEPTH_BUFFER_BIT;
|
|
||||||
}
|
|
||||||
else if (depthStencilAttachment.loadOp == AttachmentLoadOp::Discard)
|
|
||||||
invalidateAttachments.push_back(GL_DEPTH);
|
|
||||||
|
|
||||||
if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Clear && PixelFormatInfo::GetContent(depthStencilAttachment.format) == PixelFormatContent::DepthStencil)
|
|
||||||
{
|
|
||||||
context->ResetStencilWriteMasks();
|
|
||||||
context->glClearStencil(clearValues.stencil);
|
|
||||||
clearFields |= GL_STENCIL_BUFFER_BIT;
|
|
||||||
}
|
|
||||||
else if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Discard)
|
|
||||||
invalidateAttachments.push_back(GL_STENCIL);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clearFields)
|
|
||||||
{
|
|
||||||
// Reset scissor as it affects clear commands if enabled (disabling it would work too but it seems more expansive)
|
|
||||||
const Vector2ui& size = command.framebuffer->GetSize();
|
|
||||||
context->SetScissorBox(0, 0, size.x, size.y);
|
|
||||||
|
|
||||||
context->glClear(clearFields);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!invalidateAttachments.empty())
|
|
||||||
context->glInvalidateFramebuffer(GL_FRAMEBUFFER, GLsizei(invalidateAttachments.size()), invalidateAttachments.data());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
static_assert(AlwaysFalse<T>::value, "non-exhaustive visitor");
|
|
||||||
|
|
||||||
}, commandVariant);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -389,6 +134,275 @@ namespace Nz
|
||||||
context.BindVertexArray(vao.GetObjectId());
|
context.BindVertexArray(vao.GetObjectId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void OpenGLCommandBuffer::Execute(const GL::Context* context, const BeginDebugRegionCommand& command)
|
||||||
|
{
|
||||||
|
if (context->glPushDebugGroup)
|
||||||
|
context->glPushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, GLsizei(command.regionName.size()), command.regionName.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OpenGLCommandBuffer::Execute(const GL::Context* context, const BlitTextureCommand& command)
|
||||||
|
{
|
||||||
|
context->BlitTexture(*command.source, *command.target, command.sourceBox, command.targetBox, command.filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OpenGLCommandBuffer::Execute(const GL::Context* context, const CopyBufferCommand& command)
|
||||||
|
{
|
||||||
|
context->BindBuffer(GL::BufferTarget::CopyRead, command.source);
|
||||||
|
context->BindBuffer(GL::BufferTarget::CopyWrite, command.target);
|
||||||
|
context->glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, command.sourceOffset, command.targetOffset, command.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OpenGLCommandBuffer::Execute(const GL::Context* context, const CopyBufferFromMemoryCommand& command)
|
||||||
|
{
|
||||||
|
context->BindBuffer(GL::BufferTarget::CopyWrite, command.target);
|
||||||
|
context->glBufferSubData(GL_COPY_WRITE_BUFFER, command.targetOffset, command.size, command.memory);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OpenGLCommandBuffer::Execute(const GL::Context* context, const CopyTextureCommand& command)
|
||||||
|
{
|
||||||
|
context->CopyTexture(*command.source, *command.target, command.sourceBox, command.targetPoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OpenGLCommandBuffer::Execute(const GL::Context* context, const DispatchCommand& command)
|
||||||
|
{
|
||||||
|
if (!context->glDispatchCompute)
|
||||||
|
throw std::runtime_error("compute shaders are not supported on this device");
|
||||||
|
|
||||||
|
command.states.pipeline->Apply(*context);
|
||||||
|
ApplyBindings(*context, command.bindings);
|
||||||
|
context->glDispatchCompute(command.numGroupsX, command.numGroupsY, command.numGroupsZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OpenGLCommandBuffer::Execute(const GL::Context* context, const DrawCommand& command)
|
||||||
|
{
|
||||||
|
ApplyStates(*context, command.states);
|
||||||
|
ApplyBindings(*context, command.bindings);
|
||||||
|
context->glDrawArraysInstanced(ToOpenGL(command.states.pipeline->GetPipelineInfo().primitiveMode), command.firstVertex, command.vertexCount, command.instanceCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OpenGLCommandBuffer::Execute(const GL::Context* context, const DrawIndexedCommand& command)
|
||||||
|
{
|
||||||
|
const UInt8* origin = 0; //< For an easy way to cast an integer to a pointer
|
||||||
|
origin += command.states.indexBufferOffset;
|
||||||
|
|
||||||
|
switch (command.states.indexBufferType)
|
||||||
|
{
|
||||||
|
case IndexType::U8: origin += command.firstIndex * sizeof(UInt8); break;
|
||||||
|
case IndexType::U16: origin += command.firstIndex * sizeof(UInt16); break;
|
||||||
|
case IndexType::U32: origin += command.firstIndex * sizeof(UInt32); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ApplyStates(*context, command.states);
|
||||||
|
ApplyBindings(*context, command.bindings);
|
||||||
|
context->glDrawElementsInstanced(ToOpenGL(command.states.pipeline->GetPipelineInfo().primitiveMode), command.indexCount, ToOpenGL(command.states.indexBufferType), origin, command.instanceCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OpenGLCommandBuffer::Execute(const GL::Context* context, const EndDebugRegionCommand& command)
|
||||||
|
{
|
||||||
|
if (context->glPopDebugGroup)
|
||||||
|
context->glPopDebugGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OpenGLCommandBuffer::Execute(const GL::Context* context, const MemoryBarrier& command)
|
||||||
|
{
|
||||||
|
if (context->glMemoryBarrier)
|
||||||
|
context->glMemoryBarrier(command.barriers);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void OpenGLCommandBuffer::Execute(const GL::Context*& context, const SetFrameBufferCommand& command)
|
||||||
|
{
|
||||||
|
command.framebuffer->Activate();
|
||||||
|
|
||||||
|
StackArray<std::size_t> colorIndexes = NazaraStackArrayNoInit(std::size_t, m_maxColorBufferCount);
|
||||||
|
|
||||||
|
std::size_t colorBufferCount = command.framebuffer->GetColorBufferCount();
|
||||||
|
assert(colorBufferCount <= colorIndexes.size());
|
||||||
|
|
||||||
|
colorIndexes.fill(0);
|
||||||
|
std::size_t colorIndex = 0;
|
||||||
|
|
||||||
|
GLbitfield clearFields = 0;
|
||||||
|
std::optional<std::size_t> depthStencilIndex;
|
||||||
|
|
||||||
|
std::size_t attachmentCount = command.renderpass->GetAttachmentCount();
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < attachmentCount; ++i)
|
||||||
|
{
|
||||||
|
const auto& attachmentInfo = command.renderpass->GetAttachment(i);
|
||||||
|
switch (PixelFormatInfo::GetContent(attachmentInfo.format))
|
||||||
|
{
|
||||||
|
case PixelFormatContent::Undefined:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PixelFormatContent::ColorRGBA:
|
||||||
|
colorIndexes[colorIndex++] = i;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PixelFormatContent::Depth:
|
||||||
|
if (!depthStencilIndex)
|
||||||
|
depthStencilIndex = i;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PixelFormatContent::DepthStencil:
|
||||||
|
if (!depthStencilIndex)
|
||||||
|
depthStencilIndex = i;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PixelFormatContent::Stencil:
|
||||||
|
//FIXME: I'm not sure stencil is properly handled here
|
||||||
|
if (!depthStencilIndex)
|
||||||
|
depthStencilIndex = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StackVector<GLenum> invalidateAttachments;
|
||||||
|
|
||||||
|
if (command.framebuffer->GetType() == FramebufferType::Texture)
|
||||||
|
{
|
||||||
|
const OpenGLFboFramebuffer& fboFramebuffer = static_cast<const OpenGLFboFramebuffer&>(*command.framebuffer);
|
||||||
|
|
||||||
|
invalidateAttachments = NazaraStackVector(GLenum, colorBufferCount + 1);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < colorBufferCount; ++i)
|
||||||
|
{
|
||||||
|
std::size_t attachmentIndex = colorIndexes[i];
|
||||||
|
|
||||||
|
Color color = command.clearValues[attachmentIndex].color;
|
||||||
|
std::array<GLfloat, 4> clearColor = { color.r, color.g, color.b, color.a };
|
||||||
|
|
||||||
|
const auto& attachmentInfo = command.renderpass->GetAttachment(attachmentIndex);
|
||||||
|
if (attachmentInfo.loadOp == AttachmentLoadOp::Clear)
|
||||||
|
{
|
||||||
|
context->ResetColorWriteMasks();
|
||||||
|
|
||||||
|
// Reset scissor as it affects clear commands if enabled (disabling it would work too but it seems more expansive)
|
||||||
|
const Vector2ui& attachmentSize = fboFramebuffer.GetAttachmentSize(i);
|
||||||
|
context->SetScissorBox(0, 0, attachmentSize.x, attachmentSize.y);
|
||||||
|
|
||||||
|
context->glClearBufferfv(GL_COLOR, GLint(i), clearColor.data());
|
||||||
|
}
|
||||||
|
else if (attachmentInfo.loadOp == AttachmentLoadOp::Discard)
|
||||||
|
invalidateAttachments.push_back(static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + i));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depthStencilIndex)
|
||||||
|
{
|
||||||
|
std::size_t attachmentIndex = *depthStencilIndex;
|
||||||
|
const auto& clearValues = command.clearValues[attachmentIndex];
|
||||||
|
|
||||||
|
const auto& depthStencilAttachment = command.renderpass->GetAttachment(attachmentIndex);
|
||||||
|
|
||||||
|
// Reset scissor as it affects clear commands if enabled (disabling it would work too but it seems more expansive)
|
||||||
|
if (depthStencilAttachment.loadOp == AttachmentLoadOp::Clear || depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Clear)
|
||||||
|
{
|
||||||
|
const Vector2ui& attachmentSize = fboFramebuffer.GetAttachmentSize(attachmentIndex);
|
||||||
|
context->SetScissorBox(0, 0, attachmentSize.x, attachmentSize.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depthStencilAttachment.loadOp == AttachmentLoadOp::Clear && depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Clear)
|
||||||
|
{
|
||||||
|
context->ResetDepthWriteMasks();
|
||||||
|
context->ResetStencilWriteMasks();
|
||||||
|
context->glClearBufferfi(GL_DEPTH_STENCIL, 0, clearValues.depth, clearValues.stencil);
|
||||||
|
}
|
||||||
|
else if (depthStencilAttachment.loadOp == AttachmentLoadOp::Clear)
|
||||||
|
{
|
||||||
|
context->ResetDepthWriteMasks();
|
||||||
|
context->glClearBufferfv(GL_DEPTH, 0, &clearValues.depth);
|
||||||
|
|
||||||
|
if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Discard)
|
||||||
|
invalidateAttachments.push_back(GL_STENCIL_ATTACHMENT);
|
||||||
|
}
|
||||||
|
else if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Clear)
|
||||||
|
{
|
||||||
|
context->ResetStencilWriteMasks();
|
||||||
|
context->glClearBufferuiv(GL_STENCIL, 0, &clearValues.stencil);
|
||||||
|
|
||||||
|
if (depthStencilAttachment.loadOp == AttachmentLoadOp::Discard)
|
||||||
|
invalidateAttachments.push_back(GL_DEPTH_ATTACHMENT);
|
||||||
|
}
|
||||||
|
else if (depthStencilAttachment.loadOp == AttachmentLoadOp::Discard && depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Discard)
|
||||||
|
invalidateAttachments.push_back(GL_DEPTH_STENCIL_ATTACHMENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(command.framebuffer->GetType() == FramebufferType::Window);
|
||||||
|
|
||||||
|
// Window framebuffers have their own contexts
|
||||||
|
context = GL::Context::GetCurrentContext();
|
||||||
|
|
||||||
|
// glDrawBuffers doesn't accept GL_BACK on OpenGL non-ES, and glDrawBuffer must be used instead
|
||||||
|
if (context->GetParams().type != GL::ContextType::OpenGL_ES && context->glDrawBuffer)
|
||||||
|
context->glDrawBuffer(GL_BACK);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLenum buffer = GL_BACK;
|
||||||
|
context->glDrawBuffers(1, &buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidateAttachments = NazaraStackVector(GLenum, 3); //< color + depth + stencil
|
||||||
|
|
||||||
|
if (colorIndex > 0)
|
||||||
|
{
|
||||||
|
assert(colorBufferCount <= 1);
|
||||||
|
|
||||||
|
std::size_t colorAttachmentIndex = colorIndexes.front();
|
||||||
|
|
||||||
|
const auto& colorAttachment = command.renderpass->GetAttachment(colorAttachmentIndex);
|
||||||
|
if (colorAttachment.loadOp == AttachmentLoadOp::Clear)
|
||||||
|
{
|
||||||
|
context->ResetColorWriteMasks();
|
||||||
|
|
||||||
|
const Color& color = command.clearValues[colorAttachmentIndex].color;
|
||||||
|
context->glClearColor(color.r, color.g, color.b, color.a);
|
||||||
|
|
||||||
|
clearFields |= GL_COLOR_BUFFER_BIT;
|
||||||
|
}
|
||||||
|
else if (colorAttachment.loadOp == AttachmentLoadOp::Discard)
|
||||||
|
invalidateAttachments.push_back(GL_COLOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (depthStencilIndex)
|
||||||
|
{
|
||||||
|
std::size_t attachmentIndex = *depthStencilIndex;
|
||||||
|
const auto& clearValues = command.clearValues[attachmentIndex];
|
||||||
|
|
||||||
|
const auto& depthStencilAttachment = command.renderpass->GetAttachment(attachmentIndex);
|
||||||
|
if (depthStencilAttachment.loadOp == AttachmentLoadOp::Clear)
|
||||||
|
{
|
||||||
|
context->ResetDepthWriteMasks();
|
||||||
|
context->glClearDepthf(clearValues.depth);
|
||||||
|
clearFields |= GL_DEPTH_BUFFER_BIT;
|
||||||
|
}
|
||||||
|
else if (depthStencilAttachment.loadOp == AttachmentLoadOp::Discard)
|
||||||
|
invalidateAttachments.push_back(GL_DEPTH);
|
||||||
|
|
||||||
|
if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Clear && PixelFormatInfo::GetContent(depthStencilAttachment.format) == PixelFormatContent::DepthStencil)
|
||||||
|
{
|
||||||
|
context->ResetStencilWriteMasks();
|
||||||
|
context->glClearStencil(clearValues.stencil);
|
||||||
|
clearFields |= GL_STENCIL_BUFFER_BIT;
|
||||||
|
}
|
||||||
|
else if (depthStencilAttachment.stencilLoadOp == AttachmentLoadOp::Discard)
|
||||||
|
invalidateAttachments.push_back(GL_STENCIL);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clearFields)
|
||||||
|
{
|
||||||
|
// Reset scissor as it affects clear commands if enabled (disabling it would work too but it seems more expansive)
|
||||||
|
const Vector2ui& size = command.framebuffer->GetSize();
|
||||||
|
context->SetScissorBox(0, 0, size.x, size.y);
|
||||||
|
|
||||||
|
context->glClear(clearFields);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!invalidateAttachments.empty())
|
||||||
|
context->glInvalidateFramebuffer(GL_FRAMEBUFFER, GLsizei(invalidateAttachments.size()), invalidateAttachments.data());
|
||||||
|
}
|
||||||
|
|
||||||
void OpenGLCommandBuffer::Release()
|
void OpenGLCommandBuffer::Release()
|
||||||
{
|
{
|
||||||
assert(m_owner);
|
assert(m_owner);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue