Skip to content

Commit e023161

Browse files
WebGPU: Simplify SwapChainWebGPUImpl logic
1 parent 017f804 commit e023161

File tree

2 files changed

+104
-47
lines changed

2 files changed

+104
-47
lines changed

Graphics/GraphicsEngineWebGPU/include/SwapChainWebGPUImpl.hpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,21 +81,19 @@ class SwapChainWebGPUImpl final : public SwapChainBase<ISwapChainWebGPU>
8181

8282
void ConfigureSurface();
8383

84-
void CreateBuffersAndViews();
84+
void CreateDepthBufferView();
85+
86+
void RecreateSwapChain();
8587

8688
void ReleaseSwapChainResources();
8789

88-
void RecreateSwapChain();
90+
WGPUSurfaceGetCurrentTextureStatus AcquireSurfaceTexture();
8991

9092
private:
91-
class PresentCommand;
92-
9393
NativeWindow m_NativeWindow;
9494
WebGPUSurfaceWrapper m_wgpuSurface;
9595
RefCntAutoPtr<ITextureViewWebGPU> m_pBackBufferRTV;
96-
RefCntAutoPtr<ITextureViewWebGPU> m_pBackBufferSRV;
9796
RefCntAutoPtr<ITextureViewWebGPU> m_pDepthBufferDSV;
98-
std::unique_ptr<PresentCommand> m_pCmdPresent;
9997
bool m_VSyncEnabled = true;
10098
};
10199

Graphics/GraphicsEngineWebGPU/src/SwapChainWebGPUImpl.cpp

Lines changed: 100 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#include "TextureViewWebGPU.h"
3333
#include "WebGPUTypeConversions.hpp"
3434
#include "WebGPUStubs.hpp"
35+
#include "webgpu/webgpu.h"
36+
#include <cstdint>
3537

3638
#ifdef PLATFORM_WIN32
3739
# include <Windows.h>
@@ -117,6 +119,7 @@ WGPUTextureFormat WGPUConvertUnormToSRGB(WGPUTextureFormat Format)
117119

118120
} // namespace
119121

122+
/*
120123
class SwapChainWebGPUImpl::PresentCommand
121124
{
122125
public:
@@ -318,11 +321,7 @@ class SwapChainWebGPUImpl::PresentCommand
318321
319322
wgpuQueueSubmit(pDeviceContext->GetWebGPUQueue(), 1, &wgpuCmdBuffer.Get());
320323
321-
#if PLATFORM_WEB
322-
emscripten_request_animation_frame([](double Time, void* pUserData) -> EM_BOOL { return EM_FALSE; }, nullptr);
323-
#else
324-
wgpuSurfacePresent(pSwapChain->GetWebGPUSurface());
325-
#endif
324+
326325
327326
return wgpuSurfaceTexture.status;
328327
}
@@ -339,6 +338,7 @@ class SwapChainWebGPUImpl::PresentCommand
339338
WebGPUPipelineLayoutWrapper m_wgpuPipelineLayout;
340339
WebGPURenderPipelineWrapper m_wgpuRenderPipeline;
341340
};
341+
*/
342342

