Support *-srgb format as dst formats in CopyTextureForBrowser
Dawn allows texture-to-texture copy happens between the textures that formats only have diff on srgb-ness. CopyTextureForBrowser could align on this rule to achieve copying to *-srgb dst texture and keep the bytes the same as copying to non-srgb formats. This CL add support for *-srgb textures as dst textures and using an extra gamma decoding step for this. Bug: dawn:1195 Change-Id: I665dbca473aa84b9d87b7a35c4f90ce1897ade7b Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/74580 Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org> Commit-Queue: Shaobo Yan <shaobo.yan@intel.com>
This commit is contained in:
parent
e009ad7edd
commit
c40f04b85b
|
@ -48,14 +48,15 @@ namespace dawn_native {
|
||||||
padding: u32;
|
padding: u32;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Uniforms { // offset align size
|
struct Uniforms { // offset align size
|
||||||
scale: vec2<f32>; // 0 8 8
|
scale: vec2<f32>; // 0 8 8
|
||||||
offset: vec2<f32>; // 8 8 8
|
offset: vec2<f32>; // 8 8 8
|
||||||
steps_mask: u32; // 16 4 4
|
steps_mask: u32; // 16 4 4
|
||||||
// implicit padding; // 20 12
|
// implicit padding; // 20 12
|
||||||
conversion_matrix: mat3x3<f32>; // 32 16 48
|
conversion_matrix: mat3x3<f32>; // 32 16 48
|
||||||
gamma_decoding_params: GammaTransferParams; // 80 4 32
|
gamma_decoding_params: GammaTransferParams; // 80 4 32
|
||||||
gamma_encoding_params: GammaTransferParams; // 112 4 32
|
gamma_encoding_params: GammaTransferParams; // 112 4 32
|
||||||
|
gamma_decoding_for_dst_srgb_params: GammaTransferParams; // 144 4 32
|
||||||
};
|
};
|
||||||
|
|
||||||
[[binding(0), group(0)]] var<uniform> uniforms : Uniforms;
|
[[binding(0), group(0)]] var<uniform> uniforms : Uniforms;
|
||||||
|
@ -141,6 +142,7 @@ namespace dawn_native {
|
||||||
let kConvertToDstGamutStep = 0x04u;
|
let kConvertToDstGamutStep = 0x04u;
|
||||||
let kEncodeToGammaStep = 0x08u;
|
let kEncodeToGammaStep = 0x08u;
|
||||||
let kPremultiplyStep = 0x10u;
|
let kPremultiplyStep = 0x10u;
|
||||||
|
let kDecodeForSrgbDstFormat = 0x20u;
|
||||||
|
|
||||||
// Unpremultiply step. Appling color space conversion op on premultiplied source texture
|
// Unpremultiply step. Appling color space conversion op on premultiplied source texture
|
||||||
// also needs to unpremultiply first.
|
// also needs to unpremultiply first.
|
||||||
|
@ -180,6 +182,14 @@ namespace dawn_native {
|
||||||
color = vec4<f32>(color.rgb * color.a, color.a);
|
color = vec4<f32>(color.rgb * color.a, color.a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decode for copying from non-srgb formats to srgb formats
|
||||||
|
if (bool(uniforms.steps_mask & kDecodeForSrgbDstFormat)) {
|
||||||
|
color = vec4<f32>(gamma_conversion(color.r, uniforms.gamma_decoding_for_dst_srgb_params),
|
||||||
|
gamma_conversion(color.g, uniforms.gamma_decoding_for_dst_srgb_params),
|
||||||
|
gamma_conversion(color.b, uniforms.gamma_decoding_for_dst_srgb_params),
|
||||||
|
color.a);
|
||||||
|
}
|
||||||
|
|
||||||
return color;
|
return color;
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
|
@ -207,8 +217,9 @@ namespace dawn_native {
|
||||||
std::array<float, 12> conversionMatrix = {};
|
std::array<float, 12> conversionMatrix = {};
|
||||||
GammaTransferParams gammaDecodingParams = {};
|
GammaTransferParams gammaDecodingParams = {};
|
||||||
GammaTransferParams gammaEncodingParams = {};
|
GammaTransferParams gammaEncodingParams = {};
|
||||||
|
GammaTransferParams gammaDecodingForDstSrgbParams = {};
|
||||||
};
|
};
|
||||||
static_assert(sizeof(Uniform) == 144, "");
|
static_assert(sizeof(Uniform) == 176, "");
|
||||||
|
|
||||||
// TODO(crbug.com/dawn/856): Expand copyTextureForBrowser to support any
|
// TODO(crbug.com/dawn/856): Expand copyTextureForBrowser to support any
|
||||||
// non-depth, non-stencil, non-compressed texture format pair copy. Now this API
|
// non-depth, non-stencil, non-compressed texture format pair copy. Now this API
|
||||||
|
@ -232,7 +243,9 @@ namespace dawn_native {
|
||||||
case wgpu::TextureFormat::RG16Float:
|
case wgpu::TextureFormat::RG16Float:
|
||||||
case wgpu::TextureFormat::RG32Float:
|
case wgpu::TextureFormat::RG32Float:
|
||||||
case wgpu::TextureFormat::RGBA8Unorm:
|
case wgpu::TextureFormat::RGBA8Unorm:
|
||||||
|
case wgpu::TextureFormat::RGBA8UnormSrgb:
|
||||||
case wgpu::TextureFormat::BGRA8Unorm:
|
case wgpu::TextureFormat::BGRA8Unorm:
|
||||||
|
case wgpu::TextureFormat::BGRA8UnormSrgb:
|
||||||
case wgpu::TextureFormat::RGB10A2Unorm:
|
case wgpu::TextureFormat::RGB10A2Unorm:
|
||||||
case wgpu::TextureFormat::RGBA16Float:
|
case wgpu::TextureFormat::RGBA16Float:
|
||||||
case wgpu::TextureFormat::RGBA32Float:
|
case wgpu::TextureFormat::RGBA32Float:
|
||||||
|
@ -362,6 +375,17 @@ namespace dawn_native {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Whether the format of dst texture of CopyTextureForBrowser() is srgb or non-srgb.
|
||||||
|
bool IsSrgbDstFormat(wgpu::TextureFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case wgpu::TextureFormat::RGBA8UnormSrgb:
|
||||||
|
case wgpu::TextureFormat::BGRA8UnormSrgb:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MaybeError DoCopyTextureForBrowser(DeviceBase* device,
|
MaybeError DoCopyTextureForBrowser(DeviceBase* device,
|
||||||
const ImageCopyTexture* source,
|
const ImageCopyTexture* source,
|
||||||
const ImageCopyTexture* destination,
|
const ImageCopyTexture* destination,
|
||||||
|
@ -375,6 +399,7 @@ namespace dawn_native {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isSrgbDstFormat = IsSrgbDstFormat(destination->texture->GetFormat().format);
|
||||||
RenderPipelineBase* pipeline;
|
RenderPipelineBase* pipeline;
|
||||||
DAWN_TRY_ASSIGN(pipeline, GetOrCreateCopyTextureForBrowserPipeline(
|
DAWN_TRY_ASSIGN(pipeline, GetOrCreateCopyTextureForBrowserPipeline(
|
||||||
device, destination->texture->GetFormat().format));
|
device, destination->texture->GetFormat().format));
|
||||||
|
@ -422,6 +447,7 @@ namespace dawn_native {
|
||||||
constexpr uint32_t kConvertToDstGamutStep = 0x04;
|
constexpr uint32_t kConvertToDstGamutStep = 0x04;
|
||||||
constexpr uint32_t kEncodeToGammaStep = 0x08;
|
constexpr uint32_t kEncodeToGammaStep = 0x08;
|
||||||
constexpr uint32_t kPremultiplyStep = 0x10;
|
constexpr uint32_t kPremultiplyStep = 0x10;
|
||||||
|
constexpr uint32_t kDecodeForSrgbDstFormat = 0x20;
|
||||||
|
|
||||||
if (options->srcAlphaMode == wgpu::AlphaMode::Premultiplied) {
|
if (options->srcAlphaMode == wgpu::AlphaMode::Premultiplied) {
|
||||||
if (options->needsColorSpaceConversion ||
|
if (options->needsColorSpaceConversion ||
|
||||||
|
@ -470,6 +496,25 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy to *-srgb texture should keep the bytes exactly the same as copy
|
||||||
|
// to non-srgb texture. Add an extra decode-to-linear step so that after the
|
||||||
|
// sampler of *-srgb format texture applying encoding, the bytes keeps the same
|
||||||
|
// as non-srgb format texture.
|
||||||
|
// NOTE: CopyTextureForBrowser() doesn't need to accept *-srgb format texture as
|
||||||
|
// source input. But above operation also valid for *-srgb format texture input and
|
||||||
|
// non-srgb format dst texture.
|
||||||
|
// TODO(crbug.com/dawn/1195): Reinterpret to non-srgb texture view on *-srgb texture
|
||||||
|
// and use it as render attachment when possible.
|
||||||
|
// TODO(crbug.com/dawn/1195): Opt the condition for this extra step. It is possible to
|
||||||
|
// bypass this extra step in some cases.
|
||||||
|
if (isSrgbDstFormat) {
|
||||||
|
stepsMask |= kDecodeForSrgbDstFormat;
|
||||||
|
// Get gamma-linear conversion params from https://en.wikipedia.org/wiki/SRGB with some
|
||||||
|
// mathematics. Order: {G, A, B, C, D, E, F, }
|
||||||
|
uniformData.gammaDecodingForDstSrgbParams = {
|
||||||
|
2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 4.045e-02, 0.0, 0.0};
|
||||||
|
}
|
||||||
|
|
||||||
uniformData.stepsMask = stepsMask;
|
uniformData.stepsMask = stepsMask;
|
||||||
|
|
||||||
Ref<BufferBase> uniformBuffer;
|
Ref<BufferBase> uniformBuffer;
|
||||||
|
@ -511,9 +556,9 @@ namespace dawn_native {
|
||||||
dstTextureViewDesc.baseArrayLayer = destination->origin.z;
|
dstTextureViewDesc.baseArrayLayer = destination->origin.z;
|
||||||
dstTextureViewDesc.arrayLayerCount = 1;
|
dstTextureViewDesc.arrayLayerCount = 1;
|
||||||
Ref<TextureViewBase> dstView;
|
Ref<TextureViewBase> dstView;
|
||||||
|
|
||||||
DAWN_TRY_ASSIGN(dstView,
|
DAWN_TRY_ASSIGN(dstView,
|
||||||
device->CreateTextureView(destination->texture, &dstTextureViewDesc));
|
device->CreateTextureView(destination->texture, &dstTextureViewDesc));
|
||||||
|
|
||||||
// Prepare render pass color attachment descriptor.
|
// Prepare render pass color attachment descriptor.
|
||||||
RenderPassColorAttachment colorAttachmentDesc;
|
RenderPassColorAttachment colorAttachmentDesc;
|
||||||
|
|
||||||
|
@ -546,7 +591,6 @@ namespace dawn_native {
|
||||||
|
|
||||||
// Submit command buffer.
|
// Submit command buffer.
|
||||||
device->GetQueue()->APISubmit(1, &submitCommandBuffer);
|
device->GetQueue()->APISubmit(1, &submitCommandBuffer);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -571,6 +571,17 @@ class CopyTextureForBrowser_Formats
|
||||||
GetParam().mDstFormat == wgpu::TextureFormat::BGRA8UnormSrgb;
|
GetParam().mDstFormat == wgpu::TextureFormat::BGRA8UnormSrgb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wgpu::TextureFormat GetNonSrgbFormat(wgpu::TextureFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case wgpu::TextureFormat::RGBA8UnormSrgb:
|
||||||
|
return wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
case wgpu::TextureFormat::BGRA8UnormSrgb:
|
||||||
|
return wgpu::TextureFormat::BGRA8Unorm;
|
||||||
|
default:
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DoColorConversionTest() {
|
void DoColorConversionTest() {
|
||||||
TextureSpec srcTextureSpec;
|
TextureSpec srcTextureSpec;
|
||||||
srcTextureSpec.format = GetParam().mSrcFormat;
|
srcTextureSpec.format = GetParam().mSrcFormat;
|
||||||
|
@ -627,8 +638,40 @@ class CopyTextureForBrowser_Formats
|
||||||
RunCopyExternalImageToTexture(srcTextureSpec, srcTexture, dstTextureSpec, dstTexture,
|
RunCopyExternalImageToTexture(srcTextureSpec, srcTexture, dstTextureSpec, dstTexture,
|
||||||
copySize, options);
|
copySize, options);
|
||||||
|
|
||||||
|
wgpu::Texture result;
|
||||||
|
TextureSpec resultSpec = dstTextureSpec;
|
||||||
|
|
||||||
|
// To construct the expected value for the case that dst texture is srgb format,
|
||||||
|
// we need to ensure it is byte level equal to the comparable non-srgb format texture.
|
||||||
|
// We schedule an copy from srgb texture to non-srgb texture which keeps the bytes
|
||||||
|
// same and bypass the sampler to do gamma correction when comparing the expected values
|
||||||
|
// in compute shader.
|
||||||
|
if (IsDstFormatSrgbFormats()) {
|
||||||
|
resultSpec.format = GetNonSrgbFormat(dstTextureSpec.format);
|
||||||
|
wgpu::Texture intermediateTexture = CreateTexture(
|
||||||
|
resultSpec, wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::TextureBinding |
|
||||||
|
wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc);
|
||||||
|
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
|
||||||
|
// Perform the texture to texture copy
|
||||||
|
wgpu::ImageCopyTexture dstImageCopyTexture =
|
||||||
|
utils::CreateImageCopyTexture(dstTexture, 0, {0, 0, 0});
|
||||||
|
wgpu::ImageCopyTexture intermediateImageCopyTexture =
|
||||||
|
utils::CreateImageCopyTexture(intermediateTexture, 0, {0, 0, 0});
|
||||||
|
|
||||||
|
encoder.CopyTextureToTexture(&dstImageCopyTexture, &intermediateImageCopyTexture,
|
||||||
|
&(dstTextureSpec.textureSize));
|
||||||
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
|
queue.Submit(1, &commands);
|
||||||
|
|
||||||
|
result = intermediateTexture;
|
||||||
|
} else {
|
||||||
|
result = dstTexture;
|
||||||
|
}
|
||||||
|
|
||||||
// Check Result
|
// Check Result
|
||||||
CheckResultInBuiltInComputePipeline(srcTextureSpec, srcTexture, dstTextureSpec, dstTexture,
|
CheckResultInBuiltInComputePipeline(srcTextureSpec, srcTexture, resultSpec, result,
|
||||||
copySize, options);
|
copySize, options);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1045,7 +1088,8 @@ DAWN_INSTANTIATE_TEST_P(
|
||||||
{wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::R16Float, wgpu::TextureFormat::R32Float,
|
{wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::R16Float, wgpu::TextureFormat::R32Float,
|
||||||
wgpu::TextureFormat::RG8Unorm, wgpu::TextureFormat::RG16Float,
|
wgpu::TextureFormat::RG8Unorm, wgpu::TextureFormat::RG16Float,
|
||||||
wgpu::TextureFormat::RG32Float, wgpu::TextureFormat::RGBA8Unorm,
|
wgpu::TextureFormat::RG32Float, wgpu::TextureFormat::RGBA8Unorm,
|
||||||
wgpu::TextureFormat::BGRA8Unorm, wgpu::TextureFormat::RGB10A2Unorm,
|
wgpu::TextureFormat::RGBA8UnormSrgb, wgpu::TextureFormat::BGRA8Unorm,
|
||||||
|
wgpu::TextureFormat::BGRA8UnormSrgb, wgpu::TextureFormat::RGB10A2Unorm,
|
||||||
wgpu::TextureFormat::RGBA16Float, wgpu::TextureFormat::RGBA32Float}));
|
wgpu::TextureFormat::RGBA16Float, wgpu::TextureFormat::RGBA32Float}));
|
||||||
|
|
||||||
// Verify |CopyTextureForBrowser| doing subrect copy.
|
// Verify |CopyTextureForBrowser| doing subrect copy.
|
||||||
|
|
Loading…
Reference in New Issue