Introduce end2end tests.
This commit adds a test harness that handles instantiating tests on multiple backends, and have deferred expectations on the content of resources.
This commit is contained in:
parent
ef199c0310
commit
eaae746433
|
@ -15,6 +15,8 @@
|
||||||
set(TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
set(TESTS_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
set(UNITTESTS_DIR ${TESTS_DIR}/unittests)
|
set(UNITTESTS_DIR ${TESTS_DIR}/unittests)
|
||||||
set(VALIDATION_TESTS_DIR ${UNITTESTS_DIR}/validation)
|
set(VALIDATION_TESTS_DIR ${UNITTESTS_DIR}/validation)
|
||||||
|
set(END2END_TESTS_DIR ${TESTS_DIR}/end2end)
|
||||||
|
|
||||||
add_executable(nxt_unittests
|
add_executable(nxt_unittests
|
||||||
${UNITTESTS_DIR}/BitSetIteratorTests.cpp
|
${UNITTESTS_DIR}/BitSetIteratorTests.cpp
|
||||||
${UNITTESTS_DIR}/CommandAllocatorTests.cpp
|
${UNITTESTS_DIR}/CommandAllocatorTests.cpp
|
||||||
|
@ -40,3 +42,13 @@ add_executable(nxt_unittests
|
||||||
target_link_libraries(nxt_unittests gtest nxt_backend mock_nxt nxt_wire)
|
target_link_libraries(nxt_unittests gtest nxt_backend mock_nxt nxt_wire)
|
||||||
target_include_directories(nxt_unittests PRIVATE ${SRC_DIR})
|
target_include_directories(nxt_unittests PRIVATE ${SRC_DIR})
|
||||||
SetCXX14(nxt_unittests)
|
SetCXX14(nxt_unittests)
|
||||||
|
|
||||||
|
add_executable(nxt_end2end_tests
|
||||||
|
${END2END_TESTS_DIR}/BasicTests.cpp
|
||||||
|
${TESTS_DIR}/End2EndTestsMain.cpp
|
||||||
|
${TESTS_DIR}/NXTTest.cpp
|
||||||
|
${TESTS_DIR}/NXTTest.h
|
||||||
|
)
|
||||||
|
target_link_libraries(nxt_end2end_tests gtest utils)
|
||||||
|
target_include_directories(nxt_end2end_tests PRIVATE ${SRC_DIR})
|
||||||
|
SetCXX14(nxt_end2end_tests)
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
// 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 <gtest/gtest.h>
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
testing::InitGoogleTest(&argc, argv);
|
||||||
|
return RUN_ALL_TESTS();
|
||||||
|
}
|
|
@ -0,0 +1,275 @@
|
||||||
|
// 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 "NXTTest.h"
|
||||||
|
|
||||||
|
#include "utils/BackendBinding.h"
|
||||||
|
|
||||||
|
#include "GLFW/glfw3.h"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
#define ASSERT assert
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
utils::BackendType ParamToBackendType(BackendType type) {
|
||||||
|
switch(type) {
|
||||||
|
case D3D12Backend:
|
||||||
|
return utils::BackendType::D3D12;
|
||||||
|
case MetalBackend:
|
||||||
|
return utils::BackendType::Metal;
|
||||||
|
case OpenGLBackend:
|
||||||
|
return utils::BackendType::OpenGL;
|
||||||
|
case VulkanBackend:
|
||||||
|
return utils::BackendType::Vulkan;
|
||||||
|
default:
|
||||||
|
ASSERT(false);
|
||||||
|
return utils::BackendType::Null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string ParamName(BackendType type) {
|
||||||
|
switch(type) {
|
||||||
|
case D3D12Backend:
|
||||||
|
return "D3D12";
|
||||||
|
case MetalBackend:
|
||||||
|
return "Metal";
|
||||||
|
case OpenGLBackend:
|
||||||
|
return "OpenGL";
|
||||||
|
case VulkanBackend:
|
||||||
|
return "Vulkan";
|
||||||
|
default:
|
||||||
|
ASSERT(false);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Windows don't usually like to be bound to one API than the other, for example switching
|
||||||
|
// from Vulkan to OpenGL causes crashes on some drivers. Because of this, we lazily created
|
||||||
|
// a window for each backing API.
|
||||||
|
GLFWwindow* windows[NumBackendTypes];
|
||||||
|
|
||||||
|
// Creates a GLFW window set up for use with a given backend.
|
||||||
|
GLFWwindow* GetWindowForBackend(utils::BackendBinding* binding, BackendType type) {
|
||||||
|
GLFWwindow** window = &windows[type];
|
||||||
|
|
||||||
|
if (*window != nullptr) {
|
||||||
|
return *window;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!glfwInit()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
glfwDefaultWindowHints();
|
||||||
|
binding->SetupGLFWWindowHints();
|
||||||
|
|
||||||
|
std::string windowName = "NXT " + ParamName(type) + " test window";
|
||||||
|
*window = glfwCreateWindow(400, 400, windowName.c_str(), nullptr, nullptr);
|
||||||
|
|
||||||
|
return *window;
|
||||||
|
}
|
||||||
|
|
||||||
|
// End2end tests should test valid commands produce the expected result so no error
|
||||||
|
// should happen. Failure cases should be tested in the validation tests.
|
||||||
|
void DeviceErrorCauseTestFailure(const char* message, nxtCallbackUserdata) {
|
||||||
|
FAIL() << "Device level failure: " << message;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MapReadUserdata {
|
||||||
|
NXTTest* test;
|
||||||
|
size_t slot;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
NXTTest::~NXTTest() {
|
||||||
|
// We need to destroy child objects before the Device
|
||||||
|
readbackSlots.clear();
|
||||||
|
queue = nxt::Queue();
|
||||||
|
device = nxt::Device();
|
||||||
|
|
||||||
|
delete binding;
|
||||||
|
binding = nullptr;
|
||||||
|
|
||||||
|
nxtSetProcs(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NXTTest::SetUp() {
|
||||||
|
binding = utils::CreateBinding(ParamToBackendType(GetParam()));
|
||||||
|
ASSERT(binding != nullptr);
|
||||||
|
|
||||||
|
GLFWwindow* testWindow = GetWindowForBackend(binding, GetParam());
|
||||||
|
ASSERT(testWindow != nullptr);
|
||||||
|
|
||||||
|
binding->SetWindow(testWindow);
|
||||||
|
|
||||||
|
nxtDevice backendDevice;
|
||||||
|
nxtProcTable backendProcs;
|
||||||
|
binding->GetProcAndDevice(&backendProcs, &backendDevice);
|
||||||
|
|
||||||
|
nxtSetProcs(&backendProcs);
|
||||||
|
device = nxt::Device::Acquire(backendDevice);
|
||||||
|
queue = device.CreateQueueBuilder().GetResult();
|
||||||
|
|
||||||
|
device.SetErrorCallback(DeviceErrorCauseTestFailure, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NXTTest::TearDown() {
|
||||||
|
MapSlotsSynchronously();
|
||||||
|
ResolveExpectations();
|
||||||
|
|
||||||
|
for (auto& expectation : deferredExpectations) {
|
||||||
|
delete expectation.expectation;
|
||||||
|
expectation.expectation = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NXTTest::AddBufferExpectation(const char* file, int line, const nxt::Buffer& buffer, uint32_t offset, uint32_t size, detail::Expectation* expectation) {
|
||||||
|
nxt::Buffer source = buffer.Clone();
|
||||||
|
|
||||||
|
auto readback = ReserveReadback(size);
|
||||||
|
|
||||||
|
// We need to enqueue the copy immediately because by the time we resolve the expectation,
|
||||||
|
// the buffer might have been modified.
|
||||||
|
nxt::CommandBuffer commands = device.CreateCommandBufferBuilder()
|
||||||
|
.TransitionBufferUsage(source, nxt::BufferUsageBit::TransferSrc)
|
||||||
|
.TransitionBufferUsage(readback.buffer, nxt::BufferUsageBit::TransferDst)
|
||||||
|
.CopyBufferToBuffer(source, offset, readback.buffer, readback.offset, size)
|
||||||
|
.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) {
|
||||||
|
// For now create a new MapRead buffer for each readback
|
||||||
|
// TODO(cwallez@chromium.org): eventually make bigger buffers and allocate linearly?
|
||||||
|
ReadbackSlot slot;
|
||||||
|
slot.bufferSize = readbackSize;
|
||||||
|
slot.buffer = device.CreateBufferBuilder()
|
||||||
|
.SetSize(readbackSize)
|
||||||
|
.SetAllowedUsage(nxt::BufferUsageBit::MapRead | nxt::BufferUsageBit::TransferDst)
|
||||||
|
.SetInitialUsage(nxt::BufferUsageBit::TransferDst)
|
||||||
|
.GetResult();
|
||||||
|
|
||||||
|
ReadbackReservation reservation;
|
||||||
|
reservation.buffer = slot.buffer.Clone();
|
||||||
|
reservation.slot = readbackSlots.size();
|
||||||
|
reservation.offset = 0;
|
||||||
|
|
||||||
|
readbackSlots.push_back(std::move(slot));
|
||||||
|
return reservation;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NXTTest::MapSlotsSynchronously() {
|
||||||
|
// Initialize numPendingMapOperations before mapping, just in case the callback is called immediately.
|
||||||
|
numPendingMapOperations = readbackSlots.size();
|
||||||
|
|
||||||
|
// Map all readback slots
|
||||||
|
for (size_t i = 0; i < readbackSlots.size(); ++i) {
|
||||||
|
auto userdata = new MapReadUserdata{this, i};
|
||||||
|
|
||||||
|
auto& slot = readbackSlots[i];
|
||||||
|
slot.buffer.TransitionUsage(nxt::BufferUsageBit::MapRead);
|
||||||
|
slot.buffer.MapReadAsync(0, slot.bufferSize, SlotMapReadCallback, static_cast<nxt::CallbackUserdata>(reinterpret_cast<uintptr_t>(userdata)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Busy wait until all map operations are done.
|
||||||
|
// TODO(cwallez@chromium.org): usleep a bit?
|
||||||
|
while (numPendingMapOperations != 0) {
|
||||||
|
device.Tick();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void NXTTest::SlotMapReadCallback(nxtBufferMapReadStatus status, const void* data, nxtCallbackUserdata userdata_) {
|
||||||
|
ASSERT(status == NXT_BUFFER_MAP_READ_STATUS_SUCCESS);
|
||||||
|
|
||||||
|
auto userdata = reinterpret_cast<MapReadUserdata*>(static_cast<uintptr_t>(userdata_));
|
||||||
|
userdata->test->readbackSlots[userdata->slot].mappedData = data;
|
||||||
|
userdata->test->numPendingMapOperations --;
|
||||||
|
|
||||||
|
delete userdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NXTTest::ResolveExpectations() {
|
||||||
|
for(const auto& expectation : deferredExpectations) {
|
||||||
|
ASSERT(readbackSlots[expectation.readbackSlot].mappedData != nullptr);
|
||||||
|
|
||||||
|
// Get a pointer to the mapped copy of the data for the expectation.
|
||||||
|
const char* data = reinterpret_cast<const char*>(readbackSlots[expectation.readbackSlot].mappedData);
|
||||||
|
data += expectation.readbackOffset;
|
||||||
|
|
||||||
|
// Get the result for the expectation and add context to failures
|
||||||
|
testing::AssertionResult result = expectation.expectation->Check(data, expectation.size);
|
||||||
|
if (!result) {
|
||||||
|
result << " Expectation created at " << expectation.file << ":" << expectation.line;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_TRUE(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
bool IsBackendAvailable(BackendType type) {
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
return type == MetalBackend;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<BackendType> FilterBackends(const BackendType* types, size_t numParams) {
|
||||||
|
std::vector<BackendType> backends;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < numParams; ++i) {
|
||||||
|
if (IsBackendAvailable(types[i])) {
|
||||||
|
backends.push_back(types[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return backends;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper classes to set expectations
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
ExpectEq<T>::ExpectEq(T singleValue) {
|
||||||
|
expected.push_back(singleValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
testing::AssertionResult ExpectEq<T>::Check(const void* data, size_t size) {
|
||||||
|
ASSERT(size == sizeof(T) * expected.size());
|
||||||
|
|
||||||
|
const T* actual = reinterpret_cast<const T*>(data);
|
||||||
|
for (size_t i = 0; i < expected.size(); ++i) {
|
||||||
|
if (actual[i] != expected[i]) {
|
||||||
|
return testing::AssertionFailure() << "Expected data[" << i << "] to be " << expected[i] << ", actual " << actual[i] << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return testing::AssertionSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
template class ExpectEq<uint32_t>;
|
||||||
|
}
|
|
@ -0,0 +1,129 @@
|
||||||
|
// 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>
|
||||||
|
|
||||||
|
// 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 TransferDst 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));
|
||||||
|
|
||||||
|
// Backend types used in the NXT_INSTANTIATE_TEST
|
||||||
|
enum BackendType {
|
||||||
|
D3D12Backend,
|
||||||
|
MetalBackend,
|
||||||
|
OpenGLBackend,
|
||||||
|
VulkanBackend,
|
||||||
|
NumBackendTypes,
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace utils {
|
||||||
|
class BackendBinding;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace detail {
|
||||||
|
class Expectation;
|
||||||
|
}
|
||||||
|
|
||||||
|
class NXTTest : public ::testing::TestWithParam<BackendType> {
|
||||||
|
public:
|
||||||
|
~NXTTest();
|
||||||
|
|
||||||
|
void SetUp() override;
|
||||||
|
void TearDown() override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
nxt::Device device;
|
||||||
|
nxt::Queue queue;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
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> readbackSlots;
|
||||||
|
|
||||||
|
// Maps all the buffers and fill ReadbackSlot::mappedData
|
||||||
|
void MapSlotsSynchronously();
|
||||||
|
static void SlotMapReadCallback(nxtBufferMapReadStatus status, const void* data, nxtCallbackUserdata userdata);
|
||||||
|
size_t numPendingMapOperations = 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;
|
||||||
|
detail::Expectation* expectation;
|
||||||
|
};
|
||||||
|
std::vector<DeferredExpectation> deferredExpectations;
|
||||||
|
|
||||||
|
// Assuming the data is mapped, checks all expectations
|
||||||
|
void ResolveExpectations();
|
||||||
|
|
||||||
|
utils::BackendBinding* binding = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Instantiate the test once for each backend provided after the first argument. Use it like this:
|
||||||
|
// NXT_INSTANTIATE_TEST(MyTestFixture, OpenGLBackend, MetalBackend)
|
||||||
|
#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);
|
||||||
|
|
||||||
|
testing::AssertionResult Check(const void* data, size_t size) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<T> expected;
|
||||||
|
};
|
||||||
|
extern template class ExpectEq<uint32_t>;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
// 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 "tests/NXTTest.h"
|
||||||
|
|
||||||
|
class BasicTests : public NXTTest {
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test Buffer::SetSubData changes the content of the buffer, but really this is the most
|
||||||
|
// basic test possible, and tests the test harness
|
||||||
|
TEST_P(BasicTests, BufferSetSubData) {
|
||||||
|
nxt::Buffer buffer = device.CreateBufferBuilder()
|
||||||
|
.SetSize(4)
|
||||||
|
.SetAllowedUsage(nxt::BufferUsageBit::TransferSrc | nxt::BufferUsageBit::TransferDst)
|
||||||
|
.SetInitialUsage(nxt::BufferUsageBit::TransferDst)
|
||||||
|
.GetResult();
|
||||||
|
|
||||||
|
uint32_t value = 3094587;
|
||||||
|
buffer.SetSubData(0, 1, &value);
|
||||||
|
|
||||||
|
EXPECT_BUFFER_U32_EQ(value, buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
NXT_INSTANTIATE_TEST(BasicTests, MetalBackend)
|
|
@ -31,6 +31,8 @@ namespace utils {
|
||||||
|
|
||||||
class BackendBinding {
|
class BackendBinding {
|
||||||
public:
|
public:
|
||||||
|
virtual ~BackendBinding() = default;
|
||||||
|
|
||||||
virtual void SetupGLFWWindowHints() = 0;
|
virtual void SetupGLFWWindowHints() = 0;
|
||||||
virtual void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) = 0;
|
virtual void GetProcAndDevice(nxtProcTable* procs, nxtDevice* device) = 0;
|
||||||
virtual void SwapBuffers() = 0;
|
virtual void SwapBuffers() = 0;
|
||||||
|
|
Loading…
Reference in New Issue