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>
This commit is contained in:
parent
96a0bd5bdf
commit
f392c38b67
21
dawn.json
21
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,14 @@
|
|||
{"name": "aspect", "type": "texture aspect", "default": "all"}
|
||||
]
|
||||
},
|
||||
"image copy external texture": {
|
||||
"category": "structure",
|
||||
"extensible": "in",
|
||||
"members": [
|
||||
{"name": "external texture", "type": "external texture"},
|
||||
{"name": "origin", "type": "origin 3D"}
|
||||
]
|
||||
},
|
||||
"index format": {
|
||||
"category": "enum",
|
||||
"values": [
|
||||
|
@ -1721,6 +1727,17 @@
|
|||
{"name": "options", "type": "copy texture for browser options", "annotation": "const*"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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",
|
||||
|
|
|
@ -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 @@ static const char sCopyTextureForBrowserShader[] = R"(
|
|||
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 @@ static const char sCopyTextureForBrowserShader[] = R"(
|
|||
// 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 @@ static const char sCopyTextureForBrowserShader[] = R"(
|
|||
}
|
||||
|
||||
@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 @@ static const char sCopyTextureForBrowserShader[] = R"(
|
|||
|
||||
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 @@ struct Uniform {
|
|||
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 @@ MaybeError ValidateCopyTextureFormatConversion(const wgpu::TextureFormat srcForm
|
|||
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 @@ MaybeError ValidateCopyTextureFormatConversion(const wgpu::TextureFormat srcForm
|
|||
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 @@ RenderPipelineBase* GetCachedPipeline(InternalPipelineStore* store, wgpu::Textur
|
|||
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 @@ bool IsSrgbDstFormat(wgpu::TextureFormat format) {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ MaybeError DoCopyTextureForBrowser(DeviceBase* device,
|
|||
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 @@ MaybeError DoCopyTextureForBrowser(DeviceBase* device,
|
|||
// 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 @@ MaybeError DoCopyTextureForBrowser(DeviceBase* device,
|
|||
// 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 @@ MaybeError DoCopyTextureForBrowser(DeviceBase* device,
|
|||
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 @@ MaybeError DoCopyTextureForBrowser(DeviceBase* device,
|
|||
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 @@ MaybeError DoCopyTextureForBrowser(DeviceBase* device,
|
|||
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
|
||||
|
|
|
@ -30,12 +30,23 @@ MaybeError ValidateCopyTextureForBrowser(DeviceBase* device,
|
|||
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_
|
||||
|
|
|
@ -35,8 +35,10 @@ struct InternalPipelineStore {
|
|||
~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;
|
||||
|
|
|
@ -370,6 +370,14 @@ void QueueBase::APICopyTextureForBrowser(const ImageCopyTexture* source,
|
|||
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 @@ MaybeError QueueBase::CopyTextureForBrowserInternal(const ImageCopyTexture* sour
|
|||
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");
|
||||
|
|
|
@ -58,6 +58,10 @@ class QueueBase : public ApiObjectBase {
|
|||
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 @@ class QueueBase : public ApiObjectBase {
|
|||
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,
|
||||
|
|
|
@ -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,
|
|||
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 @@ BindGroupEntry BindingInitializationHelper::GetAsBinding() const {
|
|||
result.offset = offset;
|
||||
result.size = size;
|
||||
|
||||
if (externalTexture != nullptr) {
|
||||
result.nextInChain = &externalBindingEntry;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ ResultOrError<Ref<BindGroupLayoutBase>> MakeBindGroupLayout(
|
|||
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 @@ struct BindingInitializationHelper {
|
|||
Ref<SamplerBase> sampler;
|
||||
Ref<TextureViewBase> textureView;
|
||||
Ref<BufferBase> buffer;
|
||||
Ref<ExternalTextureBase> externalTexture;
|
||||
ExternalTextureBindingEntry externalBindingEntry;
|
||||
uint64_t offset = 0;
|
||||
uint64_t size = 0;
|
||||
};
|
||||
|
|
|
@ -45,6 +45,18 @@ AbslFormatConvert(const Color* value, const absl::FormatConversionSpec& spec, ab
|
|||
return {true};
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
|
@ -29,6 +29,12 @@ struct Color;
|
|||
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,
|
||||
|
|
|
@ -438,6 +438,7 @@ source_set("end2end_tests_sources") {
|
|||
"end2end/ComputeLayoutMemoryBufferTests.cpp",
|
||||
"end2end/ComputeSharedMemoryTests.cpp",
|
||||
"end2end/ComputeStorageBufferBarrierTests.cpp",
|
||||
"end2end/CopyExternalTextureForBrowserTests.cpp",
|
||||
"end2end/CopyTests.cpp",
|
||||
"end2end/CopyTextureForBrowserTests.cpp",
|
||||
"end2end/CreatePipelineAsyncTests.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}));
|
|
@ -39,10 +39,10 @@ class ExternalTextureTests : public DawnTest {
|
|||
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 @@ class ExternalTextureTests : public DawnTest {
|
|||
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 @@ TEST_P(ExternalTextureTests, SampleExternalTexture) {
|
|||
|
||||
@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 @@ TEST_P(ExternalTextureTests, SampleMultiplanarExternalTexture) {
|
|||
|
||||
@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 =
|
||||
|
|
|
@ -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 CopyTextureForBrowserInternalUsageTest : public CopyTextureForBrowserTest
|
|||
}
|
||||
};
|
||||
|
||||
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_F(CopyTextureForBrowserTest, Success) {
|
|||
// 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 @@ TEST_F(CopyTextureForBrowserTest, DestroyedTexture) {
|
|||
// 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 @@ TEST_F(CopyTextureForBrowserTest, DestroyedTexture) {
|
|||
// 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 @@ TEST_F(CopyTextureForBrowserTest, DestroyedTexture) {
|
|||
// 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_F(CopyTextureForBrowserTest, DestroyedTexture) {
|
|||
// 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_F(CopyTextureForBrowserTest, OutOfBounds) {
|
|||
// 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_F(CopyTextureForBrowserTest, InvalidDstFormat) {
|
|||
// 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_F(CopyTextureForBrowserTest, InvalidSampleCount) {
|
|||
// 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_F(CopyTextureForBrowserTest, ColorSpaceConversion_ColorSpace) {
|
|||
// 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 @@ TEST_F(CopyTextureForBrowserTest, ColorSpaceConversion_TextureAlphaState) {
|
|||
}
|
||||
}
|
||||
|
||||
// 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 @@ TEST_F(CopyTextureForBrowserTest, InternalUsage) {
|
|||
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 @@ TEST_F(CopyTextureForBrowserInternalUsageTest, InternalUsage) {
|
|||
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 @@ TEST_F(CopyTextureForBrowserInternalUsageTest, InternalUsage) {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -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 @@ wgpu::BindGroup MakeBindGroup(
|
|||
return device.CreateBindGroup(&descriptor);
|
||||
}
|
||||
|
||||
ColorSpaceConversionInfo GetYUVBT709ToRGBSRGBColorSpaceConversionInfo() {
|
||||
ColorSpaceConversionInfo info;
|
||||
info.yuvToRgbConversionMatrix = kYuvToRGBMatrixBT709;
|
||||
info.gamutConversionMatrix = kGamutConversionMatrixBT709ToSrgb;
|
||||
info.srcTransferFunctionParameters = kGammaDecodeBT709;
|
||||
info.dstTransferFunctionParameters = kGammaEncodeSrgb;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
|
|
@ -178,6 +178,15 @@ wgpu::BindGroup MakeBindGroup(
|
|||
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_
|
||||
|
|
Loading…
Reference in New Issue