Adding APICopyTextureToTextureInternal
This CL adds an internal method to copy textures, that will disregard the need of having CopySrc usage. This CL adds an intermediate helped method to be used by both APIContextTextureToTexture and APIContextTextureToTextureInternal. Fixed: dawn:1052 Change-Id: Icd28e0ef58ecfaa412eefe8c95e41cd2298a9acc Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/58440 Reviewed-by: Kai Ninomiya <kainino@chromium.org> Commit-Queue: Juanmi Huertas <juanmihd@chromium.org>
This commit is contained in:
parent
b42d701abe
commit
f00c68a216
|
@ -426,6 +426,14 @@
|
||||||
{"name": "copy size", "type": "extent 3D", "annotation": "const*"}
|
{"name": "copy size", "type": "extent 3D", "annotation": "const*"}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "copy texture to texture internal",
|
||||||
|
"args": [
|
||||||
|
{"name": "source", "type": "image copy texture", "annotation": "const*"},
|
||||||
|
{"name": "destination", "type": "image copy texture", "annotation": "const*"},
|
||||||
|
{"name": "copy size", "type": "extent 3D", "annotation": "const*"}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "inject validation error",
|
"name": "inject validation error",
|
||||||
"args": [
|
"args": [
|
||||||
|
|
|
@ -778,6 +778,19 @@ namespace dawn_native {
|
||||||
void CommandEncoder::APICopyTextureToTexture(const ImageCopyTexture* source,
|
void CommandEncoder::APICopyTextureToTexture(const ImageCopyTexture* source,
|
||||||
const ImageCopyTexture* destination,
|
const ImageCopyTexture* destination,
|
||||||
const Extent3D* copySize) {
|
const Extent3D* copySize) {
|
||||||
|
APICopyTextureToTextureHelper<false>(source, destination, copySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandEncoder::APICopyTextureToTextureInternal(const ImageCopyTexture* source,
|
||||||
|
const ImageCopyTexture* destination,
|
||||||
|
const Extent3D* copySize) {
|
||||||
|
APICopyTextureToTextureHelper<true>(source, destination, copySize);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool Internal>
|
||||||
|
void CommandEncoder::APICopyTextureToTextureHelper(const ImageCopyTexture* source,
|
||||||
|
const ImageCopyTexture* destination,
|
||||||
|
const Extent3D* copySize) {
|
||||||
mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
mEncodingContext.TryEncode(this, [&](CommandAllocator* allocator) -> MaybeError {
|
||||||
if (GetDevice()->IsValidationEnabled()) {
|
if (GetDevice()->IsValidationEnabled()) {
|
||||||
DAWN_TRY(GetDevice()->ValidateObject(source->texture));
|
DAWN_TRY(GetDevice()->ValidateObject(source->texture));
|
||||||
|
@ -792,8 +805,17 @@ namespace dawn_native {
|
||||||
DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *source, *copySize));
|
DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *source, *copySize));
|
||||||
DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *destination, *copySize));
|
DAWN_TRY(ValidateTextureCopyRange(GetDevice(), *destination, *copySize));
|
||||||
|
|
||||||
DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc));
|
// For internal usages (CopyToCopyInternal) we don't care if the user has added
|
||||||
DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst));
|
// CopySrc as a usage for this texture, but we will always add it internally.
|
||||||
|
if (Internal) {
|
||||||
|
DAWN_TRY(
|
||||||
|
ValidateInternalCanUseAs(source->texture, wgpu::TextureUsage::CopySrc));
|
||||||
|
DAWN_TRY(ValidateInternalCanUseAs(destination->texture,
|
||||||
|
wgpu::TextureUsage::CopyDst));
|
||||||
|
} else {
|
||||||
|
DAWN_TRY(ValidateCanUseAs(source->texture, wgpu::TextureUsage::CopySrc));
|
||||||
|
DAWN_TRY(ValidateCanUseAs(destination->texture, wgpu::TextureUsage::CopyDst));
|
||||||
|
}
|
||||||
|
|
||||||
mTopLevelTextures.insert(source->texture);
|
mTopLevelTextures.insert(source->texture);
|
||||||
mTopLevelTextures.insert(destination->texture);
|
mTopLevelTextures.insert(destination->texture);
|
||||||
|
|
|
@ -54,6 +54,9 @@ namespace dawn_native {
|
||||||
void APICopyTextureToTexture(const ImageCopyTexture* source,
|
void APICopyTextureToTexture(const ImageCopyTexture* source,
|
||||||
const ImageCopyTexture* destination,
|
const ImageCopyTexture* destination,
|
||||||
const Extent3D* copySize);
|
const Extent3D* copySize);
|
||||||
|
void APICopyTextureToTextureInternal(const ImageCopyTexture* source,
|
||||||
|
const ImageCopyTexture* destination,
|
||||||
|
const Extent3D* copySize);
|
||||||
|
|
||||||
void APIInjectValidationError(const char* message);
|
void APIInjectValidationError(const char* message);
|
||||||
void APIInsertDebugMarker(const char* groupLabel);
|
void APIInsertDebugMarker(const char* groupLabel);
|
||||||
|
@ -73,6 +76,14 @@ namespace dawn_native {
|
||||||
ResultOrError<Ref<CommandBufferBase>> FinishInternal(
|
ResultOrError<Ref<CommandBufferBase>> FinishInternal(
|
||||||
const CommandBufferDescriptor* descriptor);
|
const CommandBufferDescriptor* descriptor);
|
||||||
|
|
||||||
|
// Helper to be able to implement both APICopyTextureToTexture and
|
||||||
|
// APICopyTextureToTextureInternal. The only difference between both
|
||||||
|
// copies, is that the Internal one will also check internal usage.
|
||||||
|
template <bool Internal>
|
||||||
|
void APICopyTextureToTextureHelper(const ImageCopyTexture* source,
|
||||||
|
const ImageCopyTexture* destination,
|
||||||
|
const Extent3D* copySize);
|
||||||
|
|
||||||
MaybeError ValidateFinish() const;
|
MaybeError ValidateFinish() const;
|
||||||
|
|
||||||
EncodingContext mEncodingContext;
|
EncodingContext mEncodingContext;
|
||||||
|
|
|
@ -421,6 +421,15 @@ namespace dawn_native {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaybeError ValidateInternalCanUseAs(const TextureBase* texture, wgpu::TextureUsage usage) {
|
||||||
|
ASSERT(wgpu::HasZeroOrOneBits(usage));
|
||||||
|
if (!(texture->GetInternalUsage() & usage)) {
|
||||||
|
return DAWN_VALIDATION_ERROR("texture doesn't have the required usage.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
MaybeError ValidateCanUseAs(const BufferBase* buffer, wgpu::BufferUsage usage) {
|
MaybeError ValidateCanUseAs(const BufferBase* buffer, wgpu::BufferUsage usage) {
|
||||||
ASSERT(wgpu::HasZeroOrOneBits(usage));
|
ASSERT(wgpu::HasZeroOrOneBits(usage));
|
||||||
if (!(buffer->GetUsage() & usage)) {
|
if (!(buffer->GetUsage() & usage)) {
|
||||||
|
|
|
@ -71,6 +71,8 @@ namespace dawn_native {
|
||||||
|
|
||||||
MaybeError ValidateCanUseAs(const TextureBase* texture, wgpu::TextureUsage usage);
|
MaybeError ValidateCanUseAs(const TextureBase* texture, wgpu::TextureUsage usage);
|
||||||
|
|
||||||
|
MaybeError ValidateInternalCanUseAs(const TextureBase* texture, wgpu::TextureUsage usage);
|
||||||
|
|
||||||
MaybeError ValidateCanUseAs(const BufferBase* buffer, wgpu::BufferUsage usage);
|
MaybeError ValidateCanUseAs(const BufferBase* buffer, wgpu::BufferUsage usage);
|
||||||
|
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
|
|
@ -26,7 +26,7 @@ constexpr uint32_t kStrideComputeDefault = 0xFFFF'FFFEul;
|
||||||
|
|
||||||
constexpr wgpu::TextureFormat kDefaultFormat = wgpu::TextureFormat::RGBA8Unorm;
|
constexpr wgpu::TextureFormat kDefaultFormat = wgpu::TextureFormat::RGBA8Unorm;
|
||||||
|
|
||||||
class CopyTests : public DawnTest {
|
class CopyTests {
|
||||||
protected:
|
protected:
|
||||||
struct TextureSpec {
|
struct TextureSpec {
|
||||||
wgpu::TextureFormat format = kDefaultFormat;
|
wgpu::TextureFormat format = kDefaultFormat;
|
||||||
|
@ -128,7 +128,7 @@ class CopyTests : public DawnTest {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CopyTests_T2B : public CopyTests {
|
class CopyTests_T2B : public CopyTests, public DawnTest {
|
||||||
protected:
|
protected:
|
||||||
void DoTest(const TextureSpec& textureSpec,
|
void DoTest(const TextureSpec& textureSpec,
|
||||||
const BufferSpec& bufferSpec,
|
const BufferSpec& bufferSpec,
|
||||||
|
@ -234,7 +234,7 @@ class CopyTests_T2B : public CopyTests {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CopyTests_B2T : public CopyTests {
|
class CopyTests_B2T : public CopyTests, public DawnTest {
|
||||||
protected:
|
protected:
|
||||||
static void FillBufferData(RGBA8* data, size_t count) {
|
static void FillBufferData(RGBA8* data, size_t count) {
|
||||||
for (size_t i = 0; i < count; ++i) {
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
@ -322,8 +322,19 @@ class CopyTests_B2T : public CopyTests {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CopyTests_T2T : public CopyTests {
|
namespace {
|
||||||
|
// The CopyTests Texture to Texture in this class will validate both CopyTextureToTexture and
|
||||||
|
// CopyTextureToTextureInternal.
|
||||||
|
using UsageCopySrc = bool;
|
||||||
|
DAWN_TEST_PARAM_STRUCT(CopyTestsParams, UsageCopySrc)
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
class CopyTests_T2T : public CopyTests, public DawnTestWithParams<CopyTestsParams> {
|
||||||
protected:
|
protected:
|
||||||
|
std::vector<const char*> GetRequiredExtensions() override {
|
||||||
|
return {"dawn-internal-usages"};
|
||||||
|
}
|
||||||
|
|
||||||
void DoTest(const TextureSpec& srcSpec,
|
void DoTest(const TextureSpec& srcSpec,
|
||||||
const TextureSpec& dstSpec,
|
const TextureSpec& dstSpec,
|
||||||
const wgpu::Extent3D& copySize,
|
const wgpu::Extent3D& copySize,
|
||||||
|
@ -338,6 +349,12 @@ class CopyTests_T2T : public CopyTests {
|
||||||
wgpu::TextureDimension srcDimension,
|
wgpu::TextureDimension srcDimension,
|
||||||
wgpu::TextureDimension dstDimension,
|
wgpu::TextureDimension dstDimension,
|
||||||
bool copyWithinSameTexture = false) {
|
bool copyWithinSameTexture = false) {
|
||||||
|
const bool usageCopySrc = GetParam().mUsageCopySrc;
|
||||||
|
// If we do this test with a CopyWithinSameTexture, it will need to have usageCopySrc in the
|
||||||
|
// public usage of the texture as it will later use a CopyTextureToBuffer, that needs the
|
||||||
|
// public usage of it.
|
||||||
|
DAWN_TEST_UNSUPPORTED_IF(!usageCopySrc && copyWithinSameTexture);
|
||||||
|
|
||||||
ASSERT_EQ(srcSpec.format, dstSpec.format);
|
ASSERT_EQ(srcSpec.format, dstSpec.format);
|
||||||
const wgpu::TextureFormat format = srcSpec.format;
|
const wgpu::TextureFormat format = srcSpec.format;
|
||||||
|
|
||||||
|
@ -347,7 +364,17 @@ class CopyTests_T2T : public CopyTests {
|
||||||
srcDescriptor.sampleCount = 1;
|
srcDescriptor.sampleCount = 1;
|
||||||
srcDescriptor.format = format;
|
srcDescriptor.format = format;
|
||||||
srcDescriptor.mipLevelCount = srcSpec.levelCount;
|
srcDescriptor.mipLevelCount = srcSpec.levelCount;
|
||||||
srcDescriptor.usage = wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
|
srcDescriptor.usage = wgpu::TextureUsage::CopyDst;
|
||||||
|
// This test will have two versions, one where we check the normal CopyToCopy, and for that
|
||||||
|
// we will add the CopySrc usage, and the one where we test the CopyToCopyInternal, and then
|
||||||
|
// we have to add the CopySrc to the Internal usage.
|
||||||
|
wgpu::DawnTextureInternalUsageDescriptor internalDesc = {};
|
||||||
|
srcDescriptor.nextInChain = &internalDesc;
|
||||||
|
if (usageCopySrc) {
|
||||||
|
srcDescriptor.usage |= wgpu::TextureUsage::CopySrc;
|
||||||
|
} else {
|
||||||
|
internalDesc.internalUsage = wgpu::TextureUsage::CopySrc;
|
||||||
|
}
|
||||||
wgpu::Texture srcTexture = device.CreateTexture(&srcDescriptor);
|
wgpu::Texture srcTexture = device.CreateTexture(&srcDescriptor);
|
||||||
|
|
||||||
wgpu::Texture dstTexture;
|
wgpu::Texture dstTexture;
|
||||||
|
@ -394,7 +421,13 @@ class CopyTests_T2T : public CopyTests {
|
||||||
utils::CreateImageCopyTexture(srcTexture, srcSpec.copyLevel, srcSpec.copyOrigin);
|
utils::CreateImageCopyTexture(srcTexture, srcSpec.copyLevel, srcSpec.copyOrigin);
|
||||||
wgpu::ImageCopyTexture dstImageCopyTexture =
|
wgpu::ImageCopyTexture dstImageCopyTexture =
|
||||||
utils::CreateImageCopyTexture(dstTexture, dstSpec.copyLevel, dstSpec.copyOrigin);
|
utils::CreateImageCopyTexture(dstTexture, dstSpec.copyLevel, dstSpec.copyOrigin);
|
||||||
encoder.CopyTextureToTexture(&srcImageCopyTexture, &dstImageCopyTexture, ©Size);
|
|
||||||
|
if (usageCopySrc) {
|
||||||
|
encoder.CopyTextureToTexture(&srcImageCopyTexture, &dstImageCopyTexture, ©Size);
|
||||||
|
} else {
|
||||||
|
encoder.CopyTextureToTextureInternal(&srcImageCopyTexture, &dstImageCopyTexture,
|
||||||
|
©Size);
|
||||||
|
}
|
||||||
|
|
||||||
// Create an output buffer and use it to completely populate the subresources of the dst
|
// Create an output buffer and use it to completely populate the subresources of the dst
|
||||||
// texture that will be copied to at the given mip level.
|
// texture that will be copied to at the given mip level.
|
||||||
|
@ -2324,15 +2357,12 @@ TEST_P(CopyTests_T2T, Texture3DMipUnaligned) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(
|
DAWN_INSTANTIATE_TEST_P(CopyTests_T2T,
|
||||||
CopyTests_T2T,
|
{D3D12Backend(),
|
||||||
D3D12Backend(),
|
D3D12Backend({"use_temp_buffer_in_small_format_texture_to_texture_copy_"
|
||||||
D3D12Backend(
|
"from_greater_to_less_mip_level"}),
|
||||||
{"use_temp_buffer_in_small_format_texture_to_texture_copy_from_greater_to_less_mip_level"}),
|
MetalBackend(), OpenGLBackend(), OpenGLESBackend(), VulkanBackend()},
|
||||||
MetalBackend(),
|
{true, false});
|
||||||
OpenGLBackend(),
|
|
||||||
OpenGLESBackend(),
|
|
||||||
VulkanBackend());
|
|
||||||
|
|
||||||
static constexpr uint64_t kSmallBufferSize = 4;
|
static constexpr uint64_t kSmallBufferSize = 4;
|
||||||
static constexpr uint64_t kLargeBufferSize = 1 << 16;
|
static constexpr uint64_t kLargeBufferSize = 1 << 16;
|
||||||
|
|
|
@ -115,6 +115,7 @@ TEST_F(TextureInternalUsageValidationTest, UsageValidation) {
|
||||||
|
|
||||||
// Test that internal usage does not add to the validated usage
|
// Test that internal usage does not add to the validated usage
|
||||||
// for command encoding
|
// for command encoding
|
||||||
|
// This test also test the internal copy
|
||||||
TEST_F(TextureInternalUsageValidationTest, CommandValidation) {
|
TEST_F(TextureInternalUsageValidationTest, CommandValidation) {
|
||||||
wgpu::TextureDescriptor textureDesc = {};
|
wgpu::TextureDescriptor textureDesc = {};
|
||||||
textureDesc.size = {1, 1};
|
textureDesc.size = {1, 1};
|
||||||
|
@ -156,4 +157,27 @@ TEST_F(TextureInternalUsageValidationTest, CommandValidation) {
|
||||||
encoder.CopyTextureToTexture(&srcImageCopyTexture, &dstImageCopyTexture, &extent3D);
|
encoder.CopyTextureToTexture(&srcImageCopyTexture, &dstImageCopyTexture, &extent3D);
|
||||||
ASSERT_DEVICE_ERROR(encoder.Finish());
|
ASSERT_DEVICE_ERROR(encoder.Finish());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Control with internal copy: src -> dst
|
||||||
|
{
|
||||||
|
wgpu::ImageCopyTexture srcImageCopyTexture = utils::CreateImageCopyTexture(src, 0, {0, 0});
|
||||||
|
wgpu::ImageCopyTexture dstImageCopyTexture = utils::CreateImageCopyTexture(dst, 0, {0, 0});
|
||||||
|
wgpu::Extent3D extent3D = {1, 1};
|
||||||
|
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
encoder.CopyTextureToTextureInternal(&srcImageCopyTexture, &dstImageCopyTexture, &extent3D);
|
||||||
|
encoder.Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Valid with internal copy: src internal -> dst
|
||||||
|
{
|
||||||
|
wgpu::ImageCopyTexture srcImageCopyTexture =
|
||||||
|
utils::CreateImageCopyTexture(srcInternal, 0, {0, 0});
|
||||||
|
wgpu::ImageCopyTexture dstImageCopyTexture = utils::CreateImageCopyTexture(dst, 0, {0, 0});
|
||||||
|
wgpu::Extent3D extent3D = {1, 1};
|
||||||
|
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
encoder.CopyTextureToTextureInternal(&srcImageCopyTexture, &dstImageCopyTexture, &extent3D);
|
||||||
|
encoder.Finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue