mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-07 13:45:51 +00:00
Fixing offset alignments when using DynamicUploader
When using a dynamic uploader we didn't align the offset that the allocated memory might have already had. That fixes WriteTexture, WriteBuffer, ClearTexture and on D3D12 ClearBuffer. Bug: dawn:512 Change-Id: I64c7511ad6b0d3d6a28a494e1324a10ad4d38091 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/27020 Commit-Queue: Tomek Ponitka <tommek@google.com> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org> Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
parent
eff9ef0f22
commit
7f265d1d40
@ -64,4 +64,8 @@ static constexpr uint32_t kMaxTexture2DMipLevels = 14u;
|
|||||||
static_assert(1 << (kMaxTexture2DMipLevels - 1) == kMaxTextureSize,
|
static_assert(1 << (kMaxTexture2DMipLevels - 1) == kMaxTextureSize,
|
||||||
"kMaxTexture2DMipLevels and kMaxTextureSize size mismatch");
|
"kMaxTexture2DMipLevels and kMaxTextureSize size mismatch");
|
||||||
|
|
||||||
|
// Offset alignment for CopyB2B. Strictly speaking this alignment is required only
|
||||||
|
// on macOS, but we decide to do it on all platforms.
|
||||||
|
static constexpr uint64_t kCopyBufferToBufferOffsetAlignment = 4u;
|
||||||
|
|
||||||
#endif // COMMON_CONSTANTS_H_
|
#endif // COMMON_CONSTANTS_H_
|
||||||
|
@ -28,7 +28,8 @@ namespace dawn_native {
|
|||||||
mDevice->GetPendingCommandSerial());
|
mDevice->GetPendingCommandSerial());
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultOrError<UploadHandle> DynamicUploader::Allocate(uint64_t allocationSize, Serial serial) {
|
ResultOrError<UploadHandle> DynamicUploader::AllocateInternal(uint64_t allocationSize,
|
||||||
|
Serial serial) {
|
||||||
// Disable further sub-allocation should the request be too large.
|
// Disable further sub-allocation should the request be too large.
|
||||||
if (allocationSize > kRingBufferSize) {
|
if (allocationSize > kRingBufferSize) {
|
||||||
std::unique_ptr<StagingBufferBase> stagingBuffer;
|
std::unique_ptr<StagingBufferBase> stagingBuffer;
|
||||||
@ -108,4 +109,21 @@ namespace dawn_native {
|
|||||||
}
|
}
|
||||||
mReleasedStagingBuffers.ClearUpTo(lastCompletedSerial);
|
mReleasedStagingBuffers.ClearUpTo(lastCompletedSerial);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(dawn:512): Optimize this function so that it doesn't allocate additional memory
|
||||||
|
// when it's not necessary.
|
||||||
|
ResultOrError<UploadHandle> DynamicUploader::Allocate(uint64_t allocationSize,
|
||||||
|
Serial serial,
|
||||||
|
uint64_t offsetAlignment) {
|
||||||
|
ASSERT(offsetAlignment > 0);
|
||||||
|
UploadHandle uploadHandle;
|
||||||
|
DAWN_TRY_ASSIGN(uploadHandle,
|
||||||
|
AllocateInternal(allocationSize + offsetAlignment - 1, serial));
|
||||||
|
uint64_t additionalOffset =
|
||||||
|
Align(uploadHandle.startOffset, offsetAlignment) - uploadHandle.startOffset;
|
||||||
|
uploadHandle.mappedBuffer =
|
||||||
|
static_cast<uint8_t*>(uploadHandle.mappedBuffer) + additionalOffset;
|
||||||
|
uploadHandle.startOffset += additionalOffset;
|
||||||
|
return uploadHandle;
|
||||||
|
}
|
||||||
} // namespace dawn_native
|
} // namespace dawn_native
|
||||||
|
@ -40,7 +40,9 @@ namespace dawn_native {
|
|||||||
// implemented.
|
// implemented.
|
||||||
void ReleaseStagingBuffer(std::unique_ptr<StagingBufferBase> stagingBuffer);
|
void ReleaseStagingBuffer(std::unique_ptr<StagingBufferBase> stagingBuffer);
|
||||||
|
|
||||||
ResultOrError<UploadHandle> Allocate(uint64_t allocationSize, Serial serial);
|
ResultOrError<UploadHandle> Allocate(uint64_t allocationSize,
|
||||||
|
Serial serial,
|
||||||
|
uint64_t offsetAlignment);
|
||||||
void Deallocate(Serial lastCompletedSerial);
|
void Deallocate(Serial lastCompletedSerial);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -51,6 +53,8 @@ namespace dawn_native {
|
|||||||
RingBufferAllocator mAllocator;
|
RingBufferAllocator mAllocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ResultOrError<UploadHandle> AllocateInternal(uint64_t allocationSize, Serial serial);
|
||||||
|
|
||||||
std::vector<std::unique_ptr<RingBuffer>> mRingBuffers;
|
std::vector<std::unique_ptr<RingBuffer>> mRingBuffers;
|
||||||
SerialQueue<std::unique_ptr<StagingBufferBase>> mReleasedStagingBuffers;
|
SerialQueue<std::unique_ptr<StagingBufferBase>> mReleasedStagingBuffers;
|
||||||
DeviceBase* mDevice;
|
DeviceBase* mDevice;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "dawn_native/Queue.h"
|
#include "dawn_native/Queue.h"
|
||||||
|
|
||||||
|
#include "common/Constants.h"
|
||||||
#include "dawn_native/Buffer.h"
|
#include "dawn_native/Buffer.h"
|
||||||
#include "dawn_native/CommandBuffer.h"
|
#include "dawn_native/CommandBuffer.h"
|
||||||
#include "dawn_native/CommandValidation.h"
|
#include "dawn_native/CommandValidation.h"
|
||||||
@ -110,7 +111,8 @@ namespace dawn_native {
|
|||||||
|
|
||||||
UploadHandle uploadHandle;
|
UploadHandle uploadHandle;
|
||||||
DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
|
DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
|
||||||
size, device->GetPendingCommandSerial()));
|
size, device->GetPendingCommandSerial(),
|
||||||
|
kCopyBufferToBufferOffsetAlignment));
|
||||||
ASSERT(uploadHandle.mappedBuffer != nullptr);
|
ASSERT(uploadHandle.mappedBuffer != nullptr);
|
||||||
|
|
||||||
memcpy(uploadHandle.mappedBuffer, data, size);
|
memcpy(uploadHandle.mappedBuffer, data, size);
|
||||||
|
@ -425,7 +425,8 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
DynamicUploader* uploader = device->GetDynamicUploader();
|
DynamicUploader* uploader = device->GetDynamicUploader();
|
||||||
UploadHandle uploadHandle;
|
UploadHandle uploadHandle;
|
||||||
DAWN_TRY_ASSIGN(uploadHandle,
|
DAWN_TRY_ASSIGN(uploadHandle,
|
||||||
uploader->Allocate(GetSize(), device->GetPendingCommandSerial()));
|
uploader->Allocate(GetSize(), device->GetPendingCommandSerial(),
|
||||||
|
kCopyBufferToBufferOffsetAlignment));
|
||||||
|
|
||||||
memset(uploadHandle.mappedBuffer, clearValue, GetSize());
|
memset(uploadHandle.mappedBuffer, clearValue, GetSize());
|
||||||
|
|
||||||
|
@ -44,7 +44,8 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
|
|
||||||
UploadHandle uploadHandle;
|
UploadHandle uploadHandle;
|
||||||
DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
|
DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
|
||||||
newDataSizeBytes, device->GetPendingCommandSerial()));
|
newDataSizeBytes, device->GetPendingCommandSerial(),
|
||||||
|
textureFormat.blockByteSize));
|
||||||
ASSERT(uploadHandle.mappedBuffer != nullptr);
|
ASSERT(uploadHandle.mappedBuffer != nullptr);
|
||||||
|
|
||||||
uint8_t* dstPointer = static_cast<uint8_t*>(uploadHandle.mappedBuffer);
|
uint8_t* dstPointer = static_cast<uint8_t*>(uploadHandle.mappedBuffer);
|
||||||
|
@ -951,7 +951,8 @@ namespace dawn_native { namespace d3d12 {
|
|||||||
DynamicUploader* uploader = device->GetDynamicUploader();
|
DynamicUploader* uploader = device->GetDynamicUploader();
|
||||||
UploadHandle uploadHandle;
|
UploadHandle uploadHandle;
|
||||||
DAWN_TRY_ASSIGN(uploadHandle,
|
DAWN_TRY_ASSIGN(uploadHandle,
|
||||||
uploader->Allocate(bufferSize, device->GetPendingCommandSerial()));
|
uploader->Allocate(bufferSize, device->GetPendingCommandSerial(),
|
||||||
|
GetFormat().blockByteSize));
|
||||||
memset(uploadHandle.mappedBuffer, clearColor, bufferSize);
|
memset(uploadHandle.mappedBuffer, clearColor, bufferSize);
|
||||||
|
|
||||||
for (uint32_t level = range.baseMipLevel;
|
for (uint32_t level = range.baseMipLevel;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
|
|
||||||
#include "dawn_native/metal/DeviceMTL.h"
|
#include "dawn_native/metal/DeviceMTL.h"
|
||||||
|
|
||||||
|
#include "common/Platform.h"
|
||||||
#include "dawn_native/BackendConnection.h"
|
#include "dawn_native/BackendConnection.h"
|
||||||
#include "dawn_native/BindGroupLayout.h"
|
#include "dawn_native/BindGroupLayout.h"
|
||||||
#include "dawn_native/Commands.h"
|
#include "dawn_native/Commands.h"
|
||||||
@ -75,8 +76,10 @@ namespace dawn_native { namespace metal {
|
|||||||
{
|
{
|
||||||
bool haveStoreAndMSAAResolve = false;
|
bool haveStoreAndMSAAResolve = false;
|
||||||
#if defined(DAWN_PLATFORM_MACOS)
|
#if defined(DAWN_PLATFORM_MACOS)
|
||||||
|
if (@available(macOS 10.12, *)) {
|
||||||
haveStoreAndMSAAResolve =
|
haveStoreAndMSAAResolve =
|
||||||
[mMtlDevice supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v2];
|
[mMtlDevice supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily1_v2];
|
||||||
|
}
|
||||||
#elif defined(DAWN_PLATFORM_IOS)
|
#elif defined(DAWN_PLATFORM_IOS)
|
||||||
haveStoreAndMSAAResolve =
|
haveStoreAndMSAAResolve =
|
||||||
[mMtlDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v2];
|
[mMtlDevice supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v2];
|
||||||
|
@ -41,7 +41,8 @@ namespace dawn_native { namespace metal {
|
|||||||
|
|
||||||
UploadHandle uploadHandle;
|
UploadHandle uploadHandle;
|
||||||
DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
|
DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
|
||||||
newDataSizeBytes, device->GetPendingCommandSerial()));
|
newDataSizeBytes, device->GetPendingCommandSerial(),
|
||||||
|
blockInfo.blockByteSize));
|
||||||
ASSERT(uploadHandle.mappedBuffer != nullptr);
|
ASSERT(uploadHandle.mappedBuffer != nullptr);
|
||||||
|
|
||||||
uint8_t* dstPointer = static_cast<uint8_t*>(uploadHandle.mappedBuffer);
|
uint8_t* dstPointer = static_cast<uint8_t*>(uploadHandle.mappedBuffer);
|
||||||
|
@ -510,7 +510,8 @@ namespace dawn_native { namespace metal {
|
|||||||
DynamicUploader* uploader = device->GetDynamicUploader();
|
DynamicUploader* uploader = device->GetDynamicUploader();
|
||||||
UploadHandle uploadHandle;
|
UploadHandle uploadHandle;
|
||||||
DAWN_TRY_ASSIGN(uploadHandle,
|
DAWN_TRY_ASSIGN(uploadHandle,
|
||||||
uploader->Allocate(bufferSize, device->GetPendingCommandSerial()));
|
uploader->Allocate(bufferSize, device->GetPendingCommandSerial(),
|
||||||
|
GetFormat().blockByteSize));
|
||||||
memset(uploadHandle.mappedBuffer, clearColor, bufferSize);
|
memset(uploadHandle.mappedBuffer, clearColor, bufferSize);
|
||||||
|
|
||||||
id<MTLBlitCommandEncoder> encoder = commandContext->EnsureBlit();
|
id<MTLBlitCommandEncoder> encoder = commandContext->EnsureBlit();
|
||||||
|
@ -47,11 +47,17 @@ namespace dawn_native { namespace vulkan {
|
|||||||
ToBackend(device)
|
ToBackend(device)
|
||||||
->GetDeviceInfo()
|
->GetDeviceInfo()
|
||||||
.properties.limits.optimalBufferCopyOffsetAlignment;
|
.properties.limits.optimalBufferCopyOffsetAlignment;
|
||||||
|
ASSERT(IsPowerOfTwo(optimalOffsetAlignment));
|
||||||
|
ASSERT(IsPowerOfTwo(blockInfo.blockByteSize));
|
||||||
|
// We need the offset to be aligned to both optimalOffsetAlignment and blockByteSize,
|
||||||
|
// since both of them are powers of two, we only need to align to the max value.
|
||||||
|
uint64_t offsetAlignment =
|
||||||
|
std::max(optimalOffsetAlignment, uint64_t(blockInfo.blockByteSize));
|
||||||
|
|
||||||
UploadHandle uploadHandle;
|
UploadHandle uploadHandle;
|
||||||
DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
|
DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
|
||||||
newDataSizeBytes + optimalOffsetAlignment - 1,
|
newDataSizeBytes, device->GetPendingCommandSerial(),
|
||||||
device->GetPendingCommandSerial()));
|
offsetAlignment));
|
||||||
ASSERT(uploadHandle.mappedBuffer != nullptr);
|
ASSERT(uploadHandle.mappedBuffer != nullptr);
|
||||||
|
|
||||||
uint8_t* dstPointer = static_cast<uint8_t*>(uploadHandle.mappedBuffer);
|
uint8_t* dstPointer = static_cast<uint8_t*>(uploadHandle.mappedBuffer);
|
||||||
@ -64,11 +70,6 @@ namespace dawn_native { namespace vulkan {
|
|||||||
dataRowsPerImageInBlock = writeSizePixel.height / blockInfo.blockHeight;
|
dataRowsPerImageInBlock = writeSizePixel.height / blockInfo.blockHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t additionalOffset =
|
|
||||||
Align(uploadHandle.startOffset, optimalOffsetAlignment) - uploadHandle.startOffset;
|
|
||||||
uploadHandle.startOffset += additionalOffset;
|
|
||||||
dstPointer += additionalOffset;
|
|
||||||
|
|
||||||
ASSERT(dataRowsPerImageInBlock >= alignedRowsPerImageInBlock);
|
ASSERT(dataRowsPerImageInBlock >= alignedRowsPerImageInBlock);
|
||||||
uint64_t imageAdditionalStride =
|
uint64_t imageAdditionalStride =
|
||||||
dataLayout.bytesPerRow * (dataRowsPerImageInBlock - alignedRowsPerImageInBlock);
|
dataLayout.bytesPerRow * (dataRowsPerImageInBlock - alignedRowsPerImageInBlock);
|
||||||
|
@ -951,7 +951,8 @@ namespace dawn_native { namespace vulkan {
|
|||||||
DynamicUploader* uploader = device->GetDynamicUploader();
|
DynamicUploader* uploader = device->GetDynamicUploader();
|
||||||
UploadHandle uploadHandle;
|
UploadHandle uploadHandle;
|
||||||
DAWN_TRY_ASSIGN(uploadHandle,
|
DAWN_TRY_ASSIGN(uploadHandle,
|
||||||
uploader->Allocate(bufferSize, device->GetPendingCommandSerial()));
|
uploader->Allocate(bufferSize, device->GetPendingCommandSerial(),
|
||||||
|
GetFormat().blockByteSize));
|
||||||
memset(uploadHandle.mappedBuffer, clearColor, bufferSize);
|
memset(uploadHandle.mappedBuffer, clearColor, bufferSize);
|
||||||
|
|
||||||
// compute the buffer image copy to set the clear region of entire texture
|
// compute the buffer image copy to set the clear region of entire texture
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "tests/DawnTest.h"
|
#include "tests/DawnTest.h"
|
||||||
|
|
||||||
#include "utils/ComboRenderPipelineDescriptor.h"
|
#include "utils/ComboRenderPipelineDescriptor.h"
|
||||||
|
#include "utils/TestUtils.h"
|
||||||
#include "utils/WGPUHelpers.h"
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
#define EXPECT_LAZY_CLEAR(N, statement) \
|
#define EXPECT_LAZY_CLEAR(N, statement) \
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "common/Constants.h"
|
#include "common/Constants.h"
|
||||||
#include "common/Math.h"
|
#include "common/Math.h"
|
||||||
#include "utils/ComboRenderPipelineDescriptor.h"
|
#include "utils/ComboRenderPipelineDescriptor.h"
|
||||||
|
#include "utils/TestUtils.h"
|
||||||
#include "utils/TextureFormatUtils.h"
|
#include "utils/TextureFormatUtils.h"
|
||||||
#include "utils/WGPUHelpers.h"
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
@ -1066,6 +1067,35 @@ TEST_P(CompressedTextureBCFormatTest, CopyMultiple2DArrayLayers) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Testing a special code path: clearing a non-renderable texture when DynamicUploader
|
||||||
|
// is unaligned doesn't throw validation errors.
|
||||||
|
TEST_P(CompressedTextureBCFormatTest, UnalignedDynamicUploader) {
|
||||||
|
// CopyT2B for compressed texture formats is unimplemented on OpenGL.
|
||||||
|
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||||
|
|
||||||
|
utils::UnalignDynamicUploader(device);
|
||||||
|
|
||||||
|
wgpu::TextureDescriptor textureDescriptor = {};
|
||||||
|
textureDescriptor.size = {4, 4, 1};
|
||||||
|
textureDescriptor.format = wgpu::TextureFormat::BC1RGBAUnorm;
|
||||||
|
textureDescriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc;
|
||||||
|
wgpu::Texture texture = device.CreateTexture(&textureDescriptor);
|
||||||
|
|
||||||
|
wgpu::BufferDescriptor bufferDescriptor;
|
||||||
|
bufferDescriptor.size = 8;
|
||||||
|
bufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
|
||||||
|
wgpu::Buffer buffer = device.CreateBuffer(&bufferDescriptor);
|
||||||
|
|
||||||
|
wgpu::TextureCopyView textureCopyView = utils::CreateTextureCopyView(texture, 0, {0, 0, 0});
|
||||||
|
wgpu::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(buffer, 0, 256, 0);
|
||||||
|
wgpu::Extent3D copyExtent = {4, 4, 1};
|
||||||
|
|
||||||
|
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||||
|
encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, ©Extent);
|
||||||
|
wgpu::CommandBuffer commands = encoder.Finish();
|
||||||
|
queue.Submit(1, &commands);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(jiawei.shao@intel.com): support BC formats on OpenGL backend
|
// TODO(jiawei.shao@intel.com): support BC formats on OpenGL backend
|
||||||
DAWN_INSTANTIATE_TEST(CompressedTextureBCFormatTest,
|
DAWN_INSTANTIATE_TEST(CompressedTextureBCFormatTest,
|
||||||
D3D12Backend(),
|
D3D12Backend(),
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include "common/Constants.h"
|
#include "common/Constants.h"
|
||||||
#include "common/Math.h"
|
#include "common/Math.h"
|
||||||
|
#include "utils/TestUtils.h"
|
||||||
#include "utils/TextureFormatUtils.h"
|
#include "utils/TextureFormatUtils.h"
|
||||||
#include "utils/WGPUHelpers.h"
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "tests/DawnTest.h"
|
#include "tests/DawnTest.h"
|
||||||
|
|
||||||
#include "common/Math.h"
|
#include "common/Math.h"
|
||||||
|
#include "utils/TestUtils.h"
|
||||||
#include "utils/TextureFormatUtils.h"
|
#include "utils/TextureFormatUtils.h"
|
||||||
#include "utils/WGPUHelpers.h"
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
@ -170,6 +171,22 @@ TEST_P(QueueWriteBufferTests, SuperLargeWriteBuffer) {
|
|||||||
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), buffer, 0, kElements);
|
EXPECT_BUFFER_U32_RANGE_EQ(expectedData.data(), buffer, 0, kElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test a special code path: writing when dynamic uploader already contatins some unaligned
|
||||||
|
// data, it might be necessary to use a ring buffer with properly aligned offset.
|
||||||
|
TEST_P(QueueWriteBufferTests, UnalignedDynamicUploader) {
|
||||||
|
utils::UnalignDynamicUploader(device);
|
||||||
|
|
||||||
|
wgpu::BufferDescriptor descriptor;
|
||||||
|
descriptor.size = 4;
|
||||||
|
descriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
|
||||||
|
wgpu::Buffer buffer = device.CreateBuffer(&descriptor);
|
||||||
|
|
||||||
|
uint32_t value = 0x01020304;
|
||||||
|
queue.WriteBuffer(buffer, 0, &value, sizeof(value));
|
||||||
|
|
||||||
|
EXPECT_BUFFER_U32_EQ(value, buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(QueueWriteBufferTests,
|
DAWN_INSTANTIATE_TEST(QueueWriteBufferTests,
|
||||||
D3D12Backend(),
|
D3D12Backend(),
|
||||||
MetalBackend(),
|
MetalBackend(),
|
||||||
@ -522,4 +539,19 @@ TEST_P(QueueWriteTextureTests, VaryingArrayBytesPerRow) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Testing a special code path: writing when dynamic uploader already contatins some unaligned
|
||||||
|
// data, it might be necessary to use a ring buffer with properly aligned offset.
|
||||||
|
TEST_P(QueueWriteTextureTests, UnalignedDynamicUploader) {
|
||||||
|
utils::UnalignDynamicUploader(device);
|
||||||
|
|
||||||
|
constexpr wgpu::Extent3D size = {10, 10, 1};
|
||||||
|
|
||||||
|
TextureSpec textureSpec;
|
||||||
|
textureSpec.textureSize = size;
|
||||||
|
textureSpec.copyOrigin = {0, 0, 0};
|
||||||
|
textureSpec.level = 0;
|
||||||
|
|
||||||
|
DoTest(textureSpec, MinimumDataSpec(size), size);
|
||||||
|
}
|
||||||
|
|
||||||
DAWN_INSTANTIATE_TEST(QueueWriteTextureTests, D3D12Backend(), MetalBackend(), VulkanBackend());
|
DAWN_INSTANTIATE_TEST(QueueWriteTextureTests, D3D12Backend(), MetalBackend(), VulkanBackend());
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
#include "common/Math.h"
|
#include "common/Math.h"
|
||||||
#include "utils/ComboRenderPipelineDescriptor.h"
|
#include "utils/ComboRenderPipelineDescriptor.h"
|
||||||
|
#include "utils/TestUtils.h"
|
||||||
#include "utils/WGPUHelpers.h"
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
#define EXPECT_LAZY_CLEAR(N, statement) \
|
#define EXPECT_LAZY_CLEAR(N, statement) \
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "common/Constants.h"
|
#include "common/Constants.h"
|
||||||
#include "common/Math.h"
|
#include "common/Math.h"
|
||||||
#include "tests/unittests/validation/ValidationTest.h"
|
#include "tests/unittests/validation/ValidationTest.h"
|
||||||
|
#include "utils/TestUtils.h"
|
||||||
#include "utils/TextureFormatUtils.h"
|
#include "utils/TextureFormatUtils.h"
|
||||||
#include "utils/WGPUHelpers.h"
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "tests/unittests/validation/ValidationTest.h"
|
#include "tests/unittests/validation/ValidationTest.h"
|
||||||
|
|
||||||
#include "common/Math.h"
|
#include "common/Math.h"
|
||||||
|
#include "utils/TestUtils.h"
|
||||||
#include "utils/TextureFormatUtils.h"
|
#include "utils/TextureFormatUtils.h"
|
||||||
#include "utils/WGPUHelpers.h"
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
|
@ -75,6 +75,8 @@ static_library("dawn_utils") {
|
|||||||
"SystemUtils.h",
|
"SystemUtils.h",
|
||||||
"TerribleCommandBuffer.cpp",
|
"TerribleCommandBuffer.cpp",
|
||||||
"TerribleCommandBuffer.h",
|
"TerribleCommandBuffer.h",
|
||||||
|
"TestUtils.cpp",
|
||||||
|
"TestUtils.h",
|
||||||
"TextureFormatUtils.cpp",
|
"TextureFormatUtils.cpp",
|
||||||
"TextureFormatUtils.h",
|
"TextureFormatUtils.h",
|
||||||
"Timer.h",
|
"Timer.h",
|
||||||
|
@ -27,6 +27,8 @@ target_sources(dawn_utils PRIVATE
|
|||||||
"SystemUtils.h"
|
"SystemUtils.h"
|
||||||
"TerribleCommandBuffer.cpp"
|
"TerribleCommandBuffer.cpp"
|
||||||
"TerribleCommandBuffer.h"
|
"TerribleCommandBuffer.h"
|
||||||
|
"TestUtils.cpp"
|
||||||
|
"TestUtils.h"
|
||||||
"TextureFormatUtils.cpp"
|
"TextureFormatUtils.cpp"
|
||||||
"TextureFormatUtils.h"
|
"TextureFormatUtils.h"
|
||||||
"Timer.h"
|
"Timer.h"
|
||||||
|
107
src/utils/TestUtils.cpp
Normal file
107
src/utils/TestUtils.cpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// Copyright 2020 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 "utils/TestUtils.h"
|
||||||
|
|
||||||
|
#include "common/Assert.h"
|
||||||
|
#include "common/Constants.h"
|
||||||
|
#include "common/Math.h"
|
||||||
|
#include "utils/TextureFormatUtils.h"
|
||||||
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
uint32_t GetMinimumBytesPerRow(wgpu::TextureFormat format, uint32_t width) {
|
||||||
|
const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(format);
|
||||||
|
return Align(bytesPerTexel * width, kTextureBytesPerRowAlignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t GetBytesInBufferTextureCopy(wgpu::TextureFormat format,
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t bytesPerRow,
|
||||||
|
uint32_t rowsPerImage,
|
||||||
|
uint32_t copyArrayLayerCount) {
|
||||||
|
ASSERT(rowsPerImage > 0);
|
||||||
|
const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(format);
|
||||||
|
const uint32_t bytesAtLastImage = bytesPerRow * (rowsPerImage - 1) + bytesPerTexel * width;
|
||||||
|
return bytesPerRow * rowsPerImage * (copyArrayLayerCount - 1) + bytesAtLastImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(jiawei.shao@intel.com): support compressed texture formats
|
||||||
|
TextureDataCopyLayout GetTextureDataCopyLayoutForTexture2DAtLevel(
|
||||||
|
wgpu::TextureFormat format,
|
||||||
|
wgpu::Extent3D textureSizeAtLevel0,
|
||||||
|
uint32_t mipmapLevel,
|
||||||
|
uint32_t rowsPerImage) {
|
||||||
|
TextureDataCopyLayout layout;
|
||||||
|
|
||||||
|
layout.mipSize = {textureSizeAtLevel0.width >> mipmapLevel,
|
||||||
|
textureSizeAtLevel0.height >> mipmapLevel, textureSizeAtLevel0.depth};
|
||||||
|
|
||||||
|
layout.bytesPerRow = GetMinimumBytesPerRow(format, layout.mipSize.width);
|
||||||
|
|
||||||
|
uint32_t appliedRowsPerImage = rowsPerImage > 0 ? rowsPerImage : layout.mipSize.height;
|
||||||
|
layout.bytesPerImage = layout.bytesPerRow * appliedRowsPerImage;
|
||||||
|
|
||||||
|
layout.byteLength =
|
||||||
|
GetBytesInBufferTextureCopy(format, layout.mipSize.width, layout.bytesPerRow,
|
||||||
|
appliedRowsPerImage, textureSizeAtLevel0.depth);
|
||||||
|
|
||||||
|
const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(format);
|
||||||
|
layout.texelBlocksPerRow = layout.bytesPerRow / bytesPerTexel;
|
||||||
|
layout.texelBlocksPerImage = layout.bytesPerImage / bytesPerTexel;
|
||||||
|
layout.texelBlockCount = layout.byteLength / bytesPerTexel;
|
||||||
|
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t RequiredBytesInCopy(uint64_t bytesPerRow,
|
||||||
|
uint64_t rowsPerImage,
|
||||||
|
wgpu::Extent3D copyExtent,
|
||||||
|
wgpu::TextureFormat textureFormat) {
|
||||||
|
if (copyExtent.width == 0 || copyExtent.height == 0 || copyExtent.depth == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
uint32_t blockSize = utils::GetTexelBlockSizeInBytes(textureFormat);
|
||||||
|
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(textureFormat);
|
||||||
|
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(textureFormat);
|
||||||
|
|
||||||
|
uint64_t texelBlockRowsPerImage = rowsPerImage / blockHeight;
|
||||||
|
uint64_t bytesPerImage = bytesPerRow * texelBlockRowsPerImage;
|
||||||
|
uint64_t bytesInLastSlice = bytesPerRow * (copyExtent.height / blockHeight - 1) +
|
||||||
|
(copyExtent.width / blockWidth * blockSize);
|
||||||
|
return bytesPerImage * (copyExtent.depth - 1) + bytesInLastSlice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnalignDynamicUploader(wgpu::Device device) {
|
||||||
|
std::vector<uint8_t> data = {1};
|
||||||
|
|
||||||
|
wgpu::TextureDescriptor descriptor = {};
|
||||||
|
descriptor.size = {1, 1, 1};
|
||||||
|
descriptor.format = wgpu::TextureFormat::R8Unorm;
|
||||||
|
descriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc;
|
||||||
|
wgpu::Texture texture = device.CreateTexture(&descriptor);
|
||||||
|
|
||||||
|
wgpu::TextureCopyView textureCopyView = utils::CreateTextureCopyView(texture, 0, {0, 0, 0});
|
||||||
|
wgpu::TextureDataLayout textureDataLayout = utils::CreateTextureDataLayout(0, 0, 0);
|
||||||
|
wgpu::Extent3D copyExtent = {1, 1, 1};
|
||||||
|
|
||||||
|
// WriteTexture with exactly 1 byte of data.
|
||||||
|
device.GetDefaultQueue().WriteTexture(&textureCopyView, data.data(), 1, &textureDataLayout,
|
||||||
|
©Extent);
|
||||||
|
}
|
||||||
|
} // namespace utils
|
57
src/utils/TestUtils.h
Normal file
57
src/utils/TestUtils.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2020 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.
|
||||||
|
|
||||||
|
#ifndef UTILS_TESTHELPERS_H_
|
||||||
|
#define UTILS_TESTHELPERS_H_
|
||||||
|
|
||||||
|
#include <dawn/webgpu_cpp.h>
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
|
||||||
|
struct TextureDataCopyLayout {
|
||||||
|
uint64_t byteLength;
|
||||||
|
uint64_t texelBlockCount;
|
||||||
|
uint32_t bytesPerRow;
|
||||||
|
uint32_t texelBlocksPerRow;
|
||||||
|
uint32_t bytesPerImage;
|
||||||
|
uint32_t texelBlocksPerImage;
|
||||||
|
wgpu::Extent3D mipSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t GetMinimumBytesPerRow(wgpu::TextureFormat format, uint32_t width);
|
||||||
|
uint32_t GetBytesInBufferTextureCopy(wgpu::TextureFormat format,
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t bytesPerRow,
|
||||||
|
uint32_t rowsPerImage,
|
||||||
|
uint32_t copyArrayLayerCount);
|
||||||
|
TextureDataCopyLayout GetTextureDataCopyLayoutForTexture2DAtLevel(
|
||||||
|
wgpu::TextureFormat format,
|
||||||
|
wgpu::Extent3D textureSizeAtLevel0,
|
||||||
|
uint32_t mipmapLevel,
|
||||||
|
uint32_t rowsPerImage);
|
||||||
|
|
||||||
|
uint64_t RequiredBytesInCopy(uint64_t bytesPerRow,
|
||||||
|
uint64_t rowsPerImage,
|
||||||
|
wgpu::Extent3D copyExtent,
|
||||||
|
wgpu::TextureFormat textureFormat);
|
||||||
|
|
||||||
|
// A helper function used for testing DynamicUploader offset alignment.
|
||||||
|
// A call of this function will do a Queue::WriteTexture with 1 byte of data,
|
||||||
|
// so that assuming that WriteTexture uses DynamicUploader, the first RingBuffer
|
||||||
|
// in it will contain 1 byte of data.
|
||||||
|
void UnalignDynamicUploader(wgpu::Device device);
|
||||||
|
|
||||||
|
} // namespace utils
|
||||||
|
|
||||||
|
#endif // UTILS_TESTHELPERS_H_
|
@ -78,6 +78,15 @@ namespace utils {
|
|||||||
wgpu::TextureFormat::BC7RGBAUnormSrgb,
|
wgpu::TextureFormat::BC7RGBAUnormSrgb,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static constexpr std::array<wgpu::TextureFormat, 14> kBCFormats = {
|
||||||
|
wgpu::TextureFormat::BC1RGBAUnorm, wgpu::TextureFormat::BC1RGBAUnormSrgb,
|
||||||
|
wgpu::TextureFormat::BC2RGBAUnorm, wgpu::TextureFormat::BC2RGBAUnormSrgb,
|
||||||
|
wgpu::TextureFormat::BC3RGBAUnorm, wgpu::TextureFormat::BC3RGBAUnormSrgb,
|
||||||
|
wgpu::TextureFormat::BC4RUnorm, wgpu::TextureFormat::BC4RSnorm,
|
||||||
|
wgpu::TextureFormat::BC5RGUnorm, wgpu::TextureFormat::BC5RGSnorm,
|
||||||
|
wgpu::TextureFormat::BC6HRGBUfloat, wgpu::TextureFormat::BC6HRGBSfloat,
|
||||||
|
wgpu::TextureFormat::BC7RGBAUnorm, wgpu::TextureFormat::BC7RGBAUnormSrgb};
|
||||||
|
|
||||||
const char* GetColorTextureComponentTypePrefix(wgpu::TextureFormat textureFormat);
|
const char* GetColorTextureComponentTypePrefix(wgpu::TextureFormat textureFormat);
|
||||||
bool TextureFormatSupportsStorageTexture(wgpu::TextureFormat format);
|
bool TextureFormatSupportsStorageTexture(wgpu::TextureFormat format);
|
||||||
|
|
||||||
|
@ -14,11 +14,8 @@
|
|||||||
|
|
||||||
#include "utils/WGPUHelpers.h"
|
#include "utils/WGPUHelpers.h"
|
||||||
|
|
||||||
#include "common/Assert.h"
|
|
||||||
#include "common/Constants.h"
|
#include "common/Constants.h"
|
||||||
#include "common/Log.h"
|
#include "common/Log.h"
|
||||||
#include "common/Math.h"
|
|
||||||
#include "utils/TextureFormatUtils.h"
|
|
||||||
|
|
||||||
#include <shaderc/shaderc.hpp>
|
#include <shaderc/shaderc.hpp>
|
||||||
|
|
||||||
@ -393,76 +390,4 @@ namespace utils {
|
|||||||
return device.CreateBindGroup(&descriptor);
|
return device.CreateBindGroup(&descriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t GetMinimumBytesPerRow(wgpu::TextureFormat format, uint32_t width) {
|
|
||||||
const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(format);
|
|
||||||
return Align(bytesPerTexel * width, kTextureBytesPerRowAlignment);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t GetBytesInBufferTextureCopy(wgpu::TextureFormat format,
|
|
||||||
uint32_t width,
|
|
||||||
uint32_t bytesPerRow,
|
|
||||||
uint32_t rowsPerImage,
|
|
||||||
uint32_t copyArrayLayerCount) {
|
|
||||||
ASSERT(rowsPerImage > 0);
|
|
||||||
const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(format);
|
|
||||||
const uint32_t bytesAtLastImage = bytesPerRow * (rowsPerImage - 1) + bytesPerTexel * width;
|
|
||||||
return bytesPerRow * rowsPerImage * (copyArrayLayerCount - 1) + bytesAtLastImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(jiawei.shao@intel.com): support compressed texture formats
|
|
||||||
TextureDataCopyLayout GetTextureDataCopyLayoutForTexture2DAtLevel(
|
|
||||||
wgpu::TextureFormat format,
|
|
||||||
wgpu::Extent3D textureSizeAtLevel0,
|
|
||||||
uint32_t mipmapLevel,
|
|
||||||
uint32_t rowsPerImage) {
|
|
||||||
TextureDataCopyLayout layout;
|
|
||||||
|
|
||||||
layout.mipSize = {textureSizeAtLevel0.width >> mipmapLevel,
|
|
||||||
textureSizeAtLevel0.height >> mipmapLevel, textureSizeAtLevel0.depth};
|
|
||||||
|
|
||||||
layout.bytesPerRow = GetMinimumBytesPerRow(format, layout.mipSize.width);
|
|
||||||
|
|
||||||
uint32_t appliedRowsPerImage = rowsPerImage > 0 ? rowsPerImage : layout.mipSize.height;
|
|
||||||
layout.bytesPerImage = layout.bytesPerRow * appliedRowsPerImage;
|
|
||||||
|
|
||||||
layout.byteLength =
|
|
||||||
GetBytesInBufferTextureCopy(format, layout.mipSize.width, layout.bytesPerRow,
|
|
||||||
appliedRowsPerImage, textureSizeAtLevel0.depth);
|
|
||||||
|
|
||||||
const uint32_t bytesPerTexel = utils::GetTexelBlockSizeInBytes(format);
|
|
||||||
layout.texelBlocksPerRow = layout.bytesPerRow / bytesPerTexel;
|
|
||||||
layout.texelBlocksPerImage = layout.bytesPerImage / bytesPerTexel;
|
|
||||||
layout.texelBlockCount = layout.byteLength / bytesPerTexel;
|
|
||||||
|
|
||||||
return layout;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::array<wgpu::TextureFormat, 14> kBCFormats = {
|
|
||||||
wgpu::TextureFormat::BC1RGBAUnorm, wgpu::TextureFormat::BC1RGBAUnormSrgb,
|
|
||||||
wgpu::TextureFormat::BC2RGBAUnorm, wgpu::TextureFormat::BC2RGBAUnormSrgb,
|
|
||||||
wgpu::TextureFormat::BC3RGBAUnorm, wgpu::TextureFormat::BC3RGBAUnormSrgb,
|
|
||||||
wgpu::TextureFormat::BC4RUnorm, wgpu::TextureFormat::BC4RSnorm,
|
|
||||||
wgpu::TextureFormat::BC5RGUnorm, wgpu::TextureFormat::BC5RGSnorm,
|
|
||||||
wgpu::TextureFormat::BC6HRGBUfloat, wgpu::TextureFormat::BC6HRGBSfloat,
|
|
||||||
wgpu::TextureFormat::BC7RGBAUnorm, wgpu::TextureFormat::BC7RGBAUnormSrgb};
|
|
||||||
|
|
||||||
uint64_t RequiredBytesInCopy(uint64_t bytesPerRow,
|
|
||||||
uint64_t rowsPerImage,
|
|
||||||
wgpu::Extent3D copyExtent,
|
|
||||||
wgpu::TextureFormat textureFormat) {
|
|
||||||
if (copyExtent.width == 0 || copyExtent.height == 0 || copyExtent.depth == 0) {
|
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
uint32_t blockSize = utils::GetTexelBlockSizeInBytes(textureFormat);
|
|
||||||
uint32_t blockWidth = utils::GetTextureFormatBlockWidth(textureFormat);
|
|
||||||
uint32_t blockHeight = utils::GetTextureFormatBlockHeight(textureFormat);
|
|
||||||
|
|
||||||
uint64_t texelBlockRowsPerImage = rowsPerImage / blockHeight;
|
|
||||||
uint64_t bytesPerImage = bytesPerRow * texelBlockRowsPerImage;
|
|
||||||
uint64_t bytesInLastSlice = bytesPerRow * (copyExtent.height / blockHeight - 1) +
|
|
||||||
(copyExtent.width / blockWidth * blockSize);
|
|
||||||
return bytesPerImage * (copyExtent.depth - 1) + bytesInLastSlice;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
@ -137,35 +137,6 @@ namespace utils {
|
|||||||
const wgpu::BindGroupLayout& layout,
|
const wgpu::BindGroupLayout& layout,
|
||||||
std::initializer_list<BindingInitializationHelper> entriesInitializer);
|
std::initializer_list<BindingInitializationHelper> entriesInitializer);
|
||||||
|
|
||||||
struct TextureDataCopyLayout {
|
|
||||||
uint64_t byteLength;
|
|
||||||
uint64_t texelBlockCount;
|
|
||||||
uint32_t bytesPerRow;
|
|
||||||
uint32_t texelBlocksPerRow;
|
|
||||||
uint32_t bytesPerImage;
|
|
||||||
uint32_t texelBlocksPerImage;
|
|
||||||
wgpu::Extent3D mipSize;
|
|
||||||
};
|
|
||||||
|
|
||||||
uint32_t GetMinimumBytesPerRow(wgpu::TextureFormat format, uint32_t width);
|
|
||||||
uint32_t GetBytesInBufferTextureCopy(wgpu::TextureFormat format,
|
|
||||||
uint32_t width,
|
|
||||||
uint32_t bytesPerRow,
|
|
||||||
uint32_t rowsPerImage,
|
|
||||||
uint32_t copyArrayLayerCount);
|
|
||||||
TextureDataCopyLayout GetTextureDataCopyLayoutForTexture2DAtLevel(
|
|
||||||
wgpu::TextureFormat format,
|
|
||||||
wgpu::Extent3D textureSizeAtLevel0,
|
|
||||||
uint32_t mipmapLevel,
|
|
||||||
uint32_t rowsPerImage);
|
|
||||||
|
|
||||||
extern const std::array<wgpu::TextureFormat, 14> kBCFormats;
|
|
||||||
|
|
||||||
uint64_t RequiredBytesInCopy(uint64_t bytesPerRow,
|
|
||||||
uint64_t rowsPerImage,
|
|
||||||
wgpu::Extent3D copyExtent,
|
|
||||||
wgpu::TextureFormat textureFormat);
|
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
#endif // UTILS_DAWNHELPERS_H_
|
#endif // UTILS_DAWNHELPERS_H_
|
||||||
|
Loading…
x
Reference in New Issue
Block a user