Update tests and examples to follow copy row pitch alignment constraints
This commit is contained in:
parent
3f47729df6
commit
972a1e59a7
|
@ -21,6 +21,8 @@
|
||||||
#include "SampleUtils.h"
|
#include "SampleUtils.h"
|
||||||
|
|
||||||
#include "utils/NXTHelpers.h"
|
#include "utils/NXTHelpers.h"
|
||||||
|
#include "common/Math.h"
|
||||||
|
#include "common/Constants.h"
|
||||||
|
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
|
||||||
|
@ -410,29 +412,48 @@ namespace {
|
||||||
.GetResult();
|
.GetResult();
|
||||||
// TODO: release this texture
|
// TODO: release this texture
|
||||||
|
|
||||||
uint32_t numPixels = iImage.width * iImage.height;
|
|
||||||
const uint8_t* origData = iImage.image.data();
|
const uint8_t* origData = iImage.image.data();
|
||||||
const uint8_t* data = nullptr;
|
const uint8_t* data = nullptr;
|
||||||
std::vector<uint8_t> newData;
|
std::vector<uint8_t> newData;
|
||||||
if (iImage.component == 4) {
|
|
||||||
data = origData;
|
uint32_t width = static_cast<uint32_t>(iImage.width);
|
||||||
} else if (iImage.component == 3) {
|
uint32_t height = static_cast<uint32_t>(iImage.height);
|
||||||
newData.resize(numPixels * 4);
|
uint32_t rowSize = width * 4;
|
||||||
for (size_t i = 0; i < numPixels; ++i) {
|
uint32_t rowPitch = Align(rowSize, kTextureRowPitchAlignment);
|
||||||
newData[4 * i + 0] = origData[3 * i + 0];
|
|
||||||
newData[4 * i + 1] = origData[3 * i + 1];
|
if (iImage.component == 3 || iImage.component == 4) {
|
||||||
newData[4 * i + 2] = origData[3 * i + 2];
|
if (rowSize != rowPitch || iImage.component == 3) {
|
||||||
newData[4 * i + 3] = 255;
|
newData.resize(rowPitch * height);
|
||||||
|
uint32_t pixelsPerRow = rowPitch / 4;
|
||||||
|
for (uint32_t y = 0; y < height; ++y) {
|
||||||
|
for (uint32_t x = 0; x < width; ++x) {
|
||||||
|
size_t oldIndex = x + y * height;
|
||||||
|
size_t newIndex = x + y * pixelsPerRow;
|
||||||
|
if (iImage.component == 4) {
|
||||||
|
newData[4 * newIndex + 0] = origData[4 * oldIndex + 0];
|
||||||
|
newData[4 * newIndex + 1] = origData[4 * oldIndex + 1];
|
||||||
|
newData[4 * newIndex + 2] = origData[4 * oldIndex + 2];
|
||||||
|
newData[4 * newIndex + 3] = origData[4 * oldIndex + 3];
|
||||||
|
} else if (iImage.component == 3) {
|
||||||
|
newData[4 * newIndex + 0] = origData[3 * oldIndex + 0];
|
||||||
|
newData[4 * newIndex + 1] = origData[3 * oldIndex + 1];
|
||||||
|
newData[4 * newIndex + 2] = origData[3 * oldIndex + 2];
|
||||||
|
newData[4 * newIndex + 3] = 255;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data = newData.data();
|
||||||
|
} else {
|
||||||
|
data = origData;
|
||||||
}
|
}
|
||||||
data = newData.data();
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "unsupported image.component %d\n", iImage.component);
|
fprintf(stderr, "unsupported image.component %d\n", iImage.component);
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt::Buffer staging = utils::CreateFrozenBufferFromData(device, data, numPixels * 4, nxt::BufferUsageBit::TransferSrc);
|
nxt::Buffer staging = utils::CreateFrozenBufferFromData(device, data, rowPitch * iImage.height, nxt::BufferUsageBit::TransferSrc);
|
||||||
auto cmdbuf = device.CreateCommandBufferBuilder()
|
auto cmdbuf = device.CreateCommandBufferBuilder()
|
||||||
.TransitionTextureUsage(oTexture, nxt::TextureUsageBit::TransferDst)
|
.TransitionTextureUsage(oTexture, nxt::TextureUsageBit::TransferDst)
|
||||||
.CopyBufferToTexture(staging, 0, 0, oTexture, 0, 0, 0, iImage.width, iImage.height, 1, 0)
|
.CopyBufferToTexture(staging, 0, rowPitch, oTexture, 0, 0, 0, iImage.width, iImage.height, 1, 0)
|
||||||
.GetResult();
|
.GetResult();
|
||||||
queue.Submit(1, &cmdbuf);
|
queue.Submit(1, &cmdbuf);
|
||||||
oTexture.FreezeUsage(nxt::TextureUsageBit::Sampled);
|
oTexture.FreezeUsage(nxt::TextureUsageBit::Sampled);
|
||||||
|
|
|
@ -48,7 +48,7 @@ TEST_P(BasicTests, ReadPixelsTest) {
|
||||||
|
|
||||||
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
|
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
|
||||||
.TransitionTextureUsage(texture, nxt::TextureUsageBit::TransferDst)
|
.TransitionTextureUsage(texture, nxt::TextureUsageBit::TransferDst)
|
||||||
.CopyBufferToTexture(buffer, 0, 0, texture, 0, 0, 0, 1, 1, 1, 0)
|
.CopyBufferToTexture(buffer, 0, 256, texture, 0, 0, 0, 1, 1, 1, 0)
|
||||||
.GetResult();
|
.GetResult();
|
||||||
|
|
||||||
queue.Submit(1, &commands);
|
queue.Submit(1, &commands);
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "common/Constants.h"
|
||||||
|
#include "common/Math.h"
|
||||||
#include "tests/unittests/validation/ValidationTest.h"
|
#include "tests/unittests/validation/ValidationTest.h"
|
||||||
|
|
||||||
class CopyCommandTest : public ValidationTest {
|
class CopyCommandTest : public ValidationTest {
|
||||||
|
@ -37,6 +39,11 @@ class CopyCommandTest : public ValidationTest {
|
||||||
tex.FreezeUsage(usage);
|
tex.FreezeUsage(usage);
|
||||||
return tex;
|
return tex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t BufferSizeForTextureCopy(uint32_t width, uint32_t height, uint32_t depth) {
|
||||||
|
uint32_t rowPitch = Align(width * 4, kTextureRowPitchAlignment);
|
||||||
|
return (rowPitch * (height - 1) + width) * depth;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CopyCommandTest_B2B : public CopyCommandTest {
|
class CopyCommandTest_B2B : public CopyCommandTest {
|
||||||
|
@ -114,7 +121,8 @@ class CopyCommandTest_B2T : public CopyCommandTest {
|
||||||
|
|
||||||
// Test a successfull B2T copy
|
// Test a successfull B2T copy
|
||||||
TEST_F(CopyCommandTest_B2T, Success) {
|
TEST_F(CopyCommandTest_B2T, Success) {
|
||||||
nxt::Buffer source = CreateFrozenBuffer(16 * 4, nxt::BufferUsageBit::TransferSrc);
|
uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
|
||||||
|
nxt::Buffer source = CreateFrozenBuffer(bufferSize, nxt::BufferUsageBit::TransferSrc);
|
||||||
nxt::Texture destination = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
nxt::Texture destination = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
||||||
nxt::TextureUsageBit::TransferDst);
|
nxt::TextureUsageBit::TransferDst);
|
||||||
|
|
||||||
|
@ -128,7 +136,7 @@ TEST_F(CopyCommandTest_B2T, Success) {
|
||||||
// Copy 4x4 block in the 4x4 mip.
|
// Copy 4x4 block in the 4x4 mip.
|
||||||
.CopyBufferToTexture(source, 0, 0, destination, 0, 0, 0, 4, 4, 1, 2)
|
.CopyBufferToTexture(source, 0, 0, destination, 0, 0, 0, 4, 4, 1, 2)
|
||||||
// Copy with a buffer offset
|
// Copy with a buffer offset
|
||||||
.CopyBufferToTexture(source, 15 * 4, 0, destination, 0, 0, 0, 1, 1, 1, 4)
|
.CopyBufferToTexture(source, bufferSize - 4, 0, destination, 0, 0, 0, 1, 1, 1, 4)
|
||||||
.GetResult();
|
.GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +146,7 @@ TEST_F(CopyCommandTest_B2T, Success) {
|
||||||
// An empty copy
|
// An empty copy
|
||||||
.CopyBufferToTexture(source, 0, 0, destination, 0, 0, 0, 0, 0, 1, 0)
|
.CopyBufferToTexture(source, 0, 0, destination, 0, 0, 0, 0, 0, 1, 0)
|
||||||
// An empty copy touching the end of the buffer
|
// An empty copy touching the end of the buffer
|
||||||
.CopyBufferToTexture(source, 16 * 4, 0, destination, 0, 0, 0, 0, 0, 1, 0)
|
.CopyBufferToTexture(source, bufferSize, 0, destination, 0, 0, 0, 0, 0, 1, 0)
|
||||||
// An empty copy touching the side of the texture
|
// An empty copy touching the side of the texture
|
||||||
.CopyBufferToTexture(source, 0, 0, destination, 16, 16, 0, 0, 0, 1, 0)
|
.CopyBufferToTexture(source, 0, 0, destination, 16, 16, 0, 0, 0, 1, 0)
|
||||||
.GetResult();
|
.GetResult();
|
||||||
|
@ -147,7 +155,8 @@ TEST_F(CopyCommandTest_B2T, Success) {
|
||||||
|
|
||||||
// Test OOB conditions on the buffer
|
// Test OOB conditions on the buffer
|
||||||
TEST_F(CopyCommandTest_B2T, OutOfBoundsOnBuffer) {
|
TEST_F(CopyCommandTest_B2T, OutOfBoundsOnBuffer) {
|
||||||
nxt::Buffer source = CreateFrozenBuffer(16 * 4, nxt::BufferUsageBit::TransferSrc);
|
uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
|
||||||
|
nxt::Buffer source = CreateFrozenBuffer(bufferSize, nxt::BufferUsageBit::TransferSrc);
|
||||||
nxt::Texture destination = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
nxt::Texture destination = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
||||||
nxt::TextureUsageBit::TransferDst);
|
nxt::TextureUsageBit::TransferDst);
|
||||||
|
|
||||||
|
@ -168,7 +177,8 @@ TEST_F(CopyCommandTest_B2T, OutOfBoundsOnBuffer) {
|
||||||
|
|
||||||
// Test OOB conditions on the texture
|
// Test OOB conditions on the texture
|
||||||
TEST_F(CopyCommandTest_B2T, OutOfBoundsOnTexture) {
|
TEST_F(CopyCommandTest_B2T, OutOfBoundsOnTexture) {
|
||||||
nxt::Buffer source = CreateFrozenBuffer(16 * 4, nxt::BufferUsageBit::TransferSrc);
|
uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
|
||||||
|
nxt::Buffer source = CreateFrozenBuffer(bufferSize, nxt::BufferUsageBit::TransferSrc);
|
||||||
nxt::Texture destination = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
nxt::Texture destination = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
||||||
nxt::TextureUsageBit::TransferDst);
|
nxt::TextureUsageBit::TransferDst);
|
||||||
|
|
||||||
|
@ -222,7 +232,7 @@ TEST_F(CopyCommandTest_B2T, ZDepthConstraintFor2DTextures) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test B2B copies with incorrect buffer usage
|
// Test B2T copies with incorrect buffer usage
|
||||||
TEST_F(CopyCommandTest_B2T, IncorrectUsage) {
|
TEST_F(CopyCommandTest_B2T, IncorrectUsage) {
|
||||||
nxt::Buffer source = CreateFrozenBuffer(16 * 4, nxt::BufferUsageBit::TransferSrc);
|
nxt::Buffer source = CreateFrozenBuffer(16 * 4, nxt::BufferUsageBit::TransferSrc);
|
||||||
nxt::Buffer vertex = CreateFrozenBuffer(16 * 4, nxt::BufferUsageBit::Vertex);
|
nxt::Buffer vertex = CreateFrozenBuffer(16 * 4, nxt::BufferUsageBit::Vertex);
|
||||||
|
@ -251,9 +261,10 @@ class CopyCommandTest_T2B : public CopyCommandTest {
|
||||||
|
|
||||||
// Test a successfull T2B copy
|
// Test a successfull T2B copy
|
||||||
TEST_F(CopyCommandTest_T2B, Success) {
|
TEST_F(CopyCommandTest_T2B, Success) {
|
||||||
|
uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
|
||||||
nxt::Texture source = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
nxt::Texture source = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
||||||
nxt::TextureUsageBit::TransferSrc);
|
nxt::TextureUsageBit::TransferSrc);
|
||||||
nxt::Buffer destination = CreateFrozenBuffer(16 * 4, nxt::BufferUsageBit::TransferDst);
|
nxt::Buffer destination = CreateFrozenBuffer(bufferSize, nxt::BufferUsageBit::TransferDst);
|
||||||
|
|
||||||
// Different copies, including some that touch the OOB condition
|
// Different copies, including some that touch the OOB condition
|
||||||
{
|
{
|
||||||
|
@ -265,7 +276,7 @@ TEST_F(CopyCommandTest_T2B, Success) {
|
||||||
// Copy from 4x4 block in the 4x4 mip.
|
// Copy from 4x4 block in the 4x4 mip.
|
||||||
.CopyTextureToBuffer(source, 0, 0, 0, 4, 4, 1, 2, destination, 0, 0)
|
.CopyTextureToBuffer(source, 0, 0, 0, 4, 4, 1, 2, destination, 0, 0)
|
||||||
// Copy with a buffer offset
|
// Copy with a buffer offset
|
||||||
.CopyTextureToBuffer(source, 0, 0, 0, 1, 1, 1, 4, destination, 15 * 4, 0)
|
.CopyTextureToBuffer(source, 0, 0, 0, 1, 1, 1, 4, destination, bufferSize - 4, 0)
|
||||||
.GetResult();
|
.GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +286,7 @@ TEST_F(CopyCommandTest_T2B, Success) {
|
||||||
// An empty copy
|
// An empty copy
|
||||||
.CopyTextureToBuffer(source, 0, 0, 0, 0, 0, 1, 0, destination, 0, 0)
|
.CopyTextureToBuffer(source, 0, 0, 0, 0, 0, 1, 0, destination, 0, 0)
|
||||||
// An empty copy touching the end of the buffer
|
// An empty copy touching the end of the buffer
|
||||||
.CopyTextureToBuffer(source, 0, 0, 0, 0, 0, 1, 0, destination, 16 * 4, 0)
|
.CopyTextureToBuffer(source, 0, 0, 0, 0, 0, 1, 0, destination, bufferSize, 0)
|
||||||
// An empty copy touching the side of the texture
|
// An empty copy touching the side of the texture
|
||||||
.CopyTextureToBuffer(source, 16, 16, 0, 0, 0, 1, 0, destination, 0, 0)
|
.CopyTextureToBuffer(source, 16, 16, 0, 0, 0, 1, 0, destination, 0, 0)
|
||||||
.GetResult();
|
.GetResult();
|
||||||
|
@ -284,9 +295,10 @@ TEST_F(CopyCommandTest_T2B, Success) {
|
||||||
|
|
||||||
// Test OOB conditions on the texture
|
// Test OOB conditions on the texture
|
||||||
TEST_F(CopyCommandTest_T2B, OutOfBoundsOnTexture) {
|
TEST_F(CopyCommandTest_T2B, OutOfBoundsOnTexture) {
|
||||||
|
uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
|
||||||
nxt::Texture source = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
nxt::Texture source = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
||||||
nxt::TextureUsageBit::TransferSrc);
|
nxt::TextureUsageBit::TransferSrc);
|
||||||
nxt::Buffer destination = CreateFrozenBuffer(16 * 4, nxt::BufferUsageBit::TransferDst);
|
nxt::Buffer destination = CreateFrozenBuffer(bufferSize, nxt::BufferUsageBit::TransferDst);
|
||||||
|
|
||||||
// OOB on the texture because x + width overflows
|
// OOB on the texture because x + width overflows
|
||||||
{
|
{
|
||||||
|
@ -319,9 +331,10 @@ TEST_F(CopyCommandTest_T2B, OutOfBoundsOnTexture) {
|
||||||
|
|
||||||
// Test OOB conditions on the buffer
|
// Test OOB conditions on the buffer
|
||||||
TEST_F(CopyCommandTest_T2B, OutOfBoundsOnBuffer) {
|
TEST_F(CopyCommandTest_T2B, OutOfBoundsOnBuffer) {
|
||||||
|
uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
|
||||||
nxt::Texture source = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
nxt::Texture source = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
||||||
nxt::TextureUsageBit::TransferSrc);
|
nxt::TextureUsageBit::TransferSrc);
|
||||||
nxt::Buffer destination = CreateFrozenBuffer(16 * 4, nxt::BufferUsageBit::TransferDst);
|
nxt::Buffer destination = CreateFrozenBuffer(bufferSize, nxt::BufferUsageBit::TransferDst);
|
||||||
|
|
||||||
// OOB on the buffer because we copy too many pixels
|
// OOB on the buffer because we copy too many pixels
|
||||||
{
|
{
|
||||||
|
@ -340,9 +353,10 @@ TEST_F(CopyCommandTest_T2B, OutOfBoundsOnBuffer) {
|
||||||
|
|
||||||
// Test that we force Z=0 and Depth=1 on copies from to 2D textures
|
// Test that we force Z=0 and Depth=1 on copies from to 2D textures
|
||||||
TEST_F(CopyCommandTest_T2B, ZDepthConstraintFor2DTextures) {
|
TEST_F(CopyCommandTest_T2B, ZDepthConstraintFor2DTextures) {
|
||||||
|
uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
|
||||||
nxt::Texture source = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
nxt::Texture source = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
||||||
nxt::TextureUsageBit::TransferSrc);
|
nxt::TextureUsageBit::TransferSrc);
|
||||||
nxt::Buffer destination = CreateFrozenBuffer(16 * 4, nxt::BufferUsageBit::TransferDst);
|
nxt::Buffer destination = CreateFrozenBuffer(bufferSize, nxt::BufferUsageBit::TransferDst);
|
||||||
|
|
||||||
// Z=1 on an empty copy still errors
|
// Z=1 on an empty copy still errors
|
||||||
{
|
{
|
||||||
|
@ -359,14 +373,15 @@ TEST_F(CopyCommandTest_T2B, ZDepthConstraintFor2DTextures) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test B2B copies with incorrect buffer usage
|
// Test T2B copies with incorrect buffer usage
|
||||||
TEST_F(CopyCommandTest_T2B, IncorrectUsage) {
|
TEST_F(CopyCommandTest_T2B, IncorrectUsage) {
|
||||||
|
uint32_t bufferSize = BufferSizeForTextureCopy(4, 4, 1);
|
||||||
nxt::Texture source = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
nxt::Texture source = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
||||||
nxt::TextureUsageBit::TransferSrc);
|
nxt::TextureUsageBit::TransferSrc);
|
||||||
nxt::Texture sampled = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
nxt::Texture sampled = CreateFrozen2DTexture(16, 16, 5, nxt::TextureFormat::R8G8B8A8Unorm,
|
||||||
nxt::TextureUsageBit::Sampled);
|
nxt::TextureUsageBit::Sampled);
|
||||||
nxt::Buffer destination = CreateFrozenBuffer(16 * 4, nxt::BufferUsageBit::TransferDst);
|
nxt::Buffer destination = CreateFrozenBuffer(bufferSize, nxt::BufferUsageBit::TransferDst);
|
||||||
nxt::Buffer vertex = CreateFrozenBuffer(16 * 4, nxt::BufferUsageBit::Vertex);
|
nxt::Buffer vertex = CreateFrozenBuffer(bufferSize, nxt::BufferUsageBit::Vertex);
|
||||||
|
|
||||||
// Incorrect source usage
|
// Incorrect source usage
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue