Compare commits

...

3 Commits

Author SHA1 Message Date
Run Yu
0ad90d139d wgpu: code clean up based on feedback 2026-01-28 21:35:45 -05:00
Run Yu
cf694a3334 wgpu: add TextureUsage::SAMPLEABLE to the depth texture in test_Scissor,
which is needed to draw the triangle if the test is enabled.
2026-01-23 15:17:12 -05:00
Run Yu
863379b5b4 wgpu: fix the readPixels function so test_Scissor can draw the triangle 2026-01-23 15:17:12 -05:00
2 changed files with 19 additions and 10 deletions

View File

@@ -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,20 @@ 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()};
constexpr uint32_t minValidTextureSize = 1;
const uint32_t mipLeveledSrcWidth = std::max(minValidTextureSize, srcWidth >> srcMipLevel);
const uint32_t mipLeveledSrcHeight = std::max(minValidTextureSize, srcHeight >> srcMipLevel);
// 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)};
if (UTILS_UNLIKELY(actualWidth == 0 || actualHeight == 0)) {
scheduleDestroy(std::move(pixelBufferDescriptor));
return;
@@ -1526,6 +1533,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 +1544,7 @@ void WebGPUDriver::readPixels(Handle<HwRenderTarget> sourceRenderTargetHandle, c
.depthOrArrayLayers = 1,
},
.format = dstFormat,
.mipLevelCount = 1,
.mipLevelCount = srcMipLevelCount,
.sampleCount = srcTexture.GetSampleCount(),
};
stagingTexture = mDevice.CreateTexture(&stagingDescriptor);
@@ -1586,12 +1594,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,
.origin = {.x = readX, .y = flippedY, .z = 0,},
};
const wgpu::TexelCopyBufferInfo destination{

View File

@@ -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));
// Render into the bottom-left quarter of the texture.
Viewport srcRect = {