mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-08-17 09:21:45 +00:00
This will be useful to provide additional coverage of the wire in addition to the very focused WireTests unittests. All tests pass except the MapWriteAsync ones that aren't implemented in the wire yet. They can be skipped with --gtest_filter=-*MapWrite*
204 lines
7.6 KiB
C++
204 lines
7.6 KiB
C++
// Copyright 2017 The NXT 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 "nxt/nxtcpp.h"
|
|
|
|
#include <gtest/gtest.h>
|
|
#include <memory>
|
|
|
|
// Getting data back from NXT is done in an async manners so all expectations are "deferred"
|
|
// until the end of the test. Also expectations use a copy to a MapRead buffer to get the data
|
|
// so resources should have the TransferSrc allowed usage bit if you want to add expectations on them.
|
|
#define EXPECT_BUFFER_U32_EQ(expected, buffer, offset) \
|
|
AddBufferExpectation(__FILE__, __LINE__, buffer, offset, sizeof(uint32_t), new detail::ExpectEq<uint32_t>(expected))
|
|
|
|
#define EXPECT_BUFFER_U32_RANGE_EQ(expected, buffer, offset, count) \
|
|
AddBufferExpectation(__FILE__, __LINE__, buffer, offset, sizeof(uint32_t) * count, new detail::ExpectEq<uint32_t>(expected, count))
|
|
|
|
#define EXPECT_BUFFER_U8_EQ(expected, buffer, offset) \
|
|
AddBufferExpectation(__FILE__, __LINE__, buffer, offset, sizeof(uint8_t), \
|
|
new detail::ExpectEq<uint8_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, 0, sizeof(RGBA8), new detail::ExpectEq<RGBA8>(expected))
|
|
|
|
#define EXPECT_TEXTURE_RGBA8_EQ(expected, texture, x, y, width, height, level) \
|
|
AddTextureExpectation(__FILE__, __LINE__, texture, x, y, width, height, level, sizeof(RGBA8), new detail::ExpectEq<RGBA8>(expected, (width) * (height)))
|
|
|
|
struct RGBA8 {
|
|
constexpr RGBA8() : RGBA8(0,0,0,0) {}
|
|
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
|
|
enum BackendType {
|
|
D3D12Backend,
|
|
MetalBackend,
|
|
OpenGLBackend,
|
|
VulkanBackend,
|
|
NumBackendTypes,
|
|
};
|
|
std::ostream &operator<<(std::ostream& stream, BackendType backend);
|
|
|
|
namespace utils {
|
|
class BackendBinding;
|
|
}
|
|
|
|
namespace detail {
|
|
class Expectation;
|
|
}
|
|
|
|
namespace nxt { namespace wire {
|
|
class CommandHandler;
|
|
class TerribleCommandBuffer;
|
|
}} // namespace nxt::wire
|
|
|
|
class NXTTest : public ::testing::TestWithParam<BackendType> {
|
|
public:
|
|
~NXTTest();
|
|
|
|
void SetUp() override;
|
|
void TearDown() override;
|
|
|
|
bool IsD3D12() const;
|
|
bool IsMetal() const;
|
|
bool IsOpenGL() const;
|
|
bool IsVulkan() const;
|
|
|
|
protected:
|
|
nxt::Device device;
|
|
nxt::Queue queue;
|
|
nxt::SwapChain swapchain;
|
|
|
|
// Helper methods to implement the EXPECT_ macros
|
|
std::ostringstream& AddBufferExpectation(const char* file,
|
|
int line,
|
|
const nxt::Buffer& buffer,
|
|
uint32_t offset,
|
|
uint32_t size,
|
|
detail::Expectation* expectation);
|
|
std::ostringstream& AddTextureExpectation(const char* file,
|
|
int line,
|
|
const nxt::Texture& texture,
|
|
uint32_t x,
|
|
uint32_t y,
|
|
uint32_t width,
|
|
uint32_t height,
|
|
uint32_t level,
|
|
uint32_t pixelSize,
|
|
detail::Expectation* expectation);
|
|
|
|
void WaitABit();
|
|
|
|
void SwapBuffersForCapture();
|
|
|
|
private:
|
|
// Things used to set up testing through the Wire.
|
|
nxt::wire::CommandHandler* mWireServer = nullptr;
|
|
nxt::wire::CommandHandler* mWireClient = nullptr;
|
|
nxt::wire::TerribleCommandBuffer* mC2sBuf = nullptr;
|
|
nxt::wire::TerribleCommandBuffer* mS2cBuf = nullptr;
|
|
void FlushWire();
|
|
|
|
// MapRead buffers used to get data for the expectations
|
|
struct ReadbackSlot {
|
|
nxt::Buffer buffer;
|
|
uint32_t bufferSize;
|
|
const void* mappedData = nullptr;
|
|
};
|
|
std::vector<ReadbackSlot> mReadbackSlots;
|
|
|
|
// Maps all the buffers and fill ReadbackSlot::mappedData
|
|
void MapSlotsSynchronously();
|
|
static void SlotMapReadCallback(nxtBufferMapAsyncStatus status,
|
|
const void* data,
|
|
nxtCallbackUserdata userdata);
|
|
size_t mNumPendingMapOperations = 0;
|
|
|
|
// Reserve space where the data for an expectation can be copied
|
|
struct ReadbackReservation {
|
|
nxt::Buffer buffer;
|
|
size_t slot;
|
|
uint32_t offset;
|
|
};
|
|
ReadbackReservation ReserveReadback(uint32_t readbackSize);
|
|
|
|
struct DeferredExpectation {
|
|
const char* file;
|
|
int line;
|
|
size_t readbackSlot;
|
|
uint32_t readbackOffset;
|
|
uint32_t size;
|
|
uint32_t rowBytes;
|
|
uint32_t rowPitch;
|
|
detail::Expectation* expectation;
|
|
// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54316
|
|
// Use unique_ptr because of missing move/copy constructors on std::basic_ostringstream
|
|
std::unique_ptr<std::ostringstream> message;
|
|
};
|
|
std::vector<DeferredExpectation> mDeferredExpectations;
|
|
|
|
// Assuming the data is mapped, checks all expectations
|
|
void ResolveExpectations();
|
|
|
|
utils::BackendBinding* mBinding = nullptr;
|
|
};
|
|
|
|
// Instantiate the test once for each backend provided after the first argument. Use it like this:
|
|
// NXT_INSTANTIATE_TEST(MyTestFixture, MetalBackend, OpenGLBackend)
|
|
#define NXT_INSTANTIATE_TEST(testName, firstParam, ...) \
|
|
const decltype(firstParam) testName##params[] = { firstParam, ##__VA_ARGS__ }; \
|
|
INSTANTIATE_TEST_CASE_P(, testName, \
|
|
testing::ValuesIn(::detail::FilterBackends(testName##params, sizeof(testName##params) / sizeof(firstParam))), \
|
|
testing::PrintToStringParamName());
|
|
|
|
namespace detail {
|
|
// Helper functions used for NXT_INSTANTIATE_TEST
|
|
bool IsBackendAvailable(BackendType type);
|
|
std::vector<BackendType> FilterBackends(const BackendType* types, size_t numParams);
|
|
|
|
// All classes used to implement the deferred expectations should inherit from this.
|
|
class Expectation {
|
|
public:
|
|
virtual ~Expectation() = default;
|
|
|
|
// Will be called with the buffer or texture data the expectation should check.
|
|
virtual testing::AssertionResult Check(const void* data, size_t size) = 0;
|
|
};
|
|
|
|
// Expectation that checks the data is equal to some expected values.
|
|
template<typename T>
|
|
class ExpectEq : public Expectation {
|
|
public:
|
|
ExpectEq(T singleValue);
|
|
ExpectEq(const T* values, const unsigned int count);
|
|
|
|
testing::AssertionResult Check(const void* data, size_t size) override;
|
|
|
|
private:
|
|
std::vector<T> mExpected;
|
|
};
|
|
extern template class ExpectEq<uint8_t>;
|
|
extern template class ExpectEq<uint32_t>;
|
|
extern template class ExpectEq<RGBA8>;
|
|
}
|
|
|