Add internal Format structure for texture formats
Texture formats have plenty of properties we'd like to query on them like their texel size, whether they are compressend or if they are depth stencil. Instead of making switch statements for each of these properties, we store them in a new `Format` structure. Textures compute their format only onces and then pass a const reference to it on GetFormat(). This is in preparation of adding all WebGPU texture formats. BUG=dawn:128 Change-Id: Iad2831cf16f14e1a1bfce2c10b22527fc982d1aa Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/8166 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
parent
4729b15365
commit
a92f83b725
|
@ -52,10 +52,13 @@ namespace dawn_native {
|
||||||
|
|
||||||
// Compressed Textures will have paddings if their width or height is not a multiple of
|
// Compressed Textures will have paddings if their width or height is not a multiple of
|
||||||
// 4 at non-zero mipmap levels.
|
// 4 at non-zero mipmap levels.
|
||||||
if (Is4x4CompressedFormat(texture->GetFormat())) {
|
const Format& textureFormat = texture->GetFormat();
|
||||||
|
if (textureFormat.isCompressed) {
|
||||||
// TODO(jiawei.shao@intel.com): check if there are any overflows.
|
// TODO(jiawei.shao@intel.com): check if there are any overflows.
|
||||||
widthAtLevel = (widthAtLevel + 3) / 4 * 4;
|
uint32_t blockWidth = textureFormat.blockWidth;
|
||||||
heightAtLevel = (heightAtLevel + 3) / 4 * 4;
|
uint32_t blockHeight = textureFormat.blockHeight;
|
||||||
|
widthAtLevel = (widthAtLevel + blockWidth - 1) / blockWidth * blockWidth;
|
||||||
|
heightAtLevel = (heightAtLevel + blockHeight - 1) / blockHeight * blockHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uint64_t(textureCopy.origin.x) + uint64_t(copySize.width) >
|
if (uint64_t(textureCopy.origin.x) + uint64_t(copySize.width) >
|
||||||
|
@ -107,9 +110,8 @@ namespace dawn_native {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError ValidateTexelBufferOffset(TextureBase* texture, const BufferCopy& bufferCopy) {
|
MaybeError ValidateTexelBufferOffset(const BufferCopy& bufferCopy, const Format& format) {
|
||||||
uint32_t blockSize = TextureFormatTexelBlockSizeInBytes(texture->GetFormat());
|
if (bufferCopy.offset % format.blockByteSize != 0) {
|
||||||
if (bufferCopy.offset % blockSize != 0) {
|
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"Buffer offset must be a multiple of the texel or block size");
|
"Buffer offset must be a multiple of the texel or block size");
|
||||||
}
|
}
|
||||||
|
@ -187,10 +189,12 @@ namespace dawn_native {
|
||||||
DAWN_TRY(ValidateEntireSubresourceCopied(src, dst, copySize));
|
DAWN_TRY(ValidateEntireSubresourceCopied(src, dst, copySize));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src.texture.Get()->GetFormat() != dst.texture.Get()->GetFormat()) {
|
if (src.texture.Get()->GetFormat().format != dst.texture.Get()->GetFormat().format) {
|
||||||
// Metal requires texture-to-texture copies be the same format
|
// Metal requires texture-to-texture copies be the same format
|
||||||
return DAWN_VALIDATION_ERROR("Source and destination texture formats must match.");
|
return DAWN_VALIDATION_ERROR("Source and destination texture formats must match.");
|
||||||
} else if (TextureFormatHasDepthOrStencil(src.texture.Get()->GetFormat())) {
|
}
|
||||||
|
|
||||||
|
if (src.texture.Get()->GetFormat().HasDepthOrStencil()) {
|
||||||
// D3D12 requires entire subresource to be copied when using CopyTextureRegion is
|
// D3D12 requires entire subresource to be copied when using CopyTextureRegion is
|
||||||
// used with depth/stencil.
|
// used with depth/stencil.
|
||||||
DAWN_TRY(ValidateEntireSubresourceCopied(src, dst, copySize));
|
DAWN_TRY(ValidateEntireSubresourceCopied(src, dst, copySize));
|
||||||
|
@ -199,43 +203,38 @@ namespace dawn_native {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError ComputeTextureCopyBufferSize(dawn::TextureFormat textureFormat,
|
MaybeError ComputeTextureCopyBufferSize(const Format& textureFormat,
|
||||||
const Extent3D& copySize,
|
const Extent3D& copySize,
|
||||||
uint32_t rowPitch,
|
uint32_t rowPitch,
|
||||||
uint32_t imageHeight,
|
uint32_t imageHeight,
|
||||||
uint32_t* bufferSize) {
|
uint32_t* bufferSize) {
|
||||||
DAWN_TRY(ValidateImageHeight(imageHeight, copySize.height));
|
DAWN_TRY(ValidateImageHeight(imageHeight, copySize.height));
|
||||||
|
|
||||||
uint32_t texelOrBlockSizeInBytes = TextureFormatTexelBlockSizeInBytes(textureFormat);
|
uint32_t blockByteSize = textureFormat.blockByteSize;
|
||||||
uint32_t blockWidthInTexels = TextureFormatBlockWidthInTexels(textureFormat);
|
uint32_t blockWidth = textureFormat.blockWidth;
|
||||||
uint32_t blockHeightInTexels = TextureFormatBlockWidthInTexels(textureFormat);
|
uint32_t blockHeight = textureFormat.blockHeight;
|
||||||
|
|
||||||
// TODO(cwallez@chromium.org): check for overflows
|
// TODO(cwallez@chromium.org): check for overflows
|
||||||
uint32_t slicePitch = rowPitch * imageHeight / blockWidthInTexels;
|
uint32_t slicePitch = rowPitch * imageHeight / blockWidth;
|
||||||
uint32_t sliceSize = rowPitch * (copySize.height / blockHeightInTexels - 1) +
|
uint32_t sliceSize = rowPitch * (copySize.height / blockHeight - 1) +
|
||||||
(copySize.width / blockWidthInTexels) * texelOrBlockSizeInBytes;
|
(copySize.width / blockWidth) * blockByteSize;
|
||||||
*bufferSize = (slicePitch * (copySize.depth - 1)) + sliceSize;
|
*bufferSize = (slicePitch * (copySize.depth - 1)) + sliceSize;
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ComputeDefaultRowPitch(TextureBase* texture, uint32_t width) {
|
uint32_t ComputeDefaultRowPitch(const Format& format, uint32_t width) {
|
||||||
const dawn::TextureFormat format = texture->GetFormat();
|
return width / format.blockWidth * format.blockByteSize;
|
||||||
uint32_t texelOrBlockSizeInBytes = TextureFormatTexelBlockSizeInBytes(format);
|
|
||||||
uint32_t blockWidthInTexels = TextureFormatBlockWidthInTexels(format);
|
|
||||||
return width / blockWidthInTexels * texelOrBlockSizeInBytes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError ValidateRowPitch(dawn::TextureFormat format,
|
MaybeError ValidateRowPitch(const Format& format,
|
||||||
const Extent3D& copySize,
|
const Extent3D& copySize,
|
||||||
uint32_t rowPitch) {
|
uint32_t rowPitch) {
|
||||||
if (rowPitch % kTextureRowPitchAlignment != 0) {
|
if (rowPitch % kTextureRowPitchAlignment != 0) {
|
||||||
return DAWN_VALIDATION_ERROR("Row pitch must be a multiple of 256");
|
return DAWN_VALIDATION_ERROR("Row pitch must be a multiple of 256");
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t texelOrBlockSizeInBytes = TextureFormatTexelBlockSizeInBytes(format);
|
if (rowPitch < copySize.width / format.blockWidth * format.blockByteSize) {
|
||||||
uint32_t blockWidthInTexels = TextureFormatBlockWidthInTexels(format);
|
|
||||||
if (rowPitch < copySize.width / blockWidthInTexels * texelOrBlockSizeInBytes) {
|
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"Row pitch must not be less than the number of bytes per row");
|
"Row pitch must not be less than the number of bytes per row");
|
||||||
}
|
}
|
||||||
|
@ -243,8 +242,8 @@ namespace dawn_native {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError ValidateImageHeight(dawn::TextureFormat format, uint32_t imageHeight) {
|
MaybeError ValidateImageHeight(const Format& format, uint32_t imageHeight) {
|
||||||
if (imageHeight % TextureFormatBlockHeightInTexels(format) != 0) {
|
if (imageHeight % format.blockHeight != 0) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"Image height must be a multiple of compressed texture format block width");
|
"Image height must be a multiple of compressed texture format block width");
|
||||||
}
|
}
|
||||||
|
@ -252,13 +251,13 @@ namespace dawn_native {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError ValidateImageOrigin(dawn::TextureFormat format, const Origin3D& offset) {
|
MaybeError ValidateImageOrigin(const Format& format, const Origin3D& offset) {
|
||||||
if (offset.x % TextureFormatBlockWidthInTexels(format) != 0) {
|
if (offset.x % format.blockWidth != 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 (offset.y % TextureFormatBlockHeightInTexels(format) != 0) {
|
if (offset.y % format.blockHeight != 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");
|
||||||
}
|
}
|
||||||
|
@ -266,13 +265,13 @@ namespace dawn_native {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError ValidateImageCopySize(dawn::TextureFormat format, const Extent3D& extent) {
|
MaybeError ValidateImageCopySize(const Format& format, const Extent3D& extent) {
|
||||||
if (extent.width % TextureFormatBlockWidthInTexels(format) != 0) {
|
if (extent.width % format.blockWidth != 0) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"Extent.width must be a multiple of compressed texture format block width");
|
"Extent.width must be a multiple of compressed texture format block width");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extent.height % TextureFormatBlockHeightInTexels(format) != 0) {
|
if (extent.height % format.blockHeight != 0) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"Extent.height must be a multiple of compressed texture format block height");
|
"Extent.height must be a multiple of compressed texture format block height");
|
||||||
}
|
}
|
||||||
|
@ -389,8 +388,9 @@ namespace dawn_native {
|
||||||
"The size of the resolve target must be the same as the color attachment");
|
"The size of the resolve target must be the same as the color attachment");
|
||||||
}
|
}
|
||||||
|
|
||||||
dawn::TextureFormat resolveTargetFormat = colorAttachment->resolveTarget->GetFormat();
|
dawn::TextureFormat resolveTargetFormat =
|
||||||
if (resolveTargetFormat != colorAttachment->attachment->GetFormat()) {
|
colorAttachment->resolveTarget->GetFormat().format;
|
||||||
|
if (resolveTargetFormat != colorAttachment->attachment->GetFormat().format) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"The format of the resolve target must be the same as the color attachment");
|
"The format of the resolve target must be the same as the color attachment");
|
||||||
}
|
}
|
||||||
|
@ -409,7 +409,7 @@ namespace dawn_native {
|
||||||
DAWN_TRY(device->ValidateObject(colorAttachment->attachment));
|
DAWN_TRY(device->ValidateObject(colorAttachment->attachment));
|
||||||
|
|
||||||
const TextureViewBase* attachment = colorAttachment->attachment;
|
const TextureViewBase* attachment = colorAttachment->attachment;
|
||||||
if (!IsColorRenderableTextureFormat(attachment->GetFormat())) {
|
if (!attachment->GetFormat().IsColor() || !attachment->GetFormat().isRenderable) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"The format of the texture view used as color attachment is not color "
|
"The format of the texture view used as color attachment is not color "
|
||||||
"renderable");
|
"renderable");
|
||||||
|
@ -436,7 +436,8 @@ namespace dawn_native {
|
||||||
DAWN_TRY(device->ValidateObject(depthStencilAttachment->attachment));
|
DAWN_TRY(device->ValidateObject(depthStencilAttachment->attachment));
|
||||||
|
|
||||||
const TextureViewBase* attachment = depthStencilAttachment->attachment;
|
const TextureViewBase* attachment = depthStencilAttachment->attachment;
|
||||||
if (!TextureFormatHasDepthOrStencil(attachment->GetFormat())) {
|
if (!attachment->GetFormat().HasDepthOrStencil() ||
|
||||||
|
!attachment->GetFormat().isRenderable) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"The format of the texture view used as depth stencil attachment is not a "
|
"The format of the texture view used as depth stencil attachment is not a "
|
||||||
"depth stencil format");
|
"depth stencil format");
|
||||||
|
@ -783,7 +784,8 @@ namespace dawn_native {
|
||||||
copy->destination.level = destination->level;
|
copy->destination.level = destination->level;
|
||||||
copy->destination.slice = destination->slice;
|
copy->destination.slice = destination->slice;
|
||||||
if (source->rowPitch == 0) {
|
if (source->rowPitch == 0) {
|
||||||
copy->source.rowPitch = ComputeDefaultRowPitch(destination->texture, copySize->width);
|
copy->source.rowPitch =
|
||||||
|
ComputeDefaultRowPitch(destination->texture->GetFormat(), copySize->width);
|
||||||
} else {
|
} else {
|
||||||
copy->source.rowPitch = source->rowPitch;
|
copy->source.rowPitch = source->rowPitch;
|
||||||
}
|
}
|
||||||
|
@ -819,7 +821,8 @@ namespace dawn_native {
|
||||||
copy->destination.buffer = destination->buffer;
|
copy->destination.buffer = destination->buffer;
|
||||||
copy->destination.offset = destination->offset;
|
copy->destination.offset = destination->offset;
|
||||||
if (destination->rowPitch == 0) {
|
if (destination->rowPitch == 0) {
|
||||||
copy->destination.rowPitch = ComputeDefaultRowPitch(source->texture, copySize->width);
|
copy->destination.rowPitch =
|
||||||
|
ComputeDefaultRowPitch(source->texture->GetFormat(), copySize->width);
|
||||||
} else {
|
} else {
|
||||||
copy->destination.rowPitch = destination->rowPitch;
|
copy->destination.rowPitch = destination->rowPitch;
|
||||||
}
|
}
|
||||||
|
@ -977,8 +980,8 @@ namespace dawn_native {
|
||||||
|
|
||||||
DAWN_TRY(ValidateCopySizeFitsInTexture(copy->destination, copy->copySize));
|
DAWN_TRY(ValidateCopySizeFitsInTexture(copy->destination, copy->copySize));
|
||||||
DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->source, bufferCopySize));
|
DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->source, bufferCopySize));
|
||||||
DAWN_TRY(
|
DAWN_TRY(ValidateTexelBufferOffset(copy->source,
|
||||||
ValidateTexelBufferOffset(copy->destination.texture.Get(), copy->source));
|
copy->destination.texture->GetFormat()));
|
||||||
|
|
||||||
DAWN_TRY(ValidateCanUseAs(copy->source.buffer.Get(),
|
DAWN_TRY(ValidateCanUseAs(copy->source.buffer.Get(),
|
||||||
dawn::BufferUsageBit::TransferSrc));
|
dawn::BufferUsageBit::TransferSrc));
|
||||||
|
@ -1011,8 +1014,8 @@ namespace dawn_native {
|
||||||
|
|
||||||
DAWN_TRY(ValidateCopySizeFitsInTexture(copy->source, copy->copySize));
|
DAWN_TRY(ValidateCopySizeFitsInTexture(copy->source, copy->copySize));
|
||||||
DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->destination, bufferCopySize));
|
DAWN_TRY(ValidateCopySizeFitsInBuffer(copy->destination, bufferCopySize));
|
||||||
DAWN_TRY(
|
DAWN_TRY(ValidateTexelBufferOffset(copy->destination,
|
||||||
ValidateTexelBufferOffset(copy->source.texture.Get(), copy->destination));
|
copy->source.texture->GetFormat()));
|
||||||
|
|
||||||
DAWN_TRY(ValidateCanUseAs(copy->source.texture.Get(),
|
DAWN_TRY(ValidateCanUseAs(copy->source.texture.Get(),
|
||||||
dawn::TextureUsageBit::TransferSrc));
|
dawn::TextureUsageBit::TransferSrc));
|
||||||
|
|
|
@ -124,9 +124,9 @@ namespace dawn_native {
|
||||||
DAWN_TRY(ValidateBlendFactor(descriptor->colorBlend.dstFactor));
|
DAWN_TRY(ValidateBlendFactor(descriptor->colorBlend.dstFactor));
|
||||||
DAWN_TRY(ValidateColorWriteMask(descriptor->writeMask));
|
DAWN_TRY(ValidateColorWriteMask(descriptor->writeMask));
|
||||||
|
|
||||||
dawn::TextureFormat format = descriptor->format;
|
Format format;
|
||||||
DAWN_TRY(ValidateTextureFormat(format));
|
DAWN_TRY_ASSIGN(format, ConvertFormat(descriptor->format));
|
||||||
if (!IsColorRenderableTextureFormat(format)) {
|
if (!format.IsColor() || !format.isRenderable) {
|
||||||
return DAWN_VALIDATION_ERROR("Color format must be color renderable");
|
return DAWN_VALIDATION_ERROR("Color format must be color renderable");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -148,9 +148,9 @@ namespace dawn_native {
|
||||||
DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.depthFailOp));
|
DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.depthFailOp));
|
||||||
DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.passOp));
|
DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.passOp));
|
||||||
|
|
||||||
dawn::TextureFormat format = descriptor->format;
|
Format format;
|
||||||
DAWN_TRY(ValidateTextureFormat(format));
|
DAWN_TRY_ASSIGN(format, ConvertFormat(descriptor->format));
|
||||||
if (!IsDepthStencilRenderableTextureFormat(format)) {
|
if (!format.HasDepthOrStencil() || !format.isRenderable) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"Depth stencil format must be depth-stencil renderable");
|
"Depth stencil format must be depth-stencil renderable");
|
||||||
}
|
}
|
||||||
|
@ -503,7 +503,8 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint32_t i : IterateBitSet(mColorAttachmentsSet)) {
|
for (uint32_t i : IterateBitSet(mColorAttachmentsSet)) {
|
||||||
if (renderPass->colorAttachments[i].view->GetFormat() != mColorStates[i].format) {
|
if (renderPass->colorAttachments[i].view->GetFormat().format !=
|
||||||
|
mColorStates[i].format) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -513,7 +514,8 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mHasDepthStencilAttachment &&
|
if (mHasDepthStencilAttachment &&
|
||||||
(renderPass->depthStencilAttachment.view->GetFormat() != mDepthStencilState.format)) {
|
(renderPass->depthStencilAttachment.view->GetFormat().format !=
|
||||||
|
mDepthStencilState.format)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ namespace dawn_native {
|
||||||
// TODO(jiawei.shao@intel.com): implement texture view format compatibility rule
|
// TODO(jiawei.shao@intel.com): implement texture view format compatibility rule
|
||||||
MaybeError ValidateTextureViewFormatCompatibility(const TextureBase* texture,
|
MaybeError ValidateTextureViewFormatCompatibility(const TextureBase* texture,
|
||||||
const TextureViewDescriptor* descriptor) {
|
const TextureViewDescriptor* descriptor) {
|
||||||
if (texture->GetFormat() != descriptor->format) {
|
if (texture->GetFormat().format != descriptor->format) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"The format of texture view is not compatible to the original texture");
|
"The format of texture view is not compatible to the original texture");
|
||||||
}
|
}
|
||||||
|
@ -86,38 +86,88 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsBCFormat(dawn::TextureFormat format) {
|
// Returns a format with a blockByteSize of 0 for an invalid input format
|
||||||
|
Format ConvertFormatInternal(dawn::TextureFormat format) {
|
||||||
|
auto MakeColorFormat = [](dawn::TextureFormat format, bool renderable,
|
||||||
|
uint32_t byteSize) -> Format {
|
||||||
|
Format result;
|
||||||
|
result.format = format;
|
||||||
|
result.isRenderable = renderable;
|
||||||
|
result.isCompressed = false;
|
||||||
|
result.aspect = Format::Aspect::Color;
|
||||||
|
result.blockByteSize = byteSize;
|
||||||
|
result.blockWidth = 1;
|
||||||
|
result.blockHeight = 1;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto MakeDepthStencilFormat = [](dawn::TextureFormat format, Format::Aspect aspect,
|
||||||
|
uint32_t byteSize) -> Format {
|
||||||
|
Format result;
|
||||||
|
result.format = format;
|
||||||
|
result.isRenderable = true;
|
||||||
|
result.isCompressed = false;
|
||||||
|
result.aspect = aspect;
|
||||||
|
result.blockByteSize = byteSize;
|
||||||
|
result.blockWidth = 1;
|
||||||
|
result.blockHeight = 1;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto MakeCompressedFormat = [](dawn::TextureFormat format, uint32_t byteSize,
|
||||||
|
uint32_t width, uint32_t height) -> Format {
|
||||||
|
Format result;
|
||||||
|
result.format = format;
|
||||||
|
result.isRenderable = false;
|
||||||
|
result.isCompressed = true;
|
||||||
|
result.aspect = Format::Aspect::Color;
|
||||||
|
result.blockByteSize = byteSize;
|
||||||
|
result.blockWidth = width;
|
||||||
|
result.blockHeight = height;
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
switch (format) {
|
switch (format) {
|
||||||
|
case dawn::TextureFormat::R8Unorm:
|
||||||
|
case dawn::TextureFormat::R8Uint:
|
||||||
|
return MakeColorFormat(format, true, 1);
|
||||||
|
case dawn::TextureFormat::RG8Unorm:
|
||||||
|
case dawn::TextureFormat::RG8Uint:
|
||||||
|
return MakeColorFormat(format, true, 2);
|
||||||
|
case dawn::TextureFormat::RGBA8Unorm:
|
||||||
|
case dawn::TextureFormat::RGBA8Uint:
|
||||||
|
case dawn::TextureFormat::BGRA8Unorm:
|
||||||
|
return MakeColorFormat(format, true, 4);
|
||||||
|
case dawn::TextureFormat::Depth24PlusStencil8:
|
||||||
|
// TODO(cwallez@chromium.org): It isn't clear if this format should be copyable
|
||||||
|
// because its size isn't well defined, is it 4, 5 or 8?
|
||||||
|
return MakeDepthStencilFormat(format, Format::Aspect::DepthStencil, 4);
|
||||||
case dawn::TextureFormat::BC1RGBAUnorm:
|
case dawn::TextureFormat::BC1RGBAUnorm:
|
||||||
case dawn::TextureFormat::BC1RGBAUnormSrgb:
|
case dawn::TextureFormat::BC1RGBAUnormSrgb:
|
||||||
|
case dawn::TextureFormat::BC4RSnorm:
|
||||||
|
case dawn::TextureFormat::BC4RUnorm:
|
||||||
|
return MakeCompressedFormat(format, 8, 4, 4);
|
||||||
case dawn::TextureFormat::BC2RGBAUnorm:
|
case dawn::TextureFormat::BC2RGBAUnorm:
|
||||||
case dawn::TextureFormat::BC2RGBAUnormSrgb:
|
case dawn::TextureFormat::BC2RGBAUnormSrgb:
|
||||||
case dawn::TextureFormat::BC3RGBAUnorm:
|
case dawn::TextureFormat::BC3RGBAUnorm:
|
||||||
case dawn::TextureFormat::BC3RGBAUnormSrgb:
|
case dawn::TextureFormat::BC3RGBAUnormSrgb:
|
||||||
case dawn::TextureFormat::BC4RUnorm:
|
|
||||||
case dawn::TextureFormat::BC4RSnorm:
|
|
||||||
case dawn::TextureFormat::BC5RGUnorm:
|
|
||||||
case dawn::TextureFormat::BC5RGSnorm:
|
case dawn::TextureFormat::BC5RGSnorm:
|
||||||
case dawn::TextureFormat::BC6HRGBUfloat:
|
case dawn::TextureFormat::BC5RGUnorm:
|
||||||
case dawn::TextureFormat::BC6HRGBSfloat:
|
case dawn::TextureFormat::BC6HRGBSfloat:
|
||||||
|
case dawn::TextureFormat::BC6HRGBUfloat:
|
||||||
case dawn::TextureFormat::BC7RGBAUnorm:
|
case dawn::TextureFormat::BC7RGBAUnorm:
|
||||||
case dawn::TextureFormat::BC7RGBAUnormSrgb:
|
case dawn::TextureFormat::BC7RGBAUnormSrgb:
|
||||||
return true;
|
return MakeCompressedFormat(format, 16, 4, 4);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
Format result = {};
|
||||||
|
result.blockByteSize = 0;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsCompressedFormat(dawn::TextureFormat format) {
|
|
||||||
return IsBCFormat(format);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsWritableFormat(dawn::TextureFormat format) {
|
|
||||||
return !IsBCFormat(format);
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(jiawei.shao@intel.com): support more sample count.
|
// TODO(jiawei.shao@intel.com): support more sample count.
|
||||||
MaybeError ValidateSampleCount(const TextureDescriptor* descriptor) {
|
MaybeError ValidateSampleCount(const TextureDescriptor* descriptor, const Format& format) {
|
||||||
if (!IsValidSampleCount(descriptor->sampleCount)) {
|
if (!IsValidSampleCount(descriptor->sampleCount)) {
|
||||||
return DAWN_VALIDATION_ERROR("The sample count of the texture is not supported.");
|
return DAWN_VALIDATION_ERROR("The sample count of the texture is not supported.");
|
||||||
}
|
}
|
||||||
|
@ -134,7 +184,7 @@ namespace dawn_native {
|
||||||
return DAWN_VALIDATION_ERROR("Multisampled 2D array texture is not supported.");
|
return DAWN_VALIDATION_ERROR("Multisampled 2D array texture is not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsCompressedFormat(descriptor->format)) {
|
if (format.isCompressed) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"The sample counts of the textures in BC formats must be 1.");
|
"The sample counts of the textures in BC formats must be 1.");
|
||||||
}
|
}
|
||||||
|
@ -171,7 +221,7 @@ namespace dawn_native {
|
||||||
|
|
||||||
TextureViewDescriptor MakeDefaultTextureViewDescriptor(const TextureBase* texture) {
|
TextureViewDescriptor MakeDefaultTextureViewDescriptor(const TextureBase* texture) {
|
||||||
TextureViewDescriptor descriptor;
|
TextureViewDescriptor descriptor;
|
||||||
descriptor.format = texture->GetFormat();
|
descriptor.format = texture->GetFormat().format;
|
||||||
descriptor.baseArrayLayer = 0;
|
descriptor.baseArrayLayer = 0;
|
||||||
descriptor.arrayLayerCount = texture->GetArrayLayers();
|
descriptor.arrayLayerCount = texture->GetArrayLayers();
|
||||||
descriptor.baseMipLevel = 0;
|
descriptor.baseMipLevel = 0;
|
||||||
|
@ -193,7 +243,7 @@ namespace dawn_native {
|
||||||
return descriptor;
|
return descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaybeError ValidateTextureSize(const TextureDescriptor* descriptor) {
|
MaybeError ValidateTextureSize(const TextureDescriptor* descriptor, const Format& format) {
|
||||||
ASSERT(descriptor->size.width != 0 && descriptor->size.height != 0);
|
ASSERT(descriptor->size.width != 0 && descriptor->size.height != 0);
|
||||||
|
|
||||||
if (Log2(std::max(descriptor->size.width, descriptor->size.height)) + 1 <
|
if (Log2(std::max(descriptor->size.width, descriptor->size.height)) + 1 <
|
||||||
|
@ -201,63 +251,43 @@ namespace dawn_native {
|
||||||
return DAWN_VALIDATION_ERROR("Texture has too many mip levels");
|
return DAWN_VALIDATION_ERROR("Texture has too many mip levels");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Is4x4CompressedFormat(descriptor->format)) {
|
if (format.isCompressed && (descriptor->size.width % format.blockWidth != 0 ||
|
||||||
if (descriptor->size.width % 4 != 0 || descriptor->size.height % 4 != 0) {
|
descriptor->size.height % format.blockHeight != 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");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
} // anonymous namespace
|
|
||||||
|
|
||||||
bool Is4x4CompressedFormat(dawn::TextureFormat format) {
|
MaybeError ValidateTextureUsage(const TextureDescriptor* descriptor, const Format& format) {
|
||||||
return IsBCFormat(format);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We treat non-compressed texture formats as the block texture formats in 1x1 blocks.
|
|
||||||
uint32_t TextureFormatBlockWidthInTexels(dawn::TextureFormat format) {
|
|
||||||
if (Is4x4CompressedFormat(format)) {
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We treat non-compressed texture formats as the block texture formats in 1x1 blocks.
|
|
||||||
uint32_t TextureFormatBlockHeightInTexels(dawn::TextureFormat format) {
|
|
||||||
if (Is4x4CompressedFormat(format)) {
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
MaybeError ValidateTextureUsageBit(const TextureDescriptor* descriptor) {
|
|
||||||
DAWN_TRY(ValidateTextureUsageBit(descriptor->usage));
|
DAWN_TRY(ValidateTextureUsageBit(descriptor->usage));
|
||||||
if (!IsWritableFormat(descriptor->format)) {
|
if (format.isCompressed) {
|
||||||
constexpr dawn::TextureUsageBit kValidUsage = dawn::TextureUsageBit::Sampled |
|
constexpr dawn::TextureUsageBit kValidUsage = dawn::TextureUsageBit::Sampled |
|
||||||
dawn::TextureUsageBit::TransferSrc |
|
dawn::TextureUsageBit::TransferSrc |
|
||||||
dawn::TextureUsageBit::TransferDst;
|
dawn::TextureUsageBit::TransferDst;
|
||||||
if (descriptor->usage & (~kValidUsage)) {
|
if (descriptor->usage & (~kValidUsage)) {
|
||||||
return DAWN_VALIDATION_ERROR(
|
return DAWN_VALIDATION_ERROR(
|
||||||
"Texture format is incompatible with the texture usage");
|
"Compressed texture format is incompatible with the texture usage");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
MaybeError ValidateTextureDescriptor(DeviceBase*, const TextureDescriptor* descriptor) {
|
MaybeError ValidateTextureDescriptor(DeviceBase*, const TextureDescriptor* descriptor) {
|
||||||
if (descriptor->nextInChain != nullptr) {
|
if (descriptor->nextInChain != nullptr) {
|
||||||
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
|
return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_TRY(ValidateTextureUsageBit(descriptor));
|
Format format;
|
||||||
|
DAWN_TRY_ASSIGN(format, ConvertFormat(descriptor->format));
|
||||||
|
|
||||||
|
DAWN_TRY(ValidateTextureUsage(descriptor, format));
|
||||||
DAWN_TRY(ValidateTextureDimension(descriptor->dimension));
|
DAWN_TRY(ValidateTextureDimension(descriptor->dimension));
|
||||||
DAWN_TRY(ValidateTextureFormat(descriptor->format));
|
DAWN_TRY(ValidateSampleCount(descriptor, format));
|
||||||
DAWN_TRY(ValidateSampleCount(descriptor));
|
|
||||||
|
|
||||||
// TODO(jiawei.shao@intel.com): check stuff based on the dimension
|
// TODO(jiawei.shao@intel.com): check stuff based on the dimension
|
||||||
if (descriptor->size.width == 0 || descriptor->size.height == 0 ||
|
if (descriptor->size.width == 0 || descriptor->size.height == 0 ||
|
||||||
|
@ -266,7 +296,7 @@ namespace dawn_native {
|
||||||
return DAWN_VALIDATION_ERROR("Cannot create an empty texture");
|
return DAWN_VALIDATION_ERROR("Cannot create an empty texture");
|
||||||
}
|
}
|
||||||
|
|
||||||
DAWN_TRY(ValidateTextureSize(descriptor));
|
DAWN_TRY(ValidateTextureSize(descriptor, format));
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
@ -307,113 +337,6 @@ namespace dawn_native {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
// We treat non-compressed texture formats as the block texture formats in 1x1 blocks.
|
|
||||||
uint32_t TextureFormatTexelBlockSizeInBytes(dawn::TextureFormat format) {
|
|
||||||
switch (format) {
|
|
||||||
// Non-compressed texture formats
|
|
||||||
case dawn::TextureFormat::R8Unorm:
|
|
||||||
case dawn::TextureFormat::R8Uint:
|
|
||||||
return 1;
|
|
||||||
case dawn::TextureFormat::RG8Unorm:
|
|
||||||
case dawn::TextureFormat::RG8Uint:
|
|
||||||
return 2;
|
|
||||||
case dawn::TextureFormat::RGBA8Unorm:
|
|
||||||
case dawn::TextureFormat::RGBA8Uint:
|
|
||||||
case dawn::TextureFormat::BGRA8Unorm:
|
|
||||||
return 4;
|
|
||||||
case dawn::TextureFormat::Depth24PlusStencil8:
|
|
||||||
return 8;
|
|
||||||
|
|
||||||
// BC formats
|
|
||||||
case dawn::TextureFormat::BC1RGBAUnorm:
|
|
||||||
case dawn::TextureFormat::BC1RGBAUnormSrgb:
|
|
||||||
case dawn::TextureFormat::BC4RSnorm:
|
|
||||||
case dawn::TextureFormat::BC4RUnorm:
|
|
||||||
return 8;
|
|
||||||
case dawn::TextureFormat::BC2RGBAUnorm:
|
|
||||||
case dawn::TextureFormat::BC2RGBAUnormSrgb:
|
|
||||||
case dawn::TextureFormat::BC3RGBAUnorm:
|
|
||||||
case dawn::TextureFormat::BC3RGBAUnormSrgb:
|
|
||||||
case dawn::TextureFormat::BC5RGSnorm:
|
|
||||||
case dawn::TextureFormat::BC5RGUnorm:
|
|
||||||
case dawn::TextureFormat::BC6HRGBSfloat:
|
|
||||||
case dawn::TextureFormat::BC6HRGBUfloat:
|
|
||||||
case dawn::TextureFormat::BC7RGBAUnorm:
|
|
||||||
case dawn::TextureFormat::BC7RGBAUnormSrgb:
|
|
||||||
return 16;
|
|
||||||
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureFormatHasDepth(dawn::TextureFormat format) {
|
|
||||||
switch (format) {
|
|
||||||
case dawn::TextureFormat::Depth24PlusStencil8:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureFormatHasStencil(dawn::TextureFormat format) {
|
|
||||||
switch (format) {
|
|
||||||
case dawn::TextureFormat::Depth24PlusStencil8:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TextureFormatHasDepthOrStencil(dawn::TextureFormat format) {
|
|
||||||
switch (format) {
|
|
||||||
case dawn::TextureFormat::Depth24PlusStencil8:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsColorRenderableTextureFormat(dawn::TextureFormat format) {
|
|
||||||
switch (format) {
|
|
||||||
case dawn::TextureFormat::BGRA8Unorm:
|
|
||||||
case dawn::TextureFormat::RGBA8Uint:
|
|
||||||
case dawn::TextureFormat::RGBA8Unorm:
|
|
||||||
case dawn::TextureFormat::RG8Uint:
|
|
||||||
case dawn::TextureFormat::RG8Unorm:
|
|
||||||
case dawn::TextureFormat::R8Uint:
|
|
||||||
case dawn::TextureFormat::R8Unorm:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case dawn::TextureFormat::Depth24PlusStencil8:
|
|
||||||
return false;
|
|
||||||
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsDepthStencilRenderableTextureFormat(dawn::TextureFormat format) {
|
|
||||||
switch (format) {
|
|
||||||
case dawn::TextureFormat::Depth24PlusStencil8:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case dawn::TextureFormat::BGRA8Unorm:
|
|
||||||
case dawn::TextureFormat::RGBA8Uint:
|
|
||||||
case dawn::TextureFormat::RGBA8Unorm:
|
|
||||||
case dawn::TextureFormat::RG8Uint:
|
|
||||||
case dawn::TextureFormat::RG8Unorm:
|
|
||||||
case dawn::TextureFormat::R8Uint:
|
|
||||||
case dawn::TextureFormat::R8Unorm:
|
|
||||||
return false;
|
|
||||||
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsValidSampleCount(uint32_t sampleCount) {
|
bool IsValidSampleCount(uint32_t sampleCount) {
|
||||||
switch (sampleCount) {
|
switch (sampleCount) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -425,6 +348,36 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResultOrError<Format> ConvertFormat(dawn::TextureFormat format) {
|
||||||
|
Format result = ConvertFormatInternal(format);
|
||||||
|
if (result.blockByteSize == 0) {
|
||||||
|
return DAWN_VALIDATION_ERROR("Invalid texture format");
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Format ConvertValidFormat(dawn::TextureFormat format) {
|
||||||
|
Format result = ConvertFormatInternal(format);
|
||||||
|
ASSERT(result.blockByteSize != 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Format::IsColor() const {
|
||||||
|
return aspect == Aspect::Color;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Format::HasDepth() const {
|
||||||
|
return aspect == Depth || aspect == DepthStencil;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Format::HasStencil() const {
|
||||||
|
return aspect == Stencil || aspect == DepthStencil;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Format::HasDepthOrStencil() const {
|
||||||
|
return aspect != Color;
|
||||||
|
}
|
||||||
|
|
||||||
// TextureBase
|
// TextureBase
|
||||||
|
|
||||||
TextureBase::TextureBase(DeviceBase* device,
|
TextureBase::TextureBase(DeviceBase* device,
|
||||||
|
@ -432,7 +385,7 @@ namespace dawn_native {
|
||||||
TextureState state)
|
TextureState state)
|
||||||
: ObjectBase(device),
|
: ObjectBase(device),
|
||||||
mDimension(descriptor->dimension),
|
mDimension(descriptor->dimension),
|
||||||
mFormat(descriptor->format),
|
mFormat(ConvertValidFormat(descriptor->format)),
|
||||||
mSize(descriptor->size),
|
mSize(descriptor->size),
|
||||||
mArrayLayerCount(descriptor->arrayLayerCount),
|
mArrayLayerCount(descriptor->arrayLayerCount),
|
||||||
mMipLevelCount(descriptor->mipLevelCount),
|
mMipLevelCount(descriptor->mipLevelCount),
|
||||||
|
@ -459,7 +412,7 @@ namespace dawn_native {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(jiawei.shao@intel.com): return more information about texture format
|
// TODO(jiawei.shao@intel.com): return more information about texture format
|
||||||
dawn::TextureFormat TextureBase::GetFormat() const {
|
const Format& TextureBase::GetFormat() const {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
return mFormat;
|
return mFormat;
|
||||||
}
|
}
|
||||||
|
@ -586,7 +539,7 @@ namespace dawn_native {
|
||||||
TextureViewBase::TextureViewBase(TextureBase* texture, const TextureViewDescriptor* descriptor)
|
TextureViewBase::TextureViewBase(TextureBase* texture, const TextureViewDescriptor* descriptor)
|
||||||
: ObjectBase(texture->GetDevice()),
|
: ObjectBase(texture->GetDevice()),
|
||||||
mTexture(texture),
|
mTexture(texture),
|
||||||
mFormat(descriptor->format),
|
mFormat(ConvertValidFormat(descriptor->format)),
|
||||||
mBaseMipLevel(descriptor->baseMipLevel),
|
mBaseMipLevel(descriptor->baseMipLevel),
|
||||||
mMipLevelCount(descriptor->mipLevelCount),
|
mMipLevelCount(descriptor->mipLevelCount),
|
||||||
mBaseArrayLayer(descriptor->baseArrayLayer),
|
mBaseArrayLayer(descriptor->baseArrayLayer),
|
||||||
|
@ -612,7 +565,7 @@ namespace dawn_native {
|
||||||
return mTexture.Get();
|
return mTexture.Get();
|
||||||
}
|
}
|
||||||
|
|
||||||
dawn::TextureFormat TextureViewBase::GetFormat() const {
|
const Format& TextureViewBase::GetFormat() const {
|
||||||
ASSERT(!IsError());
|
ASSERT(!IsError());
|
||||||
return mFormat;
|
return mFormat;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,18 +29,8 @@ namespace dawn_native {
|
||||||
const TextureBase* texture,
|
const TextureBase* texture,
|
||||||
const TextureViewDescriptor* descriptor);
|
const TextureViewDescriptor* descriptor);
|
||||||
|
|
||||||
uint32_t TextureFormatTexelBlockSizeInBytes(dawn::TextureFormat format);
|
|
||||||
bool TextureFormatHasDepth(dawn::TextureFormat format);
|
|
||||||
bool TextureFormatHasStencil(dawn::TextureFormat format);
|
|
||||||
bool TextureFormatHasDepthOrStencil(dawn::TextureFormat format);
|
|
||||||
bool IsColorRenderableTextureFormat(dawn::TextureFormat format);
|
|
||||||
bool IsDepthStencilRenderableTextureFormat(dawn::TextureFormat format);
|
|
||||||
bool IsValidSampleCount(uint32_t sampleCount);
|
bool IsValidSampleCount(uint32_t sampleCount);
|
||||||
|
|
||||||
bool Is4x4CompressedFormat(dawn::TextureFormat format);
|
|
||||||
uint32_t TextureFormatBlockWidthInTexels(dawn::TextureFormat format);
|
|
||||||
uint32_t TextureFormatBlockHeightInTexels(dawn::TextureFormat format);
|
|
||||||
|
|
||||||
static constexpr dawn::TextureUsageBit kReadOnlyTextureUsages =
|
static constexpr dawn::TextureUsageBit kReadOnlyTextureUsages =
|
||||||
dawn::TextureUsageBit::TransferSrc | dawn::TextureUsageBit::Sampled |
|
dawn::TextureUsageBit::TransferSrc | dawn::TextureUsageBit::Sampled |
|
||||||
dawn::TextureUsageBit::Present;
|
dawn::TextureUsageBit::Present;
|
||||||
|
@ -49,6 +39,36 @@ namespace dawn_native {
|
||||||
dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Storage |
|
dawn::TextureUsageBit::TransferDst | dawn::TextureUsageBit::Storage |
|
||||||
dawn::TextureUsageBit::OutputAttachment;
|
dawn::TextureUsageBit::OutputAttachment;
|
||||||
|
|
||||||
|
struct Format {
|
||||||
|
enum Aspect {
|
||||||
|
Color,
|
||||||
|
Depth,
|
||||||
|
Stencil,
|
||||||
|
DepthStencil,
|
||||||
|
};
|
||||||
|
|
||||||
|
dawn::TextureFormat format;
|
||||||
|
bool isRenderable;
|
||||||
|
bool isCompressed;
|
||||||
|
Aspect aspect;
|
||||||
|
|
||||||
|
uint32_t blockByteSize;
|
||||||
|
uint32_t blockWidth;
|
||||||
|
uint32_t blockHeight;
|
||||||
|
|
||||||
|
bool IsColor() const;
|
||||||
|
bool HasDepth() const;
|
||||||
|
bool HasStencil() const;
|
||||||
|
bool HasDepthOrStencil() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns the Format corresponding to the dawn::TextureFormat or an error if the format
|
||||||
|
// isn't valid.
|
||||||
|
ResultOrError<Format> ConvertFormat(dawn::TextureFormat format);
|
||||||
|
|
||||||
|
// Returns the Format corresponding to the dawn::TextureFormat and assumes the format is valid.
|
||||||
|
Format ConvertValidFormat(dawn::TextureFormat format);
|
||||||
|
|
||||||
class TextureBase : public ObjectBase {
|
class TextureBase : public ObjectBase {
|
||||||
public:
|
public:
|
||||||
enum class TextureState { OwnedInternal, OwnedExternal, Destroyed };
|
enum class TextureState { OwnedInternal, OwnedExternal, Destroyed };
|
||||||
|
@ -58,7 +78,7 @@ namespace dawn_native {
|
||||||
static TextureBase* MakeError(DeviceBase* device);
|
static TextureBase* MakeError(DeviceBase* device);
|
||||||
|
|
||||||
dawn::TextureDimension GetDimension() const;
|
dawn::TextureDimension GetDimension() const;
|
||||||
dawn::TextureFormat GetFormat() const;
|
const Format& GetFormat() const;
|
||||||
const Extent3D& GetSize() const;
|
const Extent3D& GetSize() const;
|
||||||
uint32_t GetArrayLayers() const;
|
uint32_t GetArrayLayers() const;
|
||||||
uint32_t GetNumMipLevels() const;
|
uint32_t GetNumMipLevels() const;
|
||||||
|
@ -93,7 +113,8 @@ namespace dawn_native {
|
||||||
|
|
||||||
MaybeError ValidateDestroy() const;
|
MaybeError ValidateDestroy() const;
|
||||||
dawn::TextureDimension mDimension;
|
dawn::TextureDimension mDimension;
|
||||||
dawn::TextureFormat mFormat;
|
// TODO(cwallez@chromium.org): This should be deduplicated in the Device
|
||||||
|
Format mFormat;
|
||||||
Extent3D mSize;
|
Extent3D mSize;
|
||||||
uint32_t mArrayLayerCount;
|
uint32_t mArrayLayerCount;
|
||||||
uint32_t mMipLevelCount;
|
uint32_t mMipLevelCount;
|
||||||
|
@ -114,7 +135,7 @@ namespace dawn_native {
|
||||||
const TextureBase* GetTexture() const;
|
const TextureBase* GetTexture() const;
|
||||||
TextureBase* GetTexture();
|
TextureBase* GetTexture();
|
||||||
|
|
||||||
dawn::TextureFormat GetFormat() const;
|
const Format& GetFormat() const;
|
||||||
uint32_t GetBaseMipLevel() const;
|
uint32_t GetBaseMipLevel() const;
|
||||||
uint32_t GetLevelCount() const;
|
uint32_t GetLevelCount() const;
|
||||||
uint32_t GetBaseArrayLayer() const;
|
uint32_t GetBaseArrayLayer() const;
|
||||||
|
@ -125,7 +146,8 @@ namespace dawn_native {
|
||||||
|
|
||||||
Ref<TextureBase> mTexture;
|
Ref<TextureBase> mTexture;
|
||||||
|
|
||||||
dawn::TextureFormat mFormat;
|
// TODO(cwallez@chromium.org): This should be deduplicated in the Device
|
||||||
|
Format mFormat;
|
||||||
uint32_t mBaseMipLevel;
|
uint32_t mBaseMipLevel;
|
||||||
uint32_t mMipLevelCount;
|
uint32_t mMipLevelCount;
|
||||||
uint32_t mBaseArrayLayer;
|
uint32_t mBaseArrayLayer;
|
||||||
|
|
|
@ -505,9 +505,8 @@ namespace dawn_native { namespace d3d12 {
|
||||||
|
|
||||||
auto copySplit = ComputeTextureCopySplit(
|
auto copySplit = ComputeTextureCopySplit(
|
||||||
copy->destination.origin, copy->copySize,
|
copy->destination.origin, copy->copySize,
|
||||||
static_cast<uint32_t>(
|
texture->GetFormat().blockByteSize, copy->source.offset,
|
||||||
TextureFormatTexelBlockSizeInBytes(texture->GetFormat())),
|
copy->source.rowPitch, copy->source.imageHeight);
|
||||||
copy->source.offset, copy->source.rowPitch, copy->source.imageHeight);
|
|
||||||
|
|
||||||
D3D12_TEXTURE_COPY_LOCATION textureLocation =
|
D3D12_TEXTURE_COPY_LOCATION textureLocation =
|
||||||
CreateTextureCopyLocationForTexture(*texture, copy->destination.level,
|
CreateTextureCopyLocationForTexture(*texture, copy->destination.level,
|
||||||
|
@ -549,9 +548,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
buffer->TransitionUsageNow(commandList, dawn::BufferUsageBit::TransferDst);
|
buffer->TransitionUsageNow(commandList, dawn::BufferUsageBit::TransferDst);
|
||||||
|
|
||||||
auto copySplit = ComputeTextureCopySplit(
|
auto copySplit = ComputeTextureCopySplit(
|
||||||
copy->source.origin, copy->copySize,
|
copy->source.origin, copy->copySize, texture->GetFormat().blockByteSize,
|
||||||
static_cast<uint32_t>(
|
|
||||||
TextureFormatTexelBlockSizeInBytes(texture->GetFormat())),
|
|
||||||
copy->destination.offset, copy->destination.rowPitch,
|
copy->destination.offset, copy->destination.rowPitch,
|
||||||
copy->destination.imageHeight);
|
copy->destination.imageHeight);
|
||||||
|
|
||||||
|
@ -749,9 +746,9 @@ namespace dawn_native { namespace d3d12 {
|
||||||
Texture* texture = ToBackend(renderPass->depthStencilAttachment.view->GetTexture());
|
Texture* texture = ToBackend(renderPass->depthStencilAttachment.view->GetTexture());
|
||||||
|
|
||||||
// Load op - depth/stencil
|
// Load op - depth/stencil
|
||||||
bool doDepthClear = TextureFormatHasDepth(texture->GetFormat()) &&
|
bool doDepthClear = texture->GetFormat().HasDepth() &&
|
||||||
(attachmentInfo.depthLoadOp == dawn::LoadOp::Clear);
|
(attachmentInfo.depthLoadOp == dawn::LoadOp::Clear);
|
||||||
bool doStencilClear = TextureFormatHasStencil(texture->GetFormat()) &&
|
bool doStencilClear = texture->GetFormat().HasStencil() &&
|
||||||
(attachmentInfo.stencilLoadOp == dawn::LoadOp::Clear);
|
(attachmentInfo.stencilLoadOp == dawn::LoadOp::Clear);
|
||||||
|
|
||||||
D3D12_CLEAR_FLAGS clearFlags = {};
|
D3D12_CLEAR_FLAGS clearFlags = {};
|
||||||
|
|
|
@ -21,8 +21,7 @@
|
||||||
namespace dawn_native { namespace d3d12 {
|
namespace dawn_native { namespace d3d12 {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
D3D12_RESOURCE_STATES D3D12TextureUsage(dawn::TextureUsageBit usage,
|
D3D12_RESOURCE_STATES D3D12TextureUsage(dawn::TextureUsageBit usage, const Format& format) {
|
||||||
dawn::TextureFormat format) {
|
|
||||||
D3D12_RESOURCE_STATES resourceState = D3D12_RESOURCE_STATE_COMMON;
|
D3D12_RESOURCE_STATES resourceState = D3D12_RESOURCE_STATE_COMMON;
|
||||||
|
|
||||||
// Present is an exclusive flag.
|
// Present is an exclusive flag.
|
||||||
|
@ -44,7 +43,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
resourceState |= D3D12_RESOURCE_STATE_UNORDERED_ACCESS;
|
||||||
}
|
}
|
||||||
if (usage & dawn::TextureUsageBit::OutputAttachment) {
|
if (usage & dawn::TextureUsageBit::OutputAttachment) {
|
||||||
if (TextureFormatHasDepth(format) || TextureFormatHasStencil(format)) {
|
if (format.HasDepthOrStencil()) {
|
||||||
resourceState |= D3D12_RESOURCE_STATE_DEPTH_WRITE;
|
resourceState |= D3D12_RESOURCE_STATE_DEPTH_WRITE;
|
||||||
} else {
|
} else {
|
||||||
resourceState |= D3D12_RESOURCE_STATE_RENDER_TARGET;
|
resourceState |= D3D12_RESOURCE_STATE_RENDER_TARGET;
|
||||||
|
@ -55,7 +54,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
}
|
}
|
||||||
|
|
||||||
D3D12_RESOURCE_FLAGS D3D12ResourceFlags(dawn::TextureUsageBit usage,
|
D3D12_RESOURCE_FLAGS D3D12ResourceFlags(dawn::TextureUsageBit usage,
|
||||||
dawn::TextureFormat format,
|
const Format& format,
|
||||||
bool isMultisampledTexture) {
|
bool isMultisampledTexture) {
|
||||||
D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE;
|
D3D12_RESOURCE_FLAGS flags = D3D12_RESOURCE_FLAG_NONE;
|
||||||
|
|
||||||
|
@ -68,7 +67,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
// https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_resource
|
// https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_resource
|
||||||
// _desc
|
// _desc
|
||||||
if ((usage & dawn::TextureUsageBit::OutputAttachment) || isMultisampledTexture) {
|
if ((usage & dawn::TextureUsageBit::OutputAttachment) || isMultisampledTexture) {
|
||||||
if (TextureFormatHasDepth(format) || TextureFormatHasStencil(format)) {
|
if (format.HasDepthOrStencil()) {
|
||||||
flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL;
|
||||||
} else {
|
} else {
|
||||||
flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET;
|
||||||
|
@ -126,7 +125,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
|
|
||||||
resourceDescriptor.DepthOrArraySize = GetDepthOrArraySize();
|
resourceDescriptor.DepthOrArraySize = GetDepthOrArraySize();
|
||||||
resourceDescriptor.MipLevels = static_cast<UINT16>(GetNumMipLevels());
|
resourceDescriptor.MipLevels = static_cast<UINT16>(GetNumMipLevels());
|
||||||
resourceDescriptor.Format = D3D12TextureFormat(GetFormat());
|
resourceDescriptor.Format = D3D12TextureFormat(GetFormat().format);
|
||||||
resourceDescriptor.SampleDesc.Count = descriptor->sampleCount;
|
resourceDescriptor.SampleDesc.Count = descriptor->sampleCount;
|
||||||
// TODO(bryan.bernhart@intel.com): investigate how to specify standard MSAA sample pattern.
|
// TODO(bryan.bernhart@intel.com): investigate how to specify standard MSAA sample pattern.
|
||||||
resourceDescriptor.SampleDesc.Quality = 0;
|
resourceDescriptor.SampleDesc.Quality = 0;
|
||||||
|
@ -225,7 +224,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
}
|
}
|
||||||
|
|
||||||
DXGI_FORMAT Texture::GetD3D12Format() const {
|
DXGI_FORMAT Texture::GetD3D12Format() const {
|
||||||
return D3D12TextureFormat(GetFormat());
|
return D3D12TextureFormat(GetFormat().format);
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3D12Resource* Texture::GetD3D12Resource() const {
|
ID3D12Resource* Texture::GetD3D12Resource() const {
|
||||||
|
@ -329,7 +328,7 @@ namespace dawn_native { namespace d3d12 {
|
||||||
}
|
}
|
||||||
|
|
||||||
DXGI_FORMAT TextureView::GetD3D12Format() const {
|
DXGI_FORMAT TextureView::GetD3D12Format() const {
|
||||||
return D3D12TextureFormat(GetFormat());
|
return D3D12TextureFormat(GetFormat().format);
|
||||||
}
|
}
|
||||||
|
|
||||||
const D3D12_SHADER_RESOURCE_VIEW_DESC& TextureView::GetSRVDescriptor() const {
|
const D3D12_SHADER_RESOURCE_VIEW_DESC& TextureView::GetSRVDescriptor() const {
|
||||||
|
|
|
@ -89,9 +89,9 @@ namespace dawn_native { namespace metal {
|
||||||
// TODO(jiawei.shao@intel.com): support rendering into a layer of a texture.
|
// TODO(jiawei.shao@intel.com): support rendering into a layer of a texture.
|
||||||
id<MTLTexture> texture =
|
id<MTLTexture> texture =
|
||||||
ToBackend(attachmentInfo.view->GetTexture())->GetMTLTexture();
|
ToBackend(attachmentInfo.view->GetTexture())->GetMTLTexture();
|
||||||
dawn::TextureFormat format = attachmentInfo.view->GetTexture()->GetFormat();
|
const Format& format = attachmentInfo.view->GetTexture()->GetFormat();
|
||||||
|
|
||||||
if (TextureFormatHasDepth(format)) {
|
if (format.HasDepth()) {
|
||||||
descriptor.depthAttachment.texture = texture;
|
descriptor.depthAttachment.texture = texture;
|
||||||
descriptor.depthAttachment.storeAction = MTLStoreActionStore;
|
descriptor.depthAttachment.storeAction = MTLStoreActionStore;
|
||||||
|
|
||||||
|
@ -103,7 +103,7 @@ namespace dawn_native { namespace metal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TextureFormatHasStencil(format)) {
|
if (format.HasStencil()) {
|
||||||
descriptor.stencilAttachment.texture = texture;
|
descriptor.stencilAttachment.texture = texture;
|
||||||
descriptor.stencilAttachment.storeAction = MTLStoreActionStore;
|
descriptor.stencilAttachment.storeAction = MTLStoreActionStore;
|
||||||
|
|
||||||
|
@ -453,8 +453,7 @@ 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.
|
||||||
// Like copy to a 1D texture to workaround the issue.
|
// Like copy to a 1D texture to workaround the issue.
|
||||||
uint32_t lastRowDataSize =
|
uint32_t lastRowDataSize = copySize.width * texture->GetFormat().blockByteSize;
|
||||||
copySize.width * TextureFormatTexelBlockSizeInBytes(texture->GetFormat());
|
|
||||||
|
|
||||||
[encoders.blit
|
[encoders.blit
|
||||||
copyFromBuffer:buffer->GetMTLBuffer()
|
copyFromBuffer:buffer->GetMTLBuffer()
|
||||||
|
@ -567,8 +566,7 @@ 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.
|
||||||
// Like copy from a 1D texture to workaround the issue.
|
// Like copy from a 1D texture to workaround the issue.
|
||||||
uint32_t lastRowDataSize =
|
uint32_t lastRowDataSize = copySize.width * texture->GetFormat().blockByteSize;
|
||||||
copySize.width * TextureFormatTexelBlockSizeInBytes(texture->GetFormat());
|
|
||||||
|
|
||||||
[encoders.blit
|
[encoders.blit
|
||||||
copyFromTexture:texture->GetMTLTexture()
|
copyFromTexture:texture->GetMTLTexture()
|
||||||
|
|
|
@ -82,7 +82,7 @@ namespace dawn_native { namespace metal {
|
||||||
|
|
||||||
bool RequiresCreatingNewTextureView(const TextureBase* texture,
|
bool RequiresCreatingNewTextureView(const TextureBase* texture,
|
||||||
const TextureViewDescriptor* textureViewDescriptor) {
|
const TextureViewDescriptor* textureViewDescriptor) {
|
||||||
if (texture->GetFormat() != textureViewDescriptor->format) {
|
if (texture->GetFormat().format != textureViewDescriptor->format) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -389,9 +389,8 @@ namespace dawn_native { namespace opengl {
|
||||||
gl.ActiveTexture(GL_TEXTURE0);
|
gl.ActiveTexture(GL_TEXTURE0);
|
||||||
gl.BindTexture(target, texture->GetHandle());
|
gl.BindTexture(target, texture->GetHandle());
|
||||||
|
|
||||||
gl.PixelStorei(
|
gl.PixelStorei(GL_UNPACK_ROW_LENGTH,
|
||||||
GL_UNPACK_ROW_LENGTH,
|
src.rowPitch / texture->GetFormat().blockByteSize);
|
||||||
src.rowPitch / TextureFormatTexelBlockSizeInBytes(texture->GetFormat()));
|
|
||||||
gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, src.imageHeight);
|
gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, src.imageHeight);
|
||||||
switch (texture->GetDimension()) {
|
switch (texture->GetDimension()) {
|
||||||
case dawn::TextureDimension::e2D:
|
case dawn::TextureDimension::e2D:
|
||||||
|
@ -452,9 +451,8 @@ namespace dawn_native { namespace opengl {
|
||||||
}
|
}
|
||||||
|
|
||||||
gl.BindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
|
gl.BindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
|
||||||
gl.PixelStorei(
|
gl.PixelStorei(GL_PACK_ROW_LENGTH,
|
||||||
GL_PACK_ROW_LENGTH,
|
dst.rowPitch / texture->GetFormat().blockByteSize);
|
||||||
dst.rowPitch / TextureFormatTexelBlockSizeInBytes(texture->GetFormat()));
|
|
||||||
gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, dst.imageHeight);
|
gl.PixelStorei(GL_PACK_IMAGE_HEIGHT, dst.imageHeight);
|
||||||
ASSERT(copySize.depth == 1 && src.origin.z == 0);
|
ASSERT(copySize.depth == 1 && src.origin.z == 0);
|
||||||
void* offset = reinterpret_cast<void*>(static_cast<uintptr_t>(dst.offset));
|
void* offset = reinterpret_cast<void*>(static_cast<uintptr_t>(dst.offset));
|
||||||
|
@ -582,7 +580,7 @@ namespace dawn_native { namespace opengl {
|
||||||
|
|
||||||
// TODO(kainino@chromium.org): the color clears (later in
|
// TODO(kainino@chromium.org): the color clears (later in
|
||||||
// this function) may be undefined for non-normalized integer formats.
|
// this function) may be undefined for non-normalized integer formats.
|
||||||
dawn::TextureFormat format = textureView->GetTexture()->GetFormat();
|
dawn::TextureFormat format = textureView->GetTexture()->GetFormat().format;
|
||||||
ASSERT(format == dawn::TextureFormat::RGBA8Unorm ||
|
ASSERT(format == dawn::TextureFormat::RGBA8Unorm ||
|
||||||
format == dawn::TextureFormat::RG8Unorm ||
|
format == dawn::TextureFormat::RG8Unorm ||
|
||||||
format == dawn::TextureFormat::R8Unorm ||
|
format == dawn::TextureFormat::R8Unorm ||
|
||||||
|
@ -593,20 +591,25 @@ namespace dawn_native { namespace opengl {
|
||||||
if (renderPass->hasDepthStencilAttachment) {
|
if (renderPass->hasDepthStencilAttachment) {
|
||||||
TextureViewBase* textureView = renderPass->depthStencilAttachment.view.Get();
|
TextureViewBase* textureView = renderPass->depthStencilAttachment.view.Get();
|
||||||
GLuint texture = ToBackend(textureView->GetTexture())->GetHandle();
|
GLuint texture = ToBackend(textureView->GetTexture())->GetHandle();
|
||||||
dawn::TextureFormat format = textureView->GetTexture()->GetFormat();
|
const Format& format = textureView->GetTexture()->GetFormat();
|
||||||
|
|
||||||
// Attach depth/stencil buffer.
|
// Attach depth/stencil buffer.
|
||||||
GLenum glAttachment = 0;
|
GLenum glAttachment = 0;
|
||||||
// TODO(kainino@chromium.org): it may be valid to just always use
|
// TODO(kainino@chromium.org): it may be valid to just always use
|
||||||
// GL_DEPTH_STENCIL_ATTACHMENT here.
|
// GL_DEPTH_STENCIL_ATTACHMENT here.
|
||||||
if (TextureFormatHasDepth(format)) {
|
switch (format.aspect) {
|
||||||
if (TextureFormatHasStencil(format)) {
|
case Format::Aspect::Depth:
|
||||||
glAttachment = GL_DEPTH_STENCIL_ATTACHMENT;
|
|
||||||
} else {
|
|
||||||
glAttachment = GL_DEPTH_ATTACHMENT;
|
glAttachment = GL_DEPTH_ATTACHMENT;
|
||||||
}
|
break;
|
||||||
} else {
|
case Format::Aspect::Stencil:
|
||||||
glAttachment = GL_STENCIL_ATTACHMENT;
|
glAttachment = GL_STENCIL_ATTACHMENT;
|
||||||
|
break;
|
||||||
|
case Format::Aspect::DepthStencil:
|
||||||
|
glAttachment = GL_DEPTH_STENCIL_ATTACHMENT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLenum target = ToBackend(textureView->GetTexture())->GetGLTarget();
|
GLenum target = ToBackend(textureView->GetTexture())->GetGLTarget();
|
||||||
|
@ -614,7 +617,7 @@ namespace dawn_native { namespace opengl {
|
||||||
|
|
||||||
// TODO(kainino@chromium.org): the depth/stencil clears (later in
|
// TODO(kainino@chromium.org): the depth/stencil clears (later in
|
||||||
// this function) may be undefined for other texture formats.
|
// this function) may be undefined for other texture formats.
|
||||||
ASSERT(format == dawn::TextureFormat::Depth24PlusStencil8);
|
ASSERT(format.format == dawn::TextureFormat::Depth24PlusStencil8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,20 +642,19 @@ namespace dawn_native { namespace opengl {
|
||||||
|
|
||||||
if (renderPass->hasDepthStencilAttachment) {
|
if (renderPass->hasDepthStencilAttachment) {
|
||||||
const auto& attachmentInfo = renderPass->depthStencilAttachment;
|
const auto& attachmentInfo = renderPass->depthStencilAttachment;
|
||||||
dawn::TextureFormat attachmentFormat =
|
const Format& attachmentFormat = attachmentInfo.view->GetTexture()->GetFormat();
|
||||||
attachmentInfo.view->GetTexture()->GetFormat();
|
|
||||||
|
|
||||||
// Load op - depth/stencil
|
// Load op - depth/stencil
|
||||||
bool doDepthClear = TextureFormatHasDepth(attachmentFormat) &&
|
bool doDepthClear = attachmentFormat.HasDepth() &&
|
||||||
(attachmentInfo.depthLoadOp == dawn::LoadOp::Clear);
|
(attachmentInfo.depthLoadOp == dawn::LoadOp::Clear);
|
||||||
bool doStencilClear = TextureFormatHasStencil(attachmentFormat) &&
|
bool doStencilClear = attachmentFormat.HasStencil() &&
|
||||||
(attachmentInfo.stencilLoadOp == dawn::LoadOp::Clear);
|
(attachmentInfo.stencilLoadOp == dawn::LoadOp::Clear);
|
||||||
|
|
||||||
if (doDepthClear) {
|
if (doDepthClear) {
|
||||||
gl.DepthMask(GL_TRUE);
|
gl.DepthMask(GL_TRUE);
|
||||||
}
|
}
|
||||||
if (doStencilClear) {
|
if (doStencilClear) {
|
||||||
gl.StencilMask(GetStencilMaskFromStencilFormat(attachmentFormat));
|
gl.StencilMask(GetStencilMaskFromStencilFormat(attachmentFormat.format));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doDepthClear && doStencilClear) {
|
if (doDepthClear && doStencilClear) {
|
||||||
|
|
|
@ -102,7 +102,7 @@ namespace dawn_native { namespace opengl {
|
||||||
|
|
||||||
bool RequiresCreatingNewTextureView(const TextureBase* texture,
|
bool RequiresCreatingNewTextureView(const TextureBase* texture,
|
||||||
const TextureViewDescriptor* textureViewDescriptor) {
|
const TextureViewDescriptor* textureViewDescriptor) {
|
||||||
if (texture->GetFormat() != textureViewDescriptor->format) {
|
if (texture->GetFormat().format != textureViewDescriptor->format) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ namespace dawn_native { namespace opengl {
|
||||||
uint32_t arrayLayers = GetArrayLayers();
|
uint32_t arrayLayers = GetArrayLayers();
|
||||||
uint32_t sampleCount = GetSampleCount();
|
uint32_t sampleCount = GetSampleCount();
|
||||||
|
|
||||||
auto formatInfo = GetGLFormatInfo(GetFormat());
|
auto formatInfo = GetGLFormatInfo(GetFormat().format);
|
||||||
|
|
||||||
gl.BindTexture(mTarget, mHandle);
|
gl.BindTexture(mTarget, mHandle);
|
||||||
|
|
||||||
|
@ -171,7 +171,7 @@ namespace dawn_native { namespace opengl {
|
||||||
|
|
||||||
if (GetDevice()->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
|
if (GetDevice()->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
|
||||||
static constexpr uint32_t MAX_TEXEL_SIZE = 16;
|
static constexpr uint32_t MAX_TEXEL_SIZE = 16;
|
||||||
ASSERT(TextureFormatTexelBlockSizeInBytes(GetFormat()) <= MAX_TEXEL_SIZE);
|
ASSERT(GetFormat().blockByteSize <= MAX_TEXEL_SIZE);
|
||||||
GLubyte clearColor[MAX_TEXEL_SIZE];
|
GLubyte clearColor[MAX_TEXEL_SIZE];
|
||||||
std::fill(clearColor, clearColor + MAX_TEXEL_SIZE, 255);
|
std::fill(clearColor, clearColor + MAX_TEXEL_SIZE, 255);
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@ namespace dawn_native { namespace opengl {
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureFormatInfo Texture::GetGLFormat() const {
|
TextureFormatInfo Texture::GetGLFormat() const {
|
||||||
return GetGLFormatInfo(GetFormat());
|
return GetGLFormatInfo(GetFormat().format);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TextureView
|
// TextureView
|
||||||
|
|
|
@ -50,8 +50,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
region.bufferOffset = bufferCopy.offset;
|
region.bufferOffset = bufferCopy.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
|
||||||
region.bufferRowLength =
|
region.bufferRowLength = bufferCopy.rowPitch / texture->GetFormat().blockByteSize;
|
||||||
bufferCopy.rowPitch / TextureFormatTexelBlockSizeInBytes(texture->GetFormat());
|
|
||||||
region.bufferImageHeight = bufferCopy.imageHeight;
|
region.bufferImageHeight = bufferCopy.imageHeight;
|
||||||
|
|
||||||
region.imageSubresource.aspectMask = texture->GetVkAspectMask();
|
region.imageSubresource.aspectMask = texture->GetVkAspectMask();
|
||||||
|
@ -190,12 +189,13 @@ namespace dawn_native { namespace vulkan {
|
||||||
default: { UNREACHABLE(); } break;
|
default: { UNREACHABLE(); } break;
|
||||||
}
|
}
|
||||||
|
|
||||||
query.SetColor(i, attachmentInfo.view->GetFormat(), loadOp, hasResolveTarget);
|
query.SetColor(i, attachmentInfo.view->GetFormat().format, loadOp,
|
||||||
|
hasResolveTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (renderPass->hasDepthStencilAttachment) {
|
if (renderPass->hasDepthStencilAttachment) {
|
||||||
auto& attachmentInfo = renderPass->depthStencilAttachment;
|
auto& attachmentInfo = renderPass->depthStencilAttachment;
|
||||||
query.SetDepthStencil(attachmentInfo.view->GetTexture()->GetFormat(),
|
query.SetDepthStencil(attachmentInfo.view->GetTexture()->GetFormat().format,
|
||||||
attachmentInfo.depthLoadOp, attachmentInfo.stencilLoadOp);
|
attachmentInfo.depthLoadOp, attachmentInfo.stencilLoadOp);
|
||||||
if (attachmentInfo.depthLoadOp == dawn::LoadOp::Load ||
|
if (attachmentInfo.depthLoadOp == dawn::LoadOp::Load ||
|
||||||
attachmentInfo.stencilLoadOp == dawn::LoadOp::Load) {
|
attachmentInfo.stencilLoadOp == dawn::LoadOp::Load) {
|
||||||
|
|
|
@ -92,8 +92,8 @@ namespace dawn_native { namespace vulkan {
|
||||||
createInfo.imageExtent.width = width;
|
createInfo.imageExtent.width = width;
|
||||||
createInfo.imageExtent.height = height;
|
createInfo.imageExtent.height = height;
|
||||||
createInfo.imageArrayLayers = 1;
|
createInfo.imageArrayLayers = 1;
|
||||||
createInfo.imageUsage =
|
createInfo.imageUsage = VulkanImageUsage(static_cast<dawn::TextureUsageBit>(usage),
|
||||||
VulkanImageUsage(static_cast<dawn::TextureUsageBit>(usage), mConfig.format);
|
ConvertValidFormat(mConfig.format));
|
||||||
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
|
||||||
createInfo.queueFamilyIndexCount = 0;
|
createInfo.queueFamilyIndexCount = 0;
|
||||||
createInfo.pQueueFamilyIndices = nullptr;
|
createInfo.pQueueFamilyIndices = nullptr;
|
||||||
|
|
|
@ -51,7 +51,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Computes which vulkan access type could be required for the given Dawn usage.
|
// Computes which vulkan access type could be required for the given Dawn usage.
|
||||||
VkAccessFlags VulkanAccessFlags(dawn::TextureUsageBit usage, dawn::TextureFormat format) {
|
VkAccessFlags VulkanAccessFlags(dawn::TextureUsageBit usage, const Format& format) {
|
||||||
VkAccessFlags flags = 0;
|
VkAccessFlags flags = 0;
|
||||||
|
|
||||||
if (usage & dawn::TextureUsageBit::TransferSrc) {
|
if (usage & dawn::TextureUsageBit::TransferSrc) {
|
||||||
|
@ -67,7 +67,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
|
flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
|
||||||
}
|
}
|
||||||
if (usage & dawn::TextureUsageBit::OutputAttachment) {
|
if (usage & dawn::TextureUsageBit::OutputAttachment) {
|
||||||
if (TextureFormatHasDepthOrStencil(format)) {
|
if (format.HasDepthOrStencil()) {
|
||||||
flags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
flags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
|
||||||
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
|
||||||
} else {
|
} else {
|
||||||
|
@ -88,7 +88,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chooses which Vulkan image layout should be used for the given Dawn usage
|
// Chooses which Vulkan image layout should be used for the given Dawn usage
|
||||||
VkImageLayout VulkanImageLayout(dawn::TextureUsageBit usage, dawn::TextureFormat format) {
|
VkImageLayout VulkanImageLayout(dawn::TextureUsageBit usage, const Format& format) {
|
||||||
if (usage == dawn::TextureUsageBit::None) {
|
if (usage == dawn::TextureUsageBit::None) {
|
||||||
return VK_IMAGE_LAYOUT_UNDEFINED;
|
return VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
}
|
}
|
||||||
|
@ -114,7 +114,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
case dawn::TextureUsageBit::Storage:
|
case dawn::TextureUsageBit::Storage:
|
||||||
return VK_IMAGE_LAYOUT_GENERAL;
|
return VK_IMAGE_LAYOUT_GENERAL;
|
||||||
case dawn::TextureUsageBit::OutputAttachment:
|
case dawn::TextureUsageBit::OutputAttachment:
|
||||||
if (TextureFormatHasDepthOrStencil(format)) {
|
if (format.HasDepthOrStencil()) {
|
||||||
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||||
} else {
|
} else {
|
||||||
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
|
@ -128,7 +128,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
// Computes which Vulkan pipeline stage can access a texture in the given Dawn usage
|
// Computes which Vulkan pipeline stage can access a texture in the given Dawn usage
|
||||||
VkPipelineStageFlags VulkanPipelineStage(dawn::TextureUsageBit usage,
|
VkPipelineStageFlags VulkanPipelineStage(dawn::TextureUsageBit usage,
|
||||||
dawn::TextureFormat format) {
|
const Format& format) {
|
||||||
VkPipelineStageFlags flags = 0;
|
VkPipelineStageFlags flags = 0;
|
||||||
|
|
||||||
if (usage == dawn::TextureUsageBit::None) {
|
if (usage == dawn::TextureUsageBit::None) {
|
||||||
|
@ -145,7 +145,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
|
||||||
}
|
}
|
||||||
if (usage & dawn::TextureUsageBit::OutputAttachment) {
|
if (usage & dawn::TextureUsageBit::OutputAttachment) {
|
||||||
if (TextureFormatHasDepthOrStencil(format)) {
|
if (format.HasDepthOrStencil()) {
|
||||||
flags |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
flags |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
|
||||||
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
|
||||||
// TODO(cwallez@chromium.org): This is missing the stage where the depth and
|
// TODO(cwallez@chromium.org): This is missing the stage where the depth and
|
||||||
|
@ -170,22 +170,20 @@ namespace dawn_native { namespace vulkan {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Computes which Vulkan texture aspects are relevant for the given Dawn format
|
// Computes which Vulkan texture aspects are relevant for the given Dawn format
|
||||||
VkImageAspectFlags VulkanAspectMask(dawn::TextureFormat format) {
|
VkImageAspectFlags VulkanAspectMask(const Format& format) {
|
||||||
bool isDepth = TextureFormatHasDepth(format);
|
switch (format.aspect) {
|
||||||
bool isStencil = TextureFormatHasStencil(format);
|
case Format::Aspect::Color:
|
||||||
|
|
||||||
VkImageAspectFlags flags = 0;
|
|
||||||
if (isDepth) {
|
|
||||||
flags |= VK_IMAGE_ASPECT_DEPTH_BIT;
|
|
||||||
}
|
|
||||||
if (isStencil) {
|
|
||||||
flags |= VK_IMAGE_ASPECT_STENCIL_BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags != 0) {
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
return VK_IMAGE_ASPECT_COLOR_BIT;
|
return VK_IMAGE_ASPECT_COLOR_BIT;
|
||||||
|
case Format::Aspect::Depth:
|
||||||
|
return VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
case Format::Aspect::Stencil:
|
||||||
|
return VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||||
|
case Format::Aspect::DepthStencil:
|
||||||
|
return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkExtent3D VulkanExtent3D(const Extent3D& extent) {
|
VkExtent3D VulkanExtent3D(const Extent3D& extent) {
|
||||||
|
@ -236,7 +234,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
// Converts the Dawn usage flags to Vulkan usage flags. Also needs the format to choose
|
// Converts the Dawn usage flags to Vulkan usage flags. Also needs the format to choose
|
||||||
// between color and depth attachment usages.
|
// between color and depth attachment usages.
|
||||||
VkImageUsageFlags VulkanImageUsage(dawn::TextureUsageBit usage, dawn::TextureFormat format) {
|
VkImageUsageFlags VulkanImageUsage(dawn::TextureUsageBit usage, const Format& format) {
|
||||||
VkImageUsageFlags flags = 0;
|
VkImageUsageFlags flags = 0;
|
||||||
|
|
||||||
if (usage & dawn::TextureUsageBit::TransferSrc) {
|
if (usage & dawn::TextureUsageBit::TransferSrc) {
|
||||||
|
@ -252,7 +250,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
flags |= VK_IMAGE_USAGE_STORAGE_BIT;
|
flags |= VK_IMAGE_USAGE_STORAGE_BIT;
|
||||||
}
|
}
|
||||||
if (usage & dawn::TextureUsageBit::OutputAttachment) {
|
if (usage & dawn::TextureUsageBit::OutputAttachment) {
|
||||||
if (TextureFormatHasDepthOrStencil(format)) {
|
if (format.HasDepthOrStencil()) {
|
||||||
flags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
flags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
||||||
} else {
|
} else {
|
||||||
flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||||
|
@ -283,7 +281,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
createInfo.pNext = nullptr;
|
createInfo.pNext = nullptr;
|
||||||
createInfo.flags = 0;
|
createInfo.flags = 0;
|
||||||
createInfo.imageType = VulkanImageType(GetDimension());
|
createInfo.imageType = VulkanImageType(GetDimension());
|
||||||
createInfo.format = VulkanImageFormat(GetFormat());
|
createInfo.format = VulkanImageFormat(GetFormat().format);
|
||||||
createInfo.extent = VulkanExtent3D(GetSize());
|
createInfo.extent = VulkanExtent3D(GetSize());
|
||||||
createInfo.mipLevels = GetNumMipLevels();
|
createInfo.mipLevels = GetNumMipLevels();
|
||||||
createInfo.arrayLayers = GetArrayLayers();
|
createInfo.arrayLayers = GetArrayLayers();
|
||||||
|
@ -334,7 +332,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
TransitionUsageNow(ToBackend(GetDevice())->GetPendingCommandBuffer(),
|
TransitionUsageNow(ToBackend(GetDevice())->GetPendingCommandBuffer(),
|
||||||
dawn::TextureUsageBit::TransferDst);
|
dawn::TextureUsageBit::TransferDst);
|
||||||
|
|
||||||
if (TextureFormatHasDepthOrStencil(GetFormat())) {
|
if (GetFormat().HasDepthOrStencil()) {
|
||||||
VkClearDepthStencilValue clear_color[1];
|
VkClearDepthStencilValue clear_color[1];
|
||||||
clear_color[0].depth = 1.0f;
|
clear_color[0].depth = 1.0f;
|
||||||
clear_color[0].stencil = 1u;
|
clear_color[0].stencil = 1u;
|
||||||
|
@ -396,7 +394,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dawn::TextureFormat format = GetFormat();
|
const Format& format = GetFormat();
|
||||||
|
|
||||||
VkPipelineStageFlags srcStages = VulkanPipelineStage(mLastUsage, format);
|
VkPipelineStageFlags srcStages = VulkanPipelineStage(mLastUsage, format);
|
||||||
VkPipelineStageFlags dstStages = VulkanPipelineStage(usage, format);
|
VkPipelineStageFlags dstStages = VulkanPipelineStage(usage, format);
|
||||||
|
@ -439,7 +437,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
range.layerCount = layerCount;
|
range.layerCount = layerCount;
|
||||||
|
|
||||||
TransitionUsageNow(commands, dawn::TextureUsageBit::TransferDst);
|
TransitionUsageNow(commands, dawn::TextureUsageBit::TransferDst);
|
||||||
if (TextureFormatHasDepthOrStencil(GetFormat())) {
|
if (GetFormat().HasDepthOrStencil()) {
|
||||||
VkClearDepthStencilValue clear_color[1];
|
VkClearDepthStencilValue clear_color[1];
|
||||||
clear_color[0].depth = 0.0f;
|
clear_color[0].depth = 0.0f;
|
||||||
clear_color[0].stencil = 0u;
|
clear_color[0].stencil = 0u;
|
||||||
|
@ -490,7 +488,7 @@ namespace dawn_native { namespace vulkan {
|
||||||
createInfo.format = VulkanImageFormat(descriptor->format);
|
createInfo.format = VulkanImageFormat(descriptor->format);
|
||||||
createInfo.components = VkComponentMapping{VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
|
createInfo.components = VkComponentMapping{VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
|
||||||
VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
|
VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
|
||||||
createInfo.subresourceRange.aspectMask = VulkanAspectMask(descriptor->format);
|
createInfo.subresourceRange.aspectMask = VulkanAspectMask(GetFormat());
|
||||||
createInfo.subresourceRange.baseMipLevel = descriptor->baseMipLevel;
|
createInfo.subresourceRange.baseMipLevel = descriptor->baseMipLevel;
|
||||||
createInfo.subresourceRange.levelCount = descriptor->mipLevelCount;
|
createInfo.subresourceRange.levelCount = descriptor->mipLevelCount;
|
||||||
createInfo.subresourceRange.baseArrayLayer = descriptor->baseArrayLayer;
|
createInfo.subresourceRange.baseArrayLayer = descriptor->baseArrayLayer;
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
namespace dawn_native { namespace vulkan {
|
namespace dawn_native { namespace vulkan {
|
||||||
|
|
||||||
VkFormat VulkanImageFormat(dawn::TextureFormat format);
|
VkFormat VulkanImageFormat(dawn::TextureFormat format);
|
||||||
VkImageUsageFlags VulkanImageUsage(dawn::TextureUsageBit usage, dawn::TextureFormat format);
|
VkImageUsageFlags VulkanImageUsage(dawn::TextureUsageBit usage, const Format& format);
|
||||||
VkSampleCountFlagBits VulkanSampleCount(uint32_t sampleCount);
|
VkSampleCountFlagBits VulkanSampleCount(uint32_t sampleCount);
|
||||||
|
|
||||||
class Texture : public TextureBase {
|
class Texture : public TextureBase {
|
||||||
|
|
Loading…
Reference in New Issue