mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-08-09 13:39:20 +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.cpp
|
||||||
${TESTS_DIR}/NXTTest.h
|
${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)
|
NXTInternalTarget("tests" nxt_end2end_tests)
|
||||||
|
@ -14,7 +14,23 @@
|
|||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
extern bool gTestUsesWire;
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
testing::InitGoogleTest(&argc, 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();
|
return RUN_ALL_TESTS();
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,12 @@
|
|||||||
#include "utils/BackendBinding.h"
|
#include "utils/BackendBinding.h"
|
||||||
#include "utils/NXTHelpers.h"
|
#include "utils/NXTHelpers.h"
|
||||||
#include "utils/SystemUtils.h"
|
#include "utils/SystemUtils.h"
|
||||||
|
#include "wire/TerribleCommandBuffer.h"
|
||||||
|
#include "wire/Wire.h"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "GLFW/glfw3.h"
|
#include "GLFW/glfw3.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
utils::BackendType ParamToBackendType(BackendType type) {
|
utils::BackendType ParamToBackendType(BackendType type) {
|
||||||
@ -122,6 +125,8 @@ bool NXTTest::IsVulkan() const {
|
|||||||
return GetParam() == VulkanBackend;
|
return GetParam() == VulkanBackend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool gTestUsesWire = false;
|
||||||
|
|
||||||
void NXTTest::SetUp() {
|
void NXTTest::SetUp() {
|
||||||
mBinding = utils::CreateBinding(ParamToBackendType(GetParam()));
|
mBinding = utils::CreateBinding(ParamToBackendType(GetParam()));
|
||||||
NXT_ASSERT(mBinding != nullptr);
|
NXT_ASSERT(mBinding != nullptr);
|
||||||
@ -135,20 +140,50 @@ void NXTTest::SetUp() {
|
|||||||
nxtProcTable backendProcs;
|
nxtProcTable backendProcs;
|
||||||
mBinding->GetProcAndDevice(&backendProcs, &backendDevice);
|
mBinding->GetProcAndDevice(&backendProcs, &backendDevice);
|
||||||
|
|
||||||
nxtSetProcs(&backendProcs);
|
// Choose whether to use the backend procs and devices directly, or set up the wire.
|
||||||
device = nxt::Device::Acquire(backendDevice);
|
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();
|
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()
|
swapchain = device.CreateSwapChainBuilder()
|
||||||
.SetImplementation(mBinding->GetSwapChainImplementation())
|
.SetImplementation(mBinding->GetSwapChainImplementation())
|
||||||
.GetResult();
|
.GetResult();
|
||||||
swapchain.Configure(static_cast<nxt::TextureFormat>(mBinding->GetPreferredSwapChainTextureFormat()),
|
swapchain.Configure(static_cast<nxt::TextureFormat>(mBinding->GetPreferredSwapChainTextureFormat()),
|
||||||
nxt::TextureUsageBit::OutputAttachment, 400, 400);
|
nxt::TextureUsageBit::OutputAttachment, 400, 400);
|
||||||
|
|
||||||
|
// The end2end tests should never cause validation errors. These should be tested in unittests.
|
||||||
device.SetErrorCallback(DeviceErrorCauseTestFailure, 0);
|
device.SetErrorCallback(DeviceErrorCauseTestFailure, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NXTTest::TearDown() {
|
void NXTTest::TearDown() {
|
||||||
|
FlushWire();
|
||||||
|
|
||||||
MapSlotsSynchronously();
|
MapSlotsSynchronously();
|
||||||
ResolveExpectations();
|
ResolveExpectations();
|
||||||
|
|
||||||
@ -160,6 +195,13 @@ void NXTTest::TearDown() {
|
|||||||
delete expectation.expectation;
|
delete expectation.expectation;
|
||||||
expectation.expectation = nullptr;
|
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) {
|
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() {
|
void NXTTest::WaitABit() {
|
||||||
device.Tick();
|
device.Tick();
|
||||||
|
FlushWire();
|
||||||
|
|
||||||
utils::USleep(100);
|
utils::USleep(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,6 +280,13 @@ void NXTTest::SwapBuffersForCapture() {
|
|||||||
swapchain.Present(backBuffer);
|
swapchain.Present(backBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NXTTest::FlushWire() {
|
||||||
|
if (gTestUsesWire) {
|
||||||
|
mC2sBuf->Flush();
|
||||||
|
mS2cBuf->Flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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?
|
||||||
|
@ -66,74 +66,100 @@ namespace detail {
|
|||||||
class Expectation;
|
class Expectation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace nxt { namespace wire {
|
||||||
|
class CommandHandler;
|
||||||
|
class TerribleCommandBuffer;
|
||||||
|
}} // namespace nxt::wire
|
||||||
|
|
||||||
class NXTTest : public ::testing::TestWithParam<BackendType> {
|
class NXTTest : public ::testing::TestWithParam<BackendType> {
|
||||||
public:
|
public:
|
||||||
~NXTTest();
|
~NXTTest();
|
||||||
|
|
||||||
void SetUp() override;
|
void SetUp() override;
|
||||||
void TearDown() override;
|
void TearDown() override;
|
||||||
|
|
||||||
bool IsD3D12() const;
|
bool IsD3D12() const;
|
||||||
bool IsMetal() const;
|
bool IsMetal() const;
|
||||||
bool IsOpenGL() const;
|
bool IsOpenGL() const;
|
||||||
bool IsVulkan() const;
|
bool IsVulkan() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
nxt::Device device;
|
nxt::Device device;
|
||||||
nxt::Queue queue;
|
nxt::Queue queue;
|
||||||
nxt::SwapChain swapchain;
|
nxt::SwapChain swapchain;
|
||||||
|
|
||||||
// Helper methods to implement the EXPECT_ macros
|
// 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& AddBufferExpectation(const char* file,
|
||||||
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);
|
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:
|
private:
|
||||||
// MapRead buffers used to get data for the expectations
|
// Things used to set up testing through the Wire.
|
||||||
struct ReadbackSlot {
|
nxt::wire::CommandHandler* mWireServer = nullptr;
|
||||||
nxt::Buffer buffer;
|
nxt::wire::CommandHandler* mWireClient = nullptr;
|
||||||
uint32_t bufferSize;
|
nxt::wire::TerribleCommandBuffer* mC2sBuf = nullptr;
|
||||||
const void* mappedData = nullptr;
|
nxt::wire::TerribleCommandBuffer* mS2cBuf = nullptr;
|
||||||
};
|
void FlushWire();
|
||||||
std::vector<ReadbackSlot> mReadbackSlots;
|
|
||||||
|
|
||||||
// Maps all the buffers and fill ReadbackSlot::mappedData
|
// MapRead buffers used to get data for the expectations
|
||||||
void MapSlotsSynchronously();
|
struct ReadbackSlot {
|
||||||
static void SlotMapReadCallback(nxtBufferMapAsyncStatus status,
|
nxt::Buffer buffer;
|
||||||
const void* data,
|
uint32_t bufferSize;
|
||||||
nxtCallbackUserdata userdata);
|
const void* mappedData = nullptr;
|
||||||
size_t mNumPendingMapOperations = 0;
|
};
|
||||||
|
std::vector<ReadbackSlot> mReadbackSlots;
|
||||||
|
|
||||||
// Reserve space where the data for an expectation can be copied
|
// Maps all the buffers and fill ReadbackSlot::mappedData
|
||||||
struct ReadbackReservation {
|
void MapSlotsSynchronously();
|
||||||
nxt::Buffer buffer;
|
static void SlotMapReadCallback(nxtBufferMapAsyncStatus status,
|
||||||
size_t slot;
|
const void* data,
|
||||||
uint32_t offset;
|
nxtCallbackUserdata userdata);
|
||||||
};
|
size_t mNumPendingMapOperations = 0;
|
||||||
ReadbackReservation ReserveReadback(uint32_t readbackSize);
|
|
||||||
|
|
||||||
struct DeferredExpectation {
|
// Reserve space where the data for an expectation can be copied
|
||||||
const char* file;
|
struct ReadbackReservation {
|
||||||
int line;
|
nxt::Buffer buffer;
|
||||||
size_t readbackSlot;
|
size_t slot;
|
||||||
uint32_t readbackOffset;
|
uint32_t offset;
|
||||||
uint32_t size;
|
};
|
||||||
uint32_t rowBytes;
|
ReadbackReservation ReserveReadback(uint32_t readbackSize);
|
||||||
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
|
struct DeferredExpectation {
|
||||||
void ResolveExpectations();
|
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:
|
// 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