diff --git a/Graphics/GraphicsEngineWebGPU/include/RenderDeviceWebGPUImpl.hpp b/Graphics/GraphicsEngineWebGPU/include/RenderDeviceWebGPUImpl.hpp index 1f17be964..25f618096 100644 --- a/Graphics/GraphicsEngineWebGPU/include/RenderDeviceWebGPUImpl.hpp +++ b/Graphics/GraphicsEngineWebGPU/include/RenderDeviceWebGPUImpl.hpp @@ -1,5 +1,5 @@ /* - * Copyright 2023-2024 Diligent Graphics LLC + * Copyright 2023-2025 Diligent Graphics LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -52,14 +52,18 @@ class RenderDeviceWebGPUImpl final : public RenderDeviceBase; - RenderDeviceWebGPUImpl(IReferenceCounters* pRefCounters, - IMemoryAllocator& RawMemAllocator, - IEngineFactory* pEngineFactory, - const EngineWebGPUCreateInfo& EngineCI, - const GraphicsAdapterInfo& AdapterInfo, - WGPUInstance wgpuInstance, - WGPUAdapter wgpuAdapter, - WGPUDevice wgpuDevice) noexcept(false); + struct CreateInfo + { + IMemoryAllocator& RawMemAllocator; + IEngineFactory* const pEngineFactory; + const EngineWebGPUCreateInfo& EngineCI; + const GraphicsAdapterInfo& AdapterInfo; + const DeviceFeatures& EnabledFeatures; + WGPUInstance wgpuInstance = {}; + WGPUAdapter wgpuAdapter = {}; + WGPUDevice wgpuDevice = {}; + }; + RenderDeviceWebGPUImpl(IReferenceCounters* pRefCounters, const CreateInfo& CI) noexcept(false); ~RenderDeviceWebGPUImpl() override; diff --git a/Graphics/GraphicsEngineWebGPU/src/EngineFactoryWebGPU.cpp b/Graphics/GraphicsEngineWebGPU/src/EngineFactoryWebGPU.cpp index 687abe8e4..6409861be 100644 --- a/Graphics/GraphicsEngineWebGPU/src/EngineFactoryWebGPU.cpp +++ b/Graphics/GraphicsEngineWebGPU/src/EngineFactoryWebGPU.cpp @@ -237,51 +237,45 @@ static void UncapturedErrorCallback2(WGPUDevice const* device, } #endif -WebGPUDeviceWrapper CreateDeviceForAdapter(EngineWebGPUCreateInfo const& EngineCI, WGPUInstance wgpuInstance, WGPUAdapter wgpuAdapter) +WebGPUDeviceWrapper CreateDeviceForAdapter(const DeviceFeatures& Features, WGPUInstance wgpuInstance, WGPUAdapter wgpuAdapter) { WGPUSupportedLimits SupportedLimits{}; wgpuAdapterGetLimits(wgpuAdapter, &SupportedLimits); - std::vector Features{}; + std::vector wgpuFeatures{}; { - if (EngineCI.Features.DepthBiasClamp && wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_DepthClipControl)) - Features.push_back(WGPUFeatureName_DepthClipControl); - - if (EngineCI.Features.TimestampQueries && wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_TimestampQuery)) - Features.push_back(WGPUFeatureName_TimestampQuery); - - if (EngineCI.Features.TimestampQueries && wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_ChromiumExperimentalTimestampQueryInsidePasses)) - Features.push_back(WGPUFeatureName_ChromiumExperimentalTimestampQueryInsidePasses); - - if (EngineCI.Features.TextureCompressionBC && wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_TextureCompressionBC)) - Features.push_back(WGPUFeatureName_TextureCompressionBC); - - if (EngineCI.Features.TextureCompressionETC2 && wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_TextureCompressionETC2)) - Features.push_back(WGPUFeatureName_TextureCompressionETC2); + auto AddWGPUFeature = [wgpuAdapter, &wgpuFeatures](DEVICE_FEATURE_STATE FeatureState, WGPUFeatureName wgpuFeature) { + if (FeatureState && wgpuAdapterHasFeature(wgpuAdapter, wgpuFeature)) + wgpuFeatures.push_back(wgpuFeature); + }; - if (EngineCI.Features.ShaderFloat16 && wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_ShaderF16)) - Features.push_back(WGPUFeatureName_ShaderF16); + AddWGPUFeature(Features.DepthBiasClamp, WGPUFeatureName_DepthClipControl); + AddWGPUFeature(Features.TimestampQueries, WGPUFeatureName_TimestampQuery); + AddWGPUFeature(Features.DurationQueries, WGPUFeatureName_ChromiumExperimentalTimestampQueryInsidePasses); + AddWGPUFeature(Features.TextureCompressionBC, WGPUFeatureName_TextureCompressionBC); + AddWGPUFeature(Features.TextureCompressionETC2, WGPUFeatureName_TextureCompressionETC2); + AddWGPUFeature(Features.ShaderFloat16, WGPUFeatureName_ShaderF16); if (wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_Depth32FloatStencil8)) - Features.push_back(WGPUFeatureName_Depth32FloatStencil8); + wgpuFeatures.push_back(WGPUFeatureName_Depth32FloatStencil8); if (wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_Float32Filterable)) - Features.push_back(WGPUFeatureName_Float32Filterable); + wgpuFeatures.push_back(WGPUFeatureName_Float32Filterable); if (wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_IndirectFirstInstance)) - Features.push_back(WGPUFeatureName_IndirectFirstInstance); + wgpuFeatures.push_back(WGPUFeatureName_IndirectFirstInstance); if (wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_RG11B10UfloatRenderable)) - Features.push_back(WGPUFeatureName_RG11B10UfloatRenderable); + wgpuFeatures.push_back(WGPUFeatureName_RG11B10UfloatRenderable); if (wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_BGRA8UnormStorage)) - Features.push_back(WGPUFeatureName_BGRA8UnormStorage); + wgpuFeatures.push_back(WGPUFeatureName_BGRA8UnormStorage); if (wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_Unorm16TextureFormats)) - Features.push_back(WGPUFeatureName_Unorm16TextureFormats); + wgpuFeatures.push_back(WGPUFeatureName_Unorm16TextureFormats); if (wgpuAdapterHasFeature(wgpuAdapter, WGPUFeatureName_Snorm16TextureFormats)) - Features.push_back(WGPUFeatureName_Snorm16TextureFormats); + wgpuFeatures.push_back(WGPUFeatureName_Snorm16TextureFormats); } struct CallbackUserData @@ -320,8 +314,8 @@ WebGPUDeviceWrapper CreateDeviceForAdapter(EngineWebGPUCreateInfo const& EngineC WGPUDeviceDescriptor DeviceDesc{}; DeviceDesc.requiredLimits = &RequiredLimits; - DeviceDesc.requiredFeatureCount = Features.size(); - DeviceDesc.requiredFeatures = Features.data(); + DeviceDesc.requiredFeatureCount = wgpuFeatures.size(); + DeviceDesc.requiredFeatures = wgpuFeatures.data(); #if PLATFORM_EMSCRIPTEN DeviceDesc.deviceLostCallback = DeviceLostCallback; #else @@ -340,7 +334,88 @@ WebGPUDeviceWrapper CreateDeviceForAdapter(EngineWebGPUCreateInfo const& EngineC return WebGPUDeviceWrapper{UserData.Device}; } -GraphicsAdapterInfo GetGraphicsAdapterInfo(WGPUAdapter wgpuAdapter, WGPUDevice wgpuDevice = nullptr /*Hack for Emscripten*/) +bool FeatureSupported(WGPUAdapter wgpuAdapter, WGPUDevice wgpuDevice, WGPUFeatureName Feature) +{ + if (wgpuAdapter != nullptr) + { + return wgpuAdapterHasFeature(wgpuAdapter, Feature); + } + else if (wgpuDevice != nullptr) + { + return wgpuDeviceHasFeature(wgpuDevice, Feature); + } + else + { + UNEXPECTED("Either adapter or device must not be null"); + return DEVICE_FEATURE_STATE_DISABLED; + } +} + +DeviceFeatures GetSupportedFeatures(WGPUAdapter wgpuAdapter, WGPUDevice wgpuDevice = nullptr) +{ + auto CheckFeature = [wgpuAdapter, wgpuDevice](WGPUFeatureName Feature) { + return FeatureSupported(wgpuAdapter, wgpuDevice, Feature) ? DEVICE_FEATURE_STATE_ENABLED : DEVICE_FEATURE_STATE_DISABLED; + }; + + DeviceFeatures Features; + Features.SeparablePrograms = DEVICE_FEATURE_STATE_ENABLED; + Features.ShaderResourceQueries = DEVICE_FEATURE_STATE_ENABLED; + Features.WireframeFill = DEVICE_FEATURE_STATE_DISABLED; + Features.MultithreadedResourceCreation = DEVICE_FEATURE_STATE_DISABLED; + Features.ComputeShaders = DEVICE_FEATURE_STATE_ENABLED; + Features.GeometryShaders = DEVICE_FEATURE_STATE_DISABLED; + Features.Tessellation = DEVICE_FEATURE_STATE_DISABLED; + Features.MeshShaders = DEVICE_FEATURE_STATE_DISABLED; + Features.RayTracing = DEVICE_FEATURE_STATE_DISABLED; + Features.BindlessResources = DEVICE_FEATURE_STATE_DISABLED; + Features.OcclusionQueries = DEVICE_FEATURE_STATE_ENABLED; + Features.BinaryOcclusionQueries = DEVICE_FEATURE_STATE_DISABLED; + Features.PipelineStatisticsQueries = DEVICE_FEATURE_STATE_DISABLED; + Features.DepthBiasClamp = DEVICE_FEATURE_STATE_ENABLED; + Features.DepthClamp = CheckFeature(WGPUFeatureName_DepthClipControl); + Features.IndependentBlend = DEVICE_FEATURE_STATE_ENABLED; + Features.DualSourceBlend = CheckFeature(WGPUFeatureName_DualSourceBlending); + Features.MultiViewport = DEVICE_FEATURE_STATE_DISABLED; + Features.TextureCompressionBC = CheckFeature(WGPUFeatureName_TextureCompressionBC); + Features.TextureCompressionETC2 = CheckFeature(WGPUFeatureName_TextureCompressionETC2); + Features.VertexPipelineUAVWritesAndAtomics = DEVICE_FEATURE_STATE_ENABLED; + Features.PixelUAVWritesAndAtomics = DEVICE_FEATURE_STATE_ENABLED; + Features.TextureUAVExtendedFormats = DEVICE_FEATURE_STATE_ENABLED; + Features.ShaderFloat16 = CheckFeature(WGPUFeatureName_ShaderF16); + Features.ResourceBuffer16BitAccess = DEVICE_FEATURE_STATE_DISABLED; + Features.UniformBuffer16BitAccess = DEVICE_FEATURE_STATE_DISABLED; + Features.ShaderInputOutput16 = DEVICE_FEATURE_STATE_DISABLED; + Features.ShaderInt8 = DEVICE_FEATURE_STATE_DISABLED; + Features.ResourceBuffer8BitAccess = DEVICE_FEATURE_STATE_DISABLED; + Features.UniformBuffer8BitAccess = DEVICE_FEATURE_STATE_DISABLED; + Features.ShaderResourceStaticArrays = DEVICE_FEATURE_STATE_DISABLED; + Features.ShaderResourceRuntimeArrays = DEVICE_FEATURE_STATE_DISABLED; + Features.WaveOp = DEVICE_FEATURE_STATE_DISABLED; + Features.InstanceDataStepRate = DEVICE_FEATURE_STATE_DISABLED; + Features.NativeFence = DEVICE_FEATURE_STATE_DISABLED; + Features.TileShaders = DEVICE_FEATURE_STATE_DISABLED; + Features.TransferQueueTimestampQueries = DEVICE_FEATURE_STATE_DISABLED; + Features.VariableRateShading = DEVICE_FEATURE_STATE_DISABLED; + Features.SparseResources = DEVICE_FEATURE_STATE_DISABLED; + Features.SubpassFramebufferFetch = DEVICE_FEATURE_STATE_DISABLED; + Features.TextureComponentSwizzle = DEVICE_FEATURE_STATE_DISABLED; + Features.TextureSubresourceViews = DEVICE_FEATURE_STATE_ENABLED; + Features.NativeMultiDraw = DEVICE_FEATURE_STATE_DISABLED; + Features.AsyncShaderCompilation = DEVICE_FEATURE_STATE_ENABLED; + Features.FormattedBuffers = DEVICE_FEATURE_STATE_DISABLED; + + Features.TimestampQueries = CheckFeature(WGPUFeatureName_TimestampQuery); + Features.DurationQueries = Features.TimestampQueries ? + CheckFeature(WGPUFeatureName_ChromiumExperimentalTimestampQueryInsidePasses) : + DEVICE_FEATURE_STATE_DISABLED; + + ASSERT_SIZEOF(DeviceFeatures, 47, "Did you add a new feature to DeviceFeatures? Please handle its status here."); + + return Features; +} + + +GraphicsAdapterInfo GetGraphicsAdapterInfo(WGPUAdapter wgpuAdapter, WGPUDevice wgpuDevice = nullptr) { WGPUAdapterInfo wgpuAdapterInfo{}; if (wgpuAdapter) @@ -377,68 +452,7 @@ GraphicsAdapterInfo GetGraphicsAdapterInfo(WGPUAdapter wgpuAdapter, WGPUDevice w AdapterInfo.NumOutputs = 0; } - auto CheckWebGPUFeature = [wgpuAdapter, wgpuDevice](WGPUFeatureName Feature) { - return ((wgpuAdapter != nullptr && wgpuAdapterHasFeature(wgpuAdapter, Feature)) || - (wgpuDevice != nullptr && wgpuDeviceHasFeature(wgpuDevice, Feature))) ? - DEVICE_FEATURE_STATE_ENABLED : - DEVICE_FEATURE_STATE_DISABLED; - }; - - // Enable features - { - DeviceFeatures& Features{AdapterInfo.Features}; - Features.SeparablePrograms = DEVICE_FEATURE_STATE_ENABLED; - Features.ShaderResourceQueries = DEVICE_FEATURE_STATE_ENABLED; - Features.WireframeFill = DEVICE_FEATURE_STATE_DISABLED; - Features.MultithreadedResourceCreation = DEVICE_FEATURE_STATE_DISABLED; - Features.ComputeShaders = DEVICE_FEATURE_STATE_ENABLED; - Features.GeometryShaders = DEVICE_FEATURE_STATE_DISABLED; - Features.Tessellation = DEVICE_FEATURE_STATE_DISABLED; - Features.MeshShaders = DEVICE_FEATURE_STATE_DISABLED; - Features.RayTracing = DEVICE_FEATURE_STATE_DISABLED; - Features.BindlessResources = DEVICE_FEATURE_STATE_DISABLED; - Features.OcclusionQueries = DEVICE_FEATURE_STATE_ENABLED; - Features.BinaryOcclusionQueries = DEVICE_FEATURE_STATE_DISABLED; - Features.PipelineStatisticsQueries = DEVICE_FEATURE_STATE_DISABLED; - Features.DepthBiasClamp = DEVICE_FEATURE_STATE_ENABLED; - Features.DepthClamp = CheckWebGPUFeature(WGPUFeatureName_DepthClipControl); - Features.IndependentBlend = DEVICE_FEATURE_STATE_ENABLED; - Features.DualSourceBlend = CheckWebGPUFeature(WGPUFeatureName_DualSourceBlending); - Features.MultiViewport = DEVICE_FEATURE_STATE_DISABLED; - Features.TextureCompressionBC = CheckWebGPUFeature(WGPUFeatureName_TextureCompressionBC); - Features.TextureCompressionETC2 = CheckWebGPUFeature(WGPUFeatureName_TextureCompressionETC2); - Features.VertexPipelineUAVWritesAndAtomics = DEVICE_FEATURE_STATE_ENABLED; - Features.PixelUAVWritesAndAtomics = DEVICE_FEATURE_STATE_ENABLED; - Features.TextureUAVExtendedFormats = DEVICE_FEATURE_STATE_ENABLED; - Features.ShaderFloat16 = CheckWebGPUFeature(WGPUFeatureName_ShaderF16); - Features.ResourceBuffer16BitAccess = DEVICE_FEATURE_STATE_DISABLED; - Features.UniformBuffer16BitAccess = DEVICE_FEATURE_STATE_DISABLED; - Features.ShaderInputOutput16 = DEVICE_FEATURE_STATE_DISABLED; - Features.ShaderInt8 = DEVICE_FEATURE_STATE_DISABLED; - Features.ResourceBuffer8BitAccess = DEVICE_FEATURE_STATE_DISABLED; - Features.UniformBuffer8BitAccess = DEVICE_FEATURE_STATE_DISABLED; - Features.ShaderResourceStaticArrays = DEVICE_FEATURE_STATE_DISABLED; - Features.ShaderResourceRuntimeArrays = DEVICE_FEATURE_STATE_DISABLED; - Features.WaveOp = DEVICE_FEATURE_STATE_DISABLED; - Features.InstanceDataStepRate = DEVICE_FEATURE_STATE_DISABLED; - Features.NativeFence = DEVICE_FEATURE_STATE_DISABLED; - Features.TileShaders = DEVICE_FEATURE_STATE_DISABLED; - Features.TransferQueueTimestampQueries = DEVICE_FEATURE_STATE_DISABLED; - Features.VariableRateShading = DEVICE_FEATURE_STATE_DISABLED; - Features.SparseResources = DEVICE_FEATURE_STATE_DISABLED; - Features.SubpassFramebufferFetch = DEVICE_FEATURE_STATE_DISABLED; - Features.TextureComponentSwizzle = DEVICE_FEATURE_STATE_DISABLED; - Features.TextureSubresourceViews = DEVICE_FEATURE_STATE_ENABLED; - Features.NativeMultiDraw = DEVICE_FEATURE_STATE_DISABLED; - Features.AsyncShaderCompilation = DEVICE_FEATURE_STATE_ENABLED; - Features.FormattedBuffers = DEVICE_FEATURE_STATE_DISABLED; - - Features.TimestampQueries = CheckWebGPUFeature(WGPUFeatureName_TimestampQuery); - Features.DurationQueries = Features.TimestampQueries ? - CheckWebGPUFeature(WGPUFeatureName_ChromiumExperimentalTimestampQueryInsidePasses) : - DEVICE_FEATURE_STATE_DISABLED; - } - ASSERT_SIZEOF(DeviceFeatures, 47, "Did you add a new feature to DeviceFeatures? Please handle its status here."); + AdapterInfo.Features = GetSupportedFeatures(wgpuAdapter, wgpuDevice); WGPUSupportedLimits wgpuSupportedLimits{}; if (wgpuAdapter) @@ -459,7 +473,7 @@ GraphicsAdapterInfo GetGraphicsAdapterInfo(WGPUAdapter wgpuAdapter, WGPUDevice w DrawCommandInfo.MaxDrawIndirectCount = ~0u; DrawCommandInfo.CapFlags = DRAW_COMMAND_CAP_FLAG_DRAW_INDIRECT; - if (CheckWebGPUFeature(WGPUFeatureName_IndirectFirstInstance)) + if (FeatureSupported(wgpuAdapter, wgpuDevice, WGPUFeatureName_IndirectFirstInstance)) DrawCommandInfo.CapFlags |= DRAW_COMMAND_CAP_FLAG_DRAW_INDIRECT_FIRST_INSTANCE; } @@ -581,7 +595,7 @@ void EngineFactoryWebGPUImpl::CreateDeviceAndContextsWebGPU(const EngineWebGPUCr SpecificAdapter = std::move(wgpuAdapters[0]); } - WebGPUDeviceWrapper Device = CreateDeviceForAdapter(EngineCI, wgpuInstance.Get(), SpecificAdapter.Get()); + WebGPUDeviceWrapper Device = CreateDeviceForAdapter(EngineCI.Features, wgpuInstance, SpecificAdapter); AttachToWebGPUDevice(wgpuInstance.Detach(), SpecificAdapter.Detach(), Device.Detach(), EngineCI, ppDevice, ppImmediateContext); } catch (const std::runtime_error&) @@ -659,12 +673,23 @@ void EngineFactoryWebGPUImpl::AttachToWebGPUDevice(void* const GraphicsAdapterInfo AdapterInfo = GetGraphicsAdapterInfo(static_cast(wgpuAdapter), static_cast(wgpuDevice)); VerifyEngineCreateInfo(EngineCI, AdapterInfo); + const DeviceFeatures EnabledFeatures = GetSupportedFeatures(nullptr, static_cast(wgpuDevice)); + SetRawAllocator(EngineCI.pRawMemAllocator); IMemoryAllocator& RawMemAllocator = GetRawAllocator(); RenderDeviceWebGPUImpl* pRenderDeviceWebGPU{ NEW_RC_OBJ(RawMemAllocator, "RenderDeviceWebGPUImpl instance", RenderDeviceWebGPUImpl)( - RawMemAllocator, this, EngineCI, AdapterInfo, static_cast(wgpuInstance), static_cast(wgpuAdapter), static_cast(wgpuDevice))}; + RenderDeviceWebGPUImpl::CreateInfo{ + RawMemAllocator, + this, + EngineCI, + AdapterInfo, + EnabledFeatures, + static_cast(wgpuInstance), + static_cast(wgpuAdapter), + static_cast(wgpuDevice), + })}; pRenderDeviceWebGPU->QueryInterface(IID_RenderDevice, reinterpret_cast(ppDevice)); DeviceContextWebGPUImpl* pDeviceContextWebGPU{ diff --git a/Graphics/GraphicsEngineWebGPU/src/RenderDeviceWebGPUImpl.cpp b/Graphics/GraphicsEngineWebGPU/src/RenderDeviceWebGPUImpl.cpp index a6f116263..317e0fba3 100644 --- a/Graphics/GraphicsEngineWebGPU/src/RenderDeviceWebGPUImpl.cpp +++ b/Graphics/GraphicsEngineWebGPU/src/RenderDeviceWebGPUImpl.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2023-2024 Diligent Graphics LLC + * Copyright 2023-2025 Diligent Graphics LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -75,27 +75,21 @@ static void DebugMessengerCallback(WGPUErrorType MessageType, const char* Messag } #endif -RenderDeviceWebGPUImpl::RenderDeviceWebGPUImpl(IReferenceCounters* pRefCounters, - IMemoryAllocator& RawMemAllocator, - IEngineFactory* pEngineFactory, - const EngineWebGPUCreateInfo& EngineCI, - const GraphicsAdapterInfo& AdapterInfo, - WGPUInstance wgpuInstance, - WGPUAdapter wgpuAdapter, - WGPUDevice wgpuDevice) : +RenderDeviceWebGPUImpl::RenderDeviceWebGPUImpl(IReferenceCounters* pRefCounters, + const CreateInfo& CI) : // clang-format off TRenderDeviceBase { pRefCounters, - RawMemAllocator, - pEngineFactory, - EngineCI, - AdapterInfo + CI.RawMemAllocator, + CI.pEngineFactory, + CI.EngineCI, + CI.AdapterInfo }, - m_wgpuInstance(wgpuInstance), - m_wgpuAdapter{wgpuAdapter}, - m_wgpuDevice{wgpuDevice} + m_wgpuInstance(CI.wgpuInstance), + m_wgpuAdapter{CI.wgpuAdapter}, + m_wgpuDevice{CI.wgpuDevice} // clang-format on { WGPUSupportedLimits wgpuSupportedLimits{}; @@ -110,7 +104,9 @@ RenderDeviceWebGPUImpl::RenderDeviceWebGPUImpl(IReferenceCounters* pRe m_DeviceInfo.Type = RENDER_DEVICE_TYPE_WEBGPU; m_DeviceInfo.NDC = NDCAttribs{0.0f, 1.0f, -0.5f}; - m_DeviceInfo.Features = EnableDeviceFeatures(m_AdapterInfo.Features, EngineCI.Features); + const EngineWebGPUCreateInfo& EngineCI{CI.EngineCI}; + + m_DeviceInfo.Features = EnableDeviceFeatures(CI.EnabledFeatures, EngineCI.Features); m_pUploadMemoryManager = std::make_unique(m_wgpuDevice, EngineCI.UploadHeapPageSize); m_pDynamicMemoryManager = std::make_unique(m_wgpuDevice, EngineCI.DynamicHeapPageSize, EngineCI.DynamicHeapSize);