mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-08-05 19:55:37 +00:00
NXTTest: add -w to run the end2end tests through the wire
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*
This commit is contained in:
parent
862f884a65
commit
419e9841a8
@ -90,5 +90,5 @@ add_executable(nxt_end2end_tests
|
||||
${TESTS_DIR}/NXTTest.cpp
|
||||
${TESTS_DIR}/NXTTest.h
|
||||
)
|
||||
target_link_libraries(nxt_end2end_tests nxt_common gtest utils)
|
||||
target_link_libraries(nxt_end2end_tests nxt_common nxt_wire gtest utils)
|
||||
NXTInternalTarget("tests" nxt_end2end_tests)
|
||||
|
@ -14,7 +14,23 @@
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
extern bool gTestUsesWire;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
for (int i = 1; i < argc; ++i) {
|
||||
if (strcmp("-w", argv[i]) == 0 || strcmp("--use-wire", argv[i]) == 0) {
|
||||
gTestUsesWire = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp("-h", argv[i]) == 0 || strcmp("--help", argv[i]) == 0) {
|
||||
printf("\n\nUsage: %s [GTEST_FLAGS...] [-w] \n", argv[0]);
|
||||
printf(" -w, --use-wire: Run the tests through the wire (defaults to no wire)\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
@ -20,9 +20,12 @@
|
||||
#include "utils/BackendBinding.h"
|
||||
#include "utils/NXTHelpers.h"
|
||||
#include "utils/SystemUtils.h"
|
||||
#include "wire/TerribleCommandBuffer.h"
|
||||
#include "wire/Wire.h"
|
||||
|
||||
#include <iostream>
|
||||
#include "GLFW/glfw3.h"
|
||||
|
||||
namespace {
|
||||
|
||||
utils::BackendType ParamToBackendType(BackendType type) {
|
||||
@ -122,6 +125,8 @@ bool NXTTest::IsVulkan() const {
|
||||
return GetParam() == VulkanBackend;
|
||||
}
|
||||
|
||||
bool gTestUsesWire = false;
|
||||
|
||||
void NXTTest::SetUp() {
|
||||
mBinding = utils::CreateBinding(ParamToBackendType(GetParam()));
|
||||
NXT_ASSERT(mBinding != nullptr);
|
||||
@ -135,20 +140,50 @@ void NXTTest::SetUp() {
|
||||
nxtProcTable backendProcs;
|
||||
mBinding->GetProcAndDevice(&backendProcs, &backendDevice);
|
||||
|
||||
nxtSetProcs(&backendProcs);
|
||||
device = nxt::Device::Acquire(backendDevice);
|
||||
// Choose whether to use the backend procs and devices directly, or set up the wire.
|
||||
nxtDevice cDevice = nullptr;
|
||||
nxtProcTable procs;
|
||||
|
||||
if (gTestUsesWire) {
|
||||
mC2sBuf = new nxt::wire::TerribleCommandBuffer();
|
||||
mS2cBuf = new nxt::wire::TerribleCommandBuffer();
|
||||
|
||||
mWireServer = nxt::wire::NewServerCommandHandler(backendDevice, backendProcs, mS2cBuf);
|
||||
mC2sBuf->SetHandler(mWireServer);
|
||||
|
||||
nxtDevice clientDevice;
|
||||
nxtProcTable clientProcs;
|
||||
mWireClient = nxt::wire::NewClientDevice(&clientProcs, &clientDevice, mC2sBuf);
|
||||
mS2cBuf->SetHandler(mWireClient);
|
||||
|
||||
procs = clientProcs;
|
||||
cDevice = clientDevice;
|
||||
} else {
|
||||
procs = backendProcs;
|
||||
cDevice = backendDevice;
|
||||
}
|
||||
|
||||
// Set up the device and queue because all tests need them, and NXTTest needs them too for the
|
||||
// deferred expectations.
|
||||
nxtSetProcs(&procs);
|
||||
device = nxt::Device::Acquire(cDevice);
|
||||
queue = device.CreateQueueBuilder().GetResult();
|
||||
|
||||
// The swapchain isn't used by tests but is useful when debugging with graphics debuggers that
|
||||
// capture at frame boundaries.
|
||||
swapchain = device.CreateSwapChainBuilder()
|
||||
.SetImplementation(mBinding->GetSwapChainImplementation())
|
||||
.GetResult();
|
||||
swapchain.Configure(static_cast<nxt::TextureFormat>(mBinding->GetPreferredSwapChainTextureFormat()),
|
||||
nxt::TextureUsageBit::OutputAttachment, 400, 400);
|
||||
|
||||
// The end2end tests should never cause validation errors. These should be tested in unittests.
|
||||
device.SetErrorCallback(DeviceErrorCauseTestFailure, 0);
|
||||
}
|
||||
|
||||
void NXTTest::TearDown() {
|
||||
FlushWire();
|
||||
|
||||
MapSlotsSynchronously();
|
||||
ResolveExpectations();
|
||||
|
||||
@ -160,6 +195,13 @@ void NXTTest::TearDown() {
|
||||
delete expectation.expectation;
|
||||
expectation.expectation = nullptr;
|
||||
}
|
||||
|
||||
if (gTestUsesWire) {
|
||||
delete mC2sBuf;
|
||||
delete mS2cBuf;
|
||||
delete mWireClient;
|
||||
delete mWireServer;
|
||||
}
|
||||
}
|
||||
|
||||
std::ostringstream& NXTTest::AddBufferExpectation(const char* file, int line, const nxt::Buffer& buffer, uint32_t offset, uint32_t size, detail::Expectation* expectation) {
|
||||
@ -226,6 +268,8 @@ std::ostringstream& NXTTest::AddTextureExpectation(const char* file, int line, c
|
||||
|
||||
void NXTTest::WaitABit() {
|
||||
device.Tick();
|
||||
FlushWire();
|
||||
|
||||
utils::USleep(100);
|
||||
}
|
||||
|
||||
@ -236,6 +280,13 @@ void NXTTest::SwapBuffersForCapture() {
|
||||
swapchain.Present(backBuffer);
|
||||
}
|
||||
|
||||
void NXTTest::FlushWire() {
|
||||
if (gTestUsesWire) {
|
||||
mC2sBuf->Flush();
|
||||
mS2cBuf->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
NXTTest::ReadbackReservation NXTTest::ReserveReadback(uint32_t readbackSize) {
|
||||
// For now create a new MapRead buffer for each readback
|
||||
// TODO(cwallez@chromium.org): eventually make bigger buffers and allocate linearly?
|
||||
|
@ -66,74 +66,100 @@ namespace detail {
|
||||
class Expectation;
|
||||
}
|
||||
|
||||
namespace nxt { namespace wire {
|
||||
class CommandHandler;
|
||||
class TerribleCommandBuffer;
|
||||
}} // namespace nxt::wire
|
||||
|
||||
class NXTTest : public ::testing::TestWithParam<BackendType> {
|
||||
public:
|
||||
~NXTTest();
|
||||
public:
|
||||
~NXTTest();
|
||||
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
|
||||
bool IsD3D12() const;
|
||||
bool IsMetal() const;
|
||||
bool IsOpenGL() const;
|
||||
bool IsVulkan() const;
|
||||
bool IsD3D12() const;
|
||||
bool IsMetal() const;
|
||||
bool IsOpenGL() const;
|
||||
bool IsVulkan() const;
|
||||
|
||||
protected:
|
||||
nxt::Device device;
|
||||
nxt::Queue queue;
|
||||
nxt::SwapChain swapchain;
|
||||
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);
|
||||
// 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 WaitABit();
|
||||
|
||||
void SwapBuffersForCapture();
|
||||
void SwapBuffersForCapture();
|
||||
|
||||
private:
|
||||
// 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;
|
||||
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();
|
||||
|
||||
// Maps all the buffers and fill ReadbackSlot::mappedData
|
||||
void MapSlotsSynchronously();
|
||||
static void SlotMapReadCallback(nxtBufferMapAsyncStatus status,
|
||||
const void* data,
|
||||
nxtCallbackUserdata userdata);
|
||||
size_t mNumPendingMapOperations = 0;
|
||||
// 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;
|
||||
|
||||
// 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);
|
||||
// Maps all the buffers and fill ReadbackSlot::mappedData
|
||||
void MapSlotsSynchronously();
|
||||
static void SlotMapReadCallback(nxtBufferMapAsyncStatus status,
|
||||
const void* data,
|
||||
nxtCallbackUserdata userdata);
|
||||
size_t mNumPendingMapOperations = 0;
|
||||
|
||||
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;
|
||||
// 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);
|
||||
|
||||
// Assuming the data is mapped, checks all expectations
|
||||
void ResolveExpectations();
|
||||
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;
|
||||
|
||||
utils::BackendBinding* mBinding = nullptr;
|
||||
// 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:
|
||||
|
Loading…
x
Reference in New Issue
Block a user