Reland "Add CopyExternalTextureForBrowser()"
This is a reland of commit f392c38b67ca8456d448076b70dca87db02bb990
The new added structure ImageCopyExternalTexture used in dawn only. Adding
tags : ["dawn"] to fix compile error.
Original change's description:
> Add CopyExternalTextureForBrowser()
>
> This API accept ExternalTexture object as copy source and a dawn 2D texture
> as destination. It has similar functions as CopyTextureForBrowser().
> The API is used to support cases that source images are multi-planar format
> and want to do conversion and uploading to a dawn 2D texture.
>
> Bug: chromium:1361363
> Change-Id: Ie390acfb95b47d417f4a8faa2d1e19163d549154
> Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/105880
> Commit-Queue: Shaobo Yan <shaobo.yan@intel.com>
> Reviewed-by: Austin Eng <enga@chromium.org>
> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Bug: chromium:1361363
Change-Id: I213c3dc7fe81ccc35050592e491995d0d5425f6e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/106883
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Shaobo Yan <shaobo.yan@intel.com>
diff --git a/dawn.json b/dawn.json
index 4b2f150..554a95e 100644
--- a/dawn.json
+++ b/dawn.json
@@ -916,7 +916,6 @@
"category": "structure",
"extensible": "in",
"tags": ["dawn"],
- "_TODO": "support number as length input",
"members": [
{"name": "flip y", "type": "bool", "default": "false"},
{"name": "needs color space conversion", "type": "bool", "default": "false"},
@@ -1367,7 +1366,6 @@
"category": "structure",
"extensible": "in",
"tags": ["dawn"],
- "_TODO": "crbug.com/1316671: Mark 'visible rect' as must have after chromium side changes landed",
"members": [
{"name": "label", "type": "char", "annotation": "const*", "length": "strlen", "optional": true},
{"name": "plane 0", "type": "texture view"},
@@ -1440,6 +1438,15 @@
{"name": "aspect", "type": "texture aspect", "default": "all"}
]
},
+ "image copy external texture": {
+ "category": "structure",
+ "extensible": "in",
+ "tags": ["dawn"],
+ "members": [
+ {"name": "external texture", "type": "external texture"},
+ {"name": "origin", "type": "origin 3D"}
+ ]
+ },
"index format": {
"category": "enum",
"values": [
@@ -1722,6 +1729,17 @@
]
},
{
+ "name": "copy external texture for browser",
+ "extensible": "in",
+ "tags": ["dawn"],
+ "args": [
+ {"name": "source", "type": "image copy external texture", "annotation": "const*"},
+ {"name": "destination", "type": "image copy texture", "annotation": "const*"},
+ {"name": "copy size", "type": "extent 3D", "annotation": "const*"},
+ {"name": "options", "type": "copy texture for browser options", "annotation": "const*"}
+ ]
+ },
+ {
"name": "set label",
"returns": "void",
"args": [
diff --git a/src/dawn/native/CopyTextureForBrowserHelper.cpp b/src/dawn/native/CopyTextureForBrowserHelper.cpp
index 6f89842..fb585f9 100644
--- a/src/dawn/native/CopyTextureForBrowserHelper.cpp
+++ b/src/dawn/native/CopyTextureForBrowserHelper.cpp
@@ -25,6 +25,7 @@
#include "dawn/native/CommandEncoder.h"
#include "dawn/native/CommandValidation.h"
#include "dawn/native/Device.h"
+#include "dawn/native/ExternalTexture.h"
#include "dawn/native/InternalPipelineStore.h"
#include "dawn/native/Queue.h"
#include "dawn/native/RenderPassEncoder.h"
@@ -36,9 +37,8 @@
namespace dawn::native {
namespace {
-
-static const char sCopyTextureForBrowserShader[] = R"(
- struct GammaTransferParams {
+static const char sCopyForBrowserShader[] = R"(
+ struct GammaTransferParamsInternal {
G: f32,
A: f32,
B: f32,
@@ -49,15 +49,15 @@
padding: u32,
};
- struct Uniforms { // offset align size
- scale: vec2<f32>, // 0 8 8
- offset: vec2<f32>, // 8 8 8
- steps_mask: u32, // 16 4 4
- // implicit padding; // 20 12
- conversion_matrix: mat3x3<f32>, // 32 16 48
- gamma_decoding_params: GammaTransferParams, // 80 4 32
- gamma_encoding_params: GammaTransferParams, // 112 4 32
- gamma_decoding_for_dst_srgb_params: GammaTransferParams, // 144 4 32
+ struct Uniforms { // offset align size
+ scale: vec2<f32>, // 0 8 8
+ offset: vec2<f32>, // 8 8 8
+ steps_mask: u32, // 16 4 4
+ // implicit padding; // 20 12
+ conversion_matrix: mat3x3<f32>, // 32 16 48
+ gamma_decoding_params: GammaTransferParamsInternal, // 80 4 32
+ gamma_encoding_params: GammaTransferParamsInternal, // 112 4 32
+ gamma_decoding_for_dst_srgb_params: GammaTransferParamsInternal, // 144 4 32
};
@binding(0) @group(0) var<uniform> uniforms : Uniforms;
@@ -75,7 +75,7 @@
// nonlinear = pow(A * x + B, G) + E
// (https://source.chromium.org/chromium/chromium/src/+/main:ui/gfx/color_transform.cc;l=541)
// Expand the equation with sign() to make it handle all gamma conversions.
- fn gamma_conversion(v: f32, params: GammaTransferParams) -> f32 {
+ fn gamma_conversion(v: f32, params: GammaTransferParamsInternal) -> f32 {
// Linear part: C * x + F
if (abs(v) < params.D) {
return sign(v) * (params.C * abs(v) + params.F);
@@ -121,24 +121,23 @@
}
@binding(1) @group(0) var mySampler: sampler;
- @binding(2) @group(0) var myTexture: texture_2d<f32>;
- @fragment
- fn fs_main(
- @location(0) texcoord : vec2<f32>
- ) -> @location(0) vec4<f32> {
- // Clamp the texcoord and discard the out-of-bound pixels.
+ // Resource used in copyTexture entry point only.
+ @binding(2) @group(0) var mySourceTexture: texture_2d<f32>;
+
+ // Resource used in copyExternalTexture entry point only.
+ @binding(2) @group(0) var mySourceExternalTexture: texture_external;
+
+ fn discardIfOutsideOfCopy(texcoord : vec2<f32>) {
var clampedTexcoord =
clamp(texcoord, vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 1.0));
-
- // Swizzling of texture formats when sampling / rendering is handled by the
- // hardware so we don't need special logic in this shader. This is covered by tests.
- var color = textureSample(myTexture, mySampler, texcoord);
-
if (!all(clampedTexcoord == texcoord)) {
discard;
}
+ }
+ fn transform(srcColor : vec4<f32>) -> vec4<f32> {
+ var color = srcColor;
let kUnpremultiplyStep = 0x01u;
let kDecodeToLinearStep = 0x02u;
let kConvertToDstGamutStep = 0x04u;
@@ -203,11 +202,33 @@
return color;
}
+
+ @fragment
+ fn copyTexture(@location(0) texcoord : vec2<f32>
+ ) -> @location(0) vec4<f32> {
+ var color = textureSample(mySourceTexture, mySampler, texcoord);
+
+ // TODO(crbug.com/tint/1723): Discard before sampling should be valid.
+ discardIfOutsideOfCopy(texcoord);
+
+ return transform(color);
+ }
+
+ @fragment
+ fn copyExternalTexture(@location(0) texcoord : vec2<f32>
+ ) -> @location(0) vec4<f32> {
+ var color = textureSampleBaseClampToEdge(mySourceExternalTexture, mySampler, texcoord);
+
+ // TODO(crbug.com/tint/1723): Discard before sampling should be valid.
+ discardIfOutsideOfCopy(texcoord);
+
+ return transform(color);
+ }
)";
// Follow the same order of skcms_TransferFunction
// https://source.chromium.org/chromium/chromium/src/+/main:third_party/skia/include/third_party/skcms/skcms.h;l=46;
-struct GammaTransferParams {
+struct GammaTransferParamsInternal {
float G = 0.0;
float A = 0.0;
float B = 0.0;
@@ -226,16 +247,22 @@
uint32_t stepsMask = 0;
const std::array<uint32_t, 3> padding = {}; // 12 bytes padding
std::array<float, 12> conversionMatrix = {};
- GammaTransferParams gammaDecodingParams = {};
- GammaTransferParams gammaEncodingParams = {};
- GammaTransferParams gammaDecodingForDstSrgbParams = {};
+ GammaTransferParamsInternal gammaDecodingParams = {};
+ GammaTransferParamsInternal gammaEncodingParams = {};
+ GammaTransferParamsInternal gammaDecodingForDstSrgbParams = {};
};
static_assert(sizeof(Uniform) == 176);
+enum class SourceTextureType { Texture2D, ExternalTexture };
+
+struct TextureInfo {
+ Origin3D origin;
+ Extent3D size;
+};
+
// TODO(crbug.com/dawn/856): Expand copyTextureForBrowser to support any
// non-depth, non-stencil, non-compressed texture format pair copy.
-MaybeError ValidateCopyTextureFormatConversion(const wgpu::TextureFormat srcFormat,
- const wgpu::TextureFormat dstFormat) {
+MaybeError ValidateCopyTextureSourceFormat(const wgpu::TextureFormat srcFormat) {
switch (srcFormat) {
case wgpu::TextureFormat::BGRA8Unorm:
case wgpu::TextureFormat::RGBA8Unorm:
@@ -245,6 +272,10 @@
return DAWN_VALIDATION_ERROR("Source texture format (%s) is not supported.", srcFormat);
}
+ return {};
+}
+
+MaybeError ValidateCopyForBrowserDestinationFormat(const wgpu::TextureFormat dstFormat) {
switch (dstFormat) {
case wgpu::TextureFormat::R8Unorm:
case wgpu::TextureFormat::R16Float:
@@ -268,7 +299,8 @@
return {};
}
-RenderPipelineBase* GetCachedPipeline(InternalPipelineStore* store, wgpu::TextureFormat dstFormat) {
+RenderPipelineBase* GetCachedCopyTexturePipeline(InternalPipelineStore* store,
+ wgpu::TextureFormat dstFormat) {
auto pipeline = store->copyTextureForBrowserPipelines.find(dstFormat);
if (pipeline != store->copyTextureForBrowserPipelines.end()) {
return pipeline->second.Get();
@@ -276,120 +308,92 @@
return nullptr;
}
+RenderPipelineBase* GetCachedCopyExternalTexturePipeline(InternalPipelineStore* store,
+ wgpu::TextureFormat dstFormat) {
+ auto pipeline = store->copyExternalTextureForBrowserPipelines.find(dstFormat);
+ if (pipeline != store->copyExternalTextureForBrowserPipelines.end()) {
+ return pipeline->second.Get();
+ }
+ return nullptr;
+}
+
+ResultOrError<Ref<RenderPipelineBase>> CreateCopyForBrowserPipeline(
+ DeviceBase* device,
+ wgpu::TextureFormat dstFormat,
+ ShaderModuleBase* shaderModule,
+ const char* fragmentEntryPoint) {
+ // Prepare vertex stage.
+ VertexState vertex = {};
+ vertex.module = shaderModule;
+ vertex.entryPoint = "vs_main";
+
+ // Prepare frgament stage.
+ FragmentState fragment = {};
+ fragment.module = shaderModule;
+ fragment.entryPoint = fragmentEntryPoint;
+
+ // Prepare color state.
+ ColorTargetState target = {};
+ target.format = dstFormat;
+
+ // Create RenderPipeline.
+ RenderPipelineDescriptor renderPipelineDesc = {};
+
+ // Generate the layout based on shader modules.
+ renderPipelineDesc.layout = nullptr;
+
+ renderPipelineDesc.vertex = vertex;
+ renderPipelineDesc.fragment = &fragment;
+
+ renderPipelineDesc.primitive.topology = wgpu::PrimitiveTopology::TriangleList;
+
+ fragment.targetCount = 1;
+ fragment.targets = ⌖
+
+ return device->CreateRenderPipeline(&renderPipelineDesc);
+}
+
+ResultOrError<ShaderModuleBase*> GetOrCreateCopyForBrowserShaderModule(
+ DeviceBase* device,
+ InternalPipelineStore* store) {
+ if (store->copyForBrowser == nullptr) {
+ DAWN_TRY_ASSIGN(store->copyForBrowser,
+ utils::CreateShaderModule(device, sCopyForBrowserShader));
+ }
+
+ return store->copyForBrowser.Get();
+}
+
ResultOrError<RenderPipelineBase*> GetOrCreateCopyTextureForBrowserPipeline(
DeviceBase* device,
wgpu::TextureFormat dstFormat) {
InternalPipelineStore* store = device->GetInternalPipelineStore();
-
- if (GetCachedPipeline(store, dstFormat) == nullptr) {
- // Create vertex shader module if not cached before.
- if (store->copyTextureForBrowser == nullptr) {
- DAWN_TRY_ASSIGN(store->copyTextureForBrowser,
- utils::CreateShaderModule(device, sCopyTextureForBrowserShader));
- }
-
- ShaderModuleBase* shaderModule = store->copyTextureForBrowser.Get();
-
- // Prepare vertex stage.
- VertexState vertex = {};
- vertex.module = shaderModule;
- vertex.entryPoint = "vs_main";
-
- // Prepare frgament stage.
- FragmentState fragment = {};
- fragment.module = shaderModule;
- fragment.entryPoint = "fs_main";
-
- // Prepare color state.
- ColorTargetState target = {};
- target.format = dstFormat;
-
- // Create RenderPipeline.
- RenderPipelineDescriptor renderPipelineDesc = {};
-
- // Generate the layout based on shader modules.
- renderPipelineDesc.layout = nullptr;
-
- renderPipelineDesc.vertex = vertex;
- renderPipelineDesc.fragment = &fragment;
-
- renderPipelineDesc.primitive.topology = wgpu::PrimitiveTopology::TriangleList;
-
- fragment.targetCount = 1;
- fragment.targets = ⌖
-
+ if (GetCachedCopyTexturePipeline(store, dstFormat) == nullptr) {
+ ShaderModuleBase* shaderModule;
+ DAWN_TRY_ASSIGN(shaderModule, GetOrCreateCopyForBrowserShaderModule(device, store));
Ref<RenderPipelineBase> pipeline;
- DAWN_TRY_ASSIGN(pipeline, device->CreateRenderPipeline(&renderPipelineDesc));
+ DAWN_TRY_ASSIGN(
+ pipeline, CreateCopyForBrowserPipeline(device, dstFormat, shaderModule, "copyTexture"));
store->copyTextureForBrowserPipelines.insert({dstFormat, std::move(pipeline)});
}
- return GetCachedPipeline(store, dstFormat);
+ return GetCachedCopyTexturePipeline(store, dstFormat);
}
-} // anonymous namespace
-MaybeError ValidateCopyTextureForBrowser(DeviceBase* device,
- const ImageCopyTexture* source,
- const ImageCopyTexture* destination,
- const Extent3D* copySize,
- const CopyTextureForBrowserOptions* options) {
- DAWN_TRY(device->ValidateObject(source->texture));
- DAWN_TRY(device->ValidateObject(destination->texture));
-
- DAWN_INVALID_IF(source->texture->GetTextureState() == TextureBase::TextureState::Destroyed,
- "Source texture %s is destroyed.", source->texture);
-
- DAWN_INVALID_IF(destination->texture->GetTextureState() == TextureBase::TextureState::Destroyed,
- "Destination texture %s is destroyed.", destination->texture);
-
- DAWN_TRY_CONTEXT(ValidateImageCopyTexture(device, *source, *copySize),
- "validating the ImageCopyTexture for the source");
- DAWN_TRY_CONTEXT(ValidateImageCopyTexture(device, *destination, *copySize),
- "validating the ImageCopyTexture for the destination");
-
- DAWN_TRY_CONTEXT(ValidateTextureCopyRange(device, *source, *copySize),
- "validating that the copy fits in the source");
- DAWN_TRY_CONTEXT(ValidateTextureCopyRange(device, *destination, *copySize),
- "validating that the copy fits in the destination");
-
- DAWN_TRY(ValidateTextureToTextureCopyCommonRestrictions(*source, *destination, *copySize));
-
- DAWN_INVALID_IF(source->origin.z > 0, "Source has a non-zero z origin (%u).", source->origin.z);
- DAWN_INVALID_IF(copySize->depthOrArrayLayers > 1, "Copy is for more than one array layer (%u)",
- copySize->depthOrArrayLayers);
-
- DAWN_INVALID_IF(
- source->texture->GetSampleCount() > 1 || destination->texture->GetSampleCount() > 1,
- "The source texture sample count (%u) or the destination texture sample count (%u) is "
- "not 1.",
- source->texture->GetSampleCount(), destination->texture->GetSampleCount());
-
- DAWN_INVALID_IF(
- options->internalUsage && !device->HasFeature(Feature::DawnInternalUsages),
- "The internalUsage is true while the dawn-internal-usages feature is not enabled.");
- UsageValidationMode mode =
- options->internalUsage ? UsageValidationMode::Internal : UsageValidationMode::Default;
- DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc, mode));
- DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::TextureBinding, mode));
- DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst, mode));
- DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::RenderAttachment, mode));
-
- DAWN_TRY(ValidateCopyTextureFormatConversion(source->texture->GetFormat().format,
- destination->texture->GetFormat().format));
-
- DAWN_INVALID_IF(options->nextInChain != nullptr, "nextInChain must be nullptr");
-
- DAWN_TRY(ValidateAlphaMode(options->srcAlphaMode));
- DAWN_TRY(ValidateAlphaMode(options->dstAlphaMode));
-
- if (options->needsColorSpaceConversion) {
- DAWN_INVALID_IF(options->srcTransferFunctionParameters == nullptr,
- "srcTransferFunctionParameters is nullptr when doing color conversion");
- DAWN_INVALID_IF(options->conversionMatrix == nullptr,
- "conversionMatrix is nullptr when doing color conversion");
- DAWN_INVALID_IF(options->dstTransferFunctionParameters == nullptr,
- "dstTransferFunctionParameters is nullptr when doing color conversion");
+ResultOrError<RenderPipelineBase*> GetOrCreateCopyExternalTextureForBrowserPipeline(
+ DeviceBase* device,
+ wgpu::TextureFormat dstFormat) {
+ InternalPipelineStore* store = device->GetInternalPipelineStore();
+ if (GetCachedCopyExternalTexturePipeline(store, dstFormat) == nullptr) {
+ ShaderModuleBase* shaderModule;
+ DAWN_TRY_ASSIGN(shaderModule, GetOrCreateCopyForBrowserShaderModule(device, store));
+ Ref<RenderPipelineBase> pipeline;
+ DAWN_TRY_ASSIGN(pipeline, CreateCopyForBrowserPipeline(device, dstFormat, shaderModule,
+ "copyExternalTexture"));
+ store->copyExternalTextureForBrowserPipelines.insert({dstFormat, std::move(pipeline)});
}
- return {};
+
+ return GetCachedCopyExternalTexturePipeline(store, dstFormat);
}
// Whether the format of dst texture of CopyTextureForBrowser() is srgb or non-srgb.
@@ -403,11 +407,14 @@
}
}
-MaybeError DoCopyTextureForBrowser(DeviceBase* device,
- const ImageCopyTexture* source,
- const ImageCopyTexture* destination,
- const Extent3D* copySize,
- const CopyTextureForBrowserOptions* options) {
+template <typename T>
+MaybeError DoCopyForBrowser(DeviceBase* device,
+ const TextureInfo* sourceInfo,
+ T* sourceResource,
+ const ImageCopyTexture* destination,
+ const Extent3D* copySize,
+ const CopyTextureForBrowserOptions* options,
+ RenderPipelineBase* pipeline) {
// TODO(crbug.com/dawn/856): In D3D12 and Vulkan, compatible texture format can directly
// copy to each other. This can be a potential fast path.
@@ -416,23 +423,16 @@
return {};
}
- bool isSrgbDstFormat = IsSrgbDstFormat(destination->texture->GetFormat().format);
- RenderPipelineBase* pipeline;
- DAWN_TRY_ASSIGN(pipeline, GetOrCreateCopyTextureForBrowserPipeline(
- device, destination->texture->GetFormat().format));
-
// Prepare bind group layout.
Ref<BindGroupLayoutBase> layout;
DAWN_TRY_ASSIGN(layout, pipeline->GetBindGroupLayout(0));
- Extent3D srcTextureSize = source->texture->GetSize();
-
// Prepare binding 0 resource: uniform buffer.
Uniform uniformData = {
- copySize->width / static_cast<float>(srcTextureSize.width),
- copySize->height / static_cast<float>(srcTextureSize.height), // scale
- source->origin.x / static_cast<float>(srcTextureSize.width),
- source->origin.y / static_cast<float>(srcTextureSize.height) // offset
+ copySize->width / static_cast<float>(sourceInfo->size.width),
+ copySize->height / static_cast<float>(sourceInfo->size.height), // scale
+ sourceInfo->origin.x / static_cast<float>(sourceInfo->size.width),
+ sourceInfo->origin.y / static_cast<float>(sourceInfo->size.height) // offset
};
// Handle flipY. FlipY here means we flip the source texture firstly and then
@@ -440,7 +440,7 @@
// need to unpack the flip.
if (options->flipY) {
uniformData.scaleY *= -1.0;
- uniformData.offsetY += copySize->height / static_cast<float>(srcTextureSize.height);
+ uniformData.offsetY += copySize->height / static_cast<float>(sourceInfo->size.height);
}
uint32_t stepsMask = 0u;
@@ -528,6 +528,7 @@
// 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.
+ bool isSrgbDstFormat = IsSrgbDstFormat(destination->texture->GetFormat().format);
if (isSrgbDstFormat) {
stepsMask |= kDecodeForSrgbDstFormat;
// Get gamma-linear conversion params from https://en.wikipedia.org/wiki/SRGB with some
@@ -536,6 +537,7 @@
2.4, 1.0 / 1.055, 0.055 / 1.055, 1.0 / 12.92, 4.045e-02, 0.0, 0.0};
}
+ // Upload uniform data
uniformData.stepsMask = stepsMask;
Ref<BufferBase> uniformBuffer;
@@ -550,23 +552,13 @@
Ref<SamplerBase> sampler;
DAWN_TRY_ASSIGN(sampler, device->CreateSampler(&samplerDesc));
- // Prepare binding 2 resource: sampled texture
- TextureViewDescriptor srcTextureViewDesc = {};
- srcTextureViewDesc.dimension = wgpu::TextureViewDimension::e2D;
- srcTextureViewDesc.baseMipLevel = source->mipLevel;
- srcTextureViewDesc.mipLevelCount = 1;
- srcTextureViewDesc.arrayLayerCount = 1;
- Ref<TextureViewBase> srcTextureView;
- DAWN_TRY_ASSIGN(srcTextureView,
- device->CreateTextureView(source->texture, &srcTextureViewDesc));
-
// Create bind group after all binding entries are set.
UsageValidationMode mode =
options->internalUsage ? UsageValidationMode::Internal : UsageValidationMode::Default;
Ref<BindGroupBase> bindGroup;
DAWN_TRY_ASSIGN(bindGroup, utils::MakeBindGroup(
device, layout,
- {{0, uniformBuffer}, {1, sampler}, {2, srcTextureView}}, mode));
+ {{0, uniformBuffer}, {1, sampler}, {2, sourceResource}}, mode));
// Create command encoder.
CommandEncoderDescriptor commandEncoderDesc;
@@ -621,4 +613,166 @@
return {};
}
+MaybeError ValidateCopyForBrowserCommonRestrictions(DeviceBase* device,
+ const ImageCopyTexture& destination,
+ const Extent3D& copySize,
+ const CopyTextureForBrowserOptions& options) {
+ DAWN_TRY(device->ValidateObject(destination.texture));
+ DAWN_INVALID_IF(destination.texture->GetTextureState() == TextureBase::TextureState::Destroyed,
+ "Destination texture %s is destroyed.", destination.texture);
+ DAWN_TRY_CONTEXT(ValidateImageCopyTexture(device, destination, copySize),
+ "validating the ImageCopyTexture for the destination");
+ DAWN_TRY_CONTEXT(ValidateTextureCopyRange(device, destination, copySize),
+ "validating that the copy fits in the destination");
+
+ UsageValidationMode mode =
+ options.internalUsage ? UsageValidationMode::Internal : UsageValidationMode::Default;
+ DAWN_TRY(ValidateCanUseAs(destination.texture, wgpu::TextureUsage::CopyDst, mode));
+ DAWN_TRY(ValidateCanUseAs(destination.texture, wgpu::TextureUsage::RenderAttachment, mode));
+
+ DAWN_INVALID_IF(copySize.depthOrArrayLayers > 1, "Copy is for more than one array layer (%u)",
+ copySize.depthOrArrayLayers);
+
+ DAWN_INVALID_IF(destination.texture->GetSampleCount() > 1,
+ "The destination texture sample count (%u) is not 1.",
+ destination.texture->GetSampleCount());
+
+ DAWN_TRY(ValidateCopyForBrowserDestinationFormat(destination.texture->GetFormat().format));
+
+ // The valid destination formats are all color formats.
+ DAWN_INVALID_IF(
+ destination.aspect != wgpu::TextureAspect::All,
+ "Destination %s aspect (%s) doesn't select all the aspects of the destination format.",
+ destination.texture, destination.aspect);
+
+ DAWN_INVALID_IF(options.nextInChain != nullptr, "nextInChain must be nullptr");
+
+ DAWN_TRY(ValidateAlphaMode(options.srcAlphaMode));
+ DAWN_TRY(ValidateAlphaMode(options.dstAlphaMode));
+
+ if (options.needsColorSpaceConversion) {
+ DAWN_INVALID_IF(options.srcTransferFunctionParameters == nullptr,
+ "srcTransferFunctionParameters is nullptr when doing color conversion");
+ DAWN_INVALID_IF(options.conversionMatrix == nullptr,
+ "conversionMatrix is nullptr when doing color conversion");
+ DAWN_INVALID_IF(options.dstTransferFunctionParameters == nullptr,
+ "dstTransferFunctionParameters is nullptr when doing color conversion");
+ }
+ return {};
+}
+} // anonymous namespace
+
+MaybeError ValidateCopyTextureForBrowser(DeviceBase* device,
+ const ImageCopyTexture* source,
+ const ImageCopyTexture* destination,
+ const Extent3D* copySize,
+ const CopyTextureForBrowserOptions* options) {
+ DAWN_TRY(device->ValidateObject(source->texture));
+
+ DAWN_INVALID_IF(source->texture->GetTextureState() == TextureBase::TextureState::Destroyed,
+ "Source texture %s is destroyed.", source->texture);
+
+ DAWN_TRY_CONTEXT(ValidateImageCopyTexture(device, *source, *copySize),
+ "validating the ImageCopyTexture for the source");
+
+ DAWN_TRY_CONTEXT(ValidateTextureCopyRange(device, *source, *copySize),
+ "validating that the copy fits in the source");
+
+ DAWN_TRY(ValidateTextureToTextureCopyCommonRestrictions(*source, *destination, *copySize));
+
+ DAWN_INVALID_IF(source->origin.z > 0, "Source has a non-zero z origin (%u).", source->origin.z);
+
+ DAWN_INVALID_IF(source->texture->GetSampleCount() > 1,
+ "The source texture sample count (%u) is not 1. ",
+ source->texture->GetSampleCount());
+
+ DAWN_INVALID_IF(
+ options->internalUsage && !device->HasFeature(Feature::DawnInternalUsages),
+ "The internalUsage is true while the dawn-internal-usages feature is not enabled.");
+ UsageValidationMode mode =
+ options->internalUsage ? UsageValidationMode::Internal : UsageValidationMode::Default;
+ DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc, mode));
+ DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::TextureBinding, mode));
+
+ DAWN_TRY(ValidateCopyTextureSourceFormat(source->texture->GetFormat().format));
+
+ DAWN_TRY(ValidateCopyForBrowserCommonRestrictions(device, *destination, *copySize, *options));
+ return {};
+}
+
+MaybeError ValidateCopyExternalTextureForBrowser(DeviceBase* device,
+ const ImageCopyExternalTexture* source,
+ const ImageCopyTexture* destination,
+ const Extent3D* copySize,
+ const CopyTextureForBrowserOptions* options) {
+ DAWN_TRY(device->ValidateObject(source->externalTexture));
+
+ DAWN_TRY(source->externalTexture->ValidateCanUseInSubmitNow());
+
+ const Extent2D& sourceVisibleRect = source->externalTexture->GetVisibleRect();
+
+ // All texture dimensions are in uint32_t so by doing checks in uint64_t we avoid
+ // overflows.
+ DAWN_INVALID_IF(
+ static_cast<uint64_t>(source->origin.x) + static_cast<uint64_t>(copySize->width) >
+ static_cast<uint64_t>(sourceVisibleRect.width) ||
+ static_cast<uint64_t>(source->origin.y) + static_cast<uint64_t>(copySize->height) >
+ static_cast<uint64_t>(sourceVisibleRect.height) ||
+ static_cast<uint64_t>(source->origin.z) > 0,
+ "Texture copy range (origin: %s, copySize: %s) touches outside of %s visible size (%s).",
+ &source->origin, copySize, source->externalTexture, &sourceVisibleRect);
+
+ DAWN_INVALID_IF(source->origin.z > 0, "Source has a non-zero z origin (%u).", source->origin.z);
+
+ DAWN_INVALID_IF(
+ options->internalUsage && !device->HasFeature(Feature::DawnInternalUsages),
+ "The internalUsage is true while the dawn-internal-usages feature is not enabled.");
+
+ DAWN_TRY(ValidateCopyForBrowserCommonRestrictions(device, *destination, *copySize, *options));
+
+ return {};
+}
+
+MaybeError DoCopyExternalTextureForBrowser(DeviceBase* device,
+ const ImageCopyExternalTexture* source,
+ const ImageCopyTexture* destination,
+ const Extent3D* copySize,
+ const CopyTextureForBrowserOptions* options) {
+ TextureInfo info;
+ info.origin = source->origin;
+ const Extent2D& visibleRect = source->externalTexture->GetVisibleRect();
+ info.size = {visibleRect.width, visibleRect.height, 1};
+
+ RenderPipelineBase* pipeline;
+ DAWN_TRY_ASSIGN(pipeline, GetOrCreateCopyExternalTextureForBrowserPipeline(
+ device, destination->texture->GetFormat().format));
+ return DoCopyForBrowser<ExternalTextureBase>(device, &info, source->externalTexture,
+ destination, copySize, options, pipeline);
+}
+
+MaybeError DoCopyTextureForBrowser(DeviceBase* device,
+ const ImageCopyTexture* source,
+ const ImageCopyTexture* destination,
+ const Extent3D* copySize,
+ const CopyTextureForBrowserOptions* options) {
+ TextureInfo info;
+ info.origin = source->origin;
+ info.size = source->texture->GetSize();
+
+ Ref<TextureViewBase> srcTextureView = nullptr;
+ TextureViewDescriptor srcTextureViewDesc = {};
+ srcTextureViewDesc.dimension = wgpu::TextureViewDimension::e2D;
+ srcTextureViewDesc.baseMipLevel = source->mipLevel;
+ srcTextureViewDesc.mipLevelCount = 1;
+ srcTextureViewDesc.arrayLayerCount = 1;
+ DAWN_TRY_ASSIGN(srcTextureView,
+ device->CreateTextureView(source->texture, &srcTextureViewDesc));
+
+ RenderPipelineBase* pipeline;
+ DAWN_TRY_ASSIGN(pipeline, GetOrCreateCopyTextureForBrowserPipeline(
+ device, destination->texture->GetFormat().format));
+
+ return DoCopyForBrowser<TextureViewBase>(device, &info, srcTextureView.Get(), destination,
+ copySize, options, pipeline);
+}
} // namespace dawn::native
diff --git a/src/dawn/native/CopyTextureForBrowserHelper.h b/src/dawn/native/CopyTextureForBrowserHelper.h
index 0e427ba..0d496bb 100644
--- a/src/dawn/native/CopyTextureForBrowserHelper.h
+++ b/src/dawn/native/CopyTextureForBrowserHelper.h
@@ -30,12 +30,23 @@
const Extent3D* copySize,
const CopyTextureForBrowserOptions* options);
+MaybeError ValidateCopyExternalTextureForBrowser(DeviceBase* device,
+ const ImageCopyExternalTexture* source,
+ const ImageCopyTexture* destination,
+ const Extent3D* copySize,
+ const CopyTextureForBrowserOptions* options);
+
MaybeError DoCopyTextureForBrowser(DeviceBase* device,
const ImageCopyTexture* source,
const ImageCopyTexture* destination,
const Extent3D* copySize,
const CopyTextureForBrowserOptions* options);
+MaybeError DoCopyExternalTextureForBrowser(DeviceBase* device,
+ const ImageCopyExternalTexture* source,
+ const ImageCopyTexture* destination,
+ const Extent3D* copySize,
+ const CopyTextureForBrowserOptions* options);
} // namespace dawn::native
#endif // SRC_DAWN_NATIVE_COPYTEXTUREFORBROWSERHELPER_H_
diff --git a/src/dawn/native/InternalPipelineStore.h b/src/dawn/native/InternalPipelineStore.h
index b8386d5..6234ec0 100644
--- a/src/dawn/native/InternalPipelineStore.h
+++ b/src/dawn/native/InternalPipelineStore.h
@@ -35,8 +35,10 @@
~InternalPipelineStore();
std::unordered_map<wgpu::TextureFormat, Ref<RenderPipelineBase>> copyTextureForBrowserPipelines;
+ std::unordered_map<wgpu::TextureFormat, Ref<RenderPipelineBase>>
+ copyExternalTextureForBrowserPipelines;
- Ref<ShaderModuleBase> copyTextureForBrowser;
+ Ref<ShaderModuleBase> copyForBrowser;
Ref<ComputePipelineBase> timestampComputePipeline;
Ref<ShaderModuleBase> timestampCS;
diff --git a/src/dawn/native/Queue.cpp b/src/dawn/native/Queue.cpp
index 9881d65..f8dd673 100644
--- a/src/dawn/native/Queue.cpp
+++ b/src/dawn/native/Queue.cpp
@@ -370,6 +370,14 @@
CopyTextureForBrowserInternal(source, destination, copySize, options));
}
+void QueueBase::APICopyExternalTextureForBrowser(const ImageCopyExternalTexture* source,
+ const ImageCopyTexture* destination,
+ const Extent3D* copySize,
+ const CopyTextureForBrowserOptions* options) {
+ GetDevice()->ConsumedError(
+ CopyExternalTextureForBrowserInternal(source, destination, copySize, options));
+}
+
MaybeError QueueBase::CopyTextureForBrowserInternal(const ImageCopyTexture* source,
const ImageCopyTexture* destination,
const Extent3D* copySize,
@@ -384,6 +392,21 @@
return DoCopyTextureForBrowser(GetDevice(), source, destination, copySize, options);
}
+MaybeError QueueBase::CopyExternalTextureForBrowserInternal(
+ const ImageCopyExternalTexture* source,
+ const ImageCopyTexture* destination,
+ const Extent3D* copySize,
+ const CopyTextureForBrowserOptions* options) {
+ if (GetDevice()->IsValidationEnabled()) {
+ DAWN_TRY_CONTEXT(ValidateCopyExternalTextureForBrowser(GetDevice(), source, destination,
+ copySize, options),
+ "validating CopyExternalTextureForBrowser from %s to %s",
+ source->externalTexture, destination->texture);
+ }
+
+ return DoCopyExternalTextureForBrowser(GetDevice(), source, destination, copySize, options);
+}
+
MaybeError QueueBase::ValidateSubmit(uint32_t commandCount,
CommandBufferBase* const* commands) const {
TRACE_EVENT0(GetDevice()->GetPlatform(), Validation, "Queue::ValidateSubmit");
diff --git a/src/dawn/native/Queue.h b/src/dawn/native/Queue.h
index 5bfd9a0..8495987 100644
--- a/src/dawn/native/Queue.h
+++ b/src/dawn/native/Queue.h
@@ -58,6 +58,10 @@
const ImageCopyTexture* destination,
const Extent3D* copySize,
const CopyTextureForBrowserOptions* options);
+ void APICopyExternalTextureForBrowser(const ImageCopyExternalTexture* source,
+ const ImageCopyTexture* destination,
+ const Extent3D* copySize,
+ const CopyTextureForBrowserOptions* options);
MaybeError WriteBuffer(BufferBase* buffer,
uint64_t bufferOffset,
@@ -82,6 +86,10 @@
const ImageCopyTexture* destination,
const Extent3D* copySize,
const CopyTextureForBrowserOptions* options);
+ MaybeError CopyExternalTextureForBrowserInternal(const ImageCopyExternalTexture* source,
+ const ImageCopyTexture* destination,
+ const Extent3D* copySize,
+ const CopyTextureForBrowserOptions* options);
virtual MaybeError SubmitImpl(uint32_t commandCount, CommandBufferBase* const* commands) = 0;
virtual MaybeError WriteBufferImpl(BufferBase* buffer,
diff --git a/src/dawn/native/utils/WGPUHelpers.cpp b/src/dawn/native/utils/WGPUHelpers.cpp
index 2a7a5e0..ffa2980 100644
--- a/src/dawn/native/utils/WGPUHelpers.cpp
+++ b/src/dawn/native/utils/WGPUHelpers.cpp
@@ -26,6 +26,7 @@
#include "dawn/native/BindGroupLayout.h"
#include "dawn/native/Buffer.h"
#include "dawn/native/Device.h"
+#include "dawn/native/ExternalTexture.h"
#include "dawn/native/PipelineLayout.h"
#include "dawn/native/Queue.h"
#include "dawn/native/Sampler.h"
@@ -140,6 +141,12 @@
BindingInitializationHelper::BindingInitializationHelper(uint32_t binding,
const Ref<TextureViewBase>& textureView)
: binding(binding), textureView(textureView) {}
+BindingInitializationHelper::BindingInitializationHelper(
+ uint32_t binding,
+ const Ref<ExternalTextureBase>& externalTexture)
+ : binding(binding), externalTexture(externalTexture) {
+ externalBindingEntry.externalTexture = externalTexture.Get();
+}
BindingInitializationHelper::BindingInitializationHelper(uint32_t binding,
const Ref<BufferBase>& buffer,
@@ -159,6 +166,10 @@
result.offset = offset;
result.size = size;
+ if (externalTexture != nullptr) {
+ result.nextInChain = &externalBindingEntry;
+ }
+
return result;
}
diff --git a/src/dawn/native/utils/WGPUHelpers.h b/src/dawn/native/utils/WGPUHelpers.h
index 45cfa46..036d00d 100644
--- a/src/dawn/native/utils/WGPUHelpers.h
+++ b/src/dawn/native/utils/WGPUHelpers.h
@@ -95,6 +95,7 @@
struct BindingInitializationHelper {
BindingInitializationHelper(uint32_t binding, const Ref<SamplerBase>& sampler);
BindingInitializationHelper(uint32_t binding, const Ref<TextureViewBase>& textureView);
+ BindingInitializationHelper(uint32_t binding, const Ref<ExternalTextureBase>& externalTexture);
BindingInitializationHelper(uint32_t binding,
const Ref<BufferBase>& buffer,
uint64_t offset = 0,
@@ -107,6 +108,8 @@
Ref<SamplerBase> sampler;
Ref<TextureViewBase> textureView;
Ref<BufferBase> buffer;
+ Ref<ExternalTextureBase> externalTexture;
+ ExternalTextureBindingEntry externalBindingEntry;
uint64_t offset = 0;
uint64_t size = 0;
};
diff --git a/src/dawn/native/webgpu_absl_format.cpp b/src/dawn/native/webgpu_absl_format.cpp
index 8eddf46..a33ab42 100644
--- a/src/dawn/native/webgpu_absl_format.cpp
+++ b/src/dawn/native/webgpu_absl_format.cpp
@@ -46,6 +46,18 @@
}
absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
+ const Extent2D* value,
+ const absl::FormatConversionSpec& spec,
+ absl::FormatSink* s) {
+ if (value == nullptr) {
+ s->Append("[null]");
+ return {true};
+ }
+ s->Append(absl::StrFormat("[Extent2D width:%u, height:%u]", value->width, value->height));
+ return {true};
+}
+
+absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
const Extent3D* value,
const absl::FormatConversionSpec& spec,
absl::FormatSink* s) {
diff --git a/src/dawn/native/webgpu_absl_format.h b/src/dawn/native/webgpu_absl_format.h
index 4c0c667..23964ad 100644
--- a/src/dawn/native/webgpu_absl_format.h
+++ b/src/dawn/native/webgpu_absl_format.h
@@ -29,6 +29,12 @@
absl::FormatConvertResult<absl::FormatConversionCharSet::kString>
AbslFormatConvert(const Color* value, const absl::FormatConversionSpec& spec, absl::FormatSink* s);
+struct Extent2D;
+absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
+ const Extent2D* value,
+ const absl::FormatConversionSpec& spec,
+ absl::FormatSink* s);
+
struct Extent3D;
absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
const Extent3D* value,
diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn
index 6f5ba74..c1e0137 100644
--- a/src/dawn/tests/BUILD.gn
+++ b/src/dawn/tests/BUILD.gn
@@ -438,6 +438,7 @@
"end2end/ComputeLayoutMemoryBufferTests.cpp",
"end2end/ComputeSharedMemoryTests.cpp",
"end2end/ComputeStorageBufferBarrierTests.cpp",
+ "end2end/CopyExternalTextureForBrowserTests.cpp",
"end2end/CopyTests.cpp",
"end2end/CopyTextureForBrowserTests.cpp",
"end2end/CreatePipelineAsyncTests.cpp",
diff --git a/src/dawn/tests/end2end/CopyExternalTextureForBrowserTests.cpp b/src/dawn/tests/end2end/CopyExternalTextureForBrowserTests.cpp
new file mode 100644
index 0000000..549e712
--- /dev/null
+++ b/src/dawn/tests/end2end/CopyExternalTextureForBrowserTests.cpp
@@ -0,0 +1,207 @@
+// Copyright 2022 The Dawn Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <vector>
+
+#include "dawn/tests/DawnTest.h"
+#include "dawn/utils/ComboRenderPipelineDescriptor.h"
+#include "dawn/utils/WGPUHelpers.h"
+
+namespace {
+
+wgpu::Texture Create2DTexture(wgpu::Device device,
+ uint32_t width,
+ uint32_t height,
+ wgpu::TextureFormat format,
+ wgpu::TextureUsage usage) {
+ wgpu::TextureDescriptor descriptor;
+ descriptor.dimension = wgpu::TextureDimension::e2D;
+ descriptor.size.width = width;
+ descriptor.size.height = height;
+ descriptor.size.depthOrArrayLayers = 1;
+ descriptor.sampleCount = 1;
+ descriptor.format = format;
+ descriptor.mipLevelCount = 1;
+ descriptor.usage = usage;
+ return device.CreateTexture(&descriptor);
+}
+
+static constexpr uint32_t kWidth = 4;
+static constexpr uint32_t kHeight = 4;
+
+std::array<std::array<utils::RGBA8, 4>, 4> kDefaultSourceRGBA = {
+ std::array<utils::RGBA8, 4>(
+ {utils::RGBA8::kBlack, utils::RGBA8::kBlack, utils::RGBA8::kRed, utils::RGBA8::kRed}),
+ std::array<utils::RGBA8, 4>(
+ {utils::RGBA8::kBlack, utils::RGBA8::kBlack, utils::RGBA8::kRed, utils::RGBA8::kRed}),
+ std::array<utils::RGBA8, 4>(
+ {utils::RGBA8::kGreen, utils::RGBA8::kGreen, utils::RGBA8::kBlue, utils::RGBA8::kBlue}),
+ std::array<utils::RGBA8, 4>(
+ {utils::RGBA8::kGreen, utils::RGBA8::kGreen, utils::RGBA8::kBlue, utils::RGBA8::kBlue})};
+
+template <typename Parent>
+class CopyExternalTextureForBrowserTests : public Parent {
+ protected:
+ wgpu::ExternalTexture CreateDefaultExternalTexture() {
+ // y plane
+ wgpu::TextureDescriptor externalTexturePlane0Desc = {};
+ externalTexturePlane0Desc.size = {kWidth, kHeight, 1};
+ externalTexturePlane0Desc.usage = wgpu::TextureUsage::TextureBinding |
+ wgpu::TextureUsage::CopyDst |
+ wgpu::TextureUsage::RenderAttachment;
+ externalTexturePlane0Desc.format = wgpu::TextureFormat::R8Unorm;
+ wgpu::Texture externalTexturePlane0 =
+ this->device.CreateTexture(&externalTexturePlane0Desc);
+
+ // The value Ref to ExternalTextureTest.cpp:
+ // {0.0, .5, .5, utils::RGBA8::kBlack, 0.0f},
+ // {0.2126, 0.4172, 1.0, utils::RGBA8::kRed, 1.0f},
+ // {0.7152, 0.1402, 0.0175, utils::RGBA8::kGreen, 0.0f},
+ // {0.0722, 1.0, 0.4937, utils::RGBA8::kBlue, 0.0f},
+ wgpu::ImageCopyTexture plane0 = {};
+ plane0.texture = externalTexturePlane0;
+ std::array<uint8_t, 16> yPlaneData = {0, 0, 54, 54, 0, 0, 54, 54,
+ 182, 182, 18, 18, 182, 182, 18, 18};
+
+ wgpu::TextureDataLayout externalTexturePlane0DataLayout = {};
+ externalTexturePlane0DataLayout.bytesPerRow = 4;
+
+ this->queue.WriteTexture(&plane0, yPlaneData.data(), yPlaneData.size() * sizeof(float),
+ &externalTexturePlane0DataLayout, &externalTexturePlane0Desc.size);
+
+ // uv plane
+ wgpu::TextureDescriptor externalTexturePlane1Desc = {};
+ externalTexturePlane1Desc.size = {kWidth / 2, kHeight / 2, 1};
+ externalTexturePlane1Desc.usage = wgpu::TextureUsage::TextureBinding |
+ wgpu::TextureUsage::CopyDst |
+ wgpu::TextureUsage::RenderAttachment;
+ externalTexturePlane1Desc.format = wgpu::TextureFormat::RG8Unorm;
+ wgpu::Texture externalTexturePlane1 =
+ this->device.CreateTexture(&externalTexturePlane1Desc);
+
+ wgpu::ImageCopyTexture plane1 = {};
+ plane1.texture = externalTexturePlane1;
+ std::array<uint8_t, 8> uvPlaneData = {
+ 128, 128, 106, 255, 36, 4, 255, 126,
+ };
+
+ wgpu::TextureDataLayout externalTexturePlane1DataLayout = {};
+ externalTexturePlane1DataLayout.bytesPerRow = 4;
+
+ this->queue.WriteTexture(&plane1, uvPlaneData.data(), uvPlaneData.size() * sizeof(float),
+ &externalTexturePlane1DataLayout, &externalTexturePlane1Desc.size);
+
+ // Create an ExternalTextureDescriptor from the texture views
+ wgpu::ExternalTextureDescriptor externalDesc;
+ utils::ColorSpaceConversionInfo info =
+ utils::GetYUVBT709ToRGBSRGBColorSpaceConversionInfo();
+ externalDesc.yuvToRgbConversionMatrix = info.yuvToRgbConversionMatrix.data();
+ externalDesc.gamutConversionMatrix = info.gamutConversionMatrix.data();
+ externalDesc.srcTransferFunctionParameters = info.srcTransferFunctionParameters.data();
+ externalDesc.dstTransferFunctionParameters = info.dstTransferFunctionParameters.data();
+
+ externalDesc.plane0 = externalTexturePlane0.CreateView();
+ externalDesc.plane1 = externalTexturePlane1.CreateView();
+
+ externalDesc.visibleRect = {kWidth, kHeight};
+
+ // Import the external texture
+ return this->device.CreateExternalTexture(&externalDesc);
+ }
+
+ std::vector<utils::RGBA8> GetDefaultExpectedData(bool flipY,
+ wgpu::Origin3D origin,
+ wgpu::Extent3D rect) {
+ std::vector<utils::RGBA8> expected;
+ for (uint32_t row = origin.y; row < origin.y + rect.height; ++row) {
+ for (uint32_t col = origin.x; col < origin.x + rect.width; ++col) {
+ if (flipY) {
+ uint32_t flippedRow = kHeight - row - 1;
+ expected.push_back(kDefaultSourceRGBA[flippedRow][col]);
+ } else {
+ expected.push_back(kDefaultSourceRGBA[row][col]);
+ }
+ }
+ }
+
+ return expected;
+ }
+};
+
+using FlipY = bool;
+using SrcOrigin = wgpu::Origin3D;
+using DstOrigin = wgpu::Origin3D;
+
+std::ostream& operator<<(std::ostream& o, wgpu::Origin3D origin) {
+ o << origin.x << ", " << origin.y << ", " << origin.z;
+ return o;
+}
+
+DAWN_TEST_PARAM_STRUCT(CopyTestParams, SrcOrigin, DstOrigin, FlipY);
+
+class CopyExternalTextureForBrowserTests_Basic
+ : public CopyExternalTextureForBrowserTests<DawnTestWithParams<CopyTestParams>> {
+ protected:
+ void DoBasicCopyTest(const wgpu::Origin3D& srcOrigin,
+ const wgpu::Origin3D& dstOrigin,
+ const wgpu::Extent3D& copySize,
+ const wgpu::CopyTextureForBrowserOptions options = {}) {
+ wgpu::ExternalTexture externalTexture = CreateDefaultExternalTexture();
+ wgpu::ImageCopyExternalTexture srcImageCopyExternalTexture;
+ srcImageCopyExternalTexture.externalTexture = externalTexture;
+ srcImageCopyExternalTexture.origin = srcOrigin;
+
+ wgpu::Texture dstTexture =
+ Create2DTexture(device, kWidth, kHeight, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc |
+ wgpu::TextureUsage::CopyDst);
+ wgpu::ImageCopyTexture dstImageCopyTexture =
+ utils::CreateImageCopyTexture(dstTexture, 0, dstOrigin);
+
+ queue.CopyExternalTextureForBrowser(&srcImageCopyExternalTexture, &dstImageCopyTexture,
+ ©Size, &options);
+ std::vector<utils::RGBA8> expected =
+ GetDefaultExpectedData(options.flipY, srcOrigin, copySize);
+
+ EXPECT_TEXTURE_EQ(expected.data(), dstTexture, dstOrigin, copySize);
+ }
+};
+} // anonymous namespace
+
+TEST_P(CopyExternalTextureForBrowserTests_Basic, FullCopy) {
+ DAWN_SUPPRESS_TEST_IF(IsOpenGLES());
+ DAWN_SUPPRESS_TEST_IF(IsOpenGL() && IsLinux());
+
+ wgpu::CopyTextureForBrowserOptions options = {};
+ options.flipY = GetParam().mFlipY;
+
+ wgpu::Origin3D srcOrigin = GetParam().mSrcOrigin;
+ wgpu::Origin3D dstOrigin = GetParam().mDstOrigin;
+
+ wgpu::Extent3D copySize = {kWidth, kHeight};
+
+ if (srcOrigin.x != 0 || srcOrigin.y != 0 || dstOrigin.x != 0 || dstOrigin.y != 0) {
+ copySize.width = kWidth / 2;
+ copySize.height = kHeight / 2;
+ }
+
+ DoBasicCopyTest(srcOrigin, dstOrigin, copySize, options);
+}
+
+DAWN_INSTANTIATE_TEST_P(CopyExternalTextureForBrowserTests_Basic,
+ {D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
+ VulkanBackend()},
+ std::vector<wgpu::Origin3D>({{0, 0}, {2, 0}, {0, 2}, {2, 2}}),
+ std::vector<wgpu::Origin3D>({{0, 0}, {2, 0}, {0, 2}, {2, 2}}),
+ std::vector<bool>({false, true}));
diff --git a/src/dawn/tests/end2end/ExternalTextureTests.cpp b/src/dawn/tests/end2end/ExternalTextureTests.cpp
index 5511437..065836b 100644
--- a/src/dawn/tests/end2end/ExternalTextureTests.cpp
+++ b/src/dawn/tests/end2end/ExternalTextureTests.cpp
@@ -39,10 +39,10 @@
protected:
wgpu::ExternalTextureDescriptor CreateDefaultExternalTextureDescriptor() {
wgpu::ExternalTextureDescriptor desc;
- desc.yuvToRgbConversionMatrix = kYuvToRGBMatrixBT709.data();
- desc.gamutConversionMatrix = kGamutConversionMatrixBT709ToSrgb.data();
- desc.srcTransferFunctionParameters = kGammaDecodeBT709.data();
- desc.dstTransferFunctionParameters = kGammaEncodeSrgb.data();
+ desc.yuvToRgbConversionMatrix = yuvBT709ToRGBSRGB.yuvToRgbConversionMatrix.data();
+ desc.gamutConversionMatrix = yuvBT709ToRGBSRGB.gamutConversionMatrix.data();
+ desc.srcTransferFunctionParameters = yuvBT709ToRGBSRGB.srcTransferFunctionParameters.data();
+ desc.dstTransferFunctionParameters = yuvBT709ToRGBSRGB.dstTransferFunctionParameters.data();
return desc;
}
@@ -51,14 +51,8 @@
static constexpr uint32_t kHeight = 4;
static constexpr wgpu::TextureFormat kFormat = wgpu::TextureFormat::RGBA8Unorm;
static constexpr wgpu::TextureUsage kSampledUsage = wgpu::TextureUsage::TextureBinding;
- std::array<float, 12> kYuvToRGBMatrixBT709 = {1.164384f, 0.0f, 1.792741f, -0.972945f,
- 1.164384f, -0.213249f, -0.532909f, 0.301483f,
- 1.164384f, 2.112402f, 0.0f, -1.133402f};
- std::array<float, 9> kGamutConversionMatrixBT709ToSrgb = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
- 0.0f, 0.0f, 0.0f, 1.0f};
- std::array<float, 7> kGammaDecodeBT709 = {2.2, 1.0 / 1.099, 0.099 / 1.099, 1 / 4.5, 0.081,
- 0.0, 0.0};
- std::array<float, 7> kGammaEncodeSrgb = {1 / 2.4, 1.137119, 0.0, 12.92, 0.0031308, -0.055, 0.0};
+ utils::ColorSpaceConversionInfo yuvBT709ToRGBSRGB =
+ utils::GetYUVBT709ToRGBSRGBColorSpaceConversionInfo();
};
} // anonymous namespace
@@ -99,7 +93,7 @@
@fragment fn main(@builtin(position) FragCoord : vec4<f32>)
-> @location(0) vec4<f32> {
- return textureSampleLevel(t, s, FragCoord.xy / vec2<f32>(4.0, 4.0));
+ return textureSampleBaseClampToEdge(t, s, FragCoord.xy / vec2<f32>(4.0, 4.0));
})");
wgpu::Texture sampledTexture =
@@ -184,7 +178,7 @@
@fragment fn main(@builtin(position) FragCoord : vec4<f32>)
-> @location(0) vec4<f32> {
- return textureSampleLevel(t, s, FragCoord.xy / vec2<f32>(4.0, 4.0));
+ return textureSampleBaseClampToEdge(t, s, FragCoord.xy / vec2<f32>(4.0, 4.0));
})");
wgpu::Texture sampledTexturePlane0 =
diff --git a/src/dawn/tests/unittests/validation/CopyTextureForBrowserTests.cpp b/src/dawn/tests/unittests/validation/CopyTextureForBrowserTests.cpp
index 06c1b3d..96fc533 100644
--- a/src/dawn/tests/unittests/validation/CopyTextureForBrowserTests.cpp
+++ b/src/dawn/tests/unittests/validation/CopyTextureForBrowserTests.cpp
@@ -20,31 +20,59 @@
#include "dawn/utils/TextureUtils.h"
#include "dawn/utils/WGPUHelpers.h"
+namespace {
+wgpu::Texture Create2DTexture(
+ wgpu::Device device,
+ uint32_t width,
+ uint32_t height,
+ uint32_t mipLevelCount,
+ uint32_t arrayLayerCount,
+ wgpu::TextureFormat format,
+ wgpu::TextureUsage usage,
+ uint32_t sampleCount = 1,
+ const wgpu::DawnTextureInternalUsageDescriptor* internalDesc = nullptr) {
+ wgpu::TextureDescriptor descriptor;
+ descriptor.nextInChain = internalDesc;
+ descriptor.dimension = wgpu::TextureDimension::e2D;
+ descriptor.size.width = width;
+ descriptor.size.height = height;
+ descriptor.size.depthOrArrayLayers = arrayLayerCount;
+ descriptor.sampleCount = sampleCount;
+ descriptor.format = format;
+ descriptor.mipLevelCount = mipLevelCount;
+ descriptor.usage = usage;
+ wgpu::Texture tex = device.CreateTexture(&descriptor);
+ return tex;
+}
+
+wgpu::ExternalTexture CreateExternalTexture(wgpu::Device device, uint32_t width, uint32_t height) {
+ wgpu::Texture texture =
+ Create2DTexture(device, width, height, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::TextureBinding);
+
+ // Create a texture view for the external texture
+ wgpu::TextureView view = texture.CreateView();
+
+ // Create an ExternalTextureDescriptor from the texture view
+ wgpu::ExternalTextureDescriptor externalDesc;
+ utils::ColorSpaceConversionInfo info = utils::GetYUVBT709ToRGBSRGBColorSpaceConversionInfo();
+ externalDesc.yuvToRgbConversionMatrix = info.yuvToRgbConversionMatrix.data();
+ externalDesc.gamutConversionMatrix = info.gamutConversionMatrix.data();
+ externalDesc.srcTransferFunctionParameters = info.srcTransferFunctionParameters.data();
+ externalDesc.dstTransferFunctionParameters = info.dstTransferFunctionParameters.data();
+
+ externalDesc.plane0 = view;
+
+ externalDesc.visibleRect = {width, height};
+
+ // Import the external texture
+ return device.CreateExternalTexture(&externalDesc);
+}
+
+} // namespace
+
class CopyTextureForBrowserTest : public ValidationTest {
protected:
- wgpu::Texture Create2DTexture(
- uint32_t width,
- uint32_t height,
- uint32_t mipLevelCount,
- uint32_t arrayLayerCount,
- wgpu::TextureFormat format,
- wgpu::TextureUsage usage,
- uint32_t sampleCount = 1,
- const wgpu::DawnTextureInternalUsageDescriptor* internalDesc = nullptr) {
- wgpu::TextureDescriptor descriptor;
- descriptor.nextInChain = internalDesc;
- descriptor.dimension = wgpu::TextureDimension::e2D;
- descriptor.size.width = width;
- descriptor.size.height = height;
- descriptor.size.depthOrArrayLayers = arrayLayerCount;
- descriptor.sampleCount = sampleCount;
- descriptor.format = format;
- descriptor.mipLevelCount = mipLevelCount;
- descriptor.usage = usage;
- wgpu::Texture tex = device.CreateTexture(&descriptor);
- return tex;
- }
-
void TestCopyTextureForBrowser(utils::Expectation expectation,
wgpu::Texture srcTexture,
uint32_t srcLevel,
@@ -81,13 +109,52 @@
}
};
+class CopyExternalTextureForBrowserTest : public ValidationTest {
+ protected:
+ void TestCopyExternalTextureForBrowser(utils::Expectation expectation,
+ wgpu::ExternalTexture srcExternalTexture,
+ wgpu::Origin3D srcOrigin,
+ wgpu::Texture dstTexture,
+ uint32_t dstLevel,
+ wgpu::Origin3D dstOrigin,
+ wgpu::Extent3D extent3D,
+ wgpu::TextureAspect aspect = wgpu::TextureAspect::All,
+ wgpu::CopyTextureForBrowserOptions options = {}) {
+ wgpu::ImageCopyExternalTexture srcImageCopyExternalTexture;
+ srcImageCopyExternalTexture.externalTexture = srcExternalTexture;
+ srcImageCopyExternalTexture.origin = srcOrigin;
+
+ wgpu::ImageCopyTexture dstImageCopyTexture =
+ utils::CreateImageCopyTexture(dstTexture, dstLevel, dstOrigin, aspect);
+
+ if (expectation == utils::Expectation::Success) {
+ device.GetQueue().CopyExternalTextureForBrowser(
+ &srcImageCopyExternalTexture, &dstImageCopyTexture, &extent3D, &options);
+ } else {
+ ASSERT_DEVICE_ERROR(device.GetQueue().CopyExternalTextureForBrowser(
+ &srcImageCopyExternalTexture, &dstImageCopyTexture, &extent3D, &options));
+ }
+ }
+};
+
+class CopyExternalTextureForBrowserInternalUsageTest : public CopyExternalTextureForBrowserTest {
+ protected:
+ WGPUDevice CreateTestDevice(dawn::native::Adapter dawnAdapter) override {
+ wgpu::DeviceDescriptor descriptor;
+ wgpu::FeatureName feature = wgpu::FeatureName::DawnInternalUsages;
+ descriptor.requiredFeatures = &feature;
+ descriptor.requiredFeaturesCount = 1;
+ return dawnAdapter.CreateDevice(&descriptor);
+ }
+};
+
// Tests should be Success
TEST_F(CopyTextureForBrowserTest, Success) {
wgpu::Texture source =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
wgpu::Texture destination =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
// Different copies, including some that touch the OOB condition
@@ -140,19 +207,20 @@
// Test source or destination texture has wrong usages
TEST_F(CopyTextureForBrowserTest, IncorrectUsage) {
wgpu::Texture validSource =
- Create2DTexture(16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
wgpu::Texture validDestination =
- Create2DTexture(16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
- wgpu::Texture noSampledUsageSource =
- Create2DTexture(16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::CopySrc);
- wgpu::Texture noRenderAttachmentUsageDestination =
- Create2DTexture(16, 16, 5, 2, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::CopyDst);
+ wgpu::Texture noSampledUsageSource = Create2DTexture(
+ device, 16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::CopySrc);
+ wgpu::Texture noRenderAttachmentUsageDestination = Create2DTexture(
+ device, 16, 16, 5, 2, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::CopyDst);
wgpu::Texture noCopySrcUsageSource = Create2DTexture(
- 16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::TextureBinding);
- wgpu::Texture noCopyDstUsageSource = Create2DTexture(
- 16, 16, 5, 2, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::RenderAttachment);
+ device, 16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::TextureBinding);
+ wgpu::Texture noCopyDstUsageSource =
+ Create2DTexture(device, 16, 16, 5, 2, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::RenderAttachment);
// Incorrect source usage causes failure : lack |Sampled| usage
TestCopyTextureForBrowser(utils::Expectation::Failure, noSampledUsageSource, 0, {0, 0, 0},
@@ -178,10 +246,10 @@
// Valid src and dst textures.
{
wgpu::Texture source =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
wgpu::Texture destination =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
{0, 0, 0}, {4, 4, 1}, wgpu::TextureAspect::All, options);
@@ -194,10 +262,10 @@
// Destroyed src texture.
{
wgpu::Texture source =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
wgpu::Texture destination =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
source.Destroy();
TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
@@ -211,10 +279,10 @@
// Destroyed dst texture.
{
wgpu::Texture source =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
wgpu::Texture destination =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
destination.Destroy();
@@ -230,10 +298,10 @@
// Test non-zero value origin in source and OOB copy rects.
TEST_F(CopyTextureForBrowserTest, OutOfBounds) {
wgpu::Texture source =
- Create2DTexture(16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
wgpu::Texture destination =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
// OOB on source
@@ -290,10 +358,10 @@
// Test destination texture has format that not supported by CopyTextureForBrowser().
TEST_F(CopyTextureForBrowserTest, InvalidDstFormat) {
wgpu::Texture source =
- Create2DTexture(16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
wgpu::Texture destination =
- Create2DTexture(16, 16, 5, 2, wgpu::TextureFormat::RG8Uint,
+ Create2DTexture(device, 16, 16, 5, 2, wgpu::TextureFormat::RG8Uint,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
// Not supported dst texture format.
@@ -304,18 +372,18 @@
// Test source or destination texture are multisampled.
TEST_F(CopyTextureForBrowserTest, InvalidSampleCount) {
wgpu::Texture sourceMultiSampled1x =
- Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding, 1);
wgpu::Texture destinationMultiSampled1x =
- Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment, 1);
wgpu::Texture sourceMultiSampled4x =
- Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding |
wgpu::TextureUsage::RenderAttachment,
4);
wgpu::Texture destinationMultiSampled4x =
- Create2DTexture(16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment, 4);
// An empty copy with dst texture sample count > 1 failure.
@@ -330,10 +398,10 @@
// Test color space conversion related attributes in CopyTextureForBrowserOptions.
TEST_F(CopyTextureForBrowserTest, ColorSpaceConversion_ColorSpace) {
wgpu::Texture source =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
wgpu::Texture destination =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
wgpu::CopyTextureForBrowserOptions options = {};
@@ -413,10 +481,10 @@
// Test option.srcAlphaMode/dstAlphaMode
TEST_F(CopyTextureForBrowserTest, ColorSpaceConversion_TextureAlphaState) {
wgpu::Texture source =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
wgpu::Texture destination =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
wgpu::CopyTextureForBrowserOptions options = {};
@@ -449,6 +517,342 @@
}
}
+// Tests should be Success
+TEST_F(CopyExternalTextureForBrowserTest, Success) {
+ wgpu::ExternalTexture source = CreateExternalTexture(device, 16, 16);
+ wgpu::Texture destination =
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
+
+ // Different copies, including some that touch the OOB condition
+ {
+ // Copy a region along top left boundary
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1});
+
+ // Copy entire texture
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {16, 16, 1});
+
+ // Copy a region along bottom right boundary
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {8, 8, 0},
+ destination, 0, {8, 8, 0}, {8, 8, 1});
+
+ // Copy region into mip
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 2, {0, 0, 0}, {4, 4, 1});
+
+ // Copy between slices
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {0, 0, 1}, {16, 16, 1});
+ }
+
+ // Empty copies are valid
+ {
+ // An empty copy
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {0, 0, 1});
+
+ // An empty copy with depth = 0
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {0, 0, 0});
+
+ // An empty copy touching the side of the source texture
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {16, 16, 0}, {0, 0, 1});
+
+ // An empty copy touching the side of the destination texture
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {16, 16, 0}, {0, 0, 1});
+ }
+}
+
+// Test destination texture has wrong usages
+TEST_F(CopyExternalTextureForBrowserTest, IncorrectUsage) {
+ wgpu::ExternalTexture validSource = CreateExternalTexture(device, 16, 16);
+
+ wgpu::Texture validDestination =
+ Create2DTexture(device, 16, 16, 5, 1, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
+ wgpu::Texture noRenderAttachmentUsageDestination = Create2DTexture(
+ device, 16, 16, 5, 2, wgpu::TextureFormat::RGBA8Unorm, wgpu::TextureUsage::CopyDst);
+ wgpu::Texture noCopyDstUsageSource =
+ Create2DTexture(device, 16, 16, 5, 2, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::RenderAttachment);
+
+ // Incorrect destination usage causes failure: lack |RenderAttachement| usage.
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, validSource, {0, 0, 0},
+ noRenderAttachmentUsageDestination, 0, {0, 0, 0},
+ {16, 16, 1});
+
+ // Incorrect destination usage causes failure: lack |CopyDst| usage.
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, validSource, {0, 0, 0},
+ noCopyDstUsageSource, 0, {0, 0, 0}, {16, 16, 1});
+}
+
+// Test source or destination texture is destroyed.
+TEST_F(CopyExternalTextureForBrowserTest, DestroyedTexture) {
+ wgpu::CopyTextureForBrowserOptions options = {};
+
+ // Valid src and dst textures.
+ {
+ wgpu::ExternalTexture source = CreateExternalTexture(device, 16, 16);
+ wgpu::Texture destination =
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, options);
+
+ // Check noop copy
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {0, 0, 0},
+ wgpu::TextureAspect::All, options);
+ }
+
+ // Destroyed src texture.
+ {
+ wgpu::ExternalTexture source = CreateExternalTexture(device, 16, 16);
+ wgpu::Texture destination =
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
+ source.Destroy();
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, options);
+
+ // Check noop copy
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {0, 0, 0},
+ wgpu::TextureAspect::All, options);
+ }
+
+ // Destroyed dst texture.
+ {
+ wgpu::ExternalTexture source = CreateExternalTexture(device, 16, 16);
+ wgpu::Texture destination =
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
+
+ destination.Destroy();
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, options);
+
+ // Check noop copy
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {0, 0, 0},
+ wgpu::TextureAspect::All, options);
+ }
+}
+
+// Test non-zero value origin in source and OOB copy rects.
+TEST_F(CopyExternalTextureForBrowserTest, OutOfBounds) {
+ wgpu::ExternalTexture source = CreateExternalTexture(device, 16, 16);
+ wgpu::Texture destination =
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
+
+ // OOB on source
+ {
+ // x + width overflows
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {1, 0, 0},
+ destination, 0, {0, 0, 0}, {16, 16, 1});
+
+ // y + height overflows
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 1, 0},
+ destination, 0, {0, 0, 0}, {16, 16, 1});
+
+ // copy to multiple slices
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {0, 0, 2}, {16, 16, 2});
+
+ // copy origin z value is non-zero.
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 1},
+ destination, 0, {0, 0, 2}, {16, 16, 1});
+ }
+
+ // OOB on destination
+ {
+ // x + width overflows
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {1, 0, 0}, {16, 16, 1});
+
+ // y + height overflows
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {0, 1, 0}, {16, 16, 1});
+
+ // non-zero mip overflows
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 1, {0, 0, 0}, {9, 9, 1});
+
+ // arrayLayer + depth OOB
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {0, 0, 4}, {16, 16, 1});
+
+ // empty copy on non-existent mip fails
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 6, {0, 0, 0}, {0, 0, 1});
+
+ // empty copy on non-existent slice fails
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {0, 0, 4}, {0, 0, 1});
+ }
+}
+
+// Test destination texture has format that not supported by CopyTextureForBrowser().
+TEST_F(CopyExternalTextureForBrowserTest, InvalidDstFormat) {
+ wgpu::ExternalTexture source = CreateExternalTexture(device, 16, 16);
+ wgpu::Texture destination =
+ Create2DTexture(device, 16, 16, 5, 2, wgpu::TextureFormat::RG8Uint,
+ wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
+
+ // Not supported dst texture format.
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0}, destination,
+ 0, {0, 0, 0}, {0, 0, 1});
+}
+
+// Test destination texture are multisampled.
+TEST_F(CopyExternalTextureForBrowserTest, InvalidSampleCount) {
+ wgpu::ExternalTexture source = CreateExternalTexture(device, 16, 16);
+ wgpu::Texture destinationMultiSampled4x =
+ Create2DTexture(device, 16, 16, 1, 1, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment, 4);
+
+ // An empty copy with dst texture sample count > 1 failure.
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destinationMultiSampled4x, 0, {0, 0, 0}, {0, 0, 1});
+}
+
+// Test color space conversion related attributes in CopyTextureForBrowserOptions.
+TEST_F(CopyExternalTextureForBrowserTest, ColorSpaceConversion_ColorSpace) {
+ wgpu::ExternalTexture source = CreateExternalTexture(device, 16, 16);
+ wgpu::Texture destination =
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
+
+ wgpu::CopyTextureForBrowserOptions options = {};
+ options.needsColorSpaceConversion = true;
+
+ // Valid cases
+ {
+ wgpu::CopyTextureForBrowserOptions validOptions = options;
+ std::array<float, 7> srcTransferFunctionParameters = {};
+ std::array<float, 7> dstTransferFunctionParameters = {};
+ std::array<float, 9> conversionMatrix = {};
+ validOptions.srcTransferFunctionParameters = srcTransferFunctionParameters.data();
+ validOptions.dstTransferFunctionParameters = dstTransferFunctionParameters.data();
+ validOptions.conversionMatrix = conversionMatrix.data();
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, validOptions);
+
+ // if no color space conversion, no need to validate related attributes
+ wgpu::CopyTextureForBrowserOptions noColorSpaceConversion = options;
+ noColorSpaceConversion.needsColorSpaceConversion = false;
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, noColorSpaceConversion);
+ }
+
+ // Invalid cases: srcTransferFunctionParameters, dstTransferFunctionParameters or
+ // conversionMatrix is nullptr or not set
+ {
+ // not set srcTransferFunctionParameters
+ wgpu::CopyTextureForBrowserOptions invalidOptions = options;
+ std::array<float, 7> dstTransferFunctionParameters = {};
+ std::array<float, 9> conversionMatrix = {};
+ invalidOptions.dstTransferFunctionParameters = dstTransferFunctionParameters.data();
+ invalidOptions.conversionMatrix = conversionMatrix.data();
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, invalidOptions);
+
+ // set to nullptr
+ invalidOptions.srcTransferFunctionParameters = nullptr;
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, invalidOptions);
+ }
+
+ {
+ // not set dstTransferFunctionParameters
+ wgpu::CopyTextureForBrowserOptions invalidOptions = options;
+ std::array<float, 7> srcTransferFunctionParameters = {};
+ std::array<float, 9> conversionMatrix = {};
+ invalidOptions.srcTransferFunctionParameters = srcTransferFunctionParameters.data();
+ invalidOptions.conversionMatrix = conversionMatrix.data();
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, invalidOptions);
+
+ // set to nullptr
+ invalidOptions.dstTransferFunctionParameters = nullptr;
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, invalidOptions);
+ }
+
+ {
+ // not set conversionMatrix
+ wgpu::CopyTextureForBrowserOptions invalidOptions = options;
+ std::array<float, 7> srcTransferFunctionParameters = {};
+ std::array<float, 7> dstTransferFunctionParameters = {};
+ invalidOptions.srcTransferFunctionParameters = srcTransferFunctionParameters.data();
+ invalidOptions.dstTransferFunctionParameters = dstTransferFunctionParameters.data();
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, invalidOptions);
+
+ // set to nullptr
+ invalidOptions.conversionMatrix = nullptr;
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, invalidOptions);
+ }
+}
+
+// Test option.srcAlphaMode/dstAlphaMode
+TEST_F(CopyExternalTextureForBrowserTest, ColorSpaceConversion_TextureAlphaState) {
+ wgpu::ExternalTexture source = CreateExternalTexture(device, 16, 16);
+ wgpu::Texture destination =
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
+
+ wgpu::CopyTextureForBrowserOptions options = {};
+
+ // Valid src texture alpha state and valid dst texture alpha state
+ {
+ options.srcAlphaMode = wgpu::AlphaMode::Premultiplied;
+ options.dstAlphaMode = wgpu::AlphaMode::Premultiplied;
+
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, options);
+
+ options.srcAlphaMode = wgpu::AlphaMode::Premultiplied;
+ options.dstAlphaMode = wgpu::AlphaMode::Unpremultiplied;
+
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, options);
+
+ options.srcAlphaMode = wgpu::AlphaMode::Unpremultiplied;
+ options.dstAlphaMode = wgpu::AlphaMode::Premultiplied;
+
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, options);
+
+ options.srcAlphaMode = wgpu::AlphaMode::Unpremultiplied;
+ options.dstAlphaMode = wgpu::AlphaMode::Unpremultiplied;
+
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0},
+ destination, 0, {0, 0, 0}, {4, 4, 1},
+ wgpu::TextureAspect::All, options);
+ }
+}
+
// Test that the internal usage can only be set to true when the device internal usage feature is
// enabled
TEST_F(CopyTextureForBrowserTest, InternalUsage) {
@@ -456,15 +860,15 @@
internalDesc.internalUsage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding;
// Validation should fail because internal descriptor is not empty.
- ASSERT_DEVICE_ERROR(Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ ASSERT_DEVICE_ERROR(Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopySrc, 1, &internalDesc));
wgpu::Texture source =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding);
wgpu::Texture destination =
- Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
// Validation should fail because of device internal usage feature is missing when internal
@@ -480,14 +884,15 @@
wgpu::DawnTextureInternalUsageDescriptor internalDesc1 = {};
internalDesc1.internalUsage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding;
- wgpu::Texture source = Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::Texture source = Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
wgpu::TextureUsage::CopySrc, 1, &internalDesc1);
wgpu::DawnTextureInternalUsageDescriptor internalDesc2 = {};
internalDesc2.internalUsage =
wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment;
- wgpu::Texture destination = Create2DTexture(16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
- wgpu::TextureUsage::CopyDst, 1, &internalDesc2);
+ wgpu::Texture destination =
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopyDst, 1, &internalDesc2);
// Without internal usage option should fail usage validation
TestCopyTextureForBrowser(utils::Expectation::Failure, source, 0, {0, 0, 0}, destination, 0,
@@ -499,3 +904,48 @@
TestCopyTextureForBrowser(utils::Expectation::Success, source, 0, {0, 0, 0}, destination, 0,
{0, 0, 0}, {16, 16, 1}, wgpu::TextureAspect::All, options);
}
+
+// Test that the internal usage can only be set to true when the device internal usage feature is
+// enabled
+TEST_F(CopyExternalTextureForBrowserTest, InternalUsage) {
+ wgpu::DawnTextureInternalUsageDescriptor internalDesc = {};
+ internalDesc.internalUsage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::TextureBinding;
+
+ // Validation should fail because internal descriptor is not empty.
+ ASSERT_DEVICE_ERROR(Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopySrc, 1, &internalDesc));
+
+ wgpu::ExternalTexture source = CreateExternalTexture(device, 16, 16);
+
+ wgpu::Texture destination =
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment);
+
+ // Validation should fail because of device internal usage feature is missing when internal
+ // usage option is on
+ wgpu::CopyTextureForBrowserOptions options = {};
+ options.internalUsage = true;
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0}, destination,
+ 0, {0, 0, 0}, {16, 16, 1}, wgpu::TextureAspect::All, options);
+}
+
+// Test that the internal usages are taken into account when interalUsage = true
+TEST_F(CopyExternalTextureForBrowserInternalUsageTest, InternalUsage) {
+ wgpu::ExternalTexture source = CreateExternalTexture(device, 16, 16);
+
+ wgpu::DawnTextureInternalUsageDescriptor internalDesc = {};
+ internalDesc.internalUsage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment;
+ wgpu::Texture destination =
+ Create2DTexture(device, 16, 16, 5, 4, wgpu::TextureFormat::RGBA8Unorm,
+ wgpu::TextureUsage::CopyDst, 1, &internalDesc);
+
+ // Without internal usage option should fail usage validation
+ TestCopyExternalTextureForBrowser(utils::Expectation::Failure, source, {0, 0, 0}, destination,
+ 0, {0, 0, 0}, {16, 16, 1});
+
+ // With internal usage option should pass usage validation
+ wgpu::CopyTextureForBrowserOptions options = {};
+ options.internalUsage = true;
+ TestCopyExternalTextureForBrowser(utils::Expectation::Success, source, {0, 0, 0}, destination,
+ 0, {0, 0, 0}, {16, 16, 1}, wgpu::TextureAspect::All, options);
+}
diff --git a/src/dawn/utils/WGPUHelpers.cpp b/src/dawn/utils/WGPUHelpers.cpp
index dda2cab..d016620 100644
--- a/src/dawn/utils/WGPUHelpers.cpp
+++ b/src/dawn/utils/WGPUHelpers.cpp
@@ -26,6 +26,17 @@
#include "spirv-tools/optimizer.hpp"
+namespace {
+std::array<float, 12> kYuvToRGBMatrixBT709 = {1.164384f, 0.0f, 1.792741f, -0.972945f,
+ 1.164384f, -0.213249f, -0.532909f, 0.301483f,
+ 1.164384f, 2.112402f, 0.0f, -1.133402f};
+std::array<float, 9> kGamutConversionMatrixBT709ToSrgb = {1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
+ 0.0f, 0.0f, 0.0f, 1.0f};
+std::array<float, 7> kGammaDecodeBT709 = {2.2, 1.0 / 1.099, 0.099 / 1.099, 1 / 4.5, 0.081,
+ 0.0, 0.0};
+std::array<float, 7> kGammaEncodeSrgb = {1 / 2.4, 1.137119, 0.0, 12.92, 0.0031308, -0.055, 0.0};
+} // namespace
+
namespace utils {
wgpu::ShaderModule CreateShaderModuleFromASM(const wgpu::Device& device, const char* source) {
// Use SPIRV-Tools's C API to assemble the SPIR-V assembly text to binary. Because the types
@@ -389,4 +400,14 @@
return device.CreateBindGroup(&descriptor);
}
+ColorSpaceConversionInfo GetYUVBT709ToRGBSRGBColorSpaceConversionInfo() {
+ ColorSpaceConversionInfo info;
+ info.yuvToRgbConversionMatrix = kYuvToRGBMatrixBT709;
+ info.gamutConversionMatrix = kGamutConversionMatrixBT709ToSrgb;
+ info.srcTransferFunctionParameters = kGammaDecodeBT709;
+ info.dstTransferFunctionParameters = kGammaEncodeSrgb;
+
+ return info;
+}
+
} // namespace utils
diff --git a/src/dawn/utils/WGPUHelpers.h b/src/dawn/utils/WGPUHelpers.h
index 24864e6..9217ca9 100644
--- a/src/dawn/utils/WGPUHelpers.h
+++ b/src/dawn/utils/WGPUHelpers.h
@@ -178,6 +178,15 @@
const wgpu::BindGroupLayout& layout,
std::initializer_list<BindingInitializationHelper> entriesInitializer);
+struct ColorSpaceConversionInfo {
+ std::array<float, 12> yuvToRgbConversionMatrix;
+ std::array<float, 9> gamutConversionMatrix;
+ std::array<float, 7> srcTransferFunctionParameters;
+ std::array<float, 7> dstTransferFunctionParameters;
+};
+
+ColorSpaceConversionInfo GetYUVBT709ToRGBSRGBColorSpaceConversionInfo();
+
} // namespace utils
#endif // SRC_DAWN_UTILS_WGPUHELPERS_H_