@@ -115,7 +115,7 @@ void GLContextState::Invalidate()
115115 for (Uint32 rt = 0 ; rt < _countof (m_ColorWriteMasks); ++rt)
116116 m_ColorWriteMasks[rt] = 0xFF ;
117117
118- m_bIndependentWriteMasks = EnableStateHelper ();
118+ m_bIndexedWriteMasks = EnableStateHelper ();
119119
120120 m_iActiveTexture = -1 ;
121121 m_NumPatchVertices = -1 ;
@@ -717,35 +717,62 @@ void GLContextState::SetBlendFactors(const float* BlendFactors)
717717 DEV_CHECK_GL_ERROR (" Failed to set blend color" );
718718}
719719
720- void GLContextState::SetBlendState (const BlendStateDesc& BSDsc, Uint32 SampleMask)
720+ void GLContextState::SetBlendState (const BlendStateDesc& BSDsc, Uint32 RenderTargetMask, Uint32 SampleMask)
721721{
722722 if (SampleMask != 0xFFFFFFFF )
723723 LOG_ERROR_MESSAGE (" Sample mask is not currently implemented in GL backend" );
724724
725- bool bEnableBlend = false ;
726- if (BSDsc.IndependentBlendEnable )
725+ bool bEnableBlend = BSDsc.RenderTargets [0 ].BlendEnable ;
726+ bool bUseIndexedColorWriteMasks = false ;
727+ COLOR_MASK NonIndexedColorMask = COLOR_MASK_NONE;
728+
729+ if (RenderTargetMask & ~((1u << MAX_RENDER_TARGETS) - 1u ))
730+ {
731+ UNEXPECTED (" Render target mask (" , RenderTargetMask, " ) contains bits that correspond to non-existent render targets" );
732+ RenderTargetMask &= (1u << MAX_RENDER_TARGETS) - 1u ;
733+ }
734+
735+ if (RenderTargetMask & ~((1u << m_Caps.MaxDrawBuffers ) - 1u ))
736+ {
737+ LOG_ERROR_MESSAGE (" Render target mask (" , RenderTargetMask, " ) contains buffer " , PlatformMisc::GetLSB (RenderTargetMask), " but this device only supports " , m_Caps.MaxDrawBuffers , " draw buffers" );
738+ RenderTargetMask &= (1u << m_Caps.MaxDrawBuffers ) - 1u ;
739+ }
740+
741+ for (Uint32 Mask = RenderTargetMask; Mask != 0 ;)
727742 {
728- for (int i = 0 ; i < static_cast <int >(MAX_RENDER_TARGETS); ++i)
743+ Uint32 rt = PlatformMisc::GetLSB (Mask);
744+ Mask &= ~(1u << rt);
745+ VERIFY_EXPR (rt < MAX_RENDER_TARGETS && static_cast <int >(rt) < m_Caps.MaxDrawBuffers );
746+
747+ const RenderTargetBlendDesc& RT = BSDsc.RenderTargets [rt];
748+ VERIFY (RT.RenderTargetWriteMask != COLOR_MASK_NONE, " Render target write mask should not be COLOR_MASK_NONE if corresponding bit is set in RenderTargetMask" );
749+ if (NonIndexedColorMask == COLOR_MASK_NONE)
750+ {
751+ NonIndexedColorMask = RT.RenderTargetWriteMask ;
752+ }
753+ else if (NonIndexedColorMask != RT.RenderTargetWriteMask )
729754 {
730- const RenderTargetBlendDesc& RT = BSDsc.RenderTargets [i];
731- if (RT.BlendEnable )
732- bEnableBlend = true ;
755+ bUseIndexedColorWriteMasks = true ;
756+ }
733757
734- if (i < m_Caps.MaxDrawBuffers )
735- {
736- SetColorWriteMask (i, RT.RenderTargetWriteMask , True);
737- }
738- else
739- {
740- VERIFY (RT.RenderTargetWriteMask == RenderTargetBlendDesc ().RenderTargetWriteMask , " Render target write mask is specified for buffer " , i, " but this device only supports " , m_Caps.MaxDrawBuffers , " draw buffers" );
741- }
758+ if (BSDsc.IndependentBlendEnable && RT.BlendEnable )
759+ bEnableBlend = true ;
760+ }
761+
762+ if (bUseIndexedColorWriteMasks)
763+ {
764+ for (Uint32 Mask = RenderTargetMask; Mask != 0 ;)
765+ {
766+ Uint32 rt = PlatformMisc::GetLSB (Mask);
767+ Mask &= ~(1u << rt);
768+ VERIFY_EXPR (rt < MAX_RENDER_TARGETS && static_cast <int >(rt) < m_Caps.MaxDrawBuffers );
769+ SetColorWriteMaskIndexed (rt, BSDsc.RenderTargets [rt].RenderTargetWriteMask );
742770 }
743771 }
744- else
772+ else if (NonIndexedColorMask != COLOR_MASK_NONE)
745773 {
746- const RenderTargetBlendDesc& RT0 = BSDsc.RenderTargets [0 ];
747- bEnableBlend = RT0.BlendEnable ;
748- SetColorWriteMask (0 , RT0.RenderTargetWriteMask , False);
774+ // If the color write mask is COLOR_MASK_NONE, the draw buffer is disabled with glDrawBuffer.
775+ SetColorWriteMask (NonIndexedColorMask);
749776 }
750777
751778 if (bEnableBlend)
@@ -826,55 +853,57 @@ void GLContextState::SetBlendState(const BlendStateDesc& BSDsc, Uint32 SampleMas
826853 }
827854}
828855
829- void GLContextState::SetColorWriteMask (Uint32 RTIndex, Uint32 WriteMask, Bool bIsIndependent )
856+ void GLContextState::SetColorWriteMask (Uint32 WriteMask)
830857{
831858 // Even though the write mask only applies to writes to a framebuffer, the mask state is NOT
832859 // Framebuffer state. So it is NOT part of a Framebuffer Object or the Default Framebuffer.
833860 // Binding a new framebuffer will NOT affect the mask.
861+ if (!m_bIndexedWriteMasks && m_ColorWriteMasks[0 ] == WriteMask)
862+ return ;
834863
835- if (!bIsIndependent)
836- RTIndex = 0 ;
864+ // glColorMask() sets the mask for ALL draw buffers
865+ glColorMask (
866+ (WriteMask & COLOR_MASK_RED) ? GL_TRUE : GL_FALSE,
867+ (WriteMask & COLOR_MASK_GREEN) ? GL_TRUE : GL_FALSE,
868+ (WriteMask & COLOR_MASK_BLUE) ? GL_TRUE : GL_FALSE,
869+ (WriteMask & COLOR_MASK_ALPHA) ? GL_TRUE : GL_FALSE);
870+ DEV_CHECK_GL_ERROR (" Failed to set GL color mask" );
837871
838- if (m_ColorWriteMasks[RTIndex] != WriteMask ||
839- m_bIndependentWriteMasks != bIsIndependent)
840- {
841- if (bIsIndependent)
842- {
843- // Note that glColorMaski() does not set color mask for the framebuffer
844- // attachment point RTIndex. Rather it sets the mask for what was set
845- // by the glDrawBuffers() function for the i-th output
846- glColorMaski (RTIndex,
847- (WriteMask & COLOR_MASK_RED) ? GL_TRUE : GL_FALSE,
848- (WriteMask & COLOR_MASK_GREEN) ? GL_TRUE : GL_FALSE,
849- (WriteMask & COLOR_MASK_BLUE) ? GL_TRUE : GL_FALSE,
850- (WriteMask & COLOR_MASK_ALPHA) ? GL_TRUE : GL_FALSE);
851- DEV_CHECK_GL_ERROR (" Failed to set GL color mask" );
852-
853- m_ColorWriteMasks[RTIndex] = WriteMask;
854- }
855- else
856- {
857- // glColorMask() sets the mask for ALL draw buffers
858- glColorMask (
859- (WriteMask & COLOR_MASK_RED) ? GL_TRUE : GL_FALSE,
860- (WriteMask & COLOR_MASK_GREEN) ? GL_TRUE : GL_FALSE,
861- (WriteMask & COLOR_MASK_BLUE) ? GL_TRUE : GL_FALSE,
862- (WriteMask & COLOR_MASK_ALPHA) ? GL_TRUE : GL_FALSE);
863- DEV_CHECK_GL_ERROR (" Failed to set GL color mask" );
864-
865- for (size_t rt = 0 ; rt < _countof (m_ColorWriteMasks); ++rt)
866- m_ColorWriteMasks[rt] = WriteMask;
867- }
868- m_bIndependentWriteMasks = bIsIndependent;
869- }
872+ for (size_t rt = 0 ; rt < _countof (m_ColorWriteMasks); ++rt)
873+ m_ColorWriteMasks[rt] = WriteMask;
874+
875+ m_bIndexedWriteMasks = false ;
876+ }
877+
878+ void GLContextState::SetColorWriteMaskIndexed (Uint32 RTIndex, Uint32 WriteMask)
879+ {
880+ // Even though the write mask only applies to writes to a framebuffer, the mask state is NOT
881+ // Framebuffer state. So it is NOT part of a Framebuffer Object or the Default Framebuffer.
882+ // Binding a new framebuffer will NOT affect the mask.
883+ if (m_ColorWriteMasks[RTIndex] == WriteMask)
884+ return ;
885+
886+ // Note that glColorMaski() does not set color mask for the framebuffer
887+ // attachment point RTIndex. Rather it sets the mask for what was set
888+ // by the glDrawBuffers() function for the i-th output
889+ glColorMaski (RTIndex,
890+ (WriteMask & COLOR_MASK_RED) ? GL_TRUE : GL_FALSE,
891+ (WriteMask & COLOR_MASK_GREEN) ? GL_TRUE : GL_FALSE,
892+ (WriteMask & COLOR_MASK_BLUE) ? GL_TRUE : GL_FALSE,
893+ (WriteMask & COLOR_MASK_ALPHA) ? GL_TRUE : GL_FALSE);
894+ DEV_CHECK_GL_ERROR (" Failed to set GL color mask" );
895+
896+ m_ColorWriteMasks[RTIndex] = WriteMask;
897+
898+ m_bIndexedWriteMasks = true ;
870899}
871900
872- void GLContextState::GetColorWriteMask (Uint32 RTIndex, Uint32& WriteMask, Bool& bIsIndependent )
901+ void GLContextState::GetColorWriteMask (Uint32 RTIndex, Uint32& WriteMask, Bool& bIsIndexed )
873902{
874- if (!m_bIndependentWriteMasks)
875- RTIndex = 0 ;
876- WriteMask = m_ColorWriteMasks[RTIndex] ;
877- bIsIndependent = m_bIndependentWriteMasks ;
903+ WriteMask = m_ColorWriteMasks[RTIndex];
904+ if (WriteMask == 0xFF )
905+ WriteMask = 0xF ;
906+ bIsIndexed = m_bIndexedWriteMasks ;
878907}
879908
880909void GLContextState::SetNumPatchVertices (Int32 NumVertices)
0 commit comments