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); 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() { void Device::Reference() {
} }
@ -97,22 +104,49 @@ namespace null {
// Buffer // Buffer
struct BufferMapReadOperation : PendingOperation {
virtual void Execute() {
buffer->MapReadOperationCompleted(serial, ptr);
}
Ref<Buffer> buffer;
const void* ptr;
uint32_t serial;
};
Buffer::Buffer(BufferBuilder* builder) Buffer::Buffer(BufferBuilder* builder)
: BufferBase(builder) { : BufferBase(builder) {
if (GetAllowedUsage() & (nxt::BufferUsageBit::MapRead | nxt::BufferUsageBit::MapWrite)) {
backingData = std::unique_ptr<char[]>(new char[GetSize()]);
}
} }
Buffer::~Buffer() { 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) { 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) { 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() { void Buffer::UnmapImpl() {
// TODO(cwallez@chromium.org): Implement Map Read for the null backend
} }
// Queue // Queue
@ -125,6 +159,13 @@ namespace null {
} }
void Queue::Submit(uint32_t numCommands, CommandBuffer* const * commands) { 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); return ToBackendBase<NullBackendTraits>(common);
} }
struct PendingOperation {
virtual ~PendingOperation() = default;
virtual void Execute() = 0;
};
class Device : public DeviceBase { class Device : public DeviceBase {
public: public:
Device(); Device();
@ -102,9 +107,15 @@ namespace null {
TextureBase* CreateTexture(TextureBuilder* builder) override; TextureBase* CreateTexture(TextureBuilder* builder) override;
TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override; TextureViewBase* CreateTextureView(TextureViewBuilder* builder) override;
void AddPendingOperation(std::unique_ptr<PendingOperation> operation);
std::vector<std::unique_ptr<PendingOperation>> AcquirePendingOperations();
// NXT API // NXT API
void Reference(); void Reference();
void Release(); void Release();
private:
std::vector<std::unique_ptr<PendingOperation>> pendingOperations;
}; };
class Buffer : public BufferBase { class Buffer : public BufferBase {
@ -112,10 +123,14 @@ namespace null {
Buffer(BufferBuilder* builder); Buffer(BufferBuilder* builder);
~Buffer(); ~Buffer();
void MapReadOperationCompleted(uint32_t serial, const void* ptr);
private: private:
void SetSubDataImpl(uint32_t start, uint32_t count, const uint32_t* data) override; 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 MapReadAsyncImpl(uint32_t serial, uint32_t start, uint32_t count) override;
void UnmapImpl() override; void UnmapImpl() override;
std::unique_ptr<char[]> backingData;
}; };
class Queue : public QueueBase { class Queue : public QueueBase {