diff --git a/filament/backend/src/webgpu/WebGPUDriver.cpp b/filament/backend/src/webgpu/WebGPUDriver.cpp index 4dc45eb9ed..c9d8687f8e 100644 --- a/filament/backend/src/webgpu/WebGPUDriver.cpp +++ b/filament/backend/src/webgpu/WebGPUDriver.cpp @@ -443,7 +443,7 @@ void WebGPUDriver::createRenderTargetR(Handle rth, TargetBufferF // Individual attachments (color[i].layer, depth.layer, stencil.layer) specify which layer // of an array texture to bind. For now, we assume textures are pre-configured. - constructHandle(rth, width, height, samples, color, depth, stencil); + constructHandle(rth, width, height, samples, layerCount, color, depth, stencil); } void WebGPUDriver::createFenceR(Handle fh, int) { @@ -809,9 +809,14 @@ void WebGPUDriver::beginRenderPass(Handle rth, RenderPassParams if (colorInfos[i].handle) { auto* hwTexture = handleCast(colorInfos[i].handle); if (hwTexture) { - // TODO: Consider colorInfos[i].level and colorInfos[i].layer for view creation - // if WGPUTexture::getTextureView() isn't sufficient or needs parameters. - customColorViews[customColorViewCount++] = hwTexture->getTextureView(); + FILAMENT_CHECK_POSTCONDITION(colorInfos[i].layer < renderTarget->mLayerCount) + << "Color attachment " << i << " requests layer " + << colorInfos[i].layer << " but render target has only " + << renderTarget->mLayerCount << "."; + uint8_t mipLevel = colorInfos[i].level; + uint32_t arrayLayer = colorInfos[i].layer; + customColorViews[customColorViewCount++] = hwTexture->makeTextureView(mipLevel, + 1, arrayLayer, 1, hwTexture->mSamplerType); } } @@ -819,9 +824,20 @@ void WebGPUDriver::beginRenderPass(Handle rth, RenderPassParams const auto& depthInfo = renderTarget->getDepthAttachmentInfo(); if (depthInfo.handle) { + FILAMENT_CHECK_POSTCONDITION(depthInfo.layer < renderTarget->mLayerCount) + << "Depth attachment requests layer " << depthInfo.layer + << "but render target has only " << renderTarget->mLayerCount << "."; auto* hwTexture = handleCast(depthInfo.handle); if (hwTexture) { - customDepthView = hwTexture->getTextureView(); + uint8_t depthMipLevel = depthInfo.level; + uint32_t depthArrayLayer = depthInfo.layer; + customDepthView = hwTexture->makeTextureView( + depthMipLevel, + 1, + depthArrayLayer, + 1, + hwTexture->mSamplerType + ); customDepthFormat = hwTexture->getFormat(); } } @@ -831,7 +847,14 @@ void WebGPUDriver::beginRenderPass(Handle rth, RenderPassParams // If depth and stencil use the same texture handle, this will re-cast but that's fine. auto* hwTexture = handleCast(stencilInfo.handle); if (hwTexture) { - customStencilView = hwTexture->getTextureView(); + FILAMENT_CHECK_POSTCONDITION(stencilInfo.layer < renderTarget->mLayerCount) + << "Stencil attachment requests layer " << stencilInfo.layer + << " but render target has only " << renderTarget->mLayerCount + << " layers."; + uint8_t stencilMipLevel = stencilInfo.level; + uint32_t stencilArrayLayer = stencilInfo.layer; + customStencilView = hwTexture->makeTextureView(stencilMipLevel, 1, + stencilArrayLayer, 1, hwTexture->mSamplerType); customStencilFormat = hwTexture->getFormat(); } } diff --git a/filament/backend/src/webgpu/WebGPUHandles.cpp b/filament/backend/src/webgpu/WebGPUHandles.cpp index fc68408701..5025845699 100644 --- a/filament/backend/src/webgpu/WebGPUHandles.cpp +++ b/filament/backend/src/webgpu/WebGPUHandles.cpp @@ -590,9 +590,10 @@ WGPUTexture::WGPUTexture(SamplerType samplerTargetType, uint8_t levels, TextureF "the spec. See https://www.w3.org/TR/webgpu/#texture-creation or " "https://gpuweb.github.io/gpuweb/#multisample-state"); // First, the texture aspect, starting with the defaults/basic configuration - mUsage = fToWGPUTextureUsage(usage); mFormat = fToWGPUTextureFormat(format); + mUsage = fToWGPUTextureUsage(usage); mAspect = fToWGPUTextureViewAspect(usage, format); + mSamplerType = target; mBlockWidth = filament::backend::getBlockWidth(format); mBlockHeight = filament::backend::getBlockHeight(format); target = samplerTargetType; @@ -638,7 +639,7 @@ WGPUTexture::WGPUTexture(SamplerType samplerTargetType, uint8_t levels, TextureF FILAMENT_CHECK_POSTCONDITION(mTexture) << "Failed to create texture for " << textureDescriptor.label; // Second, the texture view aspect - mTexureView = makeTextureView(0, levels, target); + mTexureView = makeTextureView(0, levels, 0, mArrayLayerCount, target); } WGPUTexture::WGPUTexture(WGPUTexture* src, uint8_t baseLevel, uint8_t levelCount) noexcept { @@ -646,9 +647,10 @@ WGPUTexture::WGPUTexture(WGPUTexture* src, uint8_t baseLevel, uint8_t levelCount mAspect = src->mAspect; mBlockWidth = src->mBlockWidth; mBlockHeight = src->mBlockHeight; - target = src->target; + mArrayLayerCount = src->mArrayLayerCount; + mSamplerType = src->mSamplerType; - mTexureView = makeTextureView(baseLevel, levelCount, target); + mTexureView = makeTextureView(baseLevel, levelCount, 0, src->mArrayLayerCount, mSamplerType); } wgpu::TextureUsage WGPUTexture::fToWGPUTextureUsage(TextureUsage const& fUsage) { @@ -977,6 +979,7 @@ wgpu::TextureAspect WGPUTexture::fToWGPUTextureViewAspect(TextureUsage const& fU } wgpu::TextureView WGPUTexture::makeTextureView(const uint8_t& baseLevel, const uint8_t& levelCount, + const uint32_t& baseArrayLayer, const uint32_t& arrayLayerCount, SamplerType target) { wgpu::TextureViewDescriptor textureViewDescriptor{ @@ -984,9 +987,8 @@ wgpu::TextureView WGPUTexture::makeTextureView(const uint8_t& baseLevel, const u .format = mFormat, .baseMipLevel = baseLevel, .mipLevelCount = levelCount, - // TODO: check if this baseArrayLayer assumption is correct - .baseArrayLayer = 0, - .arrayLayerCount = mArrayLayerCount, + .baseArrayLayer = baseArrayLayer, + .arrayLayerCount = arrayLayerCount, .aspect = mAspect, .usage = mUsage }; @@ -1017,11 +1019,12 @@ wgpu::TextureView WGPUTexture::makeTextureView(const uint8_t& baseLevel, const u return textureView; } -WGPURenderTarget::WGPURenderTarget(uint32_t width, uint32_t height, uint8_t samples, +WGPURenderTarget::WGPURenderTarget(uint32_t width, uint32_t height, uint8_t samples, uint8_t layerCount, const MRT& colorAttachmentsMRT, const Attachment& depthAttachmentInfo, const Attachment& stencilAttachmentInfo) : HwRenderTarget(width, height), + mLayerCount(layerCount), defaultRenderTarget(false), samples(samples), mColorAttachments(colorAttachmentsMRT), diff --git a/filament/backend/src/webgpu/WebGPUHandles.h b/filament/backend/src/webgpu/WebGPUHandles.h index 91d921fd60..1897cf6e6d 100644 --- a/filament/backend/src/webgpu/WebGPUHandles.h +++ b/filament/backend/src/webgpu/WebGPUHandles.h @@ -181,6 +181,10 @@ public: size_t getBlockWidth() const { return mBlockWidth; } size_t getBlockHeight() const { return mBlockHeight; } + wgpu::TextureView makeTextureView(const uint8_t& baseLevel, const uint8_t& levelCount, + const uint32_t& baseArrayLayer, const uint32_t& arrayLayerCount, + SamplerType target); + [[nodiscard]] const wgpu::Texture& getTexture() const { return mTexture; } [[nodiscard]] const wgpu::TextureView& getTextureView() const { return mTexureView; } [[nodiscard]] wgpu::TextureFormat getFormat() const { return mFormat; } @@ -192,21 +196,23 @@ public: filament::backend::TextureUsage const& fUsage, filament::backend::TextureFormat const& fFormat); + SamplerType mSamplerType; + private: - wgpu::TextureView makeTextureView(const uint8_t& baseLevel, const uint8_t& levelCount, - SamplerType target); // CreateTextureR has info for a texture and sampler. Texture Views are needed for binding, // along with a sampler Current plan: Inherit the sampler and Texture to always exist (It is a // ref counted pointer) when making views. View is optional wgpu::Texture mTexture = nullptr; - wgpu::TextureUsage mUsage = wgpu::TextureUsage::None; + wgpu::TextureView mTexureView = nullptr; wgpu::TextureFormat mFormat = wgpu::TextureFormat::Undefined; wgpu::TextureAspect mAspect = wgpu::TextureAspect::Undefined; + wgpu::TextureUsage mUsage = wgpu::TextureUsage::None; uint32_t mArrayLayerCount = 1; - wgpu::TextureView mTexureView = nullptr; - wgpu::TextureUsage fToWGPUTextureUsage(filament::backend::TextureUsage const& fUsage); size_t mBlockWidth; size_t mBlockHeight; + + wgpu::TextureUsage fToWGPUTextureUsage(filament::backend::TextureUsage const& fUsage); + }; struct WGPURenderPrimitive : public HwRenderPrimitive { @@ -219,7 +225,7 @@ class WGPURenderTarget : public HwRenderTarget { public: using Attachment = TargetBufferInfo; // Using TargetBufferInfo directly for attachments - WGPURenderTarget(uint32_t width, uint32_t height, uint8_t samples, + WGPURenderTarget(uint32_t width, uint32_t height, uint8_t samples, uint8_t layerCount, const MRT& colorAttachments, const Attachment& depthAttachment, const Attachment& stencilAttachment); @@ -258,6 +264,8 @@ public: static wgpu::LoadOp getLoadOperation(const RenderPassParams& params, TargetBufferFlags buffer); static wgpu::StoreOp getStoreOperation(const RenderPassParams& params, TargetBufferFlags buffer); + uint8_t mLayerCount = 1; + private: bool defaultRenderTarget = false; uint8_t samples = 1;