mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-05 06:03:34 +00:00
This patch adds the support of BC5 formats on D3D12 backend. On D3D12, the "rowPitch" refers to the number of bytes in a row of blocks (which covers up to 4 scanlines at once) for the textures in BC formats. This patch also adds the related end2end tests for four typical cases of B2T and T2B copies on D3D12: (1) copyBytesPerRowPitch + byteOffsetPerRowPitch <= rowPitch and texelOffset.y == 0 (2) copyBytesPerRowPitch + byteOffsetPerRowPitch <= rowPitch and texelOffset.y > 0 (3) copyBytesPerRowPitch + byteOffsetPerRowPitch > rowPitch (4) texelOffset.z > 0 BUG=dawn:42 TEST=dawn_end2end_tests Change-Id: If27ab3e56596e25c1c5be787ca021c0748021a46 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/8541 Commit-Queue: Corentin Wallez <cwallez@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
456 lines
20 KiB
C++
456 lines
20 KiB
C++
// Copyright 2017 The Dawn Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "common/Assert.h"
|
|
#include "common/Constants.h"
|
|
#include "common/Math.h"
|
|
#include "dawn_native/Texture.h"
|
|
#include "dawn_native/d3d12/TextureCopySplitter.h"
|
|
#include "dawn_native/d3d12/d3d12_platform.h"
|
|
|
|
using namespace dawn_native::d3d12;
|
|
|
|
namespace {
|
|
|
|
struct TextureSpec {
|
|
uint32_t x;
|
|
uint32_t y;
|
|
uint32_t z;
|
|
uint32_t width;
|
|
uint32_t height;
|
|
uint32_t depth;
|
|
uint32_t texelBlockSizeInBytes;
|
|
uint32_t blockWidth = 1;
|
|
uint32_t blockHeight = 1;
|
|
};
|
|
|
|
struct BufferSpec {
|
|
uint64_t offset;
|
|
uint32_t rowPitch;
|
|
uint32_t imageHeight;
|
|
};
|
|
|
|
// Check that each copy region fits inside the buffer footprint
|
|
void ValidateFootprints(const TextureCopySplit& copySplit) {
|
|
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
|
const auto& copy = copySplit.copies[i];
|
|
ASSERT_LE(copy.bufferOffset.x + copy.copySize.width, copy.bufferSize.width);
|
|
ASSERT_LE(copy.bufferOffset.y + copy.copySize.height, copy.bufferSize.height);
|
|
ASSERT_LE(copy.bufferOffset.z + copy.copySize.depth, copy.bufferSize.depth);
|
|
}
|
|
}
|
|
|
|
// Check that the offset is aligned
|
|
void ValidateOffset(const TextureCopySplit& copySplit) {
|
|
ASSERT_TRUE(Align(copySplit.offset, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT) == copySplit.offset);
|
|
}
|
|
|
|
bool RangesOverlap(uint32_t minA, uint32_t maxA, uint32_t minB, uint32_t maxB) {
|
|
return (minA < minB && minB <= maxA) || (minB < minA && minA <= maxB);
|
|
}
|
|
|
|
// Check that no pair of copy regions intersect each other
|
|
void ValidateDisjoint(const TextureCopySplit& copySplit) {
|
|
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
|
const auto& a = copySplit.copies[i];
|
|
for (uint32_t j = i + 1; j < copySplit.count; ++j) {
|
|
const auto& b = copySplit.copies[j];
|
|
bool overlapX = RangesOverlap(a.textureOffset.x, a.textureOffset.x + a.copySize.width, b.textureOffset.x, b.textureOffset.x + b.copySize.width);
|
|
bool overlapY = RangesOverlap(a.textureOffset.y, a.textureOffset.y + a.copySize.height, b.textureOffset.y, b.textureOffset.y + b.copySize.height);
|
|
bool overlapZ = RangesOverlap(a.textureOffset.z, a.textureOffset.z + a.copySize.depth, b.textureOffset.z, b.textureOffset.z + b.copySize.depth);
|
|
ASSERT_TRUE(!overlapX || !overlapY || !overlapZ);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Check that the union of the copy regions exactly covers the texture region
|
|
void ValidateTextureBounds(const TextureSpec& textureSpec, const TextureCopySplit& copySplit) {
|
|
ASSERT_TRUE(copySplit.count > 0);
|
|
|
|
uint32_t minX = copySplit.copies[0].textureOffset.x;
|
|
uint32_t minY = copySplit.copies[0].textureOffset.y;
|
|
uint32_t minZ = copySplit.copies[0].textureOffset.z;
|
|
uint32_t maxX = copySplit.copies[0].textureOffset.x + copySplit.copies[0].copySize.width;
|
|
uint32_t maxY = copySplit.copies[0].textureOffset.y + copySplit.copies[0].copySize.height;
|
|
uint32_t maxZ = copySplit.copies[0].textureOffset.z + copySplit.copies[0].copySize.depth;
|
|
|
|
for (uint32_t i = 1; i < copySplit.count; ++i) {
|
|
const auto& copy = copySplit.copies[i];
|
|
minX = std::min(minX, copy.textureOffset.x);
|
|
minY = std::min(minY, copy.textureOffset.y);
|
|
minZ = std::min(minZ, copy.textureOffset.z);
|
|
maxX = std::max(maxX, copy.textureOffset.x + copy.copySize.width);
|
|
maxY = std::max(maxY, copy.textureOffset.y + copy.copySize.height);
|
|
maxZ = std::max(maxZ, copy.textureOffset.z + copy.copySize.depth);
|
|
}
|
|
|
|
ASSERT_EQ(minX, textureSpec.x);
|
|
ASSERT_EQ(minY, textureSpec.y);
|
|
ASSERT_EQ(minZ, textureSpec.z);
|
|
ASSERT_EQ(maxX, textureSpec.x + textureSpec.width);
|
|
ASSERT_EQ(maxY, textureSpec.y + textureSpec.height);
|
|
ASSERT_EQ(maxZ, textureSpec.z + textureSpec.depth);
|
|
}
|
|
|
|
// Validate that the number of pixels copied is exactly equal to the number of pixels in the texture region
|
|
void ValidatePixelCount(const TextureSpec& textureSpec, const TextureCopySplit& copySplit) {
|
|
uint32_t count = 0;
|
|
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
|
const auto& copy = copySplit.copies[i];
|
|
count += copy.copySize.width * copy.copySize.height * copy.copySize.depth;
|
|
}
|
|
ASSERT_EQ(count, textureSpec.width * textureSpec.height * textureSpec.depth);
|
|
}
|
|
|
|
// Check that every buffer offset is at the correct pixel location
|
|
void ValidateBufferOffset(const TextureSpec& textureSpec, const BufferSpec& bufferSpec, const TextureCopySplit& copySplit) {
|
|
ASSERT_TRUE(copySplit.count > 0);
|
|
|
|
uint32_t texelsPerBlock = textureSpec.blockWidth * textureSpec.blockHeight;
|
|
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
|
const auto& copy = copySplit.copies[i];
|
|
|
|
uint32_t rowPitchInTexels =
|
|
bufferSpec.rowPitch / textureSpec.texelBlockSizeInBytes * texelsPerBlock;
|
|
uint32_t slicePitchInTexels =
|
|
rowPitchInTexels * (bufferSpec.imageHeight / textureSpec.blockHeight);
|
|
uint32_t absoluteTexelOffset =
|
|
copySplit.offset / textureSpec.texelBlockSizeInBytes * texelsPerBlock +
|
|
copy.bufferOffset.x / textureSpec.blockWidth * texelsPerBlock +
|
|
copy.bufferOffset.y / textureSpec.blockHeight * rowPitchInTexels +
|
|
copy.bufferOffset.z * slicePitchInTexels;
|
|
|
|
ASSERT(absoluteTexelOffset >=
|
|
bufferSpec.offset / textureSpec.texelBlockSizeInBytes * texelsPerBlock);
|
|
uint32_t relativeTexelOffset =
|
|
absoluteTexelOffset -
|
|
bufferSpec.offset / textureSpec.texelBlockSizeInBytes * texelsPerBlock;
|
|
|
|
uint32_t z = relativeTexelOffset / slicePitchInTexels;
|
|
uint32_t y = (relativeTexelOffset % slicePitchInTexels) / rowPitchInTexels;
|
|
uint32_t x = relativeTexelOffset % rowPitchInTexels;
|
|
|
|
ASSERT_EQ(copy.textureOffset.x - textureSpec.x, x);
|
|
ASSERT_EQ(copy.textureOffset.y - textureSpec.y, y);
|
|
ASSERT_EQ(copy.textureOffset.z - textureSpec.z, z);
|
|
}
|
|
}
|
|
|
|
void ValidateCopySplit(const TextureSpec& textureSpec, const BufferSpec& bufferSpec, const TextureCopySplit& copySplit) {
|
|
ValidateFootprints(copySplit);
|
|
ValidateOffset(copySplit);
|
|
ValidateDisjoint(copySplit);
|
|
ValidateTextureBounds(textureSpec, copySplit);
|
|
ValidatePixelCount(textureSpec, copySplit);
|
|
ValidateBufferOffset(textureSpec, bufferSpec, copySplit);
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& os, const TextureSpec& textureSpec) {
|
|
os << "TextureSpec("
|
|
<< "[(" << textureSpec.x << ", " << textureSpec.y << ", " << textureSpec.z << "), ("
|
|
<< textureSpec.width << ", " << textureSpec.height << ", " << textureSpec.depth << ")], "
|
|
<< textureSpec.texelBlockSizeInBytes << ")";
|
|
return os;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& os, const BufferSpec& bufferSpec) {
|
|
os << "BufferSpec(" << bufferSpec.offset << ", " << bufferSpec.rowPitch << ", "
|
|
<< bufferSpec.imageHeight << ")";
|
|
return os;
|
|
}
|
|
|
|
std::ostream& operator<<(std::ostream& os, const TextureCopySplit& copySplit) {
|
|
os << "CopySplit" << std::endl;
|
|
for (uint32_t i = 0; i < copySplit.count; ++i) {
|
|
const auto& copy = copySplit.copies[i];
|
|
os << " " << i << ": Texture at (" << copy.textureOffset.x << ", " << copy.textureOffset.y << ", " << copy.textureOffset.z << "), size (" << copy.copySize.width << ", " << copy.copySize.height << ", " << copy.copySize.depth << ")" << std::endl;
|
|
os << " " << i << ": Buffer at (" << copy.bufferOffset.x << ", " << copy.bufferOffset.y << ", " << copy.bufferOffset.z << "), footprint (" << copy.bufferSize.width << ", " << copy.bufferSize.height << ", " << copy.bufferSize.depth << ")" << std::endl;
|
|
}
|
|
return os;
|
|
}
|
|
|
|
// Define base texture sizes and offsets to test with: some aligned, some unaligned
|
|
constexpr TextureSpec kBaseTextureSpecs[] = {
|
|
{0, 0, 0, 1, 1, 1, 4},
|
|
{31, 16, 0, 1, 1, 1, 4},
|
|
{64, 16, 0, 1, 1, 1, 4},
|
|
{64, 16, 8, 1, 1, 1, 4},
|
|
|
|
{0, 0, 0, 1024, 1024, 1, 4},
|
|
{256, 512, 0, 1024, 1024, 1, 4},
|
|
{64, 48, 0, 1024, 1024, 1, 4},
|
|
{64, 48, 16, 1024, 1024, 1024, 4},
|
|
|
|
{0, 0, 0, 257, 31, 1, 4},
|
|
{0, 0, 0, 17, 93, 1, 4},
|
|
{59, 13, 0, 257, 31, 1, 4},
|
|
{17, 73, 0, 17, 93, 1, 4},
|
|
{17, 73, 59, 17, 93, 99, 4},
|
|
|
|
{0, 0, 0, 4, 4, 1, 8, 4, 4},
|
|
{64, 16, 0, 4, 4, 1, 8, 4, 4},
|
|
{64, 16, 8, 4, 4, 1, 8, 4, 4},
|
|
{0, 0, 0, 4, 4, 1, 16, 4, 4},
|
|
{64, 16, 0, 4, 4, 1, 16, 4, 4},
|
|
{64, 16, 8, 4, 4, 1, 16, 4, 4},
|
|
|
|
{0, 0, 0, 1024, 1024, 1, 8, 4, 4},
|
|
{256, 512, 0, 1024, 1024, 1, 8, 4, 4},
|
|
{64, 48, 0, 1024, 1024, 1, 8, 4, 4},
|
|
{64, 48, 16, 1024, 1024, 1, 8, 4, 4},
|
|
{0, 0, 0, 1024, 1024, 1, 16, 4, 4},
|
|
{256, 512, 0, 1024, 1024, 1, 16, 4, 4},
|
|
{64, 48, 0, 1024, 1024, 1, 4, 16, 4},
|
|
{64, 48, 16, 1024, 1024, 1, 16, 4, 4},
|
|
};
|
|
|
|
// Define base buffer sizes to work with: some offsets aligned, some unaligned. rowPitch is the minimum required
|
|
std::array<BufferSpec, 13> BaseBufferSpecs(const TextureSpec& textureSpec) {
|
|
uint32_t rowPitch =
|
|
Align(textureSpec.texelBlockSizeInBytes * textureSpec.width, kTextureRowPitchAlignment);
|
|
|
|
auto alignNonPow2 = [](uint32_t value, uint32_t size) -> uint32_t {
|
|
return value == 0 ? 0 : ((value - 1) / size + 1) * size;
|
|
};
|
|
|
|
return {
|
|
BufferSpec{alignNonPow2(0, textureSpec.texelBlockSizeInBytes), rowPitch,
|
|
textureSpec.height},
|
|
BufferSpec{alignNonPow2(512, textureSpec.texelBlockSizeInBytes), rowPitch,
|
|
textureSpec.height},
|
|
BufferSpec{alignNonPow2(1024, textureSpec.texelBlockSizeInBytes), rowPitch,
|
|
textureSpec.height},
|
|
BufferSpec{alignNonPow2(1024, textureSpec.texelBlockSizeInBytes), rowPitch,
|
|
textureSpec.height * 2},
|
|
|
|
BufferSpec{alignNonPow2(32, textureSpec.texelBlockSizeInBytes), rowPitch,
|
|
textureSpec.height},
|
|
BufferSpec{alignNonPow2(64, textureSpec.texelBlockSizeInBytes), rowPitch,
|
|
textureSpec.height},
|
|
BufferSpec{alignNonPow2(64, textureSpec.texelBlockSizeInBytes), rowPitch,
|
|
textureSpec.height * 2},
|
|
|
|
BufferSpec{alignNonPow2(31, textureSpec.texelBlockSizeInBytes), rowPitch,
|
|
textureSpec.height},
|
|
BufferSpec{alignNonPow2(257, textureSpec.texelBlockSizeInBytes), rowPitch,
|
|
textureSpec.height},
|
|
BufferSpec{alignNonPow2(511, textureSpec.texelBlockSizeInBytes), rowPitch,
|
|
textureSpec.height},
|
|
BufferSpec{alignNonPow2(513, textureSpec.texelBlockSizeInBytes), rowPitch,
|
|
textureSpec.height},
|
|
BufferSpec{alignNonPow2(1023, textureSpec.texelBlockSizeInBytes), rowPitch,
|
|
textureSpec.height},
|
|
BufferSpec{alignNonPow2(1023, textureSpec.texelBlockSizeInBytes), rowPitch,
|
|
textureSpec.height * 2},
|
|
};
|
|
}
|
|
|
|
// Define a list of values to set properties in the spec structs
|
|
constexpr uint32_t kCheckValues[] = {
|
|
1, 2, 3, 4, 5, 6, 7, 8, // small values
|
|
16, 32, 64, 128, 256, 512, 1024, 2048, // powers of 2
|
|
15, 31, 63, 127, 257, 511, 1023, 2047, // misalignments
|
|
17, 33, 65, 129, 257, 513, 1025, 2049
|
|
};
|
|
|
|
}
|
|
|
|
class CopySplitTest : public testing::Test {
|
|
protected:
|
|
TextureCopySplit DoTest(const TextureSpec& textureSpec, const BufferSpec& bufferSpec) {
|
|
ASSERT(textureSpec.width % textureSpec.blockWidth == 0 &&
|
|
textureSpec.height % textureSpec.blockHeight == 0);
|
|
dawn_native::Format fakeFormat = {};
|
|
fakeFormat.blockWidth = textureSpec.blockWidth;
|
|
fakeFormat.blockHeight = textureSpec.blockHeight;
|
|
fakeFormat.blockByteSize = textureSpec.texelBlockSizeInBytes;
|
|
TextureCopySplit copySplit = ComputeTextureCopySplit(
|
|
{textureSpec.x, textureSpec.y, textureSpec.z},
|
|
{textureSpec.width, textureSpec.height, textureSpec.depth}, fakeFormat,
|
|
bufferSpec.offset, bufferSpec.rowPitch, bufferSpec.imageHeight);
|
|
ValidateCopySplit(textureSpec, bufferSpec, copySplit);
|
|
return copySplit;
|
|
}
|
|
};
|
|
|
|
TEST_F(CopySplitTest, General) {
|
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
|
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
|
|
|
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
|
if (HasFatalFailure()) {
|
|
std::ostringstream message;
|
|
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
|
<< copySplit << std::endl;
|
|
FAIL() << message.str();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_F(CopySplitTest, TextureWidth) {
|
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
|
for (uint32_t val : kCheckValues) {
|
|
if (val % textureSpec.blockWidth != 0) {
|
|
continue;
|
|
}
|
|
textureSpec.width = val;
|
|
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
|
|
|
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
|
if (HasFatalFailure()) {
|
|
std::ostringstream message;
|
|
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
|
<< copySplit << std::endl;
|
|
FAIL() << message.str();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_F(CopySplitTest, TextureHeight) {
|
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
|
for (uint32_t val : kCheckValues) {
|
|
if (val % textureSpec.blockHeight != 0) {
|
|
continue;
|
|
}
|
|
textureSpec.height = val;
|
|
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
|
|
|
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
|
if (HasFatalFailure()) {
|
|
std::ostringstream message;
|
|
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
|
<< copySplit << std::endl;
|
|
FAIL() << message.str();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_F(CopySplitTest, TextureX) {
|
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
|
for (uint32_t val : kCheckValues) {
|
|
textureSpec.x = val;
|
|
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
|
|
|
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
|
if (HasFatalFailure()) {
|
|
std::ostringstream message;
|
|
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
|
<< copySplit << std::endl;
|
|
FAIL() << message.str();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_F(CopySplitTest, TextureY) {
|
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
|
for (uint32_t val : kCheckValues) {
|
|
textureSpec.y = val;
|
|
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
|
|
|
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
|
if (HasFatalFailure()) {
|
|
std::ostringstream message;
|
|
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
|
<< copySplit << std::endl;
|
|
FAIL() << message.str();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_F(CopySplitTest, TexelSize) {
|
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
|
for (uint32_t texelSize : {4, 8, 16, 32, 64}) {
|
|
textureSpec.texelBlockSizeInBytes = texelSize;
|
|
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
|
|
|
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
|
if (HasFatalFailure()) {
|
|
std::ostringstream message;
|
|
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
|
<< copySplit << std::endl;
|
|
FAIL() << message.str();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_F(CopySplitTest, BufferOffset) {
|
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
|
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
|
for (uint32_t val : kCheckValues) {
|
|
bufferSpec.offset = textureSpec.texelBlockSizeInBytes * val;
|
|
|
|
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
|
if (HasFatalFailure()) {
|
|
std::ostringstream message;
|
|
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
|
<< copySplit << std::endl;
|
|
FAIL() << message.str();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_F(CopySplitTest, RowPitch) {
|
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
|
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
|
uint32_t baseRowPitch = bufferSpec.rowPitch;
|
|
for (uint32_t i = 0; i < 5; ++i) {
|
|
bufferSpec.rowPitch = baseRowPitch + i * 256;
|
|
|
|
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
|
if (HasFatalFailure()) {
|
|
std::ostringstream message;
|
|
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec << std::endl
|
|
<< copySplit << std::endl;
|
|
FAIL() << message.str();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TEST_F(CopySplitTest, ImageHeight) {
|
|
for (TextureSpec textureSpec : kBaseTextureSpecs) {
|
|
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
|
|
uint32_t baseImageHeight = bufferSpec.imageHeight;
|
|
for (uint32_t i = 0; i < 5; ++i) {
|
|
bufferSpec.imageHeight = baseImageHeight + i * 256;
|
|
|
|
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
|
|
if (HasFatalFailure()) {
|
|
std::ostringstream message;
|
|
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
|
|
<< std::endl
|
|
<< copySplit << std::endl;
|
|
FAIL() << message.str();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|