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:
parent
c863b1c26f
commit
43bfaae340
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
Loading…
Reference in New Issue