343343
SwapChainWebGPUImpl::SwapChainWebGPUImpl(IReferenceCounters* pRefCounters,
344344
const SwapChainDesc& SCDesc,
@@ -353,8 +353,7 @@ SwapChainWebGPUImpl::SwapChainWebGPUImpl(IReferenceCounters* pRefCounters,
353353
pDeviceContext,
354354
SCDesc
355355
},
356-
m_NativeWindow{Window},
357-
m_pCmdPresent{std::make_unique<PresentCommand>(pRenderDevice)}
356+
m_NativeWindow{Window}
358357
// clang-format on
359358
{
360359
if (m_DesiredPreTransform != SURFACE_TRANSFORM_OPTIMAL && m_DesiredPreTransform != SURFACE_TRANSFORM_IDENTITY)
@@ -368,7 +367,14 @@ SwapChainWebGPUImpl::SwapChainWebGPUImpl(IReferenceCounters* pRefCounters,
368367

369368
CreateSurface();
370369
ConfigureSurface();
371-
CreateBuffersAndViews();
370+
CreateDepthBufferView();
371+
372+
WGPUSurfaceGetCurrentTextureStatus wgpuStatus = AcquireSurfaceTexture();
373+
if (wgpuStatus != WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal &&
374+
wgpuStatus != WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal)
375+
{
376+
LOG_ERROR_MESSAGE("Failed to acquire the initial swap chain surface texture");
377+
}
372378
}
373379

374380
SwapChainWebGPUImpl::~SwapChainWebGPUImpl() = default;
@@ -387,9 +393,15 @@ void SwapChainWebGPUImpl::Present(Uint32 SyncInterval)
387393
}
388394

389395
DeviceContextWebGPUImpl* pImmediateCtxWebGPU = pDeviceContext.RawPtr<DeviceContextWebGPUImpl>();
390-
391396
pImmediateCtxWebGPU->Flush();
392-
WGPUSurfaceGetCurrentTextureStatus SurfaceStatus = m_pCmdPresent->Execute(m_pBackBufferSRV, this, pImmediateCtxWebGPU);
397+
398+
#if PLATFORM_WEB
399+
emscripten_request_animation_frame([](double Time, void* pUserData) -> EM_BOOL { return EM_FALSE; }, nullptr);
400+
#else
401+
wgpuSurfacePresent(m_wgpuSurface);
402+
#endif
403+
404+
WGPUSurfaceGetCurrentTextureStatus wgpuStatus = AcquireSurfaceTexture();
393405

394406
if (m_SwapChainDesc.IsPrimary)
395407
{
@@ -398,8 +410,8 @@ void SwapChainWebGPUImpl::Present(Uint32 SyncInterval)
398410
}
399411

400412
const bool EnableVSync = SyncInterval != 0;
401-
if (SurfaceStatus == WGPUSurfaceGetCurrentTextureStatus_Outdated ||
402-
SurfaceStatus == WGPUSurfaceGetCurrentTextureStatus_Lost ||
413+
if (wgpuStatus == WGPUSurfaceGetCurrentTextureStatus_Outdated ||
414+
wgpuStatus == WGPUSurfaceGetCurrentTextureStatus_Lost ||
403415
m_VSyncEnabled != EnableVSync)
404416
{
405417
m_VSyncEnabled = EnableVSync;
@@ -436,9 +448,9 @@ void SwapChainWebGPUImpl::CreateSurface()
436448
wgpuSurfaceNativeDesc.hinstance = GetModuleHandle(nullptr);
437449
#elif PLATFORM_LINUX
438450
WGPUSurfaceSourceXCBWindow wgpuSurfaceNativeDesc{};
439-
wgpuSurfaceNativeDesc.chain = {nullptr, WGPUSType_SurfaceSourceXCBWindow};
451+
wgpuSurfaceNativeDesc.chain = {nullptr, WGPUSType_SurfaceSourceXCBWindow};
440452
wgpuSurfaceNativeDesc.connection = m_NativeWindow.pXCBConnection;
441-
wgpuSurfaceNativeDesc.window = m_NativeWindow.WindowId;
453+
wgpuSurfaceNativeDesc.window = m_NativeWindow.WindowId;
442454
#elif PLATFROM_MACOS
443455
WGPUSurfaceSourceMetalLayer wgpuSurfaceNativeDesc{};
444456
wgpuSurfaceNativeDesc.chain = {nullptr, WGPUSType_SurfaceSourceMetalLayer};
@@ -512,6 +524,23 @@ void SwapChainWebGPUImpl::ConfigureSurface()
512524
return Result;
513525
};
514526

527+
auto SelectFormat = [&](TEXTURE_FORMAT Format) {
528+
WGPUTextureFormat wgpuFormat = TextureFormatToWGPUFormat(SRGBFormatToUnorm(Format));
529+
530+
const WGPUTextureFormat* FindBegin = wgpuSurfaceCapabilities.formats;
531+
const WGPUTextureFormat* FindEnd = wgpuSurfaceCapabilities.formats + wgpuSurfaceCapabilities.formatCount;
532+
533+
if (std::find(FindBegin, FindEnd, wgpuFormat) != FindEnd)
534+
{
535+
return wgpuFormat;
536+
}
537+
else
538+
{
539+
LOG_ERROR_MESSAGE("Failed to find the requested format in the surface capabilities. Using the first available format instead.");
540+
return wgpuSurfaceCapabilities.formats[0];
541+
}
542+
};
543+
515544
if (m_SwapChainDesc.Width == 0 || m_SwapChainDesc.Height == 0)
516545
{
517546
#if PLATFORM_WIN32
@@ -521,64 +550,96 @@ void SwapChainWebGPUImpl::ConfigureSurface()
521550
m_SwapChainDesc.Width = WindowRect.right - WindowRect.left;
522551
m_SwapChainDesc.Height = WindowRect.bottom - WindowRect.top;
523552
#elif PLATFORM_WEB
524-
int32_t CanvasWidth = 0;
553+
int32_t CanvasWidth = 0;
525554
int32_t CanvasHeight = 0;
526555
emscripten_get_canvas_element_size(m_NativeWindow.pCanvasId, &CanvasWidth, &CanvasHeight);
527556

528-
m_SwapChainDesc.Width = static_cast<Uint32>(CanvasWidth);
557+
m_SwapChainDesc.Width = static_cast<Uint32>(CanvasWidth);
529558
m_SwapChainDesc.Height = static_cast<Uint32>(CanvasHeight);
530559
#endif
531560

532561
m_SwapChainDesc.Width = (std::max)(m_SwapChainDesc.Width, 1u);
533562
m_SwapChainDesc.Height = (std::max)(m_SwapChainDesc.Height, 1u);
534563
}
535564

536-
const WGPUTextureFormat wgpuPreferredFormat = wgpuSurfaceCapabilities.formats[0];
565+
const WGPUTextureFormat wgpuPreferredFormat = SelectFormat(m_SwapChainDesc.ColorBufferFormat);
537566

538-
WGPUTextureFormat wgpuRTVFormats[] = {
539-
wgpuPreferredFormat,
540-
WGPUConvertUnormToSRGB(wgpuPreferredFormat),
541-
};
567+
std::vector<WGPUTextureFormat> wgpuRTVFormats;
568+
wgpuRTVFormats.push_back(wgpuPreferredFormat);
569+
if (IsSRGBFormat(m_SwapChainDesc.ColorBufferFormat))
570+
wgpuRTVFormats.push_back(WGPUConvertUnormToSRGB(wgpuPreferredFormat));
571+
572+
WGPUSurfaceColorManagement wgpuColorManagement{};
573+
wgpuColorManagement.chain.sType = WGPUSType_SurfaceColorManagement;
574+
wgpuColorManagement.colorSpace = WGPUPredefinedColorSpace_DisplayP3;
575+
wgpuColorManagement.toneMappingMode = WGPUToneMappingMode_Extended;
542576

543577
WGPUSurfaceConfiguration wgpuSurfaceConfig{};
544-
wgpuSurfaceConfig.nextInChain = nullptr;
578+
wgpuSurfaceConfig.nextInChain = &wgpuColorManagement.chain;
545579
wgpuSurfaceConfig.device = pRenderDeviceWebGPU->GetWebGPUDevice();
546580
wgpuSurfaceConfig.usage = SelectUsage(m_SwapChainDesc.Usage);
547581
wgpuSurfaceConfig.width = m_SwapChainDesc.Width;
548582
wgpuSurfaceConfig.height = m_SwapChainDesc.Height;
549583
wgpuSurfaceConfig.format = wgpuPreferredFormat;
550584
wgpuSurfaceConfig.presentMode = SelectPresentMode(m_VSyncEnabled);
551585
wgpuSurfaceConfig.alphaMode = WGPUCompositeAlphaMode_Auto;
552-
wgpuSurfaceConfig.viewFormats = wgpuRTVFormats;
553-
wgpuSurfaceConfig.viewFormatCount = _countof(wgpuRTVFormats);
586+
wgpuSurfaceConfig.viewFormats = wgpuRTVFormats.data();
587+
wgpuSurfaceConfig.viewFormatCount = static_cast<uint32_t>(wgpuRTVFormats.size());
554588

555589
wgpuSurfaceConfigure(m_wgpuSurface, &wgpuSurfaceConfig);
556590
wgpuSurfaceCapabilitiesFreeMembers(wgpuSurfaceCapabilities);
557591
}
558592

559-
void SwapChainWebGPUImpl::CreateBuffersAndViews()
593+
WGPUSurfaceGetCurrentTextureStatus SwapChainWebGPUImpl::AcquireSurfaceTexture()
560594
{
595+
m_pBackBufferRTV.Release();
596+
597+
WGPUSurfaceTexture wgpuSurfaceTexture{};
598+
wgpuSurfaceGetCurrentTexture(m_wgpuSurface, &wgpuSurfaceTexture);
599+
600+
WGPUTextureFormat wgpuFormat = wgpuTextureGetFormat(wgpuSurfaceTexture.texture);
601+
uint32_t wgpuSurfaceWidth = wgpuTextureGetWidth(wgpuSurfaceTexture.texture);
602+
uint32_t wgpuSurfaceHeight = wgpuTextureGetHeight(wgpuSurfaceTexture.texture);
603+
561604
TextureDesc BackBufferDesc{};
605+
BackBufferDesc.Name = "Main back buffer";
562606
BackBufferDesc.Type = RESOURCE_DIM_TEX_2D;
563-
BackBufferDesc.Width = m_SwapChainDesc.Width;
564-
BackBufferDesc.Height = m_SwapChainDesc.Height;
565-
BackBufferDesc.Format = m_SwapChainDesc.ColorBufferFormat;
566-
BackBufferDesc.SampleCount = 1;
607+
BackBufferDesc.Width = wgpuSurfaceWidth;
608+
BackBufferDesc.Height = wgpuSurfaceHeight;
609+
BackBufferDesc.Format = WGPUFormatToTextureFormat(wgpuFormat);
567610
BackBufferDesc.Usage = USAGE_DEFAULT;
568-
BackBufferDesc.BindFlags = BIND_SHADER_RESOURCE | BIND_RENDER_TARGET;
569-
BackBufferDesc.Name = "Main back buffer";
611+
BackBufferDesc.BindFlags = BIND_RENDER_TARGET;
570612

571-
RefCntAutoPtr<ITexture> pBackBufferTex;
572-
m_pRenderDevice->CreateTexture(BackBufferDesc, nullptr, &pBackBufferTex);
573-
m_pBackBufferRTV = RefCntAutoPtr<ITextureViewWebGPU>{pBackBufferTex->GetDefaultView(TEXTURE_VIEW_RENDER_TARGET), IID_TextureViewWebGPU};
574-
m_pBackBufferSRV = RefCntAutoPtr<ITextureViewWebGPU>{pBackBufferTex->GetDefaultView(TEXTURE_VIEW_SHADER_RESOURCE), IID_TextureViewWebGPU};
613+
RefCntAutoPtr<ITexture> pBackBufferTexture;
614+
m_pRenderDevice.RawPtr<RenderDeviceWebGPUImpl>()->CreateTextureFromWebGPUTexture(wgpuSurfaceTexture.texture, BackBufferDesc, RESOURCE_STATE_UNDEFINED, &pBackBufferTexture);
575615

616+
if (IsSRGBFormat(m_SwapChainDesc.ColorBufferFormat))
617+
{
618+
TextureViewDesc BackBufferRTVDesc{};
619+
BackBufferRTVDesc.ViewType = TEXTURE_VIEW_RENDER_TARGET;
620+
BackBufferRTVDesc.Format = m_SwapChainDesc.ColorBufferFormat;
621+
622+
RefCntAutoPtr<ITextureView> pBackBufferRTV;
623+
pBackBufferTexture->CreateView(BackBufferRTVDesc, &pBackBufferRTV);
624+
m_pBackBufferRTV = RefCntAutoPtr<ITextureViewWebGPU>{pBackBufferRTV, IID_TextureViewWebGPU};
625+
}
626+
else
627+
{
628+
m_pBackBufferRTV = RefCntAutoPtr<ITextureViewWebGPU>{pBackBufferTexture->GetDefaultView(TEXTURE_VIEW_RENDER_TARGET), IID_TextureViewWebGPU};
629+
}
630+
631+
return wgpuSurfaceTexture.status;
632+
}
633+
634+
void SwapChainWebGPUImpl::CreateDepthBufferView()
635+
{
576636
if (m_SwapChainDesc.DepthBufferFormat != TEX_FORMAT_UNKNOWN)
577637
{
578638
TextureDesc DepthBufferDesc{};
639+
DepthBufferDesc.Name = "Main depth buffer";
579640
DepthBufferDesc.Type = RESOURCE_DIM_TEX_2D;
580-
DepthBufferDesc.Width = BackBufferDesc.Width;
581-
DepthBufferDesc.Height = BackBufferDesc.Height;
641+
DepthBufferDesc.Width = m_SwapChainDesc.Width;
642+
DepthBufferDesc.Height = m_SwapChainDesc.Height;
582643
DepthBufferDesc.Format = m_SwapChainDesc.DepthBufferFormat;
583644
DepthBufferDesc.SampleCount = 1;
584645
DepthBufferDesc.Usage = USAGE_DEFAULT;
@@ -587,7 +648,7 @@ void SwapChainWebGPUImpl::CreateBuffersAndViews()
587648
DepthBufferDesc.ClearValue.Format = DepthBufferDesc.Format;
588649
DepthBufferDesc.ClearValue.DepthStencil.Depth = m_SwapChainDesc.DefaultDepthValue;
589650
DepthBufferDesc.ClearValue.DepthStencil.Stencil = m_SwapChainDesc.DefaultStencilValue;
590-
DepthBufferDesc.Name = "Main depth buffer";
651+
591652
RefCntAutoPtr<ITexture> pDepthBufferTex;
592653
m_pRenderDevice->CreateTexture(DepthBufferDesc, nullptr, &pDepthBufferTex);
593654
m_pDepthBufferDSV = RefCntAutoPtr<ITextureViewWebGPU>{pDepthBufferTex->GetDefaultView(TEXTURE_VIEW_DEPTH_STENCIL), IID_TextureViewWebGPU};
@@ -599,8 +660,6 @@ void SwapChainWebGPUImpl::ReleaseSwapChainResources()
599660
if (!m_wgpuSurface)
600661
return;
601662

602-
m_pCmdPresent->ReleaseSwapChainResources();
603-
m_pBackBufferSRV.Release();
604663
m_pBackBufferRTV.Release();
605664
m_pDepthBufferDSV.Release();
606665
}
@@ -611,7 +670,7 @@ void SwapChainWebGPUImpl::RecreateSwapChain()
611670
{
612671
ReleaseSwapChainResources();
613672
ConfigureSurface();
614-
CreateBuffersAndViews();
673+
CreateDepthBufferView();
615674
}
616675
catch (const std::runtime_error&)
617676
{

0 commit comments

Comments
 (0)