Skip to content

Commit 1aa0f40

Browse files
WebGPU: fixed issue with debug groups (close #627)
Added debug group unit tests
1 parent c409179 commit 1aa0f40

File tree

3 files changed

+304
-7
lines changed

3 files changed

+304
-7
lines changed

Graphics/GraphicsEngineWebGPU/include/DeviceContextWebGPUImpl.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ class DeviceContextWebGPUImpl final : public DeviceContextBase<EngineWebGPUImplT
603603
MappedTexturesCache m_MappedTextures;
604604
MappedBuffersCache m_MappedBuffers;
605605
DebugGroupStack m_DebugGroupsStack;
606-
DebugGroupStack m_PendingDebugGroups;
606+
DebugGroupStack m_EndedDebugGroups;
607607
OcclusionQueryStack m_OcclusionQueriesStack;
608608
PendingStagingResources m_PendingStagingReads;
609609
PendingStagingResources m_PendingStagingWrites;

Graphics/GraphicsEngineWebGPU/src/DeviceContextWebGPUImpl.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ void DeviceContextWebGPUImpl::SetRenderTargetsExt(const SetRenderTargetsAttribs&
347347

348348
if (TDeviceContextBase::SetRenderTargets(Attribs) || (Attribs.NumRenderTargets == 0 && Attribs.pDepthStencil == nullptr))
349349
{
350-
EndCommandEncoders(COMMAND_ENCODER_FLAG_RENDER);
350+
EndCommandEncoders();
351351
SetViewports(1, nullptr, 0, 0);
352352
}
353353
}
@@ -1616,14 +1616,14 @@ void DeviceContextWebGPUImpl::EndDebugGroup()
16161616
if (DebugGroupType == DEBUG_GROUP_TYPE_RENDER)
16171617
wgpuRenderPassEncoderPopDebugGroup(GetRenderPassCommandEncoder());
16181618
else
1619-
m_PendingDebugGroups.push_back(DebugGroupType);
1619+
m_EndedDebugGroups.push_back(DebugGroupType);
16201620
}
16211621
else if (m_wgpuComputePassEncoder)
16221622
{
16231623
if (DebugGroupType == DEBUG_GROUP_TYPE_COMPUTE)
16241624
wgpuComputePassEncoderPopDebugGroup(GetComputePassCommandEncoder());
16251625
else
1626-
m_PendingDebugGroups.push_back(DebugGroupType);
1626+
m_EndedDebugGroups.push_back(DebugGroupType);
16271627
}
16281628
else
16291629
{
@@ -1811,11 +1811,11 @@ void DeviceContextWebGPUImpl::EndCommandEncoders(Uint32 EncoderFlags)
18111811
}
18121812
}
18131813

