-
Notifications
You must be signed in to change notification settings - Fork 2.2k
webgpu: step 1 in fixing test_Scissor by fixing WebGPUDriver::readPixels with mipmap #9629
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1472,6 +1472,7 @@ void WebGPUDriver::readPixels(Handle<HwRenderTarget> sourceRenderTargetHandle, c | |
| const auto srcTarget{ handleCast<WebGPURenderTarget>(sourceRenderTargetHandle) }; | ||
| assert_invariant(srcTarget); | ||
|
|
||
| uint32_t srcMipLevel = 0; | ||
| wgpu::Texture srcTexture{ nullptr }; | ||
| if (srcTarget->isDefaultRenderTarget()) { | ||
| assert_invariant(mSwapChain); | ||
|
|
@@ -1482,6 +1483,7 @@ void WebGPUDriver::readPixels(Handle<HwRenderTarget> sourceRenderTargetHandle, c | |
| // TODO we are currently assuming the first attachment is the desired texture. | ||
| if (colorAttachmentInfos[0].handle) { | ||
| auto texture = handleCast<WebGPUTexture>(colorAttachmentInfos[0].handle); | ||
| srcMipLevel = colorAttachmentInfos[0].level; | ||
| if (texture) { | ||
| srcTexture = texture->getTexture(); | ||
| } | ||
|
|
@@ -1494,15 +1496,21 @@ void WebGPUDriver::readPixels(Handle<HwRenderTarget> sourceRenderTargetHandle, c | |
| return; | ||
| } | ||
| const uint32_t srcWidth {srcTexture.GetWidth()}; | ||
| const uint32_t srcHeight{srcTexture.GetHeight()}; | ||
| const uint32_t srcHeight {srcTexture.GetHeight()}; | ||
| const uint32_t srcMipLevelCount {srcTexture.GetMipLevelCount()}; | ||
|
|
||
| const uint32_t mipLevelImageScale = 1 << srcMipLevel; | ||
| const uint32_t mipLeveledSrcWidth = srcWidth / mipLevelImageScale; | ||
| const uint32_t mipLeveledSrcHeight = srcHeight / mipLevelImageScale; | ||
| assert_invariant(mipLeveledSrcWidth > 0 && mipLeveledSrcHeight > 0); | ||
|
|
||
| // Clamp read region to texture bounds | ||
| if (UTILS_UNLIKELY(x >= srcWidth || y >= srcHeight)) { | ||
| if (UTILS_UNLIKELY(x >= mipLeveledSrcWidth || y >= mipLeveledSrcHeight)) { | ||
| scheduleDestroy(std::move(pixelBufferDescriptor)); | ||
| return; | ||
| } | ||
| auto actualWidth{ std::min(width, srcWidth - x) }; | ||
| auto actualHeight{ std::min(height, srcHeight - y)}; | ||
| auto actualWidth{ std::min(width, mipLeveledSrcWidth - x) }; | ||
| auto actualHeight{ std::min(height, mipLeveledSrcHeight - y)}; | ||
|
Comment on lines
+1511
to
+1512
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand why the
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The x and y are offsets, so subtracting them from the entire texture's size (at the requested mipmap level) gives you the remaining maximum size that can be copied, from the beginning offsetted corner to the diagonally opposite corner of the entire texture. |
||
| if (UTILS_UNLIKELY(actualWidth == 0 || actualHeight == 0)) { | ||
| scheduleDestroy(std::move(pixelBufferDescriptor)); | ||
| return; | ||
|
|
@@ -1526,6 +1534,7 @@ void WebGPUDriver::readPixels(Handle<HwRenderTarget> sourceRenderTargetHandle, c | |
| // If the source format is different from the destination (e.g. BGRA vs RGBA), | ||
| // we need to perform a conversion using an intermediate blit. | ||
| if (conversionNecessary(srcFormat, dstFormat, pixelBufferDescriptor.type)) { | ||
| // TODO: check if the blit process here is correct when mipmap level > 0 | ||
| const wgpu::TextureDescriptor stagingDescriptor{ | ||
| .label = "readpixels_staging_texture", | ||
| .usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment, | ||
|
|
@@ -1536,7 +1545,7 @@ void WebGPUDriver::readPixels(Handle<HwRenderTarget> sourceRenderTargetHandle, c | |
| .depthOrArrayLayers = 1, | ||
| }, | ||
| .format = dstFormat, | ||
| .mipLevelCount = 1, | ||
| .mipLevelCount = srcMipLevelCount, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. reading code, I think you need to pass I'm not sure if it's worth copying all levels for this. But if so, you probably need to iterate through all levels with the blit call below. Otherwise, you may as well revert this along with the other comment below.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So I plan to NOT resolve issues about
|
||
| .sampleCount = srcTexture.GetSampleCount(), | ||
| }; | ||
| stagingTexture = mDevice.CreateTexture(&stagingDescriptor); | ||
|
|
@@ -1586,12 +1595,11 @@ void WebGPUDriver::readPixels(Handle<HwRenderTarget> sourceRenderTargetHandle, c | |
|
|
||
| // WebGPU's texture coordinates for copies are top-left, but Filament's y-coordinate is | ||
| // bottom-left. We must flip the y-coordinate relative to the texture we are reading from. | ||
| const uint32_t textureHeight{ textureToReadFrom.GetHeight() }; | ||
| const uint32_t flippedY{ textureHeight - readY - actualHeight }; | ||
| const uint32_t flippedY{ mipLeveledSrcHeight - readY - actualHeight }; | ||
|
|
||
| const wgpu::TexelCopyTextureInfo source{ | ||
| .texture = textureToReadFrom, // Read from the original or intermediate texture | ||
| .mipLevel = 0, | ||
| .mipLevel = srcMipLevel, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if we use the intermediate texture (stagingTexture), do we still need to specify this as srcMipLevel? not 0? I guess the blit call will copy contents only for level 0.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right, but similar to the above reply, I suggest we not fix |
||
| .origin = {.x = readX, .y = flippedY, .z = 0,}, | ||
| }; | ||
| const wgpu::TexelCopyBufferInfo destination{ | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -83,8 +83,10 @@ TEST_F(BackendTest, ScissorViewportRegion) { | |
| Handle<HwTexture> srcTexture = addCleanup(api.createTexture(SamplerType::SAMPLER_2D, | ||
| kNumLevels, kSrcTexFormat, 1, kSrcTexWidth, kSrcTexHeight, 1, | ||
| TextureUsage::SAMPLEABLE | TextureUsage::COLOR_ATTACHMENT TEXTURE_USAGE_READ_PIXELS)); | ||
| Handle<HwTexture> depthTexture = addCleanup(api.createTexture(SamplerType::SAMPLER_2D, 1, | ||
| TextureFormat::DEPTH16, 1, 512, 512, 1, TextureUsage::DEPTH_ATTACHMENT)); | ||
|
|
||
| Handle<HwTexture> depthTexture = | ||
| addCleanup(api.createTexture(SamplerType::SAMPLER_2D, 1, TextureFormat::DEPTH16, 1, | ||
| 512, 512, 1, TextureUsage::DEPTH_ATTACHMENT | TextureUsage::SAMPLEABLE)); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand why SAMPLEABLE is needed?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tbh I don't know the exact reason either... I just found without it webgpu would crash, adding it (or not using a depth attachment) makes it work. |
||
|
|
||
| // Render into the bottom-left quarter of the texture. | ||
| Viewport srcRect = { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.