@@ -694,7 +694,61 @@ void WebGPUDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
694694void WebGPUDriver::setExternalStream (Handle<HwTexture> th, Handle<HwStream> sh) {
695695}
696696
697- void WebGPUDriver::generateMipmaps (Handle<HwTexture> th) { }
697+ void WebGPUDriver::generateMipmaps (Handle<HwTexture> th) {
698+ if (!mCommandEncoder ) {
699+ mMipQueue .push_back (th);
700+ return ;
701+ }
702+ auto * texture = handleCast<WGPUTexture>(th);
703+ assert_invariant (texture);
704+ wgpu::Texture wgpuTexture = texture->getTexture ();
705+ assert_invariant (wgpuTexture);
706+
707+ FILAMENT_CHECK_PRECONDITION (wgpuTexture.GetUsage () & wgpu::TextureUsage::CopySrc)
708+ << " Texture intended for mipmap generation (as source) must have CopySrc usage." ;
709+ FILAMENT_CHECK_PRECONDITION (wgpuTexture.GetUsage () & wgpu::TextureUsage::CopyDst)
710+ << " Texture intended for mipmap generation (as destination) must have CopyDst usage." ;
711+
712+ uint32_t mipLevelCount = wgpuTexture.GetMipLevelCount ();
713+ if (mipLevelCount <= 1 ) {
714+ return ;
715+ }
716+
717+ uint32_t width = wgpuTexture.GetWidth ();
718+ uint32_t height = wgpuTexture.GetHeight ();
719+ // For 3D textures, depth is > 1. For 2D/Cube/Array, effectively 1 for mip-level copies.
720+ uint32_t depth =
721+ (texture->target == SamplerType::SAMPLER_3D) ? wgpuTexture.GetDepthOrArrayLayers () : 1 ;
722+
723+ for (uint32_t mipLevel = 0 ; mipLevel < mipLevelCount - 1 ; ++mipLevel) {
724+ wgpu::TexelCopyTextureInfo sourceCopyInfo{
725+ .texture = wgpuTexture,
726+ .mipLevel = mipLevel,
727+ .aspect = texture->getAspect (),
728+ };
729+
730+ wgpu::TexelCopyTextureInfo destinationCopyInfo{
731+ .texture = wgpuTexture,
732+ .mipLevel = mipLevel + 1 ,
733+ .aspect = texture->getAspect (),
734+ };
735+
736+ uint32_t dstWidth = std::max (1u , width >> 1 );
737+ uint32_t dstHeight = std::max (1u , height >> 1 );
738+ uint32_t dstDepth = std::max (1u , depth >> 1 );
739+
740+ wgpu::Extent3D copySize{ .width = dstWidth,
741+ .height = dstHeight,
742+ .depthOrArrayLayers = (texture->target == SamplerType::SAMPLER_3D)
743+ ? dstDepth
744+ : texture->getArrayLayerCount () };
745+ mCommandEncoder .CopyTextureToTexture (&sourceCopyInfo, &destinationCopyInfo, ©Size);
746+
747+ width = dstWidth;
748+ height = dstHeight;
749+ depth = dstDepth;
750+ }
751+ }
698752
699753void WebGPUDriver::compilePrograms (CompilerPriorityQueue priority,
700754 CallbackHandler* handler, CallbackHandler::Callback callback, void * user) {
@@ -804,6 +858,12 @@ void WebGPUDriver::makeCurrent(Handle<HwSwapChain> drawSch, Handle<HwSwapChain>
804858 .label = " command_encoder"
805859 };
806860 mCommandEncoder = mDevice .CreateCommandEncoder (&commandEncoderDescriptor);
861+ if (!mMipQueue .empty ()) {
862+ for (auto & handle: mMipQueue ) {
863+ generateMipmaps (handle);
864+ }
865+ mMipQueue .clear ();
866+ }
807867 assert_invariant (mCommandEncoder );
808868}
809869
0 commit comments