| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591 |
- // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
- // All rights reserved.
- // Code licensed under the BSD License.
- // http://www.anki3d.org/LICENSE
- #pragma once
- #include <AnKi/Gr/gl/Common.h>
- #include <AnKi/Gr/ShaderProgram.h>
- #include <AnKi/Gr/Framebuffer.h>
- #include <AnKi/Gr/gl/FramebufferImpl.h>
- #include <AnKi/Gr/Buffer.h>
- #include <AnKi/Gr/gl/BufferImpl.h>
- #include <AnKi/Gr/Texture.h>
- #include <AnKi/Gr/gl/TextureImpl.h>
- #include <AnKi/Gr/Sampler.h>
- #include <AnKi/Gr/gl/SamplerImpl.h>
- #include <AnKi/Gr/ShaderProgram.h>
- #include <AnKi/Gr/gl/ShaderProgramImpl.h>
- #include <AnKi/Gr/Framebuffer.h>
- #include <AnKi/Gr/gl/FramebufferImpl.h>
- #include <AnKi/Gr/Utils/Functions.h>
- namespace anki
- {
- /// @addtogroup opengl
- /// @{
- /// Local state tracker. Used to avoid creating command buffer commands.
- class StateTracker
- {
- public:
- /// If it's false then there might be unset state.
- Bool m_mayContainUnsetState = true;
- #if ANKI_EXTRA_CHECKS
- Bool m_secondLevel = false;
- #endif
- /// @name vert_state
- /// @{
- class VertexAttribute
- {
- public:
- U32 m_buffBinding = MAX_U32;
- Format m_fmt = Format::NONE;
- PtrSize m_relativeOffset = MAX_PTR_SIZE;
- };
- Array<VertexAttribute, MAX_VERTEX_ATTRIBUTES> m_attribs;
- Bool setVertexAttribute(U32 location, U32 buffBinding, Format fmt, PtrSize relativeOffset)
- {
- VertexAttribute& attrib = m_attribs[location];
- if(attrib.m_buffBinding != buffBinding || attrib.m_fmt != fmt || attrib.m_relativeOffset != relativeOffset)
- {
- attrib.m_buffBinding = buffBinding;
- attrib.m_fmt = fmt;
- attrib.m_relativeOffset = relativeOffset;
- return true;
- }
- return false;
- }
- class VertexBuffer
- {
- public:
- BufferImpl* m_buff = nullptr;
- PtrSize m_offset = 0;
- PtrSize m_stride = 0;
- VertexStepRate m_stepRate = VertexStepRate::COUNT;
- };
- Array<VertexBuffer, MAX_VERTEX_ATTRIBUTES> m_vertBuffs;
- Bool bindVertexBuffer(U32 binding, BufferPtr buff, PtrSize offset, PtrSize stride, VertexStepRate stepRate)
- {
- VertexBuffer& b = m_vertBuffs[binding];
- b.m_buff = static_cast<BufferImpl*>(buff.get());
- b.m_offset = offset;
- b.m_stride = stride;
- b.m_stepRate = stepRate;
- return true;
- }
- class Index
- {
- public:
- BufferImpl* m_buff = nullptr;
- PtrSize m_offset = MAX_PTR_SIZE;
- GLenum m_indexType = 0;
- } m_idx;
- Bool bindIndexBuffer(BufferPtr buff, PtrSize offset, IndexType type)
- {
- m_idx.m_buff = static_cast<BufferImpl*>(buff.get());
- m_idx.m_offset = offset;
- m_idx.m_indexType = convertIndexType(type);
- return true;
- }
- /// @}
- /// @name input_assembly
- /// @{
- Bool m_primitiveRestart = 2;
- Bool setPrimitiveRestart(Bool enable)
- {
- if(enable != m_primitiveRestart)
- {
- m_primitiveRestart = enable;
- return true;
- }
- return false;
- }
- /// @}
- /// @name viewport_state
- /// @{
- Array<U32, 4> m_viewport = {{MAX_U32, MAX_U32, MAX_U32, MAX_U32}};
- Bool setViewport(U32 minx, U32 miny, U32 width, U32 height)
- {
- ANKI_ASSERT(minx != MAX_U32 && miny != MAX_U32 && width != MAX_U32 && height != MAX_U32);
- if(m_viewport[0] != minx || m_viewport[1] != miny || m_viewport[2] != width || m_viewport[3] != height)
- {
- m_viewport = {{minx, miny, width, height}};
- return true;
- }
- return false;
- }
- /// @}
- /// @name scissor_state
- /// @{
- Array<GLsizei, 4> m_scissor = {{0, 0, MAX_I32, MAX_I32}};
- Bool m_scissorSet = false;
- Bool setScissor(GLsizei minx, GLsizei miny, GLsizei width, GLsizei height)
- {
- if(!m_scissorSet
- || (m_scissor[0] != minx || m_scissor[1] != miny || m_scissor[2] != width || m_scissor[3] != height))
- {
- m_scissor = {{minx, miny, width, height}};
- m_scissorSet = true;
- return true;
- }
- return false;
- }
- /// @}
- /// @name rasterizer
- /// @{
- FillMode m_fillMode = FillMode::COUNT;
- Bool setFillMode(FillMode mode)
- {
- if(m_fillMode != mode)
- {
- m_fillMode = mode;
- return true;
- }
- return false;
- }
- FaceSelectionBit m_cullMode = static_cast<FaceSelectionBit>(0);
- Bool setCullMode(FaceSelectionBit mode)
- {
- if(m_cullMode != mode)
- {
- m_cullMode = mode;
- return true;
- }
- return false;
- }
- F32 m_polyOffsetFactor = -1.0;
- F32 m_polyOffsetUnits = -1.0;
- Bool setPolygonOffset(F32 factor, F32 units)
- {
- if(factor != m_polyOffsetFactor || units != m_polyOffsetUnits)
- {
- m_polyOffsetFactor = factor;
- m_polyOffsetUnits = units;
- return true;
- }
- return false;
- }
- /// @}
- /// @name depth_stencil
- /// @{
- Bool m_stencilTestEnabled = 2;
- Bool maybeEnableStencilTest()
- {
- Bool enable = !stencilTestDisabled(m_stencilFail[0], m_stencilPassDepthFail[0], m_stencilPassDepthPass[0],
- m_stencilCompare[0]);
- enable = enable
- || !stencilTestDisabled(m_stencilFail[1], m_stencilPassDepthFail[1], m_stencilPassDepthPass[1],
- m_stencilCompare[1]);
- if(enable != m_stencilTestEnabled)
- {
- m_stencilTestEnabled = enable;
- return true;
- }
- return false;
- }
- Array<StencilOperation, 2> m_stencilFail = {{StencilOperation::COUNT, StencilOperation::COUNT}};
- Array<StencilOperation, 2> m_stencilPassDepthFail = {{StencilOperation::COUNT, StencilOperation::COUNT}};
- Array<StencilOperation, 2> m_stencilPassDepthPass = {{StencilOperation::COUNT, StencilOperation::COUNT}};
- Bool setStencilOperations(FaceSelectionBit face, StencilOperation stencilFail,
- StencilOperation stencilPassDepthFail, StencilOperation stencilPassDepthPass)
- {
- Bool changed = false;
- if(!!(face & FaceSelectionBit::FRONT)
- && (m_stencilFail[0] != stencilFail || m_stencilPassDepthFail[0] != stencilPassDepthFail
- || m_stencilPassDepthPass[0] != stencilPassDepthPass))
- {
- m_stencilFail[0] = stencilFail;
- m_stencilPassDepthFail[0] = stencilPassDepthFail;
- m_stencilPassDepthPass[0] = stencilPassDepthPass;
- changed = true;
- }
- if(!!(face & FaceSelectionBit::BACK)
- && (m_stencilFail[1] != stencilFail || m_stencilPassDepthFail[1] != stencilPassDepthFail
- || m_stencilPassDepthPass[1] != stencilPassDepthPass))
- {
- m_stencilFail[1] = stencilFail;
- m_stencilPassDepthFail[1] = stencilPassDepthFail;
- m_stencilPassDepthPass[1] = stencilPassDepthPass;
- changed = true;
- }
- return changed;
- }
- Array<Bool, 2> m_glStencilFuncSeparateDirty = {{false, false}};
- Array<CompareOperation, 2> m_stencilCompare = {{CompareOperation::COUNT, CompareOperation::COUNT}};
- void setStencilCompareOperation(FaceSelectionBit face, CompareOperation comp)
- {
- if(!!(face & FaceSelectionBit::FRONT) && m_stencilCompare[0] != comp)
- {
- m_stencilCompare[0] = comp;
- m_glStencilFuncSeparateDirty[0] = true;
- }
- if(!!(face & FaceSelectionBit::BACK) && m_stencilCompare[1] != comp)
- {
- m_stencilCompare[1] = comp;
- m_glStencilFuncSeparateDirty[1] = true;
- }
- }
- static const U32 DUMMY_STENCIL_MASK = 0x969696;
- Array<U32, 2> m_stencilCompareMask = {{DUMMY_STENCIL_MASK, DUMMY_STENCIL_MASK}};
- void setStencilCompareMask(FaceSelectionBit face, U32 mask)
- {
- ANKI_ASSERT(mask != DUMMY_STENCIL_MASK && "Oops");
- if(!!(face & FaceSelectionBit::FRONT) && m_stencilCompareMask[0] != mask)
- {
- m_stencilCompareMask[0] = mask;
- m_glStencilFuncSeparateDirty[0] = true;
- }
- if(!!(face & FaceSelectionBit::BACK) && m_stencilCompareMask[1] != mask)
- {
- m_stencilCompareMask[1] = mask;
- m_glStencilFuncSeparateDirty[1] = true;
- }
- }
- Array<U32, 2> m_stencilWriteMask = {{DUMMY_STENCIL_MASK, DUMMY_STENCIL_MASK}};
- Bool setStencilWriteMask(FaceSelectionBit face, U32 mask)
- {
- ANKI_ASSERT(mask != DUMMY_STENCIL_MASK && "Oops");
- Bool changed = false;
- if(!!(face & FaceSelectionBit::FRONT) && m_stencilWriteMask[0] != mask)
- {
- m_stencilWriteMask[0] = mask;
- changed = true;
- }
- if(!!(face & FaceSelectionBit::BACK) && m_stencilWriteMask[1] != mask)
- {
- m_stencilWriteMask[1] = mask;
- changed = true;
- }
- return changed;
- }
- Array<U32, 2> m_stencilRef = {{DUMMY_STENCIL_MASK, DUMMY_STENCIL_MASK}};
- void setStencilReference(FaceSelectionBit face, U32 mask)
- {
- ANKI_ASSERT(mask != DUMMY_STENCIL_MASK && "Oops");
- if(!!(face & FaceSelectionBit::FRONT) && m_stencilRef[0] != mask)
- {
- m_stencilRef[0] = mask;
- m_glStencilFuncSeparateDirty[0] = true;
- }
- if(!!(face & FaceSelectionBit::BACK) && m_stencilRef[1] != mask)
- {
- m_stencilRef[1] = mask;
- m_glStencilFuncSeparateDirty[1] = true;
- }
- }
- Bool m_depthTestEnabled = 2; ///< 2 means don't know
- Bool maybeEnableDepthTest()
- {
- ANKI_ASSERT(m_depthWrite <= 1 && m_depthOp != CompareOperation::COUNT);
- Bool enable = m_depthWrite || m_depthOp != CompareOperation::ALWAYS;
- if(enable != m_depthTestEnabled)
- {
- m_depthTestEnabled = enable;
- return true;
- }
- return false;
- }
- Bool m_depthWrite = 2;
- Bool setDepthWrite(Bool enable)
- {
- if(m_depthWrite != enable)
- {
- m_depthWrite = enable;
- return true;
- }
- return false;
- }
- CompareOperation m_depthOp = CompareOperation::COUNT;
- Bool setDepthCompareOperation(CompareOperation op)
- {
- if(op != m_depthOp)
- {
- m_depthOp = op;
- return true;
- }
- return false;
- }
- /// @}
- /// @name color
- /// @{
- static const ColorBit INVALID_COLOR_MASK = static_cast<ColorBit>(MAX_U8);
- class ColorAttachment
- {
- public:
- ColorBit m_writeMask = INVALID_COLOR_MASK;
- Bool m_enableBlend = 2;
- BlendFactor m_blendSrcFactorRgb = BlendFactor::COUNT;
- BlendFactor m_blendDstFactorRgb = BlendFactor::COUNT;
- BlendFactor m_blendSrcFactorA = BlendFactor::COUNT;
- BlendFactor m_blendDstFactorA = BlendFactor::COUNT;
- BlendOperation m_blendOpRgb = BlendOperation::COUNT;
- BlendOperation m_blendOpA = BlendOperation::COUNT;
- };
- Array<ColorAttachment, MAX_COLOR_ATTACHMENTS> m_colorAtt;
- Bool setColorChannelWriteMask(U32 attachment, ColorBit mask)
- {
- if(m_colorAtt[attachment].m_writeMask != mask)
- {
- m_colorAtt[attachment].m_writeMask = mask;
- return true;
- }
- return false;
- }
- Bool maybeEnableBlend(U attidx)
- {
- ColorAttachment& att = m_colorAtt[attidx];
- Bool wantBlend = !blendingDisabled(att.m_blendSrcFactorRgb, att.m_blendDstFactorRgb, att.m_blendSrcFactorA,
- att.m_blendDstFactorA, att.m_blendOpRgb, att.m_blendOpA);
- if(wantBlend != att.m_enableBlend)
- {
- att.m_enableBlend = wantBlend;
- return true;
- }
- return false;
- }
- Bool setBlendFactors(U32 attachment, BlendFactor srcRgb, BlendFactor dstRgb, BlendFactor srcA, BlendFactor dstA)
- {
- auto& att = m_colorAtt[attachment];
- if(att.m_blendSrcFactorRgb != srcRgb || att.m_blendDstFactorRgb != dstRgb || att.m_blendSrcFactorA != srcA
- || att.m_blendDstFactorA != dstA)
- {
- att.m_blendSrcFactorRgb = srcRgb;
- att.m_blendDstFactorRgb = dstRgb;
- att.m_blendSrcFactorA = srcA;
- att.m_blendDstFactorA = dstA;
- return true;
- }
- return false;
- }
- Bool setBlendOperation(U32 attachment, BlendOperation funcRgb, BlendOperation funcA)
- {
- auto& att = m_colorAtt[attachment];
- if(att.m_blendOpRgb != funcRgb || att.m_blendOpA != funcA)
- {
- att.m_blendOpRgb = funcRgb;
- att.m_blendOpA = funcA;
- return true;
- }
- return false;
- }
- /// @}
- /// @name resources
- /// @{
- class TextureBinding
- {
- public:
- U64 m_texViewUuid = 0;
- U64 m_samplerUuid = 0;
- };
- Array2d<TextureBinding, MAX_DESCRIPTOR_SETS, MAX_TEXTURE_BINDINGS> m_textures;
- Bool bindTextureViewAndSampler(U32 set, U32 binding, const TextureViewPtr& texView, const SamplerPtr& sampler)
- {
- TextureBinding& b = m_textures[set][binding];
- Bool dirty;
- if(b.m_texViewUuid != texView->getUuid() || b.m_samplerUuid != sampler->getUuid())
- {
- b.m_texViewUuid = texView->getUuid();
- b.m_samplerUuid = sampler->getUuid();
- dirty = true;
- }
- else
- {
- dirty = false;
- }
- return dirty;
- }
- class ShaderBufferBinding
- {
- public:
- BufferImpl* m_buff = nullptr;
- PtrSize m_offset;
- PtrSize m_range;
- };
- Array2d<ShaderBufferBinding, MAX_DESCRIPTOR_SETS, MAX_UNIFORM_BUFFER_BINDINGS> m_ubos;
- Bool bindUniformBuffer(U32 set, U32 binding, BufferPtr buff, PtrSize offset, PtrSize range)
- {
- ShaderBufferBinding& b = m_ubos[set][binding];
- b.m_buff = static_cast<BufferImpl*>(buff.get());
- b.m_offset = offset;
- b.m_range = range;
- return true;
- }
- Array2d<ShaderBufferBinding, MAX_DESCRIPTOR_SETS, MAX_STORAGE_BUFFER_BINDINGS> m_ssbos;
- Bool bindStorageBuffer(U32 set, U32 binding, BufferPtr buff, PtrSize offset, PtrSize range)
- {
- ShaderBufferBinding& b = m_ssbos[set][binding];
- b.m_buff = static_cast<BufferImpl*>(buff.get());
- b.m_offset = offset;
- b.m_range = range;
- return true;
- }
- class ImageBinding
- {
- public:
- U64 m_texViewUuid = 0;
- };
- Array2d<ImageBinding, MAX_DESCRIPTOR_SETS, MAX_IMAGE_BINDINGS> m_images;
- Bool bindImage(U32 set, U32 binding, const TextureViewPtr& img)
- {
- ImageBinding& b = m_images[set][binding];
- b.m_texViewUuid = img->getUuid();
- return true;
- }
- ShaderProgramImpl* m_prog = nullptr;
- Bool bindShaderProgram(ShaderProgramPtr prog)
- {
- ShaderProgramImpl* const progimpl = static_cast<ShaderProgramImpl*>(prog.get());
- if(progimpl != m_prog)
- {
- m_prog = progimpl;
- return true;
- }
- return false;
- }
- /// @}
- /// @name other
- /// @{
- const FramebufferImpl* m_fb = nullptr;
- Bool beginRenderPass(const FramebufferPtr& fb)
- {
- ANKI_ASSERT(!insideRenderPass() && "Already inside a renderpass");
- m_fb = static_cast<const FramebufferImpl*>(fb.get());
- m_lastSecondLevelCmdb = nullptr;
- return true;
- }
- void endRenderPass()
- {
- ANKI_ASSERT(insideRenderPass() && "Not inside a renderpass");
- if(m_lastSecondLevelCmdb)
- {
- // Renderpass had 2nd level cmdbs, need to restore the state back to default
- ::new(this) StateTracker();
- }
- else
- {
- m_fb = nullptr;
- }
- }
- Bool insideRenderPass() const
- {
- return m_fb != nullptr;
- }
- CommandBufferImpl* m_lastSecondLevelCmdb = nullptr;
- /// @}
- /// @name drawcalls
- /// @{
- void checkIndexedDracall() const
- {
- ANKI_ASSERT(m_idx.m_indexType != 0 && "Forgot to bind index buffer");
- checkDrawcall();
- }
- void checkNonIndexedDrawcall() const
- {
- checkDrawcall();
- }
- void checkDrawcall() const
- {
- ANKI_ASSERT(m_viewport[1] != MAX_U16 && "Forgot to set the viewport");
- ANKI_ASSERT(m_prog && "Forgot to bound a program");
- ANKI_ASSERT((insideRenderPass() || m_secondLevel) && "Forgot to begin a render pass");
- }
- void checkDispatch() const
- {
- ANKI_ASSERT(m_prog && "Forgot to bound a program");
- ANKI_ASSERT(!insideRenderPass() && "Forgot to end the render pass");
- }
- /// @}
- };
- /// @}
- } // end namespace anki
|