1814-
while (!m_PendingDebugGroups.empty())
1814+
while (!m_EndedDebugGroups.empty())
18151815
{
1816-
if (m_PendingDebugGroups.back() != DEBUG_GROUP_TYPE_NULL)
1816+
if (m_EndedDebugGroups.back() != DEBUG_GROUP_TYPE_NULL)
18171817
wgpuCommandEncoderPopDebugGroup(m_wgpuCommandEncoder);
1818-
m_PendingDebugGroups.pop_back();
1818+
m_EndedDebugGroups.pop_back();
18191819
}
18201820
}
18211821

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
/*
2+
* Copyright 2025 Diligent Graphics LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
* In no event and under no legal theory, whether in tort (including negligence),
17+
* contract, or otherwise, unless required by applicable law (such as deliberate
18+
* and grossly negligent acts) or agreed to in writing, shall any Contributor be
19+
* liable for any damages, including any direct, indirect, special, incidental,
20+
* or consequential damages of any character arising as a result of this License or
21+
* out of the use or inability to use the software (including but not limited to damages
22+
* for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23+
* all other commercial damages or losses), even if such Contributor has been advised
24+
* of the possibility of such damages.
25+
*/
26+
27+
#include "GPUTestingEnvironment.hpp"
28+
#include "ScopedDebugGroup.hpp"
29+
30+
#include "gtest/gtest.h"
31+
32+
using namespace Diligent;
33+
using namespace Diligent::Testing;
34+
35+
namespace
36+
{
37+
38+
namespace HLSL
39+
{
40+
constexpr char VS[] =
41+
R"(float4 main() : SV_Position
42+
{
43+
return float4(0.0, 0.0, 0.0, 1.0);
44+
}
45+
)";
46+
47+
constexpr char PS[] =
48+
R"(float4 main() : SV_Target
49+
{
50+
return float4(1.0, 0.0, 0.0, 1.0);
51+
}
52+
)";
53+
54+
constexpr char CS[] =
55+
R"(
56+
[numthreads(16, 16, 1)]
57+
void main(uint3 DTid : SV_DispatchThreadID)
58+
{
59+
}
60+
)";
61+
} // namespace HLSL
62+
63+
class DebugGroupTest : public ::testing::Test
64+
{
65+
protected:
66+
static void SetUpTestSuite()
67+
{
68+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
69+
IRenderDevice* pDevice = pEnv->GetDevice();
70+
ISwapChain* pSwapChain = pEnv->GetSwapChain();
71+
const SwapChainDesc& SCDesc = pSwapChain->GetDesc();
72+
73+
ShaderCreateInfo ShaderCI;
74+
ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_HLSL;
75+
ShaderCI.ShaderCompiler = pEnv->GetDefaultCompiler(ShaderCI.SourceLanguage);
76+
ShaderCI.EntryPoint = "main";
77+
78+
ShaderCI.Desc = {"DebugGroupTest - VS", SHADER_TYPE_VERTEX, true};
79+
ShaderCI.Source = HLSL::VS;
80+
pDevice->CreateShader(ShaderCI, &m_Resources.pVS);
81+
ASSERT_NE(m_Resources.pVS, nullptr);
82+
83+
ShaderCI.Desc = {"DebugGroupTest - PS", SHADER_TYPE_PIXEL, true};
84+
ShaderCI.Source = HLSL::PS;
85+
pDevice->CreateShader(ShaderCI, &m_Resources.pPS);
86+
ASSERT_NE(m_Resources.pPS, nullptr);
87+
88+
ShaderCI.Desc = {"DebugGroupTest - CS", SHADER_TYPE_COMPUTE, true};
89+
ShaderCI.Source = HLSL::CS;
90+
pDevice->CreateShader(ShaderCI, &m_Resources.pCS);
91+
ASSERT_NE(m_Resources.pCS, nullptr);
92+
93+
{
94+
GraphicsPipelineStateCreateInfo PSOCreateInfo{"DebugGroupTest - Graphics PSO"};
95+
PSOCreateInfo.pVS = m_Resources.pVS;
96+
PSOCreateInfo.pPS = m_Resources.pPS;
97+
PSOCreateInfo.GraphicsPipeline.NumRenderTargets = 1;
98+
PSOCreateInfo.GraphicsPipeline.RTVFormats[0] = SCDesc.ColorBufferFormat;
99+
PSOCreateInfo.GraphicsPipeline.DSVFormat = SCDesc.DepthBufferFormat;
100+
pDevice->CreateGraphicsPipelineState(PSOCreateInfo, &m_Resources.pGraphicsPSO);
101+
ASSERT_NE(m_Resources.pGraphicsPSO, nullptr);
102+
m_Resources.pGraphicsPSO->CreateShaderResourceBinding(&m_Resources.pGraphicsSRB, true);
103+
ASSERT_NE(m_Resources.pGraphicsSRB, nullptr);
104+
}
105+
106+
{
107+
ComputePipelineStateCreateInfo PSOCreateInfo{"DebugGroupTest - Compute CS"};
108+
PSOCreateInfo.pCS = m_Resources.pCS;
109+
pDevice->CreateComputePipelineState(PSOCreateInfo, &m_Resources.pComputePSO);
110+
ASSERT_NE(m_Resources.pComputePSO, nullptr);
111+
m_Resources.pComputePSO->CreateShaderResourceBinding(&m_Resources.pComputeSRB, true);
112+
ASSERT_NE(m_Resources.pComputeSRB, nullptr);
113+
}
114+
}
115+
116+
static void TearDownTestSuite()
117+
{
118+
m_Resources = {};
119+
}
120+
121+
static void Draw()
122+
{
123+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
124+
IDeviceContext* pCtx = pEnv->GetDeviceContext();
125+
ISwapChain* pSwapChain = pEnv->GetSwapChain();
126+
127+
constexpr float DebugGroupColor[] = {1, 0, 0, 0};
128+
ScopedDebugGroup DebugGroup{pCtx, "DebugGroupTest - Draw", DebugGroupColor};
129+
130+
ITextureView* RTVs[] = {pSwapChain->GetCurrentBackBufferRTV()};
131+
pCtx->SetRenderTargets(1, RTVs, pSwapChain->GetDepthBufferDSV(), RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
132+
pCtx->SetPipelineState(m_Resources.pGraphicsPSO);
133+
pCtx->CommitShaderResources(m_Resources.pGraphicsSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
134+
pCtx->Draw({3, DRAW_FLAG_VERIFY_ALL});
135+
}
136+
137+
static void DispatchCompute()
138+
{
139+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
140+
IDeviceContext* pCtx = pEnv->GetDeviceContext();
141+
142+
constexpr float DebugGroupColor[] = {0, 1, 0, 0};
143+
ScopedDebugGroup DebugGroup{pCtx, "DebugGroupTest - Compute", DebugGroupColor};
144+
145+
pCtx->SetPipelineState(m_Resources.pComputePSO);
146+
pCtx->CommitShaderResources(m_Resources.pComputeSRB, RESOURCE_STATE_TRANSITION_MODE_TRANSITION);
147+
pCtx->DispatchCompute({1, 1, 1});
148+
}
149+
150+
struct Resources
151+
{
152+
RefCntAutoPtr<IShader> pVS;
153+
RefCntAutoPtr<IShader> pPS;
154+
RefCntAutoPtr<IShader> pCS;
155+
RefCntAutoPtr<IPipelineState> pGraphicsPSO;
156+
RefCntAutoPtr<IShaderResourceBinding> pGraphicsSRB;
157+
RefCntAutoPtr<IPipelineState> pComputePSO;
158+
RefCntAutoPtr<IShaderResourceBinding> pComputeSRB;
159+
};
160+
static Resources m_Resources;
161+
};
162+
DebugGroupTest::Resources DebugGroupTest::m_Resources;
163+
164+
TEST_F(DebugGroupTest, Empty)
165+
{
166+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
167+
IDeviceContext* pCtx = pEnv->GetDeviceContext();
168+
pCtx->Flush();
169+
170+
{
171+
GPUTestingEnvironment::ScopedReset EnvironmentAutoReset;
172+
constexpr float DebugGroupColor[] = {0, 0, 1, 0};
173+
ScopedDebugGroup DebugGroup{pCtx, "DebugGroupTest - Empty", DebugGroupColor};
174+
}
175+
176+
pCtx->Flush();
177+
}
178+
179+
TEST_F(DebugGroupTest, Draw)
180+
{
181+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
182+
IDeviceContext* pCtx = pEnv->GetDeviceContext();
183+
pCtx->Flush();
184+
185+
GPUTestingEnvironment::ScopedReset EnvironmentAutoReset;
186+
187+
Draw();
188+
}
189+
190+
TEST_F(DebugGroupTest, Compute)
191+
{
192+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
193+
IDeviceContext* pCtx = pEnv->GetDeviceContext();
194+
pCtx->Flush();
195+
196+
GPUTestingEnvironment::ScopedReset EnvironmentAutoReset;
197+
198+
DispatchCompute();
199+
}
200+
201+
TEST_F(DebugGroupTest, DrawAfterCompute)
202+
{
203+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
204+
IDeviceContext* pCtx = pEnv->GetDeviceContext();
205+
pCtx->Flush();
206+
207+
GPUTestingEnvironment::ScopedReset EnvironmentAutoReset;
208+
209+
DispatchCompute();
210+
Draw();
211+
DispatchCompute();
212+
Draw();
213+
}
214+
215+
TEST_F(DebugGroupTest, ComputeAfterDraw)
216+
{
217+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
218+
IDeviceContext* pCtx = pEnv->GetDeviceContext();
219+
pCtx->Flush();
220+
221+
GPUTestingEnvironment::ScopedReset EnvironmentAutoReset;
222+
223+
Draw();
224+
DispatchCompute();
225+
Draw();
226+
DispatchCompute();
227+
}
228+
229+
TEST_F(DebugGroupTest, NestedDraw)
230+
{
231+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
232+
IDeviceContext* pCtx = pEnv->GetDeviceContext();
233+
pCtx->Flush();
234+
235+
GPUTestingEnvironment::ScopedReset EnvironmentAutoReset;
236+
237+
constexpr float DebugGroupColor[] = {0, 0, 1, 0};
238+
ScopedDebugGroup DebugGroup{pCtx, "DebugGroupTest - NestedDraw", DebugGroupColor};
239+
Draw();
240+
Draw();
241+
Draw();
242+
}
243+
244+
TEST_F(DebugGroupTest, NestedCompute)
245+
{
246+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
247+
IDeviceContext* pCtx = pEnv->GetDeviceContext();
248+
pCtx->Flush();
249+
250+
GPUTestingEnvironment::ScopedReset EnvironmentAutoReset;
251+
252+
constexpr float DebugGroupColor[] = {0, 0, 1, 0};
253+
ScopedDebugGroup DebugGroup{pCtx, "DebugGroupTest - NestedCompute", DebugGroupColor};
254+
DispatchCompute();
255+
DispatchCompute();
256+
DispatchCompute();
257+
}
258+
259+
TEST_F(DebugGroupTest, NestedDrawAfterCompute)
260+
{
261+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
262+
IDeviceContext* pCtx = pEnv->GetDeviceContext();
263+
pCtx->Flush();
264+
265+
GPUTestingEnvironment::ScopedReset EnvironmentAutoReset;
266+
267+
constexpr float DebugGroupColor[] = {0, 0, 1, 0};
268+
ScopedDebugGroup DebugGroup{pCtx, "DebugGroupTest - NestedDrawAfterCompute", DebugGroupColor};
269+
DispatchCompute();
270+
Draw();
271+
{
272+
ScopedDebugGroup DebugGroup2{pCtx, "DebugGroupTest - NestedDrawAfterCompute 2", DebugGroupColor};
273+
DispatchCompute();
274+
Draw();
275+
}
276+
}
277+
278+
TEST_F(DebugGroupTest, NestedComputeAfterDraw)
279+
{
280+
GPUTestingEnvironment* pEnv = GPUTestingEnvironment::GetInstance();
281+
IDeviceContext* pCtx = pEnv->GetDeviceContext();
282+
pCtx->Flush();
283+
284+
GPUTestingEnvironment::ScopedReset EnvironmentAutoReset;
285+
286+
constexpr float DebugGroupColor[] = {0, 0, 1, 0};
287+
ScopedDebugGroup DebugGroup{pCtx, "DebugGroupTest - NestedComputeAfterDraw", DebugGroupColor};
288+
Draw();
289+
DispatchCompute();
290+
{
291+
ScopedDebugGroup DebugGroup2{pCtx, "DebugGroupTest - NestedComputeAfterDraw 2", DebugGroupColor};
292+
Draw();
293+
DispatchCompute();
294+
}
295+
}
296+
297+
} // namespace

0 commit comments

Comments
 (0)