Add a readpixel test

This commit is contained in:
Corentin Wallez 2017-06-27 00:11:16 -04:00 committed by Corentin Wallez
parent cd13691783
commit 4cd65f03b7
3 changed files with 85 additions and 0 deletions

View File

@ -161,6 +161,34 @@ void NXTTest::AddBufferExpectation(const char* file, int line, const nxt::Buffer
deferredExpectations.push_back(deferred); deferredExpectations.push_back(deferred);
} }
void NXTTest::AddTextureExpectation(const char* file, int line, const nxt::Texture& texture, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t pixelSize, detail::Expectation* expectation) {
nxt::Texture source = texture.Clone();
uint32_t size = width * height * pixelSize;
auto readback = ReserveReadback(size);
// We need to enqueue the copy immediately because by the time we resolve the expectation,
// the texture might have been modified.
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.TransitionTextureUsage(source, nxt::TextureUsageBit::TransferSrc)
.TransitionBufferUsage(readback.buffer, nxt::BufferUsageBit::TransferDst)
.CopyTextureToBuffer(source, x, y, 0, width, height, 1, 0, readback.buffer, readback.offset)
.GetResult();
queue.Submit(1, &commands);
DeferredExpectation deferred;
deferred.file = file;
deferred.line = line;
deferred.readbackSlot = readback.slot;
deferred.readbackOffset = readback.offset;
deferred.size = size;
deferred.expectation = expectation;
deferredExpectations.push_back(deferred);
}
NXTTest::ReadbackReservation NXTTest::ReserveReadback(uint32_t readbackSize) { NXTTest::ReadbackReservation NXTTest::ReserveReadback(uint32_t readbackSize) {
// For now create a new MapRead buffer for each readback // For now create a new MapRead buffer for each readback
// TODO(cwallez@chromium.org): eventually make bigger buffers and allocate linearly? // TODO(cwallez@chromium.org): eventually make bigger buffers and allocate linearly?
@ -230,6 +258,22 @@ void NXTTest::ResolveExpectations() {
} }
} }
bool RGBA8::operator==(const RGBA8& other) const {
return r == other.r && g == other.g && b == other.b && a == other.a;
}
bool RGBA8::operator!=(const RGBA8& other) const {
return !(*this == other);
}
std::ostream& operator<< (std::ostream& stream, const RGBA8& color) {
return stream << "RGBA8(" <<
static_cast<int>(color.r) << ", " <<
static_cast<int>(color.g) << ", " <<
static_cast<int>(color.b) << ", " <<
static_cast<int>(color.a) << ")";
}
namespace detail { namespace detail {
bool IsBackendAvailable(BackendType type) { bool IsBackendAvailable(BackendType type) {
#if defined(__APPLE__) #if defined(__APPLE__)
@ -272,4 +316,5 @@ namespace detail {
} }
template class ExpectEq<uint32_t>; template class ExpectEq<uint32_t>;
template class ExpectEq<RGBA8>;
} }

View File

@ -22,6 +22,20 @@
#define EXPECT_BUFFER_U32_EQ(expected, buffer, offset) \ #define EXPECT_BUFFER_U32_EQ(expected, buffer, offset) \
AddBufferExpectation(__FILE__, __LINE__, buffer, offset, sizeof(uint32_t), new detail::ExpectEq<uint32_t>(expected)); AddBufferExpectation(__FILE__, __LINE__, buffer, offset, sizeof(uint32_t), new detail::ExpectEq<uint32_t>(expected));
// Test a pixel of the mip level 0 of a 2D texture.
#define EXPECT_PIXEL_RGBA8_EQ(expected, texture, x, y) \
AddTextureExpectation(__FILE__, __LINE__, texture, x, y, 1, 1, sizeof(RGBA8), new detail::ExpectEq<RGBA8>(expected));
struct RGBA8 {
constexpr RGBA8(uint8_t r, uint8_t g, uint8_t b, uint8_t a): r(r), g(g), b(b), a(a) {
}
bool operator==(const RGBA8& other) const;
bool operator!=(const RGBA8& other) const;
uint8_t r, g, b, a;
};
std::ostream& operator<< (std::ostream& stream, const RGBA8& color);
// Backend types used in the NXT_INSTANTIATE_TEST // Backend types used in the NXT_INSTANTIATE_TEST
enum BackendType { enum BackendType {
D3D12Backend, D3D12Backend,
@ -52,6 +66,7 @@ class NXTTest : public ::testing::TestWithParam<BackendType> {
// Helper methods to implement the EXPECT_ macros // Helper methods to implement the EXPECT_ macros
void AddBufferExpectation(const char* file, int line, const nxt::Buffer& buffer, uint32_t offset, uint32_t size, detail::Expectation* expectation); void AddBufferExpectation(const char* file, int line, const nxt::Buffer& buffer, uint32_t offset, uint32_t size, detail::Expectation* expectation);
void AddTextureExpectation(const char* file, int line, const nxt::Texture& texture, uint32_t x, uint32_t y, uint32_t width, uint32_t height, uint32_t pixelSize, detail::Expectation* expectation);
private: private:
// MapRead buffers used to get data for the expectations // MapRead buffers used to get data for the expectations
@ -125,5 +140,6 @@ namespace detail {
std::vector<T> expected; std::vector<T> expected;
}; };
extern template class ExpectEq<uint32_t>; extern template class ExpectEq<uint32_t>;
extern template class ExpectEq<RGBA8>;
} }

View File

@ -14,6 +14,8 @@
#include "tests/NXTTest.h" #include "tests/NXTTest.h"
#include "utils/NXTHelpers.h"
class BasicTests : public NXTTest { class BasicTests : public NXTTest {
}; };
@ -32,4 +34,26 @@ TEST_P(BasicTests, BufferSetSubData) {
EXPECT_BUFFER_U32_EQ(value, buffer, 0); EXPECT_BUFFER_U32_EQ(value, buffer, 0);
} }
TEST_P(BasicTests, ReadPixelsTest) {
RGBA8 red(255, 0, 0, 255);
nxt::Buffer buffer = utils::CreateFrozenBufferFromData(device, &red, sizeof(red), nxt::BufferUsageBit::TransferSrc);
nxt::Texture texture = device.CreateTextureBuilder()
.SetDimension(nxt::TextureDimension::e2D)
.SetExtent(1, 1, 1)
.SetMipLevels(1)
.SetAllowedUsage(nxt::TextureUsageBit::TransferSrc | nxt::TextureUsageBit::TransferDst)
.SetFormat(nxt::TextureFormat::R8G8B8A8Unorm)
.GetResult();
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
.TransitionTextureUsage(texture, nxt::TextureUsageBit::TransferDst)
.CopyBufferToTexture(buffer, 0, texture, 0, 0, 0, 1, 1, 1, 0)
.GetResult();
queue.Submit(1, &commands);
EXPECT_PIXEL_RGBA8_EQ(red, texture, 0, 0);
}
NXT_INSTANTIATE_TEST(BasicTests, MetalBackend) NXT_INSTANTIATE_TEST(BasicTests, MetalBackend)