Null: implement fake async BufferMapRead

We want to test BufferMapRead validation using the null backend. To get
closer to conditions on a real backend, we call the callback only on the
next Queue::Submit. This is because on real backends, we would have to
wait for the GPU to be finished with the buffer, to be sure the correct
data is read.
This commit is contained in:
Corentin Wallez 2017-06-12 10:26:29 -04:00 committed by Corentin Wallez
parent c863b1c26f
commit 43bfaae340
2 changed files with 58 additions and 2 deletions

View File

@ -89,6 +89,13 @@ namespace null {
return new TextureViewBase(builder);
}
void Device::AddPendingOperation(std::unique_ptr<PendingOperation> operation) {
pendingOperations.emplace_back(std::move(operation));
}
std::vector<std::unique_ptr<PendingOperation>> Device::AcquirePendingOperations() {
return std::move(pendingOperations);
}
void Device::Reference() {
}
@ -97,22 +104,49 @@ namespace null {
// Buffer
struct BufferMapReadOperation : PendingOperation {
virtual void Execute() {
buffer->MapReadOperationCompleted(serial, ptr);
}
Ref<Buffer> buffer;
const void* ptr;
uint32_t serial;
};
Buffer::Buffer(BufferBuilder* builder)
: BufferBase(builder) {
if (GetAllowedUsage() & (nxt::BufferUsageBit::MapRead | nxt::BufferUsageBit::MapWrite)) {
backingData = std::unique_ptr<char[]>(new char[GetSize()]);
}
}
Buffer::~Buffer() {
}
void Buffer::MapReadOperationCompleted(uint32_t serial, const void* ptr) {
CallMapReadCallback(serial, NXT_BUFFER_MAP_READ_STATUS_SUCCESS, ptr);
}
void Buffer::SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) {
ASSERT(start + count <= GetSize());
ASSERT(backingData);
memcpy(backingData.get() + start, data, count);
}
void Buffer::MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) {
// TODO(cwallez@chromium.org): Implement Map Read for the null backend
ASSERT(start + count <= GetSize());
ASSERT(backingData);
auto operation = new BufferMapReadOperation;
operation->buffer = this;
operation->ptr = backingData.get() + start;
operation->serial = serial;
ToBackend(GetDevice())->AddPendingOperation(std::unique_ptr<PendingOperation>(operation));
}
void Buffer::UnmapImpl() {
// TODO(cwallez@chromium.org): Implement Map Read for the null backend
}
// Queue
@ -125,6 +159,13 @@ namespace null {
}
void Queue::Submit(uint32_t numCommands, CommandBuffer* const * commands) {
auto operations = ToBackend(GetDevice())->AcquirePendingOperations();
for (auto& operation : operations) {
operation->Execute();
}
operations.clear();
}
}

View File

@ -80,6 +80,11 @@ namespace null {
return ToBackendBase<NullBackendTraits>(common);
}
struct PendingOperation {
virtual ~PendingOperation() = default;
virtual void Execute() = 0;
};
class Device : public DeviceBase {
public:
Device();
@ -102,9 +107,15 @@ namespace null {
TextureBase* CreateTexture(TextureBuilder* builder) override;
TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override;
void AddPendingOperation(std::unique_ptr<PendingOperation> operation);
std::vector<std::unique_ptr<PendingOperation>> AcquirePendingOperations();
// NXT API
void Reference();
void Release();
private:
std::vector<std::unique_ptr<PendingOperation>> pendingOperations;
};
class Buffer : public BufferBase {
@ -112,10 +123,14 @@ namespace null {
Buffer(BufferBuilder* builder);
~Buffer();
void MapReadOperationCompleted(uint32_t serial, const void* ptr);
private:
void SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) override;
void MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
void UnmapImpl() override;
std::unique_ptr<char[]> backingData;
};
class Queue : public QueueBase {