Fixed MRT clear with UINT8_MAX palette index clearing the attachment on clear quad. (#4006)

This commit is contained in:
Branimir Karadžić
2026-09-30 12:06:59 -07:00
committed by GitHub
parent 9304c09edc
commit 997b0cfe36
17 changed files with 176 additions and 29 deletions
+2 -1
View File
@@ -4423,7 +4423,8 @@ public static class bgfx
/// <summary>
/// Set view clear flags with different clear color for each
/// frame buffer texture. `bgfx::setPaletteColor` must be used to set up a
/// clear color palette.
/// clear color palette. Frame buffer attachment with palette index set to
/// `UINT8_MAX` is not cleared.
/// </summary>
///
/// <param name="_id">View id.</param>
+2 -1
View File
@@ -3230,7 +3230,8 @@ extern fn void set_view_clear(ushort _id, ushort _flags, uint _rgba, float _dept
// Set view clear flags with different clear color for each
// frame buffer texture. `bgfx::setPaletteColor` must be used to set up a
// clear color palette.
// clear color palette. Frame buffer attachment with palette index set to
// `UINT8_MAX` is not cleared.
// _id : `View id.`
// _flags : `Clear flags. Use `BGFX_CLEAR_NONE` to remove any clear operation. See: `BGFX_CLEAR_*`.`
// _depth : `Depth clear value.`
+2 -1
View File
@@ -4370,7 +4370,8 @@ public static partial class bgfx
/// <summary>
/// Set view clear flags with different clear color for each
/// frame buffer texture. `bgfx::setPaletteColor` must be used to set up a
/// clear color palette.
/// clear color palette. Frame buffer attachment with palette index set to
/// `UINT8_MAX` is not cleared.
/// </summary>
///
/// <param name="_id">View id.</param>
+2 -1
View File
@@ -3764,7 +3764,8 @@ mixin(joinFnBinds((){
/**
* Set view clear flags with different clear color for each
* frame buffer texture. `bgfx::setPaletteColor` must be used to set up a
* clear color palette.
* clear color palette. Frame buffer attachment with palette index set to
* `UINT8_MAX` is not cleared.
Params:
id = View id.
flags = Clear flags. Use `BGFX_CLEAR_NONE` to remove any clear
+2 -1
View File
@@ -2613,7 +2613,8 @@ def bgfx_set_view_clear(_id: int, _flags: int, _rgba: int, _depth: float, _stenc
# Set view clear flags with different clear color for each
# frame buffer texture. `bgfx::setPaletteColor` must be used to set up a
# clear color palette.
# clear color palette. Frame buffer attachment with palette index set to
# `UINT8_MAX` is not cleared.
def bgfx_set_view_clear_mrt(
_id: int,
_flags: int,
+2 -1
View File
@@ -3627,7 +3627,8 @@ extern fn bgfx_set_view_clear(_id: ViewId, _flags: u16, _rgba: u32, _depth: f32,
/// Set view clear flags with different clear color for each
/// frame buffer texture. `bgfx::setPaletteColor` must be used to set up a
/// clear color palette.
/// clear color palette. Frame buffer attachment with palette index set to
/// `UINT8_MAX` is not cleared.
/// <param name="_id">View id.</param>
/// <param name="_flags">Clear flags. Use `BGFX_CLEAR_NONE` to remove any clear operation. See: `BGFX_CLEAR_*`.</param>
/// <param name="_depth">Depth clear value.</param>
+2 -1
View File
@@ -4202,7 +4202,8 @@ namespace bgfx
/// Set view clear flags with different clear color for each
/// frame buffer texture. `bgfx::setPaletteColor` must be used to set up a
/// clear color palette.
/// clear color palette. Frame buffer attachment with palette index set to
/// `UINT8_MAX` is not cleared.
///
/// @param[in] _id View id.
/// @param[in] _flags Clear flags. Use `BGFX_CLEAR_NONE` to remove any clear
+2 -1
View File
@@ -2928,7 +2928,8 @@ BGFX_C_API void bgfx_set_view_clear(bgfx_view_id_t _id, uint16_t _flags, uint32_
/**
* Set view clear flags with different clear color for each
* frame buffer texture. `bgfx::setPaletteColor` must be used to set up a
* clear color palette.
* clear color palette. Frame buffer attachment with palette index set to
* `UINT8_MAX` is not cleared.
*
* @param[in] _id View id.
* @param[in] _flags Clear flags. Use `BGFX_CLEAR_NONE` to remove any clear
+2 -1
View File
@@ -2557,7 +2557,8 @@ func.setViewClear { section = "Views" }
--- Set view clear flags with different clear color for each
--- frame buffer texture. `bgfx::setPaletteColor` must be used to set up a
--- clear color palette.
--- clear color palette. Frame buffer attachment with palette index set to
--- `UINT8_MAX` is not cleared.
func.setViewClear { cname = "set_view_clear_mrt", section = "Views" }
"void"
.id "ViewId" --- View id.
+21
View File
@@ -6209,6 +6209,7 @@ namespace bgfx
, storageSize
, _mem->size
);
BX_UNUSED(storageSize);
}
uint32_t size = sizeof(uint32_t)+sizeof(TextureCreate);
@@ -6281,6 +6282,7 @@ namespace bgfx
, storageSize
, _mem->size
);
BX_UNUSED(storageSize);
}
uint32_t size = sizeof(uint32_t)+sizeof(TextureCreate);
@@ -6332,6 +6334,7 @@ namespace bgfx
, storageSize
, _mem->size
);
BX_UNUSED(storageSize);
}
uint32_t size = sizeof(uint32_t)+sizeof(TextureCreate);
@@ -6701,6 +6704,24 @@ namespace bgfx
void setViewClear(ViewId _id, uint16_t _flags, float _depth, uint8_t _stencil, uint8_t _0, uint8_t _1, uint8_t _2, uint8_t _3, uint8_t _4, uint8_t _5, uint8_t _6, uint8_t _7)
{
BX_ASSERT(checkView(_id), "Invalid view id: %d", _id);
if (BX_ENABLED(BGFX_CONFIG_DEBUG) )
{
const uint8_t index[] = { _0, _1, _2, _3, _4, _5, _6, _7 };
for (uint32_t ii = 0; ii < BX_COUNTOF(index); ++ii)
{
BX_ASSERT(UINT8_MAX == index[ii] || index[ii] < BGFX_CONFIG_MAX_COLOR_PALETTE
, "setViewClear: Invalid palette index %d for frame buffer attachment %d (must be less than BGFX_CONFIG_MAX_COLOR_PALETTE (%d), or UINT8_MAX to leave the attachment unchanged)."
, index[ii]
, ii
, BGFX_CONFIG_MAX_COLOR_PALETTE
);
}
BX_UNUSED(index);
}
s_ctx->setViewClear(_id, _flags, _depth, _stencil, _0, _1, _2, _3, _4, _5, _6, _7);
}
+17
View File
@@ -549,6 +549,23 @@ namespace bgfx
m_stencil = _stencil;
}
uint8_t getColorSkipMask(uint32_t _num) const
{
if (0 == (m_flags & BGFX_CLEAR_COLOR_USE_PALETTE) )
{
return 0;
}
uint8_t mask = 0;
for (uint32_t ii = 0, num = bx::min<uint32_t>(_num, BX_COUNTOF(m_index) ); ii < num; ++ii)
{
mask |= UINT8_MAX == m_index[ii] ? 1<<ii : 0;
}
return mask;
}
uint8_t m_index[8];
float m_depth;
uint8_t m_stencil;
+19 -5
View File
@@ -2901,7 +2901,7 @@ namespace bgfx { namespace d3d11
setInputLayout(BX_COUNTOF(layouts), layouts, _program, _numInstanceData);
}
void setBlendState(uint64_t _state, uint32_t _rgba = 0, uint32_t _sampleMask = UINT32_MAX)
void setBlendState(uint64_t _state, uint32_t _rgba = 0, uint32_t _sampleMask = UINT32_MAX, uint8_t _mrtMask = UINT8_MAX)
{
_state &= BGFX_D3D11_BLEND_STATE_MASK;
@@ -2912,6 +2912,7 @@ namespace bgfx { namespace d3d11
? _rgba
: -1
);
murmur.add(_mrtMask);
const uint32_t hash = murmur.end();
ID3D11BlendState* bs = m_blendStateCache.find(hash);
@@ -2981,6 +2982,19 @@ namespace bgfx { namespace d3d11
}
}
if (UINT8_MAX != _mrtMask)
{
desc.IndependentBlendEnable = true;
for (uint32_t ii = 0; ii < BX_COUNTOF(desc.RenderTarget); ++ii)
{
if (0 == (_mrtMask & (1<<ii) ) )
{
desc.RenderTarget[ii].RenderTargetWriteMask = 0;
}
}
}
DX_CHECK(m_device->CreateBlendState(&desc, &bs) );
m_blendStateCache.add(hash, bs);
@@ -3854,10 +3868,6 @@ namespace bgfx { namespace d3d11
: 0
;
setBlendState(state);
setDepthStencilState(state, stencil);
setRasterizerState(state);
uint32_t numMrt = 1;
FrameBufferHandle fbh = m_fbh;
if (isValid(fbh) )
@@ -3866,6 +3876,10 @@ namespace bgfx { namespace d3d11
numMrt = bx::max(1, fb.m_num);
}
setBlendState(state, 0, UINT32_MAX, uint8_t(~_clear.getColorSkipMask(numMrt) ) );
setDepthStencilState(state, stencil);
setRasterizerState(state);
ProgramD3D11& program = m_program[_clearQuad.m_program[numMrt-1].idx];
m_currentProgram = &program;
+1 -1
View File
@@ -2128,7 +2128,7 @@ namespace bgfx { namespace d3d12
void shutdown()
{
m_cmd.finish();
finishAll(true);
m_batch.destroy();
DX_RELEASE(m_zeroInitBuffer, 0);
+33 -2
View File
@@ -4876,8 +4876,13 @@ namespace bgfx { namespace gl
GLint intClear[4] = {};
const bool clearColor = true
&& 0 != (BGFX_CLEAR_COLOR & _clear.m_flags)
&& 0 == _clear.getColorSkipMask(1)
;
GLuint flags = 0;
if (BGFX_CLEAR_COLOR & _clear.m_flags)
if (clearColor)
{
if (BGFX_CLEAR_COLOR_USE_PALETTE & _clear.m_flags)
{
@@ -4941,7 +4946,7 @@ namespace bgfx { namespace gl
GL_CHECK(glStencilMask(0xff) );
}
const bool clearColorInt = intColor && 0 != (BGFX_CLEAR_COLOR & _clear.m_flags);
const bool clearColorInt = intColor && clearColor;
if (0 != flags
|| clearColorInt)
@@ -5081,10 +5086,36 @@ namespace bgfx { namespace gl
commit(*program.m_constantBuffer);
const uint8_t skipMask = _clear.getColorSkipMask(numMrt);
GLenum buffers[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS];
if (0 != skipMask)
{
for (uint32_t ii = 0; ii < numMrt; ++ii)
{
buffers[ii] = 0 != (skipMask & (1<<ii) )
? GL_NONE
: GL_COLOR_ATTACHMENT0 + ii
;
}
GL_CHECK(glDrawBuffers(numMrt, buffers) );
}
GL_CHECK(glDrawArrays(GL_TRIANGLE_STRIP
, 0
, 4
) );
if (0 != skipMask)
{
for (uint32_t ii = 0; ii < numMrt; ++ii)
{
buffers[ii] = GL_COLOR_ATTACHMENT0 + ii;
}
GL_CHECK(glDrawBuffers(numMrt, buffers) );
}
}
}
+23 -2
View File
@@ -2419,6 +2419,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames
, &layout
, _clearQuad.m_program[numMrt-1]
, 0
, UINT32_MAX
, uint8_t(~_clear.getColorSkipMask(numMrt) )
);
setRenderPipelineState(pso->m_rps);
@@ -2971,6 +2973,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames
, ProgramHandle _program
, uint8_t _numInstanceData
, uint32_t _sampleMask = UINT32_MAX
, uint8_t _mrtMask = UINT8_MAX
)
{
_state &= (0
@@ -2994,7 +2997,8 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames
&& m_lastPsoState.m_fbh == _fbh.idx
&& m_lastPsoState.m_numStreams == _numStreams
&& m_lastPsoState.m_numInstanceData == _numInstanceData
&& m_lastPsoState.m_sampleMask == _sampleMask)
&& m_lastPsoState.m_sampleMask == _sampleMask
&& m_lastPsoState.m_mrtMask == _mrtMask)
{
bool match = true;
for (uint8_t ii = 0; ii < _numStreams && match; ++ii)
@@ -3015,6 +3019,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames
m_lastPsoState.m_numStreams = _numStreams;
m_lastPsoState.m_numInstanceData = _numInstanceData;
m_lastPsoState.m_sampleMask = _sampleMask;
m_lastPsoState.m_mrtMask = _mrtMask;
for (uint8_t ii = 0; ii < _numStreams; ++ii)
{
m_lastPsoState.m_layouts[ii] = _layouts[ii];
@@ -3028,6 +3033,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames
murmur.add(rgba);
murmur.add(_numInstanceData);
murmur.add(_sampleMask);
murmur.add(_mrtMask);
if (!isValid(_fbh) )
{
@@ -3193,6 +3199,17 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames
}
}
if (UINT8_MAX != _mrtMask)
{
for (uint32_t ii = 0; ii < frameBufferAttachment; ++ii)
{
if (0 == (_mrtMask & (1<<ii) ) )
{
pd->colorAttachments()->object(ii)->setWriteMask(MTL::ColorWriteMaskNone);
}
}
}
pd->setVertexFunction(program.m_vsh->m_function);
pd->setFragmentFunction(program.m_fsh != NULL
? program.m_fsh->getFunction(_sampleMask)
@@ -3688,6 +3705,7 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames
uint16_t m_fbh;
uint8_t m_numStreams;
uint8_t m_numInstanceData;
uint8_t m_mrtMask;
};
PipelineState m_lastPsoState;
@@ -6289,13 +6307,16 @@ static_assert(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNames
if (clearWithRenderPass)
{
const uint8_t colorSkipMask = clr.getColorSkipMask(g_caps.limits.maxFBAttachments);
for (uint32_t ii = 0; ii < g_caps.limits.maxFBAttachments; ++ii)
{
MTL::RenderPassColorAttachmentDescriptor* desc = renderPassDescriptor->colorAttachments()->object(ii);
if (desc->texture() != NULL)
{
if (0 != (BGFX_CLEAR_COLOR & clr.m_flags) )
if (0 != (BGFX_CLEAR_COLOR & clr.m_flags)
&& 0 == (colorSkipMask & (1<<ii) ) )
{
if (0 != (BGFX_CLEAR_COLOR_USE_PALETTE & clr.m_flags) )
{
+24 -6
View File
@@ -4927,9 +4927,13 @@ VK_IMPORT_DEVICE
if (BGFX_CLEAR_COLOR & _clear.m_flags)
{
for (uint32_t ii = 0; ii < numMrt; ++ii)
const uint8_t colorMask = uint8_t(~_clear.getColorSkipMask(numMrt) & ( (1<<numMrt)-1) );
for (BitMaskToIndexIteratorT it(colorMask); !it.isDone(); it.next() )
{
attachments[mrt].colorAttachment = mrt;
const uint32_t ii = it.idx;
attachments[mrt].colorAttachment = ii;
attachments[mrt].aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
VkClearColorValue& clearValue = attachments[mrt].clearValue.color;
@@ -10602,7 +10606,17 @@ VK_DESTROY
if (isFrameBufferValid)
{
VkRenderPass renderPass = fb.getRenderPass(_render->m_view[view].m_clear.m_flags);
const Clear& clr = _render->m_view[view].m_clear;
const bool partialColorClear = true
&& 0 != (clr.m_flags & BGFX_CLEAR_COLOR)
&& 0 != clr.getColorSkipMask(NULL == fb.m_nwh ? fb.m_num : 1)
;
VkRenderPass renderPass = fb.getRenderPass(partialColorClear
? clr.m_flags & ~BGFX_CLEAR_COLOR
: clr.m_flags
);
viewState.m_rect = _render->m_view[view].m_rect;
const Rect& rect = _render->m_view[view].m_rect;
@@ -10671,8 +10685,6 @@ VK_DESTROY
VkClearValue clearValues[BGFX_CONFIG_MAX_FRAME_BUFFER_ATTACHMENTS + 1];
uint32_t mrt = 0;
const Clear& clr = _render->m_view[view].m_clear;
for (uint32_t ii = 0; ii < numMrt; ++ii)
{
if (BGFX_CLEAR_COLOR & clr.m_flags)
@@ -10738,10 +10750,16 @@ VK_DESTROY
vkCmdBeginRenderPass(m_commandBuffer, &rpbi, VK_SUBPASS_CONTENTS_INLINE);
beginRenderPass = true;
if (partialColorClear)
{
Clear colorClr = clr;
colorClr.m_flags &= ~(BGFX_CLEAR_DEPTH|BGFX_CLEAR_STENCIL);
clearQuad(renderArea, colorClr, _render->m_colorPalette);
}
}
else
{
const Clear& clr = _render->m_view[view].m_clear;
if (BGFX_CLEAR_NONE != clr.m_flags)
{
Rect clearRect;
+20 -4
View File
@@ -2567,6 +2567,12 @@ WGPU_IMPORT
, true
, renderBind
, true
, false
, 0
, 0.0f
, 0.0f
, UINT32_MAX
, uint8_t(~_clear.getColorSkipMask(numMrt) )
);
const ProgramWGPU& program = m_program[_clearQuad.m_program[numMrt-1].idx];
@@ -3206,6 +3212,7 @@ WGPU_IMPORT
, float _slopeScale = 0.0f
, float _biasClamp = 0.0f
, uint32_t _sampleMask = UINT32_MAX
, uint8_t _mrtMask = UINT8_MAX
)
{
const ProgramWGPU& program = m_program[_program.idx];
@@ -3310,6 +3317,7 @@ WGPU_IMPORT
murmur.add(_slopeScale);
murmur.add(_biasClamp);
murmur.add(_sampleMask);
murmur.add(_mrtMask);
const uint32_t hash = murmur.end();
RenderPipeline* renderPipeline = m_renderPipelineCache.find(hash);
@@ -3458,7 +3466,7 @@ WGPU_IMPORT
const bool hasFragmentShader = NULL != program.m_fsh;
const bool bgra8Storage = hasBgra8Storage(entries, entryCount);
const uint32_t targetCount = hasFragmentShader ? setColorTargetState(blendState, colorTragetState, fb, _state, _rgba) : 0;
const uint32_t targetCount = hasFragmentShader ? setColorTargetState(blendState, colorTragetState, fb, _state, _rgba, _mrtMask) : 0;
if (NULL != depthStencilTextureView)
{
@@ -3707,7 +3715,7 @@ WGPU_IMPORT
}
}
uint32_t setColorTargetState(WGPUBlendState* _outBlendState, WGPUColorTargetState* _outColorTargetState, const FrameBufferWGPU& _fb, uint64_t _state, uint32_t _rgba = 0)
uint32_t setColorTargetState(WGPUBlendState* _outBlendState, WGPUColorTargetState* _outColorTargetState, const FrameBufferWGPU& _fb, uint64_t _state, uint32_t _rgba = 0, uint8_t _mrtMask = UINT8_MAX)
{
if (0 == _fb.m_numColorAttachments
&& !_fb.isSwapChain() )
@@ -3807,7 +3815,10 @@ WGPU_IMPORT
.nextInChain = NULL,
.format = format,
.blend = blend,
.writeMask = writeMask,
.writeMask = 0 != (_mrtMask & (1<<ii) )
? writeMask
: WGPUColorWriteMask_None
,
};
}
@@ -7098,6 +7109,8 @@ WGPU_IMPORT
: fb.m_numColorAttachments
;
const uint8_t colorSkipMask = clr.getColorSkipMask(numColorAttachments);
isFrameBufferValid = false
|| 0 != numColorAttachments
|| NULL != depthStencilTextureView
@@ -7135,7 +7148,10 @@ WGPU_IMPORT
.view = colorTextureView,
.depthSlice = WGPU_DEPTH_SLICE_UNDEFINED,
.resolveTarget = resolveTextureView,
.loadOp = clearWhole && (BGFX_CLEAR_COLOR & clr.m_flags)
.loadOp = true
&& clearWhole
&& 0 != (BGFX_CLEAR_COLOR & clr.m_flags)
&& 0 == (colorSkipMask & (1<<ii) )
? WGPULoadOp_Clear
: WGPULoadOp_Load
,