Skip to content

Commit 672603f

Browse files
Generate mipmaps when requested, deferring as needed
1 parent 0ecf6c4 commit 672603f

File tree

3 files changed

+63
-1
lines changed

3 files changed

+63
-1
lines changed

filament/backend/src/webgpu/WebGPUDriver.cpp

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,61 @@ void WebGPUDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
694694
void 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, &copySize);
746+
747+
width = dstWidth;
748+
height = dstHeight;
749+
depth = dstDepth;
750+
}
751+
}
698752

699753
void 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

filament/backend/src/webgpu/WebGPUDriver.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ class WebGPUDriver final : public DriverBase {
7070
WebGPUSwapChain* mSwapChain = nullptr;
7171
uint64_t mNextFakeHandle = 1;
7272
wgpu::CommandEncoder mCommandEncoder = nullptr;
73+
std::vector<Handle<HwTexture>> mMipQueue;
7374
wgpu::TextureView mTextureView = nullptr;
7475
wgpu::RenderPassEncoder mRenderPassEncoder = nullptr;
7576
wgpu::CommandBuffer mCommandBuffer = nullptr;

filament/backend/src/webgpu/WebGPUHandles.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,7 @@ class WGPUTexture : public HwTexture {
184184
[[nodiscard]] const wgpu::Texture& getTexture() const { return mTexture; }
185185
[[nodiscard]] const wgpu::TextureView& getTextureView() const { return mTexureView; }
186186
[[nodiscard]] wgpu::TextureFormat getFormat() const { return mFormat; }
187+
[[nodiscard]] uint32_t getArrayLayerCount() const { return mArrayLayerCount; }
187188

188189
static wgpu::TextureFormat fToWGPUTextureFormat(
189190
filament::backend::TextureFormat const& fFormat);

0 commit comments

Comments
 (0)