Format: Move the TexelBlockInfo inside an AspectInfo.
In follow up CLs additional will be added to the AspectInfo, like the supported component types. Also simplify the logic for GetTexelInfo since all aspects are the first aspects, except stencil which is always stencil8. Bug: dawn:517 Change-Id: Iebbcb8a7f8fa2c4b7b06f65d6e4e8917c0a85366 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/30100 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Austin Eng <enga@chromium.org>
This commit is contained in:
parent
84b70a6e4d
commit
6298d2b70c
|
@ -168,15 +168,15 @@ namespace dawn_native {
|
||||||
|
|
||||||
const TextureBase* texture = copy->source.texture.Get();
|
const TextureBase* texture = copy->source.texture.Get();
|
||||||
const TexelBlockInfo& blockInfo =
|
const TexelBlockInfo& blockInfo =
|
||||||
texture->GetFormat().GetTexelBlockInfo(copy->source.aspect);
|
texture->GetFormat().GetAspectInfo(copy->source.aspect).block;
|
||||||
const uint64_t heightInBlocks = copy->copySize.height / blockInfo.blockHeight;
|
const uint64_t heightInBlocks = copy->copySize.height / blockInfo.height;
|
||||||
|
|
||||||
if (copy->destination.rowsPerImage > heightInBlocks) {
|
if (copy->destination.rowsPerImage > heightInBlocks) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint64_t copyTextureDataSizePerRow =
|
const uint64_t copyTextureDataSizePerRow =
|
||||||
copy->copySize.width / blockInfo.blockWidth * blockInfo.blockByteSize;
|
copy->copySize.width / blockInfo.width * blockInfo.byteSize;
|
||||||
if (copy->destination.bytesPerRow > copyTextureDataSizePerRow) {
|
if (copy->destination.bytesPerRow > copyTextureDataSizePerRow) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -650,7 +650,7 @@ namespace dawn_native {
|
||||||
DAWN_TRY(ValidateTextureCopyRange(*destination, *copySize));
|
DAWN_TRY(ValidateTextureCopyRange(*destination, *copySize));
|
||||||
}
|
}
|
||||||
const TexelBlockInfo& blockInfo =
|
const TexelBlockInfo& blockInfo =
|
||||||
destination->texture->GetFormat().GetTexelBlockInfo(destination->aspect);
|
destination->texture->GetFormat().GetAspectInfo(destination->aspect).block;
|
||||||
if (GetDevice()->IsValidationEnabled()) {
|
if (GetDevice()->IsValidationEnabled()) {
|
||||||
DAWN_TRY(ValidateLinearTextureData(source->layout, source->buffer->GetSize(),
|
DAWN_TRY(ValidateLinearTextureData(source->layout, source->buffer->GetSize(),
|
||||||
blockInfo, *copySize));
|
blockInfo, *copySize));
|
||||||
|
@ -662,15 +662,15 @@ namespace dawn_native {
|
||||||
// Compute default value for rowsPerImage
|
// Compute default value for rowsPerImage
|
||||||
uint32_t defaultedRowsPerImage = source->layout.rowsPerImage;
|
uint32_t defaultedRowsPerImage = source->layout.rowsPerImage;
|
||||||
if (defaultedRowsPerImage == 0) {
|
if (defaultedRowsPerImage == 0) {
|
||||||
ASSERT(copySize->height % blockInfo.blockHeight == 0);
|
ASSERT(copySize->height % blockInfo.height == 0);
|
||||||
defaultedRowsPerImage = copySize->height / blockInfo.blockHeight;
|
defaultedRowsPerImage = copySize->height / blockInfo.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In the case of one row copy bytesPerRow might not contain enough bytes
|
// In the case of one row copy bytesPerRow might not contain enough bytes
|
||||||
uint32_t bytesPerRow = source->layout.bytesPerRow;
|
uint32_t bytesPerRow = source->layout.bytesPerRow;
|
||||||
if (copySize->height <= 1 && copySize->depth <= 1) {
|
if (copySize->height <= 1 && copySize->depth <= 1) {
|
||||||
bytesPerRow =
|
bytesPerRow =
|
||||||
Align(copySize->width * blockInfo.blockByteSize, kTextureBytesPerRowAlignment);
|
Align(copySize->width * blockInfo.byteSize, kTextureBytesPerRowAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip noop copies.
|
// Skip noop copies.
|
||||||
|
@ -714,11 +714,10 @@ namespace dawn_native {
|
||||||
DAWN_TRY(ValidateTextureCopyRange(*source, *copySize));
|
DAWN_TRY(ValidateTextureCopyRange(*source, *copySize));
|
||||||
}
|
}
|
||||||
const TexelBlockInfo& blockInfo =
|
const TexelBlockInfo& blockInfo =
|
||||||
source->texture->GetFormat().GetTexelBlockInfo(source->aspect);
|
source->texture->GetFormat().GetAspectInfo(source->aspect).block;
|
||||||
if (GetDevice()->IsValidationEnabled()) {
|
if (GetDevice()->IsValidationEnabled()) {
|
||||||
DAWN_TRY(ValidateLinearTextureData(
|
DAWN_TRY(ValidateLinearTextureData(
|
||||||
destination->layout, destination->buffer->GetSize(),
|
destination->layout, destination->buffer->GetSize(), blockInfo, *copySize));
|
||||||
source->texture->GetFormat().GetTexelBlockInfo(source->aspect), *copySize));
|
|
||||||
|
|
||||||
mTopLevelTextures.insert(source->texture);
|
mTopLevelTextures.insert(source->texture);
|
||||||
mTopLevelBuffers.insert(destination->buffer);
|
mTopLevelBuffers.insert(destination->buffer);
|
||||||
|
@ -727,15 +726,15 @@ namespace dawn_native {
|
||||||
// Compute default value for rowsPerImage
|
// Compute default value for rowsPerImage
|
||||||
uint32_t defaultedRowsPerImage = destination->layout.rowsPerImage;
|
uint32_t defaultedRowsPerImage = destination->layout.rowsPerImage;
|
||||||
if (defaultedRowsPerImage == 0) {
|
if (defaultedRowsPerImage == 0) {
|
||||||
ASSERT(copySize->height % blockInfo.blockHeight == 0);
|
ASSERT(copySize->height % blockInfo.height == 0);
|
||||||
defaultedRowsPerImage = copySize->height / blockInfo.blockHeight;
|
defaultedRowsPerImage = copySize->height / blockInfo.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
// In the case of one row copy bytesPerRow might not contain enough bytes
|
// In the case of one row copy bytesPerRow might not contain enough bytes
|
||||||
uint32_t bytesPerRow = destination->layout.bytesPerRow;
|
uint32_t bytesPerRow = destination->layout.bytesPerRow;
|
||||||
if (copySize->height <= 1 && copySize->depth <= 1) {
|
if (copySize->height <= 1 && copySize->depth <= 1) {
|
||||||
bytesPerRow =
|
bytesPerRow =
|
||||||
Align(copySize->width * blockInfo.blockByteSize, kTextureBytesPerRowAlignment);
|
Align(copySize->width * blockInfo.byteSize, kTextureBytesPerRowAlignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip noop copies.
|
// Skip noop copies.
|
||||||
|
|
|
@ -374,8 +374,8 @@ namespace dawn_native {
|
||||||
const Extent3D& copySize,
|
const Extent3D& copySize,
|
||||||
uint32_t bytesPerRow,
|
uint32_t bytesPerRow,
|
||||||
uint32_t rowsPerImage) {
|
uint32_t rowsPerImage) {
|
||||||
ASSERT(copySize.height % blockInfo.blockHeight == 0);
|
ASSERT(copySize.height % blockInfo.height == 0);
|
||||||
uint32_t heightInBlocks = copySize.height / blockInfo.blockHeight;
|
uint32_t heightInBlocks = copySize.height / blockInfo.height;
|
||||||
|
|
||||||
// Default value for rowsPerImage
|
// Default value for rowsPerImage
|
||||||
if (rowsPerImage == 0) {
|
if (rowsPerImage == 0) {
|
||||||
|
@ -384,7 +384,7 @@ namespace dawn_native {
|
||||||
|
|
||||||
ASSERT(rowsPerImage >= heightInBlocks);
|
ASSERT(rowsPerImage >= heightInBlocks);
|
||||||
if (copySize.height > 1 || copySize.depth > 1) {
|
if (copySize.height > 1 || copySize.depth > 1) {
|
||||||
ASSERT(bytesPerRow >= copySize.width / blockInfo.blockWidth * blockInfo.blockByteSize);
|
ASSERT(bytesPerRow >= copySize.width / blockInfo.width * blockInfo.byteSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copySize.width == 0 || copySize.height == 0 || copySize.depth == 0) {
|
if (copySize.width == 0 || copySize.height == 0 || copySize.depth == 0) {
|
||||||
|
@ -400,7 +400,7 @@ namespace dawn_native {
|
||||||
// bytesPerImage. Otherwise the result is a multiplication of two uint32_t numbers.
|
// bytesPerImage. Otherwise the result is a multiplication of two uint32_t numbers.
|
||||||
uint64_t bytesInLastSlice =
|
uint64_t bytesInLastSlice =
|
||||||
uint64_t(bytesPerRow) * (heightInBlocks - 1) +
|
uint64_t(bytesPerRow) * (heightInBlocks - 1) +
|
||||||
(uint64_t(copySize.width) / blockInfo.blockWidth * blockInfo.blockByteSize);
|
(uint64_t(copySize.width) / blockInfo.width * blockInfo.byteSize);
|
||||||
|
|
||||||
// This error cannot be thrown for copySize.depth = 1.
|
// This error cannot be thrown for copySize.depth = 1.
|
||||||
// For copySize.depth > 1 we know that:
|
// For copySize.depth > 1 we know that:
|
||||||
|
@ -430,14 +430,13 @@ namespace dawn_native {
|
||||||
const TexelBlockInfo& blockInfo,
|
const TexelBlockInfo& blockInfo,
|
||||||
const Extent3D& copyExtent) {
|
const Extent3D& copyExtent) {
|
||||||
// Validation for the texel block alignments:
|
// Validation for the texel block alignments:
|
||||||
if (layout.offset % blockInfo.blockByteSize != 0) {
|
if (layout.offset % blockInfo.byteSize != 0) {
|
||||||
return DAWN_VALIDATION_ERROR("Offset must be a multiple of the texel or block size");
|
return DAWN_VALIDATION_ERROR("Offset must be a multiple of the texel or block size");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validation for other members in layout:
|
// Validation for other members in layout:
|
||||||
if ((copyExtent.height > 1 || copyExtent.depth > 1) &&
|
if ((copyExtent.height > 1 || copyExtent.depth > 1) &&
|
||||||
layout.bytesPerRow <
|
layout.bytesPerRow < copyExtent.width / blockInfo.width * blockInfo.byteSize) {
|
||||||
copyExtent.width / blockInfo.blockWidth * blockInfo.blockByteSize) {
|
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"bytesPerRow must not be less than the number of bytes per row");
|
"bytesPerRow must not be less than the number of bytes per row");
|
||||||
}
|
}
|
||||||
|
@ -445,8 +444,8 @@ namespace dawn_native {
|
||||||
// TODO(tommek@google.com): to match the spec there should be another condition here
|
// TODO(tommek@google.com): to match the spec there should be another condition here
|
||||||
// on rowsPerImage >= copyExtent.height if copyExtent.depth > 1.
|
// on rowsPerImage >= copyExtent.height if copyExtent.depth > 1.
|
||||||
|
|
||||||
ASSERT(copyExtent.height % blockInfo.blockHeight == 0);
|
ASSERT(copyExtent.height % blockInfo.height == 0);
|
||||||
uint32_t heightInBlocks = copyExtent.height / blockInfo.blockHeight;
|
uint32_t heightInBlocks = copyExtent.height / blockInfo.height;
|
||||||
|
|
||||||
// Validation for the copy being in-bounds:
|
// Validation for the copy being in-bounds:
|
||||||
if (layout.rowsPerImage != 0 && layout.rowsPerImage < heightInBlocks) {
|
if (layout.rowsPerImage != 0 && layout.rowsPerImage < heightInBlocks) {
|
||||||
|
@ -551,25 +550,27 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validation for the texel block alignments:
|
// Validation for the texel block alignments:
|
||||||
const TexelBlockInfo& blockInfo =
|
const Format& format = textureCopy.texture->GetFormat();
|
||||||
textureCopy.texture->GetFormat().GetTexelBlockInfo(textureCopy.aspect);
|
if (format.isCompressed) {
|
||||||
if (textureCopy.origin.x % blockInfo.blockWidth != 0) {
|
const TexelBlockInfo& blockInfo = format.GetAspectInfo(textureCopy.aspect).block;
|
||||||
|
if (textureCopy.origin.x % blockInfo.width != 0) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"Offset.x must be a multiple of compressed texture format block width");
|
"Offset.x must be a multiple of compressed texture format block width");
|
||||||
}
|
}
|
||||||
if (textureCopy.origin.y % blockInfo.blockHeight != 0) {
|
if (textureCopy.origin.y % blockInfo.height != 0) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"Offset.y must be a multiple of compressed texture format block height");
|
"Offset.y must be a multiple of compressed texture format block height");
|
||||||
}
|
}
|
||||||
if (copySize.width % blockInfo.blockWidth != 0) {
|
if (copySize.width % blockInfo.width != 0) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"copySize.width must be a multiple of compressed texture format block width");
|
"copySize.width must be a multiple of compressed texture format block width");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (copySize.height % blockInfo.blockHeight != 0) {
|
if (copySize.height % blockInfo.height != 0) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"copySize.height must be a multiple of compressed texture format block height");
|
"copySize.height must be a multiple of compressed texture format block height");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,12 @@
|
||||||
|
|
||||||
namespace dawn_native {
|
namespace dawn_native {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
static const AspectInfo kStencil8AspectInfo = {{1, 1, 1}};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Format
|
// Format
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
@ -78,62 +84,20 @@ namespace dawn_native {
|
||||||
return componentType == type;
|
return componentType == type;
|
||||||
}
|
}
|
||||||
|
|
||||||
TexelBlockInfo Format::GetTexelBlockInfo(wgpu::TextureAspect aspect) const {
|
const AspectInfo& Format::GetAspectInfo(wgpu::TextureAspect aspect) const {
|
||||||
switch (aspect) {
|
return GetAspectInfo(ConvertAspect(*this, aspect));
|
||||||
case wgpu::TextureAspect::All:
|
|
||||||
return blockInfo;
|
|
||||||
|
|
||||||
case wgpu::TextureAspect::DepthOnly:
|
|
||||||
ASSERT(HasDepth());
|
|
||||||
switch (format) {
|
|
||||||
case wgpu::TextureFormat::Depth32Float:
|
|
||||||
return blockInfo;
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case wgpu::TextureAspect::StencilOnly:
|
|
||||||
ASSERT(HasStencil());
|
|
||||||
switch (format) {
|
|
||||||
case wgpu::TextureFormat::Depth24PlusStencil8:
|
|
||||||
return {1, 1, 1};
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TexelBlockInfo Format::GetTexelBlockInfo(Aspect aspect) const {
|
const AspectInfo& Format::GetAspectInfo(Aspect aspect) const {
|
||||||
ASSERT(HasOneBit(aspect));
|
ASSERT(HasOneBit(aspect));
|
||||||
ASSERT(aspects & aspect);
|
ASSERT(aspects & aspect);
|
||||||
switch (aspect) {
|
|
||||||
case Aspect::Color:
|
|
||||||
ASSERT(aspects == aspect);
|
|
||||||
return blockInfo;
|
|
||||||
case Aspect::Depth:
|
|
||||||
switch (format) {
|
|
||||||
case wgpu::TextureFormat::Depth32Float:
|
|
||||||
return blockInfo;
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Aspect::Stencil:
|
|
||||||
switch (format) {
|
|
||||||
case wgpu::TextureFormat::Depth24PlusStencil8:
|
|
||||||
return {1, 1, 1};
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Aspect::None:
|
// The stencil aspect is the only aspect that's not the first aspect. Since it is alwaus the
|
||||||
UNREACHABLE();
|
// same aspect information, special case it to return a constant AspectInfo.
|
||||||
|
if (aspect == Aspect::Stencil) {
|
||||||
|
return kStencil8AspectInfo;
|
||||||
|
} else {
|
||||||
|
return firstAspect;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,9 +146,9 @@ namespace dawn_native {
|
||||||
internalFormat.supportsStorageUsage = supportsStorageUsage;
|
internalFormat.supportsStorageUsage = supportsStorageUsage;
|
||||||
internalFormat.aspects = Aspect::Color;
|
internalFormat.aspects = Aspect::Color;
|
||||||
internalFormat.type = type;
|
internalFormat.type = type;
|
||||||
internalFormat.blockInfo.blockByteSize = byteSize;
|
internalFormat.firstAspect.block.byteSize = byteSize;
|
||||||
internalFormat.blockInfo.blockWidth = 1;
|
internalFormat.firstAspect.block.width = 1;
|
||||||
internalFormat.blockInfo.blockHeight = 1;
|
internalFormat.firstAspect.block.height = 1;
|
||||||
AddFormat(internalFormat);
|
AddFormat(internalFormat);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -198,9 +162,9 @@ namespace dawn_native {
|
||||||
internalFormat.supportsStorageUsage = false;
|
internalFormat.supportsStorageUsage = false;
|
||||||
internalFormat.aspects = aspects;
|
internalFormat.aspects = aspects;
|
||||||
internalFormat.type = Type::Other;
|
internalFormat.type = Type::Other;
|
||||||
internalFormat.blockInfo.blockByteSize = byteSize;
|
internalFormat.firstAspect.block.byteSize = byteSize;
|
||||||
internalFormat.blockInfo.blockWidth = 1;
|
internalFormat.firstAspect.block.width = 1;
|
||||||
internalFormat.blockInfo.blockHeight = 1;
|
internalFormat.firstAspect.block.height = 1;
|
||||||
AddFormat(internalFormat);
|
AddFormat(internalFormat);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -214,9 +178,9 @@ namespace dawn_native {
|
||||||
internalFormat.supportsStorageUsage = false;
|
internalFormat.supportsStorageUsage = false;
|
||||||
internalFormat.aspects = Aspect::Depth;
|
internalFormat.aspects = Aspect::Depth;
|
||||||
internalFormat.type = type;
|
internalFormat.type = type;
|
||||||
internalFormat.blockInfo.blockByteSize = byteSize;
|
internalFormat.firstAspect.block.byteSize = byteSize;
|
||||||
internalFormat.blockInfo.blockWidth = 1;
|
internalFormat.firstAspect.block.width = 1;
|
||||||
internalFormat.blockInfo.blockHeight = 1;
|
internalFormat.firstAspect.block.height = 1;
|
||||||
AddFormat(internalFormat);
|
AddFormat(internalFormat);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -230,9 +194,9 @@ namespace dawn_native {
|
||||||
internalFormat.supportsStorageUsage = false;
|
internalFormat.supportsStorageUsage = false;
|
||||||
internalFormat.aspects = Aspect::Color;
|
internalFormat.aspects = Aspect::Color;
|
||||||
internalFormat.type = Type::Float;
|
internalFormat.type = Type::Float;
|
||||||
internalFormat.blockInfo.blockByteSize = byteSize;
|
internalFormat.firstAspect.block.byteSize = byteSize;
|
||||||
internalFormat.blockInfo.blockWidth = width;
|
internalFormat.firstAspect.block.width = width;
|
||||||
internalFormat.blockInfo.blockHeight = height;
|
internalFormat.firstAspect.block.height = height;
|
||||||
AddFormat(internalFormat);
|
AddFormat(internalFormat);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,8 @@
|
||||||
#include "dawn_native/dawn_platform.h"
|
#include "dawn_native/dawn_platform.h"
|
||||||
|
|
||||||
#include "common/ityp_bitset.h"
|
#include "common/ityp_bitset.h"
|
||||||
#include "dawn_native/Error.h"
|
|
||||||
|
|
||||||
#include "dawn_native/EnumClassBitmasks.h"
|
#include "dawn_native/EnumClassBitmasks.h"
|
||||||
|
#include "dawn_native/Error.h"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
|
@ -30,9 +29,13 @@ namespace dawn_native {
|
||||||
class DeviceBase;
|
class DeviceBase;
|
||||||
|
|
||||||
struct TexelBlockInfo {
|
struct TexelBlockInfo {
|
||||||
uint32_t blockByteSize;
|
uint32_t byteSize;
|
||||||
uint32_t blockWidth;
|
uint32_t width;
|
||||||
uint32_t blockHeight;
|
uint32_t height;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AspectInfo {
|
||||||
|
TexelBlockInfo block;
|
||||||
};
|
};
|
||||||
|
|
||||||
// The number of formats Dawn knows about. Asserts in BuildFormatTable ensure that this is the
|
// The number of formats Dawn knows about. Asserts in BuildFormatTable ensure that this is the
|
||||||
|
@ -69,15 +72,17 @@ namespace dawn_native {
|
||||||
bool HasDepthOrStencil() const;
|
bool HasDepthOrStencil() const;
|
||||||
bool HasComponentType(Type componentType) const;
|
bool HasComponentType(Type componentType) const;
|
||||||
|
|
||||||
TexelBlockInfo GetTexelBlockInfo(wgpu::TextureAspect aspect) const;
|
const AspectInfo& GetAspectInfo(wgpu::TextureAspect aspect) const;
|
||||||
TexelBlockInfo GetTexelBlockInfo(Aspect aspect) const;
|
const AspectInfo& GetAspectInfo(Aspect aspect) const;
|
||||||
|
|
||||||
// The index of the format in the list of all known formats: a unique number for each format
|
// The index of the format in the list of all known formats: a unique number for each format
|
||||||
// in [0, kKnownFormatCount)
|
// in [0, kKnownFormatCount)
|
||||||
size_t GetIndex() const;
|
size_t GetIndex() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TexelBlockInfo blockInfo;
|
// The most common aspect: the color aspect for color texture, the depth aspect for
|
||||||
|
// depth[-stencil] textures.
|
||||||
|
AspectInfo firstAspect;
|
||||||
|
|
||||||
friend FormatTable BuildFormatTable(const DeviceBase* device);
|
friend FormatTable BuildFormatTable(const DeviceBase* device);
|
||||||
};
|
};
|
||||||
|
|
|
@ -88,11 +88,11 @@ namespace dawn_native {
|
||||||
uint64_t optimalOffsetAlignment =
|
uint64_t optimalOffsetAlignment =
|
||||||
device->GetOptimalBufferToTextureCopyOffsetAlignment();
|
device->GetOptimalBufferToTextureCopyOffsetAlignment();
|
||||||
ASSERT(IsPowerOfTwo(optimalOffsetAlignment));
|
ASSERT(IsPowerOfTwo(optimalOffsetAlignment));
|
||||||
ASSERT(IsPowerOfTwo(blockInfo.blockByteSize));
|
ASSERT(IsPowerOfTwo(blockInfo.byteSize));
|
||||||
// We need the offset to be aligned to both optimalOffsetAlignment and 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.
|
// since both of them are powers of two, we only need to align to the max value.
|
||||||
uint64_t offsetAlignment =
|
uint64_t offsetAlignment =
|
||||||
std::max(optimalOffsetAlignment, uint64_t(blockInfo.blockByteSize));
|
std::max(optimalOffsetAlignment, uint64_t(blockInfo.byteSize));
|
||||||
|
|
||||||
UploadHandle uploadHandle;
|
UploadHandle uploadHandle;
|
||||||
DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
|
DAWN_TRY_ASSIGN(uploadHandle, device->GetDynamicUploader()->Allocate(
|
||||||
|
@ -106,7 +106,7 @@ namespace dawn_native {
|
||||||
|
|
||||||
uint32_t dataRowsPerImage = dataLayout.rowsPerImage;
|
uint32_t dataRowsPerImage = dataLayout.rowsPerImage;
|
||||||
if (dataRowsPerImage == 0) {
|
if (dataRowsPerImage == 0) {
|
||||||
dataRowsPerImage = writeSizePixel.height / blockInfo.blockHeight;
|
dataRowsPerImage = writeSizePixel.height / blockInfo.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(dataRowsPerImage >= alignedRowsPerImage);
|
ASSERT(dataRowsPerImage >= alignedRowsPerImage);
|
||||||
|
@ -266,16 +266,15 @@ namespace dawn_native {
|
||||||
const TextureDataLayout& dataLayout,
|
const TextureDataLayout& dataLayout,
|
||||||
const Extent3D& writeSizePixel) {
|
const Extent3D& writeSizePixel) {
|
||||||
const TexelBlockInfo& blockInfo =
|
const TexelBlockInfo& blockInfo =
|
||||||
destination.texture->GetFormat().GetTexelBlockInfo(destination.aspect);
|
destination.texture->GetFormat().GetAspectInfo(destination.aspect).block;
|
||||||
|
|
||||||
// We are only copying the part of the data that will appear in the texture.
|
// We are only copying the part of the data that will appear in the texture.
|
||||||
// Note that validating texture copy range ensures that writeSizePixel->width and
|
// Note that validating texture copy range ensures that writeSizePixel->width and
|
||||||
// writeSizePixel->height are multiples of blockWidth and blockHeight respectively.
|
// writeSizePixel->height are multiples of blockWidth and blockHeight respectively.
|
||||||
ASSERT(writeSizePixel.width % blockInfo.blockWidth == 0);
|
ASSERT(writeSizePixel.width % blockInfo.width == 0);
|
||||||
ASSERT(writeSizePixel.height % blockInfo.blockHeight == 0);
|
ASSERT(writeSizePixel.height % blockInfo.height == 0);
|
||||||
uint32_t alignedBytesPerRow =
|
uint32_t alignedBytesPerRow = writeSizePixel.width / blockInfo.width * blockInfo.byteSize;
|
||||||
writeSizePixel.width / blockInfo.blockWidth * blockInfo.blockByteSize;
|
uint32_t alignedRowsPerImage = writeSizePixel.height / blockInfo.height;
|
||||||
uint32_t alignedRowsPerImage = writeSizePixel.height / blockInfo.blockHeight;
|
|
||||||
|
|
||||||
uint32_t optimalBytesPerRowAlignment = GetDevice()->GetOptimalBytesPerRowAlignment();
|
uint32_t optimalBytesPerRowAlignment = GetDevice()->GetOptimalBytesPerRowAlignment();
|
||||||
uint32_t optimallyAlignedBytesPerRow =
|
uint32_t optimallyAlignedBytesPerRow =
|
||||||
|
@ -418,7 +417,8 @@ namespace dawn_native {
|
||||||
DAWN_TRY(ValidateTextureCopyRange(*destination, *writeSize));
|
DAWN_TRY(ValidateTextureCopyRange(*destination, *writeSize));
|
||||||
DAWN_TRY(ValidateLinearTextureData(
|
DAWN_TRY(ValidateLinearTextureData(
|
||||||
*dataLayout, dataSize,
|
*dataLayout, dataSize,
|
||||||
destination->texture->GetFormat().GetTexelBlockInfo(destination->aspect), *writeSize));
|
destination->texture->GetFormat().GetAspectInfo(destination->aspect).block,
|
||||||
|
*writeSize));
|
||||||
|
|
||||||
DAWN_TRY(destination->texture->ValidateCanUseInSubmitNow());
|
DAWN_TRY(destination->texture->ValidateCanUseInSubmitNow());
|
||||||
|
|
||||||
|
|
|
@ -165,12 +165,15 @@ namespace dawn_native {
|
||||||
return DAWN_VALIDATION_ERROR("Texture has too many mip levels");
|
return DAWN_VALIDATION_ERROR("Texture has too many mip levels");
|
||||||
}
|
}
|
||||||
|
|
||||||
const TexelBlockInfo& blockInfo = format->GetTexelBlockInfo(wgpu::TextureAspect::All);
|
if (format->isCompressed) {
|
||||||
if (format->isCompressed && (descriptor->size.width % blockInfo.blockWidth != 0 ||
|
const TexelBlockInfo& blockInfo =
|
||||||
descriptor->size.height % blockInfo.blockHeight != 0)) {
|
format->GetAspectInfo(wgpu::TextureAspect::All).block;
|
||||||
|
if (descriptor->size.width % blockInfo.width != 0 ||
|
||||||
|
descriptor->size.height % blockInfo.height != 0) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"The size of the texture is incompatible with the texture format");
|
"The size of the texture is incompatible with the texture format");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (descriptor->dimension == wgpu::TextureDimension::e2D &&
|
if (descriptor->dimension == wgpu::TextureDimension::e2D &&
|
||||||
descriptor->size.depth > kMaxTexture2DArrayLayers) {
|
descriptor->size.depth > kMaxTexture2DArrayLayers) {
|
||||||
|
@ -558,11 +561,10 @@ namespace dawn_native {
|
||||||
// 4 at non-zero mipmap levels.
|
// 4 at non-zero mipmap levels.
|
||||||
if (mFormat.isCompressed) {
|
if (mFormat.isCompressed) {
|
||||||
// TODO(jiawei.shao@intel.com): check if there are any overflows.
|
// TODO(jiawei.shao@intel.com): check if there are any overflows.
|
||||||
const TexelBlockInfo& blockInfo = mFormat.GetTexelBlockInfo(wgpu::TextureAspect::All);
|
const TexelBlockInfo& blockInfo = mFormat.GetAspectInfo(wgpu::TextureAspect::All).block;
|
||||||
uint32_t blockWidth = blockInfo.blockWidth;
|
extent.width = (extent.width + blockInfo.width - 1) / blockInfo.width * blockInfo.width;
|
||||||
uint32_t blockHeight = blockInfo.blockHeight;
|
extent.height =
|
||||||
extent.width = (extent.width + blockWidth - 1) / blockWidth * blockWidth;
|
(extent.height + blockInfo.height - 1) / blockInfo.height * blockInfo.height;
|
||||||
extent.height = (extent.height + blockHeight - 1) / blockHeight * blockHeight;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return extent;
|
return extent;
|
||||||
|
|
|
@ -770,7 +770,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
buffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopyDst);
|
buffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopyDst);
|
||||||
|
|
||||||
const TexelBlockInfo& blockInfo =
|
const TexelBlockInfo& blockInfo =
|
||||||
texture->GetFormat().GetTexelBlockInfo(copy->source.aspect);
|
texture->GetFormat().GetAspectInfo(copy->source.aspect).block;
|
||||||
|
|
||||||
// See comments around ComputeTextureCopySplits() for more details.
|
// See comments around ComputeTextureCopySplits() for more details.
|
||||||
const TextureCopySplits copySplits = ComputeTextureCopySplits(
|
const TextureCopySplits copySplits = ComputeTextureCopySplits(
|
||||||
|
|
|
@ -32,8 +32,8 @@ namespace dawn_native { namespace d3d12 {
|
||||||
uint32_t byteOffsetY = offset % slicePitch;
|
uint32_t byteOffsetY = offset % slicePitch;
|
||||||
uint32_t byteOffsetZ = offset - byteOffsetY;
|
uint32_t byteOffsetZ = offset - byteOffsetY;
|
||||||
|
|
||||||
return {byteOffsetX / blockInfo.blockByteSize * blockInfo.blockWidth,
|
return {byteOffsetX / blockInfo.byteSize * blockInfo.width,
|
||||||
byteOffsetY / bytesPerRow * blockInfo.blockHeight, byteOffsetZ / slicePitch};
|
byteOffsetY / bytesPerRow * blockInfo.height, byteOffsetZ / slicePitch};
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
uint32_t rowsPerImage) {
|
uint32_t rowsPerImage) {
|
||||||
Texture2DCopySplit copy;
|
Texture2DCopySplit copy;
|
||||||
|
|
||||||
ASSERT(bytesPerRow % blockInfo.blockByteSize == 0);
|
ASSERT(bytesPerRow % blockInfo.byteSize == 0);
|
||||||
|
|
||||||
uint64_t alignedOffset =
|
uint64_t alignedOffset =
|
||||||
offset & ~static_cast<uint64_t>(D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT - 1);
|
offset & ~static_cast<uint64_t>(D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT - 1);
|
||||||
|
@ -75,11 +75,9 @@ namespace dawn_native { namespace d3d12 {
|
||||||
Origin3D texelOffset = ComputeTexelOffsets(
|
Origin3D texelOffset = ComputeTexelOffsets(
|
||||||
blockInfo, static_cast<uint32_t>(offset - alignedOffset), bytesPerRow, slicePitch);
|
blockInfo, static_cast<uint32_t>(offset - alignedOffset), bytesPerRow, slicePitch);
|
||||||
|
|
||||||
uint32_t copyBytesPerRowPitch =
|
uint32_t copyBytesPerRowPitch = copySize.width / blockInfo.width * blockInfo.byteSize;
|
||||||
copySize.width / blockInfo.blockWidth * blockInfo.blockByteSize;
|
uint32_t byteOffsetInRowPitch = texelOffset.x / blockInfo.width * blockInfo.byteSize;
|
||||||
uint32_t byteOffsetInRowPitch =
|
uint32_t rowsPerImageInTexels = rowsPerImage * blockInfo.height;
|
||||||
texelOffset.x / blockInfo.blockWidth * blockInfo.blockByteSize;
|
|
||||||
uint32_t rowsPerImageInTexels = rowsPerImage * blockInfo.blockHeight;
|
|
||||||
if (copyBytesPerRowPitch + byteOffsetInRowPitch <= bytesPerRow) {
|
if (copyBytesPerRowPitch + byteOffsetInRowPitch <= bytesPerRow) {
|
||||||
// The region's rows fit inside the bytes per row. In this case, extend the width of the
|
// The region's rows fit inside the bytes per row. In this case, extend the width of the
|
||||||
// PlacedFootprint and copy the buffer with an offset location
|
// PlacedFootprint and copy the buffer with an offset location
|
||||||
|
@ -157,7 +155,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
copy.copies[0].textureOffset = origin;
|
copy.copies[0].textureOffset = origin;
|
||||||
|
|
||||||
ASSERT(bytesPerRow > byteOffsetInRowPitch);
|
ASSERT(bytesPerRow > byteOffsetInRowPitch);
|
||||||
uint32_t texelsPerRow = bytesPerRow / blockInfo.blockByteSize * blockInfo.blockWidth;
|
uint32_t texelsPerRow = bytesPerRow / blockInfo.byteSize * blockInfo.width;
|
||||||
copy.copies[0].copySize.width = texelsPerRow - texelOffset.x;
|
copy.copies[0].copySize.width = texelsPerRow - texelOffset.x;
|
||||||
copy.copies[0].copySize.height = copySize.height;
|
copy.copies[0].copySize.height = copySize.height;
|
||||||
copy.copies[0].copySize.depth = copySize.depth;
|
copy.copies[0].copySize.depth = copySize.depth;
|
||||||
|
@ -177,11 +175,10 @@ namespace dawn_native { namespace d3d12 {
|
||||||
copy.copies[1].copySize.depth = copySize.depth;
|
copy.copies[1].copySize.depth = copySize.depth;
|
||||||
|
|
||||||
copy.copies[1].bufferOffset.x = 0;
|
copy.copies[1].bufferOffset.x = 0;
|
||||||
copy.copies[1].bufferOffset.y = texelOffset.y + blockInfo.blockHeight;
|
copy.copies[1].bufferOffset.y = texelOffset.y + blockInfo.height;
|
||||||
copy.copies[1].bufferOffset.z = texelOffset.z;
|
copy.copies[1].bufferOffset.z = texelOffset.z;
|
||||||
copy.copies[1].bufferSize.width = copy.copies[1].copySize.width;
|
copy.copies[1].bufferSize.width = copy.copies[1].copySize.width;
|
||||||
copy.copies[1].bufferSize.height =
|
copy.copies[1].bufferSize.height = rowsPerImageInTexels + texelOffset.y + blockInfo.height;
|
||||||
rowsPerImageInTexels + texelOffset.y + blockInfo.blockHeight;
|
|
||||||
copy.copies[1].bufferSize.depth = copySize.depth + texelOffset.z;
|
copy.copies[1].bufferSize.depth = copySize.depth + texelOffset.z;
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
|
|
|
@ -947,12 +947,11 @@ namespace dawn_native { namespace d3d12 {
|
||||||
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_COPY_DEST, range);
|
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_COPY_DEST, range);
|
||||||
|
|
||||||
for (Aspect aspect : IterateEnumMask(range.aspects)) {
|
for (Aspect aspect : IterateEnumMask(range.aspects)) {
|
||||||
const TexelBlockInfo& blockInfo = GetFormat().GetTexelBlockInfo(aspect);
|
const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(aspect).block;
|
||||||
|
|
||||||
uint32_t bytesPerRow =
|
uint32_t bytesPerRow = Align((GetWidth() / blockInfo.width) * blockInfo.byteSize,
|
||||||
Align((GetWidth() / blockInfo.blockWidth) * blockInfo.blockByteSize,
|
|
||||||
kTextureBytesPerRowAlignment);
|
kTextureBytesPerRowAlignment);
|
||||||
uint64_t bufferSize64 = bytesPerRow * (GetHeight() / blockInfo.blockHeight);
|
uint64_t bufferSize64 = bytesPerRow * (GetHeight() / blockInfo.height);
|
||||||
if (bufferSize64 > std::numeric_limits<uint32_t>::max()) {
|
if (bufferSize64 > std::numeric_limits<uint32_t>::max()) {
|
||||||
return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
|
return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
|
||||||
}
|
}
|
||||||
|
@ -962,7 +961,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
UploadHandle uploadHandle;
|
UploadHandle uploadHandle;
|
||||||
DAWN_TRY_ASSIGN(uploadHandle,
|
DAWN_TRY_ASSIGN(uploadHandle,
|
||||||
uploader->Allocate(bufferSize, device->GetPendingCommandSerial(),
|
uploader->Allocate(bufferSize, device->GetPendingCommandSerial(),
|
||||||
blockInfo.blockByteSize));
|
blockInfo.byteSize));
|
||||||
memset(uploadHandle.mappedBuffer, clearColor, bufferSize);
|
memset(uploadHandle.mappedBuffer, clearColor, bufferSize);
|
||||||
|
|
||||||
for (uint32_t level = range.baseMipLevel;
|
for (uint32_t level = range.baseMipLevel;
|
||||||
|
@ -970,7 +969,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
// compute d3d12 texture copy locations for texture and buffer
|
// compute d3d12 texture copy locations for texture and buffer
|
||||||
Extent3D copySize = GetMipLevelVirtualSize(level);
|
Extent3D copySize = GetMipLevelVirtualSize(level);
|
||||||
|
|
||||||
uint32_t rowsPerImage = GetHeight() / blockInfo.blockHeight;
|
uint32_t rowsPerImage = GetHeight() / blockInfo.height;
|
||||||
Texture2DCopySplit copySplit = ComputeTextureCopySplit(
|
Texture2DCopySplit copySplit = ComputeTextureCopySplit(
|
||||||
{0, 0, 0}, copySize, blockInfo, uploadHandle.startOffset, bytesPerRow,
|
{0, 0, 0}, copySize, blockInfo, uploadHandle.startOffset, bytesPerRow,
|
||||||
rowsPerImage);
|
rowsPerImage);
|
||||||
|
|
|
@ -185,7 +185,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
Aspect aspect) {
|
Aspect aspect) {
|
||||||
ASSERT(HasOneBit(aspect));
|
ASSERT(HasOneBit(aspect));
|
||||||
// See comments in ComputeTextureCopySplits() for more details.
|
// See comments in ComputeTextureCopySplits() for more details.
|
||||||
const TexelBlockInfo& blockInfo = texture->GetFormat().GetTexelBlockInfo(aspect);
|
const TexelBlockInfo& blockInfo = texture->GetFormat().GetAspectInfo(aspect).block;
|
||||||
const TextureCopySplits copySplits = ComputeTextureCopySplits(
|
const TextureCopySplits copySplits = ComputeTextureCopySplits(
|
||||||
textureCopy.origin, copySize, blockInfo, offsetBytes, bytesPerRow, rowsPerImage);
|
textureCopy.origin, copySize, blockInfo, offsetBytes, bytesPerRow, rowsPerImage);
|
||||||
|
|
||||||
|
|
|
@ -297,12 +297,10 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
// This function assumes data is perfectly aligned. Otherwise, it might be necessary
|
// This function assumes data is perfectly aligned. Otherwise, it might be necessary
|
||||||
// to split copying to several stages: see ComputeTextureBufferCopySplit.
|
// to split copying to several stages: see ComputeTextureBufferCopySplit.
|
||||||
const TexelBlockInfo& blockInfo = texture->GetFormat().GetTexelBlockInfo(dst->aspect);
|
const TexelBlockInfo& blockInfo = texture->GetFormat().GetAspectInfo(dst->aspect).block;
|
||||||
uint32_t blockSize = blockInfo.blockByteSize;
|
ASSERT(dataLayout.rowsPerImage == copySizePixels.height / blockInfo.height);
|
||||||
uint32_t blockWidth = blockInfo.blockWidth;
|
ASSERT(dataLayout.bytesPerRow ==
|
||||||
uint32_t blockHeight = blockInfo.blockHeight;
|
copySizePixels.width / blockInfo.width * blockInfo.byteSize);
|
||||||
ASSERT(dataLayout.rowsPerImage == copySizePixels.height / blockHeight);
|
|
||||||
ASSERT(dataLayout.bytesPerRow == copySizePixels.width / blockWidth * blockSize);
|
|
||||||
|
|
||||||
EnsureDestinationTextureInitialized(texture, *dst, copySizePixels);
|
EnsureDestinationTextureInitialized(texture, *dst, copySizePixels);
|
||||||
|
|
||||||
|
|
|
@ -491,16 +491,16 @@ namespace dawn_native { namespace metal {
|
||||||
// Compute the buffer size big enough to fill the largest mip.
|
// Compute the buffer size big enough to fill the largest mip.
|
||||||
Extent3D largestMipSize = GetMipLevelVirtualSize(range.baseMipLevel);
|
Extent3D largestMipSize = GetMipLevelVirtualSize(range.baseMipLevel);
|
||||||
const TexelBlockInfo& blockInfo =
|
const TexelBlockInfo& blockInfo =
|
||||||
GetFormat().GetTexelBlockInfo(wgpu::TextureAspect::All);
|
GetFormat().GetAspectInfo(wgpu::TextureAspect::All).block;
|
||||||
|
|
||||||
// Metal validation layers: sourceBytesPerRow must be at least 64.
|
// Metal validation layers: sourceBytesPerRow must be at least 64.
|
||||||
uint32_t largestMipBytesPerRow = std::max(
|
uint32_t largestMipBytesPerRow =
|
||||||
(largestMipSize.width / blockInfo.blockWidth) * blockInfo.blockByteSize, 64u);
|
std::max((largestMipSize.width / blockInfo.width) * blockInfo.byteSize, 64u);
|
||||||
|
|
||||||
// Metal validation layers: sourceBytesPerImage must be at least 512.
|
// Metal validation layers: sourceBytesPerImage must be at least 512.
|
||||||
uint64_t largestMipBytesPerImage =
|
uint64_t largestMipBytesPerImage =
|
||||||
std::max(static_cast<uint64_t>(largestMipBytesPerRow) *
|
std::max(static_cast<uint64_t>(largestMipBytesPerRow) *
|
||||||
(largestMipSize.height / blockInfo.blockHeight),
|
(largestMipSize.height / blockInfo.height),
|
||||||
512llu);
|
512llu);
|
||||||
|
|
||||||
// TODO(enga): Multiply by largestMipSize.depth and do a larger 3D copy to clear a whole
|
// TODO(enga): Multiply by largestMipSize.depth and do a larger 3D copy to clear a whole
|
||||||
|
@ -515,7 +515,7 @@ namespace dawn_native { namespace metal {
|
||||||
UploadHandle uploadHandle;
|
UploadHandle uploadHandle;
|
||||||
DAWN_TRY_ASSIGN(uploadHandle,
|
DAWN_TRY_ASSIGN(uploadHandle,
|
||||||
uploader->Allocate(bufferSize, device->GetPendingCommandSerial(),
|
uploader->Allocate(bufferSize, device->GetPendingCommandSerial(),
|
||||||
blockInfo.blockByteSize));
|
blockInfo.byteSize));
|
||||||
memset(uploadHandle.mappedBuffer, clearColor, bufferSize);
|
memset(uploadHandle.mappedBuffer, clearColor, bufferSize);
|
||||||
|
|
||||||
id<MTLBlitCommandEncoder> encoder = commandContext->EnsureBlit();
|
id<MTLBlitCommandEncoder> encoder = commandContext->EnsureBlit();
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace dawn_native { namespace metal {
|
||||||
Aspect aspect) {
|
Aspect aspect) {
|
||||||
TextureBufferCopySplit copy;
|
TextureBufferCopySplit copy;
|
||||||
const Format textureFormat = texture->GetFormat();
|
const Format textureFormat = texture->GetFormat();
|
||||||
const TexelBlockInfo& blockInfo = textureFormat.GetTexelBlockInfo(aspect);
|
const TexelBlockInfo& blockInfo = textureFormat.GetAspectInfo(aspect).block;
|
||||||
|
|
||||||
// When copying textures from/to an unpacked buffer, the Metal validation layer doesn't
|
// When copying textures from/to an unpacked buffer, the Metal validation layer doesn't
|
||||||
// compute the correct range when checking if the buffer is big enough to contain the
|
// compute the correct range when checking if the buffer is big enough to contain the
|
||||||
|
@ -115,7 +115,7 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Doing all the copy in last image except the last row.
|
// Doing all the copy in last image except the last row.
|
||||||
uint32_t copyBlockRowCount = copyExtent.height / blockInfo.blockHeight;
|
uint32_t copyBlockRowCount = copyExtent.height / blockInfo.height;
|
||||||
if (copyBlockRowCount > 1) {
|
if (copyBlockRowCount > 1) {
|
||||||
copy.copies[copy.count].bufferOffset = currentOffset;
|
copy.copies[copy.count].bufferOffset = currentOffset;
|
||||||
copy.copies[copy.count].bytesPerRow = bytesPerRow;
|
copy.copies[copy.count].bytesPerRow = bytesPerRow;
|
||||||
|
@ -123,10 +123,10 @@ namespace dawn_native { namespace metal {
|
||||||
copy.copies[copy.count].textureOrigin = {origin.x, origin.y,
|
copy.copies[copy.count].textureOrigin = {origin.x, origin.y,
|
||||||
origin.z + copyExtent.depth - 1};
|
origin.z + copyExtent.depth - 1};
|
||||||
|
|
||||||
ASSERT(copyExtent.height - blockInfo.blockHeight <
|
ASSERT(copyExtent.height - blockInfo.height <
|
||||||
texture->GetMipLevelVirtualSize(mipLevel).height);
|
texture->GetMipLevelVirtualSize(mipLevel).height);
|
||||||
copy.copies[copy.count].copyExtent = {clampedCopyExtent.width,
|
copy.copies[copy.count].copyExtent = {clampedCopyExtent.width,
|
||||||
copyExtent.height - blockInfo.blockHeight, 1};
|
copyExtent.height - blockInfo.height, 1};
|
||||||
|
|
||||||
++copy.count;
|
++copy.count;
|
||||||
|
|
||||||
|
@ -136,17 +136,16 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
// Doing the last row copy with the exact number of bytes in last row.
|
// Doing the last row copy with the exact number of bytes in last row.
|
||||||
// Workaround this issue in a way just like the copy to a 1D texture.
|
// Workaround this issue in a way just like the copy to a 1D texture.
|
||||||
uint32_t lastRowDataSize =
|
uint32_t lastRowDataSize = (copyExtent.width / blockInfo.width) * blockInfo.byteSize;
|
||||||
(copyExtent.width / blockInfo.blockWidth) * blockInfo.blockByteSize;
|
|
||||||
uint32_t lastRowCopyExtentHeight =
|
uint32_t lastRowCopyExtentHeight =
|
||||||
blockInfo.blockHeight + clampedCopyExtent.height - copyExtent.height;
|
blockInfo.height + clampedCopyExtent.height - copyExtent.height;
|
||||||
ASSERT(lastRowCopyExtentHeight <= blockInfo.blockHeight);
|
ASSERT(lastRowCopyExtentHeight <= blockInfo.height);
|
||||||
|
|
||||||
copy.copies[copy.count].bufferOffset = currentOffset;
|
copy.copies[copy.count].bufferOffset = currentOffset;
|
||||||
copy.copies[copy.count].bytesPerRow = lastRowDataSize;
|
copy.copies[copy.count].bytesPerRow = lastRowDataSize;
|
||||||
copy.copies[copy.count].bytesPerImage = lastRowDataSize;
|
copy.copies[copy.count].bytesPerImage = lastRowDataSize;
|
||||||
copy.copies[copy.count].textureOrigin = {
|
copy.copies[copy.count].textureOrigin = {origin.x,
|
||||||
origin.x, origin.y + copyExtent.height - blockInfo.blockHeight,
|
origin.y + copyExtent.height - blockInfo.height,
|
||||||
origin.z + copyExtent.depth - 1};
|
origin.z + copyExtent.depth - 1};
|
||||||
copy.copies[copy.count].copyExtent = {clampedCopyExtent.width, lastRowCopyExtentHeight, 1};
|
copy.copies[copy.count].copyExtent = {clampedCopyExtent.width, lastRowCopyExtentHeight, 1};
|
||||||
++copy.count;
|
++copy.count;
|
||||||
|
|
|
@ -531,22 +531,21 @@ namespace dawn_native { namespace opengl {
|
||||||
gl.BindTexture(target, texture->GetHandle());
|
gl.BindTexture(target, texture->GetHandle());
|
||||||
|
|
||||||
const Format& formatInfo = texture->GetFormat();
|
const Format& formatInfo = texture->GetFormat();
|
||||||
const TexelBlockInfo& blockInfo = formatInfo.GetTexelBlockInfo(dst.aspect);
|
const TexelBlockInfo& blockInfo = formatInfo.GetAspectInfo(dst.aspect).block;
|
||||||
gl.PixelStorei(GL_UNPACK_ROW_LENGTH, src.bytesPerRow / blockInfo.blockByteSize *
|
gl.PixelStorei(GL_UNPACK_ROW_LENGTH,
|
||||||
blockInfo.blockWidth);
|
src.bytesPerRow / blockInfo.byteSize * blockInfo.width);
|
||||||
gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT,
|
gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, src.rowsPerImage * blockInfo.height);
|
||||||
src.rowsPerImage * blockInfo.blockHeight);
|
|
||||||
|
|
||||||
if (formatInfo.isCompressed) {
|
if (formatInfo.isCompressed) {
|
||||||
gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_SIZE, blockInfo.blockByteSize);
|
gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_SIZE, blockInfo.byteSize);
|
||||||
gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH, blockInfo.blockWidth);
|
gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH, blockInfo.width);
|
||||||
gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT, blockInfo.blockHeight);
|
gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT, blockInfo.height);
|
||||||
gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_DEPTH, 1);
|
gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_DEPTH, 1);
|
||||||
|
|
||||||
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
|
ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
|
||||||
uint64_t copyDataSize = (copySize.width / blockInfo.blockWidth) *
|
uint64_t copyDataSize = (copySize.width / blockInfo.width) *
|
||||||
(copySize.height / blockInfo.blockHeight) *
|
(copySize.height / blockInfo.height) *
|
||||||
blockInfo.blockByteSize * copySize.depth;
|
blockInfo.byteSize * copySize.depth;
|
||||||
Extent3D copyExtent = ComputeTextureCopyExtent(dst, copySize);
|
Extent3D copyExtent = ComputeTextureCopyExtent(dst, copySize);
|
||||||
|
|
||||||
if (texture->GetArrayLayers() > 1) {
|
if (texture->GetArrayLayers() > 1) {
|
||||||
|
@ -624,11 +623,11 @@ namespace dawn_native { namespace opengl {
|
||||||
gl.GenFramebuffers(1, &readFBO);
|
gl.GenFramebuffers(1, &readFBO);
|
||||||
gl.BindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
|
gl.BindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
|
||||||
|
|
||||||
const TexelBlockInfo& blockInfo = formatInfo.GetTexelBlockInfo(src.aspect);
|
const TexelBlockInfo& blockInfo = formatInfo.GetAspectInfo(src.aspect).block;
|
||||||
|
|
||||||
gl.BindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
|
gl.BindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
|
||||||
gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, dst.rowsPerImage * blockInfo.blockHeight);
|
gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, dst.rowsPerImage * blockInfo.height);
|
||||||
gl.PixelStorei(GL_PACK_ROW_LENGTH, dst.bytesPerRow / blockInfo.blockByteSize);
|
gl.PixelStorei(GL_PACK_ROW_LENGTH, dst.bytesPerRow / blockInfo.byteSize);
|
||||||
|
|
||||||
GLenum glAttachment;
|
GLenum glAttachment;
|
||||||
GLenum glFormat;
|
GLenum glFormat;
|
||||||
|
|
|
@ -294,8 +294,8 @@ namespace dawn_native { namespace opengl {
|
||||||
ASSERT(range.aspects == Aspect::Color);
|
ASSERT(range.aspects == Aspect::Color);
|
||||||
|
|
||||||
static constexpr uint32_t MAX_TEXEL_SIZE = 16;
|
static constexpr uint32_t MAX_TEXEL_SIZE = 16;
|
||||||
const TexelBlockInfo& blockInfo = GetFormat().GetTexelBlockInfo(Aspect::Color);
|
const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(Aspect::Color).block;
|
||||||
ASSERT(blockInfo.blockByteSize <= MAX_TEXEL_SIZE);
|
ASSERT(blockInfo.byteSize <= MAX_TEXEL_SIZE);
|
||||||
|
|
||||||
std::array<GLbyte, MAX_TEXEL_SIZE> clearColorData;
|
std::array<GLbyte, MAX_TEXEL_SIZE> clearColorData;
|
||||||
clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 255;
|
clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 255;
|
||||||
|
@ -324,20 +324,19 @@ namespace dawn_native { namespace opengl {
|
||||||
ASSERT(range.aspects == Aspect::Color);
|
ASSERT(range.aspects == Aspect::Color);
|
||||||
|
|
||||||
// create temp buffer with clear color to copy to the texture image
|
// create temp buffer with clear color to copy to the texture image
|
||||||
const TexelBlockInfo& blockInfo = GetFormat().GetTexelBlockInfo(Aspect::Color);
|
const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(Aspect::Color).block;
|
||||||
ASSERT(kTextureBytesPerRowAlignment % blockInfo.blockByteSize == 0);
|
ASSERT(kTextureBytesPerRowAlignment % blockInfo.byteSize == 0);
|
||||||
uint32_t bytesPerRow =
|
uint32_t bytesPerRow = Align((GetWidth() / blockInfo.width) * blockInfo.byteSize,
|
||||||
Align((GetWidth() / blockInfo.blockWidth) * blockInfo.blockByteSize,
|
|
||||||
kTextureBytesPerRowAlignment);
|
kTextureBytesPerRowAlignment);
|
||||||
|
|
||||||
// Make sure that we are not rounding
|
// Make sure that we are not rounding
|
||||||
ASSERT(bytesPerRow % blockInfo.blockByteSize == 0);
|
ASSERT(bytesPerRow % blockInfo.byteSize == 0);
|
||||||
ASSERT(GetHeight() % blockInfo.blockHeight == 0);
|
ASSERT(GetHeight() % blockInfo.height == 0);
|
||||||
|
|
||||||
dawn_native::BufferDescriptor descriptor = {};
|
dawn_native::BufferDescriptor descriptor = {};
|
||||||
descriptor.mappedAtCreation = true;
|
descriptor.mappedAtCreation = true;
|
||||||
descriptor.usage = wgpu::BufferUsage::CopySrc;
|
descriptor.usage = wgpu::BufferUsage::CopySrc;
|
||||||
descriptor.size = bytesPerRow * (GetHeight() / blockInfo.blockHeight);
|
descriptor.size = bytesPerRow * (GetHeight() / blockInfo.height);
|
||||||
if (descriptor.size > std::numeric_limits<uint32_t>::max()) {
|
if (descriptor.size > std::numeric_limits<uint32_t>::max()) {
|
||||||
return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
|
return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
|
||||||
}
|
}
|
||||||
|
@ -353,7 +352,7 @@ namespace dawn_native { namespace opengl {
|
||||||
|
|
||||||
// Bind buffer and texture, and make the buffer to texture copy
|
// Bind buffer and texture, and make the buffer to texture copy
|
||||||
gl.PixelStorei(GL_UNPACK_ROW_LENGTH,
|
gl.PixelStorei(GL_UNPACK_ROW_LENGTH,
|
||||||
(bytesPerRow / blockInfo.blockByteSize) * blockInfo.blockWidth);
|
(bytesPerRow / blockInfo.byteSize) * blockInfo.width);
|
||||||
gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
|
gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
|
||||||
for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
|
for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
|
||||||
++level) {
|
++level) {
|
||||||
|
|
|
@ -436,15 +436,15 @@ namespace dawn_native { namespace vulkan {
|
||||||
ASSERT(srcCopy.texture->GetFormat().format == dstCopy.texture->GetFormat().format);
|
ASSERT(srcCopy.texture->GetFormat().format == dstCopy.texture->GetFormat().format);
|
||||||
ASSERT(srcCopy.aspect == dstCopy.aspect);
|
ASSERT(srcCopy.aspect == dstCopy.aspect);
|
||||||
dawn_native::Format format = srcCopy.texture->GetFormat();
|
dawn_native::Format format = srcCopy.texture->GetFormat();
|
||||||
const TexelBlockInfo& blockInfo = format.GetTexelBlockInfo(srcCopy.aspect);
|
const TexelBlockInfo& blockInfo = format.GetAspectInfo(srcCopy.aspect).block;
|
||||||
ASSERT(copySize.width % blockInfo.blockWidth == 0);
|
ASSERT(copySize.width % blockInfo.width == 0);
|
||||||
uint32_t widthInBlocks = copySize.width / blockInfo.blockWidth;
|
uint32_t widthInBlocks = copySize.width / blockInfo.width;
|
||||||
ASSERT(copySize.height % blockInfo.blockHeight == 0);
|
ASSERT(copySize.height % blockInfo.height == 0);
|
||||||
uint32_t heightInBlocks = copySize.height / blockInfo.blockHeight;
|
uint32_t heightInBlocks = copySize.height / blockInfo.height;
|
||||||
|
|
||||||
// Create the temporary buffer. Note that We don't need to respect WebGPU's 256 alignment
|
// Create the temporary buffer. Note that We don't need to respect WebGPU's 256 alignment
|
||||||
// because it isn't a hard constraint in Vulkan.
|
// because it isn't a hard constraint in Vulkan.
|
||||||
uint64_t tempBufferSize = widthInBlocks * heightInBlocks * blockInfo.blockByteSize;
|
uint64_t tempBufferSize = widthInBlocks * heightInBlocks * blockInfo.byteSize;
|
||||||
BufferDescriptor tempBufferDescriptor;
|
BufferDescriptor tempBufferDescriptor;
|
||||||
tempBufferDescriptor.size = tempBufferSize;
|
tempBufferDescriptor.size = tempBufferSize;
|
||||||
tempBufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
|
tempBufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
|
||||||
|
@ -456,8 +456,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
tempBufferCopy.buffer = tempBuffer.Get();
|
tempBufferCopy.buffer = tempBuffer.Get();
|
||||||
tempBufferCopy.rowsPerImage = heightInBlocks;
|
tempBufferCopy.rowsPerImage = heightInBlocks;
|
||||||
tempBufferCopy.offset = 0;
|
tempBufferCopy.offset = 0;
|
||||||
tempBufferCopy.bytesPerRow =
|
tempBufferCopy.bytesPerRow = copySize.width / blockInfo.width * blockInfo.byteSize;
|
||||||
copySize.width / blockInfo.blockWidth * blockInfo.blockByteSize;
|
|
||||||
|
|
||||||
VkCommandBuffer commands = recordingContext->commandBuffer;
|
VkCommandBuffer commands = recordingContext->commandBuffer;
|
||||||
VkImage srcImage = ToBackend(srcCopy.texture)->GetHandle();
|
VkImage srcImage = ToBackend(srcCopy.texture)->GetHandle();
|
||||||
|
|
|
@ -108,11 +108,10 @@ namespace dawn_native { namespace vulkan {
|
||||||
region.bufferOffset = dataLayout.offset;
|
region.bufferOffset = dataLayout.offset;
|
||||||
// In Vulkan the row length is in texels while it is in bytes for Dawn
|
// In Vulkan the row length is in texels while it is in bytes for Dawn
|
||||||
const TexelBlockInfo& blockInfo =
|
const TexelBlockInfo& blockInfo =
|
||||||
texture->GetFormat().GetTexelBlockInfo(textureCopy.aspect);
|
texture->GetFormat().GetAspectInfo(textureCopy.aspect).block;
|
||||||
ASSERT(dataLayout.bytesPerRow % blockInfo.blockByteSize == 0);
|
ASSERT(dataLayout.bytesPerRow % blockInfo.byteSize == 0);
|
||||||
region.bufferRowLength =
|
region.bufferRowLength = dataLayout.bytesPerRow / blockInfo.byteSize * blockInfo.width;
|
||||||
dataLayout.bytesPerRow / blockInfo.blockByteSize * blockInfo.blockWidth;
|
region.bufferImageHeight = dataLayout.rowsPerImage * blockInfo.height;
|
||||||
region.bufferImageHeight = dataLayout.rowsPerImage * blockInfo.blockHeight;
|
|
||||||
|
|
||||||
region.imageSubresource.aspectMask = VulkanAspectMask(textureCopy.aspect);
|
region.imageSubresource.aspectMask = VulkanAspectMask(textureCopy.aspect);
|
||||||
region.imageSubresource.mipLevel = textureCopy.mipLevel;
|
region.imageSubresource.mipLevel = textureCopy.mipLevel;
|
||||||
|
|
|
@ -291,9 +291,9 @@ class CopySplitTest : public testing::Test {
|
||||||
ASSERT(textureSpec.width % textureSpec.blockWidth == 0 &&
|
ASSERT(textureSpec.width % textureSpec.blockWidth == 0 &&
|
||||||
textureSpec.height % textureSpec.blockHeight == 0);
|
textureSpec.height % textureSpec.blockHeight == 0);
|
||||||
dawn_native::TexelBlockInfo blockInfo = {};
|
dawn_native::TexelBlockInfo blockInfo = {};
|
||||||
blockInfo.blockWidth = textureSpec.blockWidth;
|
blockInfo.width = textureSpec.blockWidth;
|
||||||
blockInfo.blockHeight = textureSpec.blockHeight;
|
blockInfo.height = textureSpec.blockHeight;
|
||||||
blockInfo.blockByteSize = textureSpec.texelBlockSizeInBytes;
|
blockInfo.byteSize = textureSpec.texelBlockSizeInBytes;
|
||||||
Texture2DCopySplit copySplit = ComputeTextureCopySplit(
|
Texture2DCopySplit copySplit = ComputeTextureCopySplit(
|
||||||
{textureSpec.x, textureSpec.y, textureSpec.z},
|
{textureSpec.x, textureSpec.y, textureSpec.z},
|
||||||
{textureSpec.width, textureSpec.height, textureSpec.depth}, blockInfo,
|
{textureSpec.width, textureSpec.height, textureSpec.depth}, blockInfo,
|
||||||
|
|
Loading…
Reference in New Issue