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) }; const auto srcTarget{ handleCast<WebGPURenderTarget>(sourceRenderTargetHandle) };
assert_invariant(srcTarget); assert_invariant(srcTarget);
uint32_t srcMipLevel = 0;
wgpu::Texture srcTexture{ nullptr }; wgpu::Texture srcTexture{ nullptr };
if (srcTarget->isDefaultRenderTarget()) { if (srcTarget->isDefaultRenderTarget()) {
assert_invariant(mSwapChain); 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. // TODO we are currently assuming the first attachment is the desired texture.
if (colorAttachmentInfos[0].handle) { if (colorAttachmentInfos[0].handle) {
auto texture = handleCast<WebGPUTexture>(colorAttachmentInfos[0].handle); auto texture = handleCast<WebGPUTexture>(colorAttachmentInfos[0].handle);
srcMipLevel = colorAttachmentInfos[0].level;
if (texture) { if (texture) {
srcTexture = texture->getTexture(); srcTexture = texture->getTexture();
} }
@@ -1494,15 +1496,20 @@ void WebGPUDriver::readPixels(Handle<HwRenderTarget> sourceRenderTargetHandle, c
return; return;
} }
const uint32_t srcWidth {srcTexture.GetWidth()}; 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 // Clamp read region to texture bounds
if (UTILS_UNLIKELY(x >= srcWidth || y >= srcHeight)) { if (UTILS_UNLIKELY(x >= mipLeveledSrcWidth || y >= mipLeveledSrcHeight)) {
scheduleDestroy(std::move(pixelBufferDescriptor)); scheduleDestroy(std::move(pixelBufferDescriptor));
return; return;
} }
auto actualWidth{ std::min(width, srcWidth - x) }; auto actualWidth{ std::min(width, mipLeveledSrcWidth - x) };
auto actualHeight{ std::min(height, srcHeight - y)}; auto actualHeight{ std::min(height, mipLeveledSrcHeight - y)};
if (UTILS_UNLIKELY(actualWidth == 0 || actualHeight == 0)) { if (UTILS_UNLIKELY(actualWidth == 0 || actualHeight == 0)) {
scheduleDestroy(std::move(pixelBufferDescriptor)); scheduleDestroy(std::move(pixelBufferDescriptor));
return; 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), // If the source format is different from the destination (e.g. BGRA vs RGBA),
// we need to perform a conversion using an intermediate blit. // we need to perform a conversion using an intermediate blit.
if (conversionNecessary(srcFormat, dstFormat, pixelBufferDescriptor.type)) { if (conversionNecessary(srcFormat, dstFormat, pixelBufferDescriptor.type)) {
// TODO: check if the blit process here is correct when mipmap level > 0
const wgpu::TextureDescriptor stagingDescriptor{ const wgpu::TextureDescriptor stagingDescriptor{
.label = "readpixels_staging_texture", .label = "readpixels_staging_texture",
.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment, .usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::RenderAttachment,
@@ -1536,7 +1544,7 @@ void WebGPUDriver::readPixels(Handle<HwRenderTarget> sourceRenderTargetHandle, c
.depthOrArrayLayers = 1, .depthOrArrayLayers = 1,
}, },
.format = dstFormat, .format = dstFormat,
.mipLevelCount = 1, .mipLevelCount = srcMipLevelCount,
.sampleCount = srcTexture.GetSampleCount(), .sampleCount = srcTexture.GetSampleCount(),
}; };
stagingTexture = mDevice.CreateTexture(&stagingDescriptor); 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 // 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. // 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{ mipLeveledSrcHeight - readY - actualHeight };
const uint32_t flippedY{ textureHeight - readY - actualHeight };
const wgpu::TexelCopyTextureInfo source{ const wgpu::TexelCopyTextureInfo source{
.texture = textureToReadFrom, // Read from the original or intermediate texture .texture = textureToReadFrom, // Read from the original or intermediate texture
.mipLevel = 0, .mipLevel = srcMipLevel,
.origin = {.x = readX, .y = flippedY, .z = 0,}, .origin = {.x = readX, .y = flippedY, .z = 0,},
}; };
const wgpu::TexelCopyBufferInfo destination{ const wgpu::TexelCopyBufferInfo destination{

View File

@@ -83,8 +83,10 @@ TEST_F(BackendTest, ScissorViewportRegion) {
Handle<HwTexture> srcTexture = addCleanup(api.createTexture(SamplerType::SAMPLER_2D, Handle<HwTexture> srcTexture = addCleanup(api.createTexture(SamplerType::SAMPLER_2D,
kNumLevels, kSrcTexFormat, 1, kSrcTexWidth, kSrcTexHeight, 1, kNumLevels, kSrcTexFormat, 1, kSrcTexWidth, kSrcTexHeight, 1,
TextureUsage::SAMPLEABLE | TextureUsage::COLOR_ATTACHMENT TEXTURE_USAGE_READ_PIXELS)); 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. // Render into the bottom-left quarter of the texture.
Viewport srcRect = { Viewport srcRect = {