| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- // Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #include <AnKi/Gr/gl/CommandBufferImpl.h>
- #include <AnKi/Gr/GrManager.h>
- #include <AnKi/Gr/gl/GrManagerImpl.h>
- #include <AnKi/Gr/gl/GlState.h>
- #include <AnKi/Gr/gl/Error.h>
- #include <AnKi/Gr/OcclusionQuery.h>
- #include <AnKi/Gr/gl/OcclusionQueryImpl.h>
- #include <AnKi/Gr/Buffer.h>
- #include <AnKi/Gr/gl/BufferImpl.h>
- #include <AnKi/Util/Logger.h>
- #include <AnKi/Core/Trace.h>
- #include <cstring>
- namespace anki {
- void CommandBufferImpl::init(const CommandBufferInitInfo& init)
- {
- auto& pool = getManager().getAllocator().getMemoryPool();
- m_alloc = CommandBufferAllocator<GlCommand*>(pool.getAllocationCallback(), pool.getAllocationCallbackUserData(), init.m_hints.m_chunkSize, 1.0, 0,
- false);
- m_flags = init.m_flags;
- #if ANKI_EXTRA_CHECKS
- m_state.m_secondLevel = !!(init.m_flags & CommandBufferFlag::kSecondLevel);
- #endif
- if(!!(init.m_flags & CommandBufferFlag::kSecondLevel))
- {
- // TODO Need to hold a ref
- m_state.m_fb = static_cast<const FramebufferImpl*>(init.m_framebuffer.get());
- }
- }
- void CommandBufferImpl::destroy()
- {
- ANKI_TRACE_SCOPED_EVENT(GL_CMD_BUFFER_DESTROY);
- #if ANKI_EXTRA_CHECKS
- if(!m_executed && m_firstCommand)
- {
- ANKI_GL_LOGW("Chain contains commands but never executed. This should only happen on exceptions");
- }
- #endif
- GlCommand* command = m_firstCommand;
- while(command != nullptr)
- {
- GlCommand* next = command->m_nextCommand; // Get next before deleting
- m_alloc.deleteInstance(command);
- command = next;
- }
- ANKI_ASSERT(m_alloc.getMemoryPool().getUsersCount() == 1 && "Someone is holding a reference to the command buffer's allocator");
- m_alloc = CommandBufferAllocator<U8>();
- }
- Error CommandBufferImpl::executeAllCommands()
- {
- ANKI_ASSERT(m_firstCommand != nullptr && "Empty command buffer");
- ANKI_ASSERT(m_lastCommand != nullptr && "Empty command buffer");
- #if ANKI_EXTRA_CHECKS
- m_executed = true;
- #endif
- Error err = Error::kNone;
- GlState& state = static_cast<GrManagerImpl&>(getManager()).getState();
- GlCommand* command = m_firstCommand;
- while(command != nullptr && !err)
- {
- err = (*command)(state);
- ANKI_CHECK_GL_ERROR();
- command = command->m_nextCommand;
- }
- return err;
- }
- void CommandBufferImpl::flushDrawcall(CommandBuffer& cmdb)
- {
- ANKI_ASSERT(!!(m_flags & CommandBufferFlag::GRAPHICS_WORK));
- //
- // Set default state
- //
- if(m_state.m_mayContainUnsetState) [[unlikely]]
- {
- m_state.m_mayContainUnsetState = false;
- if(m_state.m_primitiveRestart == 2)
- {
- cmdb.setPrimitiveRestart(false);
- }
- if(m_state.m_fillMode == FillMode::COUNT)
- {
- cmdb.setFillMode(FillMode::SOLID);
- }
- if(m_state.m_cullMode == static_cast<FaceSelectionBit>(0))
- {
- cmdb.setCullMode(FaceSelectionBit::BACK);
- }
- if(m_state.m_polyOffsetFactor == -1.0)
- {
- cmdb.setPolygonOffset(0.0, 0.0);
- }
- for(U i = 0; i < 2; ++i)
- {
- FaceSelectionBit face = (i == 0) ? FaceSelectionBit::FRONT : FaceSelectionBit::BACK;
- if(m_state.m_stencilFail[i] == StencilOperation::COUNT)
- {
- cmdb.setStencilOperations(face, StencilOperation::KEEP, StencilOperation::KEEP, StencilOperation::KEEP);
- }
- if(m_state.m_stencilCompare[i] == CompareOperation::COUNT)
- {
- cmdb.setStencilCompareOperation(face, CompareOperation::ALWAYS);
- }
- if(m_state.m_stencilCompareMask[i] == StateTracker::DUMMY_STENCIL_MASK)
- {
- cmdb.setStencilCompareMask(face, kMaxU32);
- }
- if(m_state.m_stencilWriteMask[i] == StateTracker::DUMMY_STENCIL_MASK)
- {
- cmdb.setStencilWriteMask(face, kMaxU32);
- }
- if(m_state.m_stencilRef[i] == StateTracker::DUMMY_STENCIL_MASK)
- {
- cmdb.setStencilReference(face, 0);
- }
- }
- if(m_state.m_depthWrite == 2)
- {
- cmdb.setDepthWrite(true);
- }
- if(m_state.m_depthOp == CompareOperation::COUNT)
- {
- cmdb.setDepthCompareOperation(CompareOperation::LESS);
- }
- for(U i = 0; i < kMaxColorRenderTargets; ++i)
- {
- const auto& att = m_state.m_colorAtt[i];
- if(att.m_writeMask == StateTracker::INVALID_COLOR_MASK)
- {
- cmdb.setColorChannelWriteMask(i, ColorBit::ALL);
- }
- if(att.m_blendSrcFactorRgb == BlendFactor::COUNT)
- {
- cmdb.setBlendFactors(i, BlendFactor::ONE, BlendFactor::ZERO, BlendFactor::ONE, BlendFactor::ZERO);
- }
- if(att.m_blendOpRgb == BlendOperation::COUNT)
- {
- cmdb.setBlendOperation(i, BlendOperation::ADD, BlendOperation::ADD);
- }
- }
- if(!m_state.m_scissorSet)
- {
- cmdb.setScissor(0, 0, kMaxU32, kMaxU32);
- }
- }
- //
- // Fire commands to change some state
- //
- class StencilCmd final : public GlCommand
- {
- public:
- GLenum m_face;
- GLenum m_func;
- GLint m_ref;
- GLuint m_compareMask;
- StencilCmd(GLenum face, GLenum func, GLint ref, GLuint mask)
- : m_face(face)
- , m_func(func)
- , m_ref(ref)
- , m_compareMask(mask)
- {
- }
- Error operator()(GlState&)
- {
- glStencilFuncSeparate(m_face, m_func, m_ref, m_compareMask);
- return Error::kNone;
- }
- };
- for(U i = 0; i < 2; ++i)
- {
- if(m_state.m_glStencilFuncSeparateDirty[i])
- {
- pushBackNewCommand<StencilCmd>(GL_FRONT + i, convertCompareOperation(m_state.m_stencilCompare[i]), m_state.m_stencilRef[i],
- m_state.m_stencilCompareMask[i]);
- m_state.m_glStencilFuncSeparateDirty[i] = false;
- }
- }
- class DepthTestCmd final : public GlCommand
- {
- public:
- Bool m_enable;
- DepthTestCmd(Bool enable)
- : m_enable(enable)
- {
- }
- Error operator()(GlState&)
- {
- if(m_enable)
- {
- glEnable(GL_DEPTH_TEST);
- }
- else
- {
- glDisable(GL_DEPTH_TEST);
- }
- return Error::kNone;
- }
- };
- if(m_state.maybeEnableDepthTest())
- {
- pushBackNewCommand<DepthTestCmd>(m_state.m_depthTestEnabled);
- }
- class StencilTestCmd final : public GlCommand
- {
- public:
- Bool m_enable;
- StencilTestCmd(Bool enable)
- : m_enable(enable)
- {
- }
- Error operator()(GlState&)
- {
- if(m_enable)
- {
- glEnable(GL_STENCIL_TEST);
- }
- else
- {
- glDisable(GL_STENCIL_TEST);
- }
- return Error::kNone;
- }
- };
- if(m_state.maybeEnableStencilTest())
- {
- pushBackNewCommand<StencilTestCmd>(m_state.m_stencilTestEnabled);
- }
- class BlendCmd final : public GlCommand
- {
- public:
- U8 m_enableMask;
- U8 m_disableMask;
- BlendCmd(U8 enableMask, U8 disableMask)
- : m_enableMask(enableMask)
- , m_disableMask(disableMask)
- {
- }
- Error operator()(GlState&)
- {
- for(U i = 0; i < kMaxColorRenderTargets; ++i)
- {
- if(m_enableMask & (1 << i))
- {
- glEnablei(GL_BLEND, i);
- }
- else if(m_disableMask & (1 << i))
- {
- glDisablei(GL_BLEND, i);
- }
- }
- return Error::kNone;
- }
- };
- U8 blendEnableMask = 0;
- U8 blendDisableMask = 0;
- for(U i = 0; i < kMaxColorRenderTargets; ++i)
- {
- if(m_state.maybeEnableBlend(i))
- {
- if(m_state.m_colorAtt[i].m_enableBlend)
- {
- blendEnableMask |= 1 << i;
- }
- else
- {
- blendDisableMask |= 1 << i;
- }
- }
- }
- if(blendEnableMask || blendDisableMask)
- {
- pushBackNewCommand<BlendCmd>(blendEnableMask, blendDisableMask);
- }
- }
- } // end namespace anki
|