OpenGL: clear nonrenderable texture formats
Clears nonrenderable color formats and merges zero vs nonzero clears to use the same code path. Bug: dawn:145 Change-Id: I8f2f36134b56787e07231d82e37c36897ba1d4ba Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/10820 Commit-Queue: Natasha Lee <natlee@microsoft.com> Reviewed-by: Kai Ninomiya <kainino@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
parent
be990077f4
commit
617e356580
|
@ -552,22 +552,28 @@ namespace dawn_native { namespace d3d12 {
|
|||
Extent3D copySize = {GetSize().width, GetSize().height, 1};
|
||||
TextureCopySplit copySplit = ComputeTextureCopySplit(
|
||||
{0, 0, 0}, copySize, GetFormat(), uploadHandle.startOffset, rowPitch, 0);
|
||||
D3D12_TEXTURE_COPY_LOCATION textureLocation =
|
||||
ComputeTextureCopyLocationForTexture(this, baseMipLevel, baseArrayLayer);
|
||||
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
||||
TextureCopySplit::CopyInfo& info = copySplit.copies[i];
|
||||
|
||||
D3D12_TEXTURE_COPY_LOCATION bufferLocation =
|
||||
ComputeBufferLocationForCopyTextureRegion(
|
||||
this, ToBackend(uploadHandle.stagingBuffer)->GetResource(), info.bufferSize,
|
||||
copySplit.offset, rowPitch);
|
||||
D3D12_BOX sourceRegion =
|
||||
ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
|
||||
for (uint32_t level = baseMipLevel; level < baseMipLevel + levelCount; ++level) {
|
||||
for (uint32_t layer = baseArrayLayer; layer < baseArrayLayer + layerCount;
|
||||
++layer) {
|
||||
D3D12_TEXTURE_COPY_LOCATION textureLocation =
|
||||
ComputeTextureCopyLocationForTexture(this, level, layer);
|
||||
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
||||
TextureCopySplit::CopyInfo& info = copySplit.copies[i];
|
||||
|
||||
// copy the buffer filled with clear color to the texture
|
||||
commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x,
|
||||
info.textureOffset.y, info.textureOffset.z,
|
||||
&bufferLocation, &sourceRegion);
|
||||
D3D12_TEXTURE_COPY_LOCATION bufferLocation =
|
||||
ComputeBufferLocationForCopyTextureRegion(
|
||||
this, ToBackend(uploadHandle.stagingBuffer)->GetResource(),
|
||||
info.bufferSize, copySplit.offset, rowPitch);
|
||||
D3D12_BOX sourceRegion =
|
||||
ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
|
||||
|
||||
// copy the buffer filled with clear color to the texture
|
||||
commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x,
|
||||
info.textureOffset.y, info.textureOffset.z,
|
||||
&bufferLocation, &sourceRegion);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clearValue == TextureBase::ClearValue::Zero) {
|
||||
|
|
|
@ -457,22 +457,20 @@ namespace dawn_native { namespace opengl {
|
|||
gl.BindTexture(target, texture->GetHandle());
|
||||
|
||||
const Format& formatInfo = texture->GetFormat();
|
||||
gl.PixelStorei(
|
||||
GL_UNPACK_ROW_LENGTH,
|
||||
src.rowPitch / texture->GetFormat().blockByteSize * formatInfo.blockWidth);
|
||||
gl.PixelStorei(GL_UNPACK_ROW_LENGTH,
|
||||
src.rowPitch / formatInfo.blockByteSize * formatInfo.blockWidth);
|
||||
gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, src.imageHeight);
|
||||
|
||||
if (texture->GetFormat().isCompressed) {
|
||||
if (formatInfo.isCompressed) {
|
||||
gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_SIZE, formatInfo.blockByteSize);
|
||||
gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_WIDTH, formatInfo.blockWidth);
|
||||
gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_HEIGHT, formatInfo.blockHeight);
|
||||
gl.PixelStorei(GL_UNPACK_COMPRESSED_BLOCK_DEPTH, 1);
|
||||
|
||||
ASSERT(texture->GetDimension() == dawn::TextureDimension::e2D);
|
||||
uint64_t copyDataSize =
|
||||
(copySize.width / texture->GetFormat().blockWidth) *
|
||||
(copySize.height / texture->GetFormat().blockHeight) *
|
||||
texture->GetFormat().blockByteSize;
|
||||
uint64_t copyDataSize = (copySize.width / formatInfo.blockWidth) *
|
||||
(copySize.height / formatInfo.blockHeight) *
|
||||
formatInfo.blockByteSize;
|
||||
Extent3D copyExtent = ComputeTextureCopyExtent(dst, copySize);
|
||||
|
||||
if (texture->GetArrayLayers() > 1) {
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#include "dawn_native/opengl/TextureGL.h"
|
||||
|
||||
#include "common/Assert.h"
|
||||
#include "common/Constants.h"
|
||||
#include "common/Math.h"
|
||||
#include "dawn_native/opengl/BufferGL.h"
|
||||
#include "dawn_native/opengl/DeviceGL.h"
|
||||
#include "dawn_native/opengl/UtilsGL.h"
|
||||
|
||||
|
@ -142,14 +145,8 @@ namespace dawn_native { namespace opengl {
|
|||
gl.TexParameteri(mTarget, GL_TEXTURE_MAX_LEVEL, levels - 1);
|
||||
|
||||
if (GetDevice()->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
|
||||
static constexpr uint32_t MAX_TEXEL_SIZE = 16;
|
||||
ASSERT(GetFormat().blockByteSize <= MAX_TEXEL_SIZE);
|
||||
GLubyte clearColor[MAX_TEXEL_SIZE];
|
||||
std::fill(clearColor, clearColor + MAX_TEXEL_SIZE, 255);
|
||||
// TODO(natlee@microsoft.com): clear all subresources
|
||||
for (uint32_t i = 0; i < GetNumMipLevels(); i++) {
|
||||
gl.ClearTexImage(mHandle, i, glFormat.format, glFormat.type, clearColor);
|
||||
}
|
||||
GetDevice()->ConsumedError(ClearTexture(0, GetNumMipLevels(), 0, GetArrayLayers(),
|
||||
TextureBase::ClearValue::NonZero));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,50 +179,123 @@ namespace dawn_native { namespace opengl {
|
|||
return ToBackend(GetDevice())->GetGLFormat(GetFormat());
|
||||
}
|
||||
|
||||
void Texture::ClearTexture(GLint baseMipLevel,
|
||||
GLint levelCount,
|
||||
GLint baseArrayLayer,
|
||||
uint32_t layerCount) {
|
||||
const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
|
||||
MaybeError Texture::ClearTexture(GLint baseMipLevel,
|
||||
GLint levelCount,
|
||||
GLint baseArrayLayer,
|
||||
uint32_t layerCount,
|
||||
TextureBase::ClearValue clearValue) {
|
||||
// TODO(jiawei.shao@intel.com): initialize the textures with compressed formats.
|
||||
if (GetFormat().isCompressed) {
|
||||
return;
|
||||
return {};
|
||||
}
|
||||
|
||||
if (GetFormat().HasDepthOrStencil()) {
|
||||
bool doDepthClear = GetFormat().HasDepth();
|
||||
bool doStencilClear = GetFormat().HasStencil();
|
||||
GLfloat depth = 0.0f;
|
||||
GLint stencil = 0u;
|
||||
if (doDepthClear) {
|
||||
gl.DepthMask(GL_TRUE);
|
||||
}
|
||||
if (doStencilClear) {
|
||||
gl.StencilMask(GetStencilMaskFromStencilFormat(GetFormat().format));
|
||||
}
|
||||
Device* device = ToBackend(GetDevice());
|
||||
const OpenGLFunctions& gl = device->gl;
|
||||
uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
|
||||
if (GetFormat().isRenderable) {
|
||||
if (GetFormat().HasDepthOrStencil()) {
|
||||
bool doDepthClear = GetFormat().HasDepth();
|
||||
bool doStencilClear = GetFormat().HasStencil();
|
||||
GLfloat depth = clearColor;
|
||||
GLint stencil = clearColor;
|
||||
if (doDepthClear) {
|
||||
gl.DepthMask(GL_TRUE);
|
||||
}
|
||||
if (doStencilClear) {
|
||||
gl.StencilMask(GetStencilMaskFromStencilFormat(GetFormat().format));
|
||||
}
|
||||
|
||||
GLuint framebuffer = 0;
|
||||
gl.GenFramebuffers(1, &framebuffer);
|
||||
gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
|
||||
gl.FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GetGLTarget(),
|
||||
GetHandle(), 0);
|
||||
if (doDepthClear && doStencilClear) {
|
||||
gl.ClearBufferfi(GL_DEPTH_STENCIL, 0, depth, stencil);
|
||||
} else if (doDepthClear) {
|
||||
gl.ClearBufferfv(GL_DEPTH, 0, &depth);
|
||||
} else if (doStencilClear) {
|
||||
gl.ClearBufferiv(GL_STENCIL, 0, &stencil);
|
||||
GLuint framebuffer = 0;
|
||||
gl.GenFramebuffers(1, &framebuffer);
|
||||
gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);
|
||||
// TODO(natlee@microsoft.com): clear all mip levels and array layers.
|
||||
gl.FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
||||
GetGLTarget(), GetHandle(), 0);
|
||||
if (doDepthClear && doStencilClear) {
|
||||
gl.ClearBufferfi(GL_DEPTH_STENCIL, 0, depth, stencil);
|
||||
} else if (doDepthClear) {
|
||||
gl.ClearBufferfv(GL_DEPTH, 0, &depth);
|
||||
} else if (doStencilClear) {
|
||||
gl.ClearBufferiv(GL_STENCIL, 0, &stencil);
|
||||
}
|
||||
gl.DeleteFramebuffers(1, &framebuffer);
|
||||
} else {
|
||||
static constexpr uint32_t MAX_TEXEL_SIZE = 16;
|
||||
ASSERT(GetFormat().blockByteSize <= MAX_TEXEL_SIZE);
|
||||
std::array<GLbyte, MAX_TEXEL_SIZE> clearColorData;
|
||||
clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 255;
|
||||
clearColorData.fill(clearColor);
|
||||
|
||||
const GLFormat& glFormat = GetGLFormat();
|
||||
for (GLint level = baseMipLevel; level < baseMipLevel + levelCount; ++level) {
|
||||
Extent3D mipSize = GetMipLevelPhysicalSize(level);
|
||||
gl.ClearTexSubImage(mHandle, level, 0, 0, baseArrayLayer, mipSize.width,
|
||||
mipSize.height, layerCount, glFormat.format, glFormat.type,
|
||||
clearColorData.data());
|
||||
}
|
||||
}
|
||||
gl.DeleteFramebuffers(1, &framebuffer);
|
||||
} else {
|
||||
const GLFormat& glFormat = GetGLFormat();
|
||||
// TODO(natlee@microsoft.com): test compressed textures are cleared
|
||||
// create temp buffer with clear color to copy to the texture image
|
||||
ASSERT(kTextureRowPitchAlignment % GetFormat().blockByteSize == 0);
|
||||
uint32_t rowPitch =
|
||||
Align((GetSize().width / GetFormat().blockWidth) * GetFormat().blockByteSize,
|
||||
kTextureRowPitchAlignment);
|
||||
|
||||
// Make sure that we are not rounding
|
||||
ASSERT(rowPitch % GetFormat().blockByteSize == 0);
|
||||
ASSERT(GetSize().height % GetFormat().blockHeight == 0);
|
||||
|
||||
dawn_native::BufferDescriptor descriptor;
|
||||
descriptor.size = rowPitch * (GetSize().height / GetFormat().blockHeight);
|
||||
if (descriptor.size > std::numeric_limits<uint32_t>::max()) {
|
||||
return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
|
||||
}
|
||||
descriptor.nextInChain = nullptr;
|
||||
descriptor.usage = dawn::BufferUsage::CopySrc | dawn::BufferUsage::MapWrite;
|
||||
// TODO(natlee@microsoft.com): use Dynamic Uplaoder here for temp buffer
|
||||
Ref<Buffer> srcBuffer = ToBackend(device->CreateBuffer(&descriptor));
|
||||
// Call release here to prevent memory leak since CreateBuffer will up the ref count to
|
||||
// 1, then assigning to Ref<Buffer> ups the ref count to 2. Release will reduce the ref
|
||||
// count and ensure it to reach 0 when out of use.
|
||||
srcBuffer->Release();
|
||||
|
||||
// Fill the buffer with clear color
|
||||
uint8_t* clearBuffer = nullptr;
|
||||
DAWN_TRY(srcBuffer->MapAtCreation(&clearBuffer));
|
||||
std::fill(reinterpret_cast<uint32_t*>(clearBuffer),
|
||||
reinterpret_cast<uint32_t*>(clearBuffer + descriptor.size), clearColor);
|
||||
srcBuffer->Unmap();
|
||||
|
||||
// Bind buffer and texture, and make the buffer to texture copy
|
||||
gl.PixelStorei(GL_UNPACK_ROW_LENGTH,
|
||||
(rowPitch / GetFormat().blockByteSize) * GetFormat().blockWidth);
|
||||
gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
|
||||
for (GLint level = baseMipLevel; level < baseMipLevel + levelCount; ++level) {
|
||||
Extent3D mipSize = GetMipLevelPhysicalSize(level);
|
||||
gl.ClearTexSubImage(mHandle, level, 0, 0, baseArrayLayer, mipSize.width,
|
||||
mipSize.height, layerCount, glFormat.format, glFormat.type,
|
||||
nullptr);
|
||||
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, srcBuffer->GetHandle());
|
||||
gl.ActiveTexture(GL_TEXTURE0);
|
||||
gl.BindTexture(GetGLTarget(), GetHandle());
|
||||
|
||||
Extent3D size = GetMipLevelPhysicalSize(level);
|
||||
switch (GetDimension()) {
|
||||
case dawn::TextureDimension::e2D:
|
||||
// TODO(natlee@microsoft.com): This will break when layerCount is greater
|
||||
// than 1, because the buffer is only sized for one layer.
|
||||
ASSERT(layerCount == 1);
|
||||
gl.TexSubImage2D(GetGLTarget(), level, 0, 0, size.width, size.height,
|
||||
GetGLFormat().format, GetGLFormat().type, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
gl.PixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||
gl.PixelStorei(GL_UNPACK_IMAGE_HEIGHT, 0);
|
||||
|
||||
gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void Texture::EnsureSubresourceContentInitialized(uint32_t baseMipLevel,
|
||||
|
@ -238,7 +308,8 @@ namespace dawn_native { namespace opengl {
|
|||
}
|
||||
if (!IsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer,
|
||||
layerCount)) {
|
||||
ClearTexture(baseMipLevel, levelCount, baseArrayLayer, layerCount);
|
||||
GetDevice()->ConsumedError(ClearTexture(baseMipLevel, levelCount, baseArrayLayer,
|
||||
layerCount, TextureBase::ClearValue::Zero));
|
||||
if (isLazyClear) {
|
||||
GetDevice()->IncrementLazyClearCountForTesting();
|
||||
}
|
||||
|
|
|
@ -45,10 +45,11 @@ namespace dawn_native { namespace opengl {
|
|||
|
||||
private:
|
||||
void DestroyImpl() override;
|
||||
void ClearTexture(GLint baseMipLevel,
|
||||
GLint levelCount,
|
||||
GLint baseArrayLayer,
|
||||
uint32_t layerCount);
|
||||
MaybeError ClearTexture(GLint baseMipLevel,
|
||||
GLint levelCount,
|
||||
GLint baseArrayLayer,
|
||||
uint32_t layerCount,
|
||||
TextureBase::ClearValue clearValue);
|
||||
|
||||
GLuint mHandle;
|
||||
GLenum mTarget;
|
||||
|
|
|
@ -701,22 +701,27 @@ namespace dawn_native { namespace vulkan {
|
|||
bufferCopy.offset = uploadHandle.startOffset;
|
||||
bufferCopy.rowPitch = rowPitch;
|
||||
|
||||
dawn_native::TextureCopy textureCopy;
|
||||
textureCopy.texture = this;
|
||||
textureCopy.origin = {0, 0, 0};
|
||||
textureCopy.mipLevel = baseMipLevel;
|
||||
textureCopy.arrayLayer = baseArrayLayer;
|
||||
|
||||
Extent3D copySize = {GetSize().width, GetSize().height, 1};
|
||||
|
||||
VkBufferImageCopy region =
|
||||
ComputeBufferImageCopyRegion(bufferCopy, textureCopy, copySize);
|
||||
for (uint32_t level = baseMipLevel; level < baseMipLevel + levelCount; ++level) {
|
||||
for (uint32_t layer = baseArrayLayer; layer < baseArrayLayer + layerCount;
|
||||
++layer) {
|
||||
dawn_native::TextureCopy textureCopy;
|
||||
textureCopy.texture = this;
|
||||
textureCopy.origin = {0, 0, 0};
|
||||
textureCopy.mipLevel = level;
|
||||
textureCopy.arrayLayer = layer;
|
||||
|
||||
// copy the clear buffer to the texture image
|
||||
device->fn.CmdCopyBufferToImage(
|
||||
recordingContext->commandBuffer,
|
||||
ToBackend(uploadHandle.stagingBuffer)->GetBufferHandle(), GetHandle(),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
VkBufferImageCopy region =
|
||||
ComputeBufferImageCopyRegion(bufferCopy, textureCopy, copySize);
|
||||
|
||||
// copy the clear buffer to the texture image
|
||||
device->fn.CmdCopyBufferToImage(
|
||||
recordingContext->commandBuffer,
|
||||
ToBackend(uploadHandle.stagingBuffer)->GetBufferHandle(), GetHandle(),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (clearValue == TextureBase::ClearValue::Zero) {
|
||||
SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer,
|
||||
|
|
|
@ -96,8 +96,6 @@ TEST_P(NonzeroTextureCreationTests, ArrayLayerClears) {
|
|||
|
||||
// Test that nonrenderable texture formats clear to 1's because toggle is enabled
|
||||
TEST_P(NonzeroTextureCreationTests, NonrenderableTextureFormat) {
|
||||
// skip test for other backends since they are not implemented yet
|
||||
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||
dawn::TextureDescriptor descriptor;
|
||||
descriptor.dimension = dawn::TextureDimension::e2D;
|
||||
descriptor.size.width = kSize;
|
||||
|
@ -129,6 +127,44 @@ TEST_P(NonzeroTextureCreationTests, NonrenderableTextureFormat) {
|
|||
EXPECT_BUFFER_U32_RANGE_EQ(expected.data(), bufferDst, 0, 8);
|
||||
}
|
||||
|
||||
// Test that textures with more than 1 array layers and nonrenderable texture formats clear to 1's
|
||||
// because toggle is enabled
|
||||
TEST_P(NonzeroTextureCreationTests, NonRenderableTextureClearWithMultiArrayLayers) {
|
||||
// TODO(natlee@microsoft.com): skip for now on opengl because TextureClear nonrenderable
|
||||
// textures does not create large enough buffers for array layers greater than 1.
|
||||
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||
|
||||
dawn::TextureDescriptor descriptor;
|
||||
descriptor.dimension = dawn::TextureDimension::e2D;
|
||||
descriptor.size.width = kSize;
|
||||
descriptor.size.height = kSize;
|
||||
descriptor.size.depth = 1;
|
||||
descriptor.arrayLayerCount = 2;
|
||||
descriptor.sampleCount = 1;
|
||||
descriptor.format = dawn::TextureFormat::RGBA8Snorm;
|
||||
descriptor.mipLevelCount = 1;
|
||||
descriptor.usage = dawn::TextureUsage::CopySrc;
|
||||
dawn::Texture texture = device.CreateTexture(&descriptor);
|
||||
|
||||
// Set buffer with dirty data so we know it is cleared by the lazy cleared texture copy
|
||||
uint32_t bufferSize = 4 * kSize * kSize;
|
||||
std::vector<uint8_t> data(bufferSize, 100);
|
||||
dawn::Buffer bufferDst = utils::CreateBufferFromData(
|
||||
device, data.data(), static_cast<uint32_t>(data.size()), dawn::BufferUsage::CopySrc);
|
||||
|
||||
dawn::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(bufferDst, 0, 0, 0);
|
||||
dawn::TextureCopyView textureCopyView = utils::CreateTextureCopyView(texture, 0, 1, {0, 0, 0});
|
||||
dawn::Extent3D copySize = {kSize, kSize, 1};
|
||||
|
||||
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, ©Size);
|
||||
dawn::CommandBuffer commands = encoder.Finish();
|
||||
queue.Submit(1, &commands);
|
||||
|
||||
std::vector<uint32_t> expectedWithZeros(bufferSize, 1);
|
||||
EXPECT_BUFFER_U32_RANGE_EQ(expectedWithZeros.data(), bufferDst, 0, 8);
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(NonzeroTextureCreationTests,
|
||||
ForceWorkarounds(D3D12Backend,
|
||||
{"nonzero_clear_resources_on_creation_for_testing"},
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
#include "tests/DawnTest.h"
|
||||
|
||||
#include "common/Math.h"
|
||||
#include "utils/ComboRenderPipelineDescriptor.h"
|
||||
#include "utils/DawnHelpers.h"
|
||||
|
||||
|
@ -83,6 +84,10 @@ class TextureZeroInitTest : public DawnTest {
|
|||
return device.CreateRenderPipeline(&pipelineDescriptor);
|
||||
}
|
||||
constexpr static uint32_t kSize = 128;
|
||||
constexpr static uint32_t kUnalignedSize = 127;
|
||||
// All three texture formats used (RGBA8Unorm, Depth24PlusStencil8, and RGBA8Snorm) have the
|
||||
// same byte size of 4.
|
||||
constexpr static uint32_t kFormatBlockByteSize = 4;
|
||||
constexpr static dawn::TextureFormat kColorFormat = dawn::TextureFormat::RGBA8Unorm;
|
||||
constexpr static dawn::TextureFormat kDepthStencilFormat =
|
||||
dawn::TextureFormat::Depth24PlusStencil8;
|
||||
|
@ -165,7 +170,7 @@ TEST_P(TextureZeroInitTest, CopyBufferToTexture) {
|
|||
kColorFormat);
|
||||
dawn::Texture texture = device.CreateTexture(&descriptor);
|
||||
|
||||
std::vector<uint8_t> data(4 * kSize * kSize, 100);
|
||||
std::vector<uint8_t> data(kFormatBlockByteSize * kSize * kSize, 100);
|
||||
dawn::Buffer stagingBuffer = utils::CreateBufferFromData(
|
||||
device, data.data(), static_cast<uint32_t>(data.size()), dawn::BufferUsage::CopySrc);
|
||||
|
||||
|
@ -192,7 +197,7 @@ TEST_P(TextureZeroInitTest, CopyBufferToTextureHalf) {
|
|||
kColorFormat);
|
||||
dawn::Texture texture = device.CreateTexture(&descriptor);
|
||||
|
||||
std::vector<uint8_t> data(4 * kSize * kSize, 100);
|
||||
std::vector<uint8_t> data(kFormatBlockByteSize * kSize * kSize, 100);
|
||||
dawn::Buffer stagingBuffer = utils::CreateBufferFromData(
|
||||
device, data.data(), static_cast<uint32_t>(data.size()), dawn::BufferUsage::CopySrc);
|
||||
|
||||
|
@ -256,7 +261,7 @@ TEST_P(TextureZeroInitTest, CopyTextureToTextureHalf) {
|
|||
|
||||
// fill srcTexture with 100
|
||||
{
|
||||
std::vector<uint8_t> data(4 * kSize * kSize, 100);
|
||||
std::vector<uint8_t> data(kFormatBlockByteSize * kSize * kSize, 100);
|
||||
dawn::Buffer stagingBuffer = utils::CreateBufferFromData(
|
||||
device, data.data(), static_cast<uint32_t>(data.size()), dawn::BufferUsage::CopySrc);
|
||||
dawn::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(stagingBuffer, 0, 0, 0);
|
||||
|
@ -504,7 +509,7 @@ TEST_P(TextureZeroInitTest, ComputePassSampledTextureClear) {
|
|||
descriptor.size.height = 1;
|
||||
dawn::Texture texture = device.CreateTexture(&descriptor);
|
||||
|
||||
uint32_t bufferSize = 4 * sizeof(uint32_t);
|
||||
uint32_t bufferSize = kFormatBlockByteSize * sizeof(uint32_t);
|
||||
dawn::BufferDescriptor bufferDescriptor;
|
||||
bufferDescriptor.size = bufferSize;
|
||||
bufferDescriptor.usage =
|
||||
|
@ -560,26 +565,81 @@ TEST_P(TextureZeroInitTest, ComputePassSampledTextureClear) {
|
|||
|
||||
// Expect the buffer to be zeroed out by the compute pass
|
||||
std::vector<uint32_t> expectedWithZeros(bufferSize, 0);
|
||||
EXPECT_BUFFER_U32_RANGE_EQ(expectedWithZeros.data(), bufferTex, 0, 4);
|
||||
EXPECT_BUFFER_U32_RANGE_EQ(expectedWithZeros.data(), bufferTex, 0, kFormatBlockByteSize);
|
||||
}
|
||||
|
||||
// This tests that the code path of CopyTextureToBuffer clears correctly for non-renderable textures
|
||||
TEST_P(TextureZeroInitTest, NonRenderableTextureClear) {
|
||||
// skip test for other backends since they are not implemented yet
|
||||
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||
|
||||
dawn::TextureDescriptor descriptor =
|
||||
CreateTextureDescriptor(1, 1, dawn::TextureUsage::CopySrc, kNonrenderableColorFormat);
|
||||
dawn::Texture texture = device.CreateTexture(&descriptor);
|
||||
|
||||
// Set buffer with dirty data so we know it is cleared by the lazy cleared texture copy
|
||||
uint32_t bufferSize = 4 * kSize * kSize;
|
||||
uint32_t rowPitch = Align(kSize * kFormatBlockByteSize, kTextureRowPitchAlignment);
|
||||
uint32_t bufferSize = rowPitch * kSize;
|
||||
std::vector<uint8_t> data(bufferSize, 100);
|
||||
dawn::Buffer bufferDst = utils::CreateBufferFromData(
|
||||
device, data.data(), static_cast<uint32_t>(data.size()), dawn::BufferUsage::CopySrc);
|
||||
|
||||
dawn::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(bufferDst, 0, rowPitch, 0);
|
||||
dawn::TextureCopyView textureCopyView = utils::CreateTextureCopyView(texture, 0, 0, {0, 0, 0});
|
||||
dawn::Extent3D copySize = {kSize, kSize, 1};
|
||||
|
||||
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, ©Size);
|
||||
dawn::CommandBuffer commands = encoder.Finish();
|
||||
EXPECT_LAZY_CLEAR(1u, queue.Submit(1, &commands));
|
||||
|
||||
std::vector<uint32_t> expectedWithZeros(bufferSize, 0);
|
||||
EXPECT_BUFFER_U32_RANGE_EQ(expectedWithZeros.data(), bufferDst, 0, kSize);
|
||||
}
|
||||
|
||||
// This tests that the code path of CopyTextureToBuffer clears correctly for non-renderable textures
|
||||
TEST_P(TextureZeroInitTest, NonRenderableTextureClearUnalignedSize) {
|
||||
dawn::TextureDescriptor descriptor =
|
||||
CreateTextureDescriptor(1, 1, dawn::TextureUsage::CopySrc, kNonrenderableColorFormat);
|
||||
descriptor.size.width = kUnalignedSize;
|
||||
descriptor.size.height = kUnalignedSize;
|
||||
dawn::Texture texture = device.CreateTexture(&descriptor);
|
||||
|
||||
// Set buffer with dirty data so we know it is cleared by the lazy cleared texture copy
|
||||
uint32_t rowPitch = Align(kUnalignedSize * kFormatBlockByteSize, kTextureRowPitchAlignment);
|
||||
uint32_t bufferSize = rowPitch * kUnalignedSize;
|
||||
std::vector<uint8_t> data(bufferSize, 100);
|
||||
dawn::Buffer bufferDst = utils::CreateBufferFromData(
|
||||
device, data.data(), static_cast<uint32_t>(data.size()), dawn::BufferUsage::CopySrc);
|
||||
dawn::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(bufferDst, 0, rowPitch, 0);
|
||||
dawn::TextureCopyView textureCopyView = utils::CreateTextureCopyView(texture, 0, 0, {0, 0, 0});
|
||||
dawn::Extent3D copySize = {kUnalignedSize, kUnalignedSize, 1};
|
||||
|
||||
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
encoder.CopyTextureToBuffer(&textureCopyView, &bufferCopyView, ©Size);
|
||||
dawn::CommandBuffer commands = encoder.Finish();
|
||||
EXPECT_LAZY_CLEAR(1u, queue.Submit(1, &commands));
|
||||
|
||||
std::vector<uint32_t> expectedWithZeros(bufferSize, 0);
|
||||
EXPECT_BUFFER_U32_RANGE_EQ(expectedWithZeros.data(), bufferDst, 0, kUnalignedSize);
|
||||
}
|
||||
|
||||
// This tests that the code path of CopyTextureToBuffer clears correctly for non-renderable textures
|
||||
// with more than 1 array layers
|
||||
TEST_P(TextureZeroInitTest, NonRenderableTextureClearWithMultiArrayLayers) {
|
||||
// TODO(natlee@microsoft.com): skip for now on opengl because TextureClear nonrenderable
|
||||
// textures does not create large enough buffers for array layers greater than 1.
|
||||
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||
|
||||
dawn::TextureDescriptor descriptor =
|
||||
CreateTextureDescriptor(1, 2, dawn::TextureUsage::CopySrc, kNonrenderableColorFormat);
|
||||
dawn::Texture texture = device.CreateTexture(&descriptor);
|
||||
|
||||
// Set buffer with dirty data so we know it is cleared by the lazy cleared texture copy
|
||||
uint32_t bufferSize = kFormatBlockByteSize * kSize * kSize;
|
||||
std::vector<uint8_t> data(bufferSize, 100);
|
||||
dawn::Buffer bufferDst = utils::CreateBufferFromData(
|
||||
device, data.data(), static_cast<uint32_t>(data.size()), dawn::BufferUsage::CopySrc);
|
||||
|
||||
dawn::BufferCopyView bufferCopyView = utils::CreateBufferCopyView(bufferDst, 0, 0, 0);
|
||||
dawn::TextureCopyView textureCopyView = utils::CreateTextureCopyView(texture, 0, 0, {0, 0, 0});
|
||||
dawn::TextureCopyView textureCopyView = utils::CreateTextureCopyView(texture, 0, 1, {0, 0, 0});
|
||||
dawn::Extent3D copySize = {kSize, kSize, 1};
|
||||
|
||||
dawn::CommandEncoder encoder = device.CreateCommandEncoder();
|
||||
|
|
Loading…
Reference in New Issue